Version of easy-connect with the u-blox cellular platforms C027 and C030 added.

Dependents:   HelloMQTT

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