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

Dependents:   SimpleSerialProtocolExample SerialFileReceiver

Protocol.h

Committer:
p3p
Date:
2014-08-27
Revision:
1:98ad30934a71
Parent:
0:1639507580d5
Child:
2:43794e0b738f

File content as of revision 1:98ad30934a71:

#ifndef SIMPLE_SERIAL_PROTOCOL
#define SIMPLE_SERIAL_PROTOCOL

#include <map>
#include <vector>

#include "mbed.h"
#include "MODSERIAL.h"
#include "Packet.h"
#include "FPointer.h"
#include "Ringbuffer.h"

namespace SimpleSerialProtocol {

#define SEND_CHUNK_SIZE 512

class Protocol : public MODSERIAL {
public:
    enum {
        PACKET_START,
        HEADER_RECEIVE,
        DATA_RECEIVE,
        DATA_VALIDATE,
    };
    
    Protocol(PinName tx, PinName rx, PinName led_pin);
    virtual ~Protocol();

    virtual void initialise(uint32_t baud) {
        MODSERIAL::baud(baud);
    }
    
    virtual void update();
    
    void send(uint8_t byte);
    void blockUntilTxEmpty();
    
    void baud(uint32_t baud_rate) {
        blockUntilTxEmpty();
        MODSERIAL::baud(baud_rate);
    }

    bool packetWaiting() {
        return _packet._valid;
    }

    uint32_t _corrupt_packets;
    uint32_t _invalid_bytes;
    
    uint32_t droppedBytes(){
        return _send_buffer.droppedBytes();
    }
    
    uint32_t sendBufferSize(){
        return _send_buffer.available();
    }

    template<class T> void receiveCallback(uint8_t type, T* item, void (T::*method)(Protocol*, Packet*)) {
        FPointer callback;
        callback.attach(item, (void (T::*)(Packet*))method);
        _callback[type].push_back(callback);
    }

    template<class T> void transmitCallback(float frequency, T* item, void (T::*method)(Protocol*, Packet*)) {
        FPointer callback;
        callback.attach(item, (void (T::*)(Packet*))method);
        _transmit_callback.push_back(TimerData(frequency, callback));
    }

    virtual void sendPacket(Packet* packet) {
        if (packet!=0) {
            send(255);
            send(127);
            send(packet->_size);
            for (int i = 0; i < packet->_size; i++) {
                send(packet->_data[i]);
            }
            send(checksum(packet->_data,  packet->_size));
        }
    }

    DigitalOut _receive_led;
    Packet _packet;
    Packet _packet_transmit;
    
    Timer _receive_timeout;
    Timer _throttle_transfer;
    
    void send();
    virtual void receive();
    static uint8_t checksum(uint8_t* packet, uint16_t packet_size);

    struct TimerData {
        TimerData(float frequency, FPointer callback) {
            _timer.start();
            _frequency = frequency;
            _callback = callback;
        }
        bool trigger() {
            if (_timer.read_us() > _frequency) {
                _timer.reset();
                return true;
            }
            return false;
        }
        Timer _timer;
        float _frequency;
        FPointer _callback;
    };

    uint8_t _header[2];
    uint8_t _header_read;
    uint8_t _data_read;
    uint8_t _footer[4];
    uint8_t _footer_read;
    uint8_t _state;
    uint8_t _last_byte;


    RingBuffer _send_buffer;
    std::map<uint8_t, std::vector<FPointer> > _callback;
    std::vector<TimerData> _transmit_callback;
};

}

#endif