A library to send and receive packets over serial, uses MODSERIAL
Dependents: SimpleSerialProtocolExample SerialFileReceiver
Protocol.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 | 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 | 2:43794e0b738f | 10 | #include "Codec.h" |
p3p | 0:1639507580d5 | 11 | #include "FPointer.h" |
p3p | 0:1639507580d5 | 12 | #include "Ringbuffer.h" |
p3p | 0:1639507580d5 | 13 | |
p3p | 0:1639507580d5 | 14 | namespace SimpleSerialProtocol { |
p3p | 0:1639507580d5 | 15 | |
p3p | 0:1639507580d5 | 16 | #define SEND_CHUNK_SIZE 512 |
p3p | 0:1639507580d5 | 17 | |
p3p | 0:1639507580d5 | 18 | class Protocol : public MODSERIAL { |
p3p | 0:1639507580d5 | 19 | public: |
p3p | 0:1639507580d5 | 20 | enum { |
p3p | 0:1639507580d5 | 21 | PACKET_START, |
p3p | 0:1639507580d5 | 22 | HEADER_RECEIVE, |
p3p | 0:1639507580d5 | 23 | DATA_RECEIVE, |
p3p | 0:1639507580d5 | 24 | DATA_VALIDATE, |
p3p | 0:1639507580d5 | 25 | }; |
p3p | 0:1639507580d5 | 26 | |
p3p | 0:1639507580d5 | 27 | Protocol(PinName tx, PinName rx, PinName led_pin); |
p3p | 0:1639507580d5 | 28 | virtual ~Protocol(); |
p3p | 0:1639507580d5 | 29 | |
p3p | 3:5caff50e14a7 | 30 | virtual void initialise(uint32_t baud) { |
p3p | 3:5caff50e14a7 | 31 | MODSERIAL::baud(baud); |
p3p | 3:5caff50e14a7 | 32 | } |
p3p | 3:5caff50e14a7 | 33 | |
p3p | 3:5caff50e14a7 | 34 | void setCodec(ICodec* stream_codec){ |
p3p | 2:43794e0b738f | 35 | codec = stream_codec; |
p3p | 0:1639507580d5 | 36 | } |
p3p | 0:1639507580d5 | 37 | |
p3p | 1:98ad30934a71 | 38 | virtual void update(); |
p3p | 0:1639507580d5 | 39 | |
p3p | 0:1639507580d5 | 40 | void send(uint8_t byte); |
p3p | 0:1639507580d5 | 41 | void blockUntilTxEmpty(); |
p3p | 0:1639507580d5 | 42 | |
p3p | 0:1639507580d5 | 43 | void baud(uint32_t baud_rate) { |
p3p | 0:1639507580d5 | 44 | blockUntilTxEmpty(); |
p3p | 0:1639507580d5 | 45 | MODSERIAL::baud(baud_rate); |
p3p | 0:1639507580d5 | 46 | } |
p3p | 0:1639507580d5 | 47 | |
p3p | 0:1639507580d5 | 48 | bool packetWaiting() { |
p3p | 0:1639507580d5 | 49 | return _packet._valid; |
p3p | 0:1639507580d5 | 50 | } |
p3p | 0:1639507580d5 | 51 | |
p3p | 0:1639507580d5 | 52 | uint32_t _corrupt_packets; |
p3p | 0:1639507580d5 | 53 | uint32_t _invalid_bytes; |
p3p | 0:1639507580d5 | 54 | |
p3p | 0:1639507580d5 | 55 | uint32_t droppedBytes(){ |
p3p | 0:1639507580d5 | 56 | return _send_buffer.droppedBytes(); |
p3p | 0:1639507580d5 | 57 | } |
p3p | 0:1639507580d5 | 58 | |
p3p | 0:1639507580d5 | 59 | uint32_t sendBufferSize(){ |
p3p | 0:1639507580d5 | 60 | return _send_buffer.available(); |
p3p | 0:1639507580d5 | 61 | } |
p3p | 0:1639507580d5 | 62 | |
p3p | 1:98ad30934a71 | 63 | template<class T> void receiveCallback(uint8_t type, T* item, void (T::*method)(Protocol*, Packet*)) { |
p3p | 0:1639507580d5 | 64 | FPointer callback; |
p3p | 0:1639507580d5 | 65 | callback.attach(item, (void (T::*)(Packet*))method); |
p3p | 0:1639507580d5 | 66 | _callback[type].push_back(callback); |
p3p | 0:1639507580d5 | 67 | } |
p3p | 0:1639507580d5 | 68 | |
p3p | 1:98ad30934a71 | 69 | template<class T> void transmitCallback(float frequency, T* item, void (T::*method)(Protocol*, Packet*)) { |
p3p | 0:1639507580d5 | 70 | FPointer callback; |
p3p | 0:1639507580d5 | 71 | callback.attach(item, (void (T::*)(Packet*))method); |
p3p | 0:1639507580d5 | 72 | _transmit_callback.push_back(TimerData(frequency, callback)); |
p3p | 0:1639507580d5 | 73 | } |
p3p | 0:1639507580d5 | 74 | |
p3p | 2:43794e0b738f | 75 | virtual void send(Packet* packet); |
p3p | 2:43794e0b738f | 76 | |
p3p | 2:43794e0b738f | 77 | void transmit(); |
p3p | 2:43794e0b738f | 78 | void receive(); |
p3p | 0:1639507580d5 | 79 | |
p3p | 0:1639507580d5 | 80 | DigitalOut _receive_led; |
p3p | 0:1639507580d5 | 81 | Packet _packet; |
p3p | 0:1639507580d5 | 82 | Packet _packet_transmit; |
p3p | 0:1639507580d5 | 83 | |
p3p | 0:1639507580d5 | 84 | Timer _receive_timeout; |
p3p | 0:1639507580d5 | 85 | Timer _throttle_transfer; |
p3p | 0:1639507580d5 | 86 | |
p3p | 0:1639507580d5 | 87 | struct TimerData { |
p3p | 0:1639507580d5 | 88 | TimerData(float frequency, FPointer callback) { |
p3p | 0:1639507580d5 | 89 | _timer.start(); |
p3p | 0:1639507580d5 | 90 | _frequency = frequency; |
p3p | 0:1639507580d5 | 91 | _callback = callback; |
p3p | 0:1639507580d5 | 92 | } |
p3p | 0:1639507580d5 | 93 | bool trigger() { |
p3p | 0:1639507580d5 | 94 | if (_timer.read_us() > _frequency) { |
p3p | 0:1639507580d5 | 95 | _timer.reset(); |
p3p | 0:1639507580d5 | 96 | return true; |
p3p | 0:1639507580d5 | 97 | } |
p3p | 0:1639507580d5 | 98 | return false; |
p3p | 0:1639507580d5 | 99 | } |
p3p | 0:1639507580d5 | 100 | Timer _timer; |
p3p | 0:1639507580d5 | 101 | float _frequency; |
p3p | 0:1639507580d5 | 102 | FPointer _callback; |
p3p | 0:1639507580d5 | 103 | }; |
p3p | 0:1639507580d5 | 104 | |
p3p | 0:1639507580d5 | 105 | RingBuffer _send_buffer; |
p3p | 0:1639507580d5 | 106 | std::map<uint8_t, std::vector<FPointer> > _callback; |
p3p | 0:1639507580d5 | 107 | std::vector<TimerData> _transmit_callback; |
p3p | 2:43794e0b738f | 108 | ICodec* codec; |
p3p | 3:5caff50e14a7 | 109 | Codec default_codec; |
p3p | 0:1639507580d5 | 110 | }; |
p3p | 0:1639507580d5 | 111 | |
p3p | 0:1639507580d5 | 112 | } |
p3p | 0:1639507580d5 | 113 | |
p3p | 0:1639507580d5 | 114 | #endif |