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 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 }
Generated on Tue Jul 12 2022 16:35:33 by
