Files
@ a2269c9fe536
Branch filter:
Location: seniordesign-firmware/master/master/lib/serparser.c
a2269c9fe536
4.9 KiB
text/plain
merge
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | /*
* Master Firmware: Serial Parser
*
* Wireless Observational Modular Aerial Network
*
* Ethan Zonca
* Matthew Kanning
* Kyle Ripperger
* Matthew Kroening
*
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "../config.h"
#include "serial.h"
#include "serparser.h"
#include "led.h"
// Circular buffer for incoming data
uint8_t buffer[BUFFER_SIZE];
// Location of parser in the buffer
uint8_t bufferParsePosition = 0;
// Location of receive byte interrupt in the buffer
volatile uint16_t bufferDataPosition = 0;
// Parser state
uint8_t parserState = STATE_RESET;
uint8_t lastParserState = STATE_RESET;
// Length of current payload data (and checksum)
uint8_t payloadLength = 0;
// Data and checksum of most recent transmission
char receivedPayload[MAX_PAYLOAD_LEN];
// Payload type ID of the sensor of most recent transmission
char receivedPayloadType = 0;
// Checksum to be calculated and then compared to the received checksum
char checksumCalc = 0;
// Accessors
uint8_t getPayloadLength()
{
return payloadLength;
}
uint8_t* getPayload()
{
return receivedPayload;
}
uint8_t getPayloadType() {
return receivedPayloadType;
}
// Could inline if program space available
static void setParserState(uint8_t state)
{
lastParserState = parserState;
parserState = state;
// If resetting, clear vars
if(state == STATE_RESET)
{
payloadLength = 0;
checksumCalc = 0;
}
// Every time we change state, we have parsed a byte
bufferParsePosition = (bufferParsePosition + 1) % BUFFER_SIZE;
}
// Receive data on USART
char debugBuff[16];
ISR(USART0_RX_vect)
{
buffer[bufferDataPosition % BUFFER_SIZE] = UDR0;
bufferDataPosition = (bufferDataPosition + 1) % BUFFER_SIZE;
//sprintf(debugBuff, "bdp: %d, bpp: %d \r\n", bufferDataPosition, bufferParsePosition);
//serial0_sendString((debugBuff));
}
#define DEBUG
// Parse data from circular buffer
int serparser_parse(void)
{
char byte;
// Process first command (if any) on the circular buffer
while(bufferDataPosition != bufferParsePosition)
{
byte = buffer[bufferParsePosition];
// Reset
if(parserState == STATE_RESET)
{
if(byte == '[') // Start of frame; keep parsing
{
#ifdef DEBUG
serial0_sendString("start\r\n");
#endif
setParserState(STATE_GETDATATYPE);
}
else // Not start of frame, reset
{
#ifdef DEBUG
serial0_sendString("invalid\r\n");
#endif
setParserState(STATE_RESET);
return PARSERESULT_NODATA; // no valid start bit; better luck next time. run the function the next time around the main loop.
}
}
// Get payload type ID
else if(parserState == STATE_GETDATATYPE)
{
#ifdef DEBUG
serial0_sendString("type\r\n");
#endif
receivedPayloadType = byte; // Store the type of data receiving
checksumCalc += byte;
setParserState(STATE_GETDATA);
}
// Get payload data
else if(parserState == STATE_GETDATA)
{
if (byte == ']') // End of frame
{
#ifdef DEBUG
serial0_sendString("eof\r\n");
sprintf(debugBuff, "%d B, sum=%d\r\n", payloadLength, checksumCalc);
serial0_sendString((debugBuff));
#endif
receivedPayload[payloadLength] = 0; // null-terminate string for atoi
setParserState(STATE_GETCHECKSUM);
// Checksum is now after the close bracket to solve bug FS#29
}
else // Still receiving data
{
#ifdef DEBUG
serial0_sendString("data\r\n");
#endif
receivedPayload[payloadLength] = byte;
payloadLength++;
checksumCalc += byte;
// Data buffer overrun protection
if(payloadLength > MAX_PAYLOAD_LEN) {
#ifdef DEBUG
serial0_sendString("ovf\r\n");
#endif
setParserState(STATE_RESET);
return PARSERESULT_FAIL;
}
else {
// Set state. MUST call even though state is maintained to update parse position
setParserState(STATE_GETDATA);
return PARSERESULT_STILLPARSING;
}
}
}
else if(STATE_GETCHECKSUM)
{
// TODO: Compare checksums
if(byte == checksumCalc) {
#ifdef DEBUG
serial0_sendString("check\r\n");
#endif
setParserState(STATE_RESET);
return PARSERESULT_PARSEOK;
}
else {
#ifdef DEBUG
serial0_sendString("bcheck\r\n");
#endif
setParserState(STATE_RESET);
return PARSERESULT_FAIL;
}
/*
if(bufferParsePosition == bufferDataPosition)
{
// We are at the end of the line. No more data to parse.
setParserState(STATE_RESET);
return PARSERESULT_PARSEOK;
}
else
{
setParserState(STATE_RESET);
// we could choose to keep parsing now, or parse the next message next loop around (better idea).
// return now so we hit it the next time around
return PARSERESULT_PARSEOK;
}
*/
}
}
return PARSERESULT_NODATA;
}
|