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 Jul 03 14:39:01 2017 +0200
Revision:
64:28ef790e4ef7
Parent:
60:956afcef7ef7
Child:
65:a16f0064110a
Implement indications received by Kevin Bracey

Date: Mon, 3 Jul 2017 10:14:23 +0000
From: Kevin Bracey <notifications@github.com>

https://github.com/ARMmbed/mbed-os-example-client/issues/266#issuecomment-312606944

I've just spent a little while reviewing the Spirit driver code, just to see if I can see any obvious flaws. (Hard to say much without knowing the hardware, but I can look for general issues.)

I'm a bit wary about the software ack handling - can be tricky.

There is one specific problem that could be affecting performance now - it seems to me the acks are sent with a common send() routine that enables hardware CSMA-CD. An ack should be being sent 192us after transmission completion, without CSMA. Backing off the ack will greatly reduce the chance of packets being successfully acknowledged.

Other notes on ack reception - you're calling TX_DONE whenever tx_sequence == seq_number, whether you were expecting an ack or not. This could cause stack confusion in various ways (eg if you were backing off while someone else used the same sequence number). You should only process an ACK when you actually expect one (TX completed, and AR bit was set in it)

Also, while expecting an ack, it can be beneficial to report TX_FAIL and stop expecting when you receive anything other then an ack with the expected sequence number. The stack will eventually time out if it doesn't get TX_DONE, but receipt of anything else (including a wrongly-numbered ack) indicates a lack of acknowledgment, which can be reported immediately.

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 60:956afcef7ef7 54 _spi.frequency(10000000); // 10MHz (i.e. max speed allowed for 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 64:28ef790e4ef7 164 int SimpleSpirit1::send(const void *payload, unsigned int payload_len, bool use_csma_ca) {
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 64:28ef790e4ef7 190 if(use_csma_ca) {
Wolfgang Betz 64:28ef790e4ef7 191 csma_ca_state(S_ENABLE); // enable CSMA/CA
Wolfgang Betz 64:28ef790e4ef7 192 }
Wolfgang Betz 34:edda6a7238ec 193
Wolfgang Betz 45:2d01cc9bc761 194 /* Init buffer & number of bytes to be send */
Wolfgang Betz 45:2d01cc9bc761 195 tx_fifo_remaining = payload_len;
Wolfgang Betz 45:2d01cc9bc761 196 tx_fifo_buffer = (const uint8_t*)payload;
Wolfgang Betz 45:2d01cc9bc761 197
Wolfgang Betz 45:2d01cc9bc761 198 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
Wolfgang Betz 45:2d01cc9bc761 199 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
Wolfgang Betz 34:edda6a7238ec 200
Wolfgang Betz 45:2d01cc9bc761 201 tx_fifo_remaining -= to_send;
Wolfgang Betz 34:edda6a7238ec 202
Wolfgang Betz 45:2d01cc9bc761 203 /* Fill FIFO Buffer */
Wolfgang Betz 45:2d01cc9bc761 204 if(to_send > 0) {
Wolfgang Betz 45:2d01cc9bc761 205 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
Wolfgang Betz 45:2d01cc9bc761 206 }
Wolfgang Betz 34:edda6a7238ec 207
Wolfgang Betz 45:2d01cc9bc761 208 tx_buffer_pos = to_send;
Wolfgang Betz 34:edda6a7238ec 209 _spirit_tx_started = true;
Wolfgang Betz 34:edda6a7238ec 210
Wolfgang Betz 34:edda6a7238ec 211 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 212
Wolfgang Betz 45:2d01cc9bc761 213 /* Start transmitting */
Wolfgang Betz 45:2d01cc9bc761 214 cmd_strobe(SPIRIT1_STROBE_TX);
Wolfgang Betz 45:2d01cc9bc761 215
Wolfgang Betz 45:2d01cc9bc761 216 while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
Wolfgang Betz 45:2d01cc9bc761 217
Wolfgang Betz 34:edda6a7238ec 218 BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
Wolfgang Betz 34:edda6a7238ec 219 #ifdef HEAVY_DEBUG
Wolfgang Betz 34:edda6a7238ec 220 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 221 #endif
Wolfgang Betz 34:edda6a7238ec 222
Wolfgang Betz 34:edda6a7238ec 223 _spirit_tx_started = false; // in case of state timeout
Wolfgang Betz 34:edda6a7238ec 224
Wolfgang Betz 64:28ef790e4ef7 225 if(use_csma_ca) {
Wolfgang Betz 64:28ef790e4ef7 226 csma_ca_state(S_DISABLE); // disable CSMA/CA
Wolfgang Betz 64:28ef790e4ef7 227 }
Wolfgang Betz 43:a512f909514a 228
Wolfgang Betz 34:edda6a7238ec 229 cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
Wolfgang Betz 34:edda6a7238ec 230
Wolfgang Betz 34:edda6a7238ec 231 return RADIO_TX_OK;
Wolfgang Betz 34:edda6a7238ec 232 }
Wolfgang Betz 34:edda6a7238ec 233
Wolfgang Betz 34:edda6a7238ec 234 /** Set Ready State **/
Wolfgang Betz 34:edda6a7238ec 235 void SimpleSpirit1::set_ready_state(void) {
Wolfgang Betz 34:edda6a7238ec 236 uint16_t state;
Wolfgang Betz 34:edda6a7238ec 237
Wolfgang Betz 34:edda6a7238ec 238 disable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 239
Wolfgang Betz 34:edda6a7238ec 240 _spirit_tx_started = false;
Wolfgang Betz 34:edda6a7238ec 241 _is_receiving = false;
Wolfgang Betz 34:edda6a7238ec 242 stop_rx_timeout();
Wolfgang Betz 34:edda6a7238ec 243
Wolfgang Betz 34:edda6a7238ec 244 cmd_strobe(SPIRIT1_STROBE_FRX);
Wolfgang Betz 34:edda6a7238ec 245 CLEAR_RXBUF();
Wolfgang Betz 34:edda6a7238ec 246 CLEAR_TXBUF();
Wolfgang Betz 34:edda6a7238ec 247
Wolfgang Betz 34:edda6a7238ec 248 state = SPIRIT1_STATUS();
Wolfgang Betz 34:edda6a7238ec 249 if(state == SPIRIT1_STATE_STANDBY) {
Wolfgang Betz 34:edda6a7238ec 250 cmd_strobe(SPIRIT1_STROBE_READY);
Wolfgang Betz 34:edda6a7238ec 251 } else if(state == SPIRIT1_STATE_RX) {
Wolfgang Betz 34:edda6a7238ec 252 cmd_strobe(SPIRIT1_STROBE_SABORT);
Wolfgang Betz 34:edda6a7238ec 253 } else if(state != SPIRIT1_STATE_READY) {
Wolfgang Betz 34:edda6a7238ec 254 #ifndef NDEBUG
Wolfgang Betz 34:edda6a7238ec 255 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, state>>1);
Wolfgang Betz 34:edda6a7238ec 256 #endif
Wolfgang Betz 34:edda6a7238ec 257 }
Wolfgang Betz 34:edda6a7238ec 258
Wolfgang Betz 34:edda6a7238ec 259 BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
Wolfgang Betz 34:edda6a7238ec 260 if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
Wolfgang Betz 34:edda6a7238ec 261 error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state);
Wolfgang Betz 34:edda6a7238ec 262 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 263 return;
Wolfgang Betz 34:edda6a7238ec 264 }
Wolfgang Betz 34:edda6a7238ec 265
Wolfgang Betz 34:edda6a7238ec 266 irq_clear_status();
Wolfgang Betz 34:edda6a7238ec 267
Wolfgang Betz 34:edda6a7238ec 268 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 269 }
Wolfgang Betz 34:edda6a7238ec 270
Wolfgang Betz 34:edda6a7238ec 271 int SimpleSpirit1::off(void) {
Wolfgang Betz 34:edda6a7238ec 272 if(spirit_on == ON) {
Wolfgang Betz 34:edda6a7238ec 273 /* Disables the mcu to get IRQ from the SPIRIT1 */
Wolfgang Betz 34:edda6a7238ec 274 disable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 275
Wolfgang Betz 34:edda6a7238ec 276 /* first stop rx/tx */
Wolfgang Betz 34:edda6a7238ec 277 set_ready_state();
Wolfgang Betz 34:edda6a7238ec 278
Wolfgang Betz 34:edda6a7238ec 279 #ifdef USE_STANDBY_STATE
Wolfgang Betz 34:edda6a7238ec 280 /* Puts the SPIRIT1 in STANDBY */
Wolfgang Betz 34:edda6a7238ec 281 cmd_strobe(SPIRIT1_STROBE_STANDBY);
Wolfgang Betz 34:edda6a7238ec 282 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
Wolfgang Betz 34:edda6a7238ec 283 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
Wolfgang Betz 34:edda6a7238ec 284 error("\n\rSpirit1: failed to enter standby (%x)\n\r", last_state>>1);
Wolfgang Betz 34:edda6a7238ec 285 return 1;
Wolfgang Betz 34:edda6a7238ec 286 }
Wolfgang Betz 34:edda6a7238ec 287 #endif // USE_STANDBY_STATE
Wolfgang Betz 34:edda6a7238ec 288
Wolfgang Betz 34:edda6a7238ec 289 spirit_on = OFF;
Wolfgang Betz 34:edda6a7238ec 290 _nr_of_irq_disables = 1;
Wolfgang Betz 34:edda6a7238ec 291 }
Wolfgang Betz 34:edda6a7238ec 292 return 0;
Wolfgang Betz 34:edda6a7238ec 293 }
Wolfgang Betz 34:edda6a7238ec 294
Wolfgang Betz 34:edda6a7238ec 295 int SimpleSpirit1::on(void) {
Wolfgang Betz 34:edda6a7238ec 296 if(spirit_on == OFF) {
Wolfgang Betz 34:edda6a7238ec 297 set_ready_state();
Wolfgang Betz 34:edda6a7238ec 298
Wolfgang Betz 34:edda6a7238ec 299 /* now we go to Rx */
Wolfgang Betz 34:edda6a7238ec 300 cmd_strobe(SPIRIT1_STROBE_RX);
Wolfgang Betz 34:edda6a7238ec 301
Wolfgang Betz 34:edda6a7238ec 302 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
Wolfgang Betz 34:edda6a7238ec 303 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
Wolfgang Betz 34:edda6a7238ec 304 error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1);
Wolfgang Betz 34:edda6a7238ec 305 }
Wolfgang Betz 34:edda6a7238ec 306
Wolfgang Betz 34:edda6a7238ec 307 /* Enables the mcu to get IRQ from the SPIRIT1 */
Wolfgang Betz 34:edda6a7238ec 308 spirit_on = ON;
Wolfgang Betz 34:edda6a7238ec 309 #ifndef NDEBUG
Wolfgang Betz 34:edda6a7238ec 310 debug_if(!(_nr_of_irq_disables == 1), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 34:edda6a7238ec 311 #endif
Wolfgang Betz 34:edda6a7238ec 312 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 313 }
Wolfgang Betz 34:edda6a7238ec 314
Wolfgang Betz 34:edda6a7238ec 315 #ifndef NDEBUG
Wolfgang Betz 34:edda6a7238ec 316 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
Wolfgang Betz 34:edda6a7238ec 317 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
Wolfgang Betz 34:edda6a7238ec 318 }
Wolfgang Betz 34:edda6a7238ec 319 #endif
Wolfgang Betz 34:edda6a7238ec 320
Wolfgang Betz 34:edda6a7238ec 321 return 0;
Wolfgang Betz 34:edda6a7238ec 322 }
Wolfgang Betz 34:edda6a7238ec 323
Wolfgang Betz 34:edda6a7238ec 324 uint8_t SimpleSpirit1::refresh_state(void) {
Wolfgang Betz 34:edda6a7238ec 325 uint8_t mcstate;
Wolfgang Betz 34:edda6a7238ec 326
Wolfgang Betz 34:edda6a7238ec 327 SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
Wolfgang Betz 34:edda6a7238ec 328
Wolfgang Betz 34:edda6a7238ec 329 return mcstate;
Wolfgang Betz 34:edda6a7238ec 330 }
Wolfgang Betz 34:edda6a7238ec 331
Wolfgang Betz 34:edda6a7238ec 332 int SimpleSpirit1::read(void *buf, unsigned int bufsize)
Wolfgang Betz 34:edda6a7238ec 333 {
Wolfgang Betz 34:edda6a7238ec 334 disable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 335
Wolfgang Betz 34:edda6a7238ec 336 /* Checks if the RX buffer is empty */
Wolfgang Betz 34:edda6a7238ec 337 if(IS_RXBUF_EMPTY()) {
Wolfgang Betz 43:a512f909514a 338 #ifndef NDEBUG
Wolfgang Betz 43:a512f909514a 339 debug("\n\rBuffer is empty\n\r");
Wolfgang Betz 43:a512f909514a 340 #endif
Wolfgang Betz 34:edda6a7238ec 341 set_ready_state();
Wolfgang Betz 34:edda6a7238ec 342
Wolfgang Betz 34:edda6a7238ec 343 cmd_strobe(SPIRIT1_STROBE_RX);
Wolfgang Betz 34:edda6a7238ec 344 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
Wolfgang Betz 34:edda6a7238ec 345 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 346 return 0;
Wolfgang Betz 34:edda6a7238ec 347 }
Wolfgang Betz 34:edda6a7238ec 348
Wolfgang Betz 34:edda6a7238ec 349 if(bufsize < spirit_rx_len) {
Wolfgang Betz 34:edda6a7238ec 350 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 351
Wolfgang Betz 34:edda6a7238ec 352 /* If buf has the correct size */
Wolfgang Betz 34:edda6a7238ec 353 #ifndef NDEBUG
Wolfgang Betz 34:edda6a7238ec 354 debug("\n\rTOO SMALL BUF\n\r");
Wolfgang Betz 34:edda6a7238ec 355 #endif
Wolfgang Betz 34:edda6a7238ec 356 return 0;
Wolfgang Betz 34:edda6a7238ec 357 } else {
Wolfgang Betz 34:edda6a7238ec 358 /* Copies the packet received */
Wolfgang Betz 34:edda6a7238ec 359 memcpy(buf, spirit_rx_buf, spirit_rx_len);
Wolfgang Betz 34:edda6a7238ec 360
Wolfgang Betz 34:edda6a7238ec 361 bufsize = spirit_rx_len;
Wolfgang Betz 34:edda6a7238ec 362 CLEAR_RXBUF();
Wolfgang Betz 34:edda6a7238ec 363
Wolfgang Betz 34:edda6a7238ec 364 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 365
Wolfgang Betz 34:edda6a7238ec 366 return bufsize;
Wolfgang Betz 34:edda6a7238ec 367 }
Wolfgang Betz 34:edda6a7238ec 368
Wolfgang Betz 34:edda6a7238ec 369 }
Wolfgang Betz 34:edda6a7238ec 370
Wolfgang Betz 34:edda6a7238ec 371 int SimpleSpirit1::channel_clear(void)
Wolfgang Betz 34:edda6a7238ec 372 {
Wolfgang Betz 34:edda6a7238ec 373 float rssi_value;
Wolfgang Betz 34:edda6a7238ec 374 /* Local variable used to memorize the SPIRIT1 state */
Wolfgang Betz 34:edda6a7238ec 375 uint8_t spirit_state = ON;
Wolfgang Betz 34:edda6a7238ec 376
Wolfgang Betz 34:edda6a7238ec 377 if(spirit_on == OFF) {
Wolfgang Betz 34:edda6a7238ec 378 /* Wakes up the SPIRIT1 */
Wolfgang Betz 34:edda6a7238ec 379 on();
Wolfgang Betz 34:edda6a7238ec 380 spirit_state = OFF;
Wolfgang Betz 34:edda6a7238ec 381 }
Wolfgang Betz 34:edda6a7238ec 382
Wolfgang Betz 34:edda6a7238ec 383 #ifndef NDEBUG
Wolfgang Betz 34:edda6a7238ec 384 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
Wolfgang Betz 34:edda6a7238ec 385 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
Wolfgang Betz 34:edda6a7238ec 386 }
Wolfgang Betz 34:edda6a7238ec 387 #endif
Wolfgang Betz 34:edda6a7238ec 388
Wolfgang Betz 34:edda6a7238ec 389 disable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 390
Wolfgang Betz 34:edda6a7238ec 391 /* Reset State to Ready */
Wolfgang Betz 34:edda6a7238ec 392 set_ready_state();
Wolfgang Betz 34:edda6a7238ec 393
Wolfgang Betz 34:edda6a7238ec 394 /* Stores the RSSI value */
Wolfgang Betz 34:edda6a7238ec 395 rssi_value = qi_get_rssi_dbm();
Wolfgang Betz 34:edda6a7238ec 396
Wolfgang Betz 34:edda6a7238ec 397 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 398
Wolfgang Betz 34:edda6a7238ec 399 /* Puts the SPIRIT1 in its previous state */
Wolfgang Betz 34:edda6a7238ec 400 if(spirit_state==OFF) {
Wolfgang Betz 34:edda6a7238ec 401 off();
Wolfgang Betz 34:edda6a7238ec 402 #ifndef NDEBUG
Wolfgang Betz 34:edda6a7238ec 403 #ifdef USE_STANDBY_STATE
Wolfgang Betz 34:edda6a7238ec 404 if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
Wolfgang Betz 34:edda6a7238ec 405 #else
Wolfgang Betz 34:edda6a7238ec 406 if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
Wolfgang Betz 34:edda6a7238ec 407 #endif
Wolfgang Betz 34:edda6a7238ec 408 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
Wolfgang Betz 34:edda6a7238ec 409 }
Wolfgang Betz 34:edda6a7238ec 410 #endif
Wolfgang Betz 34:edda6a7238ec 411 } else {
Wolfgang Betz 34:edda6a7238ec 412 disable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 413
Wolfgang Betz 34:edda6a7238ec 414 set_ready_state();
Wolfgang Betz 34:edda6a7238ec 415
Wolfgang Betz 34:edda6a7238ec 416 cmd_strobe(SPIRIT1_STROBE_RX);
Wolfgang Betz 34:edda6a7238ec 417 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
Wolfgang Betz 34:edda6a7238ec 418 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
Wolfgang Betz 34:edda6a7238ec 419 error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1);
Wolfgang Betz 34:edda6a7238ec 420 }
Wolfgang Betz 34:edda6a7238ec 421
Wolfgang Betz 34:edda6a7238ec 422 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 423
Wolfgang Betz 34:edda6a7238ec 424 #ifndef NDEBUG
Wolfgang Betz 34:edda6a7238ec 425 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
Wolfgang Betz 34:edda6a7238ec 426 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
Wolfgang Betz 34:edda6a7238ec 427 }
Wolfgang Betz 34:edda6a7238ec 428 #endif
Wolfgang Betz 34:edda6a7238ec 429 }
Wolfgang Betz 34:edda6a7238ec 430
Wolfgang Betz 34:edda6a7238ec 431 /* Checks the RSSI value with the threshold */
Wolfgang Betz 34:edda6a7238ec 432 if(rssi_value<CCA_THRESHOLD) {
Wolfgang Betz 34:edda6a7238ec 433 return 0;
Wolfgang Betz 34:edda6a7238ec 434 } else {
Wolfgang Betz 34:edda6a7238ec 435 return 1;
Wolfgang Betz 34:edda6a7238ec 436 }
Wolfgang Betz 34:edda6a7238ec 437 }
Wolfgang Betz 34:edda6a7238ec 438
Wolfgang Betz 34:edda6a7238ec 439 int SimpleSpirit1::get_pending_packet(void)
Wolfgang Betz 34:edda6a7238ec 440 {
Wolfgang Betz 34:edda6a7238ec 441 return !IS_RXBUF_EMPTY();
Wolfgang Betz 34:edda6a7238ec 442 }
Wolfgang Betz 34:edda6a7238ec 443
Wolfgang Betz 34:edda6a7238ec 444 /** Spirit Irq Callback **/
Wolfgang Betz 57:8cc871dc6cac 445 /* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */
Wolfgang Betz 34:edda6a7238ec 446 void SimpleSpirit1::IrqHandler() {
Wolfgang Betz 34:edda6a7238ec 447 st_lib_spirit_irqs x_irq_status;
Wolfgang Betz 34:edda6a7238ec 448
Wolfgang Betz 34:edda6a7238ec 449 /* get interrupt source from radio */
Wolfgang Betz 34:edda6a7238ec 450 irq_get_status(&x_irq_status);
Wolfgang Betz 34:edda6a7238ec 451
Wolfgang Betz 45:2d01cc9bc761 452 /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
Wolfgang Betz 45:2d01cc9bc761 453 if(x_irq_status.IRQ_TX_DATA_SENT) {
Wolfgang Betz 34:edda6a7238ec 454 #ifdef DEBUG_IRQ
Wolfgang Betz 34:edda6a7238ec 455 uint32_t *tmp = (uint32_t*)&x_irq_status;
Wolfgang Betz 45:2d01cc9bc761 456 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 45:2d01cc9bc761 457 debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 45:2d01cc9bc761 458 debug_if(tx_fifo_remaining != 0, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 34:edda6a7238ec 459 #endif
Wolfgang Betz 45:2d01cc9bc761 460
Wolfgang Betz 45:2d01cc9bc761 461 tx_fifo_buffer = NULL;
Wolfgang Betz 45:2d01cc9bc761 462 _spirit_tx_started = false;
Wolfgang Betz 45:2d01cc9bc761 463
Wolfgang Betz 45:2d01cc9bc761 464 /* call user callback */
Wolfgang Betz 45:2d01cc9bc761 465 if(_current_irq_callback) {
Wolfgang Betz 45:2d01cc9bc761 466 _current_irq_callback(TX_DONE);
Wolfgang Betz 34:edda6a7238ec 467 }
Wolfgang Betz 40:343254875d89 468
Wolfgang Betz 45:2d01cc9bc761 469 /* Disable handling of other TX flags */
Wolfgang Betz 46:d104e58c5caf 470 x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET;
Wolfgang Betz 45:2d01cc9bc761 471 }
Wolfgang Betz 45:2d01cc9bc761 472
Wolfgang Betz 47:3a30b960a8c2 473 #ifndef RX_FIFO_THR_WA
Wolfgang Betz 45:2d01cc9bc761 474 /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
Wolfgang Betz 45:2d01cc9bc761 475 if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
Wolfgang Betz 45:2d01cc9bc761 476 #ifdef DEBUG_IRQ
Wolfgang Betz 45:2d01cc9bc761 477 uint32_t *tmp = (uint32_t*)&x_irq_status;
Wolfgang Betz 45:2d01cc9bc761 478 debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 45:2d01cc9bc761 479 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 45:2d01cc9bc761 480 debug_if(tx_fifo_buffer == NULL, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 45:2d01cc9bc761 481 #endif
Wolfgang Betz 45:2d01cc9bc761 482
Wolfgang Betz 45:2d01cc9bc761 483 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
Wolfgang Betz 45:2d01cc9bc761 484 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
Wolfgang Betz 45:2d01cc9bc761 485
Wolfgang Betz 45:2d01cc9bc761 486 tx_fifo_remaining -= to_send;
Wolfgang Betz 45:2d01cc9bc761 487
Wolfgang Betz 45:2d01cc9bc761 488 /* Fill FIFO Buffer */
Wolfgang Betz 45:2d01cc9bc761 489 if(to_send > 0) {
Wolfgang Betz 45:2d01cc9bc761 490 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
Wolfgang Betz 45:2d01cc9bc761 491 }
Wolfgang Betz 45:2d01cc9bc761 492 tx_buffer_pos += to_send;
Wolfgang Betz 34:edda6a7238ec 493 }
Wolfgang Betz 47:3a30b960a8c2 494 #endif // !RX_FIFO_THR_WA
Wolfgang Betz 34:edda6a7238ec 495
Wolfgang Betz 34:edda6a7238ec 496 /* Transmission error */
Wolfgang Betz 34:edda6a7238ec 497 if(x_irq_status.IRQ_TX_FIFO_ERROR) {
Wolfgang Betz 34:edda6a7238ec 498 #ifdef DEBUG_IRQ
Wolfgang Betz 34:edda6a7238ec 499 uint32_t *tmp = (uint32_t*)&x_irq_status;
Wolfgang Betz 43:a512f909514a 500 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
Wolfgang Betz 43:a512f909514a 501 debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 34:edda6a7238ec 502 #endif
Wolfgang Betz 34:edda6a7238ec 503 if(_spirit_tx_started) {
Wolfgang Betz 34:edda6a7238ec 504 _spirit_tx_started = false;
Wolfgang Betz 34:edda6a7238ec 505 /* call user callback */
Wolfgang Betz 34:edda6a7238ec 506 if(_current_irq_callback) {
Wolfgang Betz 34:edda6a7238ec 507 _current_irq_callback(TX_ERR);
Wolfgang Betz 34:edda6a7238ec 508 }
Wolfgang Betz 34:edda6a7238ec 509 }
Wolfgang Betz 40:343254875d89 510
Wolfgang Betz 45:2d01cc9bc761 511 /* reset data still to be sent */
Wolfgang Betz 45:2d01cc9bc761 512 tx_fifo_remaining = 0;
Wolfgang Betz 34:edda6a7238ec 513 }
Wolfgang Betz 34:edda6a7238ec 514
Wolfgang Betz 34:edda6a7238ec 515 /* The IRQ_RX_DATA_READY notifies a new packet arrived */
Wolfgang Betz 34:edda6a7238ec 516 if(x_irq_status.IRQ_RX_DATA_READY) {
Wolfgang Betz 42:92a60a905ee7 517 #ifdef DEBUG_IRQ
Wolfgang Betz 42:92a60a905ee7 518 uint32_t *tmp = (uint32_t*)&x_irq_status;
Wolfgang Betz 43:a512f909514a 519 debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 42:92a60a905ee7 520 #endif
Wolfgang Betz 34:edda6a7238ec 521
Wolfgang Betz 44:aedd63cb0ce3 522 if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!)
Wolfgang Betz 44:aedd63cb0ce3 523 #ifdef HEAVY_DEBUG
Wolfgang Betz 43:a512f909514a 524 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
Wolfgang Betz 43:a512f909514a 525 #endif
Wolfgang Betz 43:a512f909514a 526 } else {
Wolfgang Betz 43:a512f909514a 527 _is_receiving = false; // Finished receiving
Wolfgang Betz 43:a512f909514a 528 stop_rx_timeout();
Wolfgang Betz 43:a512f909514a 529
Wolfgang Betz 43:a512f909514a 530 spirit_rx_len = pkt_basic_get_received_pkt_length();
Wolfgang Betz 34:edda6a7238ec 531
Wolfgang Betz 34:edda6a7238ec 532 #ifdef DEBUG_IRQ
Wolfgang Betz 48:373e1b7e424f 533 debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
Wolfgang Betz 34:edda6a7238ec 534 #endif
Wolfgang Betz 34:edda6a7238ec 535
Wolfgang Betz 48:373e1b7e424f 536 if(spirit_rx_len <= MAX_PACKET_LEN) {
Wolfgang Betz 43:a512f909514a 537 uint8_t to_receive = spirit_rx_len - _spirit_rx_pos;
Wolfgang Betz 43:a512f909514a 538 if(to_receive > 0) {
Wolfgang Betz 43:a512f909514a 539 spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]);
Wolfgang Betz 43:a512f909514a 540 _spirit_rx_pos += to_receive;
Wolfgang Betz 43:a512f909514a 541 }
Wolfgang Betz 34:edda6a7238ec 542 }
Wolfgang Betz 43:a512f909514a 543
Wolfgang Betz 43:a512f909514a 544 cmd_strobe(SPIRIT1_STROBE_FRX);
Wolfgang Betz 43:a512f909514a 545
Wolfgang Betz 43:a512f909514a 546 last_rssi = qi_get_rssi(); //MGR
Wolfgang Betz 43:a512f909514a 547 last_sqi = qi_get_sqi(); //MGR
Wolfgang Betz 43:a512f909514a 548
Wolfgang Betz 43:a512f909514a 549 /* call user callback */
Wolfgang Betz 48:373e1b7e424f 550 if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) {
Wolfgang Betz 43:a512f909514a 551 _current_irq_callback(RX_DONE);
Wolfgang Betz 43:a512f909514a 552 }
Wolfgang Betz 43:a512f909514a 553
Wolfgang Betz 43:a512f909514a 554 /* Disable handling of other RX flags */
Wolfgang Betz 46:d104e58c5caf 555 x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
Wolfgang Betz 40:343254875d89 556 }
Wolfgang Betz 43:a512f909514a 557 }
Wolfgang Betz 34:edda6a7238ec 558
Wolfgang Betz 47:3a30b960a8c2 559 #ifndef RX_FIFO_THR_WA
Wolfgang Betz 43:a512f909514a 560 /* RX FIFO almost full */
Wolfgang Betz 43:a512f909514a 561 if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) {
Wolfgang Betz 43:a512f909514a 562 #ifdef DEBUG_IRQ
Wolfgang Betz 43:a512f909514a 563 uint32_t *tmp = (uint32_t*)&x_irq_status;
Wolfgang Betz 43:a512f909514a 564 debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 43:a512f909514a 565 #endif
Wolfgang Betz 43:a512f909514a 566 if(!_is_receiving) { // spurious irq?!?
Wolfgang Betz 43:a512f909514a 567 #ifdef DEBUG_IRQ
Wolfgang Betz 43:a512f909514a 568 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
Wolfgang Betz 43:a512f909514a 569 #endif
Wolfgang Betz 43:a512f909514a 570 } else {
Wolfgang Betz 43:a512f909514a 571 uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
Wolfgang Betz 48:373e1b7e424f 572 if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) {
Wolfgang Betz 48:373e1b7e424f 573 spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
Wolfgang Betz 48:373e1b7e424f 574 _spirit_rx_pos += fifo_available;
Wolfgang Betz 48:373e1b7e424f 575 } else {
Wolfgang Betz 48:373e1b7e424f 576 #ifdef DEBUG_IRQ
Wolfgang Betz 48:373e1b7e424f 577 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
Wolfgang Betz 48:373e1b7e424f 578 #endif
Wolfgang Betz 48:373e1b7e424f 579 }
Wolfgang Betz 45:2d01cc9bc761 580 }
Wolfgang Betz 45:2d01cc9bc761 581 }
Wolfgang Betz 47:3a30b960a8c2 582 #endif // !RX_FIFO_THR_WA
Wolfgang Betz 43:a512f909514a 583
Wolfgang Betz 45:2d01cc9bc761 584 /* Reception errors */
Wolfgang Betz 45:2d01cc9bc761 585 if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
Wolfgang Betz 45:2d01cc9bc761 586 #ifdef DEBUG_IRQ
Wolfgang Betz 45:2d01cc9bc761 587 uint32_t *tmp = (uint32_t*)&x_irq_status;
Wolfgang Betz 45:2d01cc9bc761 588 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
Wolfgang Betz 45:2d01cc9bc761 589 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 590 #endif
Wolfgang Betz 45:2d01cc9bc761 591 rx_timeout_handler();
Wolfgang Betz 45:2d01cc9bc761 592 if(_spirit_tx_started) {
Wolfgang Betz 45:2d01cc9bc761 593 _spirit_tx_started = false;
Wolfgang Betz 45:2d01cc9bc761 594 /* call user callback */
Wolfgang Betz 45:2d01cc9bc761 595 if(_current_irq_callback) {
Wolfgang Betz 45:2d01cc9bc761 596 _current_irq_callback(TX_ERR);
Wolfgang Betz 45:2d01cc9bc761 597 }
Wolfgang Betz 34:edda6a7238ec 598 }
Wolfgang Betz 34:edda6a7238ec 599 }
Wolfgang Betz 34:edda6a7238ec 600
Wolfgang Betz 34:edda6a7238ec 601 /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
Wolfgang Betz 34:edda6a7238ec 602 if(x_irq_status.IRQ_VALID_SYNC) {
Wolfgang Betz 42:92a60a905ee7 603 #ifdef DEBUG_IRQ
Wolfgang Betz 42:92a60a905ee7 604 uint32_t *tmp = (uint32_t*)&x_irq_status;
Wolfgang Betz 43:a512f909514a 605 debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 42:92a60a905ee7 606 #endif
Wolfgang Betz 39:75481c4c6655 607 /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and
Wolfgang Betz 39:75481c4c6655 608 * the MCU trying to send a packet, which gets resolved in favor of
Wolfgang Betz 39:75481c4c6655 609 * sending.
Wolfgang Betz 39:75481c4c6655 610 */
Wolfgang Betz 39:75481c4c6655 611 if(_spirit_tx_started) {
Wolfgang Betz 34:edda6a7238ec 612 #ifdef DEBUG_IRQ
Wolfgang Betz 43:a512f909514a 613 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
Wolfgang Betz 34:edda6a7238ec 614 #endif
Wolfgang Betz 39:75481c4c6655 615 } else {
Wolfgang Betz 39:75481c4c6655 616 _is_receiving = true;
Wolfgang Betz 39:75481c4c6655 617 start_rx_timeout();
Wolfgang Betz 39:75481c4c6655 618 }
Wolfgang Betz 34:edda6a7238ec 619 }
Wolfgang Betz 34:edda6a7238ec 620 }