Reem M / Mbed OS http-server-example1
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleSpirit1.cpp Source File

SimpleSpirit1.cpp

00001 /*** Mbed Includes ***/
00002 #include "SimpleSpirit1.h"
00003 #include "radio_spi.h"
00004 
00005 #define SPIRIT_GPIO_IRQ         (SPIRIT_GPIO_3)
00006 
00007 static uint16_t last_state;
00008 #define SPIRIT1_STATUS()        ((last_state = (uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS)
00009 
00010 #define XO_ON                   (0x1)
00011 
00012 #define BUSYWAIT_UNTIL(cond, millisecs)                                                         \
00013         do {                                                                                            \
00014             uint32_t start = us_ticker_read();                                                  \
00015             while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U));  \
00016         } while(0)
00017 
00018 #define st_lib_spirit_irqs      SpiritIrqs
00019 
00020 #define STATE_TIMEOUT           (100)
00021 
00022 // betzw: switching force & back from standby is on some devices quite unstable
00023 #define USE_STANDBY_STATE
00024 
00025 /*** Class Implementation ***/
00026 /** Static Class Variables **/
00027 SimpleSpirit1 *SimpleSpirit1::_singleton = NULL;
00028 
00029 /** Constructor **/
00030 SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
00031         PinName irq, PinName cs, PinName sdn,
00032         PinName led) :
00033             _spi(mosi, miso, sclk),
00034             _irq(irq),
00035             _chip_select(cs),
00036             _shut_down(sdn),
00037             _led(led),
00038             _current_irq_callback(),
00039             _rx_receiving_timeout()
00040 {
00041 }
00042 
00043 /** Init Function **/
00044 void SimpleSpirit1::init() {
00045     /* reset irq disable counter and irq callback & disable irq */
00046     _nr_of_irq_disables = 0;
00047     disable_spirit_irq();
00048 
00049     /* unselect chip */
00050     chip_unselect();
00051 
00052     /* configure spi */
00053     _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
00054     _spi.frequency(10000000); // 10MHz (i.e. max speed allowed for Spirit1)
00055 
00056     /* install irq handler */
00057     _irq.mode(PullUp);
00058     _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler));
00059 
00060     /* init cube vars */
00061     spirit_on = OFF;
00062     last_rssi = 0 ; //MGR
00063     last_sqi = 0 ;  //MGR
00064 
00065     /* set frequencies */
00066     radio_set_xtal_freq(XTAL_FREQUENCY);
00067     mgmt_set_freq_base((uint32_t)BASE_FREQUENCY);
00068 
00069     /* restart board */
00070     enter_shutdown();
00071     exit_shutdown();
00072 
00073     /* soft core reset */
00074     cmd_strobe(SPIRIT1_STROBE_SRES);
00075 
00076     /* Configures the SPIRIT1 radio part */
00077     SRadioInit x_radio_init = {
00078             XTAL_OFFSET_PPM,
00079             (uint32_t)BASE_FREQUENCY,
00080             (uint32_t)CHANNEL_SPACE,
00081             CHANNEL_NUMBER,
00082             MODULATION_SELECT,
00083             DATARATE,
00084             (uint32_t)FREQ_DEVIATION,
00085             (uint32_t)BANDWIDTH
00086     };
00087     radio_init(&x_radio_init);
00088     radio_set_pa_level_dbm(0,POWER_DBM);
00089     radio_set_pa_level_max_index(0);
00090 
00091     /* Configures the SPIRIT1 packet handler part*/
00092     PktBasicInit x_basic_init = {
00093             PREAMBLE_LENGTH,
00094             SYNC_LENGTH,
00095             SYNC_WORD,
00096             LENGTH_TYPE,
00097             LENGTH_WIDTH,
00098             CRC_MODE,
00099             CONTROL_LENGTH,
00100             EN_ADDRESS,
00101             EN_FEC,
00102             EN_WHITENING
00103     };
00104     pkt_basic_init(&x_basic_init);
00105 
00106     /* Enable the following interrupt sources, routed to GPIO */
00107     irq_de_init(NULL);
00108     irq_clear_status();
00109     irq_set_status(TX_DATA_SENT , S_ENABLE);
00110     irq_set_status(RX_DATA_READY ,S_ENABLE);
00111     irq_set_status(RX_DATA_DISC , S_ENABLE);
00112     irq_set_status(VALID_SYNC , S_ENABLE);
00113     irq_set_status(TX_FIFO_ERROR , S_ENABLE);
00114     irq_set_status(RX_FIFO_ERROR , S_ENABLE);
00115 #ifndef RX_FIFO_THR_WA
00116     irq_set_status(TX_FIFO_ALMOST_EMPTY , S_ENABLE);
00117     irq_set_status(RX_FIFO_ALMOST_FULL , S_ENABLE);
00118 #endif // !RX_FIFO_THR_WA
00119 
00120     /* Configure Spirit1 */
00121     radio_persistent_rx(S_ENABLE);
00122     qi_set_sqi_threshold(SQI_TH_0);
00123     qi_sqi_check(S_ENABLE);
00124     qi_set_rssi_threshold_dbm(CCA_THRESHOLD);
00125     timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD);
00126     timer_set_infinite_rx_timeout();
00127     radio_afc_freeze_on_sync(S_ENABLE);
00128     calibration_rco(S_ENABLE);
00129 
00130     spirit_on = OFF;
00131     CLEAR_TXBUF();
00132     CLEAR_RXBUF();
00133     _spirit_tx_started = false;
00134     _is_receiving = false;
00135 
00136     /* Configure the radio to route the IRQ signal to its GPIO 3 */
00137     SGpioInit x_gpio_init = {
00138             SPIRIT_GPIO_IRQ,
00139             SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP ,
00140             SPIRIT_GPIO_DIG_OUT_IRQ 
00141     };
00142     spirit_gpio_init(&x_gpio_init);
00143 
00144     /* Setup CSMA/CA */
00145     CsmaInit x_csma_init = {
00146             S_ENABLE,         // enable persistent mode
00147             TBIT_TIME_64 ,     // Tcca time
00148             TCCA_TIME_3 ,      // Lcca length
00149             3,                // max nr of backoffs (<8)
00150             1,                // BU counter seed
00151             8                 // BU prescaler
00152     };
00153     csma_ca_init(&x_csma_init);
00154 
00155 #ifdef USE_STANDBY_STATE
00156     /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
00157     cmd_strobe(SPIRIT1_STROBE_STANDBY);
00158 #endif // USE_STANDBY_STATE
00159 }
00160 
00161 static volatile int tx_fifo_remaining = 0;     // to be used in irq handler
00162 static volatile int tx_buffer_pos = 0;         // to be used in irq handler
00163 const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler
00164 int SimpleSpirit1::send(const void *payload, unsigned int payload_len) {
00165     /* Checks if the payload length is supported */
00166     if(payload_len > MAX_PACKET_LEN) {
00167         return RADIO_TX_ERR;
00168     }
00169 
00170     disable_spirit_irq();
00171 
00172     BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
00173 #ifndef NDEBUG
00174     if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
00175         debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
00176     }
00177 #endif
00178 
00179     /* Reset State to Ready */
00180     set_ready_state();
00181 
00182     cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer
00183 
00184 #ifndef NDEBUG
00185     debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00186 #endif
00187 
00188     pkt_basic_set_payload_length(payload_len); // set desired payload len
00189 
00190     csma_ca_state(S_ENABLE); // enable CSMA/CA
00191 
00192     /* Init buffer & number of bytes to be send */
00193     tx_fifo_remaining = payload_len;
00194     tx_fifo_buffer = (const uint8_t*)payload;
00195 
00196     int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
00197     int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
00198 
00199     tx_fifo_remaining -= to_send;
00200 
00201     /* Fill FIFO Buffer */
00202     if(to_send > 0) {
00203         spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
00204     }
00205 
00206     tx_buffer_pos = to_send;
00207     _spirit_tx_started = true;
00208 
00209     enable_spirit_irq();
00210 
00211     /* Start transmitting */
00212     cmd_strobe(SPIRIT1_STROBE_TX);
00213 
00214     while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
00215 
00216     BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
00217 #ifdef HEAVY_DEBUG
00218     debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
00219 #endif
00220 
00221     _spirit_tx_started = false; // in case of state timeout
00222 
00223     csma_ca_state(S_DISABLE); // disable CSMA/CA
00224 
00225     cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
00226 
00227     return RADIO_TX_OK;
00228 }
00229 
00230 /** Set Ready State **/
00231 void SimpleSpirit1::set_ready_state(void) {
00232     uint16_t state;
00233 
00234     disable_spirit_irq();
00235 
00236     _spirit_tx_started = false;
00237     _is_receiving = false;
00238     stop_rx_timeout();
00239 
00240     cmd_strobe(SPIRIT1_STROBE_FRX);
00241     CLEAR_RXBUF();
00242     CLEAR_TXBUF();
00243 
00244     state = SPIRIT1_STATUS();
00245     if(state == SPIRIT1_STATE_STANDBY) {
00246         cmd_strobe(SPIRIT1_STROBE_READY);
00247     } else if(state == SPIRIT1_STATE_RX) {
00248         cmd_strobe(SPIRIT1_STROBE_SABORT);
00249     } else if(state != SPIRIT1_STATE_READY) {
00250 #ifndef NDEBUG
00251         debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, state>>1);
00252 #endif
00253     }
00254 
00255     BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
00256     if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
00257         error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state);
00258         enable_spirit_irq();
00259         return;
00260     }
00261 
00262     irq_clear_status();
00263 
00264     enable_spirit_irq();
00265 }
00266 
00267 int SimpleSpirit1::off(void) {
00268     if(spirit_on == ON) {
00269         /* Disables the mcu to get IRQ from the SPIRIT1 */
00270         disable_spirit_irq();
00271 
00272         /* first stop rx/tx */
00273         set_ready_state();
00274 
00275 #ifdef USE_STANDBY_STATE
00276         /* Puts the SPIRIT1 in STANDBY */
00277         cmd_strobe(SPIRIT1_STROBE_STANDBY);
00278         BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
00279         if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
00280             error("\n\rSpirit1: failed to enter standby (%x)\n\r", last_state>>1);
00281             return 1;
00282         }
00283 #endif // USE_STANDBY_STATE
00284 
00285         spirit_on = OFF;
00286         _nr_of_irq_disables = 1;
00287     }
00288     return 0;
00289 }
00290 
00291 int SimpleSpirit1::on(void) {
00292     if(spirit_on == OFF) {
00293         set_ready_state();
00294 
00295         /* now we go to Rx */
00296         cmd_strobe(SPIRIT1_STROBE_RX);
00297 
00298         BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
00299         if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
00300             error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1);
00301         }
00302 
00303         /* Enables the mcu to get IRQ from the SPIRIT1 */
00304         spirit_on = ON;
00305 #ifndef NDEBUG
00306         debug_if(!(_nr_of_irq_disables == 1), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00307 #endif
00308         enable_spirit_irq();
00309     }
00310 
00311 #ifndef NDEBUG
00312     if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
00313         debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
00314     }
00315 #endif
00316 
00317     return 0;
00318 }
00319 
00320 uint8_t SimpleSpirit1::refresh_state(void) {
00321     uint8_t mcstate;
00322 
00323     SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
00324 
00325     return mcstate;
00326 }
00327 
00328 int SimpleSpirit1::read(void *buf, unsigned int bufsize)
00329 {
00330     disable_spirit_irq();
00331 
00332     /* Checks if the RX buffer is empty */
00333     if(IS_RXBUF_EMPTY()) {
00334 #ifndef NDEBUG
00335         debug("\n\rBuffer is empty\n\r");
00336 #endif
00337         set_ready_state();
00338 
00339         cmd_strobe(SPIRIT1_STROBE_RX);
00340         BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
00341         enable_spirit_irq();
00342         return 0;
00343     }
00344 
00345     if(bufsize < spirit_rx_len) {
00346         enable_spirit_irq();
00347 
00348         /* If buf has the correct size */
00349 #ifndef NDEBUG
00350         debug("\n\rTOO SMALL BUF\n\r");
00351 #endif
00352         return 0;
00353     } else {
00354         /* Copies the packet received */
00355         memcpy(buf, spirit_rx_buf, spirit_rx_len);
00356 
00357         bufsize = spirit_rx_len;
00358         CLEAR_RXBUF();
00359 
00360         enable_spirit_irq();
00361 
00362         return bufsize;
00363     }
00364 
00365 }
00366 
00367 int SimpleSpirit1::channel_clear(void)
00368 {
00369     float rssi_value;
00370     /* Local variable used to memorize the SPIRIT1 state */
00371     uint8_t spirit_state = ON;
00372 
00373     if(spirit_on == OFF) {
00374         /* Wakes up the SPIRIT1 */
00375         on();
00376         spirit_state = OFF;
00377     }
00378 
00379 #ifndef NDEBUG
00380     if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
00381         debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
00382     }
00383 #endif
00384 
00385     disable_spirit_irq();
00386 
00387     /* Reset State to Ready */
00388     set_ready_state();
00389 
00390     /* Stores the RSSI value */
00391     rssi_value = qi_get_rssi_dbm();
00392 
00393     enable_spirit_irq();
00394 
00395     /* Puts the SPIRIT1 in its previous state */
00396     if(spirit_state==OFF) {
00397         off();
00398 #ifndef NDEBUG
00399 #ifdef USE_STANDBY_STATE
00400         if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
00401 #else
00402         if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
00403 #endif
00404             debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
00405         }
00406 #endif
00407     } else {
00408         disable_spirit_irq();
00409 
00410         set_ready_state();
00411 
00412         cmd_strobe(SPIRIT1_STROBE_RX);
00413         BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
00414         if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
00415             error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1);
00416         }
00417 
00418         enable_spirit_irq();
00419 
00420 #ifndef NDEBUG
00421         if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
00422             debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
00423         }
00424 #endif
00425     }
00426 
00427     /* Checks the RSSI value with the threshold */
00428     if(rssi_value<CCA_THRESHOLD) {
00429         return 0;
00430     } else {
00431         return 1;
00432     }
00433 }
00434 
00435 int SimpleSpirit1::get_pending_packet(void)
00436 {
00437     return !IS_RXBUF_EMPTY();
00438 }
00439 
00440 /** Spirit Irq Callback **/
00441 /* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */
00442 void SimpleSpirit1::IrqHandler() {
00443     st_lib_spirit_irqs x_irq_status;
00444 
00445     /* get interrupt source from radio */
00446     irq_get_status(&x_irq_status);
00447 
00448     /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
00449     if(x_irq_status.IRQ_TX_DATA_SENT) {
00450 #ifdef DEBUG_IRQ
00451         uint32_t *tmp = (uint32_t*)&x_irq_status;
00452         debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00453         debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00454         debug_if(tx_fifo_remaining != 0, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00455 #endif
00456 
00457         tx_fifo_buffer = NULL;
00458         _spirit_tx_started = false;
00459 
00460         /* call user callback */
00461         if(_current_irq_callback) {
00462             _current_irq_callback(TX_DONE);
00463         }
00464 
00465         /* Disable handling of other TX flags */
00466         x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET;
00467     }
00468 
00469 #ifndef RX_FIFO_THR_WA
00470     /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
00471     if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
00472 #ifdef DEBUG_IRQ
00473         uint32_t *tmp = (uint32_t*)&x_irq_status;
00474         debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00475         debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00476         debug_if(tx_fifo_buffer == NULL, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00477 #endif
00478 
00479         int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
00480         int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
00481 
00482         tx_fifo_remaining -= to_send;
00483 
00484         /* Fill FIFO Buffer */
00485         if(to_send > 0) {
00486             spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
00487         }
00488         tx_buffer_pos += to_send;
00489     }
00490 #endif // !RX_FIFO_THR_WA
00491 
00492     /* Transmission error */
00493     if(x_irq_status.IRQ_TX_FIFO_ERROR) {
00494 #ifdef DEBUG_IRQ
00495         uint32_t *tmp = (uint32_t*)&x_irq_status;
00496         debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
00497         debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00498 #endif
00499         if(_spirit_tx_started) {
00500             _spirit_tx_started = false;
00501             /* call user callback */
00502             if(_current_irq_callback) {
00503                 _current_irq_callback(TX_ERR);
00504             }
00505         }
00506 
00507         /* reset data still to be sent */
00508         tx_fifo_remaining = 0;
00509     }
00510 
00511     /* The IRQ_RX_DATA_READY notifies a new packet arrived */
00512     if(x_irq_status.IRQ_RX_DATA_READY) {
00513 #ifdef DEBUG_IRQ
00514         uint32_t *tmp = (uint32_t*)&x_irq_status;
00515         debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00516 #endif
00517 
00518         if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!)
00519 #ifdef HEAVY_DEBUG
00520             debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
00521 #endif
00522         } else {
00523             _is_receiving = false; // Finished receiving
00524             stop_rx_timeout();
00525 
00526             spirit_rx_len = pkt_basic_get_received_pkt_length();
00527 
00528 #ifdef DEBUG_IRQ
00529             debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
00530 #endif
00531 
00532             if(spirit_rx_len <= MAX_PACKET_LEN) {
00533                 uint8_t to_receive = spirit_rx_len - _spirit_rx_pos;
00534                 if(to_receive > 0) {
00535                     spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]);
00536                     _spirit_rx_pos += to_receive;
00537                 }
00538             }
00539 
00540             cmd_strobe(SPIRIT1_STROBE_FRX);
00541 
00542             last_rssi = qi_get_rssi(); //MGR
00543             last_sqi  = qi_get_sqi();  //MGR
00544 
00545             /* call user callback */
00546             if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) {
00547                 _current_irq_callback(RX_DONE);
00548             }
00549 
00550             /* Disable handling of other RX flags */
00551             x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
00552         }
00553     }
00554 
00555 #ifndef RX_FIFO_THR_WA
00556     /* RX FIFO almost full */
00557     if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) {
00558 #ifdef DEBUG_IRQ
00559         uint32_t *tmp = (uint32_t*)&x_irq_status;
00560         debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00561 #endif
00562         if(!_is_receiving) { // spurious irq?!?
00563 #ifdef DEBUG_IRQ
00564             debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
00565 #endif
00566         } else {
00567             uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
00568             if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) {
00569                 spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
00570                 _spirit_rx_pos += fifo_available;
00571             } else {
00572 #ifdef DEBUG_IRQ
00573                 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
00574 #endif
00575             }
00576         }
00577     }
00578 #endif // !RX_FIFO_THR_WA
00579 
00580     /* Reception errors */
00581     if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
00582 #ifdef DEBUG_IRQ
00583         uint32_t *tmp = (uint32_t*)&x_irq_status;
00584         debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
00585         debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00586 #endif
00587         rx_timeout_handler();
00588         if(_spirit_tx_started) {
00589             _spirit_tx_started = false;
00590             /* call user callback */
00591             if(_current_irq_callback) {
00592                 _current_irq_callback(TX_ERR);
00593             }
00594         }
00595     }
00596 
00597     /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
00598     if(x_irq_status.IRQ_VALID_SYNC) {
00599 #ifdef DEBUG_IRQ
00600         uint32_t *tmp = (uint32_t*)&x_irq_status;
00601         debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
00602 #endif
00603         /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and
00604          *               the MCU trying to send a packet, which gets resolved in favor of
00605          *               sending.
00606          */
00607         if(_spirit_tx_started) {
00608 #ifdef DEBUG_IRQ
00609             debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
00610 #endif
00611         } else {
00612             _is_receiving = true;
00613             start_rx_timeout();
00614         }
00615     }
00616 }