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