JunMo Hong / EV-COG-AD3029LZ

Fork of stm-spirit1-rf-driver by ST

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 
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 }