seesaw/source/Delegate.cpp
2018-10-02 14:15:38 -04:00

862 lines
24 KiB
C++

/*******************************************************************************
* Copyright (C) Dean Miller
* All rights reserved.
*
* This program is open source 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "qpcpp.h"
#include "qp_extras.h"
#include "hsm_id.h"
#include "Delegate.h"
#include "event.h"
#include "RegisterMap.h"
#include "SeesawConfig.h"
#include "PinMap.h"
#include "bsp_gpio.h"
#include "bsp_sercom.h"
#include "bsp_adc.h"
#include "bsp_nvmctrl.h"
#include "bsp_sercom.h"
Q_DEFINE_THIS_FILE
using namespace FW;
volatile uint32_t Delegate::m_inten = 0;
volatile uint32_t Delegate::m_intflag = 0;
Delegate::Delegate() :
QActive((QStateHandler)&Delegate::InitialPseudoState),
m_id(DELEGATE), m_name("Delegate") {}
QState Delegate::InitialPseudoState(Delegate * const me, QEvt const * const e) {
(void)e;
me->subscribe(DELEGATE_START_REQ);
me->subscribe(DELEGATE_STOP_REQ);
me->subscribe(DELEGATE_PROCESS_COMMAND);
me->subscribe(GPIO_INTERRUPT_RECEIVED);
return Q_TRAN(&Delegate::Root);
}
QState Delegate::Root(Delegate * const me, QEvt const * const e) {
QState status;
switch (e->sig) {
case Q_ENTRY_SIG: {
LOG_EVENT(e);
status = Q_HANDLED();
break;
}
case Q_EXIT_SIG: {
LOG_EVENT(e);
status = Q_HANDLED();
break;
}
case Q_INIT_SIG: {
status = Q_TRAN(&Delegate::Stopped);
break;
}
default: {
status = Q_SUPER(&QHsm::top);
break;
}
}
return status;
}
QState Delegate::Stopped(Delegate * const me, QEvt const * const e) {
QState status;
switch (e->sig) {
case Q_ENTRY_SIG: {
LOG_EVENT(e);
status = Q_HANDLED();
break;
}
case Q_EXIT_SIG: {
LOG_EVENT(e);
status = Q_HANDLED();
break;
}
case DELEGATE_STOP_REQ: {
LOG_EVENT(e);
Evt const &req = EVT_CAST(*e);
Evt *evt = new DelegateStopCfm(req.GetSeq(), ERROR_SUCCESS);
QF::PUBLISH(evt, me);
status = Q_HANDLED();
break;
}
case DELEGATE_START_REQ: {
LOG_EVENT(e);
Delegate::m_inten = 0;
Delegate::m_intflag = 0;
Evt const &req = EVT_CAST(*e);
Evt *evt = new DelegateStartCfm(req.GetSeq(), ERROR_SUCCESS);
QF::PUBLISH(evt, me);
status = Q_TRAN(&Delegate::Started);
break;
}
case GPIO_INTERRUPT_RECEIVED: {
//ignore
status = Q_HANDLED();
break;
}
default: {
status = Q_SUPER(&Delegate::Root);
break;
}
}
return status;
}
QState Delegate::Started(Delegate * const me, QEvt const * const e) {
QState status;
switch (e->sig) {
case Q_ENTRY_SIG: {
LOG_EVENT(e);
status = Q_HANDLED();
break;
}
case Q_EXIT_SIG: {
LOG_EVENT(e);
status = Q_HANDLED();
break;
}
case DELEGATE_PROCESS_COMMAND: {
//LOG_EVENT(e);
DelegateProcessCommand const &req = static_cast<DelegateProcessCommand const &>(*e);
uint8_t highByte = req.getHighByte();
uint8_t lowByte = req.getLowByte();
uint8_t len = req.getLen();
#ifdef ENABLE_LOGGING
PRINT("DELEGATE_PROCESS_COMMAND: (0x%x, 0x%x) %i\n", highByte, lowByte, len);
#endif
if(!len){
//we are reading
switch(highByte){
//We don't have a separate AO to handle STATUS or GPIO stuff since it's simple and a waste of resources
case SEESAW_STATUS_BASE: {
Fifo *fifo = req.getFifo();
switch(lowByte){
case SEESAW_STATUS_HW_ID:{
uint8_t r = SEESAW_STATUS_HW_ID_CODE;
fifo->Write(&r, 1);
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
case SEESAW_STATUS_VERSION: {
uint8_t ret[4];
me->break32Bit(CONFIG_VERSION, ret);
fifo->Write(ret, 4);
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
case SEESAW_STATUS_OPTIONS: {
uint32_t data = CONFIG_OPTIONS;
uint8_t ret[4];
me->break32Bit(data, ret);
fifo->Write(ret, 4);
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
#if CONFIG_TEMP_SENSOR
case SEESAW_STATUS_TEMP: {
int32_t data = calculate_temperature();
uint8_t ret[4];
me->break32Bit(data, ret);
fifo->Write(ret, 4);
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
#endif
default:
//Unrecognized command or unreadable register. Do nothing.
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
break;
}
case SEESAW_GPIO_BASE: {
Fifo *fifo = req.getFifo();
switch(lowByte){
case SEESAW_GPIO_BULK: {
uint32_t data = gpio_read_bulk(PORTA);
uint8_t ret[4];
me->break32Bit(data, ret);
fifo->Write(ret, 4);
#ifdef HAS_PORTB
data = gpio_read_bulk(PORTB);
me->break32Bit(data, ret);
fifo->Write(ret, 4);
#endif
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
//clear interrupt if interrupts are enabled
if(Delegate::m_inten > 0 && Delegate::m_intflag > 0){
Delegate::m_intflag = 0;
Evt *evt = new InterruptClearReq( SEESAW_INTERRUPT_GPIO );
QF::PUBLISH(evt, me);
}
break;
}
case SEESAW_GPIO_INTFLAG: {
uint8_t ret[4];
me->break32Bit(Delegate::m_intflag, ret);
fifo->Write(ret, 4);
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
//clear interrupt if interrupts are enabled
if(Delegate::m_inten > 0){
Delegate::m_intflag = 0;
Evt *evt = new InterruptClearReq( SEESAW_INTERRUPT_GPIO );
QF::PUBLISH(evt, me);
}
break;
}
default:
//unrecognized command
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
break;
}
#if CONFIG_ADC
case SEESAW_ADC_BASE: {
switch(lowByte){
case SEESAW_ADC_WINMODE:
case SEESAW_ADC_INTEN:
case SEESAW_ADC_INTENCLR:
#if CONFIG_ADC_INPUT_0
case SEESAW_ADC_CHANNEL_0:
#endif
#if CONFIG_ADC_INPUT_1
case SEESAW_ADC_CHANNEL_1:
#endif
#if CONFIG_ADC_INPUT_2
case SEESAW_ADC_CHANNEL_2:
#endif
#if CONFIG_ADC_INPUT_3
case SEESAW_ADC_CHANNEL_3:
#endif
#if CONFIG_ADC_INPUT_4
case SEESAW_ADC_CHANNEL_4:
#endif
#if CONFIG_ADC_INPUT_5
case SEESAW_ADC_CHANNEL_5:
#endif
#if CONFIG_ADC_INPUT_6
case SEESAW_ADC_CHANNEL_6:
#endif
#if CONFIG_ADC_INPUT_7
case SEESAW_ADC_CHANNEL_7:
#endif
default: {
Evt *evt = new ADCReadRegReq(req.getRequesterId(), lowByte, req.getFifo());
QF::PUBLISH(evt, me);
break;
}
}
break;
}
#endif //ADC
#if CONFIG_TOUCH
case SEESAW_TOUCH_BASE: {
switch(lowByte){
default: {
Evt *evt = new TouchReadRegReq(req.getRequesterId(), lowByte, req.getFifo());
QF::PUBLISH(evt, me);
break;
}
}
break;
}
#endif //TOUCH
#if CONFIG_SERCOM0 || CONFIG_SERCOM1 || CONFIG_SERCOM2 || CONFIG_SERCOM3 || CONFIG_SERCOM4 || CONFIG_SERCOM5
case SEESAW_SERCOM0_BASE:
case SEESAW_SERCOM1_BASE:
case SEESAW_SERCOM2_BASE:
case SEESAW_SERCOM3_BASE:
case SEESAW_SERCOM4_BASE:
case SEESAW_SERCOM5_BASE:{
switch(lowByte){
//TODO: fix for more sercoms
case SEESAW_SERCOM_STATUS:
case SEESAW_SERCOM_INTEN:
case SEESAW_SERCOM_BAUD:{
Evt *evt = new SercomReadRegReq(req.getRequesterId(), lowByte, req.getFifo());
QF::PUBLISH(evt, me);
break;
}
case SEESAW_SERCOM_DATA:{
Evt *evt = new SercomReadDataReq(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
default: {
__BKPT();
Q_ASSERT(0);
}
}
break;
}
#endif //SERCOM
#if CONFIG_DAP
case SEESAW_DAP_BASE:{
Evt *evt = new DAPRead(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
#endif //DAP
#if CONFIG_EEPROM
case SEESAW_EEPROM_BASE:{
Fifo *fifo = req.getFifo();
uint8_t r = eeprom_read_byte(lowByte);
fifo->Write(&r, 1);
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
#endif
#if CONFIG_NEOPIXEL
case SEESAW_NEOPIXEL_BASE:{
switch(lowByte){
case SEESAW_NEOPIXEL_SHOW:{
Evt *evt = new Evt(NEOPIXEL_SHOW_REQ);
QF::PUBLISH(evt, me);
evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
}
break;
}
#endif
#if CONFIG_KEYPAD
case SEESAW_KEYPAD_BASE:{
Evt *evt = new KeypadReadRegReq(req.getRequesterId(), lowByte, req.getFifo());
QF::PUBLISH(evt, me);
break;
}
#endif
#if CONFIG_ENCODER
case SEESAW_ENCODER_BASE:{
Evt *evt = new EncoderReadRegReq(req.getRequesterId(), lowByte, req.getFifo());
QF::PUBLISH(evt, me);
break;
}
#endif
default:
//Unrecognized command or unreadable register. Do nothing.
Evt *evt = new DelegateDataReady(req.getRequesterId());
QF::PUBLISH(evt, me);
break;
}
}
else{
//we are writing
switch(highByte){
//We don't have a separate AO to handle STATUS or GPIO stuff since it's simple and a waste of resources
case SEESAW_STATUS_BASE: {
switch(lowByte){
case SEESAW_STATUS_SWRST:{
Evt *evt = new Evt(SYSTEM_STOP_REQ);
QF::PUBLISH(evt, me);
break;
}
}
break;
}
case SEESAW_GPIO_BASE: {
Fifo *fifo = req.getFifo();
switch(lowByte){
case SEESAW_GPIO_DIRSET_BULK: {
uint8_t pins[4];
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_dirset_bulk(PORTA, combined & CONFIG_GPIO_A_MASK);
#ifdef HAS_PORTB
if(len > 0){
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_dirset_bulk(PORTB, combined & CONFIG_GPIO_B_MASK);
}
#endif
break;
}
case SEESAW_GPIO_DIRCLR_BULK: {
uint8_t pins[4];
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_dirclr_bulk(PORTA, combined & CONFIG_GPIO_A_MASK);
#ifdef HAS_PORTB
if(len > 0){
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_dirclr_bulk(PORTB, combined & CONFIG_GPIO_B_MASK);
}
#endif
break;
}
case SEESAW_GPIO_BULK_SET: {
uint8_t pins[4];
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_outset_bulk(PORTA, combined & CONFIG_GPIO_A_MASK);
#ifdef HAS_PORTB
if(len > 0){
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_outset_bulk(PORTB, combined & CONFIG_GPIO_B_MASK);
}
#endif
break;
}
case SEESAW_GPIO_BULK_CLR: {
uint8_t pins[4];
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_outclr_bulk(PORTA, combined & CONFIG_GPIO_A_MASK);
#ifdef HAS_PORTB
if(len > 0){
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_outclr_bulk(PORTB, combined & CONFIG_GPIO_B_MASK);
}
#endif
break;
}
case SEESAW_GPIO_INTENSET: {
uint8_t pins[4];
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
Delegate::m_inten |= (combined & CONFIG_GPIO_A_MASK);
break;
}
case SEESAW_GPIO_INTENCLR: {
uint8_t pins[4];
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
combined &= CONFIG_GPIO_A_MASK;
Delegate::m_inten &= !combined;
break;
}
case SEESAW_GPIO_PULLENSET: {
uint8_t pins[4];
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_pullenset_bulk(combined & CONFIG_GPIO_A_MASK);
#ifdef HAS_PORTB
if(len > 0){
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_pullenset_bulk(combined & CONFIG_GPIO_B_MASK, PORTB);
}
#endif
break;
}
case SEESAW_GPIO_PULLENCLR: {
uint8_t pins[4];
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_pullenclr_bulk(combined & CONFIG_GPIO_A_MASK);
#ifdef HAS_PORTB
if(len > 0){
fifo->Read(pins, 4);
len-=4;
uint32_t combined = ((uint32_t)pins[0] << 24) | ((uint32_t)pins[1] << 16) | ((uint32_t)pins[2] << 8) | (uint32_t)pins[3];
gpio_pullenclr_bulk(combined & CONFIG_GPIO_B_MASK, PORTB);
}
#endif
break;
}
}
//discard any extra data
me->discard(fifo, len);
break;
}
#if CONFIG_ADC
case SEESAW_ADC_BASE: {
switch(lowByte){
//these take 1 byte of data
case SEESAW_ADC_WINMODE:
case SEESAW_ADC_INTEN:
case SEESAW_ADC_INTENCLR:{
Fifo *fifo = req.getFifo();
uint8_t dataByte = 0;
fifo->Read(&dataByte, 1);
len--;
//read any extra bytes and discard
me->discard(fifo, len);
Evt *evt = new ADCWriteRegReq(lowByte, dataByte);
QF::PUBLISH(evt, me);
break;
}
case SEESAW_ADC_WINTHRESH:{
Fifo *fifo = req.getFifo();
uint8_t data[4];
fifo->Read(data, 4);
len-=4;
//read any extra bytes and discard
me->discard(fifo, len);
uint16_t ht = ((uint16_t)data[0] << 8) | data[1];
uint16_t lt = ((uint16_t)data[2] << 8) | data[3];
Evt *evt = new ADCWriteWinmonThresh(ht, lt);
QF::PUBLISH(evt, me);
break;
}
}
break;
}
#endif // ADC
#if ( CONFIG_SERCOM0 | CONFIG_SERCOM1 | CONFIG_SERCOM2 | CONFIG_SERCOM3 | CONFIG_SERCOM4 | CONFIG_SERCOM5 )
case SEESAW_SERCOM0_BASE:
case SEESAW_SERCOM1_BASE:
case SEESAW_SERCOM2_BASE:
case SEESAW_SERCOM3_BASE:
case SEESAW_SERCOM4_BASE:
case SEESAW_SERCOM5_BASE:{
switch(lowByte){
//TODO: fix for more sercoms
case SEESAW_SERCOM_STATUS:
case SEESAW_SERCOM_INTEN:{
Fifo *fifo = req.getFifo();
uint8_t dataByte = 0;
fifo->Read(&dataByte, 1);
len--;
//read any extra bytes and discard
me->discard(fifo, len);
Evt *evt = new SercomWriteRegReq(lowByte, dataByte);
QF::PUBLISH(evt, me);
break;
}
case SEESAW_SERCOM_BAUD:{
Fifo *fifo = req.getFifo();
uint8_t baud[4];
fifo->Read(baud, 4);
len-=4;
uint32_t combined = ((uint32_t)baud[0] << 24) | ((uint32_t)baud[1] << 16) | ((uint32_t)baud[2] << 8) | (uint32_t)baud[3];
//read any extra bytes and discard
me->discard(fifo, len);
Evt *evt = new SercomWriteRegReq(lowByte, combined);
QF::PUBLISH(evt, me);
break;
}
case SEESAW_SERCOM_DATA:{
//TODO: this should take in number of bytes to write
Evt *evt = new SercomWriteDataReq(req.getFifo(), req.getLen());
QF::PUBLISH(evt, me);
break;
}
}
break;
}
#endif //SERCOM
#if CONFIG_TIMER
case SEESAW_TIMER_BASE:{
switch(lowByte){
case SEESAW_TIMER_PWM: {
Fifo *fifo = req.getFifo();
uint8_t dataBytes[3];
fifo->Read(dataBytes, 3);
len -= 3;
me->discard(fifo, len);
Evt *evt = new TimerWritePWM(dataBytes[0], ((uint16_t)dataBytes[1] << 8) | (dataBytes[2]));
QF::PUBLISH(evt, me);
break;
}
case SEESAW_TIMER_FREQ: {
Fifo *fifo = req.getFifo();
uint8_t dataBytes[3];
fifo->Read(dataBytes, 3);
len -= 3;
me->discard(fifo, len);
Evt *evt = new TimerSetFreq(dataBytes[0], ((uint16_t)dataBytes[1] << 8) | (dataBytes[2]));
QF::PUBLISH(evt, me);
break;
}
}
break;
}
#endif //TIMER
#if CONFIG_DAP
case SEESAW_DAP_BASE:{
Evt *evt = new DAPRequest(req.getRequesterId(), req.getFifo(), req.getLen());
QF::PUBLISH(evt, me);
break;
}
#endif //DAP
#if CONFIG_EEPROM
case SEESAW_EEPROM_BASE:{
Fifo *fifo = req.getFifo();
uint8_t c[req.getLen()];
fifo->Read(c, req.getLen());
eeprom_write(lowByte, c, req.getLen());
break;
}
#endif
#if CONFIG_NEOPIXEL
case SEESAW_NEOPIXEL_BASE: {
Fifo *fifo = req.getFifo();
switch(lowByte){
case SEESAW_NEOPIXEL_PIN:{
uint8_t pin;
fifo->Read(&pin, 1);
Evt *evt = new NeopixelSetPinReq(pin);
QF::PUBLISH(evt, me);
me->discard(fifo, req.getLen());
break;
}
case SEESAW_NEOPIXEL_SPEED:{
uint8_t speed;
fifo->Read(&speed, 1);
Evt *evt = new NeopixelSetSpeedReq(speed);
QF::PUBLISH(evt, me);
me->discard(fifo, req.getLen());
break;
}
case SEESAW_NEOPIXEL_BUF_LENGTH:{
uint8_t d[2];
fifo->Read(d, 2);
Evt *evt = new NeopixelSetBufferLengthReq( ((uint16_t)d[0] << 8) | (uint16_t)d[1]);
QF::PUBLISH(evt, me);
me->discard(fifo, req.getLen());
break;
}
case SEESAW_NEOPIXEL_BUF:{
uint8_t d[2];
fifo->Read(d, 2);
Evt *evt = new NeopixelSetBufferReq( ((uint16_t)d[0] << 8) | (uint16_t)d[1], fifo);
QF::PUBLISH(evt, me);
}
break;
}
break;
}
#endif //NEOPIXEL
#if CONFIG_KEYPAD
case SEESAW_KEYPAD_BASE:{
Fifo *fifo = req.getFifo();
uint8_t dataBytes[2];
fifo->Read(dataBytes, 2);
len-=2;
Evt *evt = new KeypadWriteRegReq(lowByte, (dataBytes[0] << 8) | dataBytes[1]);
QF::PUBLISH(evt, me);
break;
}
#endif
#if CONFIG_ENCODER
case SEESAW_ENCODER_BASE:{
Fifo *fifo = req.getFifo();
uint8_t dataBytes[4];
fifo->Read(dataBytes, 4);
len-=4;
int32_t combined = ((int32_t)dataBytes[0] << 24) | ((int32_t)dataBytes[1] << 16) | ((int32_t)dataBytes[2] << 8) | (int32_t)dataBytes[3];
Evt *evt = new EncoderWriteRegReq(lowByte, combined);
QF::PUBLISH(evt, me);
break;
}
#endif
default:
break;
}
}
status = Q_HANDLED();
break;
}
#if CONFIG_INTERRUPT
case GPIO_INTERRUPT_RECEIVED: {
LOG_EVENT(e);
Q_ASSERT(Delegate::m_intflag > 0);
Evt *evt = new InterruptSetReq( SEESAW_INTERRUPT_GPIO );
QF::PUBLISH(evt, me);
status = Q_HANDLED();
break;
}
#endif
case DELEGATE_STOP_REQ: {
LOG_EVENT(e);
Evt const &req = EVT_CAST(*e);
Evt *evt = new DelegateStopCfm(req.GetSeq(), ERROR_SUCCESS);
QF::PUBLISH(evt, me);
status = Q_TRAN(Delegate::Stopped);
break;
}
default: {
status = Q_SUPER(&Delegate::Root);
break;
}
}
return status;
}
void Delegate::intCallback()
{
Evt *evt = new Evt(GPIO_INTERRUPT_RECEIVED);
QF::PUBLISH(evt, 0);
}
void Delegate::discard(Fifo *fifo, uint8_t len)
{
//read any extra bytes and discard
while(len > 0){
uint8_t dummy;
fifo->Read(&dummy, 1);
len--;
}
}
void Delegate::break32Bit(uint32_t in, uint8_t *out)
{
uint8_t b3 = (in >> 24) & 0xFF;
uint8_t b2 = (in >> 16) & 0xFF;
uint8_t b1 = (in >> 8) & 0xFF;
uint8_t b0 = in & 0xFF;
out[0] = b3;
out[1] = b2;
out[2] = b1;
out[3] = b0;
}
extern "C" {
/*
void EIC_Handler(void)
{
QXK_ISR_ENTRY();
NVIC_DisableIRQ(EIC_IRQn);
Delegate::intCallback(EIC->INTFLAG.reg);
EIC->INTFLAG.reg = 0xFFFF;
QXK_ISR_ENTRY();
}
*/
};