A library to send and receive packets over serial, uses MODSERIAL
Dependents: SimpleSerialProtocolExample SerialFileReceiver
Protocol.h@1:98ad30934a71, 2014-08-27 (annotated)
- Committer:
- p3p
- Date:
- Wed Aug 27 17:35:30 2014 +0000
- Revision:
- 1:98ad30934a71
- Parent:
- 0:1639507580d5
- Child:
- 2:43794e0b738f
Fixed the packet state machine, and added access to the protocol from callbacks
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
p3p | 0:1639507580d5 | 1 | #ifndef SIMPLE_SERIAL_PROTOCOL |
p3p | 0:1639507580d5 | 2 | #define SIMPLE_SERIAL_PROTOCOL |
p3p | 0:1639507580d5 | 3 | |
p3p | 0:1639507580d5 | 4 | #include <map> |
p3p | 0:1639507580d5 | 5 | #include <vector> |
p3p | 0:1639507580d5 | 6 | |
p3p | 0:1639507580d5 | 7 | #include "mbed.h" |
p3p | 0:1639507580d5 | 8 | #include "MODSERIAL.h" |
p3p | 0:1639507580d5 | 9 | #include "Packet.h" |
p3p | 0:1639507580d5 | 10 | #include "FPointer.h" |
p3p | 0:1639507580d5 | 11 | #include "Ringbuffer.h" |
p3p | 0:1639507580d5 | 12 | |
p3p | 0:1639507580d5 | 13 | namespace SimpleSerialProtocol { |
p3p | 0:1639507580d5 | 14 | |
p3p | 0:1639507580d5 | 15 | #define SEND_CHUNK_SIZE 512 |
p3p | 0:1639507580d5 | 16 | |
p3p | 0:1639507580d5 | 17 | class Protocol : public MODSERIAL { |
p3p | 0:1639507580d5 | 18 | public: |
p3p | 0:1639507580d5 | 19 | enum { |
p3p | 0:1639507580d5 | 20 | PACKET_START, |
p3p | 0:1639507580d5 | 21 | HEADER_RECEIVE, |
p3p | 0:1639507580d5 | 22 | DATA_RECEIVE, |
p3p | 0:1639507580d5 | 23 | DATA_VALIDATE, |
p3p | 0:1639507580d5 | 24 | }; |
p3p | 0:1639507580d5 | 25 | |
p3p | 0:1639507580d5 | 26 | Protocol(PinName tx, PinName rx, PinName led_pin); |
p3p | 0:1639507580d5 | 27 | virtual ~Protocol(); |
p3p | 0:1639507580d5 | 28 | |
p3p | 1:98ad30934a71 | 29 | virtual void initialise(uint32_t baud) { |
p3p | 1:98ad30934a71 | 30 | MODSERIAL::baud(baud); |
p3p | 0:1639507580d5 | 31 | } |
p3p | 0:1639507580d5 | 32 | |
p3p | 1:98ad30934a71 | 33 | virtual void update(); |
p3p | 0:1639507580d5 | 34 | |
p3p | 0:1639507580d5 | 35 | void send(uint8_t byte); |
p3p | 0:1639507580d5 | 36 | void blockUntilTxEmpty(); |
p3p | 0:1639507580d5 | 37 | |
p3p | 0:1639507580d5 | 38 | void baud(uint32_t baud_rate) { |
p3p | 0:1639507580d5 | 39 | blockUntilTxEmpty(); |
p3p | 0:1639507580d5 | 40 | MODSERIAL::baud(baud_rate); |
p3p | 0:1639507580d5 | 41 | } |
p3p | 0:1639507580d5 | 42 | |
p3p | 0:1639507580d5 | 43 | bool packetWaiting() { |
p3p | 0:1639507580d5 | 44 | return _packet._valid; |
p3p | 0:1639507580d5 | 45 | } |
p3p | 0:1639507580d5 | 46 | |
p3p | 0:1639507580d5 | 47 | uint32_t _corrupt_packets; |
p3p | 0:1639507580d5 | 48 | uint32_t _invalid_bytes; |
p3p | 0:1639507580d5 | 49 | |
p3p | 0:1639507580d5 | 50 | uint32_t droppedBytes(){ |
p3p | 0:1639507580d5 | 51 | return _send_buffer.droppedBytes(); |
p3p | 0:1639507580d5 | 52 | } |
p3p | 0:1639507580d5 | 53 | |
p3p | 0:1639507580d5 | 54 | uint32_t sendBufferSize(){ |
p3p | 0:1639507580d5 | 55 | return _send_buffer.available(); |
p3p | 0:1639507580d5 | 56 | } |
p3p | 0:1639507580d5 | 57 | |
p3p | 1:98ad30934a71 | 58 | template<class T> void receiveCallback(uint8_t type, T* item, void (T::*method)(Protocol*, Packet*)) { |
p3p | 0:1639507580d5 | 59 | FPointer callback; |
p3p | 0:1639507580d5 | 60 | callback.attach(item, (void (T::*)(Packet*))method); |
p3p | 0:1639507580d5 | 61 | _callback[type].push_back(callback); |
p3p | 0:1639507580d5 | 62 | } |
p3p | 0:1639507580d5 | 63 | |
p3p | 1:98ad30934a71 | 64 | template<class T> void transmitCallback(float frequency, T* item, void (T::*method)(Protocol*, Packet*)) { |
p3p | 0:1639507580d5 | 65 | FPointer callback; |
p3p | 0:1639507580d5 | 66 | callback.attach(item, (void (T::*)(Packet*))method); |
p3p | 0:1639507580d5 | 67 | _transmit_callback.push_back(TimerData(frequency, callback)); |
p3p | 0:1639507580d5 | 68 | } |
p3p | 0:1639507580d5 | 69 | |
p3p | 0:1639507580d5 | 70 | virtual void sendPacket(Packet* packet) { |
p3p | 0:1639507580d5 | 71 | if (packet!=0) { |
p3p | 0:1639507580d5 | 72 | send(255); |
p3p | 0:1639507580d5 | 73 | send(127); |
p3p | 0:1639507580d5 | 74 | send(packet->_size); |
p3p | 0:1639507580d5 | 75 | for (int i = 0; i < packet->_size; i++) { |
p3p | 0:1639507580d5 | 76 | send(packet->_data[i]); |
p3p | 0:1639507580d5 | 77 | } |
p3p | 0:1639507580d5 | 78 | send(checksum(packet->_data, packet->_size)); |
p3p | 0:1639507580d5 | 79 | } |
p3p | 0:1639507580d5 | 80 | } |
p3p | 0:1639507580d5 | 81 | |
p3p | 0:1639507580d5 | 82 | DigitalOut _receive_led; |
p3p | 0:1639507580d5 | 83 | Packet _packet; |
p3p | 0:1639507580d5 | 84 | Packet _packet_transmit; |
p3p | 0:1639507580d5 | 85 | |
p3p | 0:1639507580d5 | 86 | Timer _receive_timeout; |
p3p | 0:1639507580d5 | 87 | Timer _throttle_transfer; |
p3p | 0:1639507580d5 | 88 | |
p3p | 0:1639507580d5 | 89 | void send(); |
p3p | 0:1639507580d5 | 90 | virtual void receive(); |
p3p | 0:1639507580d5 | 91 | static uint8_t checksum(uint8_t* packet, uint16_t packet_size); |
p3p | 0:1639507580d5 | 92 | |
p3p | 0:1639507580d5 | 93 | struct TimerData { |
p3p | 0:1639507580d5 | 94 | TimerData(float frequency, FPointer callback) { |
p3p | 0:1639507580d5 | 95 | _timer.start(); |
p3p | 0:1639507580d5 | 96 | _frequency = frequency; |
p3p | 0:1639507580d5 | 97 | _callback = callback; |
p3p | 0:1639507580d5 | 98 | } |
p3p | 0:1639507580d5 | 99 | bool trigger() { |
p3p | 0:1639507580d5 | 100 | if (_timer.read_us() > _frequency) { |
p3p | 0:1639507580d5 | 101 | _timer.reset(); |
p3p | 0:1639507580d5 | 102 | return true; |
p3p | 0:1639507580d5 | 103 | } |
p3p | 0:1639507580d5 | 104 | return false; |
p3p | 0:1639507580d5 | 105 | } |
p3p | 0:1639507580d5 | 106 | Timer _timer; |
p3p | 0:1639507580d5 | 107 | float _frequency; |
p3p | 0:1639507580d5 | 108 | FPointer _callback; |
p3p | 0:1639507580d5 | 109 | }; |
p3p | 0:1639507580d5 | 110 | |
p3p | 0:1639507580d5 | 111 | uint8_t _header[2]; |
p3p | 0:1639507580d5 | 112 | uint8_t _header_read; |
p3p | 0:1639507580d5 | 113 | uint8_t _data_read; |
p3p | 0:1639507580d5 | 114 | uint8_t _footer[4]; |
p3p | 0:1639507580d5 | 115 | uint8_t _footer_read; |
p3p | 0:1639507580d5 | 116 | uint8_t _state; |
p3p | 0:1639507580d5 | 117 | uint8_t _last_byte; |
p3p | 0:1639507580d5 | 118 | |
p3p | 0:1639507580d5 | 119 | |
p3p | 0:1639507580d5 | 120 | RingBuffer _send_buffer; |
p3p | 0:1639507580d5 | 121 | std::map<uint8_t, std::vector<FPointer> > _callback; |
p3p | 0:1639507580d5 | 122 | std::vector<TimerData> _transmit_callback; |
p3p | 0:1639507580d5 | 123 | }; |
p3p | 0:1639507580d5 | 124 | |
p3p | 0:1639507580d5 | 125 | } |
p3p | 0:1639507580d5 | 126 | |
p3p | 0:1639507580d5 | 127 | #endif |