Easily add all supported connectivity methods to your mbed OS project

Dependencies:   type-yd-driver

Committer:
MACRUM
Date:
Wed Jul 12 10:52:58 2017 +0000
Revision:
0:615f90842ce8
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MACRUM 0:615f90842ce8 1 /*** Mbed Includes ***/
MACRUM 0:615f90842ce8 2 #include "SimpleSpirit1.h"
MACRUM 0:615f90842ce8 3 #include "radio_spi.h"
MACRUM 0:615f90842ce8 4
MACRUM 0:615f90842ce8 5 #define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_3)
MACRUM 0:615f90842ce8 6
MACRUM 0:615f90842ce8 7 static uint16_t last_state;
MACRUM 0:615f90842ce8 8 #define SPIRIT1_STATUS() ((last_state = (uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS)
MACRUM 0:615f90842ce8 9
MACRUM 0:615f90842ce8 10 #define XO_ON (0x1)
MACRUM 0:615f90842ce8 11
MACRUM 0:615f90842ce8 12 #define BUSYWAIT_UNTIL(cond, millisecs) \
MACRUM 0:615f90842ce8 13 do { \
MACRUM 0:615f90842ce8 14 uint32_t start = us_ticker_read(); \
MACRUM 0:615f90842ce8 15 while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U)); \
MACRUM 0:615f90842ce8 16 } while(0)
MACRUM 0:615f90842ce8 17
MACRUM 0:615f90842ce8 18 #define st_lib_spirit_irqs SpiritIrqs
MACRUM 0:615f90842ce8 19
MACRUM 0:615f90842ce8 20 #define STATE_TIMEOUT (100)
MACRUM 0:615f90842ce8 21
MACRUM 0:615f90842ce8 22 // betzw: switching force & back from standby is on some devices quite unstable
MACRUM 0:615f90842ce8 23 #define USE_STANDBY_STATE
MACRUM 0:615f90842ce8 24
MACRUM 0:615f90842ce8 25 /*** Class Implementation ***/
MACRUM 0:615f90842ce8 26 /** Static Class Variables **/
MACRUM 0:615f90842ce8 27 SimpleSpirit1 *SimpleSpirit1::_singleton = NULL;
MACRUM 0:615f90842ce8 28
MACRUM 0:615f90842ce8 29 /** Constructor **/
MACRUM 0:615f90842ce8 30 SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
MACRUM 0:615f90842ce8 31 PinName irq, PinName cs, PinName sdn,
MACRUM 0:615f90842ce8 32 PinName led) :
MACRUM 0:615f90842ce8 33 _spi(mosi, miso, sclk),
MACRUM 0:615f90842ce8 34 _irq(irq),
MACRUM 0:615f90842ce8 35 _chip_select(cs),
MACRUM 0:615f90842ce8 36 _shut_down(sdn),
MACRUM 0:615f90842ce8 37 _led(led),
MACRUM 0:615f90842ce8 38 _current_irq_callback(),
MACRUM 0:615f90842ce8 39 _rx_receiving_timeout()
MACRUM 0:615f90842ce8 40 {
MACRUM 0:615f90842ce8 41 }
MACRUM 0:615f90842ce8 42
MACRUM 0:615f90842ce8 43 /** Init Function **/
MACRUM 0:615f90842ce8 44 void SimpleSpirit1::init() {
MACRUM 0:615f90842ce8 45 /* reset irq disable counter and irq callback & disable irq */
MACRUM 0:615f90842ce8 46 _nr_of_irq_disables = 0;
MACRUM 0:615f90842ce8 47 disable_spirit_irq();
MACRUM 0:615f90842ce8 48
MACRUM 0:615f90842ce8 49 /* unselect chip */
MACRUM 0:615f90842ce8 50 chip_unselect();
MACRUM 0:615f90842ce8 51
MACRUM 0:615f90842ce8 52 /* configure spi */
MACRUM 0:615f90842ce8 53 _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
MACRUM 0:615f90842ce8 54 _spi.frequency(10000000); // 10MHz (i.e. max speed allowed for Spirit1)
MACRUM 0:615f90842ce8 55
MACRUM 0:615f90842ce8 56 /* install irq handler */
MACRUM 0:615f90842ce8 57 _irq.mode(PullUp);
MACRUM 0:615f90842ce8 58 _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler));
MACRUM 0:615f90842ce8 59
MACRUM 0:615f90842ce8 60 /* init cube vars */
MACRUM 0:615f90842ce8 61 spirit_on = OFF;
MACRUM 0:615f90842ce8 62 last_rssi = 0 ; //MGR
MACRUM 0:615f90842ce8 63 last_sqi = 0 ; //MGR
MACRUM 0:615f90842ce8 64
MACRUM 0:615f90842ce8 65 /* set frequencies */
MACRUM 0:615f90842ce8 66 radio_set_xtal_freq(XTAL_FREQUENCY);
MACRUM 0:615f90842ce8 67 mgmt_set_freq_base((uint32_t)BASE_FREQUENCY);
MACRUM 0:615f90842ce8 68
MACRUM 0:615f90842ce8 69 /* restart board */
MACRUM 0:615f90842ce8 70 enter_shutdown();
MACRUM 0:615f90842ce8 71 exit_shutdown();
MACRUM 0:615f90842ce8 72
MACRUM 0:615f90842ce8 73 /* soft core reset */
MACRUM 0:615f90842ce8 74 cmd_strobe(SPIRIT1_STROBE_SRES);
MACRUM 0:615f90842ce8 75
MACRUM 0:615f90842ce8 76 /* Configures the SPIRIT1 radio part */
MACRUM 0:615f90842ce8 77 SRadioInit x_radio_init = {
MACRUM 0:615f90842ce8 78 XTAL_OFFSET_PPM,
MACRUM 0:615f90842ce8 79 (uint32_t)BASE_FREQUENCY,
MACRUM 0:615f90842ce8 80 (uint32_t)CHANNEL_SPACE,
MACRUM 0:615f90842ce8 81 CHANNEL_NUMBER,
MACRUM 0:615f90842ce8 82 MODULATION_SELECT,
MACRUM 0:615f90842ce8 83 DATARATE,
MACRUM 0:615f90842ce8 84 (uint32_t)FREQ_DEVIATION,
MACRUM 0:615f90842ce8 85 (uint32_t)BANDWIDTH
MACRUM 0:615f90842ce8 86 };
MACRUM 0:615f90842ce8 87 radio_init(&x_radio_init);
MACRUM 0:615f90842ce8 88 radio_set_pa_level_dbm(0,POWER_DBM);
MACRUM 0:615f90842ce8 89 radio_set_pa_level_max_index(0);
MACRUM 0:615f90842ce8 90
MACRUM 0:615f90842ce8 91 /* Configures the SPIRIT1 packet handler part*/
MACRUM 0:615f90842ce8 92 PktBasicInit x_basic_init = {
MACRUM 0:615f90842ce8 93 PREAMBLE_LENGTH,
MACRUM 0:615f90842ce8 94 SYNC_LENGTH,
MACRUM 0:615f90842ce8 95 SYNC_WORD,
MACRUM 0:615f90842ce8 96 LENGTH_TYPE,
MACRUM 0:615f90842ce8 97 LENGTH_WIDTH,
MACRUM 0:615f90842ce8 98 CRC_MODE,
MACRUM 0:615f90842ce8 99 CONTROL_LENGTH,
MACRUM 0:615f90842ce8 100 EN_ADDRESS,
MACRUM 0:615f90842ce8 101 EN_FEC,
MACRUM 0:615f90842ce8 102 EN_WHITENING
MACRUM 0:615f90842ce8 103 };
MACRUM 0:615f90842ce8 104 pkt_basic_init(&x_basic_init);
MACRUM 0:615f90842ce8 105
MACRUM 0:615f90842ce8 106 /* Enable the following interrupt sources, routed to GPIO */
MACRUM 0:615f90842ce8 107 irq_de_init(NULL);
MACRUM 0:615f90842ce8 108 irq_clear_status();
MACRUM 0:615f90842ce8 109 irq_set_status(TX_DATA_SENT, S_ENABLE);
MACRUM 0:615f90842ce8 110 irq_set_status(RX_DATA_READY,S_ENABLE);
MACRUM 0:615f90842ce8 111 irq_set_status(RX_DATA_DISC, S_ENABLE);
MACRUM 0:615f90842ce8 112 irq_set_status(VALID_SYNC, S_ENABLE);
MACRUM 0:615f90842ce8 113 irq_set_status(TX_FIFO_ERROR, S_ENABLE);
MACRUM 0:615f90842ce8 114 irq_set_status(RX_FIFO_ERROR, S_ENABLE);
MACRUM 0:615f90842ce8 115 #ifndef RX_FIFO_THR_WA
MACRUM 0:615f90842ce8 116 irq_set_status(TX_FIFO_ALMOST_EMPTY, S_ENABLE);
MACRUM 0:615f90842ce8 117 irq_set_status(RX_FIFO_ALMOST_FULL, S_ENABLE);
MACRUM 0:615f90842ce8 118 #endif // !RX_FIFO_THR_WA
MACRUM 0:615f90842ce8 119
MACRUM 0:615f90842ce8 120 /* Configure Spirit1 */
MACRUM 0:615f90842ce8 121 radio_persistent_rx(S_ENABLE);
MACRUM 0:615f90842ce8 122 qi_set_sqi_threshold(SQI_TH_0);
MACRUM 0:615f90842ce8 123 qi_sqi_check(S_ENABLE);
MACRUM 0:615f90842ce8 124 qi_set_rssi_threshold_dbm(CCA_THRESHOLD);
MACRUM 0:615f90842ce8 125 timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD);
MACRUM 0:615f90842ce8 126 timer_set_infinite_rx_timeout();
MACRUM 0:615f90842ce8 127 radio_afc_freeze_on_sync(S_ENABLE);
MACRUM 0:615f90842ce8 128 calibration_rco(S_ENABLE);
MACRUM 0:615f90842ce8 129
MACRUM 0:615f90842ce8 130 spirit_on = OFF;
MACRUM 0:615f90842ce8 131 CLEAR_TXBUF();
MACRUM 0:615f90842ce8 132 CLEAR_RXBUF();
MACRUM 0:615f90842ce8 133 _spirit_tx_started = false;
MACRUM 0:615f90842ce8 134 _is_receiving = false;
MACRUM 0:615f90842ce8 135
MACRUM 0:615f90842ce8 136 /* Configure the radio to route the IRQ signal to its GPIO 3 */
MACRUM 0:615f90842ce8 137 SGpioInit x_gpio_init = {
MACRUM 0:615f90842ce8 138 SPIRIT_GPIO_IRQ,
MACRUM 0:615f90842ce8 139 SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP,
MACRUM 0:615f90842ce8 140 SPIRIT_GPIO_DIG_OUT_IRQ
MACRUM 0:615f90842ce8 141 };
MACRUM 0:615f90842ce8 142 spirit_gpio_init(&x_gpio_init);
MACRUM 0:615f90842ce8 143
MACRUM 0:615f90842ce8 144 /* Setup CSMA/CA */
MACRUM 0:615f90842ce8 145 CsmaInit x_csma_init = {
MACRUM 0:615f90842ce8 146 S_ENABLE, // enable persistent mode
MACRUM 0:615f90842ce8 147 TBIT_TIME_64, // Tcca time
MACRUM 0:615f90842ce8 148 TCCA_TIME_3, // Lcca length
MACRUM 0:615f90842ce8 149 3, // max nr of backoffs (<8)
MACRUM 0:615f90842ce8 150 1, // BU counter seed
MACRUM 0:615f90842ce8 151 8 // BU prescaler
MACRUM 0:615f90842ce8 152 };
MACRUM 0:615f90842ce8 153 csma_ca_init(&x_csma_init);
MACRUM 0:615f90842ce8 154
MACRUM 0:615f90842ce8 155 #ifdef USE_STANDBY_STATE
MACRUM 0:615f90842ce8 156 /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
MACRUM 0:615f90842ce8 157 cmd_strobe(SPIRIT1_STROBE_STANDBY);
MACRUM 0:615f90842ce8 158 #endif // USE_STANDBY_STATE
MACRUM 0:615f90842ce8 159 }
MACRUM 0:615f90842ce8 160
MACRUM 0:615f90842ce8 161 static volatile int tx_fifo_remaining = 0; // to be used in irq handler
MACRUM 0:615f90842ce8 162 static volatile int tx_buffer_pos = 0; // to be used in irq handler
MACRUM 0:615f90842ce8 163 const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler
MACRUM 0:615f90842ce8 164 int SimpleSpirit1::send(const void *payload, unsigned int payload_len) {
MACRUM 0:615f90842ce8 165 /* Checks if the payload length is supported */
MACRUM 0:615f90842ce8 166 if(payload_len > MAX_PACKET_LEN) {
MACRUM 0:615f90842ce8 167 return RADIO_TX_ERR;
MACRUM 0:615f90842ce8 168 }
MACRUM 0:615f90842ce8 169
MACRUM 0:615f90842ce8 170 disable_spirit_irq();
MACRUM 0:615f90842ce8 171
MACRUM 0:615f90842ce8 172 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
MACRUM 0:615f90842ce8 173 #ifndef NDEBUG
MACRUM 0:615f90842ce8 174 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
MACRUM 0:615f90842ce8 175 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
MACRUM 0:615f90842ce8 176 }
MACRUM 0:615f90842ce8 177 #endif
MACRUM 0:615f90842ce8 178
MACRUM 0:615f90842ce8 179 /* Reset State to Ready */
MACRUM 0:615f90842ce8 180 set_ready_state();
MACRUM 0:615f90842ce8 181
MACRUM 0:615f90842ce8 182 cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer
MACRUM 0:615f90842ce8 183
MACRUM 0:615f90842ce8 184 #ifndef NDEBUG
MACRUM 0:615f90842ce8 185 debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 186 #endif
MACRUM 0:615f90842ce8 187
MACRUM 0:615f90842ce8 188 pkt_basic_set_payload_length(payload_len); // set desired payload len
MACRUM 0:615f90842ce8 189
MACRUM 0:615f90842ce8 190 csma_ca_state(S_ENABLE); // enable CSMA/CA
MACRUM 0:615f90842ce8 191
MACRUM 0:615f90842ce8 192 /* Init buffer & number of bytes to be send */
MACRUM 0:615f90842ce8 193 tx_fifo_remaining = payload_len;
MACRUM 0:615f90842ce8 194 tx_fifo_buffer = (const uint8_t*)payload;
MACRUM 0:615f90842ce8 195
MACRUM 0:615f90842ce8 196 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
MACRUM 0:615f90842ce8 197 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
MACRUM 0:615f90842ce8 198
MACRUM 0:615f90842ce8 199 tx_fifo_remaining -= to_send;
MACRUM 0:615f90842ce8 200
MACRUM 0:615f90842ce8 201 /* Fill FIFO Buffer */
MACRUM 0:615f90842ce8 202 if(to_send > 0) {
MACRUM 0:615f90842ce8 203 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
MACRUM 0:615f90842ce8 204 }
MACRUM 0:615f90842ce8 205
MACRUM 0:615f90842ce8 206 tx_buffer_pos = to_send;
MACRUM 0:615f90842ce8 207 _spirit_tx_started = true;
MACRUM 0:615f90842ce8 208
MACRUM 0:615f90842ce8 209 enable_spirit_irq();
MACRUM 0:615f90842ce8 210
MACRUM 0:615f90842ce8 211 /* Start transmitting */
MACRUM 0:615f90842ce8 212 cmd_strobe(SPIRIT1_STROBE_TX);
MACRUM 0:615f90842ce8 213
MACRUM 0:615f90842ce8 214 while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
MACRUM 0:615f90842ce8 215
MACRUM 0:615f90842ce8 216 BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
MACRUM 0:615f90842ce8 217 #ifdef HEAVY_DEBUG
MACRUM 0:615f90842ce8 218 debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
MACRUM 0:615f90842ce8 219 #endif
MACRUM 0:615f90842ce8 220
MACRUM 0:615f90842ce8 221 _spirit_tx_started = false; // in case of state timeout
MACRUM 0:615f90842ce8 222
MACRUM 0:615f90842ce8 223 csma_ca_state(S_DISABLE); // disable CSMA/CA
MACRUM 0:615f90842ce8 224
MACRUM 0:615f90842ce8 225 cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
MACRUM 0:615f90842ce8 226
MACRUM 0:615f90842ce8 227 return RADIO_TX_OK;
MACRUM 0:615f90842ce8 228 }
MACRUM 0:615f90842ce8 229
MACRUM 0:615f90842ce8 230 /** Set Ready State **/
MACRUM 0:615f90842ce8 231 void SimpleSpirit1::set_ready_state(void) {
MACRUM 0:615f90842ce8 232 uint16_t state;
MACRUM 0:615f90842ce8 233
MACRUM 0:615f90842ce8 234 disable_spirit_irq();
MACRUM 0:615f90842ce8 235
MACRUM 0:615f90842ce8 236 _spirit_tx_started = false;
MACRUM 0:615f90842ce8 237 _is_receiving = false;
MACRUM 0:615f90842ce8 238 stop_rx_timeout();
MACRUM 0:615f90842ce8 239
MACRUM 0:615f90842ce8 240 cmd_strobe(SPIRIT1_STROBE_FRX);
MACRUM 0:615f90842ce8 241 CLEAR_RXBUF();
MACRUM 0:615f90842ce8 242 CLEAR_TXBUF();
MACRUM 0:615f90842ce8 243
MACRUM 0:615f90842ce8 244 state = SPIRIT1_STATUS();
MACRUM 0:615f90842ce8 245 if(state == SPIRIT1_STATE_STANDBY) {
MACRUM 0:615f90842ce8 246 cmd_strobe(SPIRIT1_STROBE_READY);
MACRUM 0:615f90842ce8 247 } else if(state == SPIRIT1_STATE_RX) {
MACRUM 0:615f90842ce8 248 cmd_strobe(SPIRIT1_STROBE_SABORT);
MACRUM 0:615f90842ce8 249 } else if(state != SPIRIT1_STATE_READY) {
MACRUM 0:615f90842ce8 250 #ifndef NDEBUG
MACRUM 0:615f90842ce8 251 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, state>>1);
MACRUM 0:615f90842ce8 252 #endif
MACRUM 0:615f90842ce8 253 }
MACRUM 0:615f90842ce8 254
MACRUM 0:615f90842ce8 255 BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
MACRUM 0:615f90842ce8 256 if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
MACRUM 0:615f90842ce8 257 error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state);
MACRUM 0:615f90842ce8 258 enable_spirit_irq();
MACRUM 0:615f90842ce8 259 return;
MACRUM 0:615f90842ce8 260 }
MACRUM 0:615f90842ce8 261
MACRUM 0:615f90842ce8 262 irq_clear_status();
MACRUM 0:615f90842ce8 263
MACRUM 0:615f90842ce8 264 enable_spirit_irq();
MACRUM 0:615f90842ce8 265 }
MACRUM 0:615f90842ce8 266
MACRUM 0:615f90842ce8 267 int SimpleSpirit1::off(void) {
MACRUM 0:615f90842ce8 268 if(spirit_on == ON) {
MACRUM 0:615f90842ce8 269 /* Disables the mcu to get IRQ from the SPIRIT1 */
MACRUM 0:615f90842ce8 270 disable_spirit_irq();
MACRUM 0:615f90842ce8 271
MACRUM 0:615f90842ce8 272 /* first stop rx/tx */
MACRUM 0:615f90842ce8 273 set_ready_state();
MACRUM 0:615f90842ce8 274
MACRUM 0:615f90842ce8 275 #ifdef USE_STANDBY_STATE
MACRUM 0:615f90842ce8 276 /* Puts the SPIRIT1 in STANDBY */
MACRUM 0:615f90842ce8 277 cmd_strobe(SPIRIT1_STROBE_STANDBY);
MACRUM 0:615f90842ce8 278 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
MACRUM 0:615f90842ce8 279 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
MACRUM 0:615f90842ce8 280 error("\n\rSpirit1: failed to enter standby (%x)\n\r", last_state>>1);
MACRUM 0:615f90842ce8 281 return 1;
MACRUM 0:615f90842ce8 282 }
MACRUM 0:615f90842ce8 283 #endif // USE_STANDBY_STATE
MACRUM 0:615f90842ce8 284
MACRUM 0:615f90842ce8 285 spirit_on = OFF;
MACRUM 0:615f90842ce8 286 _nr_of_irq_disables = 1;
MACRUM 0:615f90842ce8 287 }
MACRUM 0:615f90842ce8 288 return 0;
MACRUM 0:615f90842ce8 289 }
MACRUM 0:615f90842ce8 290
MACRUM 0:615f90842ce8 291 int SimpleSpirit1::on(void) {
MACRUM 0:615f90842ce8 292 if(spirit_on == OFF) {
MACRUM 0:615f90842ce8 293 set_ready_state();
MACRUM 0:615f90842ce8 294
MACRUM 0:615f90842ce8 295 /* now we go to Rx */
MACRUM 0:615f90842ce8 296 cmd_strobe(SPIRIT1_STROBE_RX);
MACRUM 0:615f90842ce8 297
MACRUM 0:615f90842ce8 298 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
MACRUM 0:615f90842ce8 299 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
MACRUM 0:615f90842ce8 300 error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1);
MACRUM 0:615f90842ce8 301 }
MACRUM 0:615f90842ce8 302
MACRUM 0:615f90842ce8 303 /* Enables the mcu to get IRQ from the SPIRIT1 */
MACRUM 0:615f90842ce8 304 spirit_on = ON;
MACRUM 0:615f90842ce8 305 #ifndef NDEBUG
MACRUM 0:615f90842ce8 306 debug_if(!(_nr_of_irq_disables == 1), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 307 #endif
MACRUM 0:615f90842ce8 308 enable_spirit_irq();
MACRUM 0:615f90842ce8 309 }
MACRUM 0:615f90842ce8 310
MACRUM 0:615f90842ce8 311 #ifndef NDEBUG
MACRUM 0:615f90842ce8 312 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
MACRUM 0:615f90842ce8 313 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
MACRUM 0:615f90842ce8 314 }
MACRUM 0:615f90842ce8 315 #endif
MACRUM 0:615f90842ce8 316
MACRUM 0:615f90842ce8 317 return 0;
MACRUM 0:615f90842ce8 318 }
MACRUM 0:615f90842ce8 319
MACRUM 0:615f90842ce8 320 uint8_t SimpleSpirit1::refresh_state(void) {
MACRUM 0:615f90842ce8 321 uint8_t mcstate;
MACRUM 0:615f90842ce8 322
MACRUM 0:615f90842ce8 323 SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
MACRUM 0:615f90842ce8 324
MACRUM 0:615f90842ce8 325 return mcstate;
MACRUM 0:615f90842ce8 326 }
MACRUM 0:615f90842ce8 327
MACRUM 0:615f90842ce8 328 int SimpleSpirit1::read(void *buf, unsigned int bufsize)
MACRUM 0:615f90842ce8 329 {
MACRUM 0:615f90842ce8 330 disable_spirit_irq();
MACRUM 0:615f90842ce8 331
MACRUM 0:615f90842ce8 332 /* Checks if the RX buffer is empty */
MACRUM 0:615f90842ce8 333 if(IS_RXBUF_EMPTY()) {
MACRUM 0:615f90842ce8 334 #ifndef NDEBUG
MACRUM 0:615f90842ce8 335 debug("\n\rBuffer is empty\n\r");
MACRUM 0:615f90842ce8 336 #endif
MACRUM 0:615f90842ce8 337 set_ready_state();
MACRUM 0:615f90842ce8 338
MACRUM 0:615f90842ce8 339 cmd_strobe(SPIRIT1_STROBE_RX);
MACRUM 0:615f90842ce8 340 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
MACRUM 0:615f90842ce8 341 enable_spirit_irq();
MACRUM 0:615f90842ce8 342 return 0;
MACRUM 0:615f90842ce8 343 }
MACRUM 0:615f90842ce8 344
MACRUM 0:615f90842ce8 345 if(bufsize < spirit_rx_len) {
MACRUM 0:615f90842ce8 346 enable_spirit_irq();
MACRUM 0:615f90842ce8 347
MACRUM 0:615f90842ce8 348 /* If buf has the correct size */
MACRUM 0:615f90842ce8 349 #ifndef NDEBUG
MACRUM 0:615f90842ce8 350 debug("\n\rTOO SMALL BUF\n\r");
MACRUM 0:615f90842ce8 351 #endif
MACRUM 0:615f90842ce8 352 return 0;
MACRUM 0:615f90842ce8 353 } else {
MACRUM 0:615f90842ce8 354 /* Copies the packet received */
MACRUM 0:615f90842ce8 355 memcpy(buf, spirit_rx_buf, spirit_rx_len);
MACRUM 0:615f90842ce8 356
MACRUM 0:615f90842ce8 357 bufsize = spirit_rx_len;
MACRUM 0:615f90842ce8 358 CLEAR_RXBUF();
MACRUM 0:615f90842ce8 359
MACRUM 0:615f90842ce8 360 enable_spirit_irq();
MACRUM 0:615f90842ce8 361
MACRUM 0:615f90842ce8 362 return bufsize;
MACRUM 0:615f90842ce8 363 }
MACRUM 0:615f90842ce8 364
MACRUM 0:615f90842ce8 365 }
MACRUM 0:615f90842ce8 366
MACRUM 0:615f90842ce8 367 int SimpleSpirit1::channel_clear(void)
MACRUM 0:615f90842ce8 368 {
MACRUM 0:615f90842ce8 369 float rssi_value;
MACRUM 0:615f90842ce8 370 /* Local variable used to memorize the SPIRIT1 state */
MACRUM 0:615f90842ce8 371 uint8_t spirit_state = ON;
MACRUM 0:615f90842ce8 372
MACRUM 0:615f90842ce8 373 if(spirit_on == OFF) {
MACRUM 0:615f90842ce8 374 /* Wakes up the SPIRIT1 */
MACRUM 0:615f90842ce8 375 on();
MACRUM 0:615f90842ce8 376 spirit_state = OFF;
MACRUM 0:615f90842ce8 377 }
MACRUM 0:615f90842ce8 378
MACRUM 0:615f90842ce8 379 #ifndef NDEBUG
MACRUM 0:615f90842ce8 380 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
MACRUM 0:615f90842ce8 381 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
MACRUM 0:615f90842ce8 382 }
MACRUM 0:615f90842ce8 383 #endif
MACRUM 0:615f90842ce8 384
MACRUM 0:615f90842ce8 385 disable_spirit_irq();
MACRUM 0:615f90842ce8 386
MACRUM 0:615f90842ce8 387 /* Reset State to Ready */
MACRUM 0:615f90842ce8 388 set_ready_state();
MACRUM 0:615f90842ce8 389
MACRUM 0:615f90842ce8 390 /* Stores the RSSI value */
MACRUM 0:615f90842ce8 391 rssi_value = qi_get_rssi_dbm();
MACRUM 0:615f90842ce8 392
MACRUM 0:615f90842ce8 393 enable_spirit_irq();
MACRUM 0:615f90842ce8 394
MACRUM 0:615f90842ce8 395 /* Puts the SPIRIT1 in its previous state */
MACRUM 0:615f90842ce8 396 if(spirit_state==OFF) {
MACRUM 0:615f90842ce8 397 off();
MACRUM 0:615f90842ce8 398 #ifndef NDEBUG
MACRUM 0:615f90842ce8 399 #ifdef USE_STANDBY_STATE
MACRUM 0:615f90842ce8 400 if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
MACRUM 0:615f90842ce8 401 #else
MACRUM 0:615f90842ce8 402 if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
MACRUM 0:615f90842ce8 403 #endif
MACRUM 0:615f90842ce8 404 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
MACRUM 0:615f90842ce8 405 }
MACRUM 0:615f90842ce8 406 #endif
MACRUM 0:615f90842ce8 407 } else {
MACRUM 0:615f90842ce8 408 disable_spirit_irq();
MACRUM 0:615f90842ce8 409
MACRUM 0:615f90842ce8 410 set_ready_state();
MACRUM 0:615f90842ce8 411
MACRUM 0:615f90842ce8 412 cmd_strobe(SPIRIT1_STROBE_RX);
MACRUM 0:615f90842ce8 413 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
MACRUM 0:615f90842ce8 414 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
MACRUM 0:615f90842ce8 415 error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1);
MACRUM 0:615f90842ce8 416 }
MACRUM 0:615f90842ce8 417
MACRUM 0:615f90842ce8 418 enable_spirit_irq();
MACRUM 0:615f90842ce8 419
MACRUM 0:615f90842ce8 420 #ifndef NDEBUG
MACRUM 0:615f90842ce8 421 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
MACRUM 0:615f90842ce8 422 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
MACRUM 0:615f90842ce8 423 }
MACRUM 0:615f90842ce8 424 #endif
MACRUM 0:615f90842ce8 425 }
MACRUM 0:615f90842ce8 426
MACRUM 0:615f90842ce8 427 /* Checks the RSSI value with the threshold */
MACRUM 0:615f90842ce8 428 if(rssi_value<CCA_THRESHOLD) {
MACRUM 0:615f90842ce8 429 return 0;
MACRUM 0:615f90842ce8 430 } else {
MACRUM 0:615f90842ce8 431 return 1;
MACRUM 0:615f90842ce8 432 }
MACRUM 0:615f90842ce8 433 }
MACRUM 0:615f90842ce8 434
MACRUM 0:615f90842ce8 435 int SimpleSpirit1::get_pending_packet(void)
MACRUM 0:615f90842ce8 436 {
MACRUM 0:615f90842ce8 437 return !IS_RXBUF_EMPTY();
MACRUM 0:615f90842ce8 438 }
MACRUM 0:615f90842ce8 439
MACRUM 0:615f90842ce8 440 /** Spirit Irq Callback **/
MACRUM 0:615f90842ce8 441 /* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */
MACRUM 0:615f90842ce8 442 void SimpleSpirit1::IrqHandler() {
MACRUM 0:615f90842ce8 443 st_lib_spirit_irqs x_irq_status;
MACRUM 0:615f90842ce8 444
MACRUM 0:615f90842ce8 445 /* get interrupt source from radio */
MACRUM 0:615f90842ce8 446 irq_get_status(&x_irq_status);
MACRUM 0:615f90842ce8 447
MACRUM 0:615f90842ce8 448 /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
MACRUM 0:615f90842ce8 449 if(x_irq_status.IRQ_TX_DATA_SENT) {
MACRUM 0:615f90842ce8 450 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 451 uint32_t *tmp = (uint32_t*)&x_irq_status;
MACRUM 0:615f90842ce8 452 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 453 debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 454 debug_if(tx_fifo_remaining != 0, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 455 #endif
MACRUM 0:615f90842ce8 456
MACRUM 0:615f90842ce8 457 tx_fifo_buffer = NULL;
MACRUM 0:615f90842ce8 458 _spirit_tx_started = false;
MACRUM 0:615f90842ce8 459
MACRUM 0:615f90842ce8 460 /* call user callback */
MACRUM 0:615f90842ce8 461 if(_current_irq_callback) {
MACRUM 0:615f90842ce8 462 _current_irq_callback(TX_DONE);
MACRUM 0:615f90842ce8 463 }
MACRUM 0:615f90842ce8 464
MACRUM 0:615f90842ce8 465 /* Disable handling of other TX flags */
MACRUM 0:615f90842ce8 466 x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET;
MACRUM 0:615f90842ce8 467 }
MACRUM 0:615f90842ce8 468
MACRUM 0:615f90842ce8 469 #ifndef RX_FIFO_THR_WA
MACRUM 0:615f90842ce8 470 /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
MACRUM 0:615f90842ce8 471 if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
MACRUM 0:615f90842ce8 472 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 473 uint32_t *tmp = (uint32_t*)&x_irq_status;
MACRUM 0:615f90842ce8 474 debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 475 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 476 debug_if(tx_fifo_buffer == NULL, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 477 #endif
MACRUM 0:615f90842ce8 478
MACRUM 0:615f90842ce8 479 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
MACRUM 0:615f90842ce8 480 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
MACRUM 0:615f90842ce8 481
MACRUM 0:615f90842ce8 482 tx_fifo_remaining -= to_send;
MACRUM 0:615f90842ce8 483
MACRUM 0:615f90842ce8 484 /* Fill FIFO Buffer */
MACRUM 0:615f90842ce8 485 if(to_send > 0) {
MACRUM 0:615f90842ce8 486 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
MACRUM 0:615f90842ce8 487 }
MACRUM 0:615f90842ce8 488 tx_buffer_pos += to_send;
MACRUM 0:615f90842ce8 489 }
MACRUM 0:615f90842ce8 490 #endif // !RX_FIFO_THR_WA
MACRUM 0:615f90842ce8 491
MACRUM 0:615f90842ce8 492 /* Transmission error */
MACRUM 0:615f90842ce8 493 if(x_irq_status.IRQ_TX_FIFO_ERROR) {
MACRUM 0:615f90842ce8 494 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 495 uint32_t *tmp = (uint32_t*)&x_irq_status;
MACRUM 0:615f90842ce8 496 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
MACRUM 0:615f90842ce8 497 debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 498 #endif
MACRUM 0:615f90842ce8 499 if(_spirit_tx_started) {
MACRUM 0:615f90842ce8 500 _spirit_tx_started = false;
MACRUM 0:615f90842ce8 501 /* call user callback */
MACRUM 0:615f90842ce8 502 if(_current_irq_callback) {
MACRUM 0:615f90842ce8 503 _current_irq_callback(TX_ERR);
MACRUM 0:615f90842ce8 504 }
MACRUM 0:615f90842ce8 505 }
MACRUM 0:615f90842ce8 506
MACRUM 0:615f90842ce8 507 /* reset data still to be sent */
MACRUM 0:615f90842ce8 508 tx_fifo_remaining = 0;
MACRUM 0:615f90842ce8 509 }
MACRUM 0:615f90842ce8 510
MACRUM 0:615f90842ce8 511 /* The IRQ_RX_DATA_READY notifies a new packet arrived */
MACRUM 0:615f90842ce8 512 if(x_irq_status.IRQ_RX_DATA_READY) {
MACRUM 0:615f90842ce8 513 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 514 uint32_t *tmp = (uint32_t*)&x_irq_status;
MACRUM 0:615f90842ce8 515 debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 516 #endif
MACRUM 0:615f90842ce8 517
MACRUM 0:615f90842ce8 518 if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!)
MACRUM 0:615f90842ce8 519 #ifdef HEAVY_DEBUG
MACRUM 0:615f90842ce8 520 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
MACRUM 0:615f90842ce8 521 #endif
MACRUM 0:615f90842ce8 522 } else {
MACRUM 0:615f90842ce8 523 _is_receiving = false; // Finished receiving
MACRUM 0:615f90842ce8 524 stop_rx_timeout();
MACRUM 0:615f90842ce8 525
MACRUM 0:615f90842ce8 526 spirit_rx_len = pkt_basic_get_received_pkt_length();
MACRUM 0:615f90842ce8 527
MACRUM 0:615f90842ce8 528 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 529 debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
MACRUM 0:615f90842ce8 530 #endif
MACRUM 0:615f90842ce8 531
MACRUM 0:615f90842ce8 532 if(spirit_rx_len <= MAX_PACKET_LEN) {
MACRUM 0:615f90842ce8 533 uint8_t to_receive = spirit_rx_len - _spirit_rx_pos;
MACRUM 0:615f90842ce8 534 if(to_receive > 0) {
MACRUM 0:615f90842ce8 535 spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]);
MACRUM 0:615f90842ce8 536 _spirit_rx_pos += to_receive;
MACRUM 0:615f90842ce8 537 }
MACRUM 0:615f90842ce8 538 }
MACRUM 0:615f90842ce8 539
MACRUM 0:615f90842ce8 540 cmd_strobe(SPIRIT1_STROBE_FRX);
MACRUM 0:615f90842ce8 541
MACRUM 0:615f90842ce8 542 last_rssi = qi_get_rssi(); //MGR
MACRUM 0:615f90842ce8 543 last_sqi = qi_get_sqi(); //MGR
MACRUM 0:615f90842ce8 544
MACRUM 0:615f90842ce8 545 /* call user callback */
MACRUM 0:615f90842ce8 546 if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) {
MACRUM 0:615f90842ce8 547 _current_irq_callback(RX_DONE);
MACRUM 0:615f90842ce8 548 }
MACRUM 0:615f90842ce8 549
MACRUM 0:615f90842ce8 550 /* Disable handling of other RX flags */
MACRUM 0:615f90842ce8 551 x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
MACRUM 0:615f90842ce8 552 }
MACRUM 0:615f90842ce8 553 }
MACRUM 0:615f90842ce8 554
MACRUM 0:615f90842ce8 555 #ifndef RX_FIFO_THR_WA
MACRUM 0:615f90842ce8 556 /* RX FIFO almost full */
MACRUM 0:615f90842ce8 557 if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) {
MACRUM 0:615f90842ce8 558 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 559 uint32_t *tmp = (uint32_t*)&x_irq_status;
MACRUM 0:615f90842ce8 560 debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 561 #endif
MACRUM 0:615f90842ce8 562 if(!_is_receiving) { // spurious irq?!?
MACRUM 0:615f90842ce8 563 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 564 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
MACRUM 0:615f90842ce8 565 #endif
MACRUM 0:615f90842ce8 566 } else {
MACRUM 0:615f90842ce8 567 uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
MACRUM 0:615f90842ce8 568 if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) {
MACRUM 0:615f90842ce8 569 spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
MACRUM 0:615f90842ce8 570 _spirit_rx_pos += fifo_available;
MACRUM 0:615f90842ce8 571 } else {
MACRUM 0:615f90842ce8 572 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 573 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
MACRUM 0:615f90842ce8 574 #endif
MACRUM 0:615f90842ce8 575 }
MACRUM 0:615f90842ce8 576 }
MACRUM 0:615f90842ce8 577 }
MACRUM 0:615f90842ce8 578 #endif // !RX_FIFO_THR_WA
MACRUM 0:615f90842ce8 579
MACRUM 0:615f90842ce8 580 /* Reception errors */
MACRUM 0:615f90842ce8 581 if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
MACRUM 0:615f90842ce8 582 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 583 uint32_t *tmp = (uint32_t*)&x_irq_status;
MACRUM 0:615f90842ce8 584 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
MACRUM 0:615f90842ce8 585 debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 586 #endif
MACRUM 0:615f90842ce8 587 rx_timeout_handler();
MACRUM 0:615f90842ce8 588 if(_spirit_tx_started) {
MACRUM 0:615f90842ce8 589 _spirit_tx_started = false;
MACRUM 0:615f90842ce8 590 /* call user callback */
MACRUM 0:615f90842ce8 591 if(_current_irq_callback) {
MACRUM 0:615f90842ce8 592 _current_irq_callback(TX_ERR);
MACRUM 0:615f90842ce8 593 }
MACRUM 0:615f90842ce8 594 }
MACRUM 0:615f90842ce8 595 }
MACRUM 0:615f90842ce8 596
MACRUM 0:615f90842ce8 597 /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
MACRUM 0:615f90842ce8 598 if(x_irq_status.IRQ_VALID_SYNC) {
MACRUM 0:615f90842ce8 599 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 600 uint32_t *tmp = (uint32_t*)&x_irq_status;
MACRUM 0:615f90842ce8 601 debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
MACRUM 0:615f90842ce8 602 #endif
MACRUM 0:615f90842ce8 603 /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and
MACRUM 0:615f90842ce8 604 * the MCU trying to send a packet, which gets resolved in favor of
MACRUM 0:615f90842ce8 605 * sending.
MACRUM 0:615f90842ce8 606 */
MACRUM 0:615f90842ce8 607 if(_spirit_tx_started) {
MACRUM 0:615f90842ce8 608 #ifdef DEBUG_IRQ
MACRUM 0:615f90842ce8 609 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
MACRUM 0:615f90842ce8 610 #endif
MACRUM 0:615f90842ce8 611 } else {
MACRUM 0:615f90842ce8 612 _is_receiving = true;
MACRUM 0:615f90842ce8 613 start_rx_timeout();
MACRUM 0:615f90842ce8 614 }
MACRUM 0:615f90842ce8 615 }
MACRUM 0:615f90842ce8 616 }