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 while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U)); \ 00016 } while(0) 00017 00018 #define st_lib_spirit_irqs SpiritIrqs 00019 00020 #define STATE_TIMEOUT (100) 00021 00022 // betzw: switching force & back from standby is on some devices quite unstable 00023 #define USE_STANDBY_STATE 00024 00025 /*** Class Implementation ***/ 00026 /** Static Class Variables **/ 00027 SimpleSpirit1 *SimpleSpirit1::_singleton = NULL; 00028 00029 /** Constructor **/ 00030 SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk, 00031 PinName irq, PinName cs, PinName sdn, 00032 PinName led) : 00033 _spi(mosi, miso, sclk), 00034 _irq(irq), 00035 _chip_select(cs), 00036 _shut_down(sdn), 00037 _led(led), 00038 _current_irq_callback(), 00039 _rx_receiving_timeout() 00040 { 00041 } 00042 00043 /** Init Function **/ 00044 void SimpleSpirit1::init() { 00045 /* reset irq disable counter and irq callback & disable irq */ 00046 _nr_of_irq_disables = 0; 00047 disable_spirit_irq(); 00048 00049 /* unselect chip */ 00050 chip_unselect(); 00051 00052 /* configure spi */ 00053 _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */ 00054 _spi.frequency(1000000); // 1MHz // betzw: heuristic value // betzw - NOTE: high frequencies lead to instability of Spirit1 00055 00056 /* install irq handler */ 00057 _irq.mode(PullUp); 00058 _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler)); 00059 00060 /* init cube vars */ 00061 spirit_on = OFF; 00062 last_rssi = 0 ; //MGR 00063 last_sqi = 0 ; //MGR 00064 00065 /* set frequencies */ 00066 radio_set_xtal_freq(XTAL_FREQUENCY); 00067 mgmt_set_freq_base((uint32_t)BASE_FREQUENCY); 00068 00069 /* restart board */ 00070 enter_shutdown(); 00071 exit_shutdown(); 00072 00073 /* soft core reset */ 00074 cmd_strobe(SPIRIT1_STROBE_SRES); 00075 00076 /* Configures the SPIRIT1 radio part */ 00077 SRadioInit x_radio_init = { 00078 XTAL_OFFSET_PPM, 00079 (uint32_t)BASE_FREQUENCY, 00080 (uint32_t)CHANNEL_SPACE, 00081 CHANNEL_NUMBER, 00082 MODULATION_SELECT, 00083 DATARATE, 00084 (uint32_t)FREQ_DEVIATION, 00085 (uint32_t)BANDWIDTH 00086 }; 00087 radio_init(&x_radio_init); 00088 radio_set_pa_level_dbm(0,POWER_DBM); 00089 radio_set_pa_level_max_index(0); 00090 00091 /* Configures the SPIRIT1 packet handler part*/ 00092 PktBasicInit x_basic_init = { 00093 PREAMBLE_LENGTH, 00094 SYNC_LENGTH, 00095 SYNC_WORD, 00096 LENGTH_TYPE, 00097 LENGTH_WIDTH, 00098 CRC_MODE, 00099 CONTROL_LENGTH, 00100 EN_ADDRESS, 00101 EN_FEC, 00102 EN_WHITENING 00103 }; 00104 pkt_basic_init(&x_basic_init); 00105 00106 /* Enable the following interrupt sources, routed to GPIO */ 00107 irq_de_init(NULL); 00108 irq_clear_status(); 00109 irq_set_status(TX_DATA_SENT , S_ENABLE); 00110 irq_set_status(RX_DATA_READY ,S_ENABLE); 00111 irq_set_status(RX_DATA_DISC , S_ENABLE); 00112 irq_set_status(VALID_SYNC , S_ENABLE); 00113 irq_set_status(TX_FIFO_ERROR , S_ENABLE); 00114 irq_set_status(RX_FIFO_ERROR , S_ENABLE); 00115 #ifndef RX_FIFO_THR_WA 00116 irq_set_status(TX_FIFO_ALMOST_EMPTY , S_ENABLE); 00117 irq_set_status(RX_FIFO_ALMOST_FULL , S_ENABLE); 00118 #endif // !RX_FIFO_THR_WA 00119 00120 /* Configure Spirit1 */ 00121 radio_persistent_rx(S_ENABLE); 00122 qi_set_sqi_threshold(SQI_TH_0); 00123 qi_sqi_check(S_ENABLE); 00124 qi_set_rssi_threshold_dbm(CCA_THRESHOLD); 00125 timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD); 00126 timer_set_infinite_rx_timeout(); 00127 radio_afc_freeze_on_sync(S_ENABLE); 00128 calibration_rco(S_ENABLE); 00129 00130 spirit_on = OFF; 00131 CLEAR_TXBUF(); 00132 CLEAR_RXBUF(); 00133 _spirit_tx_started = false; 00134 _is_receiving = false; 00135 00136 /* Configure the radio to route the IRQ signal to its GPIO 3 */ 00137 SGpioInit x_gpio_init = { 00138 SPIRIT_GPIO_IRQ, 00139 SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP , 00140 SPIRIT_GPIO_DIG_OUT_IRQ 00141 }; 00142 spirit_gpio_init(&x_gpio_init); 00143 00144 /* Setup CSMA/CA */ 00145 CsmaInit x_csma_init = { 00146 S_ENABLE, // enable persistent mode 00147 TBIT_TIME_64 , // Tcca time 00148 TCCA_TIME_3 , // Lcca length 00149 3, // max nr of backoffs (<8) 00150 1, // BU counter seed 00151 8 // BU prescaler 00152 }; 00153 csma_ca_init(&x_csma_init); 00154 00155 #ifdef USE_STANDBY_STATE 00156 /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */ 00157 cmd_strobe(SPIRIT1_STROBE_STANDBY); 00158 #endif // USE_STANDBY_STATE 00159 } 00160 00161 static volatile int tx_fifo_remaining = 0; // to be used in irq handler 00162 static volatile int tx_buffer_pos = 0; // to be used in irq handler 00163 const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler 00164 int SimpleSpirit1::send(const void *payload, unsigned int payload_len) { 00165 /* Checks if the payload length is supported */ 00166 if(payload_len > MAX_PACKET_LEN) { 00167 return RADIO_TX_ERR; 00168 } 00169 00170 disable_spirit_irq(); 00171 00172 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00173 #ifndef NDEBUG 00174 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { 00175 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00176 } 00177 #endif 00178 00179 /* Reset State to Ready */ 00180 set_ready_state(); 00181 00182 cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer 00183 00184 #ifndef NDEBUG 00185 debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00186 #endif 00187 00188 pkt_basic_set_payload_length(payload_len); // set desired payload len 00189 00190 csma_ca_state(S_ENABLE); // enable CSMA/CA 00191 00192 /* Init buffer & number of bytes to be send */ 00193 tx_fifo_remaining = payload_len; 00194 tx_fifo_buffer = (const uint8_t*)payload; 00195 00196 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo 00197 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining; 00198 00199 tx_fifo_remaining -= to_send; 00200 00201 /* Fill FIFO Buffer */ 00202 if(to_send > 0) { 00203 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]); 00204 } 00205 00206 tx_buffer_pos = to_send; 00207 _spirit_tx_started = true; 00208 00209 enable_spirit_irq(); 00210 00211 /* Start transmitting */ 00212 cmd_strobe(SPIRIT1_STROBE_TX); 00213 00214 while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler) 00215 00216 BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT); 00217 #ifdef HEAVY_DEBUG 00218 debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started); 00219 #endif 00220 00221 _spirit_tx_started = false; // in case of state timeout 00222 00223 csma_ca_state(S_DISABLE); // disable CSMA/CA 00224 00225 cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state 00226 00227 return RADIO_TX_OK; 00228 } 00229 00230 /** Set Ready State **/ 00231 void SimpleSpirit1::set_ready_state(void) { 00232 uint16_t state; 00233 00234 disable_spirit_irq(); 00235 00236 _spirit_tx_started = false; 00237 _is_receiving = false; 00238 stop_rx_timeout(); 00239 00240 cmd_strobe(SPIRIT1_STROBE_FRX); 00241 CLEAR_RXBUF(); 00242 CLEAR_TXBUF(); 00243 00244 state = SPIRIT1_STATUS(); 00245 if(state == SPIRIT1_STATE_STANDBY) { 00246 cmd_strobe(SPIRIT1_STROBE_READY); 00247 } else if(state == SPIRIT1_STATE_RX) { 00248 cmd_strobe(SPIRIT1_STROBE_SABORT); 00249 } else if(state != SPIRIT1_STATE_READY) { 00250 #ifndef NDEBUG 00251 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, state>>1); 00252 #endif 00253 } 00254 00255 BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT); 00256 if(last_state != (SPIRIT1_STATE_READY | XO_ON)) { 00257 error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state); 00258 enable_spirit_irq(); 00259 return; 00260 } 00261 00262 irq_clear_status(); 00263 00264 enable_spirit_irq(); 00265 } 00266 00267 int SimpleSpirit1::off(void) { 00268 if(spirit_on == ON) { 00269 /* Disables the mcu to get IRQ from the SPIRIT1 */ 00270 disable_spirit_irq(); 00271 00272 /* first stop rx/tx */ 00273 set_ready_state(); 00274 00275 #ifdef USE_STANDBY_STATE 00276 /* Puts the SPIRIT1 in STANDBY */ 00277 cmd_strobe(SPIRIT1_STROBE_STANDBY); 00278 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT); 00279 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) { 00280 error("\n\rSpirit1: failed to enter standby (%x)\n\r", last_state>>1); 00281 return 1; 00282 } 00283 #endif // USE_STANDBY_STATE 00284 00285 spirit_on = OFF; 00286 _nr_of_irq_disables = 1; 00287 } 00288 return 0; 00289 } 00290 00291 int SimpleSpirit1::on(void) { 00292 if(spirit_on == OFF) { 00293 set_ready_state(); 00294 00295 /* now we go to Rx */ 00296 cmd_strobe(SPIRIT1_STROBE_RX); 00297 00298 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00299 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { 00300 error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1); 00301 } 00302 00303 /* Enables the mcu to get IRQ from the SPIRIT1 */ 00304 spirit_on = ON; 00305 #ifndef NDEBUG 00306 debug_if(!(_nr_of_irq_disables == 1), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00307 #endif 00308 enable_spirit_irq(); 00309 } 00310 00311 #ifndef NDEBUG 00312 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { 00313 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00314 } 00315 #endif 00316 00317 return 0; 00318 } 00319 00320 uint8_t SimpleSpirit1::refresh_state(void) { 00321 uint8_t mcstate; 00322 00323 SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate); 00324 00325 return mcstate; 00326 } 00327 00328 int SimpleSpirit1::read(void *buf, unsigned int bufsize) 00329 { 00330 disable_spirit_irq(); 00331 00332 /* Checks if the RX buffer is empty */ 00333 if(IS_RXBUF_EMPTY()) { 00334 #ifndef NDEBUG 00335 debug("\n\rBuffer is empty\n\r"); 00336 #endif 00337 set_ready_state(); 00338 00339 cmd_strobe(SPIRIT1_STROBE_RX); 00340 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00341 enable_spirit_irq(); 00342 return 0; 00343 } 00344 00345 if(bufsize < spirit_rx_len) { 00346 enable_spirit_irq(); 00347 00348 /* If buf has the correct size */ 00349 #ifndef NDEBUG 00350 debug("\n\rTOO SMALL BUF\n\r"); 00351 #endif 00352 return 0; 00353 } else { 00354 /* Copies the packet received */ 00355 memcpy(buf, spirit_rx_buf, spirit_rx_len); 00356 00357 bufsize = spirit_rx_len; 00358 CLEAR_RXBUF(); 00359 00360 enable_spirit_irq(); 00361 00362 return bufsize; 00363 } 00364 00365 } 00366 00367 int SimpleSpirit1::channel_clear(void) 00368 { 00369 float rssi_value; 00370 /* Local variable used to memorize the SPIRIT1 state */ 00371 uint8_t spirit_state = ON; 00372 00373 if(spirit_on == OFF) { 00374 /* Wakes up the SPIRIT1 */ 00375 on(); 00376 spirit_state = OFF; 00377 } 00378 00379 #ifndef NDEBUG 00380 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { 00381 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00382 } 00383 #endif 00384 00385 disable_spirit_irq(); 00386 00387 /* Reset State to Ready */ 00388 set_ready_state(); 00389 00390 /* Stores the RSSI value */ 00391 rssi_value = qi_get_rssi_dbm(); 00392 00393 enable_spirit_irq(); 00394 00395 /* Puts the SPIRIT1 in its previous state */ 00396 if(spirit_state==OFF) { 00397 off(); 00398 #ifndef NDEBUG 00399 #ifdef USE_STANDBY_STATE 00400 if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) { 00401 #else 00402 if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) { 00403 #endif 00404 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00405 } 00406 #endif 00407 } else { 00408 disable_spirit_irq(); 00409 00410 set_ready_state(); 00411 00412 cmd_strobe(SPIRIT1_STROBE_RX); 00413 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00414 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { 00415 error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1); 00416 } 00417 00418 enable_spirit_irq(); 00419 00420 #ifndef NDEBUG 00421 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { 00422 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00423 } 00424 #endif 00425 } 00426 00427 /* Checks the RSSI value with the threshold */ 00428 if(rssi_value<CCA_THRESHOLD) { 00429 return 0; 00430 } else { 00431 return 1; 00432 } 00433 } 00434 00435 int SimpleSpirit1::get_pending_packet(void) 00436 { 00437 return !IS_RXBUF_EMPTY(); 00438 } 00439 00440 /** Spirit Irq Callback **/ 00441 void SimpleSpirit1::IrqHandler() { 00442 st_lib_spirit_irqs x_irq_status; 00443 00444 /* get interrupt source from radio */ 00445 irq_get_status(&x_irq_status); 00446 00447 /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */ 00448 if(x_irq_status.IRQ_TX_DATA_SENT) { 00449 #ifdef DEBUG_IRQ 00450 uint32_t *tmp = (uint32_t*)&x_irq_status; 00451 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00452 debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00453 debug_if(tx_fifo_remaining != 0, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00454 #endif 00455 00456 tx_fifo_buffer = NULL; 00457 _spirit_tx_started = false; 00458 00459 /* call user callback */ 00460 if(_current_irq_callback) { 00461 _current_irq_callback(TX_DONE); 00462 } 00463 00464 /* Disable handling of other TX flags */ 00465 x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET; 00466 } 00467 00468 #ifndef RX_FIFO_THR_WA 00469 /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */ 00470 if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) { 00471 #ifdef DEBUG_IRQ 00472 uint32_t *tmp = (uint32_t*)&x_irq_status; 00473 debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00474 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00475 debug_if(tx_fifo_buffer == NULL, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00476 #endif 00477 00478 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo 00479 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining; 00480 00481 tx_fifo_remaining -= to_send; 00482 00483 /* Fill FIFO Buffer */ 00484 if(to_send > 0) { 00485 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]); 00486 } 00487 tx_buffer_pos += to_send; 00488 } 00489 #endif // !RX_FIFO_THR_WA 00490 00491 /* Transmission error */ 00492 if(x_irq_status.IRQ_TX_FIFO_ERROR) { 00493 #ifdef DEBUG_IRQ 00494 uint32_t *tmp = (uint32_t*)&x_irq_status; 00495 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00496 debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00497 #endif 00498 if(_spirit_tx_started) { 00499 _spirit_tx_started = false; 00500 /* call user callback */ 00501 if(_current_irq_callback) { 00502 _current_irq_callback(TX_ERR); 00503 } 00504 } 00505 00506 /* reset data still to be sent */ 00507 tx_fifo_remaining = 0; 00508 } 00509 00510 /* The IRQ_RX_DATA_READY notifies a new packet arrived */ 00511 if(x_irq_status.IRQ_RX_DATA_READY) { 00512 #ifdef DEBUG_IRQ 00513 uint32_t *tmp = (uint32_t*)&x_irq_status; 00514 debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00515 #endif 00516 00517 if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!) 00518 #ifdef HEAVY_DEBUG 00519 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00520 #endif 00521 } else { 00522 _is_receiving = false; // Finished receiving 00523 stop_rx_timeout(); 00524 00525 spirit_rx_len = pkt_basic_get_received_pkt_length(); 00526 00527 #ifdef DEBUG_IRQ 00528 debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00529 #endif 00530 00531 if(spirit_rx_len <= MAX_PACKET_LEN) { 00532 uint8_t to_receive = spirit_rx_len - _spirit_rx_pos; 00533 if(to_receive > 0) { 00534 spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]); 00535 _spirit_rx_pos += to_receive; 00536 } 00537 } 00538 00539 cmd_strobe(SPIRIT1_STROBE_FRX); 00540 00541 last_rssi = qi_get_rssi(); //MGR 00542 last_sqi = qi_get_sqi(); //MGR 00543 00544 /* call user callback */ 00545 if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) { 00546 _current_irq_callback(RX_DONE); 00547 } 00548 00549 /* Disable handling of other RX flags */ 00550 x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET; 00551 } 00552 } 00553 00554 #ifndef RX_FIFO_THR_WA 00555 /* RX FIFO almost full */ 00556 if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) { 00557 #ifdef DEBUG_IRQ 00558 uint32_t *tmp = (uint32_t*)&x_irq_status; 00559 debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00560 #endif 00561 if(!_is_receiving) { // spurious irq?!? 00562 #ifdef DEBUG_IRQ 00563 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00564 #endif 00565 } else { 00566 uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo(); 00567 if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) { 00568 spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]); 00569 _spirit_rx_pos += fifo_available; 00570 } else { 00571 #ifdef DEBUG_IRQ 00572 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00573 #endif 00574 } 00575 } 00576 } 00577 #endif // !RX_FIFO_THR_WA 00578 00579 /* Reception errors */ 00580 if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) { 00581 #ifdef DEBUG_IRQ 00582 uint32_t *tmp = (uint32_t*)&x_irq_status; 00583 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00584 debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00585 #endif 00586 rx_timeout_handler(); 00587 if(_spirit_tx_started) { 00588 _spirit_tx_started = false; 00589 /* call user callback */ 00590 if(_current_irq_callback) { 00591 _current_irq_callback(TX_ERR); 00592 } 00593 } 00594 } 00595 00596 /* The IRQ_VALID_SYNC is used to notify a new packet is coming */ 00597 if(x_irq_status.IRQ_VALID_SYNC) { 00598 #ifdef DEBUG_IRQ 00599 uint32_t *tmp = (uint32_t*)&x_irq_status; 00600 debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00601 #endif 00602 /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and 00603 * the MCU trying to send a packet, which gets resolved in favor of 00604 * sending. 00605 */ 00606 if(_spirit_tx_started) { 00607 #ifdef DEBUG_IRQ 00608 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00609 #endif 00610 } else { 00611 _is_receiving = true; 00612 start_rx_timeout(); 00613 } 00614 } 00615 }
Generated on Tue Jul 12 2022 18:06:46 by
1.7.2