Just a small test for frames and serial (RS232) communication, with ideas from http://eli.thegreenplace.net/2009/08/20/frames-and-protocols-for-the-serial-port-in-python/
parser.c
- Committer:
- janwesterkamp
- Date:
- 2012-05-02
- Revision:
- 0:566fc5f530fe
File content as of revision 0:566fc5f530fe:
/*
*
*/
#include "mbed.h"
#include "parser.h"
int wrap_protocol(char *c, string *message, list<string> *messages, char header, char footer, char dle ) {
static int state = 0;
static int dle_state = 0;
static int index;
static int size;
switch (state) {
case 0: // start sending a header if there is a valid message available
if (!messages->empty()) {
*message = messages->front();
messages->pop_front(); // now that we have the message, delete it from the list
index = 0; // initialize sending the actual message
size = message->size();
state = 1;
*c = header;
return WRAP_SEND;
}
return WRAP_ABORT;
case 1:
if ((size == 0) || (index==size)) {
*c = footer;
state = 0;
return WRAP_FINISHED;
}
*c = (*message)[index];
if ( dle_state == 1 ) {
dle_state = 0;
index++;
return WRAP_SEND;
}
if ( (*c == header) || (*c == footer) || (*c == dle) ) {
dle_state = 1;
*c = dle;
return WRAP_SEND;
}
index++;
return WRAP_SEND;
}
// if we reach this point, something went wrong!
return WRAP_ABORT;
}
void unwrap_protocol(char *c, string *buffer, list<string> *messages, unsigned int max_message_size,
unsigned int max_messages, char header, char footer, char dle ) {
// these are needed for the internal state of the function
// they are also the reaseon, why this function can only be used in exactly one location
// i.e. the interrupt routine for receiving characters from the RS232
static int state = 0;
static int dle_state = 0;
switch (state) {
case 0:
if (*c == header) {
message_led=!message_led;
state = 1;
}
return;
case 1:
if (*c== header && dle_state==0) {
// new header that is not escaped will set e new message start
buffer->clear();
return;
}
if (*c == footer && dle_state==0 ) {
// a frame end is only a frame end, if the footer is not escaped
messages->push_back( *buffer );
buffer->clear();
state = 0;
message_led=!message_led;
return;
}
// check length of buffer; clear, if too large; restart search for header!
if (buffer->length() > max_message_size) {
// prevent buffer overflows if someone is flooding us with characters
buffer->clear();
state=0;
return;
}
if (*c == dle && dle_state==0) {
// the next character is "escaped" and is part of the message
dle_state = 1;
return;
}
// probably the easiest and quickest way of resetting the dle_state
dle_state = 0;
// in all other cases, we found a new character and append it to the buffer
*buffer += *c;
}
}