I've written a library for sending short messages from one device to another (with addressing and checksums)
I have tested the library on an Adafruit Feather M0, sending data between two UART instances, and it works fine.
Now I am using it on an ATTiny 3227 with the MegaTinyCore, and a SAMD21 board with the Mattairtech core and the code has stopped working. In my update function it reads the latest serial byte and then has a switch statement with the various parser states for incoming data. This switch statement never executes even when valid data arrives. If I replace the switch with a series of if/else statements the code works.
I'm at a complete loss as to why the code would fail like this on two different boards when it works fine on a third.
The update function from my class is below, it prints out incoming data to confirm that the data is arriving but the switch statement doesn't execute. A commented out if/else statement is there and when I uncomment it I get ">Start2" printed out, indicating that the first byte of incoming data is accepted by the parser.
I'm not even close to the flash or ram limits of any of the devices I am using.
This is not the first time I have had relatively simple switch statements fail on Arduino boards and I am not getting any compiler warnings (with verbose messages on)
Am I missing some subtle bug here?
bool MicroMessage::update(){
//returns true of a new packet was accepted - including if the packet has failed the checksum
bool returnState = false;
int inByte;
//Data available? If not then check the timeout
if(port->available()){
inByte = port->read();
}else{
checkTimeout();
//timeout will reset the parser
return returnState;
}
#ifdef MESSAGE_TIMING_DEBUG
commRxStart = micros();
#endif
#ifdef PRINT_BYTES_IN
//Incoming data is printed here just fine!
Serial.print(inByte);
Serial.print(" ");
#endif
/*
//THESE IF/ELSE STATEMENTS WORK FINE
if(commRXState == COMM_IDLE){
if(inByte == PACKET_START_A) commRXState = READING_START2;
}else if(commRXState == READING_START2){
#ifdef PARSER_DEBUG
debug.println(">Start2");
#endif
if(inByte == PACKET_START_B) commRXState = READING_START3;
else commRXState = COMM_IDLE;
}*/
//THIS SWITCH STATEMENT WILL NOT EXECUTE ON SOME BOARDS
switch(commRXState){
case COMM_IDLE:
if(inByte == PACKET_START_A) commRXState = READING_START2;
break;
case READING_START2:
#ifdef PARSER_DEBUG
debug.println(">Start2");
#endif
if(inByte == PACKET_START_B) commRXState = READING_START3;
else commRXState = COMM_IDLE;
break;
case READING_START3:
#ifdef PARSER_DEBUG
debug.println(">Start3");
#endif
if(inByte == PACKET_START_A) commRXState = READING_START4;
else commRXState = COMM_IDLE;
break;
case READING_START4:
#ifdef PARSER_DEBUG
debug.println(">Start4");
#endif
if(inByte == PACKET_START_B) commRXState = READING_GROUP_ID;
else commRXState = COMM_IDLE;
break;
case READING_GROUP_ID:
#ifdef PARSER_DEBUG
debug.println(">group");
#endif
if( checkGroup((uint8_t)inByte) ){
crc.add( (uint8_t)inByte );
commRXState = READING_NODE_ID;
}
else resetBuffer(RESET_REJECTED_GROUP);
break;
case READING_NODE_ID:
#ifdef PARSER_DEBUG
debug.println(">node");
#endif
if( checkNode((uint8_t)inByte) ){
crc.add( (uint8_t)inByte );
commRXState = READING_COMMAND;
}
else resetBuffer(RESET_REJECTED_NODE);
break;
case READING_COMMAND:
#ifdef PARSER_DEBUG
debug.println(">command");
#endif
commandIn = (uint8_t)inByte;
crc.add(commandIn);
commRXState = READING_PACKET_LENGTH;
break;
case READING_PACKET_LENGTH:
#ifdef PARSER_DEBUG
debug.println(">packet length");
#endif
packetLengthIn = (uint8_t)inByte;
crc.add(packetLengthIn);
if(packetLengthIn == 0) commRXState = READING_CHECKSUM;
else commRXState = READING_DATA;
break;
case READING_DATA:
#ifdef PARSER_DEBUG
debug.println(">data");
#endif
if(addToBuffer((uint8_t)inByte)) commRXState = READING_CHECKSUM;
break;
case READING_CHECKSUM:
#ifdef PARSER_DEBUG
debug.println(">checksum");
#endif
checksumIn = (uint8_t)inByte;
checksumOKFlag = verifyChecksum();
resetBuffer(RESET_DATA_OK);
#ifdef MESSAGE_TIMING_DEBUG
commRxEnd = micros();
MESSAGE_TIMING_DEBUG debug.print("RxStart ");
MESSAGE_TIMING_DEBUG debug.print(commRxStart);
MESSAGE_TIMING_DEBUG debug.print(" RxEnd ");
MESSAGE_TIMING_DEBUG debug.print(commRxEnd);
MESSAGE_TIMING_DEBUG debug.print(" elapsed ");
MESSAGE_TIMING_DEBUG debug.println(commRxEnd - commRxStart);
#endif
returnState = true;
break;
default:
#ifdef PARSER_DEBUG
debug.println("UNKNOWN STATE");
#endif
commRXState = COMM_IDLE;
break;
}
return returnState;
}