simple serial protocol
Dependents: AwsomeStation LoRaBaseStation LoRaTerminal
Revision 11:390476907bfc, committed 2016-09-02
- Comitter:
- rba90
- Date:
- Fri Sep 02 02:39:04 2016 +0000
- Parent:
- 10:2a710d0bab2c
- Commit message:
- The CommandPacket is reconstructed.
Changed in this revision
diff -r 2a710d0bab2c -r 390476907bfc CommandPacket.cpp --- a/CommandPacket.cpp Thu Sep 01 04:15:40 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +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 = '>'; -} - -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; -} - -
diff -r 2a710d0bab2c -r 390476907bfc CommandPacket.h --- a/CommandPacket.h Thu Sep 01 04:15:40 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +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); - -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(); - int serialize(uint8_t *output); - uint8_t generate_checksum(); -}; - - - - -#endif
diff -r 2a710d0bab2c -r 390476907bfc CommandPacket2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CommandPacket2.cpp Fri Sep 02 02:39:04 2016 +0000 @@ -0,0 +1,175 @@ +#include "CommandPacket2.h" +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> + +CommandPacket2::CommandPacket2() +{ + // initialize payload + memset(_payload, 0x0, sizeof(_payload)); + + // reset is verified state + _isVerified = false; +} + +CommandPacket2::~CommandPacket2() +{ + +} + +void CommandPacket2::setSFlag(uint8_t sflag) +{ + _sflag = sflag; + _isVerified = false; +} + +void CommandPacket2::setCommand(uint8_t command) +{ + _command = command; + _isVerified = false; +} + +void CommandPacket2::setLength(uint8_t length) +{ + _length = length; + _isVerified = false; +} + +void CommandPacket2::setPayload(uint8_t idx, uint8_t payload) +{ + _payload[idx] = payload; + _isVerified = false; +} + +void CommandPacket2::setChecksum(uint8_t checksum) +{ + _checksum = checksum; + _isVerified = false; +} + +void CommandPacket2::setEFlag(uint8_t eflag) +{ + _eflag = eflag; + _isVerified = false; +} + +uint8_t CommandPacket2::getSFlag() +{ + return _sflag; +} + +uint8_t CommandPacket2::getCommand() +{ + return _command; +} + +uint8_t CommandPacket2::getLength() +{ + return _length; +} + +uint8_t CommandPacket2::getPayload(uint8_t idx) +{ + return _payload[idx]; +} + +uint8_t CommandPacket2::getEFlag() +{ + return _eflag; +} + +uint8_t CommandPacket2::getChecksum() +{ + return _checksum; +} + +bool CommandPacket2::verify() +{ + if (_isVerified) + { + return true; + } + else + { + return _checksum == calculate_checksum(); + } +} + +uint8_t CommandPacket2::calculate_checksum() +{ + // take the sum of all user defined data bytes preceding checksum field + uint8_t s = 0; + + // add command + s += _command; + + // add length + s += _length; + + // add payload + for (uint8_t i = 0; i < _length; i++) + { + s += _payload[i]; + } + + // calculate two's complement of the remainder + s = 0xff - s + 1; + + return s; +} + +void CommandPacket2::generateChecksum() +{ + _checksum = calculate_checksum(); + + _isVerified = true; +} + +int CommandPacket2::serialize(uint8_t *buffer) +{ + // the user need to make sure that they have enough space for buffer + if (!buffer) return 0; + + char octet[3]; + int offset = 0; + + // cast content to output buffer + // sflag + buffer[offset] = _sflag; + offset += 1; + + // command + memset(octet, 0x0, sizeof(octet)); + sprintf(octet, "%02X", _command); + memcpy(buffer + offset, octet, 2); + offset += 2; + + // length + memset(octet, 0x0, sizeof(octet)); + sprintf(octet, "%02X", _length); + memcpy(buffer + offset, octet, 2); + offset += 2; + + // payload + for (uint8_t i = 0; i < _length; i++) + { + memset(octet, 0x0, sizeof(octet)); + sprintf(octet, "%02X", _payload[i]); + memcpy(buffer + offset, octet, 2); + offset += 2; + } + + // checksum + memset(octet, 0x0, sizeof(octet)); + sprintf(octet, "%02X", _checksum); + memcpy(buffer + offset, octet, 2); + offset += 2; + + // eflag + buffer[offset] = _eflag; + offset += 1; + + return offset; +} + \ No newline at end of file
diff -r 2a710d0bab2c -r 390476907bfc CommandPacket2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CommandPacket2.h Fri Sep 02 02:39:04 2016 +0000 @@ -0,0 +1,67 @@ +// command packet consists of following parts +// u4 sflag +// u8 command +// u8 length +// u8 payload[len] +// u8 checksum +// u4 eflag + + +#ifndef COMMAND_PACKET2_H_ +#define COMMAND_PACKET2_H_ + +#include <stdint.h> + +class CommandPacket2 +{ +// public types +public: + typedef enum + { + CP_SFLAG = '<', + CP_EFLAG = '>' + } CPFlag_t; + +// private properties +private: + uint8_t _sflag; + uint8_t _command; + uint8_t _length; + uint8_t _payload[256]; + uint8_t _checksum; + uint8_t _eflag; + + bool _isVerified; + +// private methods +private: + uint8_t calculate_checksum(); + +// public methods +public: + CommandPacket2(); + ~CommandPacket2(); + + void setSFlag(uint8_t sflag=CP_SFLAG); + void setCommand(uint8_t command); + void setLength(uint8_t length); + void setPayload(uint8_t idx, uint8_t payload); + void setChecksum(uint8_t checksum); + void setEFlag(uint8_t eflag=CP_EFLAG); + + uint8_t getSFlag(); + uint8_t getCommand(); + uint8_t getLength(); + uint8_t getPayload(uint8_t idx); + uint8_t getEFlag(); + uint8_t getChecksum(); + + + + bool verify(); + void generateChecksum(); + int serialize(uint8_t *buffer); + +}; + +#endif \ No newline at end of file
diff -r 2a710d0bab2c -r 390476907bfc SerialInterfaceProtocol.cpp --- a/SerialInterfaceProtocol.cpp Thu Sep 01 04:15:40 2016 +0000 +++ b/SerialInterfaceProtocol.cpp Fri Sep 02 02:39:04 2016 +0000 @@ -1,5 +1,6 @@ +#include "mbed.h" #include "SerialInterfaceProtocol.h" -#include "mbed.h" +#include "CommandPacket2.h" SerialInterfaceProtocol::SerialInterfaceProtocol(SerialBuffer_t *in, SerialBuffer_t *out) { @@ -14,7 +15,7 @@ } // init internal state machine - state = CommandPacket::NONE; + state = NONE; // init internal state isChecksumEnabled = false; @@ -37,13 +38,25 @@ int SerialInterfaceProtocol::execute(uint8_t *response, uint8_t *response_length) { + // read command from packet buffer + uint8_t command = PacketBuffer.getCommand(); // execute the command if it's already been registered - if (CommandVectorTable[PacketBuffer.command] != NULL) - { - return CommandVectorTable[PacketBuffer.command]( - PacketBuffer.payload, - PacketBuffer.length, + if (CommandVectorTable[command] != NULL) + { + // extract length and payload from packet buffer + uint8_t length = PacketBuffer.getLength(); + uint8_t payload[length]; + memset(payload, 0x0, length); + + for (uint8_t i = 0; i < length; i++) + { + payload[i] = PacketBuffer.getPayload(i); + } + + return CommandVectorTable[command]( + payload, + length, response, response_length ); @@ -58,7 +71,7 @@ if (response_length != 0) { respond( - 0xD0 | ((uint8_t) PacketBuffer.errno & 0x0F), + 0xD0 | ((uint8_t) errno & 0x0F), response, response_length ); @@ -66,7 +79,7 @@ else { respond( - 0xE0 | ((uint8_t) PacketBuffer.errno & 0x0F), + 0xE0 | ((uint8_t) errno & 0x0F), response, response_length ); @@ -77,30 +90,36 @@ int SerialInterfaceProtocol::respond(uint8_t command, uint8_t *response, uint8_t response_length) { - // prepare for packet buffer - PacketBuffer.sflag = CommandPacket::CP_SFLAG; + // create a new packet buffer + CommandPacket2 responsePacket; + + // set sflag + responsePacket.setSFlag(); // use default sflag // return flag as specified by the user - PacketBuffer.command = command; + responsePacket.setCommand(command); // copy buffer length - PacketBuffer.length = response_length; + responsePacket.setLength(response_length); // copy buffer to payload - memcpy(PacketBuffer.payload, response, response_length); + for (uint8_t i = 0; i < response_length; i++) + { + responsePacket.setPayload(i, response[i]); + } // generate checksum - PacketBuffer.checksum = PacketBuffer.generate_checksum(); + responsePacket.generateChecksum(); // end flag - PacketBuffer.eflag = CommandPacket::CP_EFLAG; + responsePacket.setEFlag(); // serialize the packet - int total_len = PacketBuffer.length * 2 + 8; + int total_len = response_length * 2 + 8; uint8_t buffer[total_len]; memset(buffer, 0x0, total_len); - PacketBuffer.serialize(buffer); + responsePacket.serialize(buffer); #ifdef DEBUG_SIP printf("SIP::respond:total: %d chars\r\n", total_len); @@ -122,6 +141,13 @@ void SerialInterfaceProtocol::poll() { static uint8_t payload_counter = 0; + + // temp variable for building full byte from hex strings + static uint8_t command = 0; + static uint8_t length = 0; + static uint8_t payload = 0; + static uint8_t checksum = 0; + uint8_t response[SIP_MAX_RESP_LEN]; uint8_t response_length; @@ -132,105 +158,119 @@ ch = SerialInputBuffer->dequeue(); // reset state to keep sync - if (ch == CommandPacket::CP_SFLAG) + if (ch == CommandPacket2::CP_SFLAG) { - state = CommandPacket::SFLAG; + state = SFLAG; // reset variable payload_counter = 0; - memset(PacketBuffer.payload, 0x0, sizeof(PacketBuffer.payload)); - PacketBuffer.errno = CommandPacket::NO_ERROR; + errno = NO_ERROR; } switch (state) { - case CommandPacket::SFLAG: - PacketBuffer.sflag = ch; - state = CommandPacket::COMMAND_H; + case SFLAG: + PacketBuffer.setSFlag(ch); + state = COMMAND_H; #ifdef DEBUG_SIP - printf("CommandPacket::SFLAG: 0x%x\r\n", PacketBuffer.sflag); + printf("SIP::SFLAG: 0x%x\r\n", PacketBuffer.getSFlag()); #endif break; - case CommandPacket::COMMAND_H: - PacketBuffer.command = hexchar_to_uint8(ch) << 4; - state = CommandPacket::COMMAND_L; + case COMMAND_H: + command = hexchar_to_uint8(ch) << 4; + state = COMMAND_L; #ifdef DEBUG_SIP - printf("CommandPacket::COMMAND_H: 0x%x\r\n", PacketBuffer.command); + printf("SIP::COMMAND_H: 0x%x\r\n", command); #endif break; - case CommandPacket::COMMAND_L: - PacketBuffer.command |= (hexchar_to_uint8(ch) & 0x0f); - state = CommandPacket::LENGTH_H; + case COMMAND_L: + command |= (hexchar_to_uint8(ch) & 0x0f); + + // store command + PacketBuffer.setCommand(command); + + state = LENGTH_H; #ifdef DEBUG_SIP - printf("CommandPacket::COMMAND_L: 0x%x\r\n", PacketBuffer.command); + printf("SIP::COMMAND_L: 0x%x\r\n", command); #endif break; - case CommandPacket::LENGTH_H: - PacketBuffer.length = hexchar_to_uint8(ch) << 4; - state = CommandPacket::LENGTH_L; + case LENGTH_H: + length = hexchar_to_uint8(ch) << 4; + state = LENGTH_L; #ifdef DEBUG_SIP - printf("CommandPacket::LENGTH_H: 0x%x\r\n", PacketBuffer.length); + printf("SIP::LENGTH_H: 0x%x\r\n", 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 + case LENGTH_L: + length |= (hexchar_to_uint8(ch) & 0x0f); + + // store length + PacketBuffer.setLength(length); + + if (length != 0) // if the length is not zero, then proceed to payload state { - state = CommandPacket::PAYLOAD_H; + state = PAYLOAD_H; } else // otherwise proceed to checksum state { - state = CommandPacket::CHECKSUM_H; + state = CHECKSUM_H; } #ifdef DEBUG_SIP - printf("CommandPacket::LENGTH_L: 0x%x\r\n", PacketBuffer.length); + printf("SIP::LENGTH_L: 0x%x\r\n", 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; + case PAYLOAD_H: + payload = hexchar_to_uint8(ch) << 4; // store higher 4 bits of payload + state = PAYLOAD_L; #ifdef DEBUG_SIP - printf("CommandPacket::PAYLOAD_H: 0x%x\r\n", PacketBuffer.payload[payload_counter]); + printf("SIP::PAYLOAD_H: 0x%x\r\n", payload); #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 + case PAYLOAD_L: + payload |= (hexchar_to_uint8(ch) & 0x0f); // store lower 4 bits of payload + + // store payload + PacketBuffer.setPayload(payload_counter++, payload); + + if (payload_counter < PacketBuffer.getLength()) // append ch to payload until reach the length { - state = CommandPacket::PAYLOAD_H; + state = PAYLOAD_H; } else { - state = CommandPacket::CHECKSUM_H; + state = CHECKSUM_H; } #ifdef DEBUG_SIP - printf("CommandPacket::PAYLOAD_L: 0x%x\r\n", PacketBuffer.payload[payload_counter - 1]); + printf("SIP::PAYLOAD_L: 0x%x\r\n", payload); #endif break; - case CommandPacket::CHECKSUM_H: - PacketBuffer.checksum = hexchar_to_uint8(ch) << 4; - state = CommandPacket::CHECKSUM_L; + case CHECKSUM_H: + checksum = hexchar_to_uint8(ch) << 4; + state = CHECKSUM_L; #ifdef DEBUG_SIP - printf("CommandPacket::CHECKSUM_H: 0x%x\r\n", PacketBuffer.checksum); + printf("SIP::CHECKSUM_H: 0x%x\r\n", checksum); #endif break; - case CommandPacket::CHECKSUM_L: - PacketBuffer.checksum |= (hexchar_to_uint8(ch) & 0x0f); + case CHECKSUM_L: + checksum |= (hexchar_to_uint8(ch) & 0x0f); + + // store checksum + PacketBuffer.setChecksum(checksum); // checksum can be turned off if (isChecksumEnabled) { if (PacketBuffer.verify()) // checksum match { - state = CommandPacket::EFLAG; + state = EFLAG; } else // checksum mismatch { @@ -239,27 +279,27 @@ memset(response, 0x0, sizeof(response)); // prepare for checksum error response - PacketBuffer.errno = CommandPacket::INVALID_CS_ERROR; + errno = INVALID_CS_ERROR; assemble(response, response_length); - state = CommandPacket::NONE; + state = NONE; } } else { - state = CommandPacket::EFLAG; + state = EFLAG; } #ifdef DEBUG_SIP - printf("CommandPacket::CHECKSUM_L: 0x%x\r\n", PacketBuffer.checksum); + printf("SIP::CHECKSUM_L: 0x%x\r\n", checksum); #endif break; - case CommandPacket::EFLAG: - if (ch == CommandPacket::CP_EFLAG) + case EFLAG: + if (ch == CommandPacket2::CP_EFLAG) { - PacketBuffer.eflag = ch; + PacketBuffer.setEFlag(ch); // clear response and response length response_length = 0; @@ -270,36 +310,36 @@ if (ret < 0) // command not registered { - PacketBuffer.errno = CommandPacket::INVALID_CMD_ERROR; + errno = INVALID_CMD_ERROR; } else if (ret != 0) // error to execute { - PacketBuffer.errno = CommandPacket::INVALID_EXEC_ERROR; + errno = INVALID_EXEC_ERROR; } else { - PacketBuffer.errno = CommandPacket::NO_ERROR; + errno = NO_ERROR; } assemble(response, response_length); } - state = CommandPacket::NONE; + state = NONE; #ifdef DEBUG_SIP - printf("CommandPacket::EFLAG: 0x%x\r\n", PacketBuffer.eflag); + printf("SIP::EFLAG: 0x%x\r\n", PacketBuffer.getEFlag()); #endif break; - case CommandPacket::NONE: + case NONE: // clear response and response length response_length = 0; memset(response, 0x0, sizeof(response)); // Execute error generator - PacketBuffer.errno = CommandPacket::INVALID_SFLAG_ERROR; + errno = INVALID_SFLAG_ERROR; assemble(response, response_length); #ifdef DEBUG_SIP - printf("CommandPacket::NONE\r\n"); + printf("SIP::NONE\r\n"); #endif break; @@ -317,4 +357,26 @@ void SerialInterfaceProtocol::enableChecksum() { isChecksumEnabled = true; -} \ No newline at end of file +} + +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; +}
diff -r 2a710d0bab2c -r 390476907bfc SerialInterfaceProtocol.h --- a/SerialInterfaceProtocol.h Thu Sep 01 04:15:40 2016 +0000 +++ b/SerialInterfaceProtocol.h Fri Sep 02 02:39:04 2016 +0000 @@ -5,8 +5,8 @@ #include "mbed.h" #include "stdint.h" -#include "CommandPacket.h" #include "RingBuffer.h" +#include "CommandPacket2.h" #define SIP_CMD_VECTOR_TABLE_SZ 256 #define SIP_MAX_RESP_LEN 256 @@ -15,10 +15,36 @@ typedef int (*callback_func)(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length); typedef CircularBuffer<uint8_t> SerialBuffer_t; +uint8_t hexchar_to_uint8(uint8_t ch); + class SerialInterfaceProtocol { public: // namespace + 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; protected: // internal variable @@ -27,10 +53,15 @@ // buffered interface SerialBuffer_t *SerialInputBuffer; SerialBuffer_t *SerialOutputBuffer; - CommandPacket PacketBuffer; + + // internal packet buffer (the SIP could issue one command at a time) + CommandPacket2 PacketBuffer; // state machine - CommandPacket::State_t state; + State_t state; + + // error code + Error_t errno; // internal state bool isChecksumEnabled;