JunMo Hong / stm-spirit1-rf-driver_for_cubebite

Fork of EV-COG-AD3029LZ by JunMo Hong

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleSpirit1.cpp Source File

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 }