Vergil Cola
/
MQTTGateway2
Fork of my original MQTTGateway
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 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