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 Dec 22 08:25:22 2016 +0100
Revision:
47:3a30b960a8c2
Parent:
46:d104e58c5caf
Child:
48:373e1b7e424f
Optimize IRQ handler

Who changed what in which revision?

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