A library to send and receive packets over serial, uses MODSERIAL
Dependents: SimpleSerialProtocolExample SerialFileReceiver
Codec.h@3:5caff50e14a7, 2014-09-19 (annotated)
- 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?
User | Revision | Line number | New 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 |