A library to send and receive packets over serial, uses MODSERIAL
Dependents: SimpleSerialProtocolExample SerialFileReceiver
Codec.h
- Committer:
- p3p
- Date:
- 2014-09-19
- Revision:
- 3:5caff50e14a7
- Parent:
- 2:43794e0b738f
File content as of revision 3:5caff50e14a7:
#ifndef SIMPLE_SERIAL_PROTOCOL_CODEC #define SIMPLE_SERIAL_PROTOCOL_CODEC #include "Ringbuffer.h" #include "Packet.h" namespace SimpleSerialProtocol { class ICodec { public: ICodec(){} virtual ~ICodec(){} virtual bool encode(Packet* packet, RingBuffer* buffer) = 0; virtual void decode(Packet* packet, char data) = 0; virtual uint32_t getStreamErrors() = 0; virtual uint32_t getPacketErrors() = 0; }; class Codec: public ICodec { public: Codec(){ state = PACKET_STARTA; header_read = 0; data_read = 0; stream_errors = 0; packet_errors = 0; } virtual ~Codec(){} virtual uint32_t getStreamErrors() { return stream_errors; } virtual uint32_t getPacketErrors() { return packet_errors; } virtual bool encode(Packet* packet, RingBuffer* buffer){ if (packet!=0) { if((buffer->size() - buffer->available()) < packet->_size + 4){ return false; } buffer->write(PACKET_BYTE1); buffer->write(PACKET_BYTE2); buffer->write(packet->_size); for (int i = 0; i < packet->_size; i++) { buffer->write(packet->_data[i]); } buffer->write(checksum(packet)); return true; } return 0; } virtual void decode(Packet* packet, char data){ switch (state) { case PACKET_STARTA: if(data == PACKET_BYTE1){ state = PACKET_STARTB; } break; case PACKET_STARTB: if(data == PACKET_BYTE2){ state = HEADER_RECEIVE; } else { state = PACKET_STARTA; stream_errors ++; } break; case HEADER_RECEIVE: header[header_read++] = data; if(header_read == PACKET_HEADER_SIZE){ packet->_size = header[0]; state = DATA_RECEIVE; } break; case DATA_RECEIVE: if (data_read < packet->_size) { packet->_data[data_read++] = data; if (data_read == packet->_size) { state = DATA_VALIDATE; } } else { state = PACKET_STARTA; header_read = 0; data_read = 0; } break; case DATA_VALIDATE: packet->_type = packet->_data[0]; packet->_checksum = data; if (checksum(packet) == packet->_checksum) { packet->_valid = true; } else { packet_errors ++; } state = PACKET_STARTA; header_read = 0; data_read = 0; break; default: state = PACKET_STARTA; header_read = 0; data_read = 0; break; } } virtual uint16_t checksum(Packet* packet){ uint8_t tmp_checksum = 16; for (int i = 0; i < packet->_size; i++) { tmp_checksum ^= packet->_data[i]; } return tmp_checksum; } enum { PACKET_STARTA, PACKET_STARTB, HEADER_RECEIVE, DATA_RECEIVE, DATA_VALIDATE, }; enum { PACKET_BYTE1 = 255, PACKET_BYTE2 = 127, PACKET_HEADER_SIZE = 1, }; uint8_t state; char header[PACKET_HEADER_SIZE]; uint8_t header_read; uint32_t data_read; uint32_t stream_errors; uint32_t packet_errors; }; } #endif