Prototype RF driver for STM Sub-1 GHz RF expansion board based on the SPSGRF-868 module for STM32 Nucleo.
Embed:
(wiki syntax)
Show/hide line numbers
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
1.7.2
X-NUCLEO-IDS01A4 Sub-1GHz RF Expansion Board