Ningkai Wu / Mbed 2 deprecated test_spi_ble

Dependencies:   mbed-rtos mbed

Committer:
wninghj
Date:
Thu Apr 05 21:26:10 2018 +0000
Revision:
0:39b7f3158ebe
TEAM12 DJ;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wninghj 0:39b7f3158ebe 1 #include "mbed.h"
wninghj 0:39b7f3158ebe 2 #include "rtos.h"
wninghj 0:39b7f3158ebe 3 #include "sdep.h"
wninghj 0:39b7f3158ebe 4 #include "Adafruit_FIFO.h"
wninghj 0:39b7f3158ebe 5 #include <stdio.h>
wninghj 0:39b7f3158ebe 6
wninghj 0:39b7f3158ebe 7 #define BLUEFRUIT_MODE_COMMAND HIGH
wninghj 0:39b7f3158ebe 8 #define BLUEFRUIT_MODE_DATA LOW
wninghj 0:39b7f3158ebe 9 #define BLE_BUFSIZE 4*SDEP_MAX_PACKETSIZE
wninghj 0:39b7f3158ebe 10
wninghj 0:39b7f3158ebe 11
wninghj 0:39b7f3158ebe 12 #define SPI_IGNORED_BYTE 0xFEu /**< SPI default character. Character clocked out in case of an ignored transaction. */
wninghj 0:39b7f3158ebe 13 #define SPI_OVERREAD_BYTE 0xFFu /**< SPI over-read character. Character clocked out after an over-read of the transmit buffer. */
wninghj 0:39b7f3158ebe 14 #define SPI_DEFAULT_DELAY_US 50
wninghj 0:39b7f3158ebe 15
wninghj 0:39b7f3158ebe 16 DigitalOut myled(LED1);
wninghj 0:39b7f3158ebe 17
wninghj 0:39b7f3158ebe 18 Serial pc(USBTX,USBRX);
wninghj 0:39b7f3158ebe 19
wninghj 0:39b7f3158ebe 20 SPI spi(p5, p6, p7); // mosi, miso, sclk
wninghj 0:39b7f3158ebe 21
wninghj 0:39b7f3158ebe 22 DigitalOut cs(p21);
wninghj 0:39b7f3158ebe 23 DigitalIn m_irq_pin(p22);
wninghj 0:39b7f3158ebe 24 DigitalOut ble_reset(p23);
wninghj 0:39b7f3158ebe 25
wninghj 0:39b7f3158ebe 26 void enable_spi() {
wninghj 0:39b7f3158ebe 27 cs = 0;
wninghj 0:39b7f3158ebe 28 }
wninghj 0:39b7f3158ebe 29
wninghj 0:39b7f3158ebe 30 void disable_spi() {
wninghj 0:39b7f3158ebe 31 cs = 1;
wninghj 0:39b7f3158ebe 32 }
wninghj 0:39b7f3158ebe 33
wninghj 0:39b7f3158ebe 34 // TX
wninghj 0:39b7f3158ebe 35 uint8_t m_tx_buffer[SDEP_MAX_PACKETSIZE] = {0};
wninghj 0:39b7f3158ebe 36 uint8_t m_tx_count = 0;
wninghj 0:39b7f3158ebe 37
wninghj 0:39b7f3158ebe 38 // RX
wninghj 0:39b7f3158ebe 39 uint8_t m_rx_buffer[BLE_BUFSIZE * 2] = {0};
wninghj 0:39b7f3158ebe 40 Adafruit_FIFO m_rx_fifo(m_rx_buffer, sizeof(m_rx_buffer), 1, true);
wninghj 0:39b7f3158ebe 41
wninghj 0:39b7f3158ebe 42 enum BLE_MODE {
wninghj 0:39b7f3158ebe 43 COMMAND = 0,
wninghj 0:39b7f3158ebe 44 DATA
wninghj 0:39b7f3158ebe 45 };
wninghj 0:39b7f3158ebe 46
wninghj 0:39b7f3158ebe 47 BLE_MODE bleMode = COMMAND;
wninghj 0:39b7f3158ebe 48
wninghj 0:39b7f3158ebe 49
wninghj 0:39b7f3158ebe 50 // prototypes
wninghj 0:39b7f3158ebe 51 void spixfer(void *buff, size_t len);
wninghj 0:39b7f3158ebe 52 uint8_t spixfer(uint8_t x);
wninghj 0:39b7f3158ebe 53 bool bleGetResponse(void);
wninghj 0:39b7f3158ebe 54 bool sendPacket(uint16_t command, const uint8_t* buf, uint8_t count, uint8_t more_data);
wninghj 0:39b7f3158ebe 55 size_t bleWriteChar(uint8_t c);
wninghj 0:39b7f3158ebe 56 void bleWrite(char *cmd);
wninghj 0:39b7f3158ebe 57
wninghj 0:39b7f3158ebe 58
wninghj 0:39b7f3158ebe 59 volatile unsigned long _millis = 0;
wninghj 0:39b7f3158ebe 60 unsigned long millis(void) {
wninghj 0:39b7f3158ebe 61 return _millis;
wninghj 0:39b7f3158ebe 62 }
wninghj 0:39b7f3158ebe 63
wninghj 0:39b7f3158ebe 64
wninghj 0:39b7f3158ebe 65 class TimeoutTimer
wninghj 0:39b7f3158ebe 66 {
wninghj 0:39b7f3158ebe 67 private:
wninghj 0:39b7f3158ebe 68 uint32_t start;
wninghj 0:39b7f3158ebe 69 uint32_t interval;
wninghj 0:39b7f3158ebe 70
wninghj 0:39b7f3158ebe 71 public:
wninghj 0:39b7f3158ebe 72 TimeoutTimer() { start = millis(); interval = 0; }
wninghj 0:39b7f3158ebe 73 TimeoutTimer(uint32_t msec) { set(msec); }
wninghj 0:39b7f3158ebe 74
wninghj 0:39b7f3158ebe 75 void set(uint32_t msec) { start = millis(); interval = msec; }
wninghj 0:39b7f3158ebe 76 bool expired(void) const { return (millis() - start) >= interval; }
wninghj 0:39b7f3158ebe 77 void restart(void) { start = millis(); }
wninghj 0:39b7f3158ebe 78 void reset(void) { start += interval; } // used for periodic invoke to prevent drift
wninghj 0:39b7f3158ebe 79 };
wninghj 0:39b7f3158ebe 80
wninghj 0:39b7f3158ebe 81
wninghj 0:39b7f3158ebe 82 uint16_t word(uint8_t h, uint8_t l) {
wninghj 0:39b7f3158ebe 83 uint16_t res = h;
wninghj 0:39b7f3158ebe 84 res <<= 8;
wninghj 0:39b7f3158ebe 85 res |= l;
wninghj 0:39b7f3158ebe 86 return res;
wninghj 0:39b7f3158ebe 87 }
wninghj 0:39b7f3158ebe 88
wninghj 0:39b7f3158ebe 89
wninghj 0:39b7f3158ebe 90 uint32_t _timeout = 250;
wninghj 0:39b7f3158ebe 91
wninghj 0:39b7f3158ebe 92
wninghj 0:39b7f3158ebe 93 bool bleGetPacket(sdepMsgResponse_t* p_response)
wninghj 0:39b7f3158ebe 94 {
wninghj 0:39b7f3158ebe 95 // Wait until IRQ is asserted, double timeout since some commands take long time to start responding
wninghj 0:39b7f3158ebe 96 TimeoutTimer tt(2*_timeout);
wninghj 0:39b7f3158ebe 97
wninghj 0:39b7f3158ebe 98 while ( !m_irq_pin ) {
wninghj 0:39b7f3158ebe 99 if (tt.expired()) return false;
wninghj 0:39b7f3158ebe 100 }
wninghj 0:39b7f3158ebe 101
wninghj 0:39b7f3158ebe 102 sdepMsgHeader_t* p_header = &p_response->header;
wninghj 0:39b7f3158ebe 103
wninghj 0:39b7f3158ebe 104 enable_spi();
wninghj 0:39b7f3158ebe 105
wninghj 0:39b7f3158ebe 106 tt.set(_timeout);
wninghj 0:39b7f3158ebe 107
wninghj 0:39b7f3158ebe 108 do {
wninghj 0:39b7f3158ebe 109 if ( tt.expired() ) break;
wninghj 0:39b7f3158ebe 110
wninghj 0:39b7f3158ebe 111 p_header->msg_type = spixfer(0xff);
wninghj 0:39b7f3158ebe 112
wninghj 0:39b7f3158ebe 113 if (p_header->msg_type == SPI_IGNORED_BYTE)
wninghj 0:39b7f3158ebe 114 {
wninghj 0:39b7f3158ebe 115 // Bluefruit may not be ready
wninghj 0:39b7f3158ebe 116 // Disable & Re-enable CS with a bit of delay for Bluefruit to ready itself
wninghj 0:39b7f3158ebe 117 disable_spi();
wninghj 0:39b7f3158ebe 118 wait_us(50);
wninghj 0:39b7f3158ebe 119 enable_spi();
wninghj 0:39b7f3158ebe 120 }
wninghj 0:39b7f3158ebe 121 else if (p_header->msg_type == SPI_OVERREAD_BYTE)
wninghj 0:39b7f3158ebe 122 {
wninghj 0:39b7f3158ebe 123 // IRQ may not be pulled down by Bluefruit when returning all data in previous transfer.
wninghj 0:39b7f3158ebe 124 // This could happen when Arduino MCU is running at fast rate comparing to Bluefruit's MCU,
wninghj 0:39b7f3158ebe 125 // causing an SPI_OVERREAD_BYTE to be returned at stage.
wninghj 0:39b7f3158ebe 126 //
wninghj 0:39b7f3158ebe 127 // Walkaround: Disable & Re-enable CS with a bit of delay and keep waiting
wninghj 0:39b7f3158ebe 128 // TODO IRQ is supposed to be OFF then ON, it is better to use GPIO trigger interrupt.
wninghj 0:39b7f3158ebe 129
wninghj 0:39b7f3158ebe 130 disable_spi();
wninghj 0:39b7f3158ebe 131 // wait for the clock to be enabled..
wninghj 0:39b7f3158ebe 132 // while (!digitalRead(m_irq_pin)) {
wninghj 0:39b7f3158ebe 133 // if ( tt.expired() ) break;
wninghj 0:39b7f3158ebe 134 // }
wninghj 0:39b7f3158ebe 135 // if (!digitalRead(m_irq_pin)) break;
wninghj 0:39b7f3158ebe 136 wait_us(50);
wninghj 0:39b7f3158ebe 137 enable_spi();
wninghj 0:39b7f3158ebe 138 }
wninghj 0:39b7f3158ebe 139 } while (p_header->msg_type == SPI_IGNORED_BYTE || p_header->msg_type == SPI_OVERREAD_BYTE);
wninghj 0:39b7f3158ebe 140
wninghj 0:39b7f3158ebe 141 bool result=false;
wninghj 0:39b7f3158ebe 142
wninghj 0:39b7f3158ebe 143 // Not a loop, just a way to avoid goto with error handling
wninghj 0:39b7f3158ebe 144 do
wninghj 0:39b7f3158ebe 145 {
wninghj 0:39b7f3158ebe 146 // Look for the header
wninghj 0:39b7f3158ebe 147 // note that we should always get the right header at this point, and not doing so will really mess up things.
wninghj 0:39b7f3158ebe 148 while ( p_header->msg_type != SDEP_MSGTYPE_RESPONSE && p_header->msg_type != SDEP_MSGTYPE_ERROR && !tt.expired() )
wninghj 0:39b7f3158ebe 149 {
wninghj 0:39b7f3158ebe 150 p_header->msg_type = spixfer(0xff);
wninghj 0:39b7f3158ebe 151 }
wninghj 0:39b7f3158ebe 152
wninghj 0:39b7f3158ebe 153 if ( tt.expired() ) break;
wninghj 0:39b7f3158ebe 154
wninghj 0:39b7f3158ebe 155 memset( (&p_header->msg_type)+1, 0xff, sizeof(sdepMsgHeader_t) - 1);
wninghj 0:39b7f3158ebe 156 spixfer((&p_header->msg_type)+1, sizeof(sdepMsgHeader_t) - 1);
wninghj 0:39b7f3158ebe 157
wninghj 0:39b7f3158ebe 158 // Command is 16-bit at odd address, may have alignment issue with 32-bit chip
wninghj 0:39b7f3158ebe 159 uint16_t cmd_id = word(p_header->cmd_id_high, p_header->cmd_id_low);
wninghj 0:39b7f3158ebe 160
wninghj 0:39b7f3158ebe 161 // Error Message Response
wninghj 0:39b7f3158ebe 162 if ( p_header->msg_type == SDEP_MSGTYPE_ERROR ) break;
wninghj 0:39b7f3158ebe 163
wninghj 0:39b7f3158ebe 164 // Invalid command
wninghj 0:39b7f3158ebe 165 if (!(cmd_id == SDEP_CMDTYPE_AT_WRAPPER ||
wninghj 0:39b7f3158ebe 166 cmd_id == SDEP_CMDTYPE_BLE_UARTTX ||
wninghj 0:39b7f3158ebe 167 cmd_id == SDEP_CMDTYPE_BLE_UARTRX) )
wninghj 0:39b7f3158ebe 168 {
wninghj 0:39b7f3158ebe 169 break;
wninghj 0:39b7f3158ebe 170 }
wninghj 0:39b7f3158ebe 171
wninghj 0:39b7f3158ebe 172 // Invalid length
wninghj 0:39b7f3158ebe 173 if(p_header->length > SDEP_MAX_PACKETSIZE) break;
wninghj 0:39b7f3158ebe 174
wninghj 0:39b7f3158ebe 175 // read payload
wninghj 0:39b7f3158ebe 176 memset(p_response->payload, 0xff, p_header->length);
wninghj 0:39b7f3158ebe 177 spixfer(p_response->payload, p_header->length);
wninghj 0:39b7f3158ebe 178
wninghj 0:39b7f3158ebe 179 result = true;
wninghj 0:39b7f3158ebe 180 }while(0);
wninghj 0:39b7f3158ebe 181
wninghj 0:39b7f3158ebe 182 disable_spi();
wninghj 0:39b7f3158ebe 183
wninghj 0:39b7f3158ebe 184 return result;
wninghj 0:39b7f3158ebe 185 }
wninghj 0:39b7f3158ebe 186
wninghj 0:39b7f3158ebe 187
wninghj 0:39b7f3158ebe 188 /******************************************************************************/
wninghj 0:39b7f3158ebe 189 /*!
wninghj 0:39b7f3158ebe 190
wninghj 0:39b7f3158ebe 191 */
wninghj 0:39b7f3158ebe 192 /******************************************************************************/
wninghj 0:39b7f3158ebe 193 void spixfer(void *buff, size_t len) {
wninghj 0:39b7f3158ebe 194 uint8_t *p = (uint8_t *)buff;
wninghj 0:39b7f3158ebe 195 while (len--) {
wninghj 0:39b7f3158ebe 196 p[0] = spixfer(p[0]);
wninghj 0:39b7f3158ebe 197 p++;
wninghj 0:39b7f3158ebe 198 }
wninghj 0:39b7f3158ebe 199 }
wninghj 0:39b7f3158ebe 200
wninghj 0:39b7f3158ebe 201 /******************************************************************************/
wninghj 0:39b7f3158ebe 202 /*!
wninghj 0:39b7f3158ebe 203
wninghj 0:39b7f3158ebe 204 */
wninghj 0:39b7f3158ebe 205 /******************************************************************************/
wninghj 0:39b7f3158ebe 206 uint8_t spixfer(uint8_t x) {
wninghj 0:39b7f3158ebe 207 return spi.write(x);
wninghj 0:39b7f3158ebe 208 }
wninghj 0:39b7f3158ebe 209
wninghj 0:39b7f3158ebe 210
wninghj 0:39b7f3158ebe 211 /******************************************************************************/
wninghj 0:39b7f3158ebe 212 /*!
wninghj 0:39b7f3158ebe 213 @brief Try to perform an full AT response transfer from Bluefruit, or execute
wninghj 0:39b7f3158ebe 214 as many SPI transaction as internal FIFO can hold up.
wninghj 0:39b7f3158ebe 215
wninghj 0:39b7f3158ebe 216 @note If verbose is enabled, all the received data will be print to Serial
wninghj 0:39b7f3158ebe 217
wninghj 0:39b7f3158ebe 218 @return
wninghj 0:39b7f3158ebe 219 - true : if succeeded
wninghj 0:39b7f3158ebe 220 - false : if failed
wninghj 0:39b7f3158ebe 221 */
wninghj 0:39b7f3158ebe 222 /******************************************************************************/
wninghj 0:39b7f3158ebe 223 bool bleGetResponse(void)
wninghj 0:39b7f3158ebe 224 {
wninghj 0:39b7f3158ebe 225 // Try to read data from Bluefruit if there is enough room in the fifo
wninghj 0:39b7f3158ebe 226 while ( m_rx_fifo.remaining() >= SDEP_MAX_PACKETSIZE )
wninghj 0:39b7f3158ebe 227 {
wninghj 0:39b7f3158ebe 228 // Get a SDEP packet
wninghj 0:39b7f3158ebe 229 sdepMsgResponse_t msg_response;
wninghj 0:39b7f3158ebe 230 memset(&msg_response, 0, sizeof(sdepMsgResponse_t));
wninghj 0:39b7f3158ebe 231
wninghj 0:39b7f3158ebe 232 if ( !bleGetPacket(&msg_response) ) return false;
wninghj 0:39b7f3158ebe 233
wninghj 0:39b7f3158ebe 234 // Write to fifo
wninghj 0:39b7f3158ebe 235 if ( msg_response.header.length > 0)
wninghj 0:39b7f3158ebe 236 {
wninghj 0:39b7f3158ebe 237 m_rx_fifo.write_n(msg_response.payload, msg_response.header.length);
wninghj 0:39b7f3158ebe 238 }
wninghj 0:39b7f3158ebe 239
wninghj 0:39b7f3158ebe 240 // No more packet data
wninghj 0:39b7f3158ebe 241 if ( !msg_response.header.more_data ) break;
wninghj 0:39b7f3158ebe 242
wninghj 0:39b7f3158ebe 243 // It takes a bit since all Data received to IRQ to get LOW
wninghj 0:39b7f3158ebe 244 // May need to delay a bit for it to be stable before the next try
wninghj 0:39b7f3158ebe 245 wait_us(50);
wninghj 0:39b7f3158ebe 246 }
wninghj 0:39b7f3158ebe 247
wninghj 0:39b7f3158ebe 248 return true;
wninghj 0:39b7f3158ebe 249 }
wninghj 0:39b7f3158ebe 250
wninghj 0:39b7f3158ebe 251
wninghj 0:39b7f3158ebe 252 void bleWrite(char *cmd) {
wninghj 0:39b7f3158ebe 253 while (*cmd != '\0') {
wninghj 0:39b7f3158ebe 254 bleWriteChar((uint8_t) *cmd);
wninghj 0:39b7f3158ebe 255 cmd += 1;
wninghj 0:39b7f3158ebe 256 }
wninghj 0:39b7f3158ebe 257 }
wninghj 0:39b7f3158ebe 258
wninghj 0:39b7f3158ebe 259
wninghj 0:39b7f3158ebe 260 /******************************************************************************/
wninghj 0:39b7f3158ebe 261 /*!
wninghj 0:39b7f3158ebe 262 @brief Check if the response from the previous command is ready
wninghj 0:39b7f3158ebe 263
wninghj 0:39b7f3158ebe 264 @return 'true' if a response is ready, otherwise 'false'
wninghj 0:39b7f3158ebe 265 */
wninghj 0:39b7f3158ebe 266 /******************************************************************************/
wninghj 0:39b7f3158ebe 267 int bleAvailable(void)
wninghj 0:39b7f3158ebe 268 {
wninghj 0:39b7f3158ebe 269 if (! m_rx_fifo.empty() ) {
wninghj 0:39b7f3158ebe 270 return m_rx_fifo.count();
wninghj 0:39b7f3158ebe 271 }
wninghj 0:39b7f3158ebe 272
wninghj 0:39b7f3158ebe 273 if ( bleMode == DATA )
wninghj 0:39b7f3158ebe 274 {
wninghj 0:39b7f3158ebe 275 // DATA Mode: query for BLE UART data
wninghj 0:39b7f3158ebe 276 sendPacket(SDEP_CMDTYPE_BLE_UARTRX, NULL, 0, 0);
wninghj 0:39b7f3158ebe 277
wninghj 0:39b7f3158ebe 278 // Waiting to get response from Bluefruit
wninghj 0:39b7f3158ebe 279 bleGetResponse();
wninghj 0:39b7f3158ebe 280
wninghj 0:39b7f3158ebe 281 return m_rx_fifo.count();
wninghj 0:39b7f3158ebe 282 }else{
wninghj 0:39b7f3158ebe 283 return m_irq_pin;
wninghj 0:39b7f3158ebe 284 }
wninghj 0:39b7f3158ebe 285 }
wninghj 0:39b7f3158ebe 286
wninghj 0:39b7f3158ebe 287 /******************************************************************************/
wninghj 0:39b7f3158ebe 288 /*!
wninghj 0:39b7f3158ebe 289 @brief Get a byte from response data, perform SPI transaction if needed
wninghj 0:39b7f3158ebe 290
wninghj 0:39b7f3158ebe 291 @return -1 if no data is available
wninghj 0:39b7f3158ebe 292 */
wninghj 0:39b7f3158ebe 293 /******************************************************************************/
wninghj 0:39b7f3158ebe 294 int bleRead(void)
wninghj 0:39b7f3158ebe 295 {
wninghj 0:39b7f3158ebe 296 uint8_t ch;
wninghj 0:39b7f3158ebe 297
wninghj 0:39b7f3158ebe 298 // try to grab from buffer first...
wninghj 0:39b7f3158ebe 299 if (!m_rx_fifo.empty()) {
wninghj 0:39b7f3158ebe 300 m_rx_fifo.read(&ch);
wninghj 0:39b7f3158ebe 301 return (int)ch;
wninghj 0:39b7f3158ebe 302 }
wninghj 0:39b7f3158ebe 303
wninghj 0:39b7f3158ebe 304 if ( bleMode == DATA )
wninghj 0:39b7f3158ebe 305 {
wninghj 0:39b7f3158ebe 306 // DATA Mode: query for BLE UART data
wninghj 0:39b7f3158ebe 307 sendPacket(SDEP_CMDTYPE_BLE_UARTRX, NULL, 0, 0);
wninghj 0:39b7f3158ebe 308
wninghj 0:39b7f3158ebe 309 // Waiting to get response from Bluefruit
wninghj 0:39b7f3158ebe 310 bleGetResponse();
wninghj 0:39b7f3158ebe 311 }else
wninghj 0:39b7f3158ebe 312 {
wninghj 0:39b7f3158ebe 313 // COMMAND Mode: Only read data from Bluefruit if IRQ is raised
wninghj 0:39b7f3158ebe 314 if ( m_irq_pin ) bleGetResponse();
wninghj 0:39b7f3158ebe 315 }
wninghj 0:39b7f3158ebe 316
wninghj 0:39b7f3158ebe 317 return m_rx_fifo.read(&ch) ? ((int) ch) : EOF;
wninghj 0:39b7f3158ebe 318
wninghj 0:39b7f3158ebe 319 }
wninghj 0:39b7f3158ebe 320
wninghj 0:39b7f3158ebe 321
wninghj 0:39b7f3158ebe 322 uint16_t bleReadLine(char * buf, uint16_t bufsize)
wninghj 0:39b7f3158ebe 323 {
wninghj 0:39b7f3158ebe 324 uint16_t timeout = 1000 * 10;
wninghj 0:39b7f3158ebe 325 bool multiline = false;
wninghj 0:39b7f3158ebe 326 uint16_t replyidx = 0;
wninghj 0:39b7f3158ebe 327
wninghj 0:39b7f3158ebe 328 while (timeout--) {
wninghj 0:39b7f3158ebe 329 while(bleAvailable()) {
wninghj 0:39b7f3158ebe 330 //pc.printf("SPI: Available\n");
wninghj 0:39b7f3158ebe 331 char c = bleRead();
wninghj 0:39b7f3158ebe 332 //pc.printf("SPI: %d\n", (int) c);
wninghj 0:39b7f3158ebe 333 //SerialDebug.println(c);
wninghj 0:39b7f3158ebe 334
wninghj 0:39b7f3158ebe 335 if (c == '\r') continue;
wninghj 0:39b7f3158ebe 336
wninghj 0:39b7f3158ebe 337 if (c == '\n') {
wninghj 0:39b7f3158ebe 338 // the first '\n' is ignored
wninghj 0:39b7f3158ebe 339 if (replyidx == 0) continue;
wninghj 0:39b7f3158ebe 340
wninghj 0:39b7f3158ebe 341 if (!multiline) {
wninghj 0:39b7f3158ebe 342 timeout = 0;
wninghj 0:39b7f3158ebe 343 break;
wninghj 0:39b7f3158ebe 344 }
wninghj 0:39b7f3158ebe 345 }
wninghj 0:39b7f3158ebe 346 buf[replyidx] = c;
wninghj 0:39b7f3158ebe 347 replyidx++;
wninghj 0:39b7f3158ebe 348
wninghj 0:39b7f3158ebe 349 // Buffer is full
wninghj 0:39b7f3158ebe 350 if (replyidx >= bufsize) {
wninghj 0:39b7f3158ebe 351 //if (_verbose) { SerialDebug.println("*overflow*"); } // for my debuggin' only!
wninghj 0:39b7f3158ebe 352 timeout = 0;
wninghj 0:39b7f3158ebe 353 break;
wninghj 0:39b7f3158ebe 354 }
wninghj 0:39b7f3158ebe 355 }
wninghj 0:39b7f3158ebe 356
wninghj 0:39b7f3158ebe 357 // delay if needed
wninghj 0:39b7f3158ebe 358 if (timeout) {
wninghj 0:39b7f3158ebe 359 Thread::wait(1);
wninghj 0:39b7f3158ebe 360 }
wninghj 0:39b7f3158ebe 361 }
wninghj 0:39b7f3158ebe 362
wninghj 0:39b7f3158ebe 363 buf[replyidx] = 0; // null term
wninghj 0:39b7f3158ebe 364
wninghj 0:39b7f3158ebe 365 return replyidx;
wninghj 0:39b7f3158ebe 366 }
wninghj 0:39b7f3158ebe 367
wninghj 0:39b7f3158ebe 368 bool waitForOK(void)
wninghj 0:39b7f3158ebe 369 {
wninghj 0:39b7f3158ebe 370 // Use temp buffer to avoid overwrite returned result if any
wninghj 0:39b7f3158ebe 371 char tempbuf[BLE_BUFSIZE + 1];
wninghj 0:39b7f3158ebe 372
wninghj 0:39b7f3158ebe 373 while (bleReadLine(tempbuf, BLE_BUFSIZE)) {
wninghj 0:39b7f3158ebe 374 // pc.printf("SPI: %s\n", tempbuf);
wninghj 0:39b7f3158ebe 375 if (strcmp(tempbuf, "OK") == 0) return true;
wninghj 0:39b7f3158ebe 376 if (strcmp(tempbuf, "ERROR") == 0) return false;
wninghj 0:39b7f3158ebe 377 }
wninghj 0:39b7f3158ebe 378 return false;
wninghj 0:39b7f3158ebe 379 }
wninghj 0:39b7f3158ebe 380
wninghj 0:39b7f3158ebe 381 bool sendATCommand(char *cmd) {
wninghj 0:39b7f3158ebe 382 bleMode = COMMAND;
wninghj 0:39b7f3158ebe 383 bleWrite(cmd);
wninghj 0:39b7f3158ebe 384 bleWrite("\r\n");
wninghj 0:39b7f3158ebe 385 bool result = waitForOK();
wninghj 0:39b7f3158ebe 386 bleMode = DATA;
wninghj 0:39b7f3158ebe 387 return result;
wninghj 0:39b7f3158ebe 388 }
wninghj 0:39b7f3158ebe 389
wninghj 0:39b7f3158ebe 390 bool sendCommandCheckOK(char *cmd) {
wninghj 0:39b7f3158ebe 391 return sendATCommand(cmd);
wninghj 0:39b7f3158ebe 392 }
wninghj 0:39b7f3158ebe 393
wninghj 0:39b7f3158ebe 394 // =============================================================================
wninghj 0:39b7f3158ebe 395
wninghj 0:39b7f3158ebe 396 void flush(void)
wninghj 0:39b7f3158ebe 397 {
wninghj 0:39b7f3158ebe 398 m_rx_fifo.clear();
wninghj 0:39b7f3158ebe 399 }
wninghj 0:39b7f3158ebe 400
wninghj 0:39b7f3158ebe 401 uint8_t highByte(uint16_t x) {
wninghj 0:39b7f3158ebe 402 return (uint8_t) (x >> 8);
wninghj 0:39b7f3158ebe 403 }
wninghj 0:39b7f3158ebe 404
wninghj 0:39b7f3158ebe 405 uint8_t lowByte(uint16_t x) {
wninghj 0:39b7f3158ebe 406 return (uint8_t) (x & 0xff);
wninghj 0:39b7f3158ebe 407 }
wninghj 0:39b7f3158ebe 408
wninghj 0:39b7f3158ebe 409 bool sendPacket(uint16_t command, const uint8_t* buf, uint8_t count, uint8_t more_data) {
wninghj 0:39b7f3158ebe 410 // flush old response before sending the new command
wninghj 0:39b7f3158ebe 411 if (more_data == 0) flush();
wninghj 0:39b7f3158ebe 412
wninghj 0:39b7f3158ebe 413 sdepMsgCommand_t msgCmd;
wninghj 0:39b7f3158ebe 414
wninghj 0:39b7f3158ebe 415 msgCmd.header.msg_type = SDEP_MSGTYPE_COMMAND;
wninghj 0:39b7f3158ebe 416 msgCmd.header.cmd_id_high = highByte(command);
wninghj 0:39b7f3158ebe 417 msgCmd.header.cmd_id_low = lowByte(command);
wninghj 0:39b7f3158ebe 418 msgCmd.header.length = count;
wninghj 0:39b7f3158ebe 419 msgCmd.header.more_data = (count == SDEP_MAX_PACKETSIZE) ? more_data : 0;
wninghj 0:39b7f3158ebe 420
wninghj 0:39b7f3158ebe 421 // Copy payload
wninghj 0:39b7f3158ebe 422 if ( buf != NULL && count > 0) memcpy(msgCmd.payload, buf, count);
wninghj 0:39b7f3158ebe 423
wninghj 0:39b7f3158ebe 424 enable_spi();
wninghj 0:39b7f3158ebe 425
wninghj 0:39b7f3158ebe 426 TimeoutTimer tt(_timeout);
wninghj 0:39b7f3158ebe 427
wninghj 0:39b7f3158ebe 428 // Bluefruit may not be ready
wninghj 0:39b7f3158ebe 429 while ( ( spixfer(msgCmd.header.msg_type) == SPI_IGNORED_BYTE ) && !tt.expired() )
wninghj 0:39b7f3158ebe 430 {
wninghj 0:39b7f3158ebe 431 // Disable & Re-enable CS with a bit of delay for Bluefruit to ready itself
wninghj 0:39b7f3158ebe 432 disable_spi();
wninghj 0:39b7f3158ebe 433 wait_us(SPI_DEFAULT_DELAY_US);
wninghj 0:39b7f3158ebe 434 enable_spi();
wninghj 0:39b7f3158ebe 435 }
wninghj 0:39b7f3158ebe 436
wninghj 0:39b7f3158ebe 437 bool result = !tt.expired();
wninghj 0:39b7f3158ebe 438 if ( result )
wninghj 0:39b7f3158ebe 439 {
wninghj 0:39b7f3158ebe 440 // transfer the rest of the data
wninghj 0:39b7f3158ebe 441 spixfer((void*) (((uint8_t*)&msgCmd) +1), sizeof(sdepMsgHeader_t)+count-1);
wninghj 0:39b7f3158ebe 442 }
wninghj 0:39b7f3158ebe 443
wninghj 0:39b7f3158ebe 444 disable_spi();
wninghj 0:39b7f3158ebe 445
wninghj 0:39b7f3158ebe 446 return result;
wninghj 0:39b7f3158ebe 447 }
wninghj 0:39b7f3158ebe 448
wninghj 0:39b7f3158ebe 449 size_t bleWriteChar(uint8_t c) {
wninghj 0:39b7f3158ebe 450 if (bleMode == DATA)
wninghj 0:39b7f3158ebe 451 {
wninghj 0:39b7f3158ebe 452 sendPacket(SDEP_CMDTYPE_BLE_UARTTX, &c, 1, 0);
wninghj 0:39b7f3158ebe 453 bleGetResponse();
wninghj 0:39b7f3158ebe 454 return 1;
wninghj 0:39b7f3158ebe 455 }
wninghj 0:39b7f3158ebe 456
wninghj 0:39b7f3158ebe 457 // Following code handle BLUEFRUIT_MODE_COMMAND
wninghj 0:39b7f3158ebe 458
wninghj 0:39b7f3158ebe 459 // Final packet due to \r or \n terminator
wninghj 0:39b7f3158ebe 460 if (c == '\r' || c == '\n')
wninghj 0:39b7f3158ebe 461 {
wninghj 0:39b7f3158ebe 462 if (m_tx_count > 0)
wninghj 0:39b7f3158ebe 463 {
wninghj 0:39b7f3158ebe 464 bool result = sendPacket(SDEP_CMDTYPE_AT_WRAPPER, m_tx_buffer, m_tx_count, 0);
wninghj 0:39b7f3158ebe 465 m_tx_count = 0;
wninghj 0:39b7f3158ebe 466 if (!result) {
wninghj 0:39b7f3158ebe 467 return 0;
wninghj 0:39b7f3158ebe 468 }
wninghj 0:39b7f3158ebe 469 }
wninghj 0:39b7f3158ebe 470 }
wninghj 0:39b7f3158ebe 471 // More than max packet buffered --> send with more_data = 1
wninghj 0:39b7f3158ebe 472 else if (m_tx_count == SDEP_MAX_PACKETSIZE)
wninghj 0:39b7f3158ebe 473 {
wninghj 0:39b7f3158ebe 474 bool result = sendPacket(SDEP_CMDTYPE_AT_WRAPPER, m_tx_buffer, m_tx_count, 1);
wninghj 0:39b7f3158ebe 475
wninghj 0:39b7f3158ebe 476 m_tx_buffer[0] = c;
wninghj 0:39b7f3158ebe 477 m_tx_count = 1;
wninghj 0:39b7f3158ebe 478 if (!result) {
wninghj 0:39b7f3158ebe 479 return 0;
wninghj 0:39b7f3158ebe 480 }
wninghj 0:39b7f3158ebe 481 }
wninghj 0:39b7f3158ebe 482 // Not enough data, continue to buffer
wninghj 0:39b7f3158ebe 483 else
wninghj 0:39b7f3158ebe 484 {
wninghj 0:39b7f3158ebe 485 m_tx_buffer[m_tx_count++] = c;
wninghj 0:39b7f3158ebe 486 }
wninghj 0:39b7f3158ebe 487 return 1;
wninghj 0:39b7f3158ebe 488 }
wninghj 0:39b7f3158ebe 489
wninghj 0:39b7f3158ebe 490 int32_t readline_parseInt(void)
wninghj 0:39b7f3158ebe 491 {
wninghj 0:39b7f3158ebe 492 char buffer[101] = { 0 };
wninghj 0:39b7f3158ebe 493 uint16_t len = bleReadLine(buffer, 100);
wninghj 0:39b7f3158ebe 494 if (len == 0) return 0;
wninghj 0:39b7f3158ebe 495
wninghj 0:39b7f3158ebe 496 // also parsed hex number e.g 0xADAF
wninghj 0:39b7f3158ebe 497 int32_t val = strtol(buffer, NULL, 0);
wninghj 0:39b7f3158ebe 498
wninghj 0:39b7f3158ebe 499 return val;
wninghj 0:39b7f3158ebe 500 }
wninghj 0:39b7f3158ebe 501
wninghj 0:39b7f3158ebe 502 bool send_arg_get_resp(int32_t *reply) {
wninghj 0:39b7f3158ebe 503 bleWrite("\r\n"); // execute command
wninghj 0:39b7f3158ebe 504
wninghj 0:39b7f3158ebe 505 // parse integer response if required
wninghj 0:39b7f3158ebe 506 if (reply)
wninghj 0:39b7f3158ebe 507 {
wninghj 0:39b7f3158ebe 508 (*reply) = readline_parseInt();
wninghj 0:39b7f3158ebe 509 }
wninghj 0:39b7f3158ebe 510
wninghj 0:39b7f3158ebe 511 // check OK or ERROR status
wninghj 0:39b7f3158ebe 512 return waitForOK();
wninghj 0:39b7f3158ebe 513 }
wninghj 0:39b7f3158ebe 514
wninghj 0:39b7f3158ebe 515 int32_t sendATCommandIntReply(char *cmd) {
wninghj 0:39b7f3158ebe 516 int32_t reply = 0;
wninghj 0:39b7f3158ebe 517 BLE_MODE current_mode = bleMode;
wninghj 0:39b7f3158ebe 518
wninghj 0:39b7f3158ebe 519 // switch mode if necessary to execute command
wninghj 0:39b7f3158ebe 520 bleMode = COMMAND;
wninghj 0:39b7f3158ebe 521
wninghj 0:39b7f3158ebe 522 // Execute command with parameter and get response
wninghj 0:39b7f3158ebe 523 bleWrite(cmd);
wninghj 0:39b7f3158ebe 524 send_arg_get_resp(&reply);
wninghj 0:39b7f3158ebe 525
wninghj 0:39b7f3158ebe 526 // switch back if necessary
wninghj 0:39b7f3158ebe 527 if ( current_mode == DATA ) bleMode = DATA;
wninghj 0:39b7f3158ebe 528 return reply;
wninghj 0:39b7f3158ebe 529 }
wninghj 0:39b7f3158ebe 530
wninghj 0:39b7f3158ebe 531 bool sendInitializePattern() {
wninghj 0:39b7f3158ebe 532 return sendPacket(SDEP_CMDTYPE_INITIALIZE, NULL, 0, 0);
wninghj 0:39b7f3158ebe 533 }
wninghj 0:39b7f3158ebe 534
wninghj 0:39b7f3158ebe 535 bool isBLEConnected() {
wninghj 0:39b7f3158ebe 536 int32_t connected = 0;
wninghj 0:39b7f3158ebe 537 connected = sendATCommandIntReply("AT+GAPGETCONN");
wninghj 0:39b7f3158ebe 538 return connected;
wninghj 0:39b7f3158ebe 539 }
wninghj 0:39b7f3158ebe 540
wninghj 0:39b7f3158ebe 541
wninghj 0:39b7f3158ebe 542 void timer_function_millis(void const *n) {
wninghj 0:39b7f3158ebe 543 _millis += 1;
wninghj 0:39b7f3158ebe 544 }
wninghj 0:39b7f3158ebe 545
wninghj 0:39b7f3158ebe 546 int main() {
wninghj 0:39b7f3158ebe 547 // timer to bump _millis
wninghj 0:39b7f3158ebe 548 RtosTimer millis_timer(timer_function_millis, osTimerPeriodic, (void *)0);
wninghj 0:39b7f3158ebe 549 millis_timer.start(1);
wninghj 0:39b7f3158ebe 550
wninghj 0:39b7f3158ebe 551 pc.baud(115200);
wninghj 0:39b7f3158ebe 552 spi.format(8, 0);
wninghj 0:39b7f3158ebe 553 spi.frequency(4000000);
wninghj 0:39b7f3158ebe 554
wninghj 0:39b7f3158ebe 555 pc.printf("Prepare to initiaize BLE\n");
wninghj 0:39b7f3158ebe 556
wninghj 0:39b7f3158ebe 557 // initialize BLE
wninghj 0:39b7f3158ebe 558 cs = 1;
wninghj 0:39b7f3158ebe 559 if (!sendInitializePattern()) pc.printf("BLE Init Failed\n");
wninghj 0:39b7f3158ebe 560 ble_reset = 1;
wninghj 0:39b7f3158ebe 561 ble_reset = 0;
wninghj 0:39b7f3158ebe 562 Thread::wait(10);
wninghj 0:39b7f3158ebe 563 ble_reset = 1;
wninghj 0:39b7f3158ebe 564 Thread::wait(500);
wninghj 0:39b7f3158ebe 565 cs = 1;
wninghj 0:39b7f3158ebe 566
wninghj 0:39b7f3158ebe 567 pc.printf("Set BLE Name\n");
wninghj 0:39b7f3158ebe 568
wninghj 0:39b7f3158ebe 569 // change name
wninghj 0:39b7f3158ebe 570 if (!sendCommandCheckOK("AT+GAPDEVNAME=AdafruitDJ")) {
wninghj 0:39b7f3158ebe 571 pc.printf("Could not set device name.\n");
wninghj 0:39b7f3158ebe 572 }
wninghj 0:39b7f3158ebe 573
wninghj 0:39b7f3158ebe 574 // wait until connected
wninghj 0:39b7f3158ebe 575 while (!isBLEConnected()) {
wninghj 0:39b7f3158ebe 576 Thread::wait(100);
wninghj 0:39b7f3158ebe 577 }
wninghj 0:39b7f3158ebe 578
wninghj 0:39b7f3158ebe 579 pc.printf("Ready\n");
wninghj 0:39b7f3158ebe 580
wninghj 0:39b7f3158ebe 581 Thread::wait(1000);
wninghj 0:39b7f3158ebe 582
wninghj 0:39b7f3158ebe 583 int i = 0;
wninghj 0:39b7f3158ebe 584 while (true) {
wninghj 0:39b7f3158ebe 585 bleMode = DATA;
wninghj 0:39b7f3158ebe 586 // send character
wninghj 0:39b7f3158ebe 587 char str[40] = { 0 };
wninghj 0:39b7f3158ebe 588 sprintf(str, "Hello DJ %d\r\n", i);
wninghj 0:39b7f3158ebe 589 bleWrite(str);
wninghj 0:39b7f3158ebe 590 Thread::wait(1000);
wninghj 0:39b7f3158ebe 591 pc.printf("Send\n");
wninghj 0:39b7f3158ebe 592 i += 1;
wninghj 0:39b7f3158ebe 593 }
wninghj 0:39b7f3158ebe 594
wninghj 0:39b7f3158ebe 595 Thread::wait(osWaitForever);
wninghj 0:39b7f3158ebe 596 }