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.
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 15:14:30 by
