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

Dependents:   SimpleSerialProtocolExample SerialFileReceiver

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?

UserRevisionLine numberNew 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