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:
Thu Nov 17 08:24:29 2016 +0100
Revision:
28:6a71e15d5272
Parent:
27:e68ffb6ac223
Child:
29:fe1b113f71d0
Backup commit

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