Experiment of serial command protocol

Dependencies:   RingBuffer SerialInterfaceProtocol duinotech_16x2_LCD mbed

You can edit this area

Files at this revision

API Documentation at this revision

Comitter:
rba90
Date:
Sun Jun 19 01:39:39 2016 +0000
Parent:
3:0c4aa3cec685
Commit message:
Create new library

Changed in this revision

CommandPacket.cpp Show diff for this revision Revisions of this file
CommandPacket.h Show diff for this revision Revisions of this file
RingBuffer.lib Show annotated file Show diff for this revision Revisions of this file
SerialInterfaceProtocol.cpp Show diff for this revision Revisions of this file
SerialInterfaceProtocol.h Show diff for this revision Revisions of this file
SerialInterfaceProtocol.lib Show annotated file Show diff for this revision Revisions of this file
buffer.cpp Show diff for this revision Revisions of this file
buffer.h Show diff for this revision Revisions of this file
--- a/CommandPacket.cpp	Thu Jun 16 03:52:01 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-#include "CommandPacket.h"
-#include "mbed.h"
-
-#define CHECKSUM_DEBUG
-
-uint8_t generate_checksum(uint8_t *data, uint8_t length, uint8_t offset)
-{
-    uint8_t s = 0;
-    
-    if (data)
-    {
-        // take the sum of all data bytes preceding checksum field
-        for(uint8_t i = 0; i < length; i++)
-        {
-            s += data[i + offset];
-        }
-        
-        // calculate two's complement of the remainder
-        s = 0xff - s + 1;
-    }
-    
-    return s;
-}
-
-uint8_t hexchar_to_uint8(uint8_t ch)
-{
-    uint8_t val = 0;
-
-    if (ch >= '0' && ch <= '9')
-    {
-        val = ch - '0';
-    }
-    else if (ch >= 'A' && ch <= 'F')
-    {
-        val  = ch - 'A';
-        val += 10;
-    }
-    else if (ch >= 'a' && ch <= 'f')
-    {
-        val = ch - 'a';
-        val += 10;
-    }
-
-    return val;
-}
-    
-
-bool CommandPacket::verify()
-{
-    return checksum == generate_checksum();
-}
-
-CommandPacket::CommandPacket()
-{
-    // reset internal error number
-    errno = NO_ERROR;
-    
-    // set public variables
-    sflag = '<';
-    command = 0x0;
-    length = 0x0;
-    memset(payload, 0x0, sizeof(payload));
-    checksum = 0x0;
-    eflag = '>';
-}
-
-const char *CommandPacket::getErrorString() const
-{
-    return errorString[errno];
-}
-
-int CommandPacket::serialize(uint8_t *output)
-{    
-    // create buffer for payload
-    uint8_t buffer[length * 2];
-    memset(buffer, 0x0, sizeof(buffer));
-    
-    for (int i = 0; i < length; i++)
-    {
-        sprintf((char *) (buffer + i * 2), "%02X", payload[i]);
-    }
-    
-    // assume the user provide output buffer large enough
-    sprintf((char *) output, "%c%02X%02X%s%02X%c",
-        sflag,
-        command,
-        length,
-        (char *) buffer,
-        generate_checksum(),
-        eflag
-    );
-    
-    return length;
-}
-
-uint8_t CommandPacket::generate_checksum()
-{
-    // checksum is defined by the sum of all characters between sflag and checksum field
-    uint8_t s = 0;
-    
-    // include command
-    s += command;
-    
-    // include length
-    s += length;
-    
-    // include payload
-    for (int i = 0; i < length; i++)
-    {
-        s += payload[i];
-    }
-    
-    // calculate two's complement of the remainder
-    s = 0xff - s + 1;
-    
-    return s;
-}
-    
-    
--- a/CommandPacket.h	Thu Jun 16 03:52:01 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-#ifndef COMMAND_PACKET_H_
-#define COMMAND_PACKET_H_
-
-#include "stdint.h"
-
-// command packet consists of following parts
-// u4 sflag
-// u8 command
-// u8 length
-// u8 payload[len]
-// u8 checksum
-// u4 eflag
-
-uint8_t generate_checksum(uint8_t *payload, uint8_t length, uint8_t offset=0);
-uint8_t hexchar_to_uint8(uint8_t ch);
-uint8_t uint8_to_hexchar(uint8_t data);
-
-static const char *errorString[16] = 
-    {
-        "No Error",
-        "Invalid start flag",
-        "Invalid end flag",
-        "Invalid command",
-        "Invalid checksum"
-    };
-    
-static char errorCode[16] = { 0 };
-
-
-class CommandPacket
-{
-public:
-    typedef enum
-    {
-        CP_SFLAG = '<',
-        CP_EFLAG = '>'
-    } CPFlag_t; 
-    
-    typedef enum
-    {
-        NONE = 0,
-        SFLAG,
-        COMMAND_H,
-        COMMAND_L,
-        LENGTH_H,
-        LENGTH_L,
-        PAYLOAD_H,
-        PAYLOAD_L,
-        CHECKSUM_H,
-        CHECKSUM_L,
-        EFLAG
-    } State_t;
-    
-    typedef enum
-    {
-        NO_ERROR = 0,
-        INVALID_SFLAG_ERROR,
-        INVALID_EFLAG_ERROR,
-        INVALID_CMD_ERROR,
-        INVALID_CS_ERROR,
-        INVALID_EXEC_ERROR
-    } Error_t;
-
-public:
-    Error_t errno;
-    
-public:
-    uint8_t sflag;
-    uint8_t command;
-    uint8_t length;
-    uint8_t payload[256 + 1]; // payload include terminator
-    uint8_t checksum;
-    uint8_t eflag;
-    
-public:
-    CommandPacket();
-    ~CommandPacket() {};
-    
-    bool verify();
-    const char *getErrorString() const;
-    int serialize(uint8_t *output);
-    uint8_t generate_checksum();
-};
-
-
-    
-
-#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RingBuffer.lib	Sun Jun 19 01:39:39 2016 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/ENEL400/code/RingBuffer/#36b372831d9e
--- a/SerialInterfaceProtocol.cpp	Thu Jun 16 03:52:01 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,281 +0,0 @@
-#include "SerialInterfaceProtocol.h"
-
-// #define DEBUG_MESSAGE
-
-SerialInterfaceProtocol::SerialInterfaceProtocol(SerialBuffer_t *in, SerialBuffer_t *out)
-{
-    // assign input and output buffers
-    SerialInputBuffer = in;
-    SerialOutputBuffer = out;
-    
-    // init command vector table
-    for (int i = 0; i < SIP_CMD_VECTOR_TABLE_SZ; i++)
-    {
-        CommandVectorTable[i] = NULL;
-    }
-    
-    // init internal state machine
-    state = CommandPacket::NONE;
-    
-    // init internal state
-    isChecksumEnabled = true;
-}
-
-SerialInterfaceProtocol::~SerialInterfaceProtocol()
-{
-    
-}
-
-void SerialInterfaceProtocol::registerCommand(uint8_t command, callback_func f)
-{
-    CommandVectorTable[command] = f;
-}
-
-void SerialInterfaceProtocol::deRegisterCommand(uint8_t command)
-{
-    CommandVectorTable[command] = NULL;
-}
-
-int SerialInterfaceProtocol::execute(uint8_t *response, uint8_t *response_length)
-{
-    
-    // execute the command if it's already been registered
-    if (CommandVectorTable[PacketBuffer.command] != NULL)
-    {       
-        return CommandVectorTable[PacketBuffer.command](
-            PacketBuffer.payload, 
-            PacketBuffer.length,
-            response, 
-            response_length
-        );
-    }
-    
-    printf("Callback function not registered\r\n");
-    
-    return -1;
-}
-
-int SerialInterfaceProtocol::assemble(uint8_t *response, uint8_t response_length)
-{
-    // prepare for packet buffer
-    PacketBuffer.sflag = CommandPacket::CP_SFLAG;
-    
-    PacketBuffer.command = 0xE0 | ((uint8_t) PacketBuffer.errno & 0x0f);
-    
-    PacketBuffer.length = response_length;
-    
-    memcpy(PacketBuffer.payload, response, response_length);
-    
-    PacketBuffer.checksum = PacketBuffer.generate_checksum();
-    
-    PacketBuffer.eflag = CommandPacket::CP_EFLAG;
-
-    
-    // serialize the packet
-    int total_len = PacketBuffer.length * 2 + 8;
-    uint8_t buffer[total_len];
-    memset(buffer, 0x0, total_len);
-    
-    PacketBuffer.serialize(buffer);
-    
-    // add to ring buffer
-    for (int i = 0; i < total_len; i++)
-    {
-        SerialOutputBuffer->enqueue(buffer[i]);
-    }
-    
-    return 0;
-    
-}
-
-void SerialInterfaceProtocol::poll()
-{
-    static uint8_t payload_counter = 0;
-    uint8_t response[SIP_MAX_RESP_LEN];
-    uint8_t response_length;
-    
-    // fetch data from ring buffer
-    while (SerialInputBuffer->getCounter() > 0)
-    {
-        uint8_t ch;
-        ch = SerialInputBuffer->dequeue();
-        
-        // reset state to keep sync
-        if (ch == CommandPacket::CP_SFLAG)
-        {
-            state = CommandPacket::SFLAG;
-            
-            // reset variable
-            payload_counter = 0;
-            memset(PacketBuffer.payload, 0x0, sizeof(PacketBuffer.payload));
-            PacketBuffer.errno = CommandPacket::NO_ERROR;
-        }
-        
-        switch (state)
-        {
-            case CommandPacket::SFLAG:
-                PacketBuffer.sflag = ch;
-                state = CommandPacket::COMMAND_H;
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::SFLAG: 0x%x\r\n", PacketBuffer.sflag);
-#endif
-                break;
-                
-            case CommandPacket::COMMAND_H:
-                PacketBuffer.command = hexchar_to_uint8(ch) << 4;
-                state = CommandPacket::COMMAND_L;
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::COMMAND_H: 0x%x\r\n", PacketBuffer.command);
-#endif
-                break;
-                
-            case CommandPacket::COMMAND_L:
-                PacketBuffer.command |= (hexchar_to_uint8(ch) & 0x0f);
-                state = CommandPacket::LENGTH_H;
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::COMMAND_L: 0x%x\r\n", PacketBuffer.command);
-#endif
-                break;
-                
-            case CommandPacket::LENGTH_H:
-                PacketBuffer.length = hexchar_to_uint8(ch) << 4;
-                state = CommandPacket::LENGTH_L;
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::LENGTH_H: 0x%x\r\n", PacketBuffer.length);
-#endif
-                break;
-                
-            case CommandPacket::LENGTH_L:
-                PacketBuffer.length |= (hexchar_to_uint8(ch) & 0x0f);
-                if (PacketBuffer.length != 0) // if the length is not zero, then proceed to payload state
-                {
-                    state = CommandPacket::PAYLOAD_H;
-                }
-                else // otherwise proceed to checksum state
-                {
-                    state = CommandPacket::CHECKSUM_H;
-                }
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::LENGTH_L: 0x%x\r\n", PacketBuffer.length);
-#endif
-                break;
-            
-            case CommandPacket::PAYLOAD_H:
-                PacketBuffer.payload[payload_counter] = hexchar_to_uint8(ch) << 4; // store higher 4 bits of payload
-                state = CommandPacket::PAYLOAD_L;
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::PAYLOAD_H: 0x%x\r\n", PacketBuffer.payload[payload_counter]);
-#endif
-                break;
-                
-            case CommandPacket::PAYLOAD_L:
-                PacketBuffer.payload[payload_counter++] |= (hexchar_to_uint8(ch) & 0x0f); // store lower 4 bits of payload
-                if (payload_counter < PacketBuffer.length) // append ch to payload until reach the length
-                {
-                    state = CommandPacket::PAYLOAD_H;
-                }
-                else
-                {
-                    state = CommandPacket::CHECKSUM_H;
-                }
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::PAYLOAD_L: 0x%x\r\n", PacketBuffer.payload[payload_counter - 1]);
-#endif
-                break;
-                
-            case CommandPacket::CHECKSUM_H:
-                PacketBuffer.checksum = hexchar_to_uint8(ch) << 4;
-                state = CommandPacket::CHECKSUM_L;
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::CHECKSUM_H: 0x%x\r\n", PacketBuffer.checksum);
-#endif
-                break;
-                
-            case CommandPacket::CHECKSUM_L:
-                PacketBuffer.checksum |= (hexchar_to_uint8(ch) & 0x0f);
-                
-                // checksum can be turned off
-                if (isChecksumEnabled)
-                {
-                    if (PacketBuffer.verify()) // checksum match
-                    {
-                        state = CommandPacket::EFLAG;
-                    }
-                    else // checksum mismatch
-                    {
-                        PacketBuffer.errno = CommandPacket::INVALID_CS_ERROR;
-                        
-                        // prepare for checksum error response
-                        PacketBuffer.errno = CommandPacket::INVALID_CS_ERROR;
-                        assemble(response, response_length);
-                        
-                        state = CommandPacket::NONE;
-                    }
-                }
-                else
-                {
-                    state = CommandPacket::EFLAG;
-                }
-                
-                
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::CHECKSUM_L: 0x%x\r\n", PacketBuffer.checksum);
-#endif
-                break;
-                
-            case CommandPacket::EFLAG:
-                if (ch == CommandPacket::CP_EFLAG)
-                {
-                    PacketBuffer.eflag = ch;
-                    
-                    // clear response and response length
-                    response_length = 0;
-                    memset(response, 0x0, sizeof(response));
-                    
-                    // execute command
-                    int ret = execute(response, &response_length);
-                    
-                    if (ret < 0) // command not registered
-                    {
-                        PacketBuffer.errno = CommandPacket::INVALID_CMD_ERROR;
-                    }
-                    else if (ret != 0) // error to execute
-                    {
-                        PacketBuffer.errno = CommandPacket::INVALID_EXEC_ERROR;
-                    }
-                    
-                    assemble(response, response_length);
-                }
-                state = CommandPacket::NONE;
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::EFLAG: 0x%x\r\n", PacketBuffer.eflag);
-#endif
-                break;
-                
-            case CommandPacket::NONE:
-                PacketBuffer.errno = CommandPacket::INVALID_SFLAG_ERROR;
-                
-                // TODO:: Execute error generator
-                PacketBuffer.errno = CommandPacket::INVALID_SFLAG_ERROR;
-                assemble(response, response_length);
-                
-#ifdef DEBUG_MESSAGE
-                printf("CommandPacket::NONE\r\n");
-#endif
-                break;
-                
-            default:
-                break;
-        }
-    }
-}
-
-void SerialInterfaceProtocol::disableChecksum()
-{
-    isChecksumEnabled = false;
-}
-
-void SerialInterfaceProtocol::enableChecksum()
-{
-    isChecksumEnabled = true;
-}
\ No newline at end of file
--- a/SerialInterfaceProtocol.h	Thu Jun 16 03:52:01 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-// SerialInterfaceProtocol (SIP) is a protocol which help to exchange
-// information between host and slave devices
-#ifndef SERIALINTERFACEPROTOCOL_H_
-#define SERIALINTERFACEPROTOCOL_H_
-
-#include "mbed.h"
-#include "stdint.h"
-#include "CommandPacket.h"
-#include "buffer.h"
-
-#define SIP_CMD_VECTOR_TABLE_SZ 256
-#define SIP_MAX_RESP_LEN 256
-#define SIP_MAX_PAYLOAD_LEN 256
-
-typedef int (*callback_func)(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length); 
-typedef CircularBuffer<uint8_t> SerialBuffer_t;
-
-class SerialInterfaceProtocol
-{
-public:
-    // namespace
-    
-protected:
-    // internal variable
-    callback_func CommandVectorTable[SIP_CMD_VECTOR_TABLE_SZ];
-    
-    // buffered interface
-    SerialBuffer_t *SerialInputBuffer;
-    SerialBuffer_t *SerialOutputBuffer;
-    CommandPacket PacketBuffer;
-    
-    // state machine
-    CommandPacket::State_t state;
-    
-    // internal state
-    bool isChecksumEnabled;
-    
-protected:
-    // internal methods
-    int execute(uint8_t *response, uint8_t *response_length);
-    
-    int assemble(uint8_t *response, uint8_t response_length);
-    
-    
-public:
-    // public methods
-    
-    // constructor
-    SerialInterfaceProtocol(SerialBuffer_t *in, SerialBuffer_t *out);
-    ~SerialInterfaceProtocol();
-    
-    // member function
-    void poll();
-    void registerCommand(uint8_t command, callback_func f);
-    void deRegisterCommand(uint8_t command);
-    
-    void disableChecksum();
-    void enableChecksum();
-    
-};
-        
-        
-        
-        
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialInterfaceProtocol.lib	Sun Jun 19 01:39:39 2016 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/ENEL400/code/SerialInterfaceProtocol/#21e4e3afa5e6
--- a/buffer.cpp	Thu Jun 16 03:52:01 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-#include "buffer.h"
-
-template <typename T>
-CircularBuffer<T>::CircularBuffer(const uint32_t size)
-    :buffer_size(size)
-{
-    read_ptr = 0;
-    write_ptr = 0;
-    count = 0;
-    
-    // mutex lock
-    mux = false; 
-    
-    // overflow
-    is_over_flow = false;
-    
-    // container
-    data = new T[buffer_size];
-}
-
-template <typename T>
-CircularBuffer<T>::~CircularBuffer()
-{
-    delete[] data;
-}
-
-template <typename T>
-bool CircularBuffer<T>::isLocked()
-{
-    return mux;
-}
-
-template <typename T>
-void CircularBuffer<T>::lock()
-{
-    mux = true;
-}
-
-template <typename T>
-void CircularBuffer<T>::unlock()
-{
-    mux = false;
-}
-
-template <typename T>
-void CircularBuffer<T>::enqueue(T in)
-{
-    data[write_ptr++] = in;
-    write_ptr %= buffer_size;
-    
-    count++;
-}
-
-template <typename T>
-T CircularBuffer<T>::dequeue()
-{
-    T temp = data[read_ptr++];
-    read_ptr %= buffer_size;
-    
-    count--;
-    return temp;   
-}
-
-template <typename T>
-uint32_t CircularBuffer<T>::getReadPtr()
-{
-    return read_ptr;
-}
-
-template <typename T>
-uint32_t CircularBuffer<T>::getWritePtr()
-{
-    return write_ptr;
-}
-
-template <typename T>
-uint32_t CircularBuffer<T>::getCounter()
-{
-    return count;
-}
-
-template <typename T>
-bool CircularBuffer<T>::getOverFlow()
-{
-    return is_over_flow;
-}
-
-template <typename T>
-void CircularBuffer<T>::clearOverFlow()
-{
-    is_over_flow = false;  
-}
-
-template <typename T>
-T CircularBuffer<T>::first()
-{
-    if (read_ptr > 0)
-    {
-        return data[read_ptr - 1];   
-    }
-    else
-    {
-        return data[read_ptr];
-    }
-}
-
-template <typename T>
-T CircularBuffer<T>::last()
-{
-    if (write_ptr > 0)
-    {
-        return data[write_ptr - 1];   
-    }
-    else
-    {
-        return data[write_ptr];
-    }
-}
-
-template <typename T>
-T CircularBuffer<T>::operator[](uint32_t idx)
-{
-    return data[idx];
-}
-
-// force compiler to create code for template
-template class CircularBuffer<int>;
-template class CircularBuffer<uint8_t>;
-template class CircularBuffer<uint16_t>;
-template class CircularBuffer<uint32_t>;
\ No newline at end of file
--- a/buffer.h	Thu Jun 16 03:52:01 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-#ifndef BUFFER_H_
-#define BUFFER_H_
-
-#define DEFAULT_MAX_BUFFER_SZ 64
-
-#include "stdint.h"
-
-template <typename T>
-class CircularBuffer
-{
-private:
-    const uint32_t buffer_size;
-    uint32_t read_ptr;
-    uint32_t write_ptr;
-    uint32_t count;
-    
-    // mutex lock
-    bool mux; 
-    
-    // overflow
-    bool is_over_flow;
-    
-    // container
-    T *data;
-    
-    
-public:
-    CircularBuffer(const uint32_t size=DEFAULT_MAX_BUFFER_SZ);
-    ~CircularBuffer();
-    
-    // psudo mutex
-    bool isLocked();
-    void lock();
-    void unlock();
-    
-    // enqueue and dequeue
-    void enqueue(T in);
-    T dequeue();
-    
-    // pointer operation
-    uint32_t getReadPtr();
-    uint32_t getWritePtr();
-    uint32_t getCounter();
-    
-    // overflow
-    bool getOverFlow();
-    void clearOverFlow();
-    
-    // operation
-    T first();
-    T last();
-    
-    // random access
-    T operator[](uint32_t idx);
-};
-
-#endif
\ No newline at end of file