Baseline for testing
Revision 0:b6d729ae4f27, committed 2019-07-25
- Comitter:
- foxbrianr
- Date:
- Thu Jul 25 00:43:08 2019 +0000
- Commit message:
- Baseline for testing
Changed in this revision
diff -r 000000000000 -r b6d729ae4f27 ButtonController.cpp --- /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; +}
diff -r 000000000000 -r b6d729ae4f27 ButtonController.h --- /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
diff -r 000000000000 -r b6d729ae4f27 mcp23s08.cpp --- /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(); +}
diff -r 000000000000 -r b6d729ae4f27 mcp23s08.h --- /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