This is a SLIP interface for the STM32F446RE Nucleo Board. It is designed to work specifically with the esp-link software for the ESP8266. The program is an example of a rest command.

Dependencies:   mbed DHT Matrix

Committer:
ShaneKirkbride
Date:
Thu Aug 04 19:44:11 2016 +0000
Revision:
2:20ea1be14e4b
Parent:
0:70a6082c1bf7
Child:
3:8ed85d940c4c
now just posting to posttestserver.com

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ShaneKirkbride 0:70a6082c1bf7 1 #include "STMClient.h"
ShaneKirkbride 0:70a6082c1bf7 2 #include "millis.h"
ShaneKirkbride 0:70a6082c1bf7 3
ShaneKirkbride 0:70a6082c1bf7 4 #define xstr(s) str(s)
ShaneKirkbride 0:70a6082c1bf7 5 #define str(s) #s
ShaneKirkbride 0:70a6082c1bf7 6
ShaneKirkbride 0:70a6082c1bf7 7 #define SLIP_END 0300 // indicates end of packet
ShaneKirkbride 0:70a6082c1bf7 8 #define SLIP_ESC 0333 // indicates byte stuffing
ShaneKirkbride 0:70a6082c1bf7 9 #define SLIP_ESC_END 0334 // ESC ESC_END means END data byte
ShaneKirkbride 0:70a6082c1bf7 10 #define SLIP_ESC_ESC 0335 // ESC ESC_ESC means ESC data byte
ShaneKirkbride 0:70a6082c1bf7 11
ShaneKirkbride 0:70a6082c1bf7 12 //===== Input
ShaneKirkbride 0:70a6082c1bf7 13
ShaneKirkbride 0:70a6082c1bf7 14 // Process a received SLIP message
ShaneKirkbride 0:70a6082c1bf7 15 STMClientPacket* STMClient::protoCompletedCb(void) {
ShaneKirkbride 0:70a6082c1bf7 16 // the packet starts with a STMClientPacket
ShaneKirkbride 0:70a6082c1bf7 17 STMClientPacket* packet = (STMClientPacket*)_proto.buf;
ShaneKirkbride 0:70a6082c1bf7 18 if (_debugEn) {
ShaneKirkbride 0:70a6082c1bf7 19 // _debug->printf("STMC: got %i @ %i:\n\r 0x%x\n\r 0x%x\n\r 0x%x\n\r", _proto.dataLen,(uint32_t)_proto.buf, packet->cmd, packet->value, packet->argc);
ShaneKirkbride 0:70a6082c1bf7 20
ShaneKirkbride 0:70a6082c1bf7 21 for (uint16_t i=8; i<_proto.dataLen; i++)
ShaneKirkbride 0:70a6082c1bf7 22 {
ShaneKirkbride 0:70a6082c1bf7 23 // _debug->printf("%x", *(uint8_t*)(_proto.buf+i));
ShaneKirkbride 0:70a6082c1bf7 24 }
ShaneKirkbride 0:70a6082c1bf7 25 //_debug->printf("\n\r");
ShaneKirkbride 0:70a6082c1bf7 26 }
ShaneKirkbride 0:70a6082c1bf7 27
ShaneKirkbride 0:70a6082c1bf7 28 // verify CRC
ShaneKirkbride 0:70a6082c1bf7 29 uint16_t crc = crc16Data(_proto.buf, _proto.dataLen-2, 0);
ShaneKirkbride 0:70a6082c1bf7 30 //_debug->printf("CRC: %i\n\r",crc);
ShaneKirkbride 0:70a6082c1bf7 31 //wait(0.5);
ShaneKirkbride 0:70a6082c1bf7 32 uint16_t resp_crc = *(uint16_t*)(_proto.buf+_proto.dataLen-2);
ShaneKirkbride 0:70a6082c1bf7 33 //_debug->printf("resp_crc: %i\n\r",resp_crc);
ShaneKirkbride 0:70a6082c1bf7 34 if (crc != resp_crc) {
ShaneKirkbride 0:70a6082c1bf7 35 DBG("STMC: Invalid CRC\n\r");
ShaneKirkbride 0:70a6082c1bf7 36 wait(0.5);
ShaneKirkbride 0:70a6082c1bf7 37
ShaneKirkbride 0:70a6082c1bf7 38 //return NULL; maybe the CRC isn't getting calculated correctly...
ShaneKirkbride 0:70a6082c1bf7 39 }
ShaneKirkbride 0:70a6082c1bf7 40
ShaneKirkbride 0:70a6082c1bf7 41 // dispatch based on command
ShaneKirkbride 0:70a6082c1bf7 42 if (packet->cmd == CMD_RESP_V) {
ShaneKirkbride 0:70a6082c1bf7 43 // value response
ShaneKirkbride 0:70a6082c1bf7 44 _debug->printf("RESP_V: 0x%x \n\r",packet->value);
ShaneKirkbride 0:70a6082c1bf7 45
ShaneKirkbride 0:70a6082c1bf7 46 return packet;
ShaneKirkbride 0:70a6082c1bf7 47 } else if (packet->cmd == CMD_RESP_CB) {
ShaneKirkbride 0:70a6082c1bf7 48 FP<void, void*> *fp;
ShaneKirkbride 0:70a6082c1bf7 49 // callback reponse
ShaneKirkbride 0:70a6082c1bf7 50 _debug->printf("RESP_CB: 0x%x 0x%x \n\r", packet->value, packet->argc);
ShaneKirkbride 0:70a6082c1bf7 51
ShaneKirkbride 0:70a6082c1bf7 52 fp = (FP<void, void*>*)packet->value;
ShaneKirkbride 0:70a6082c1bf7 53 if (fp->attached()) {
ShaneKirkbride 0:70a6082c1bf7 54 STMClientResponse resp(packet);
ShaneKirkbride 0:70a6082c1bf7 55 (*fp)(&resp);
ShaneKirkbride 0:70a6082c1bf7 56 }
ShaneKirkbride 0:70a6082c1bf7 57 return NULL;
ShaneKirkbride 0:70a6082c1bf7 58 } else {
ShaneKirkbride 0:70a6082c1bf7 59 // command (NOT IMPLEMENTED)
ShaneKirkbride 0:70a6082c1bf7 60 _debug->printf("CMD 0x%x Value 0x%x ??\n\r", packet->cmd, packet->value);
ShaneKirkbride 0:70a6082c1bf7 61 return NULL;
ShaneKirkbride 0:70a6082c1bf7 62 }
ShaneKirkbride 0:70a6082c1bf7 63 }
ShaneKirkbride 0:70a6082c1bf7 64
ShaneKirkbride 0:70a6082c1bf7 65 // Read all characters available on the serial input and process any messages that arrive, but
ShaneKirkbride 0:70a6082c1bf7 66 // stop if a non-callback response comes in
ShaneKirkbride 0:70a6082c1bf7 67 STMClientPacket *STMClient::Process() {
ShaneKirkbride 0:70a6082c1bf7 68 while (_serial->readable()) {
ShaneKirkbride 0:70a6082c1bf7 69 //value =_serial->getc(rxBuffer, 5, eSerialCb, SERIAL_EVENT_RX_ALL, '$');
ShaneKirkbride 0:70a6082c1bf7 70 char character=_serial->getc();
ShaneKirkbride 0:70a6082c1bf7 71 //value = _serial->read();
ShaneKirkbride 0:70a6082c1bf7 72
ShaneKirkbride 0:70a6082c1bf7 73 if ((int)character == SLIP_ESC) {
ShaneKirkbride 0:70a6082c1bf7 74 _proto.isEsc = 1;
ShaneKirkbride 0:70a6082c1bf7 75 } else if ((int)character == SLIP_END) {
ShaneKirkbride 0:70a6082c1bf7 76 STMClientPacket *packet = _proto.dataLen >= 8 ? protoCompletedCb() : 0;
ShaneKirkbride 0:70a6082c1bf7 77 _proto.dataLen = 0;
ShaneKirkbride 0:70a6082c1bf7 78 _proto.isEsc = 0;
ShaneKirkbride 0:70a6082c1bf7 79 if (packet != NULL) return packet;
ShaneKirkbride 0:70a6082c1bf7 80 } else {
ShaneKirkbride 0:70a6082c1bf7 81 if (_proto.isEsc) {
ShaneKirkbride 0:70a6082c1bf7 82 if ((int)character == SLIP_ESC_END) character = SLIP_END;
ShaneKirkbride 0:70a6082c1bf7 83 if ((int)character == SLIP_ESC_ESC) character = SLIP_ESC;
ShaneKirkbride 0:70a6082c1bf7 84 _proto.isEsc = 0;
ShaneKirkbride 0:70a6082c1bf7 85 }
ShaneKirkbride 0:70a6082c1bf7 86 if (_proto.dataLen < _proto.bufSize) {
ShaneKirkbride 0:70a6082c1bf7 87 _proto.buf[_proto.dataLen++] = (int)character;
ShaneKirkbride 0:70a6082c1bf7 88 }
ShaneKirkbride 0:70a6082c1bf7 89 }
ShaneKirkbride 0:70a6082c1bf7 90 }
ShaneKirkbride 0:70a6082c1bf7 91 return NULL;
ShaneKirkbride 0:70a6082c1bf7 92 }
ShaneKirkbride 0:70a6082c1bf7 93
ShaneKirkbride 0:70a6082c1bf7 94 //===== Output
ShaneKirkbride 0:70a6082c1bf7 95
ShaneKirkbride 0:70a6082c1bf7 96 // Write a byte to the output stream and perform SLIP escaping
ShaneKirkbride 0:70a6082c1bf7 97 void STMClient::write(uint8_t data) {
ShaneKirkbride 0:70a6082c1bf7 98 switch (data) {
ShaneKirkbride 0:70a6082c1bf7 99 case SLIP_END:
ShaneKirkbride 0:70a6082c1bf7 100 _serial->putc(SLIP_ESC);
ShaneKirkbride 0:70a6082c1bf7 101 _serial->putc(SLIP_ESC_END);
ShaneKirkbride 0:70a6082c1bf7 102 break;
ShaneKirkbride 0:70a6082c1bf7 103 case SLIP_ESC:
ShaneKirkbride 0:70a6082c1bf7 104 _serial->putc(SLIP_ESC);
ShaneKirkbride 0:70a6082c1bf7 105 _serial->putc(SLIP_ESC_ESC);
ShaneKirkbride 0:70a6082c1bf7 106 break;
ShaneKirkbride 0:70a6082c1bf7 107 default:
ShaneKirkbride 0:70a6082c1bf7 108 _serial->putc(data);
ShaneKirkbride 0:70a6082c1bf7 109 }
ShaneKirkbride 0:70a6082c1bf7 110 }
ShaneKirkbride 0:70a6082c1bf7 111
ShaneKirkbride 0:70a6082c1bf7 112 // Write some bytes to the output stream
ShaneKirkbride 0:70a6082c1bf7 113 void STMClient::write(void* data, uint16_t len) {
ShaneKirkbride 0:70a6082c1bf7 114 uint8_t *d = (uint8_t*)data;
ShaneKirkbride 2:20ea1be14e4b 115 _debug->printf("Writing: 0x%x\n\r", (const char*)data);
ShaneKirkbride 0:70a6082c1bf7 116 while (len--)
ShaneKirkbride 2:20ea1be14e4b 117 {
ShaneKirkbride 0:70a6082c1bf7 118 write(*d++);
ShaneKirkbride 2:20ea1be14e4b 119 }
ShaneKirkbride 0:70a6082c1bf7 120 }
ShaneKirkbride 0:70a6082c1bf7 121
ShaneKirkbride 0:70a6082c1bf7 122 // Start a request. cmd=command, value=address of callback pointer or first arg,
ShaneKirkbride 0:70a6082c1bf7 123 // argc=additional argument count
ShaneKirkbride 0:70a6082c1bf7 124 void STMClient::Request(uint16_t cmd, uint32_t value, uint16_t argc) {
ShaneKirkbride 2:20ea1be14e4b 125 _debug->printf("Starting a request...\n\r");
ShaneKirkbride 2:20ea1be14e4b 126 wait(0.5);
ShaneKirkbride 0:70a6082c1bf7 127 crc = 0;
ShaneKirkbride 0:70a6082c1bf7 128 _serial->putc(SLIP_END);
ShaneKirkbride 0:70a6082c1bf7 129
ShaneKirkbride 0:70a6082c1bf7 130 write(&cmd, 2);
ShaneKirkbride 0:70a6082c1bf7 131 crc = crc16Data((unsigned const char*)&cmd, 2, crc);
ShaneKirkbride 0:70a6082c1bf7 132
ShaneKirkbride 0:70a6082c1bf7 133 write(&argc, 2);
ShaneKirkbride 0:70a6082c1bf7 134 crc = crc16Data((unsigned const char*)&argc, 2, crc);
ShaneKirkbride 0:70a6082c1bf7 135
ShaneKirkbride 0:70a6082c1bf7 136 write(&value, 4);
ShaneKirkbride 0:70a6082c1bf7 137 crc = crc16Data((unsigned const char*)&value, 4, crc);
ShaneKirkbride 0:70a6082c1bf7 138 }
ShaneKirkbride 0:70a6082c1bf7 139
ShaneKirkbride 0:70a6082c1bf7 140 // Append a block of data as an argument to the request
ShaneKirkbride 0:70a6082c1bf7 141 void STMClient::Request(const void* data, uint16_t len) {
ShaneKirkbride 0:70a6082c1bf7 142 uint8_t *d = (uint8_t*)data;
ShaneKirkbride 0:70a6082c1bf7 143
ShaneKirkbride 0:70a6082c1bf7 144 // write the length
ShaneKirkbride 0:70a6082c1bf7 145 write(&len, 2);
ShaneKirkbride 0:70a6082c1bf7 146 crc = crc16Data((unsigned const char*)&len, 2, crc);
ShaneKirkbride 0:70a6082c1bf7 147
ShaneKirkbride 0:70a6082c1bf7 148 // output the data
ShaneKirkbride 0:70a6082c1bf7 149 for (uint16_t l=len; l>0; l--) {
ShaneKirkbride 0:70a6082c1bf7 150 write(*d);
ShaneKirkbride 0:70a6082c1bf7 151 crc = crc16Add(*d, crc);
ShaneKirkbride 0:70a6082c1bf7 152 d++;
ShaneKirkbride 0:70a6082c1bf7 153 }
ShaneKirkbride 0:70a6082c1bf7 154
ShaneKirkbride 0:70a6082c1bf7 155 // output padding
ShaneKirkbride 0:70a6082c1bf7 156 uint16_t pad = (4-(len&3))&3;
ShaneKirkbride 0:70a6082c1bf7 157 uint8_t temp = 0;
ShaneKirkbride 0:70a6082c1bf7 158 while (pad--) {
ShaneKirkbride 0:70a6082c1bf7 159 write(temp);
ShaneKirkbride 0:70a6082c1bf7 160 crc = crc16Add(temp, crc);
ShaneKirkbride 0:70a6082c1bf7 161 }
ShaneKirkbride 0:70a6082c1bf7 162 }
ShaneKirkbride 2:20ea1be14e4b 163 /*
ShaneKirkbride 0:70a6082c1bf7 164 // Append a block of data located in flash as an argument to the request
ShaneKirkbride 2:20ea1be14e4b 165 void STMClient::Request(const __FlashStringHelper* data, uint16_t len) {
ShaneKirkbride 0:70a6082c1bf7 166 // write the length
ShaneKirkbride 0:70a6082c1bf7 167 write(&len, 2);
ShaneKirkbride 0:70a6082c1bf7 168 crc = crc16Data((unsigned const char*)&len, 2, crc);
ShaneKirkbride 0:70a6082c1bf7 169
ShaneKirkbride 0:70a6082c1bf7 170 // output the data
ShaneKirkbride 0:70a6082c1bf7 171 PGM_P p = reinterpret_cast<PGM_P>(data);
ShaneKirkbride 0:70a6082c1bf7 172 for (uint16_t l=len; l>0; l--) {
ShaneKirkbride 0:70a6082c1bf7 173 uint8_t c = pgm_read_byte(p++);
ShaneKirkbride 0:70a6082c1bf7 174 write(c);
ShaneKirkbride 0:70a6082c1bf7 175 crc = crc16Add(c, crc);
ShaneKirkbride 0:70a6082c1bf7 176 }
ShaneKirkbride 0:70a6082c1bf7 177
ShaneKirkbride 0:70a6082c1bf7 178 // output padding
ShaneKirkbride 0:70a6082c1bf7 179 uint16_t pad = (4-(len&3))&3;
ShaneKirkbride 0:70a6082c1bf7 180 uint8_t temp = 0;
ShaneKirkbride 0:70a6082c1bf7 181 while (pad--) {
ShaneKirkbride 0:70a6082c1bf7 182 write(temp);
ShaneKirkbride 0:70a6082c1bf7 183 crc = crc16Add(temp, crc);
ShaneKirkbride 0:70a6082c1bf7 184 }
ShaneKirkbride 0:70a6082c1bf7 185 }
ShaneKirkbride 0:70a6082c1bf7 186 */
ShaneKirkbride 0:70a6082c1bf7 187
ShaneKirkbride 0:70a6082c1bf7 188 // Append the final CRC to the request and finish the request
ShaneKirkbride 0:70a6082c1bf7 189 void STMClient::Request(void) {
ShaneKirkbride 0:70a6082c1bf7 190 write((uint8_t*)&crc, 2);
ShaneKirkbride 2:20ea1be14e4b 191
ShaneKirkbride 0:70a6082c1bf7 192 _serial->putc(SLIP_END);
ShaneKirkbride 0:70a6082c1bf7 193 }
ShaneKirkbride 0:70a6082c1bf7 194
ShaneKirkbride 0:70a6082c1bf7 195 //===== Initialization
ShaneKirkbride 0:70a6082c1bf7 196
ShaneKirkbride 0:70a6082c1bf7 197 void STMClient::init() {
ShaneKirkbride 0:70a6082c1bf7 198 _proto.buf = _protoBuf;
ShaneKirkbride 0:70a6082c1bf7 199 _proto.bufSize = sizeof(_protoBuf);
ShaneKirkbride 0:70a6082c1bf7 200 _proto.dataLen = 0;
ShaneKirkbride 0:70a6082c1bf7 201 _proto.isEsc = 0;
ShaneKirkbride 0:70a6082c1bf7 202 }
ShaneKirkbride 0:70a6082c1bf7 203
ShaneKirkbride 0:70a6082c1bf7 204 STMClient::STMClient(Serial* serial) :
ShaneKirkbride 0:70a6082c1bf7 205 _serial(serial) {
ShaneKirkbride 0:70a6082c1bf7 206 _debugEn = false;
ShaneKirkbride 0:70a6082c1bf7 207 init();
ShaneKirkbride 0:70a6082c1bf7 208 }
ShaneKirkbride 0:70a6082c1bf7 209
ShaneKirkbride 0:70a6082c1bf7 210 STMClient::STMClient(Serial* serial, Serial* debug) :
ShaneKirkbride 0:70a6082c1bf7 211 _debug(debug), _serial(serial) {
ShaneKirkbride 0:70a6082c1bf7 212 _debugEn = true;
ShaneKirkbride 0:70a6082c1bf7 213 init();
ShaneKirkbride 0:70a6082c1bf7 214 }
ShaneKirkbride 0:70a6082c1bf7 215
ShaneKirkbride 0:70a6082c1bf7 216 void STMClient::DBG(const char* info) {
ShaneKirkbride 0:70a6082c1bf7 217 if (_debugEn) _debug->printf(info);
ShaneKirkbride 0:70a6082c1bf7 218 }
ShaneKirkbride 0:70a6082c1bf7 219
ShaneKirkbride 0:70a6082c1bf7 220 //===== Responses
ShaneKirkbride 0:70a6082c1bf7 221
ShaneKirkbride 0:70a6082c1bf7 222 // Wait for a response for a given timeout
ShaneKirkbride 0:70a6082c1bf7 223 STMClientPacket *STMClient::WaitReturn(uint32_t timeout) {
ShaneKirkbride 0:70a6082c1bf7 224 uint32_t wait = millis();
ShaneKirkbride 0:70a6082c1bf7 225 while (millis() - wait < timeout) {
ShaneKirkbride 0:70a6082c1bf7 226 STMClientPacket *packet = Process();
ShaneKirkbride 0:70a6082c1bf7 227 if (packet != NULL) return packet;
ShaneKirkbride 0:70a6082c1bf7 228 }
ShaneKirkbride 0:70a6082c1bf7 229 return NULL;
ShaneKirkbride 0:70a6082c1bf7 230 }
ShaneKirkbride 0:70a6082c1bf7 231
ShaneKirkbride 0:70a6082c1bf7 232 //===== CRC hSTMper functions
ShaneKirkbride 0:70a6082c1bf7 233
ShaneKirkbride 0:70a6082c1bf7 234 uint16_t STMClient::crc16Add(unsigned char b, uint16_t acc)
ShaneKirkbride 0:70a6082c1bf7 235 {
ShaneKirkbride 0:70a6082c1bf7 236 acc ^= b;
ShaneKirkbride 0:70a6082c1bf7 237 acc = (acc >> 8) | (acc << 8);
ShaneKirkbride 0:70a6082c1bf7 238 acc ^= (acc & 0xff00) << 4;
ShaneKirkbride 0:70a6082c1bf7 239 acc ^= (acc >> 8) >> 4;
ShaneKirkbride 0:70a6082c1bf7 240 acc ^= (acc & 0xff00) >> 5;
ShaneKirkbride 0:70a6082c1bf7 241 return acc;
ShaneKirkbride 0:70a6082c1bf7 242 }
ShaneKirkbride 0:70a6082c1bf7 243
ShaneKirkbride 0:70a6082c1bf7 244 uint16_t STMClient::crc16Data(const unsigned char *data, uint16_t len, uint16_t acc)
ShaneKirkbride 0:70a6082c1bf7 245 {
ShaneKirkbride 0:70a6082c1bf7 246 for (uint16_t i=0; i<len; i++)
ShaneKirkbride 0:70a6082c1bf7 247 acc = crc16Add(*data++, acc);
ShaneKirkbride 0:70a6082c1bf7 248 return acc;
ShaneKirkbride 0:70a6082c1bf7 249 }
ShaneKirkbride 0:70a6082c1bf7 250
ShaneKirkbride 0:70a6082c1bf7 251 //===== Basic requests built into STMClient
ShaneKirkbride 0:70a6082c1bf7 252
ShaneKirkbride 0:70a6082c1bf7 253 bool STMClient::Sync(uint32_t timeout) {
ShaneKirkbride 0:70a6082c1bf7 254 //_debug->printf("syncing...");
ShaneKirkbride 0:70a6082c1bf7 255 wait(0.5);
ShaneKirkbride 0:70a6082c1bf7 256 // send sync request
ShaneKirkbride 0:70a6082c1bf7 257 Request(CMD_SYNC, (uint32_t)&wifiCb, 0);
ShaneKirkbride 0:70a6082c1bf7 258 Request();
ShaneKirkbride 0:70a6082c1bf7 259
ShaneKirkbride 0:70a6082c1bf7 260 // empty the response queue hoping to find the wifiCb address
ShaneKirkbride 0:70a6082c1bf7 261 STMClientPacket *packet;
ShaneKirkbride 0:70a6082c1bf7 262 while ((packet = WaitReturn(timeout)) != NULL) {
ShaneKirkbride 0:70a6082c1bf7 263 if (packet->value == (uint32_t)&wifiCb)
ShaneKirkbride 0:70a6082c1bf7 264 {
ShaneKirkbride 0:70a6082c1bf7 265 // _debug->printf("SYNC!");
ShaneKirkbride 2:20ea1be14e4b 266 wait(0.5);
ShaneKirkbride 0:70a6082c1bf7 267 return true;
ShaneKirkbride 0:70a6082c1bf7 268 }
ShaneKirkbride 0:70a6082c1bf7 269 _debug->printf("BAD: %s /n/r", packet->value);
ShaneKirkbride 0:70a6082c1bf7 270 }
ShaneKirkbride 0:70a6082c1bf7 271
ShaneKirkbride 0:70a6082c1bf7 272 // doesn't look like we got a real response
ShaneKirkbride 0:70a6082c1bf7 273 return false;
ShaneKirkbride 0:70a6082c1bf7 274 }
ShaneKirkbride 0:70a6082c1bf7 275
ShaneKirkbride 0:70a6082c1bf7 276 void STMClient::GetWifiStatus(void) {
ShaneKirkbride 0:70a6082c1bf7 277 Request(CMD_WIFI_STATUS, 0, 0);
ShaneKirkbride 0:70a6082c1bf7 278 Request();
ShaneKirkbride 0:70a6082c1bf7 279 }