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.
Dependents: DISCO_IOT-wifi_client
Fork of stm-spirit1-rf-driver by
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 }
Generated on Tue Jul 12 2022 14:16:15 by
1.7.2
