simple serial protocol

Dependents:   AwsomeStation LoRaBaseStation LoRaTerminal

Committer:
rba90
Date:
Fri Sep 02 02:39:04 2016 +0000
Revision:
11:390476907bfc
Parent:
10:2a710d0bab2c
The CommandPacket is reconstructed.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rba90 11:390476907bfc 1 #include "mbed.h"
rba90 0:21e4e3afa5e6 2 #include "SerialInterfaceProtocol.h"
rba90 11:390476907bfc 3 #include "CommandPacket2.h"
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 11:390476907bfc 18 state = NONE;
rba90 0:21e4e3afa5e6 19
rba90 0:21e4e3afa5e6 20 // init internal state
rba90 3:22bb958f0eb0 21 isChecksumEnabled = false;
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 11:390476907bfc 41 // read command from packet buffer
rba90 11:390476907bfc 42 uint8_t command = PacketBuffer.getCommand();
rba90 0:21e4e3afa5e6 43
rba90 0:21e4e3afa5e6 44 // execute the command if it's already been registered
rba90 11:390476907bfc 45 if (CommandVectorTable[command] != NULL)
rba90 11:390476907bfc 46 {
rba90 11:390476907bfc 47 // extract length and payload from packet buffer
rba90 11:390476907bfc 48 uint8_t length = PacketBuffer.getLength();
rba90 11:390476907bfc 49 uint8_t payload[length];
rba90 11:390476907bfc 50 memset(payload, 0x0, length);
rba90 11:390476907bfc 51
rba90 11:390476907bfc 52 for (uint8_t i = 0; i < length; i++)
rba90 11:390476907bfc 53 {
rba90 11:390476907bfc 54 payload[i] = PacketBuffer.getPayload(i);
rba90 11:390476907bfc 55 }
rba90 11:390476907bfc 56
rba90 11:390476907bfc 57 return CommandVectorTable[command](
rba90 11:390476907bfc 58 payload,
rba90 11:390476907bfc 59 length,
rba90 0:21e4e3afa5e6 60 response,
rba90 0:21e4e3afa5e6 61 response_length
rba90 0:21e4e3afa5e6 62 );
rba90 0:21e4e3afa5e6 63 }
rba90 0:21e4e3afa5e6 64
rba90 0:21e4e3afa5e6 65 return -1;
rba90 0:21e4e3afa5e6 66 }
rba90 0:21e4e3afa5e6 67
rba90 0:21e4e3afa5e6 68 int SerialInterfaceProtocol::assemble(uint8_t *response, uint8_t response_length)
rba90 0:21e4e3afa5e6 69 {
rba90 5:d39ee3fc4f4a 70 // if no response, return E, otherwise return F
rba90 5:d39ee3fc4f4a 71 if (response_length != 0)
rba90 5:d39ee3fc4f4a 72 {
rba90 10:2a710d0bab2c 73 respond(
rba90 11:390476907bfc 74 0xD0 | ((uint8_t) errno & 0x0F),
rba90 10:2a710d0bab2c 75 response,
rba90 10:2a710d0bab2c 76 response_length
rba90 10:2a710d0bab2c 77 );
rba90 5:d39ee3fc4f4a 78 }
rba90 5:d39ee3fc4f4a 79 else
rba90 5:d39ee3fc4f4a 80 {
rba90 10:2a710d0bab2c 81 respond(
rba90 11:390476907bfc 82 0xE0 | ((uint8_t) errno & 0x0F),
rba90 10:2a710d0bab2c 83 response,
rba90 10:2a710d0bab2c 84 response_length
rba90 10:2a710d0bab2c 85 );
rba90 0:21e4e3afa5e6 86 }
rba90 0:21e4e3afa5e6 87
rba90 7:100865963801 88 return 0;
rba90 7:100865963801 89 }
rba90 7:100865963801 90
rba90 7:100865963801 91 int SerialInterfaceProtocol::respond(uint8_t command, uint8_t *response, uint8_t response_length)
rba90 7:100865963801 92 {
rba90 11:390476907bfc 93 // create a new packet buffer
rba90 11:390476907bfc 94 CommandPacket2 responsePacket;
rba90 11:390476907bfc 95
rba90 11:390476907bfc 96 // set sflag
rba90 11:390476907bfc 97 responsePacket.setSFlag(); // use default sflag
rba90 7:100865963801 98
rba90 7:100865963801 99 // return flag as specified by the user
rba90 11:390476907bfc 100 responsePacket.setCommand(command);
rba90 7:100865963801 101
rba90 7:100865963801 102 // copy buffer length
rba90 11:390476907bfc 103 responsePacket.setLength(response_length);
rba90 7:100865963801 104
rba90 7:100865963801 105 // copy buffer to payload
rba90 11:390476907bfc 106 for (uint8_t i = 0; i < response_length; i++)
rba90 11:390476907bfc 107 {
rba90 11:390476907bfc 108 responsePacket.setPayload(i, response[i]);
rba90 11:390476907bfc 109 }
rba90 7:100865963801 110
rba90 7:100865963801 111 // generate checksum
rba90 11:390476907bfc 112 responsePacket.generateChecksum();
rba90 0:21e4e3afa5e6 113
rba90 7:100865963801 114 // end flag
rba90 11:390476907bfc 115 responsePacket.setEFlag();
rba90 7:100865963801 116
rba90 7:100865963801 117 // serialize the packet
rba90 11:390476907bfc 118 int total_len = response_length * 2 + 8;
rba90 7:100865963801 119 uint8_t buffer[total_len];
rba90 7:100865963801 120 memset(buffer, 0x0, total_len);
rba90 7:100865963801 121
rba90 11:390476907bfc 122 responsePacket.serialize(buffer);
rba90 10:2a710d0bab2c 123
rba90 10:2a710d0bab2c 124 #ifdef DEBUG_SIP
rba90 10:2a710d0bab2c 125 printf("SIP::respond:total: %d chars\r\n", total_len);
rba90 10:2a710d0bab2c 126 #endif
rba90 7:100865963801 127
rba90 7:100865963801 128 // add to ring buffer
rba90 7:100865963801 129 for (int i = 0; i < total_len; i++)
rba90 7:100865963801 130 {
rba90 10:2a710d0bab2c 131 #ifdef DEBUG_SIP
rba90 10:2a710d0bab2c 132 printf("SIP::respond:0x%x (%c)\r\n", buffer[i], buffer[i]);
rba90 10:2a710d0bab2c 133 #endif
rba90 7:100865963801 134 SerialOutputBuffer->enqueue(buffer[i]);
rba90 7:100865963801 135 }
rba90 7:100865963801 136
rba90 7:100865963801 137 return 0;
rba90 7:100865963801 138 };
rba90 7:100865963801 139
rba90 0:21e4e3afa5e6 140
rba90 0:21e4e3afa5e6 141 void SerialInterfaceProtocol::poll()
rba90 0:21e4e3afa5e6 142 {
rba90 0:21e4e3afa5e6 143 static uint8_t payload_counter = 0;
rba90 11:390476907bfc 144
rba90 11:390476907bfc 145 // temp variable for building full byte from hex strings
rba90 11:390476907bfc 146 static uint8_t command = 0;
rba90 11:390476907bfc 147 static uint8_t length = 0;
rba90 11:390476907bfc 148 static uint8_t payload = 0;
rba90 11:390476907bfc 149 static uint8_t checksum = 0;
rba90 11:390476907bfc 150
rba90 0:21e4e3afa5e6 151 uint8_t response[SIP_MAX_RESP_LEN];
rba90 0:21e4e3afa5e6 152 uint8_t response_length;
rba90 0:21e4e3afa5e6 153
rba90 0:21e4e3afa5e6 154 // fetch data from ring buffer
rba90 0:21e4e3afa5e6 155 while (SerialInputBuffer->getCounter() > 0)
rba90 0:21e4e3afa5e6 156 {
rba90 0:21e4e3afa5e6 157 uint8_t ch;
rba90 0:21e4e3afa5e6 158 ch = SerialInputBuffer->dequeue();
rba90 0:21e4e3afa5e6 159
rba90 0:21e4e3afa5e6 160 // reset state to keep sync
rba90 11:390476907bfc 161 if (ch == CommandPacket2::CP_SFLAG)
rba90 0:21e4e3afa5e6 162 {
rba90 11:390476907bfc 163 state = SFLAG;
rba90 0:21e4e3afa5e6 164
rba90 0:21e4e3afa5e6 165 // reset variable
rba90 0:21e4e3afa5e6 166 payload_counter = 0;
rba90 11:390476907bfc 167 errno = NO_ERROR;
rba90 0:21e4e3afa5e6 168 }
rba90 0:21e4e3afa5e6 169
rba90 0:21e4e3afa5e6 170 switch (state)
rba90 0:21e4e3afa5e6 171 {
rba90 11:390476907bfc 172 case SFLAG:
rba90 11:390476907bfc 173 PacketBuffer.setSFlag(ch);
rba90 11:390476907bfc 174 state = COMMAND_H;
rba90 8:9a8085508415 175 #ifdef DEBUG_SIP
rba90 11:390476907bfc 176 printf("SIP::SFLAG: 0x%x\r\n", PacketBuffer.getSFlag());
rba90 0:21e4e3afa5e6 177 #endif
rba90 0:21e4e3afa5e6 178 break;
rba90 0:21e4e3afa5e6 179
rba90 11:390476907bfc 180 case COMMAND_H:
rba90 11:390476907bfc 181 command = hexchar_to_uint8(ch) << 4;
rba90 11:390476907bfc 182 state = COMMAND_L;
rba90 8:9a8085508415 183 #ifdef DEBUG_SIP
rba90 11:390476907bfc 184 printf("SIP::COMMAND_H: 0x%x\r\n", command);
rba90 0:21e4e3afa5e6 185 #endif
rba90 0:21e4e3afa5e6 186 break;
rba90 0:21e4e3afa5e6 187
rba90 11:390476907bfc 188 case COMMAND_L:
rba90 11:390476907bfc 189 command |= (hexchar_to_uint8(ch) & 0x0f);
rba90 11:390476907bfc 190
rba90 11:390476907bfc 191 // store command
rba90 11:390476907bfc 192 PacketBuffer.setCommand(command);
rba90 11:390476907bfc 193
rba90 11:390476907bfc 194 state = LENGTH_H;
rba90 8:9a8085508415 195 #ifdef DEBUG_SIP
rba90 11:390476907bfc 196 printf("SIP::COMMAND_L: 0x%x\r\n", command);
rba90 0:21e4e3afa5e6 197 #endif
rba90 0:21e4e3afa5e6 198 break;
rba90 0:21e4e3afa5e6 199
rba90 11:390476907bfc 200 case LENGTH_H:
rba90 11:390476907bfc 201 length = hexchar_to_uint8(ch) << 4;
rba90 11:390476907bfc 202 state = LENGTH_L;
rba90 8:9a8085508415 203 #ifdef DEBUG_SIP
rba90 11:390476907bfc 204 printf("SIP::LENGTH_H: 0x%x\r\n", length);
rba90 0:21e4e3afa5e6 205 #endif
rba90 0:21e4e3afa5e6 206 break;
rba90 0:21e4e3afa5e6 207
rba90 11:390476907bfc 208 case LENGTH_L:
rba90 11:390476907bfc 209 length |= (hexchar_to_uint8(ch) & 0x0f);
rba90 11:390476907bfc 210
rba90 11:390476907bfc 211 // store length
rba90 11:390476907bfc 212 PacketBuffer.setLength(length);
rba90 11:390476907bfc 213
rba90 11:390476907bfc 214 if (length != 0) // if the length is not zero, then proceed to payload state
rba90 0:21e4e3afa5e6 215 {
rba90 11:390476907bfc 216 state = PAYLOAD_H;
rba90 0:21e4e3afa5e6 217 }
rba90 0:21e4e3afa5e6 218 else // otherwise proceed to checksum state
rba90 0:21e4e3afa5e6 219 {
rba90 11:390476907bfc 220 state = CHECKSUM_H;
rba90 0:21e4e3afa5e6 221 }
rba90 8:9a8085508415 222 #ifdef DEBUG_SIP
rba90 11:390476907bfc 223 printf("SIP::LENGTH_L: 0x%x\r\n", length);
rba90 0:21e4e3afa5e6 224 #endif
rba90 0:21e4e3afa5e6 225 break;
rba90 0:21e4e3afa5e6 226
rba90 11:390476907bfc 227 case PAYLOAD_H:
rba90 11:390476907bfc 228 payload = hexchar_to_uint8(ch) << 4; // store higher 4 bits of payload
rba90 11:390476907bfc 229 state = PAYLOAD_L;
rba90 8:9a8085508415 230 #ifdef DEBUG_SIP
rba90 11:390476907bfc 231 printf("SIP::PAYLOAD_H: 0x%x\r\n", payload);
rba90 0:21e4e3afa5e6 232 #endif
rba90 0:21e4e3afa5e6 233 break;
rba90 0:21e4e3afa5e6 234
rba90 11:390476907bfc 235 case PAYLOAD_L:
rba90 11:390476907bfc 236 payload |= (hexchar_to_uint8(ch) & 0x0f); // store lower 4 bits of payload
rba90 11:390476907bfc 237
rba90 11:390476907bfc 238 // store payload
rba90 11:390476907bfc 239 PacketBuffer.setPayload(payload_counter++, payload);
rba90 11:390476907bfc 240
rba90 11:390476907bfc 241 if (payload_counter < PacketBuffer.getLength()) // append ch to payload until reach the length
rba90 0:21e4e3afa5e6 242 {
rba90 11:390476907bfc 243 state = PAYLOAD_H;
rba90 0:21e4e3afa5e6 244 }
rba90 0:21e4e3afa5e6 245 else
rba90 0:21e4e3afa5e6 246 {
rba90 11:390476907bfc 247 state = CHECKSUM_H;
rba90 0:21e4e3afa5e6 248 }
rba90 8:9a8085508415 249 #ifdef DEBUG_SIP
rba90 11:390476907bfc 250 printf("SIP::PAYLOAD_L: 0x%x\r\n", payload);
rba90 0:21e4e3afa5e6 251 #endif
rba90 0:21e4e3afa5e6 252 break;
rba90 0:21e4e3afa5e6 253
rba90 11:390476907bfc 254 case CHECKSUM_H:
rba90 11:390476907bfc 255 checksum = hexchar_to_uint8(ch) << 4;
rba90 11:390476907bfc 256 state = CHECKSUM_L;
rba90 8:9a8085508415 257 #ifdef DEBUG_SIP
rba90 11:390476907bfc 258 printf("SIP::CHECKSUM_H: 0x%x\r\n", checksum);
rba90 0:21e4e3afa5e6 259 #endif
rba90 0:21e4e3afa5e6 260 break;
rba90 0:21e4e3afa5e6 261
rba90 11:390476907bfc 262 case CHECKSUM_L:
rba90 11:390476907bfc 263 checksum |= (hexchar_to_uint8(ch) & 0x0f);
rba90 11:390476907bfc 264
rba90 11:390476907bfc 265 // store checksum
rba90 11:390476907bfc 266 PacketBuffer.setChecksum(checksum);
rba90 0:21e4e3afa5e6 267
rba90 0:21e4e3afa5e6 268 // checksum can be turned off
rba90 0:21e4e3afa5e6 269 if (isChecksumEnabled)
rba90 0:21e4e3afa5e6 270 {
rba90 0:21e4e3afa5e6 271 if (PacketBuffer.verify()) // checksum match
rba90 0:21e4e3afa5e6 272 {
rba90 11:390476907bfc 273 state = EFLAG;
rba90 0:21e4e3afa5e6 274 }
rba90 0:21e4e3afa5e6 275 else // checksum mismatch
rba90 0:21e4e3afa5e6 276 {
rba90 1:03208c983c8b 277 // clear response and response length
rba90 1:03208c983c8b 278 response_length = 0;
rba90 1:03208c983c8b 279 memset(response, 0x0, sizeof(response));
rba90 0:21e4e3afa5e6 280
rba90 0:21e4e3afa5e6 281 // prepare for checksum error response
rba90 11:390476907bfc 282 errno = INVALID_CS_ERROR;
rba90 0:21e4e3afa5e6 283 assemble(response, response_length);
rba90 0:21e4e3afa5e6 284
rba90 11:390476907bfc 285 state = NONE;
rba90 0:21e4e3afa5e6 286 }
rba90 0:21e4e3afa5e6 287 }
rba90 0:21e4e3afa5e6 288 else
rba90 0:21e4e3afa5e6 289 {
rba90 11:390476907bfc 290 state = EFLAG;
rba90 0:21e4e3afa5e6 291 }
rba90 0:21e4e3afa5e6 292
rba90 0:21e4e3afa5e6 293
rba90 8:9a8085508415 294 #ifdef DEBUG_SIP
rba90 11:390476907bfc 295 printf("SIP::CHECKSUM_L: 0x%x\r\n", checksum);
rba90 0:21e4e3afa5e6 296 #endif
rba90 0:21e4e3afa5e6 297 break;
rba90 0:21e4e3afa5e6 298
rba90 11:390476907bfc 299 case EFLAG:
rba90 11:390476907bfc 300 if (ch == CommandPacket2::CP_EFLAG)
rba90 0:21e4e3afa5e6 301 {
rba90 11:390476907bfc 302 PacketBuffer.setEFlag(ch);
rba90 0:21e4e3afa5e6 303
rba90 0:21e4e3afa5e6 304 // clear response and response length
rba90 0:21e4e3afa5e6 305 response_length = 0;
rba90 0:21e4e3afa5e6 306 memset(response, 0x0, sizeof(response));
rba90 0:21e4e3afa5e6 307
rba90 0:21e4e3afa5e6 308 // execute command
rba90 0:21e4e3afa5e6 309 int ret = execute(response, &response_length);
rba90 0:21e4e3afa5e6 310
rba90 0:21e4e3afa5e6 311 if (ret < 0) // command not registered
rba90 0:21e4e3afa5e6 312 {
rba90 11:390476907bfc 313 errno = INVALID_CMD_ERROR;
rba90 0:21e4e3afa5e6 314 }
rba90 0:21e4e3afa5e6 315 else if (ret != 0) // error to execute
rba90 0:21e4e3afa5e6 316 {
rba90 11:390476907bfc 317 errno = INVALID_EXEC_ERROR;
rba90 0:21e4e3afa5e6 318 }
rba90 4:4a92da3f19c0 319 else
rba90 4:4a92da3f19c0 320 {
rba90 11:390476907bfc 321 errno = NO_ERROR;
rba90 4:4a92da3f19c0 322 }
rba90 0:21e4e3afa5e6 323
rba90 0:21e4e3afa5e6 324 assemble(response, response_length);
rba90 0:21e4e3afa5e6 325 }
rba90 11:390476907bfc 326 state = NONE;
rba90 8:9a8085508415 327 #ifdef DEBUG_SIP
rba90 11:390476907bfc 328 printf("SIP::EFLAG: 0x%x\r\n", PacketBuffer.getEFlag());
rba90 0:21e4e3afa5e6 329 #endif
rba90 0:21e4e3afa5e6 330 break;
rba90 0:21e4e3afa5e6 331
rba90 11:390476907bfc 332 case NONE:
rba90 1:03208c983c8b 333 // clear response and response length
rba90 1:03208c983c8b 334 response_length = 0;
rba90 1:03208c983c8b 335 memset(response, 0x0, sizeof(response));
rba90 0:21e4e3afa5e6 336
rba90 1:03208c983c8b 337 // Execute error generator
rba90 11:390476907bfc 338 errno = INVALID_SFLAG_ERROR;
rba90 0:21e4e3afa5e6 339 assemble(response, response_length);
rba90 0:21e4e3afa5e6 340
rba90 8:9a8085508415 341 #ifdef DEBUG_SIP
rba90 11:390476907bfc 342 printf("SIP::NONE\r\n");
rba90 0:21e4e3afa5e6 343 #endif
rba90 0:21e4e3afa5e6 344 break;
rba90 0:21e4e3afa5e6 345
rba90 0:21e4e3afa5e6 346 default:
rba90 0:21e4e3afa5e6 347 break;
rba90 0:21e4e3afa5e6 348 }
rba90 0:21e4e3afa5e6 349 }
rba90 0:21e4e3afa5e6 350 }
rba90 0:21e4e3afa5e6 351
rba90 0:21e4e3afa5e6 352 void SerialInterfaceProtocol::disableChecksum()
rba90 0:21e4e3afa5e6 353 {
rba90 0:21e4e3afa5e6 354 isChecksumEnabled = false;
rba90 0:21e4e3afa5e6 355 }
rba90 0:21e4e3afa5e6 356
rba90 0:21e4e3afa5e6 357 void SerialInterfaceProtocol::enableChecksum()
rba90 0:21e4e3afa5e6 358 {
rba90 0:21e4e3afa5e6 359 isChecksumEnabled = true;
rba90 11:390476907bfc 360 }
rba90 11:390476907bfc 361
rba90 11:390476907bfc 362 uint8_t hexchar_to_uint8(uint8_t ch)
rba90 11:390476907bfc 363 {
rba90 11:390476907bfc 364 uint8_t val = 0;
rba90 11:390476907bfc 365
rba90 11:390476907bfc 366 if (ch >= '0' && ch <= '9')
rba90 11:390476907bfc 367 {
rba90 11:390476907bfc 368 val = ch - '0';
rba90 11:390476907bfc 369 }
rba90 11:390476907bfc 370 else if (ch >= 'A' && ch <= 'F')
rba90 11:390476907bfc 371 {
rba90 11:390476907bfc 372 val = ch - 'A';
rba90 11:390476907bfc 373 val += 10;
rba90 11:390476907bfc 374 }
rba90 11:390476907bfc 375 else if (ch >= 'a' && ch <= 'f')
rba90 11:390476907bfc 376 {
rba90 11:390476907bfc 377 val = ch - 'a';
rba90 11:390476907bfc 378 val += 10;
rba90 11:390476907bfc 379 }
rba90 11:390476907bfc 380
rba90 11:390476907bfc 381 return val;
rba90 11:390476907bfc 382 }