ST / stm-spirit1-rf-driver
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     CLEAR_TXBUF();
00135     CLEAR_RXBUF();
00136     _spirit_tx_started = false;
00137     _is_receiving = false;
00138 
00139     /* Configure the radio to route the IRQ signal to its GPIO 3 */
00140     SGpioInit x_gpio_init = {
00141             SPIRIT_GPIO_IRQ,
00142             SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP ,
00143             SPIRIT_GPIO_DIG_OUT_IRQ 
00144     };
00145     spirit_gpio_init(&x_gpio_init);
00146 
00147     /* Setup CSMA/CA */
00148     CsmaInit x_csma_init = {
00149             S_ENABLE,         // enable persistent mode
00150             TBIT_TIME_64 ,     // Tcca time
00151             TCCA_TIME_3 ,      // Lcca length
00152             5,                // max nr of backoffs (<8)
00153             1,                // BU counter seed
00154             8                 // BU prescaler
00155     };
00156     csma_ca_init(&x_csma_init);
00157 
00158 #ifdef USE_STANDBY_STATE
00159     /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
00160     cmd_strobe(SPIRIT1_STROBE_STANDBY);
00161 #endif // USE_STANDBY_STATE
00162 }
00163 
00164 static volatile int tx_fifo_remaining = 0;            // to be used in irq handler
00165 static volatile int tx_buffer_pos = 0;                // to be used in irq handler
00166 static const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler
00167 int SimpleSpirit1::send(const void *payload, unsigned int payload_len, bool use_csma_ca) {
00168     /* Checks if the payload length is supported */
00169     if(payload_len > MAX_PACKET_LEN) {
00170         return RADIO_TX_ERR;
00171     }
00172 
00173     disable_spirit_irq();
00174 
00175     BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
00176 #ifndef NDEBUG
00177     if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
00178         debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
00179     }
00180 #endif
00181 
00182     /* Reset State to Ready */
00183     set_ready_state();
00184 
00185     cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer
00186 
00187 #ifndef NDEBUG
00188     debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00189 #endif
00190 
00191     pkt_basic_set_payload_length(payload_len); // set desired payload len
00192 
00193     if(use_csma_ca) {
00194         csma_ca_state(S_ENABLE); // enable CSMA/CA
00195     }
00196 
00197     /* Init buffer & number of bytes to be send */
00198     tx_fifo_remaining = payload_len;
00199     tx_fifo_buffer = (const uint8_t*)payload;
00200 
00201     int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
00202     int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
00203 
00204     tx_fifo_remaining -= to_send;
00205 
00206     /* Fill FIFO Buffer */
00207     if(to_send > 0) {
00208         spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
00209     }
00210 
00211     tx_buffer_pos = to_send;
00212     _spirit_tx_started = true;
00213 
00214     enable_spirit_irq();
00215 
00216     /* Start transmitting */
00217     cmd_strobe(SPIRIT1_STROBE_TX);
00218 
00219     while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
00220 
00221     BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
00222 #ifdef HEAVY_DEBUG
00223     debug("\r\n%s (%d): state=%x, _spirit_tx_started=%d\r\n", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
00224 #endif
00225 
00226     if(use_csma_ca) {
00227         csma_ca_state(S_DISABLE); // disable CSMA/CA
00228     }
00229 
00230     cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
00231 
00232     disable_spirit_irq();
00233     if(_spirit_tx_started) { // in case of state timeout
00234         _spirit_tx_started = false;
00235         enable_spirit_irq();
00236         return RADIO_TX_ERR;
00237     } else {
00238         enable_spirit_irq();
00239         return RADIO_TX_OK;
00240     }
00241 }
00242 
00243 /** Set Ready State **/
00244 void SimpleSpirit1::set_ready_state(void) {
00245     uint16_t state;
00246 
00247     disable_spirit_irq();
00248 
00249     _spirit_tx_started = false;
00250     _is_receiving = false;
00251     stop_rx_timeout();
00252 
00253     cmd_strobe(SPIRIT1_STROBE_FRX);
00254     CLEAR_RXBUF();
00255     CLEAR_TXBUF();
00256 
00257     state = SPIRIT1_STATUS();
00258     if(state == SPIRIT1_STATE_STANDBY) {
00259         cmd_strobe(SPIRIT1_STROBE_READY);
00260     } else if(state == SPIRIT1_STATE_RX) {
00261         cmd_strobe(SPIRIT1_STROBE_SABORT);
00262     } else if(state != SPIRIT1_STATE_READY) {
00263 #ifndef NDEBUG
00264         debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, state>>1);
00265 #endif
00266     }
00267 
00268     BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
00269     if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
00270         error("\r\nSpirit1: failed to become ready (%x) => pls. reset!\r\n", last_state);
00271         enable_spirit_irq();
00272         return;
00273     }
00274 
00275     irq_clear_status();
00276 
00277     enable_spirit_irq();
00278 }
00279 
00280 int SimpleSpirit1::off(void) {
00281     if(spirit_on == ON) {
00282         /* Disables the mcu to get IRQ from the SPIRIT1 */
00283         disable_spirit_irq();
00284 
00285         /* first stop rx/tx */
00286         set_ready_state();
00287 
00288 #ifdef USE_STANDBY_STATE
00289         /* Puts the SPIRIT1 in STANDBY */
00290         cmd_strobe(SPIRIT1_STROBE_STANDBY);
00291         BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
00292         if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
00293             error("\r\nSpirit1: failed to enter standby (%x)\r\n", last_state>>1);
00294             return 1;
00295         }
00296 #endif // USE_STANDBY_STATE
00297 
00298         spirit_on = OFF;
00299         _nr_of_irq_disables = 1;
00300     }
00301     return 0;
00302 }
00303 
00304 int SimpleSpirit1::on(void) {
00305     if(spirit_on == OFF) {
00306         set_ready_state();
00307 
00308         /* now we go to Rx */
00309         cmd_strobe(SPIRIT1_STROBE_RX);
00310 
00311         BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
00312         if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
00313             error("\r\nSpirit1: failed to enter rx (%x) => retry\r\n", last_state>>1);
00314         }
00315 
00316         /* Enables the mcu to get IRQ from the SPIRIT1 */
00317         spirit_on = ON;
00318 #ifndef NDEBUG
00319         debug_if(!(_nr_of_irq_disables == 1), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00320 #endif
00321         enable_spirit_irq();
00322     }
00323 
00324 #ifndef NDEBUG
00325     if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
00326         debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
00327     }
00328 #endif
00329 
00330     return 0;
00331 }
00332 
00333 uint8_t SimpleSpirit1::refresh_state(void) {
00334     uint8_t mcstate;
00335 
00336     SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
00337 
00338     return mcstate;
00339 }
00340 
00341 int SimpleSpirit1::read(void *buf, unsigned int bufsize)
00342 {
00343     disable_spirit_irq();
00344 
00345     /* Checks if the RX buffer is empty */
00346     if(IS_RXBUF_EMPTY()) {
00347 #ifndef NDEBUG
00348         debug("\r\nBuffer is empty\r\n");
00349 #endif
00350         set_ready_state();
00351 
00352         cmd_strobe(SPIRIT1_STROBE_RX);
00353         BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
00354         enable_spirit_irq();
00355         return 0;
00356     }
00357 
00358     if(bufsize < spirit_rx_len) {
00359         enable_spirit_irq();
00360 
00361         /* If buf has the correct size */
00362 #ifndef NDEBUG
00363         debug("\r\nTOO SMALL BUF\r\n");
00364 #endif
00365         return 0;
00366     } else {
00367         /* Copies the packet received */
00368         memcpy(buf, spirit_rx_buf, spirit_rx_len);
00369 
00370         bufsize = spirit_rx_len;
00371         CLEAR_RXBUF();
00372 
00373         enable_spirit_irq();
00374 
00375         return bufsize;
00376     }
00377 
00378 }
00379 
00380 /* betzw - TODO: CCA should be reviewed (completely)! */
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 
00413 #ifndef NDEBUG
00414 #ifdef USE_STANDBY_STATE
00415         if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
00416             debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
00417         }
00418 #else // !USE_STANDBY_STATE
00419         if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
00420             debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
00421         }
00422 #endif // !USE_STANDBY_STATE
00423 #endif // NDEBUG
00424     } else { // spirit_state != OFF
00425         disable_spirit_irq();
00426 
00427         set_ready_state();
00428 
00429         cmd_strobe(SPIRIT1_STROBE_RX);
00430         BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
00431         if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
00432             error("\r\nSpirit1: (#2) failed to enter rx (%x) => retry\r\n", last_state>>1);
00433         }
00434 
00435         enable_spirit_irq();
00436 
00437 #ifndef NDEBUG
00438         if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
00439             debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
00440         }
00441 #endif
00442     }
00443 
00444     /* If the received signal strength is above a certain level the medium is considered busy! */
00445     /* Compare RSSI value with threshold */
00446     if(rssi_value < CCA_THRESHOLD) {
00447         return 0; // idle
00448     } else {
00449         return 1; // busy
00450     }
00451 }
00452 
00453 int SimpleSpirit1::get_pending_packet(void)
00454 {
00455     return !IS_RXBUF_EMPTY();
00456 }
00457 
00458 /** Spirit Irq Callback **/
00459 /* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */
00460 void SimpleSpirit1::IrqHandler() {
00461     st_lib_spirit_irqs x_irq_status;
00462 
00463     /* get interrupt source from radio */
00464     irq_get_status(&x_irq_status);
00465 
00466     /* The IRQ_TX_DATA_SENT notifies the packet has been sent. Puts the SPIRIT1 in RX */
00467     if(x_irq_status.IRQ_TX_DATA_SENT) { /* betzw - NOTE: MUST be handled before `IRQ_RX_DATA_READY` for Nanostack integration!
00468                                                          Logically, Nanostack only expects the "DONE" after "SUCCESS" (if it gets
00469                                                          DONE before SUCCESS, it assumes you're not going to bother to send SUCCESS).
00470      */
00471 #ifdef DEBUG_IRQ
00472         uint32_t *tmp = (uint32_t*)&x_irq_status;
00473         debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00474         debug_if(tx_fifo_remaining != 0, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00475 #endif
00476 
00477         if(_spirit_tx_started) {
00478             _spirit_tx_started = false;
00479 
00480             /* call user callback */
00481             if(_current_irq_callback) {
00482                 _current_irq_callback(TX_DONE);
00483             }
00484         }
00485 
00486         /* Disable handling of other TX flags */
00487         x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET;
00488         tx_fifo_buffer = NULL;
00489     }
00490 
00491 #ifndef RX_FIFO_THR_WA
00492     /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
00493     if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
00494 #ifdef DEBUG_IRQ
00495         uint32_t *tmp = (uint32_t*)&x_irq_status;
00496         debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00497         debug_if(!_spirit_tx_started, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00498         debug_if(tx_fifo_buffer == NULL, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00499 #endif
00500 
00501         int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
00502         int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
00503 
00504         tx_fifo_remaining -= to_send;
00505 
00506         /* Fill FIFO Buffer */
00507         if(to_send > 0) {
00508             spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
00509         }
00510         tx_buffer_pos += to_send;
00511     }
00512 #endif // !RX_FIFO_THR_WA
00513 
00514     /* TX FIFO underflow/overflow error */
00515     if(x_irq_status.IRQ_TX_FIFO_ERROR) {
00516 #ifdef DEBUG_IRQ
00517         uint32_t *tmp = (uint32_t*)&x_irq_status;
00518         debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
00519         debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00520 #endif
00521         if(_spirit_tx_started) {
00522             _spirit_tx_started = false;
00523             /* call user callback */
00524             if(_current_irq_callback) {
00525                 _current_irq_callback(TX_ERR);
00526             }
00527         }
00528 
00529         /* reset data still to be sent */
00530         tx_fifo_remaining = 0;
00531     }
00532 
00533     /* The IRQ_RX_DATA_READY notifies a new packet arrived */
00534     if(x_irq_status.IRQ_RX_DATA_READY) {
00535 #ifdef DEBUG_IRQ
00536         uint32_t *tmp = (uint32_t*)&x_irq_status;
00537         debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00538 #endif
00539 
00540         if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!)
00541 #ifdef HEAVY_DEBUG
00542             debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
00543 #endif
00544         } else {
00545             _is_receiving = false; // Finished receiving
00546             stop_rx_timeout();
00547 
00548             spirit_rx_len = pkt_basic_get_received_pkt_length();
00549 
00550 #ifdef DEBUG_IRQ
00551             debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
00552 #endif
00553 
00554             if(spirit_rx_len <= MAX_PACKET_LEN) {
00555                 uint8_t to_receive = spirit_rx_len - _spirit_rx_pos;
00556                 if(to_receive > 0) {
00557                     spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]);
00558                     _spirit_rx_pos += to_receive;
00559                 }
00560             }
00561 
00562             cmd_strobe(SPIRIT1_STROBE_FRX);
00563 
00564             last_rssi = qi_get_rssi(); //MGR
00565             last_sqi  = qi_get_sqi();  //MGR
00566 
00567             /* call user callback */
00568             if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) {
00569                 _current_irq_callback(RX_DONE);
00570             }
00571 
00572             /* Disable handling of other RX flags */
00573             x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
00574         }
00575     }
00576 
00577 #ifndef RX_FIFO_THR_WA
00578     /* RX FIFO almost full */
00579     if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) {
00580 #ifdef DEBUG_IRQ
00581         uint32_t *tmp = (uint32_t*)&x_irq_status;
00582         debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00583 #endif
00584         if(!_is_receiving) { // spurious irq?!?
00585 #ifdef DEBUG_IRQ
00586             debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
00587 #endif
00588         } else {
00589             uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
00590             if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) {
00591                 spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
00592                 _spirit_rx_pos += fifo_available;
00593             } else {
00594 #ifdef DEBUG_IRQ
00595                 debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
00596 #endif
00597             }
00598         }
00599     }
00600 #endif // !RX_FIFO_THR_WA
00601 
00602     /* Reception errors */
00603     if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
00604 #ifdef DEBUG_IRQ
00605         uint32_t *tmp = (uint32_t*)&x_irq_status;
00606         debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
00607         debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00608 #endif
00609         rx_timeout_handler();
00610         if(_spirit_tx_started) {
00611             _spirit_tx_started = false;
00612             /* call user callback */
00613             if(_current_irq_callback) {
00614                 _current_irq_callback(TX_ERR);
00615             }
00616         }
00617     }
00618 
00619     /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
00620     if(x_irq_status.IRQ_VALID_SYNC) {
00621 #ifdef DEBUG_IRQ
00622         uint32_t *tmp = (uint32_t*)&x_irq_status;
00623         debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
00624 #endif
00625         /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and
00626          *               the MCU trying to send a packet, which gets resolved in favor of
00627          *               sending.
00628          */
00629         if(_spirit_tx_started) {
00630 #ifdef DEBUG_IRQ
00631             debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
00632 #endif
00633         } else {
00634             _is_receiving = true;
00635             start_rx_timeout();
00636         }
00637     }
00638 }