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.
Fork of stm-spirit1-rf-driver by
SimpleSpirit1.cpp
00001 /*** Mbed Includes ***/ 00002 #include "SimpleSpirit1.h" 00003 #include "radio_spi.h" 00004 //#include "main.h" 00005 00006 00007 //180327 HJM : 디버그 라인 00008 //180619 HJM : 디버그는 전부 중지. 00009 //#define CUBEBITE_DEBUG 00010 //#define NDEBUG 00011 //#define DEBUG_IRQ 00012 //#define HEAVY_DEBUG 00013 00014 00015 //180619 HJM : init 재시작을 위한 카운팅 변수 00016 static int iErrorCounting = 0; 00017 #define MAX_ERROR_COUNTING 3 00018 #define RETURN_ERROR_NUMBER 100 00019 00020 00021 #define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_0) 00022 //#define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_2) 00023 //#define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_1) //EV-COG-AD3029LZ -> GPIO 8 -> P0_08 00024 00025 static uint16_t last_state; 00026 #define SPIRIT1_STATUS() ((last_state = (uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS) 00027 00028 #define XO_ON (0x1) 00029 00030 #define BUSYWAIT_UNTIL(cond, millisecs) \ 00031 do { \ 00032 uint32_t start = us_ticker_read(); \ 00033 uint32_t limit = (uint32_t)millisecs*1000U; \ 00034 while (!(cond)) { \ 00035 uint32_t now = us_ticker_read(); \ 00036 if((now - start) > limit) break; \ 00037 } \ 00038 } while(0) 00039 00040 #define st_lib_spirit_irqs SpiritIrqs 00041 00042 #define STATE_TIMEOUT (100) 00043 00044 00045 #define CUBEBITE_OUTPUT_POWER_DBM_TEST 0 00046 00047 00048 // betzw: switching force & back from standby is on some devices quite unstable 00049 #define USE_STANDBY_STATE 00050 00051 /*** Class Implementation ***/ 00052 /** Static Class Variables **/ 00053 SimpleSpirit1 *SimpleSpirit1::_singleton = NULL; 00054 00055 00056 00057 00058 00059 00060 /** Constructor **/ 00061 SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk, 00062 PinName irq, PinName cs, PinName sdn, 00063 PinName led, uint32_t uint32SClkSettingValue) : 00064 _spi(mosi, miso, sclk), 00065 _irq(irq), 00066 _chip_select(cs), 00067 _shut_down(sdn), 00068 _led(led), 00069 _current_irq_callback(), 00070 _rx_receiving_timeout(), 00071 _uint32SpiClkSettingValue(uint32SClkSettingValue) 00072 { 00073 } 00074 00075 00076 00077 00078 00079 00080 //180619 HJM : 굳이 spi init을 한 번 더한다고 문제가 없는 거라면 ?? 테스트 해보자. 00081 /** Init Function **/ 00082 void SimpleSpirit1::init() 00083 { 00084 printf("[INIT_REVISE]init start...\n"); 00085 //if (false == isItDoItSPIInit) 00086 // { 00087 // isItDoItSPIInit = true; 00088 00089 /*cubebite HJM, reset irq disable counter and irq callback & disable irq */ 00090 _nr_of_irq_disables = 0; // @@ 00091 // disable_spirit_irq(); 00092 00093 /*cubebite HJM, unselect chip */ 00094 chip_unselect(); 00095 00096 /*cubebite HJM, configure spi */ 00097 _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */ 00098 00099 _spi.frequency(_uint32SpiClkSettingValue); //HJM 초기 값, 6500000 00100 printf("Setting spi clk : [%d]\r\n", _uint32SpiClkSettingValue); 00101 00102 // _spi.frequency(13000000); // 13MHz (i.e. max speed allowed for Spirit1) 00103 // _spi.frequency(6500000); // 6.5MHz (i.e. max speed allowed for Spirit1) 00104 // _spi.frequency(4333333); // 4.3333...MHz (i.e. max speed allowed for Spirit1) 00105 // _spi.frequency(2600000); // 2.6MHz (i.e. max speed allowed for Spirit1) 00106 // _spi.frequency(1444444); // 1.4444...MHz (i.e. max speed allowed for Spirit1) 00107 // _spi.frequency(764705); // 0.6470...MHz (i.e. max speed allowed for Spirit1) 00108 // _spi.frequency(393939); // 0.3939...MHz (i.e. max speed allowed for Spirit1) 00109 // } 00110 00111 //if (false == isItDoItRFInit) 00112 // { 00113 // isItDoItRFInit = true; 00114 00115 //180619 HJM : 여기서 부터 sprit1 init 부분 00116 /*cubebite HJM, install irq handler */ 00117 _irq.mode(PullUp); 00118 _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler)); 00119 00120 00121 00122 /*cubebite HJM, init cube vars */ 00123 spirit_on = OFF; 00124 last_rssi = 0 ; //MGR 00125 last_sqi = 0 ; //MGR 00126 00127 00128 /*cubebite HJM, set frequencies */ 00129 printf("[INIT_REVISE]set frequencies..."); 00130 radio_set_xtal_freq(XTAL_FREQUENCY); //cubebite HJM, 50MHz, 180619 HJM : 단순히 변수 셋팅 00131 mgmt_set_freq_base((uint32_t)BASE_FREQUENCY); // @@ 00132 printf("OK\n"); 00133 00134 /*cubebite HJM , restart board */ 00135 enter_shutdown(); 00136 exit_shutdown(); 00137 00138 /*cubebite HJM, soft core reset */ 00139 cmd_strobe(SPIRIT1_STROBE_SRES); 00140 00141 00142 00143 00144 00145 00146 00147 //180619 HJM : 여기서 부터는 init while문이 들어감. 00148 /*cubebite HJM, Configures the SPIRIT1 radio part */ 00149 //180119 HJM : 433MHz 설정으로 변경 후 테스트. 00150 printf("[INIT_REVISE]set SPIRIT1 radio...\n"); 00151 SRadioInit x_radio_init = { 00152 XTAL_OFFSET_PPM, // Xtal offset in ppm 00153 (uint32_t)BASE_FREQUENCY, // HJM 수정 후 테스트 중 base frequency 00154 (uint32_t)CHANNEL_SPACE, // channel space 00155 CHANNEL_NUMBER, // channel number, HJM : 뭐지 0 인줄 알았더니 1로 셋팅되어있네/ 00156 MODULATION_SELECT, // modulation select 00157 DATARATE, // HJM 수정 후 테스트 중 00158 (uint32_t)FREQ_DEVIATION, // frequency deviation 00159 (uint32_t)BANDWIDTH // channel filter bandwidth 00160 }; 00161 00162 00163 00164 00165 00166 uint8_t ui8Return; 00167 ui8Return = radio_init(&x_radio_init); 00168 if (RETURN_ERROR_NUMBER == ui8Return) 00169 { 00170 reset_board(); 00171 return; 00172 } 00173 printf("test 9, ui8Return : [%d]\n", ui8Return); 00174 00175 00176 00177 00178 /*180117 HJM : 송신 신호 세기 */ 00179 radio_set_pa_level_dbm(0,POWER_DBM); ///hjm test 00180 // radio_set_pa_level_dbm(0,10.0); 00181 // radio_set_pa_level_dbm(0,CUBEBITE_OUTPUT_POWER_DBM_TEST); 00182 radio_set_pa_level_max_index(0); 00183 00184 00185 00186 00187 /* Configures the SPIRIT1 packet handler part*/ 00188 PktBasicInit x_basic_init = { 00189 PREAMBLE_LENGTH, 00190 SYNC_LENGTH, 00191 SYNC_WORD, 00192 LENGTH_TYPE, 00193 LENGTH_WIDTH, 00194 CRC_MODE, 00195 CONTROL_LENGTH, 00196 EN_ADDRESS, 00197 EN_FEC, 00198 EN_WHITENING 00199 }; 00200 pkt_basic_init(&x_basic_init); 00201 00202 00203 00204 00205 00206 00207 /* Enable the following interrupt sources, routed to GPIO */ 00208 irq_de_init(NULL); 00209 irq_clear_status(); 00210 irq_set_status(TX_DATA_SENT , S_ENABLE); 00211 irq_set_status(RX_DATA_READY ,S_ENABLE); 00212 irq_set_status(RX_DATA_DISC , S_ENABLE); 00213 irq_set_status(VALID_SYNC , S_ENABLE); 00214 irq_set_status(TX_FIFO_ERROR , S_ENABLE); 00215 irq_set_status(RX_FIFO_ERROR , S_ENABLE); 00216 #ifndef RX_FIFO_THR_WA 00217 irq_set_status(TX_FIFO_ALMOST_EMPTY , S_ENABLE); 00218 irq_set_status(RX_FIFO_ALMOST_FULL , S_ENABLE); 00219 #endif // !RX_FIFO_THR_WA 00220 00221 00222 00223 00224 /* Configure Spirit1 */ 00225 radio_persistent_rx(S_ENABLE); 00226 qi_set_sqi_threshold(SQI_TH_0); 00227 qi_sqi_check(S_ENABLE); 00228 qi_set_rssi_threshold_dbm(CCA_THRESHOLD); //180205 HJM : RRSI 셋팅 값 수정 테스트 00229 timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD); 00230 timer_set_infinite_rx_timeout(); 00231 radio_afc_freeze_on_sync(S_ENABLE); 00232 calibration_rco(S_ENABLE); 00233 00234 spirit_on = OFF; 00235 CLEAR_TXBUF(); 00236 CLEAR_RXBUF(); 00237 _spirit_tx_started = false; 00238 _is_receiving = false; 00239 00240 /* Configure the radio to route the IRQ signal to its GPIO 3 */ 00241 SGpioInit x_gpio_init = { 00242 SPIRIT_GPIO_IRQ, 00243 SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP , 00244 SPIRIT_GPIO_DIG_OUT_IRQ 00245 }; 00246 spirit_gpio_init(&x_gpio_init); 00247 00248 00249 00250 00251 00252 00253 /* Setup CSMA/CA */ 00254 CsmaInit x_csma_init = { 00255 S_ENABLE, // enable persistent mode 00256 TBIT_TIME_64 , // Tcca time 00257 TCCA_TIME_3 , // Lcca length 00258 5, // max nr of backoffs (<8) 00259 1, // BU counter seed 00260 8 // BU prescaler 00261 }; 00262 csma_ca_init(&x_csma_init); 00263 00264 #ifdef USE_STANDBY_STATE 00265 /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */ 00266 cmd_strobe(SPIRIT1_STROBE_STANDBY); 00267 #endif // USE_STANDBY_STATE 00268 00269 // } 00270 printf("[INIT_REVISE]init end.\n"); 00271 } 00272 00273 00274 00275 00276 00277 static volatile int tx_fifo_remaining = 0; // to be used in irq handler 00278 static volatile int tx_buffer_pos = 0; // to be used in irq handler 00279 static const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler 00280 int SimpleSpirit1::send(const void *payload, unsigned int payload_len, bool use_csma_ca) 00281 { 00282 /* Checks if the payload length is supported */ 00283 // printf("\r\n[SEND] 1, MAX_PACKET_LEN : [%d]\n", MAX_PACKET_LEN); 00284 // printf("[SEND] 2, payload_len : [%d]\n", payload_len); 00285 00286 if(payload_len > MAX_PACKET_LEN) 00287 { 00288 // printf("[SEND] \n"); 00289 return RADIO_TX_ERR; 00290 } 00291 00292 00293 00294 00295 00296 00297 00298 00299 00300 printf("send [1"); 00301 // disable_spirit_irq(); 00302 00303 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00304 #ifndef NDEBUG 00305 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { 00306 debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); 00307 } 00308 #endif 00309 00310 00311 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) 00312 { 00313 //180619 HJM : 여기서 뻗지는 않음, 그냥 send error 만 띄울 뿐. 하지만 이것도 카운팅 걸어두고 몇 번(MAX_ERROR_COUNTING) 이상이면 init을 타도록 해야 하겠다. 00314 debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); 00315 printf("[SEND] error \n"); 00316 00317 if (0x3 == (last_state>>1)) 00318 { 00319 return RADIO_TX_ERR_RESET; 00320 // reset_board(); 00321 } 00322 00323 if (0x40 == (last_state>>1)) 00324 { 00325 return RADIO_TX_ERR_RESET; 00326 00327 } 00328 //180619 HJM : 아예 여기서 걸리면 흘러가게 냅두면 spirit1 이 꼬인다. 00329 ++iErrorCounting; 00330 if (iErrorCounting >= MAX_ERROR_COUNTING) 00331 { 00332 iErrorCounting = 0; 00333 return RADIO_TX_ERR_RESET; 00334 } 00335 // 00336 return RADIO_TX_ERR; 00337 } 00338 iErrorCounting = 0; 00339 00340 00341 printf(" 2"); 00342 //if (SPIRIT1_STATE_RX == SPIRIT1_STATUS()) 00343 // { 00344 // printf("[SEND] error \n"); 00345 // 00346 // return RADIO_TX_ERR; 00347 // } 00348 00349 //180323 HJM : IRQ 선이 동작하지 않기 때문에 여기에 현재 sprit1의 상태가 비지 상태인지 체크하고 송신. 00350 00351 00352 00353 00354 00355 00356 00357 00358 00359 00360 00361 /* Reset State to Ready */ 00362 printf(" 3"); 00363 // printf("[SEND] 3, set_ready_state() call, \n"); 00364 set_ready_state(); 00365 00366 printf(" 4"); 00367 // printf("[SEND] 4, cmd_strobe() call, SPIRIT1_STROBE_FTX \n"); 00368 cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer 00369 00370 #ifndef NDEBUG 00371 debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00372 #endif 00373 00374 printf(" 5"); 00375 // printf("[SEND] 5, pkt_basic_set_payload_length() call, \n"); 00376 pkt_basic_set_payload_length(payload_len); // set desired payload len 00377 00378 if(use_csma_ca) { 00379 // printf("[SEND] 6, csma_ca_state() call, \n"); 00380 csma_ca_state(S_ENABLE); // enable CSMA/CA 00381 } 00382 00383 printf(" 6"); 00384 /* Init buffer & number of bytes to be send */ 00385 // printf("[SEND] 7, csma_ca_state() call, \n"); 00386 tx_fifo_remaining = payload_len; 00387 tx_fifo_buffer = (const uint8_t*)payload; 00388 00389 printf(" 7"); 00390 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo 00391 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining; 00392 00393 printf(" 8"); 00394 tx_fifo_remaining -= to_send; 00395 00396 printf(" 9"); 00397 /* Fill FIFO Buffer */ 00398 if(to_send > 0) { 00399 // printf("[SEND] 8, if(to_send > 0), if(to_send > 0) \n"); 00400 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]); 00401 // printf("[SEND] 9, if(to_send > 0), if(to_send > 0) \n"); 00402 } 00403 printf(" 10"); 00404 tx_buffer_pos = to_send; 00405 _spirit_tx_started = true; 00406 00407 printf(" 11"); 00408 // enable_spirit_irq(); 00409 // printf(" 6"); 00410 00411 00412 00413 00414 00415 00416 00417 00418 00419 00420 00421 00422 00423 00424 00425 /* Start transmitting */ 00426 // printf("[SEND] 10, Start transmitting \n"); 00427 printf(" 12"); 00428 cmd_strobe(SPIRIT1_STROBE_TX); 00429 00430 printf(" 13"); 00431 while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler) 00432 00433 /* 00434 if (SPIRIT1_STATUS() == SPIRIT1_STATE_TX) 00435 { 00436 00437 } 00438 else if (SPIRIT1_STATUS() == SPIRIT1_STATE_RX) 00439 { 00440 00441 } 00442 else if (SPIRIT1_STATUS() == SPIRIT1_STATE_) 00443 { 00444 00445 } 00446 */ 00447 00448 00449 00450 00451 00452 00453 00454 00455 00456 00457 00458 printf(" 14"); 00459 // printf("[SEND] 11, Start transmitting end, BUSYWAIT_UNTIL \n"); 00460 BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT); 00461 00462 00463 00464 00465 00466 00467 00468 00469 00470 00471 00472 00473 00474 00475 00476 00477 00478 00479 00480 00481 00482 00483 00484 00485 00486 #ifdef HEAVY_DEBUG 00487 debug("\r\n%s (%d): state=%x, _spirit_tx_started=%d\r\n", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started); 00488 #endif 00489 00490 printf(" 15"); 00491 if(use_csma_ca) { 00492 csma_ca_state(S_DISABLE); // disable CSMA/CA 00493 } 00494 00495 00496 00497 00498 00499 00500 00501 00502 00503 00504 00505 //180323 HJM : irq가 작동하지 않아 수동으로 irq 값을 읽어 오기로 결정됬다. 00506 //이걸 while 로 가둬서 send 하기 전에 검토하면 된다. 00507 printf(" 16"); 00508 int iCounting = 0; 00509 while(1) 00510 { 00511 // printf(" 16-1"); 00512 st_lib_spirit_irqs x_irq_status; 00513 00514 irq_get_status(&x_irq_status); 00515 #ifdef CUBEBITE_DEBUG 00516 printf("while\n"); 00517 #endif 00518 iCounting = iCounting + 1; 00519 00520 // BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_TX, STATE_TIMEOUT); 00521 00522 00523 // printf(" 16-2"); 00524 if(x_irq_status.IRQ_TX_DATA_SENT) 00525 { 00526 00527 #ifdef DEBUG_IRQ 00528 // uint32_t *tmp = (uint32_t*)&x_irq_status; 00529 // debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00530 // debug_if(tx_fifo_remaining != 0, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00531 #endif 00532 // printf(" 16-3"); 00533 if(_spirit_tx_started) 00534 { 00535 #ifdef CUBEBITE_DEBUG 00536 printf("[IRQ] if(x_irq_status.IRQ_TX_DATA_SENT) in, if(_spirit_tx_started) in \n"); 00537 #endif 00538 00539 } 00540 00541 // printf(" 16-4"); 00542 x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET; 00543 tx_fifo_buffer = NULL; 00544 00545 _spirit_tx_started = false; 00546 00547 break; 00548 } 00549 else 00550 { 00551 #ifdef CUBEBITE_DEBUG 00552 printf("not yet sent!!!\n"); 00553 #endif //CUBEBITE_DEBUG 00554 } 00555 00556 00557 00558 00559 00560 // printf(" 17"); 00561 /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */ 00562 if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) { 00563 // printf("1\n"); 00564 // printf("[IRQ] if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) in\n"); 00565 00566 //uint32_t *tmp = (uint32_t*)&x_irq_status; 00567 // debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00568 // debug_if(!_spirit_tx_started, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00569 // debug_if(tx_fifo_buffer == NULL, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00570 00571 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo 00572 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining; 00573 00574 tx_fifo_remaining -= to_send; 00575 00576 /* Fill FIFO Buffer */ 00577 if(to_send > 0) { 00578 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]); 00579 } 00580 tx_buffer_pos += to_send; 00581 } 00582 00583 00584 00585 /* TX FIFO underflow/overflow error */ 00586 if(x_irq_status.IRQ_TX_FIFO_ERROR) 00587 { 00588 #ifdef CUBEBITE_DEBUG 00589 printf("[IRQ] if(x_irq_status.IRQ_TX_FIFO_ERROR) in\n"); 00590 #endif //CUBEBITE_DEBUG 00591 00592 //uint32_t *tmp = (uint32_t*)&x_irq_status; 00593 // debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); 00594 // debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00595 00596 //if(_spirit_tx_started) 00597 // { 00598 // _spirit_tx_started = false; 00599 // /* call user callback */ 00600 // if(_current_irq_callback) 00601 // { 00602 // _current_irq_callback(TX_ERR); 00603 // } 00604 // } 00605 00606 /* reset data still to be sent */ 00607 tx_fifo_remaining = 0; 00608 } 00609 00610 00611 00612 00613 00614 00615 if (1000 == iCounting) 00616 { 00617 //180327 HJM : 10번이나 검색을 했는데 IRQ가 이상이 있으면 정말 이상이 있다고 생각하고 그냥 break 00618 #ifdef CUBEBITE_DEBUG 00619 printf("if (1000 == iCounting) \n"); 00620 #endif 00621 iCounting = 0; 00622 return RADIO_TX_ERR_RESET; 00623 00624 } 00625 00626 00627 } 00628 00629 00630 00631 00632 00633 00634 00635 00636 00637 00638 00639 00640 00641 00642 00643 00644 00645 00646 00647 00648 00649 00650 00651 00652 00653 00654 00655 printf(" 18"); 00656 cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state 00657 00658 // printf("[SEND] 12, Start transmitting end, BUSYWAIT_UNTIL \n"); 00659 // disable_spirit_irq(); 00660 if(_spirit_tx_started) { 00661 // in case of state timeout 00662 _spirit_tx_started = false; 00663 // enable_spirit_irq(); 00664 00665 // printf("[SEND] 13, if(_spirit_tx_started), in case of state timeout, return RADIO_TX_ERR \n"); 00666 printf(" 19, err\n"); 00667 return RADIO_TX_ERR; 00668 } else { 00669 // enable_spirit_irq(); 00670 /* call user callback */ 00671 if(_current_irq_callback) { 00672 _current_irq_callback(TX_DONE); 00673 } 00674 // printf("[SEND] 13, else, in case of state timeout, return RADIO_TX_OK \n"); 00675 printf(" 19, ok\n"); 00676 return RADIO_TX_OK; 00677 } 00678 } 00679 00680 /** Set Ready State **/ 00681 int SimpleSpirit1::set_ready_state(void) 00682 { 00683 uint16_t state; 00684 00685 // disable_spirit_irq(); 00686 00687 _spirit_tx_started = false; 00688 _is_receiving = false; 00689 stop_rx_timeout(); 00690 00691 cmd_strobe(SPIRIT1_STROBE_FRX); 00692 CLEAR_RXBUF(); 00693 CLEAR_TXBUF(); 00694 00695 state = SPIRIT1_STATUS(); 00696 if(state == SPIRIT1_STATE_STANDBY) { 00697 // printf("[SEND] 3-1, set_ready_state() call, if(state == SPIRIT1_STATE_STANDBY) in \n"); 00698 cmd_strobe(SPIRIT1_STROBE_READY); 00699 } else if(state == SPIRIT1_STATE_RX) { 00700 // printf("[SEND] 3-2, set_ready_state() call, if(state == SPIRIT1_STATE_RX) in \n"); 00701 cmd_strobe(SPIRIT1_STROBE_SABORT); 00702 } else if(state != SPIRIT1_STATE_READY) 00703 { 00704 #ifndef NDEBUG 00705 debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, state>>1); 00706 #endif 00707 return RETURN_ERROR_NUMBER; 00708 00709 // off(); 00710 // reset_board(); 00711 // on(); 00712 // printf("[SEND] 3-3, set_ready_state() call, else if(state != SPIRIT1_STATE_READY) in, something is wrong. \n"); 00713 } 00714 00715 BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT); 00716 if(last_state != (SPIRIT1_STATE_READY | XO_ON)) { 00717 error("\r\nSpirit1: failed to become ready (%x) => pls. reset!\r\n", last_state); 00718 // enable_spirit_irq(); 00719 return RETURN_ERROR_NUMBER + 2; 00720 } 00721 00722 irq_clear_status(); 00723 00724 // enable_spirit_irq(); 00725 } 00726 00727 int SimpleSpirit1::off(void) 00728 { 00729 if(spirit_on == ON) { 00730 /* Disables the mcu to get IRQ from the SPIRIT1 */ 00731 // disable_spirit_irq(); 00732 00733 /* first stop rx/tx */ 00734 set_ready_state(); 00735 00736 #ifdef USE_STANDBY_STATE 00737 /* Puts the SPIRIT1 in STANDBY */ 00738 cmd_strobe(SPIRIT1_STROBE_STANDBY); 00739 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT); 00740 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) { 00741 error("\r\nSpirit1: failed to enter standby (%x)\r\n", last_state>>1); 00742 return 1; 00743 } 00744 #endif // USE_STANDBY_STATE 00745 00746 spirit_on = OFF; 00747 _nr_of_irq_disables = 1; 00748 } 00749 return 0; 00750 } 00751 00752 int SimpleSpirit1::on(void) 00753 { 00754 if(spirit_on == OFF) { 00755 set_ready_state(); 00756 00757 /* now we go to Rx */ 00758 cmd_strobe(SPIRIT1_STROBE_RX); 00759 00760 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00761 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { 00762 error("\r\nSpirit1: failed to enter rx (%x) => retry\r\n", last_state>>1); 00763 } 00764 00765 /* Enables the mcu to get IRQ from the SPIRIT1 */ 00766 spirit_on = ON; 00767 #ifndef NDEBUG 00768 debug_if(!(_nr_of_irq_disables == 1), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00769 #endif 00770 // enable_spirit_irq(); 00771 } 00772 00773 #ifndef NDEBUG 00774 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { 00775 debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); 00776 } 00777 #endif 00778 00779 return 0; 00780 } 00781 00782 uint8_t SimpleSpirit1::refresh_state(void) 00783 { 00784 uint8_t mcstate; 00785 00786 SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate); 00787 00788 return mcstate; 00789 } 00790 00791 int SimpleSpirit1::read(void *buf, unsigned int bufsize) 00792 { 00793 // disable_spirit_irq(); 00794 printf("read() 1 "); 00795 00796 /* Checks if the RX buffer is empty */ 00797 if(IS_RXBUF_EMPTY()) { 00798 #ifndef NDEBUG 00799 debug("\r\nBuffer is empty\r\n"); 00800 #endif 00801 printf("[DEBUG] 2-1"); 00802 set_ready_state(); 00803 00804 cmd_strobe(SPIRIT1_STROBE_RX); 00805 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00806 // enable_spirit_irq(); 00807 return 0; 00808 } 00809 00810 if(bufsize < spirit_rx_len) { 00811 // enable_spirit_irq(); 00812 00813 /* If buf has the correct size */ 00814 #ifndef NDEBUG 00815 debug("\r\nTOO SMALL BUF\r\n"); 00816 #endif 00817 return 0; 00818 } else { 00819 /* Copies the packet received */ 00820 00821 memcpy(buf, spirit_rx_buf, spirit_rx_len); 00822 bufsize = spirit_rx_len; 00823 printf("recv 3-1"); 00824 00825 CLEAR_RXBUF(); 00826 printf(" 3-2"); 00827 00828 // enable_spirit_irq(); 00829 printf(" 3-3 read ok\n"); 00830 00831 return bufsize; 00832 } 00833 00834 } 00835 00836 int SimpleSpirit1::channel_clear(void) 00837 { 00838 float rssi_value; 00839 /* Local variable used to memorize the SPIRIT1 state */ 00840 uint8_t spirit_state = ON; 00841 00842 if(spirit_on == OFF) { 00843 /* Wakes up the SPIRIT1 */ 00844 on(); 00845 spirit_state = OFF; 00846 } 00847 00848 #ifndef NDEBUG 00849 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { 00850 debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); 00851 } 00852 #endif 00853 00854 // disable_spirit_irq(); 00855 00856 /* Reset State to Ready */ 00857 set_ready_state(); 00858 00859 /* Stores the RSSI value */ 00860 rssi_value = qi_get_rssi_dbm(); 00861 00862 // enable_spirit_irq(); 00863 00864 /* Puts the SPIRIT1 in its previous state */ 00865 if(spirit_state==OFF) { 00866 off(); 00867 #ifndef NDEBUG 00868 #ifdef USE_STANDBY_STATE 00869 if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) { 00870 #else 00871 if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) { 00872 #endif 00873 debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); 00874 } 00875 #endif 00876 } else { 00877 // disable_spirit_irq(); 00878 00879 set_ready_state(); 00880 00881 cmd_strobe(SPIRIT1_STROBE_RX); 00882 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00883 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { 00884 error("\r\nSpirit1: (#2) failed to enter rx (%x) => retry\r\n", last_state>>1); 00885 } 00886 00887 // enable_spirit_irq(); 00888 00889 #ifndef NDEBUG 00890 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { 00891 debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); 00892 } 00893 #endif 00894 } 00895 00896 /* Checks the RSSI value with the threshold */ 00897 if(rssi_value<CCA_THRESHOLD) { 00898 return 0; 00899 } else { 00900 return 1; 00901 } 00902 } 00903 00904 int SimpleSpirit1::get_pending_packet(void) 00905 { 00906 return !IS_RXBUF_EMPTY(); 00907 } 00908 00909 /** Spirit Irq Callback **/ 00910 /* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */ 00911 void SimpleSpirit1::IrqHandler() 00912 { 00913 #ifdef CUBEBITE_DEBUG 00914 printf("[CUBEBITE] IrqHandler() call !\r\n"); 00915 #endif //CUBEBITE_DEBUG 00916 00917 st_lib_spirit_irqs x_irq_status; 00918 00919 /* get interrupt source from radio */ 00920 irq_get_status(&x_irq_status); 00921 00922 /* The IRQ_TX_DATA_SENT notifies the packet has been sent. Puts the SPIRIT1 in RX */ 00923 if(x_irq_status.IRQ_TX_DATA_SENT) { 00924 /* betzw - NOTE: MUST be handled before `IRQ_RX_DATA_READY` for Nanostack integration! 00925 Logically, Nanostack only expects the "DONE" after "SUCCESS" (if it gets 00926 DONE before SUCCESS, it assumes you're not going to bother to send SUCCESS). 00927 */ 00928 #ifdef DEBUG_IRQ 00929 uint32_t *tmp = (uint32_t*)&x_irq_status; 00930 debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00931 debug_if(tx_fifo_remaining != 0, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00932 #endif 00933 00934 if(_spirit_tx_started) { 00935 printf("[IRQ] if(x_irq_status.IRQ_TX_DATA_SENT) in, if(_spirit_tx_started) in \n"); 00936 _spirit_tx_started = false; 00937 00938 /* call user callback */ 00939 if(_current_irq_callback) { 00940 _current_irq_callback(TX_DONE); 00941 } 00942 } 00943 00944 /* Disable handling of other TX flags */ 00945 x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET; 00946 tx_fifo_buffer = NULL; 00947 } 00948 00949 #ifndef RX_FIFO_THR_WA 00950 /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */ 00951 if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) { 00952 #ifdef DEBUG_IRQ 00953 uint32_t *tmp = (uint32_t*)&x_irq_status; 00954 debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00955 debug_if(!_spirit_tx_started, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00956 debug_if(tx_fifo_buffer == NULL, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00957 #endif 00958 00959 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo 00960 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining; 00961 00962 tx_fifo_remaining -= to_send; 00963 00964 /* Fill FIFO Buffer */ 00965 if(to_send > 0) { 00966 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]); 00967 } 00968 tx_buffer_pos += to_send; 00969 } 00970 #endif // !RX_FIFO_THR_WA 00971 00972 /* TX FIFO underflow/overflow error */ 00973 if(x_irq_status.IRQ_TX_FIFO_ERROR) { 00974 #ifdef DEBUG_IRQ 00975 uint32_t *tmp = (uint32_t*)&x_irq_status; 00976 debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); 00977 debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00978 #endif 00979 if(_spirit_tx_started) { 00980 _spirit_tx_started = false; 00981 /* call user callback */ 00982 if(_current_irq_callback) { 00983 _current_irq_callback(TX_ERR); 00984 } 00985 } 00986 00987 /* reset data still to be sent */ 00988 tx_fifo_remaining = 0; 00989 } 00990 00991 /* The IRQ_RX_DATA_READY notifies a new packet arrived */ 00992 if(x_irq_status.IRQ_RX_DATA_READY) { 00993 #ifdef DEBUG_IRQ 00994 uint32_t *tmp = (uint32_t*)&x_irq_status; 00995 debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 00996 #endif 00997 00998 if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!) 00999 #ifdef HEAVY_DEBUG 01000 debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); 01001 #endif 01002 } else { 01003 _is_receiving = false; // Finished receiving 01004 stop_rx_timeout(); 01005 01006 spirit_rx_len = pkt_basic_get_received_pkt_length(); 01007 01008 #ifdef DEBUG_IRQ 01009 debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); 01010 #endif 01011 01012 if(spirit_rx_len <= MAX_PACKET_LEN) { 01013 uint8_t to_receive = spirit_rx_len - _spirit_rx_pos; 01014 if(to_receive > 0) { 01015 spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]); 01016 _spirit_rx_pos += to_receive; 01017 } 01018 } 01019 01020 cmd_strobe(SPIRIT1_STROBE_FRX); 01021 01022 last_rssi = qi_get_rssi(); //MGR 01023 last_sqi = qi_get_sqi(); //MGR 01024 01025 /* call user callback */ 01026 if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) { 01027 _current_irq_callback(RX_DONE); 01028 } 01029 01030 /* Disable handling of other RX flags */ 01031 x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET; 01032 } 01033 } 01034 01035 #ifndef RX_FIFO_THR_WA 01036 /* RX FIFO almost full */ 01037 if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) { 01038 #ifdef DEBUG_IRQ 01039 uint32_t *tmp = (uint32_t*)&x_irq_status; 01040 debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 01041 #endif 01042 if(!_is_receiving) { // spurious irq?!? 01043 #ifdef DEBUG_IRQ 01044 debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); 01045 #endif 01046 } else { 01047 uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo(); 01048 if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) { 01049 spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]); 01050 _spirit_rx_pos += fifo_available; 01051 } else { 01052 #ifdef DEBUG_IRQ 01053 debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); 01054 #endif 01055 } 01056 } 01057 } 01058 #endif // !RX_FIFO_THR_WA 01059 01060 /* Reception errors */ 01061 if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) { 01062 #ifdef DEBUG_IRQ 01063 uint32_t *tmp = (uint32_t*)&x_irq_status; 01064 debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); 01065 debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 01066 #endif 01067 rx_timeout_handler(); 01068 if(_spirit_tx_started) { 01069 _spirit_tx_started = false; 01070 /* call user callback */ 01071 if(_current_irq_callback) { 01072 _current_irq_callback(TX_ERR); 01073 } 01074 } 01075 } 01076 01077 /* The IRQ_VALID_SYNC is used to notify a new packet is coming */ 01078 if(x_irq_status.IRQ_VALID_SYNC) { 01079 #ifdef DEBUG_IRQ 01080 uint32_t *tmp = (uint32_t*)&x_irq_status; 01081 debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); 01082 #endif 01083 /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and 01084 * the MCU trying to send a packet, which gets resolved in favor of 01085 * sending. 01086 */ 01087 if(_spirit_tx_started) { 01088 #ifdef DEBUG_IRQ 01089 debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); 01090 #endif 01091 } else { 01092 _is_receiving = true; 01093 start_rx_timeout(); 01094 } 01095 } 01096 }
Generated on Wed Jul 13 2022 00:11:56 by
