simple serial protocol

Dependents:   AwsomeStation LoRaBaseStation LoRaTerminal

Committer:
rba90
Date:
Sun Jun 19 01:37:43 2016 +0000
Revision:
0:21e4e3afa5e6
Child:
1:03208c983c8b
Init

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rba90 0:21e4e3afa5e6 1 #include "SerialInterfaceProtocol.h"
rba90 0:21e4e3afa5e6 2
rba90 0:21e4e3afa5e6 3 // #define DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 4
rba90 0:21e4e3afa5e6 5 SerialInterfaceProtocol::SerialInterfaceProtocol(SerialBuffer_t *in, SerialBuffer_t *out)
rba90 0:21e4e3afa5e6 6 {
rba90 0:21e4e3afa5e6 7 // assign input and output buffers
rba90 0:21e4e3afa5e6 8 SerialInputBuffer = in;
rba90 0:21e4e3afa5e6 9 SerialOutputBuffer = out;
rba90 0:21e4e3afa5e6 10
rba90 0:21e4e3afa5e6 11 // init command vector table
rba90 0:21e4e3afa5e6 12 for (int i = 0; i < SIP_CMD_VECTOR_TABLE_SZ; i++)
rba90 0:21e4e3afa5e6 13 {
rba90 0:21e4e3afa5e6 14 CommandVectorTable[i] = NULL;
rba90 0:21e4e3afa5e6 15 }
rba90 0:21e4e3afa5e6 16
rba90 0:21e4e3afa5e6 17 // init internal state machine
rba90 0:21e4e3afa5e6 18 state = CommandPacket::NONE;
rba90 0:21e4e3afa5e6 19
rba90 0:21e4e3afa5e6 20 // init internal state
rba90 0:21e4e3afa5e6 21 isChecksumEnabled = true;
rba90 0:21e4e3afa5e6 22 }
rba90 0:21e4e3afa5e6 23
rba90 0:21e4e3afa5e6 24 SerialInterfaceProtocol::~SerialInterfaceProtocol()
rba90 0:21e4e3afa5e6 25 {
rba90 0:21e4e3afa5e6 26
rba90 0:21e4e3afa5e6 27 }
rba90 0:21e4e3afa5e6 28
rba90 0:21e4e3afa5e6 29 void SerialInterfaceProtocol::registerCommand(uint8_t command, callback_func f)
rba90 0:21e4e3afa5e6 30 {
rba90 0:21e4e3afa5e6 31 CommandVectorTable[command] = f;
rba90 0:21e4e3afa5e6 32 }
rba90 0:21e4e3afa5e6 33
rba90 0:21e4e3afa5e6 34 void SerialInterfaceProtocol::deRegisterCommand(uint8_t command)
rba90 0:21e4e3afa5e6 35 {
rba90 0:21e4e3afa5e6 36 CommandVectorTable[command] = NULL;
rba90 0:21e4e3afa5e6 37 }
rba90 0:21e4e3afa5e6 38
rba90 0:21e4e3afa5e6 39 int SerialInterfaceProtocol::execute(uint8_t *response, uint8_t *response_length)
rba90 0:21e4e3afa5e6 40 {
rba90 0:21e4e3afa5e6 41
rba90 0:21e4e3afa5e6 42 // execute the command if it's already been registered
rba90 0:21e4e3afa5e6 43 if (CommandVectorTable[PacketBuffer.command] != NULL)
rba90 0:21e4e3afa5e6 44 {
rba90 0:21e4e3afa5e6 45 return CommandVectorTable[PacketBuffer.command](
rba90 0:21e4e3afa5e6 46 PacketBuffer.payload,
rba90 0:21e4e3afa5e6 47 PacketBuffer.length,
rba90 0:21e4e3afa5e6 48 response,
rba90 0:21e4e3afa5e6 49 response_length
rba90 0:21e4e3afa5e6 50 );
rba90 0:21e4e3afa5e6 51 }
rba90 0:21e4e3afa5e6 52
rba90 0:21e4e3afa5e6 53 printf("Callback function not registered\r\n");
rba90 0:21e4e3afa5e6 54
rba90 0:21e4e3afa5e6 55 return -1;
rba90 0:21e4e3afa5e6 56 }
rba90 0:21e4e3afa5e6 57
rba90 0:21e4e3afa5e6 58 int SerialInterfaceProtocol::assemble(uint8_t *response, uint8_t response_length)
rba90 0:21e4e3afa5e6 59 {
rba90 0:21e4e3afa5e6 60 // prepare for packet buffer
rba90 0:21e4e3afa5e6 61 PacketBuffer.sflag = CommandPacket::CP_SFLAG;
rba90 0:21e4e3afa5e6 62
rba90 0:21e4e3afa5e6 63 PacketBuffer.command = 0xE0 | ((uint8_t) PacketBuffer.errno & 0x0f);
rba90 0:21e4e3afa5e6 64
rba90 0:21e4e3afa5e6 65 PacketBuffer.length = response_length;
rba90 0:21e4e3afa5e6 66
rba90 0:21e4e3afa5e6 67 memcpy(PacketBuffer.payload, response, response_length);
rba90 0:21e4e3afa5e6 68
rba90 0:21e4e3afa5e6 69 PacketBuffer.checksum = PacketBuffer.generate_checksum();
rba90 0:21e4e3afa5e6 70
rba90 0:21e4e3afa5e6 71 PacketBuffer.eflag = CommandPacket::CP_EFLAG;
rba90 0:21e4e3afa5e6 72
rba90 0:21e4e3afa5e6 73
rba90 0:21e4e3afa5e6 74 // serialize the packet
rba90 0:21e4e3afa5e6 75 int total_len = PacketBuffer.length * 2 + 8;
rba90 0:21e4e3afa5e6 76 uint8_t buffer[total_len];
rba90 0:21e4e3afa5e6 77 memset(buffer, 0x0, total_len);
rba90 0:21e4e3afa5e6 78
rba90 0:21e4e3afa5e6 79 PacketBuffer.serialize(buffer);
rba90 0:21e4e3afa5e6 80
rba90 0:21e4e3afa5e6 81 // add to ring buffer
rba90 0:21e4e3afa5e6 82 for (int i = 0; i < total_len; i++)
rba90 0:21e4e3afa5e6 83 {
rba90 0:21e4e3afa5e6 84 SerialOutputBuffer->enqueue(buffer[i]);
rba90 0:21e4e3afa5e6 85 }
rba90 0:21e4e3afa5e6 86
rba90 0:21e4e3afa5e6 87 return 0;
rba90 0:21e4e3afa5e6 88
rba90 0:21e4e3afa5e6 89 }
rba90 0:21e4e3afa5e6 90
rba90 0:21e4e3afa5e6 91 void SerialInterfaceProtocol::poll()
rba90 0:21e4e3afa5e6 92 {
rba90 0:21e4e3afa5e6 93 static uint8_t payload_counter = 0;
rba90 0:21e4e3afa5e6 94 uint8_t response[SIP_MAX_RESP_LEN];
rba90 0:21e4e3afa5e6 95 uint8_t response_length;
rba90 0:21e4e3afa5e6 96
rba90 0:21e4e3afa5e6 97 // fetch data from ring buffer
rba90 0:21e4e3afa5e6 98 while (SerialInputBuffer->getCounter() > 0)
rba90 0:21e4e3afa5e6 99 {
rba90 0:21e4e3afa5e6 100 uint8_t ch;
rba90 0:21e4e3afa5e6 101 ch = SerialInputBuffer->dequeue();
rba90 0:21e4e3afa5e6 102
rba90 0:21e4e3afa5e6 103 // reset state to keep sync
rba90 0:21e4e3afa5e6 104 if (ch == CommandPacket::CP_SFLAG)
rba90 0:21e4e3afa5e6 105 {
rba90 0:21e4e3afa5e6 106 state = CommandPacket::SFLAG;
rba90 0:21e4e3afa5e6 107
rba90 0:21e4e3afa5e6 108 // reset variable
rba90 0:21e4e3afa5e6 109 payload_counter = 0;
rba90 0:21e4e3afa5e6 110 memset(PacketBuffer.payload, 0x0, sizeof(PacketBuffer.payload));
rba90 0:21e4e3afa5e6 111 PacketBuffer.errno = CommandPacket::NO_ERROR;
rba90 0:21e4e3afa5e6 112 }
rba90 0:21e4e3afa5e6 113
rba90 0:21e4e3afa5e6 114 switch (state)
rba90 0:21e4e3afa5e6 115 {
rba90 0:21e4e3afa5e6 116 case CommandPacket::SFLAG:
rba90 0:21e4e3afa5e6 117 PacketBuffer.sflag = ch;
rba90 0:21e4e3afa5e6 118 state = CommandPacket::COMMAND_H;
rba90 0:21e4e3afa5e6 119 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 120 printf("CommandPacket::SFLAG: 0x%x\r\n", PacketBuffer.sflag);
rba90 0:21e4e3afa5e6 121 #endif
rba90 0:21e4e3afa5e6 122 break;
rba90 0:21e4e3afa5e6 123
rba90 0:21e4e3afa5e6 124 case CommandPacket::COMMAND_H:
rba90 0:21e4e3afa5e6 125 PacketBuffer.command = hexchar_to_uint8(ch) << 4;
rba90 0:21e4e3afa5e6 126 state = CommandPacket::COMMAND_L;
rba90 0:21e4e3afa5e6 127 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 128 printf("CommandPacket::COMMAND_H: 0x%x\r\n", PacketBuffer.command);
rba90 0:21e4e3afa5e6 129 #endif
rba90 0:21e4e3afa5e6 130 break;
rba90 0:21e4e3afa5e6 131
rba90 0:21e4e3afa5e6 132 case CommandPacket::COMMAND_L:
rba90 0:21e4e3afa5e6 133 PacketBuffer.command |= (hexchar_to_uint8(ch) & 0x0f);
rba90 0:21e4e3afa5e6 134 state = CommandPacket::LENGTH_H;
rba90 0:21e4e3afa5e6 135 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 136 printf("CommandPacket::COMMAND_L: 0x%x\r\n", PacketBuffer.command);
rba90 0:21e4e3afa5e6 137 #endif
rba90 0:21e4e3afa5e6 138 break;
rba90 0:21e4e3afa5e6 139
rba90 0:21e4e3afa5e6 140 case CommandPacket::LENGTH_H:
rba90 0:21e4e3afa5e6 141 PacketBuffer.length = hexchar_to_uint8(ch) << 4;
rba90 0:21e4e3afa5e6 142 state = CommandPacket::LENGTH_L;
rba90 0:21e4e3afa5e6 143 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 144 printf("CommandPacket::LENGTH_H: 0x%x\r\n", PacketBuffer.length);
rba90 0:21e4e3afa5e6 145 #endif
rba90 0:21e4e3afa5e6 146 break;
rba90 0:21e4e3afa5e6 147
rba90 0:21e4e3afa5e6 148 case CommandPacket::LENGTH_L:
rba90 0:21e4e3afa5e6 149 PacketBuffer.length |= (hexchar_to_uint8(ch) & 0x0f);
rba90 0:21e4e3afa5e6 150 if (PacketBuffer.length != 0) // if the length is not zero, then proceed to payload state
rba90 0:21e4e3afa5e6 151 {
rba90 0:21e4e3afa5e6 152 state = CommandPacket::PAYLOAD_H;
rba90 0:21e4e3afa5e6 153 }
rba90 0:21e4e3afa5e6 154 else // otherwise proceed to checksum state
rba90 0:21e4e3afa5e6 155 {
rba90 0:21e4e3afa5e6 156 state = CommandPacket::CHECKSUM_H;
rba90 0:21e4e3afa5e6 157 }
rba90 0:21e4e3afa5e6 158 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 159 printf("CommandPacket::LENGTH_L: 0x%x\r\n", PacketBuffer.length);
rba90 0:21e4e3afa5e6 160 #endif
rba90 0:21e4e3afa5e6 161 break;
rba90 0:21e4e3afa5e6 162
rba90 0:21e4e3afa5e6 163 case CommandPacket::PAYLOAD_H:
rba90 0:21e4e3afa5e6 164 PacketBuffer.payload[payload_counter] = hexchar_to_uint8(ch) << 4; // store higher 4 bits of payload
rba90 0:21e4e3afa5e6 165 state = CommandPacket::PAYLOAD_L;
rba90 0:21e4e3afa5e6 166 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 167 printf("CommandPacket::PAYLOAD_H: 0x%x\r\n", PacketBuffer.payload[payload_counter]);
rba90 0:21e4e3afa5e6 168 #endif
rba90 0:21e4e3afa5e6 169 break;
rba90 0:21e4e3afa5e6 170
rba90 0:21e4e3afa5e6 171 case CommandPacket::PAYLOAD_L:
rba90 0:21e4e3afa5e6 172 PacketBuffer.payload[payload_counter++] |= (hexchar_to_uint8(ch) & 0x0f); // store lower 4 bits of payload
rba90 0:21e4e3afa5e6 173 if (payload_counter < PacketBuffer.length) // append ch to payload until reach the length
rba90 0:21e4e3afa5e6 174 {
rba90 0:21e4e3afa5e6 175 state = CommandPacket::PAYLOAD_H;
rba90 0:21e4e3afa5e6 176 }
rba90 0:21e4e3afa5e6 177 else
rba90 0:21e4e3afa5e6 178 {
rba90 0:21e4e3afa5e6 179 state = CommandPacket::CHECKSUM_H;
rba90 0:21e4e3afa5e6 180 }
rba90 0:21e4e3afa5e6 181 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 182 printf("CommandPacket::PAYLOAD_L: 0x%x\r\n", PacketBuffer.payload[payload_counter - 1]);
rba90 0:21e4e3afa5e6 183 #endif
rba90 0:21e4e3afa5e6 184 break;
rba90 0:21e4e3afa5e6 185
rba90 0:21e4e3afa5e6 186 case CommandPacket::CHECKSUM_H:
rba90 0:21e4e3afa5e6 187 PacketBuffer.checksum = hexchar_to_uint8(ch) << 4;
rba90 0:21e4e3afa5e6 188 state = CommandPacket::CHECKSUM_L;
rba90 0:21e4e3afa5e6 189 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 190 printf("CommandPacket::CHECKSUM_H: 0x%x\r\n", PacketBuffer.checksum);
rba90 0:21e4e3afa5e6 191 #endif
rba90 0:21e4e3afa5e6 192 break;
rba90 0:21e4e3afa5e6 193
rba90 0:21e4e3afa5e6 194 case CommandPacket::CHECKSUM_L:
rba90 0:21e4e3afa5e6 195 PacketBuffer.checksum |= (hexchar_to_uint8(ch) & 0x0f);
rba90 0:21e4e3afa5e6 196
rba90 0:21e4e3afa5e6 197 // checksum can be turned off
rba90 0:21e4e3afa5e6 198 if (isChecksumEnabled)
rba90 0:21e4e3afa5e6 199 {
rba90 0:21e4e3afa5e6 200 if (PacketBuffer.verify()) // checksum match
rba90 0:21e4e3afa5e6 201 {
rba90 0:21e4e3afa5e6 202 state = CommandPacket::EFLAG;
rba90 0:21e4e3afa5e6 203 }
rba90 0:21e4e3afa5e6 204 else // checksum mismatch
rba90 0:21e4e3afa5e6 205 {
rba90 0:21e4e3afa5e6 206 PacketBuffer.errno = CommandPacket::INVALID_CS_ERROR;
rba90 0:21e4e3afa5e6 207
rba90 0:21e4e3afa5e6 208 // prepare for checksum error response
rba90 0:21e4e3afa5e6 209 PacketBuffer.errno = CommandPacket::INVALID_CS_ERROR;
rba90 0:21e4e3afa5e6 210 assemble(response, response_length);
rba90 0:21e4e3afa5e6 211
rba90 0:21e4e3afa5e6 212 state = CommandPacket::NONE;
rba90 0:21e4e3afa5e6 213 }
rba90 0:21e4e3afa5e6 214 }
rba90 0:21e4e3afa5e6 215 else
rba90 0:21e4e3afa5e6 216 {
rba90 0:21e4e3afa5e6 217 state = CommandPacket::EFLAG;
rba90 0:21e4e3afa5e6 218 }
rba90 0:21e4e3afa5e6 219
rba90 0:21e4e3afa5e6 220
rba90 0:21e4e3afa5e6 221 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 222 printf("CommandPacket::CHECKSUM_L: 0x%x\r\n", PacketBuffer.checksum);
rba90 0:21e4e3afa5e6 223 #endif
rba90 0:21e4e3afa5e6 224 break;
rba90 0:21e4e3afa5e6 225
rba90 0:21e4e3afa5e6 226 case CommandPacket::EFLAG:
rba90 0:21e4e3afa5e6 227 if (ch == CommandPacket::CP_EFLAG)
rba90 0:21e4e3afa5e6 228 {
rba90 0:21e4e3afa5e6 229 PacketBuffer.eflag = ch;
rba90 0:21e4e3afa5e6 230
rba90 0:21e4e3afa5e6 231 // clear response and response length
rba90 0:21e4e3afa5e6 232 response_length = 0;
rba90 0:21e4e3afa5e6 233 memset(response, 0x0, sizeof(response));
rba90 0:21e4e3afa5e6 234
rba90 0:21e4e3afa5e6 235 // execute command
rba90 0:21e4e3afa5e6 236 int ret = execute(response, &response_length);
rba90 0:21e4e3afa5e6 237
rba90 0:21e4e3afa5e6 238 if (ret < 0) // command not registered
rba90 0:21e4e3afa5e6 239 {
rba90 0:21e4e3afa5e6 240 PacketBuffer.errno = CommandPacket::INVALID_CMD_ERROR;
rba90 0:21e4e3afa5e6 241 }
rba90 0:21e4e3afa5e6 242 else if (ret != 0) // error to execute
rba90 0:21e4e3afa5e6 243 {
rba90 0:21e4e3afa5e6 244 PacketBuffer.errno = CommandPacket::INVALID_EXEC_ERROR;
rba90 0:21e4e3afa5e6 245 }
rba90 0:21e4e3afa5e6 246
rba90 0:21e4e3afa5e6 247 assemble(response, response_length);
rba90 0:21e4e3afa5e6 248 }
rba90 0:21e4e3afa5e6 249 state = CommandPacket::NONE;
rba90 0:21e4e3afa5e6 250 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 251 printf("CommandPacket::EFLAG: 0x%x\r\n", PacketBuffer.eflag);
rba90 0:21e4e3afa5e6 252 #endif
rba90 0:21e4e3afa5e6 253 break;
rba90 0:21e4e3afa5e6 254
rba90 0:21e4e3afa5e6 255 case CommandPacket::NONE:
rba90 0:21e4e3afa5e6 256 PacketBuffer.errno = CommandPacket::INVALID_SFLAG_ERROR;
rba90 0:21e4e3afa5e6 257
rba90 0:21e4e3afa5e6 258 // TODO:: Execute error generator
rba90 0:21e4e3afa5e6 259 PacketBuffer.errno = CommandPacket::INVALID_SFLAG_ERROR;
rba90 0:21e4e3afa5e6 260 assemble(response, response_length);
rba90 0:21e4e3afa5e6 261
rba90 0:21e4e3afa5e6 262 #ifdef DEBUG_MESSAGE
rba90 0:21e4e3afa5e6 263 printf("CommandPacket::NONE\r\n");
rba90 0:21e4e3afa5e6 264 #endif
rba90 0:21e4e3afa5e6 265 break;
rba90 0:21e4e3afa5e6 266
rba90 0:21e4e3afa5e6 267 default:
rba90 0:21e4e3afa5e6 268 break;
rba90 0:21e4e3afa5e6 269 }
rba90 0:21e4e3afa5e6 270 }
rba90 0:21e4e3afa5e6 271 }
rba90 0:21e4e3afa5e6 272
rba90 0:21e4e3afa5e6 273 void SerialInterfaceProtocol::disableChecksum()
rba90 0:21e4e3afa5e6 274 {
rba90 0:21e4e3afa5e6 275 isChecksumEnabled = false;
rba90 0:21e4e3afa5e6 276 }
rba90 0:21e4e3afa5e6 277
rba90 0:21e4e3afa5e6 278 void SerialInterfaceProtocol::enableChecksum()
rba90 0:21e4e3afa5e6 279 {
rba90 0:21e4e3afa5e6 280 isChecksumEnabled = true;
rba90 0:21e4e3afa5e6 281 }