I have an ISR putting in bytes from the UART on an AVR XMEGA into a circular buffer. Every byte received, also increments RX_COUNT. I copy the circular buffer into a local buffer if it is at least two bytes for a potential "#A" command.
The protocol I am using is #A, #B, #C, etc. The problem is I am searching for the sync char, '#' and they seeing what the next byte is, and checking if it is a valid command. The issue is, sometimes if I send a string like aaaaaaa#A it doesn't execute the command. I'm simulating garbage data to see if it will ever sync to the byte. How can I make sure that I will eventually sync to the start of the message?
Periodically, I have from my main function, check how much data is available in the circular buffer. If there is at least 2 bytes available, I copy the circular buffer into a local buffer:
USART_RXBufferData_Available() returns true or false is there is any data in the circular buffer.
Another question is, do I even have to copy the circular buffer into a local buffer? What is generally the best practice to decode a serial packet similar to this?
#define MIN_MSG_SIZE 2 // Command is #A, #B, #C, etc...
bool dataAvailable = false;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
// Copy Circular buffer into local buffer
if (USART_RXBufferData_Available(&UARTCom1))
{
if (UARTCom1.buffer.RX_Count >= MIN_MSG_SIZE)
{
for (int i = 0; i < MIN_MSG_SIZE; i++)
{
localBuff[i] = USART_RXBuffer_GetByte(&UARTCom1);
UARTCom1.buffer.RX_Count--; // decrement RX count
}
dataAvailable = true;
}
}
else
{
dataAvailable = false;
}
}
if ((dataAvailable) && localBuff[0] == '#') // Check if there is a new Message AND Check Sync Byte
{
uint8_t data = localBuff[1];
PORTR_DIR = 0b00000011;
char led0Msg[] = "Turning ON LED0\r\n";
char led1Msg[] = "Turning ON LED1\r\n";
char ledoffMsg[] = "Turning OFF LEDS\r\n";
switch (data)
{
case 'A':
UART->transmit(led0Msg, strlen(led0Msg));
PORTR_OUT = ~(PIN0_bm); // Turn on LED0
break;
case 'B':
UART->transmit(led1Msg, strlen(led1Msg));
PORTR_OUT = ~(PIN1_bm); // Turn on LED1
break;
default:
UART->transmit(ledoffMsg, strlen(ledoffMsg));
PORTR_OUT = (PIN1_bm | PIN0_bm); // Turn off BOTH LEDS
}
memset(localBuff, 0, sizeof(localBuff)); // Clear the buffer
return true;
}
localLan1Buff
and how do you know it has '#' at index 0? You're also assuming that your command character will be inlocalBuff[1]
, but will it be every time? Also, don't see where you are settingdataAvailable
back to false. \$\endgroup\$localBuff[0]
and potentially also inlocalBuff[1]
. You could also end up with 'a' inlocalBuff[0]
and '#' inlocalBuff[1]
. \$\endgroup\$a#AB
? Possibly, what you'll see in your local buffer isa#
andAB
, while you'd want#A
. So don't copy from the circular buffer this way. \$\endgroup\$