Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: WNC14A2AInterface
Dependents: http-example-wnc http-example-wnc-modified
Diff: stm-spirit1-rf-driver/source/SimpleSpirit1.cpp
- Revision:
- 0:2563b0415d1f
diff -r 000000000000 -r 2563b0415d1f stm-spirit1-rf-driver/source/SimpleSpirit1.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stm-spirit1-rf-driver/source/SimpleSpirit1.cpp Wed Apr 19 01:13:10 2017 +0000
@@ -0,0 +1,615 @@
+/*** Mbed Includes ***/
+#include "SimpleSpirit1.h"
+#include "radio_spi.h"
+
+#define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_3)
+
+static uint16_t last_state;
+#define SPIRIT1_STATUS() ((last_state = (uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS)
+
+#define XO_ON (0x1)
+
+#define BUSYWAIT_UNTIL(cond, millisecs) \
+ do { \
+ uint32_t start = us_ticker_read(); \
+ while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U)); \
+ } while(0)
+
+#define st_lib_spirit_irqs SpiritIrqs
+
+#define STATE_TIMEOUT (100)
+
+// betzw: switching force & back from standby is on some devices quite unstable
+#define USE_STANDBY_STATE
+
+/*** Class Implementation ***/
+/** Static Class Variables **/
+SimpleSpirit1 *SimpleSpirit1::_singleton = NULL;
+
+/** Constructor **/
+SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
+ PinName irq, PinName cs, PinName sdn,
+ PinName led) :
+ _spi(mosi, miso, sclk),
+ _irq(irq),
+ _chip_select(cs),
+ _shut_down(sdn),
+ _led(led),
+ _current_irq_callback(),
+ _rx_receiving_timeout()
+{
+}
+
+/** Init Function **/
+void SimpleSpirit1::init() {
+ /* reset irq disable counter and irq callback & disable irq */
+ _nr_of_irq_disables = 0;
+ disable_spirit_irq();
+
+ /* unselect chip */
+ chip_unselect();
+
+ /* configure spi */
+ _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
+ _spi.frequency(1000000); // 1MHz // betzw: heuristic value // betzw - NOTE: high frequencies lead to instability of Spirit1
+
+ /* install irq handler */
+ _irq.mode(PullUp);
+ _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler));
+
+ /* init cube vars */
+ spirit_on = OFF;
+ last_rssi = 0 ; //MGR
+ last_sqi = 0 ; //MGR
+
+ /* set frequencies */
+ radio_set_xtal_freq(XTAL_FREQUENCY);
+ mgmt_set_freq_base((uint32_t)BASE_FREQUENCY);
+
+ /* restart board */
+ enter_shutdown();
+ exit_shutdown();
+
+ /* soft core reset */
+ cmd_strobe(SPIRIT1_STROBE_SRES);
+
+ /* Configures the SPIRIT1 radio part */
+ SRadioInit x_radio_init = {
+ XTAL_OFFSET_PPM,
+ (uint32_t)BASE_FREQUENCY,
+ (uint32_t)CHANNEL_SPACE,
+ CHANNEL_NUMBER,
+ MODULATION_SELECT,
+ DATARATE,
+ (uint32_t)FREQ_DEVIATION,
+ (uint32_t)BANDWIDTH
+ };
+ radio_init(&x_radio_init);
+ radio_set_pa_level_dbm(0,POWER_DBM);
+ radio_set_pa_level_max_index(0);
+
+ /* Configures the SPIRIT1 packet handler part*/
+ PktBasicInit x_basic_init = {
+ PREAMBLE_LENGTH,
+ SYNC_LENGTH,
+ SYNC_WORD,
+ LENGTH_TYPE,
+ LENGTH_WIDTH,
+ CRC_MODE,
+ CONTROL_LENGTH,
+ EN_ADDRESS,
+ EN_FEC,
+ EN_WHITENING
+ };
+ pkt_basic_init(&x_basic_init);
+
+ /* Enable the following interrupt sources, routed to GPIO */
+ irq_de_init(NULL);
+ irq_clear_status();
+ irq_set_status(TX_DATA_SENT, S_ENABLE);
+ irq_set_status(RX_DATA_READY,S_ENABLE);
+ irq_set_status(RX_DATA_DISC, S_ENABLE);
+ irq_set_status(VALID_SYNC, S_ENABLE);
+ irq_set_status(TX_FIFO_ERROR, S_ENABLE);
+ irq_set_status(RX_FIFO_ERROR, S_ENABLE);
+#ifndef RX_FIFO_THR_WA
+ irq_set_status(TX_FIFO_ALMOST_EMPTY, S_ENABLE);
+ irq_set_status(RX_FIFO_ALMOST_FULL, S_ENABLE);
+#endif // !RX_FIFO_THR_WA
+
+ /* Configure Spirit1 */
+ radio_persistent_rx(S_ENABLE);
+ qi_set_sqi_threshold(SQI_TH_0);
+ qi_sqi_check(S_ENABLE);
+ qi_set_rssi_threshold_dbm(CCA_THRESHOLD);
+ timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD);
+ timer_set_infinite_rx_timeout();
+ radio_afc_freeze_on_sync(S_ENABLE);
+ calibration_rco(S_ENABLE);
+
+ spirit_on = OFF;
+ CLEAR_TXBUF();
+ CLEAR_RXBUF();
+ _spirit_tx_started = false;
+ _is_receiving = false;
+
+ /* Configure the radio to route the IRQ signal to its GPIO 3 */
+ SGpioInit x_gpio_init = {
+ SPIRIT_GPIO_IRQ,
+ SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP,
+ SPIRIT_GPIO_DIG_OUT_IRQ
+ };
+ spirit_gpio_init(&x_gpio_init);
+
+ /* Setup CSMA/CA */
+ CsmaInit x_csma_init = {
+ S_ENABLE, // enable persistent mode
+ TBIT_TIME_64, // Tcca time
+ TCCA_TIME_3, // Lcca length
+ 3, // max nr of backoffs (<8)
+ 1, // BU counter seed
+ 8 // BU prescaler
+ };
+ csma_ca_init(&x_csma_init);
+
+#ifdef USE_STANDBY_STATE
+ /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
+ cmd_strobe(SPIRIT1_STROBE_STANDBY);
+#endif // USE_STANDBY_STATE
+}
+
+static volatile int tx_fifo_remaining = 0; // to be used in irq handler
+static volatile int tx_buffer_pos = 0; // to be used in irq handler
+const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler
+int SimpleSpirit1::send(const void *payload, unsigned int payload_len) {
+ /* Checks if the payload length is supported */
+ if(payload_len > MAX_PACKET_LEN) {
+ return RADIO_TX_ERR;
+ }
+
+ disable_spirit_irq();
+
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+#ifndef NDEBUG
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
+ debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+ }
+#endif
+
+ /* Reset State to Ready */
+ set_ready_state();
+
+ cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer
+
+#ifndef NDEBUG
+ debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+ pkt_basic_set_payload_length(payload_len); // set desired payload len
+
+ csma_ca_state(S_ENABLE); // enable CSMA/CA
+
+ /* Init buffer & number of bytes to be send */
+ tx_fifo_remaining = payload_len;
+ tx_fifo_buffer = (const uint8_t*)payload;
+
+ int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
+ int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
+
+ tx_fifo_remaining -= to_send;
+
+ /* Fill FIFO Buffer */
+ if(to_send > 0) {
+ spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
+ }
+
+ tx_buffer_pos = to_send;
+ _spirit_tx_started = true;
+
+ enable_spirit_irq();
+
+ /* Start transmitting */
+ cmd_strobe(SPIRIT1_STROBE_TX);
+
+ while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
+
+ BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
+#ifdef HEAVY_DEBUG
+ debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
+#endif
+
+ _spirit_tx_started = false; // in case of state timeout
+
+ csma_ca_state(S_DISABLE); // disable CSMA/CA
+
+ cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
+
+ return RADIO_TX_OK;
+}
+
+/** Set Ready State **/
+void SimpleSpirit1::set_ready_state(void) {
+ uint16_t state;
+
+ disable_spirit_irq();
+
+ _spirit_tx_started = false;
+ _is_receiving = false;
+ stop_rx_timeout();
+
+ cmd_strobe(SPIRIT1_STROBE_FRX);
+ CLEAR_RXBUF();
+ CLEAR_TXBUF();
+
+ state = SPIRIT1_STATUS();
+ if(state == SPIRIT1_STATE_STANDBY) {
+ cmd_strobe(SPIRIT1_STROBE_READY);
+ } else if(state == SPIRIT1_STATE_RX) {
+ cmd_strobe(SPIRIT1_STROBE_SABORT);
+ } else if(state != SPIRIT1_STATE_READY) {
+#ifndef NDEBUG
+ debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, state>>1);
+#endif
+ }
+
+ BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
+ if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
+ error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state);
+ enable_spirit_irq();
+ return;
+ }
+
+ irq_clear_status();
+
+ enable_spirit_irq();
+}
+
+int SimpleSpirit1::off(void) {
+ if(spirit_on == ON) {
+ /* Disables the mcu to get IRQ from the SPIRIT1 */
+ disable_spirit_irq();
+
+ /* first stop rx/tx */
+ set_ready_state();
+
+#ifdef USE_STANDBY_STATE
+ /* Puts the SPIRIT1 in STANDBY */
+ cmd_strobe(SPIRIT1_STROBE_STANDBY);
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
+ error("\n\rSpirit1: failed to enter standby (%x)\n\r", last_state>>1);
+ return 1;
+ }
+#endif // USE_STANDBY_STATE
+
+ spirit_on = OFF;
+ _nr_of_irq_disables = 1;
+ }
+ return 0;
+}
+
+int SimpleSpirit1::on(void) {
+ if(spirit_on == OFF) {
+ set_ready_state();
+
+ /* now we go to Rx */
+ cmd_strobe(SPIRIT1_STROBE_RX);
+
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
+ error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1);
+ }
+
+ /* Enables the mcu to get IRQ from the SPIRIT1 */
+ spirit_on = ON;
+#ifndef NDEBUG
+ debug_if(!(_nr_of_irq_disables == 1), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+ enable_spirit_irq();
+ }
+
+#ifndef NDEBUG
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+ debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+ }
+#endif
+
+ return 0;
+}
+
+uint8_t SimpleSpirit1::refresh_state(void) {
+ uint8_t mcstate;
+
+ SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
+
+ return mcstate;
+}
+
+int SimpleSpirit1::read(void *buf, unsigned int bufsize)
+{
+ disable_spirit_irq();
+
+ /* Checks if the RX buffer is empty */
+ if(IS_RXBUF_EMPTY()) {
+#ifndef NDEBUG
+ debug("\n\rBuffer is empty\n\r");
+#endif
+ set_ready_state();
+
+ cmd_strobe(SPIRIT1_STROBE_RX);
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+ enable_spirit_irq();
+ return 0;
+ }
+
+ if(bufsize < spirit_rx_len) {
+ enable_spirit_irq();
+
+ /* If buf has the correct size */
+#ifndef NDEBUG
+ debug("\n\rTOO SMALL BUF\n\r");
+#endif
+ return 0;
+ } else {
+ /* Copies the packet received */
+ memcpy(buf, spirit_rx_buf, spirit_rx_len);
+
+ bufsize = spirit_rx_len;
+ CLEAR_RXBUF();
+
+ enable_spirit_irq();
+
+ return bufsize;
+ }
+
+}
+
+int SimpleSpirit1::channel_clear(void)
+{
+ float rssi_value;
+ /* Local variable used to memorize the SPIRIT1 state */
+ uint8_t spirit_state = ON;
+
+ if(spirit_on == OFF) {
+ /* Wakes up the SPIRIT1 */
+ on();
+ spirit_state = OFF;
+ }
+
+#ifndef NDEBUG
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+ debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+ }
+#endif
+
+ disable_spirit_irq();
+
+ /* Reset State to Ready */
+ set_ready_state();
+
+ /* Stores the RSSI value */
+ rssi_value = qi_get_rssi_dbm();
+
+ enable_spirit_irq();
+
+ /* Puts the SPIRIT1 in its previous state */
+ if(spirit_state==OFF) {
+ off();
+#ifndef NDEBUG
+#ifdef USE_STANDBY_STATE
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
+#else
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
+#endif
+ debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+ }
+#endif
+ } else {
+ disable_spirit_irq();
+
+ set_ready_state();
+
+ cmd_strobe(SPIRIT1_STROBE_RX);
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
+ error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1);
+ }
+
+ enable_spirit_irq();
+
+#ifndef NDEBUG
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+ debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+ }
+#endif
+ }
+
+ /* Checks the RSSI value with the threshold */
+ if(rssi_value<CCA_THRESHOLD) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+int SimpleSpirit1::get_pending_packet(void)
+{
+ return !IS_RXBUF_EMPTY();
+}
+
+/** Spirit Irq Callback **/
+void SimpleSpirit1::IrqHandler() {
+ st_lib_spirit_irqs x_irq_status;
+
+ /* get interrupt source from radio */
+ irq_get_status(&x_irq_status);
+
+ /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
+ if(x_irq_status.IRQ_TX_DATA_SENT) {
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+ debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+ debug_if(tx_fifo_remaining != 0, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+ tx_fifo_buffer = NULL;
+ _spirit_tx_started = false;
+
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(TX_DONE);
+ }
+
+ /* Disable handling of other TX flags */
+ x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET;
+ }
+
+#ifndef RX_FIFO_THR_WA
+ /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
+ if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+ debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+ debug_if(tx_fifo_buffer == NULL, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+ int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
+ int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
+
+ tx_fifo_remaining -= to_send;
+
+ /* Fill FIFO Buffer */
+ if(to_send > 0) {
+ spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
+ }
+ tx_buffer_pos += to_send;
+ }
+#endif // !RX_FIFO_THR_WA
+
+ /* Transmission error */
+ if(x_irq_status.IRQ_TX_FIFO_ERROR) {
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+ debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+ if(_spirit_tx_started) {
+ _spirit_tx_started = false;
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(TX_ERR);
+ }
+ }
+
+ /* reset data still to be sent */
+ tx_fifo_remaining = 0;
+ }
+
+ /* The IRQ_RX_DATA_READY notifies a new packet arrived */
+ if(x_irq_status.IRQ_RX_DATA_READY) {
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+ if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!)
+#ifdef HEAVY_DEBUG
+ debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+ } else {
+ _is_receiving = false; // Finished receiving
+ stop_rx_timeout();
+
+ spirit_rx_len = pkt_basic_get_received_pkt_length();
+
+#ifdef DEBUG_IRQ
+ debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+
+ if(spirit_rx_len <= MAX_PACKET_LEN) {
+ uint8_t to_receive = spirit_rx_len - _spirit_rx_pos;
+ if(to_receive > 0) {
+ spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]);
+ _spirit_rx_pos += to_receive;
+ }
+ }
+
+ cmd_strobe(SPIRIT1_STROBE_FRX);
+
+ last_rssi = qi_get_rssi(); //MGR
+ last_sqi = qi_get_sqi(); //MGR
+
+ /* call user callback */
+ if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) {
+ _current_irq_callback(RX_DONE);
+ }
+
+ /* Disable handling of other RX flags */
+ x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
+ }
+ }
+
+#ifndef RX_FIFO_THR_WA
+ /* RX FIFO almost full */
+ if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) {
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+ if(!_is_receiving) { // spurious irq?!?
+#ifdef DEBUG_IRQ
+ debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+ } else {
+ uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
+ if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) {
+ spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
+ _spirit_rx_pos += fifo_available;
+ } else {
+#ifdef DEBUG_IRQ
+ debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+ }
+ }
+ }
+#endif // !RX_FIFO_THR_WA
+
+ /* Reception errors */
+ if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+ debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+ rx_timeout_handler();
+ if(_spirit_tx_started) {
+ _spirit_tx_started = false;
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(TX_ERR);
+ }
+ }
+ }
+
+ /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
+ if(x_irq_status.IRQ_VALID_SYNC) {
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+ /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and
+ * the MCU trying to send a packet, which gets resolved in favor of
+ * sending.
+ */
+ if(_spirit_tx_started) {
+#ifdef DEBUG_IRQ
+ debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+ } else {
+ _is_receiving = true;
+ start_rx_timeout();
+ }
+ }
+}