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:
Tue Aug 09 22:42:31 2016 +0000
Revision:
4:31bed73a0d08
Parent:
3:8ed85d940c4c
Child:
8:6a3b7c5d9ba7
added interrupt driven interface;

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 3:8ed85d940c4c 36 wait(0.25);
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 4:31bed73a0d08 68 int value;
ShaneKirkbride 0:70a6082c1bf7 69 while (_serial->readable()) {
ShaneKirkbride 4:31bed73a0d08 70 value = _serial->getc();
ShaneKirkbride 4:31bed73a0d08 71 if (value == SLIP_ESC) {
ShaneKirkbride 0:70a6082c1bf7 72 _proto.isEsc = 1;
ShaneKirkbride 4:31bed73a0d08 73 } else if (value == SLIP_END) {
ShaneKirkbride 0:70a6082c1bf7 74 STMClientPacket *packet = _proto.dataLen >= 8 ? protoCompletedCb() : 0;
ShaneKirkbride 0:70a6082c1bf7 75 _proto.dataLen = 0;
ShaneKirkbride 0:70a6082c1bf7 76 _proto.isEsc = 0;
ShaneKirkbride 0:70a6082c1bf7 77 if (packet != NULL) return packet;
ShaneKirkbride 0:70a6082c1bf7 78 } else {
ShaneKirkbride 0:70a6082c1bf7 79 if (_proto.isEsc) {
ShaneKirkbride 4:31bed73a0d08 80 if (value == SLIP_ESC_END) value = SLIP_END;
ShaneKirkbride 4:31bed73a0d08 81 if (value == SLIP_ESC_ESC) value = SLIP_ESC;
ShaneKirkbride 0:70a6082c1bf7 82 _proto.isEsc = 0;
ShaneKirkbride 0:70a6082c1bf7 83 }
ShaneKirkbride 0:70a6082c1bf7 84 if (_proto.dataLen < _proto.bufSize) {
ShaneKirkbride 4:31bed73a0d08 85 _proto.buf[_proto.dataLen++] = value;
ShaneKirkbride 0:70a6082c1bf7 86 }
ShaneKirkbride 0:70a6082c1bf7 87 }
ShaneKirkbride 0:70a6082c1bf7 88 }
ShaneKirkbride 0:70a6082c1bf7 89 return NULL;
ShaneKirkbride 0:70a6082c1bf7 90 }
ShaneKirkbride 0:70a6082c1bf7 91
ShaneKirkbride 0:70a6082c1bf7 92 //===== Output
ShaneKirkbride 0:70a6082c1bf7 93
ShaneKirkbride 0:70a6082c1bf7 94 // Write a byte to the output stream and perform SLIP escaping
ShaneKirkbride 0:70a6082c1bf7 95 void STMClient::write(uint8_t data) {
ShaneKirkbride 0:70a6082c1bf7 96 switch (data) {
ShaneKirkbride 0:70a6082c1bf7 97 case SLIP_END:
ShaneKirkbride 0:70a6082c1bf7 98 _serial->putc(SLIP_ESC);
ShaneKirkbride 0:70a6082c1bf7 99 _serial->putc(SLIP_ESC_END);
ShaneKirkbride 0:70a6082c1bf7 100 break;
ShaneKirkbride 0:70a6082c1bf7 101 case SLIP_ESC:
ShaneKirkbride 0:70a6082c1bf7 102 _serial->putc(SLIP_ESC);
ShaneKirkbride 0:70a6082c1bf7 103 _serial->putc(SLIP_ESC_ESC);
ShaneKirkbride 0:70a6082c1bf7 104 break;
ShaneKirkbride 0:70a6082c1bf7 105 default:
ShaneKirkbride 0:70a6082c1bf7 106 _serial->putc(data);
ShaneKirkbride 0:70a6082c1bf7 107 }
ShaneKirkbride 0:70a6082c1bf7 108 }
ShaneKirkbride 0:70a6082c1bf7 109
ShaneKirkbride 0:70a6082c1bf7 110 // Write some bytes to the output stream
ShaneKirkbride 0:70a6082c1bf7 111 void STMClient::write(void* data, uint16_t len) {
ShaneKirkbride 0:70a6082c1bf7 112 uint8_t *d = (uint8_t*)data;
ShaneKirkbride 3:8ed85d940c4c 113 //_debug->printf("Writing: 0x%x\n\r", (const char*)data);
ShaneKirkbride 0:70a6082c1bf7 114 while (len--)
ShaneKirkbride 2:20ea1be14e4b 115 {
ShaneKirkbride 0:70a6082c1bf7 116 write(*d++);
ShaneKirkbride 2:20ea1be14e4b 117 }
ShaneKirkbride 0:70a6082c1bf7 118 }
ShaneKirkbride 0:70a6082c1bf7 119
ShaneKirkbride 0:70a6082c1bf7 120 // Start a request. cmd=command, value=address of callback pointer or first arg,
ShaneKirkbride 0:70a6082c1bf7 121 // argc=additional argument count
ShaneKirkbride 0:70a6082c1bf7 122 void STMClient::Request(uint16_t cmd, uint32_t value, uint16_t argc) {
ShaneKirkbride 3:8ed85d940c4c 123 //_debug->printf("Starting a request...\n\r");
ShaneKirkbride 3:8ed85d940c4c 124 wait(0.25);
ShaneKirkbride 0:70a6082c1bf7 125 crc = 0;
ShaneKirkbride 0:70a6082c1bf7 126 _serial->putc(SLIP_END);
ShaneKirkbride 0:70a6082c1bf7 127
ShaneKirkbride 0:70a6082c1bf7 128 write(&cmd, 2);
ShaneKirkbride 0:70a6082c1bf7 129 crc = crc16Data((unsigned const char*)&cmd, 2, crc);
ShaneKirkbride 0:70a6082c1bf7 130
ShaneKirkbride 0:70a6082c1bf7 131 write(&argc, 2);
ShaneKirkbride 0:70a6082c1bf7 132 crc = crc16Data((unsigned const char*)&argc, 2, crc);
ShaneKirkbride 0:70a6082c1bf7 133
ShaneKirkbride 0:70a6082c1bf7 134 write(&value, 4);
ShaneKirkbride 0:70a6082c1bf7 135 crc = crc16Data((unsigned const char*)&value, 4, crc);
ShaneKirkbride 0:70a6082c1bf7 136 }
ShaneKirkbride 0:70a6082c1bf7 137
ShaneKirkbride 0:70a6082c1bf7 138 // Append a block of data as an argument to the request
ShaneKirkbride 0:70a6082c1bf7 139 void STMClient::Request(const void* data, uint16_t len) {
ShaneKirkbride 0:70a6082c1bf7 140 uint8_t *d = (uint8_t*)data;
ShaneKirkbride 0:70a6082c1bf7 141
ShaneKirkbride 0:70a6082c1bf7 142 // write the length
ShaneKirkbride 0:70a6082c1bf7 143 write(&len, 2);
ShaneKirkbride 0:70a6082c1bf7 144 crc = crc16Data((unsigned const char*)&len, 2, crc);
ShaneKirkbride 0:70a6082c1bf7 145
ShaneKirkbride 0:70a6082c1bf7 146 // output the data
ShaneKirkbride 0:70a6082c1bf7 147 for (uint16_t l=len; l>0; l--) {
ShaneKirkbride 0:70a6082c1bf7 148 write(*d);
ShaneKirkbride 0:70a6082c1bf7 149 crc = crc16Add(*d, crc);
ShaneKirkbride 0:70a6082c1bf7 150 d++;
ShaneKirkbride 0:70a6082c1bf7 151 }
ShaneKirkbride 0:70a6082c1bf7 152
ShaneKirkbride 0:70a6082c1bf7 153 // output padding
ShaneKirkbride 0:70a6082c1bf7 154 uint16_t pad = (4-(len&3))&3;
ShaneKirkbride 0:70a6082c1bf7 155 uint8_t temp = 0;
ShaneKirkbride 0:70a6082c1bf7 156 while (pad--) {
ShaneKirkbride 0:70a6082c1bf7 157 write(temp);
ShaneKirkbride 0:70a6082c1bf7 158 crc = crc16Add(temp, crc);
ShaneKirkbride 0:70a6082c1bf7 159 }
ShaneKirkbride 0:70a6082c1bf7 160 }
ShaneKirkbride 2:20ea1be14e4b 161 /*
ShaneKirkbride 0:70a6082c1bf7 162 // Append a block of data located in flash as an argument to the request
ShaneKirkbride 2:20ea1be14e4b 163 void STMClient::Request(const __FlashStringHelper* data, uint16_t len) {
ShaneKirkbride 0:70a6082c1bf7 164 // write the length
ShaneKirkbride 0:70a6082c1bf7 165 write(&len, 2);
ShaneKirkbride 0:70a6082c1bf7 166 crc = crc16Data((unsigned const char*)&len, 2, crc);
ShaneKirkbride 0:70a6082c1bf7 167
ShaneKirkbride 0:70a6082c1bf7 168 // output the data
ShaneKirkbride 0:70a6082c1bf7 169 PGM_P p = reinterpret_cast<PGM_P>(data);
ShaneKirkbride 0:70a6082c1bf7 170 for (uint16_t l=len; l>0; l--) {
ShaneKirkbride 0:70a6082c1bf7 171 uint8_t c = pgm_read_byte(p++);
ShaneKirkbride 0:70a6082c1bf7 172 write(c);
ShaneKirkbride 0:70a6082c1bf7 173 crc = crc16Add(c, crc);
ShaneKirkbride 0:70a6082c1bf7 174 }
ShaneKirkbride 0:70a6082c1bf7 175
ShaneKirkbride 0:70a6082c1bf7 176 // output padding
ShaneKirkbride 0:70a6082c1bf7 177 uint16_t pad = (4-(len&3))&3;
ShaneKirkbride 0:70a6082c1bf7 178 uint8_t temp = 0;
ShaneKirkbride 0:70a6082c1bf7 179 while (pad--) {
ShaneKirkbride 0:70a6082c1bf7 180 write(temp);
ShaneKirkbride 0:70a6082c1bf7 181 crc = crc16Add(temp, crc);
ShaneKirkbride 0:70a6082c1bf7 182 }
ShaneKirkbride 0:70a6082c1bf7 183 }
ShaneKirkbride 0:70a6082c1bf7 184 */
ShaneKirkbride 0:70a6082c1bf7 185
ShaneKirkbride 0:70a6082c1bf7 186 // Append the final CRC to the request and finish the request
ShaneKirkbride 0:70a6082c1bf7 187 void STMClient::Request(void) {
ShaneKirkbride 0:70a6082c1bf7 188 write((uint8_t*)&crc, 2);
ShaneKirkbride 2:20ea1be14e4b 189
ShaneKirkbride 0:70a6082c1bf7 190 _serial->putc(SLIP_END);
ShaneKirkbride 0:70a6082c1bf7 191 }
ShaneKirkbride 0:70a6082c1bf7 192
ShaneKirkbride 0:70a6082c1bf7 193 //===== Initialization
ShaneKirkbride 0:70a6082c1bf7 194
ShaneKirkbride 0:70a6082c1bf7 195 void STMClient::init() {
ShaneKirkbride 0:70a6082c1bf7 196 _proto.buf = _protoBuf;
ShaneKirkbride 0:70a6082c1bf7 197 _proto.bufSize = sizeof(_protoBuf);
ShaneKirkbride 0:70a6082c1bf7 198 _proto.dataLen = 0;
ShaneKirkbride 0:70a6082c1bf7 199 _proto.isEsc = 0;
ShaneKirkbride 0:70a6082c1bf7 200 }
ShaneKirkbride 0:70a6082c1bf7 201
ShaneKirkbride 0:70a6082c1bf7 202 STMClient::STMClient(Serial* serial) :
ShaneKirkbride 0:70a6082c1bf7 203 _serial(serial) {
ShaneKirkbride 0:70a6082c1bf7 204 _debugEn = false;
ShaneKirkbride 0:70a6082c1bf7 205 init();
ShaneKirkbride 0:70a6082c1bf7 206 }
ShaneKirkbride 0:70a6082c1bf7 207
ShaneKirkbride 0:70a6082c1bf7 208 STMClient::STMClient(Serial* serial, Serial* debug) :
ShaneKirkbride 0:70a6082c1bf7 209 _debug(debug), _serial(serial) {
ShaneKirkbride 0:70a6082c1bf7 210 _debugEn = true;
ShaneKirkbride 0:70a6082c1bf7 211 init();
ShaneKirkbride 0:70a6082c1bf7 212 }
ShaneKirkbride 0:70a6082c1bf7 213
ShaneKirkbride 0:70a6082c1bf7 214 void STMClient::DBG(const char* info) {
ShaneKirkbride 0:70a6082c1bf7 215 if (_debugEn) _debug->printf(info);
ShaneKirkbride 0:70a6082c1bf7 216 }
ShaneKirkbride 0:70a6082c1bf7 217
ShaneKirkbride 0:70a6082c1bf7 218 //===== Responses
ShaneKirkbride 0:70a6082c1bf7 219
ShaneKirkbride 0:70a6082c1bf7 220 // Wait for a response for a given timeout
ShaneKirkbride 0:70a6082c1bf7 221 STMClientPacket *STMClient::WaitReturn(uint32_t timeout) {
ShaneKirkbride 0:70a6082c1bf7 222 uint32_t wait = millis();
ShaneKirkbride 0:70a6082c1bf7 223 while (millis() - wait < timeout) {
ShaneKirkbride 0:70a6082c1bf7 224 STMClientPacket *packet = Process();
ShaneKirkbride 0:70a6082c1bf7 225 if (packet != NULL) return packet;
ShaneKirkbride 0:70a6082c1bf7 226 }
ShaneKirkbride 0:70a6082c1bf7 227 return NULL;
ShaneKirkbride 0:70a6082c1bf7 228 }
ShaneKirkbride 0:70a6082c1bf7 229
ShaneKirkbride 0:70a6082c1bf7 230 //===== CRC hSTMper functions
ShaneKirkbride 0:70a6082c1bf7 231
ShaneKirkbride 0:70a6082c1bf7 232 uint16_t STMClient::crc16Add(unsigned char b, uint16_t acc)
ShaneKirkbride 0:70a6082c1bf7 233 {
ShaneKirkbride 0:70a6082c1bf7 234 acc ^= b;
ShaneKirkbride 0:70a6082c1bf7 235 acc = (acc >> 8) | (acc << 8);
ShaneKirkbride 0:70a6082c1bf7 236 acc ^= (acc & 0xff00) << 4;
ShaneKirkbride 0:70a6082c1bf7 237 acc ^= (acc >> 8) >> 4;
ShaneKirkbride 0:70a6082c1bf7 238 acc ^= (acc & 0xff00) >> 5;
ShaneKirkbride 0:70a6082c1bf7 239 return acc;
ShaneKirkbride 0:70a6082c1bf7 240 }
ShaneKirkbride 0:70a6082c1bf7 241
ShaneKirkbride 0:70a6082c1bf7 242 uint16_t STMClient::crc16Data(const unsigned char *data, uint16_t len, uint16_t acc)
ShaneKirkbride 0:70a6082c1bf7 243 {
ShaneKirkbride 0:70a6082c1bf7 244 for (uint16_t i=0; i<len; i++)
ShaneKirkbride 0:70a6082c1bf7 245 acc = crc16Add(*data++, acc);
ShaneKirkbride 0:70a6082c1bf7 246 return acc;
ShaneKirkbride 0:70a6082c1bf7 247 }
ShaneKirkbride 0:70a6082c1bf7 248
ShaneKirkbride 0:70a6082c1bf7 249 //===== Basic requests built into STMClient
ShaneKirkbride 0:70a6082c1bf7 250
ShaneKirkbride 0:70a6082c1bf7 251 bool STMClient::Sync(uint32_t timeout) {
ShaneKirkbride 0:70a6082c1bf7 252 //_debug->printf("syncing...");
ShaneKirkbride 0:70a6082c1bf7 253 wait(0.5);
ShaneKirkbride 0:70a6082c1bf7 254 // send sync request
ShaneKirkbride 0:70a6082c1bf7 255 Request(CMD_SYNC, (uint32_t)&wifiCb, 0);
ShaneKirkbride 0:70a6082c1bf7 256 Request();
ShaneKirkbride 0:70a6082c1bf7 257
ShaneKirkbride 0:70a6082c1bf7 258 // empty the response queue hoping to find the wifiCb address
ShaneKirkbride 0:70a6082c1bf7 259 STMClientPacket *packet;
ShaneKirkbride 0:70a6082c1bf7 260 while ((packet = WaitReturn(timeout)) != NULL) {
ShaneKirkbride 0:70a6082c1bf7 261 if (packet->value == (uint32_t)&wifiCb)
ShaneKirkbride 0:70a6082c1bf7 262 {
ShaneKirkbride 0:70a6082c1bf7 263 // _debug->printf("SYNC!");
ShaneKirkbride 2:20ea1be14e4b 264 wait(0.5);
ShaneKirkbride 0:70a6082c1bf7 265 return true;
ShaneKirkbride 0:70a6082c1bf7 266 }
ShaneKirkbride 0:70a6082c1bf7 267 _debug->printf("BAD: %s /n/r", packet->value);
ShaneKirkbride 0:70a6082c1bf7 268 }
ShaneKirkbride 0:70a6082c1bf7 269
ShaneKirkbride 0:70a6082c1bf7 270 // doesn't look like we got a real response
ShaneKirkbride 0:70a6082c1bf7 271 return false;
ShaneKirkbride 0:70a6082c1bf7 272 }
ShaneKirkbride 0:70a6082c1bf7 273
ShaneKirkbride 0:70a6082c1bf7 274 void STMClient::GetWifiStatus(void) {
ShaneKirkbride 0:70a6082c1bf7 275 Request(CMD_WIFI_STATUS, 0, 0);
ShaneKirkbride 0:70a6082c1bf7 276 Request();
ShaneKirkbride 0:70a6082c1bf7 277 }