Prototype RF driver for STM Sub-1 GHz RF expansion board based on the SPSGRF-868 module for STM32 Nucleo.

Prototype RF Driver for STM Sub-1 GHz RF Expansion Boards based on the SPSGRF-868 and SPSGRF-915 Modules for STM32 Nucleo

Currently supported boards:

Note, in order to use expansion board X-NUCLEO-IDS01A4 in mbed you need to perform the following HW modifications on the board:

  • Unmount resistor R4
  • Mount resistor R7

Furthermore, on some Nucleo development boards (e.g. the NUCLEO_F429ZI), in order to be able to use Ethernet together with these Sub-1 GHz RF expansion boards, you need to compile this driver with macro SPIRIT1_SPI_MOSI=PB_5 defined, while the development board typically requires some HW modification as e.g. described here!

This driver can be used together with the 6LoWPAN stack (a.k.a. Nanostack).

Committer:
Wolfgang Betz
Date:
Mon Nov 14 11:26:03 2016 +0100
Revision:
25:2ec45788f28c
Parent:
24:03e351bfc9c9
Child:
26:45dae8d48029
Enable the automatic RCO calibration

Who changed what in which revision?

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