A library to send and receive packets over serial, uses MODSERIAL
Dependents: SimpleSerialProtocolExample SerialFileReceiver
Protocol.h@2:43794e0b738f, 2014-09-18 (annotated)
- Committer:
- p3p
- Date:
- Thu Sep 18 17:37:04 2014 +0000
- Revision:
- 2:43794e0b738f
- Parent:
- 1:98ad30934a71
- Child:
- 3:5caff50e14a7
Refactored Protocol format into a separate codec class, implementing multiple codecs is now simple
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 | 2:43794e0b738f | 30 | virtual void initialise(uint32_t baud, ICodec* stream_codec) { |
p3p | 2:43794e0b738f | 31 | codec = stream_codec; |
p3p | 1:98ad30934a71 | 32 | MODSERIAL::baud(baud); |
p3p | 0:1639507580d5 | 33 | } |
p3p | 0:1639507580d5 | 34 | |
p3p | 1:98ad30934a71 | 35 | virtual void update(); |
p3p | 0:1639507580d5 | 36 | |
p3p | 0:1639507580d5 | 37 | void send(uint8_t byte); |
p3p | 0:1639507580d5 | 38 | void blockUntilTxEmpty(); |
p3p | 0:1639507580d5 | 39 | |
p3p | 0:1639507580d5 | 40 | void baud(uint32_t baud_rate) { |
p3p | 0:1639507580d5 | 41 | blockUntilTxEmpty(); |
p3p | 0:1639507580d5 | 42 | MODSERIAL::baud(baud_rate); |
p3p | 0:1639507580d5 | 43 | } |
p3p | 0:1639507580d5 | 44 | |
p3p | 0:1639507580d5 | 45 | bool packetWaiting() { |
p3p | 0:1639507580d5 | 46 | return _packet._valid; |
p3p | 0:1639507580d5 | 47 | } |
p3p | 0:1639507580d5 | 48 | |
p3p | 0:1639507580d5 | 49 | uint32_t _corrupt_packets; |
p3p | 0:1639507580d5 | 50 | uint32_t _invalid_bytes; |
p3p | 0:1639507580d5 | 51 | |
p3p | 0:1639507580d5 | 52 | uint32_t droppedBytes(){ |
p3p | 0:1639507580d5 | 53 | return _send_buffer.droppedBytes(); |
p3p | 0:1639507580d5 | 54 | } |
p3p | 0:1639507580d5 | 55 | |
p3p | 0:1639507580d5 | 56 | uint32_t sendBufferSize(){ |
p3p | 0:1639507580d5 | 57 | return _send_buffer.available(); |
p3p | 0:1639507580d5 | 58 | } |
p3p | 0:1639507580d5 | 59 | |
p3p | 1:98ad30934a71 | 60 | template<class T> void receiveCallback(uint8_t type, T* item, void (T::*method)(Protocol*, Packet*)) { |
p3p | 0:1639507580d5 | 61 | FPointer callback; |
p3p | 0:1639507580d5 | 62 | callback.attach(item, (void (T::*)(Packet*))method); |
p3p | 0:1639507580d5 | 63 | _callback[type].push_back(callback); |
p3p | 0:1639507580d5 | 64 | } |
p3p | 0:1639507580d5 | 65 | |
p3p | 1:98ad30934a71 | 66 | template<class T> void transmitCallback(float frequency, T* item, void (T::*method)(Protocol*, Packet*)) { |
p3p | 0:1639507580d5 | 67 | FPointer callback; |
p3p | 0:1639507580d5 | 68 | callback.attach(item, (void (T::*)(Packet*))method); |
p3p | 0:1639507580d5 | 69 | _transmit_callback.push_back(TimerData(frequency, callback)); |
p3p | 0:1639507580d5 | 70 | } |
p3p | 0:1639507580d5 | 71 | |
p3p | 2:43794e0b738f | 72 | virtual void send(Packet* packet); |
p3p | 2:43794e0b738f | 73 | |
p3p | 2:43794e0b738f | 74 | void transmit(); |
p3p | 2:43794e0b738f | 75 | void receive(); |
p3p | 0:1639507580d5 | 76 | |
p3p | 0:1639507580d5 | 77 | DigitalOut _receive_led; |
p3p | 0:1639507580d5 | 78 | Packet _packet; |
p3p | 0:1639507580d5 | 79 | Packet _packet_transmit; |
p3p | 0:1639507580d5 | 80 | |
p3p | 0:1639507580d5 | 81 | Timer _receive_timeout; |
p3p | 0:1639507580d5 | 82 | Timer _throttle_transfer; |
p3p | 0:1639507580d5 | 83 | |
p3p | 0:1639507580d5 | 84 | struct TimerData { |
p3p | 0:1639507580d5 | 85 | TimerData(float frequency, FPointer callback) { |
p3p | 0:1639507580d5 | 86 | _timer.start(); |
p3p | 0:1639507580d5 | 87 | _frequency = frequency; |
p3p | 0:1639507580d5 | 88 | _callback = callback; |
p3p | 0:1639507580d5 | 89 | } |
p3p | 0:1639507580d5 | 90 | bool trigger() { |
p3p | 0:1639507580d5 | 91 | if (_timer.read_us() > _frequency) { |
p3p | 0:1639507580d5 | 92 | _timer.reset(); |
p3p | 0:1639507580d5 | 93 | return true; |
p3p | 0:1639507580d5 | 94 | } |
p3p | 0:1639507580d5 | 95 | return false; |
p3p | 0:1639507580d5 | 96 | } |
p3p | 0:1639507580d5 | 97 | Timer _timer; |
p3p | 0:1639507580d5 | 98 | float _frequency; |
p3p | 0:1639507580d5 | 99 | FPointer _callback; |
p3p | 0:1639507580d5 | 100 | }; |
p3p | 0:1639507580d5 | 101 | |
p3p | 0:1639507580d5 | 102 | RingBuffer _send_buffer; |
p3p | 0:1639507580d5 | 103 | std::map<uint8_t, std::vector<FPointer> > _callback; |
p3p | 0:1639507580d5 | 104 | std::vector<TimerData> _transmit_callback; |
p3p | 2:43794e0b738f | 105 | ICodec* codec; |
p3p | 0:1639507580d5 | 106 | }; |
p3p | 0:1639507580d5 | 107 | |
p3p | 0:1639507580d5 | 108 | } |
p3p | 0:1639507580d5 | 109 | |
p3p | 0:1639507580d5 | 110 | #endif |