Baseline for testing

Files at this revision

API Documentation at this revision

Comitter:
foxbrianr
Date:
Thu Jul 25 00:43:08 2019 +0000
Commit message:
Baseline for testing

Changed in this revision

ButtonController.cpp Show annotated file Show diff for this revision Revisions of this file
ButtonController.h Show annotated file Show diff for this revision Revisions of this file
mcp23s08.cpp Show annotated file Show diff for this revision Revisions of this file
mcp23s08.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ButtonController.cpp	Thu Jul 25 00:43:08 2019 +0000
@@ -0,0 +1,250 @@
+#include "ButtonController.h"
+
+
+ButtonController::ButtonController(Navigator * navigator)
+{
+    
+    spi_io_exp = new mcp23s08 (p5, p6, p7, p26, 0x20);
+    
+    // set pin modes
+    // ---------------------------------------
+    spi_io_exp->gpioPinMode(0,0);
+    spi_io_exp->gpioPinMode(1,0);
+    spi_io_exp->gpioPinMode(2,0);
+    spi_io_exp->gpioPinMode(3,0);
+    spi_io_exp->gpioPinMode(4,0);
+    spi_io_exp->gpioPinMode(5,1);
+    spi_io_exp->gpioPinMode(6,1);
+    spi_io_exp->gpioPinMode(7,1);
+    
+    // enable the audio amplifier
+    // ---------------------------------------
+    spi_io_exp->gpioPinMode(5,1);
+    spi_io_exp->gpioDigitalWrite(5,1);
+    spi_io_exp->gpioDigitalWrite(6,0);
+    spi_io_exp->gpioDigitalWrite(7,0);
+    
+    this->navigator = navigator;
+}
+
+ButtonController::~ButtonController()
+{
+    
+}
+
+void ButtonController::init(void)
+{
+    
+}
+
+void ButtonController::update(int currentValue, Menu * menu)
+{
+    switch(currentValue)
+    {
+        case 1:
+            menu->pressUp();
+            break;
+        case 2:
+            menu->pressDown();
+            break;
+        case 3:
+            menu->pressMode();
+            break;
+        case 4:
+            menu->pressSet();
+            break;
+        case 5:
+            break;
+        default:
+            /* no action */
+            printf("!Button Pressed:%d\n\r",currentValue);
+            break;
+    };
+}
+
+void ButtonController::update(Menu * menu)
+{
+    int trigger_action = 0;
+    currentValue = spi_io_exp->readGpioPort();
+    
+    // if (raising edge | falling edge )
+    if (currentValue != prevValue ) {
+        prevValue = currentValue;
+        countsSinceChange = 0;
+        trigger_action = 1;
+
+    }
+    else
+    {   //TODO: play with time for what is short or long hold
+        countsSinceChange++;
+        if ( currentValue != NO_BUTTON && countsSinceChange>=10000)
+        {
+            if (isHeld != 2) printf("Button Long Held:%d\n\r",currentValue);
+            isHeld = 2;
+            trigger_action = 1;
+        }
+        else if (currentValue != NO_BUTTON && countsSinceChange>=5000)
+        {
+            if (isHeld != 1) printf("Button Short Held:%d\n\r",currentValue);
+            isHeld = 1;
+            trigger_action = 1;
+            countsSinceChange = 0;
+        }
+        else
+        {
+            isHeld =0;
+        }
+    }
+    
+    if (trigger_action || isHeld){
+        switch(currentValue)
+        {
+            case BUTTON_UP:
+                menu->pressUp();
+                break;
+            case BUTTON_DOWN:
+                menu->pressDown();
+                break;
+            case BUTTON_MODE:
+                menu->pressMode();
+                break;
+            case BUTTON_SET:
+                menu->pressSet();
+                break;
+            case BUTTON_CLEAR:
+                break;
+            case NO_BUTTON:
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+uint8_t ButtonController::getCurrentState()
+{
+    currentValue = spi_io_exp->readGpioPort();
+    
+    return currentValue;
+}
+
+void ButtonController::update(Navigator * navigator)
+{
+    currentValue = spi_io_exp->readGpioPort();
+    
+    // if (raising edge | falling edge )
+    if (currentValue != prevValue ) {
+        prevValue = currentValue;
+        countsSinceChange = 0;
+        switch(currentValue)
+        {
+            case BUTTON_UP:
+                if(!cmd_queue.full())  cmd_queue.push(1);
+                pressButtonUp();
+                break;
+            case BUTTON_DOWN:
+                if(!cmd_queue.full())  cmd_queue.push(2);
+                pressButtonDown();
+                break;
+            case BUTTON_MODE:
+                if(!cmd_queue.full())  cmd_queue.push(3);
+                pressButtonMode();
+                break;
+            case BUTTON_SET:
+                if(!cmd_queue.full())  cmd_queue.push(4);
+                pressButtonSet();
+                break;
+            case BUTTON_CLEAR:
+                if(!cmd_queue.full())  cmd_queue.push(5);
+                pressButtonClear();
+                break;
+            case NO_BUTTON:
+                if(!cmd_queue.full())  cmd_queue.push(0);
+                releaseButton();
+                break;
+            default:
+                /* no action */
+                printf("!!!Button Pressed:%d\n\r",currentValue);
+                break;
+        }
+    }
+    else
+    {   //TODO: play with time for what is short or long hold
+        countsSinceChange++;
+        if ( currentValue != NO_BUTTON && countsSinceChange>=100000)
+        {
+            if (isHeld != 2) printf("Button Long Held:%d\n\r",currentValue);
+            isHeld = 2;
+        }
+        else if (currentValue != NO_BUTTON && countsSinceChange>=50000)
+        {
+            if (isHeld != 1) printf("Button Short Held:%d\n\r",currentValue);
+            isHeld = 1;
+        }
+        else
+        {
+            isHeld =0;
+        }
+    }
+     
+}
+
+
+
+
+void ButtonController::update(void)
+{        
+    currentValue = spi_io_exp->readGpioPort() ;
+    currentValue = (~currentValue & 0x1F); // clear bit is stuck
+    
+    // if (raising edge | falling edge )
+    if (currentValue != prevValue ) {
+        prevValue = currentValue;
+        countsSinceChange = 0;
+        
+        if (currentValue && !cmd_queue.full())  {
+            cmd_queue.push(currentValue);
+            //printf("!!Button Pressed:%d\n\r",currentValue);
+        }
+        
+    }
+}
+
+
+void ButtonController::pressButtonUp(void)
+{
+    printf("Up Button Pressed:%d\n\r",currentValue);
+    if (navigator) 
+        navigator->moveUp();
+}
+
+void ButtonController::pressButtonDown(void)
+{
+    printf("Down Button Pressed:%d\n\r",currentValue);
+    if (navigator) 
+    navigator->moveDown();
+}
+
+void ButtonController::pressButtonSet(void)
+{
+    printf("Set Button Pressed:%d\n\r",currentValue);
+    if (navigator) 
+        navigator->selectMenu();
+}
+
+void ButtonController::pressButtonMode(void)
+{
+    printf("Mode Button Pressed:%d\n\r",currentValue);
+}
+
+void ButtonController::pressButtonClear(void)
+{
+    printf("Clear Button Pressed:%d\n\r",currentValue);
+}
+
+void ButtonController::releaseButton(void)
+{
+    //printf("Button Released:%d\n\r",currentValue);
+    isHeld = 0;
+    countsSinceChange = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ButtonController.h	Thu Jul 25 00:43:08 2019 +0000
@@ -0,0 +1,78 @@
+#ifndef _BUTTON_CONTROLLER_
+#define _BUTTON_CONTROLLER_
+
+#include "mbed.h"
+#include "rtos.h"
+#include "mcp23s08.h"
+#include "Menu.h"
+#include "Navigator.h"
+
+/**
+ * service to manage the external GPIO expander board.
+ */
+typedef enum
+{
+    NO_BUTTON    = 27,
+    BUTTON_UP    = 26,
+    BUTTON_DOWN  = 25,
+    BUTTON_MODE  = 19,
+    BUTTON_SET   = 11,
+    BUTTON_CLEAR = 0
+} tButtonValue ;
+
+typedef void (*t_ButtonPressCallback)(void);
+
+
+/***
+*
+* This class wrapps the communication with the GPIO expander over SPI bus.
+*  PIN 0 : Up
+*  PIN 1 : Down
+*  PIN 2 : Clear
+*  PIN 3 : Mode
+*  PIN 4 : Set
+*  PIN 5 : Enable Audio
+*  PIN 6 : na
+*  PIN 7 : na 
+*  
+*  MASK = 0x1F;
+*  
+*/
+class ButtonController 
+{
+    public :
+        
+        Navigator *     navigator;
+        mcp23s08 *      spi_io_exp;
+        Mutex           _mutex;
+        unsigned char   currentValue;
+        unsigned char   prevValue;
+        unsigned char   confirmedValue;
+        unsigned int    countsSinceChange;
+        unsigned char   isServiced;
+        unsigned char   isHeld;
+        
+        
+        CircularBuffer<uint8_t, 64> cmd_queue;
+        
+        ButtonController(Navigator * navigator);
+        ~ButtonController();
+        
+        void  pressButtonUp(void);
+        void  pressButtonDown(void);
+        void  pressButtonClear(void);
+        void  pressButtonMode(void);
+        void  pressButtonSet(void);
+        void  releaseButton(void);
+        
+        void init(void);
+        void update(void);
+        void update(Navigator * navigator);
+        void update(Menu * menu);
+        void update(int currentValue, Menu * menu);
+        
+        uint8_t getCurrentState ();
+};
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mcp23s08.cpp	Thu Jul 25 00:43:08 2019 +0000
@@ -0,0 +1,185 @@
+#include "mbed.h"
+#include "mcp23s08.h"
+
+#define INPUT 0
+#define OUTPUT 1
+
+#define LOW 0
+#define HIGH 1
+
+mcp23s08::mcp23s08(PinName mosi, PinName miso, PinName clk, PinName cs_pin,const uint8_t haenAdrs) : SPI(mosi, miso, clk), cs(cs_pin) {
+    format(8, 3);
+    frequency(2000000);
+
+    postSetup(haenAdrs);
+
+}
+
+
+void mcp23s08::postSetup(const uint8_t haenAdrs){
+    if (haenAdrs >= 0x20 && haenAdrs <= 0x23){//HAEN works between 0x20...0x23
+        _adrs = haenAdrs;
+        _useHaen = 1;
+    } else {
+        _adrs = 0;
+        _useHaen = 0;
+    }
+    _readCmd =  (_adrs << 1) | 1;
+    _writeCmd = _adrs << 1;
+    //setup register values for this chip
+    IOCON =     0x05;
+    IODIR =     0x00;
+    GPPU =      0x06;
+    GPIO =      0x09;
+    GPINTEN =   0x02;
+    IPOL =      0x01;
+    DEFVAL =    0x03;
+    INTF =      0x07;
+    INTCAP =    0x08;
+    OLAT =      0x0A;
+    INTCON =    0x04;
+}
+
+void mcp23s08::begin(bool protocolInitOverride) {
+    
+    cs=1;
+    wait(0.1);
+    _useHaen == 1 ? writeByte(IOCON,0b00101000) : writeByte(IOCON,0b00100000);
+    /*
+    if (_useHaen){
+        writeByte(IOCON,0b00101000);//read datasheet for details!
+    } else {
+        writeByte(IOCON,0b00100000);
+    }
+    */
+    _gpioDirection = 0xFF;//all in
+    _gpioState = 0x00;//all low 
+}
+
+
+uint8_t mcp23s08::readAddress(uint8_t addr){
+    uint8_t low_byte = 0x00;
+    startSend(1);
+    SPI::write(addr);
+    low_byte = (uint8_t)SPI::write(0x00);
+    endSend();
+    return low_byte;
+}
+
+
+
+void mcp23s08::gpioPinMode(uint8_t mode){
+    if (mode == INPUT){
+        _gpioDirection = 0xFF;
+    } else if (mode == OUTPUT){ 
+        _gpioDirection = 0x00;
+        _gpioState = 0x00;
+    } else {
+        _gpioDirection = mode;
+    }
+    writeByte(IODIR,_gpioDirection);
+}
+
+void mcp23s08::gpioPinMode(uint8_t pin, bool mode){
+    if (pin < 8){//0...7
+        mode == INPUT ? _gpioDirection |= (1 << pin) :_gpioDirection &= ~(1 << pin);
+        writeByte(IODIR,_gpioDirection);
+    }
+}
+
+void mcp23s08::gpioPort(uint8_t value){
+    if (value == HIGH){
+        _gpioState = 0xFF;
+    } else if (value == LOW){   
+        _gpioState = 0x00;
+    } else {
+        _gpioState = value;
+    }
+    writeByte(GPIO,_gpioState);
+}
+
+
+uint8_t mcp23s08::readGpioPort(){
+    return readAddress(GPIO);
+}
+
+uint8_t mcp23s08::readGpioPortFast(){
+    return _gpioState;
+}
+
+int mcp23s08::gpioDigitalReadFast(uint8_t pin){
+    if (pin < 8){//0...7
+        int temp = _gpioState & (1 << pin);
+        return temp;
+    } else {
+        return 0;
+    }
+}
+
+void mcp23s08::portPullup(uint8_t data) {
+    if (data == HIGH){
+        _gpioState = 0xFF;
+    } else if (data == LOW){    
+        _gpioState = 0x00;
+    } else {
+        _gpioState = data;
+    }
+    writeByte(GPPU, _gpioState);
+}
+
+
+
+
+void mcp23s08::gpioDigitalWrite(uint8_t pin, bool value){
+    if (pin < 8){//0...7
+        value == HIGH ? _gpioState |= (1 << pin) : _gpioState &= ~(1 << pin);
+        writeByte(GPIO,_gpioState);
+    }
+}
+
+void mcp23s08::gpioDigitalWriteFast(uint8_t pin, bool value){
+    if (pin < 8){//0...8
+        value == HIGH ? _gpioState |= (1 << pin) : _gpioState &= ~(1 << pin);
+    }
+}
+
+void mcp23s08::gpioPortUpdate(){
+    writeByte(GPIO,_gpioState);
+}
+
+int mcp23s08::gpioDigitalRead(uint8_t pin){
+    if (pin < 8) return (int)(readAddress(GPIO) & 1 << pin);
+    return 0;
+}
+
+uint8_t mcp23s08::gpioRegisterReadByte(uint8_t reg){
+  uint8_t data = 0;
+  startSend(1);
+  SPI::write(reg);
+  data = (uint8_t)SPI::write(0x00);
+  endSend();
+  return data;
+}
+
+
+void mcp23s08::gpioRegisterWriteByte(uint8_t reg,uint8_t data){
+    writeByte(reg,(uint8_t)data);
+}
+
+/* ------------------------------ Low Level ----------------*/
+void mcp23s08::startSend(bool mode){
+    cs=0;
+    mode == 1 ? SPI::write(_readCmd) : SPI::write(_writeCmd);
+}
+
+void mcp23s08::endSend(){
+    cs=1;
+}
+
+
+void mcp23s08::writeByte(uint8_t addr, uint8_t data){
+    startSend(0);
+    SPI::write(addr);
+    SPI::write(data);
+    endSend();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mcp23s08.h	Thu Jul 25 00:43:08 2019 +0000
@@ -0,0 +1,123 @@
+/*
+ ___  _   _  _ __ ___    ___  | |_  ___   _   _ 
+/ __|| | | || '_ ` _ \  / _ \ | __|/ _ \ | | | |
+\__ \| |_| || | | | | || (_) || |_| (_) || |_| |
+|___/ \__,_||_| |_| |_| \___/  \__|\___/  \__, |
+                                          |___/ 
+                                          
+    gpio_expander - An attemp to create a fast and universal library for drive many GPIO chips
+    
+model:          company:        pins:       protocol:       Special Features:
+---------------------------------------------------------------------------------------------------------------------
+mcp23s08        Microchip         8         SPI                 INT/HAEN
+---------------------------------------------------------------------------------------------------------------------
+Version history:
+0.5b1: first release, just coded and never tested
+0.5b2: fixed 2wire version, added portPullup, tested output mode (ok)
+0.5b3: added some drivers
+0.5b4: ability to include library inside other libraries.
+0.5b7: Changed functionalities of some function.
+0.6b1: Changed gpioRegisterRead to gpioRegisterReadByte. Added gpioRegisterReadWord (for some GPIO)
+0.6b3: Added basic support for SPI transactions, small optimizations.
+0.8b3: Added 2 more commands and 2 gpio chip.
+0.8b4: Support for SPI Transaction post setup
+---------------------------------------------------------------------------------------------------------------------
+        Copyright (c) 2013-2014, s.u.m.o.t.o.y [sumotoy(at)gmail.com]
+---------------------------------------------------------------------------------------------------------------------
+    gpio_expander Library is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+    gpio_expander Library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+    
+    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    Version:0.8b3: Added 2 more commands and 2 gpio chip.
+    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+*/
+
+/* ------------------------------ MCP23S08 WIRING ------------------------------------
+This chip has a very useful feature called HAEN that allow you to share the same CS pin trough
+4 different addresses. Of course chip has to be Microchip and should be assigned to different addresses!
+Basic Address:  001000 A1 A0 (from 0x20 to 0x23)
+A1,A0 tied to ground = 0x20
+                __ __
+    ->  sck   [|  U  |] ++++
+    ->  mosi  [|     |] IO-7
+    <-  miso  [|     |] IO-6
+        A1    [|     |] IO-5
+        A0    [|     |] IO-4
+ rst (con.+)  [|     |] IO-3
+        cs    [|     |] IO-2
+        int   [|     |] IO-1
+        GND   [|_____|] IO-0
+*/
+#ifndef _MCP23S08_H_
+#define _MCP23S08_H_
+
+#include <inttypes.h>
+
+class mcp23s08 : public SPI 
+{
+
+public:
+    mcp23s08(PinName mosi, PinName miso, PinName clk, PinName cs_pin,const uint8_t haenAdrs);
+    void            postSetup(const uint8_t haenAdrs);//used with other libraries only
+    virtual void    begin(bool protocolInitOverride=false); //protocolInitOverride=true will not init the SPI   
+
+    
+    void            gpioPinMode(uint8_t mode);                      //set all pins to INPUT or OUTPUT
+    void            gpioPinMode(uint8_t pin, bool mode);        //set a unique pin as IN(1) or OUT (0)
+    void            gpioPort(uint8_t value);                    //write data to all pins
+    //void          gpioPort(uint8_t lowByte, uint8_t highByte);        //same as abowe but uses 2 separate bytes (not applicable to this chip)
+    uint8_t         readGpioPort();                             //read the state of the pins (all)
+    uint8_t         readGpioPortFast();                         
+    
+    void            gpioDigitalWrite(uint8_t pin, bool value);  //write data to one pin
+    void            gpioDigitalWriteFast(uint8_t pin, bool value);
+    int             gpioDigitalRead(uint8_t pin);               //read data from one pin
+    uint8_t         gpioRegisterReadByte(uint8_t reg);                  //read a uint8_t from chip register
+    int             gpioDigitalReadFast(uint8_t pin);
+    void            gpioRegisterWriteByte(uint8_t reg,uint8_t data);        //write a chip register
+    void            portPullup(uint8_t data);                       // true=pullup, false=pulldown all pins
+    void            gpioPortUpdate();
+    // direct access commands
+    uint8_t         readAddress(uint8_t addr);
+    
+    void            setSPIspeed(uint32_t spispeed);//for SPI transactions
+    
+    //------------------------- REGISTERS
+    uint8_t IOCON;
+    uint8_t IODIR;
+    uint8_t GPPU;
+    uint8_t GPIO;
+    uint8_t GPINTEN;
+    uint8_t IPOL;
+    uint8_t DEFVAL;
+    uint8_t INTF;
+    uint8_t INTCAP;
+    uint8_t OLAT;
+    uint8_t INTCON;
+    
+private:
+    DigitalOut cs;
+
+    uint8_t         _cs;
+    uint8_t         _adrs;
+    
+    uint32_t        _spiTransactionsSpeed;//for SPI transactions
+    
+    uint8_t         _useHaen;
+    uint8_t         _readCmd;
+    uint8_t         _writeCmd;
+    void            startSend(bool mode);
+    void            endSend();
+    uint8_t         _gpioDirection;
+    uint8_t         _gpioState;
+    void            writeByte(uint8_t addr, uint8_t data);  
+};
+#endif
\ No newline at end of file