A library to send and receive packets over serial, uses MODSERIAL

Dependents:   SimpleSerialProtocolExample SerialFileReceiver

Committer:
p3p
Date:
Fri Sep 19 15:51:05 2014 +0000
Revision:
3:5caff50e14a7
Parent:
2:43794e0b738f
fixed packet detection when struggling to keep up with data stream

Who changed what in which revision?

UserRevisionLine numberNew contents of line
p3p 2:43794e0b738f 1 #ifndef SIMPLE_SERIAL_PROTOCOL_CODEC
p3p 2:43794e0b738f 2 #define SIMPLE_SERIAL_PROTOCOL_CODEC
p3p 2:43794e0b738f 3
p3p 2:43794e0b738f 4 #include "Ringbuffer.h"
p3p 2:43794e0b738f 5 #include "Packet.h"
p3p 2:43794e0b738f 6
p3p 2:43794e0b738f 7 namespace SimpleSerialProtocol {
p3p 2:43794e0b738f 8
p3p 2:43794e0b738f 9 class ICodec {
p3p 2:43794e0b738f 10 public:
p3p 2:43794e0b738f 11 ICodec(){}
p3p 2:43794e0b738f 12 virtual ~ICodec(){}
p3p 2:43794e0b738f 13 virtual bool encode(Packet* packet, RingBuffer* buffer) = 0;
p3p 2:43794e0b738f 14 virtual void decode(Packet* packet, char data) = 0;
p3p 2:43794e0b738f 15 virtual uint32_t getStreamErrors() = 0;
p3p 2:43794e0b738f 16 virtual uint32_t getPacketErrors() = 0;
p3p 2:43794e0b738f 17 };
p3p 2:43794e0b738f 18
p3p 2:43794e0b738f 19 class Codec: public ICodec {
p3p 2:43794e0b738f 20 public:
p3p 2:43794e0b738f 21 Codec(){
p3p 2:43794e0b738f 22 state = PACKET_STARTA;
p3p 2:43794e0b738f 23 header_read = 0;
p3p 2:43794e0b738f 24 data_read = 0;
p3p 2:43794e0b738f 25 stream_errors = 0;
p3p 2:43794e0b738f 26 packet_errors = 0;
p3p 2:43794e0b738f 27 }
p3p 2:43794e0b738f 28 virtual ~Codec(){}
p3p 2:43794e0b738f 29
p3p 2:43794e0b738f 30 virtual uint32_t getStreamErrors() {
p3p 2:43794e0b738f 31 return stream_errors;
p3p 2:43794e0b738f 32 }
p3p 2:43794e0b738f 33 virtual uint32_t getPacketErrors() {
p3p 2:43794e0b738f 34 return packet_errors;
p3p 2:43794e0b738f 35 }
p3p 2:43794e0b738f 36
p3p 2:43794e0b738f 37 virtual bool encode(Packet* packet, RingBuffer* buffer){
p3p 2:43794e0b738f 38 if (packet!=0) {
p3p 2:43794e0b738f 39
p3p 2:43794e0b738f 40 if((buffer->size() - buffer->available()) < packet->_size + 4){
p3p 2:43794e0b738f 41 return false;
p3p 2:43794e0b738f 42 }
p3p 2:43794e0b738f 43
p3p 3:5caff50e14a7 44 buffer->write(PACKET_BYTE1);
p3p 3:5caff50e14a7 45 buffer->write(PACKET_BYTE2);
p3p 2:43794e0b738f 46 buffer->write(packet->_size);
p3p 2:43794e0b738f 47 for (int i = 0; i < packet->_size; i++) {
p3p 2:43794e0b738f 48 buffer->write(packet->_data[i]);
p3p 2:43794e0b738f 49 }
p3p 2:43794e0b738f 50 buffer->write(checksum(packet));
p3p 2:43794e0b738f 51
p3p 2:43794e0b738f 52 return true;
p3p 2:43794e0b738f 53
p3p 2:43794e0b738f 54 }
p3p 2:43794e0b738f 55 return 0;
p3p 2:43794e0b738f 56 }
p3p 2:43794e0b738f 57
p3p 2:43794e0b738f 58 virtual void decode(Packet* packet, char data){
p3p 2:43794e0b738f 59 switch (state) {
p3p 2:43794e0b738f 60 case PACKET_STARTA:
p3p 2:43794e0b738f 61 if(data == PACKET_BYTE1){
p3p 2:43794e0b738f 62 state = PACKET_STARTB;
p3p 2:43794e0b738f 63 }
p3p 2:43794e0b738f 64 break;
p3p 2:43794e0b738f 65
p3p 2:43794e0b738f 66 case PACKET_STARTB:
p3p 2:43794e0b738f 67 if(data == PACKET_BYTE2){
p3p 2:43794e0b738f 68 state = HEADER_RECEIVE;
p3p 2:43794e0b738f 69 } else {
p3p 2:43794e0b738f 70 state = PACKET_STARTA;
p3p 2:43794e0b738f 71 stream_errors ++;
p3p 2:43794e0b738f 72 }
p3p 2:43794e0b738f 73 break;
p3p 2:43794e0b738f 74
p3p 2:43794e0b738f 75 case HEADER_RECEIVE:
p3p 2:43794e0b738f 76 header[header_read++] = data;
p3p 2:43794e0b738f 77 if(header_read == PACKET_HEADER_SIZE){
p3p 2:43794e0b738f 78 packet->_size = header[0];
p3p 2:43794e0b738f 79 state = DATA_RECEIVE;
p3p 2:43794e0b738f 80 }
p3p 2:43794e0b738f 81 break;
p3p 2:43794e0b738f 82
p3p 2:43794e0b738f 83 case DATA_RECEIVE:
p3p 2:43794e0b738f 84 if (data_read < packet->_size) {
p3p 2:43794e0b738f 85 packet->_data[data_read++] = data;
p3p 2:43794e0b738f 86 if (data_read == packet->_size) {
p3p 2:43794e0b738f 87 state = DATA_VALIDATE;
p3p 2:43794e0b738f 88 }
p3p 2:43794e0b738f 89 } else {
p3p 2:43794e0b738f 90 state = PACKET_STARTA;
p3p 2:43794e0b738f 91 header_read = 0;
p3p 2:43794e0b738f 92 data_read = 0;
p3p 2:43794e0b738f 93 }
p3p 2:43794e0b738f 94 break;
p3p 2:43794e0b738f 95
p3p 2:43794e0b738f 96 case DATA_VALIDATE:
p3p 2:43794e0b738f 97 packet->_type = packet->_data[0];
p3p 2:43794e0b738f 98 packet->_checksum = data;
p3p 2:43794e0b738f 99 if (checksum(packet) == packet->_checksum) {
p3p 2:43794e0b738f 100 packet->_valid = true;
p3p 2:43794e0b738f 101 } else {
p3p 2:43794e0b738f 102 packet_errors ++;
p3p 2:43794e0b738f 103 }
p3p 2:43794e0b738f 104 state = PACKET_STARTA;
p3p 2:43794e0b738f 105 header_read = 0;
p3p 2:43794e0b738f 106 data_read = 0;
p3p 2:43794e0b738f 107 break;
p3p 2:43794e0b738f 108
p3p 2:43794e0b738f 109 default:
p3p 2:43794e0b738f 110 state = PACKET_STARTA;
p3p 2:43794e0b738f 111 header_read = 0;
p3p 2:43794e0b738f 112 data_read = 0;
p3p 2:43794e0b738f 113 break;
p3p 2:43794e0b738f 114 }
p3p 2:43794e0b738f 115 }
p3p 2:43794e0b738f 116
p3p 2:43794e0b738f 117 virtual uint16_t checksum(Packet* packet){
p3p 2:43794e0b738f 118 uint8_t tmp_checksum = 16;
p3p 2:43794e0b738f 119 for (int i = 0; i < packet->_size; i++) {
p3p 2:43794e0b738f 120 tmp_checksum ^= packet->_data[i];
p3p 2:43794e0b738f 121 }
p3p 2:43794e0b738f 122 return tmp_checksum;
p3p 2:43794e0b738f 123 }
p3p 2:43794e0b738f 124
p3p 2:43794e0b738f 125
p3p 2:43794e0b738f 126 enum {
p3p 2:43794e0b738f 127 PACKET_STARTA,
p3p 2:43794e0b738f 128 PACKET_STARTB,
p3p 2:43794e0b738f 129 HEADER_RECEIVE,
p3p 2:43794e0b738f 130 DATA_RECEIVE,
p3p 2:43794e0b738f 131 DATA_VALIDATE,
p3p 2:43794e0b738f 132 };
p3p 2:43794e0b738f 133
p3p 2:43794e0b738f 134 enum {
p3p 2:43794e0b738f 135 PACKET_BYTE1 = 255,
p3p 2:43794e0b738f 136 PACKET_BYTE2 = 127,
p3p 2:43794e0b738f 137 PACKET_HEADER_SIZE = 1,
p3p 2:43794e0b738f 138 };
p3p 2:43794e0b738f 139
p3p 2:43794e0b738f 140 uint8_t state;
p3p 2:43794e0b738f 141 char header[PACKET_HEADER_SIZE];
p3p 2:43794e0b738f 142 uint8_t header_read;
p3p 2:43794e0b738f 143 uint32_t data_read;
p3p 2:43794e0b738f 144 uint32_t stream_errors;
p3p 2:43794e0b738f 145 uint32_t packet_errors;
p3p 2:43794e0b738f 146
p3p 2:43794e0b738f 147 };
p3p 2:43794e0b738f 148
p3p 2:43794e0b738f 149 }
p3p 2:43794e0b738f 150
p3p 2:43794e0b738f 151 #endif