simple serial protocol

Dependents:   AwsomeStation LoRaBaseStation LoRaTerminal

Committer:
rba90
Date:
Fri Aug 12 03:32:55 2016 +0000
Revision:
7:100865963801
Parent:
5:d39ee3fc4f4a
Child:
8:9a8085508415
add a method that write to serial port with SIP format

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