A library to send and receive packets over serial, uses MODSERIAL
Dependents: SimpleSerialProtocolExample SerialFileReceiver
Diff: Codec.h
- Revision:
- 2:43794e0b738f
- Child:
- 3:5caff50e14a7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Codec.h Thu Sep 18 17:37:04 2014 +0000 @@ -0,0 +1,151 @@ +#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(255); + buffer->write(127); + 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 \ No newline at end of file