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:
Fri Feb 02 14:13:24 2018 +0100
Revision:
82:a18c22d2b83a
Parent:
71:4a7772415d9c
Correct comments/documentation

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