simple serial protocol

Dependents:   AwsomeStation LoRaBaseStation LoRaTerminal

Committer:
rba90
Date:
Thu Sep 01 04:15:40 2016 +0000
Revision:
10:2a710d0bab2c
Parent:
9:61ed835bb206
Child:
11:390476907bfc
remove redundant code

Who changed what in which revision?

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