Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of stm-spirit1-rf-driver by
SimpleSpirit1.h
00001 /*** Mbed Includes ***/ 00002 #include "mbed.h" 00003 #include "mbed_debug.h" 00004 00005 00006 /*** Cube Includes ***/ 00007 #include "SPIRIT_Radio.h" 00008 #include "SPIRIT_Management.h" 00009 #include "SPIRIT_Commands.h" 00010 #include "MCU_Interface.h" 00011 00012 00013 /*** Contiki Lib Includes ***/ 00014 #include "spirit1.h" 00015 #include "spirit1-config.h" 00016 #include "spirit1-const.h" 00017 00018 00019 // betzw: enable beyond macro if you want debug messages also from IRQ handler 00020 // #define DEBUG_IRQ 00021 00022 00023 /*** Macros from Cube Implementation ***/ 00024 #define CLEAR_TXBUF() (spirit_tx_len = 0) 00025 #define IS_RXBUF_EMPTY() (spirit_rx_len == 0) 00026 #define CLEAR_RXBUF() do { \ 00027 spirit_rx_len = 0; \ 00028 _spirit_rx_pos = 0; \ 00029 } while(0) 00030 00031 00032 /*** Macros from Cube Implementation ***/ 00033 /* transceiver state. */ 00034 #define ON 0 00035 #define OFF 1 00036 00037 00038 /*** Macros for Spirit1 API ***/ 00039 /* max payload */ 00040 #define SPIRIT1_MAX_PAYLOAD (MAX_PACKET_LEN) 00041 00042 //180619 HJM : init 재시작을 위한 OnOff 변수 00043 // : 15:22, 일단 안해보고 해보기로.. spi init을 두번해도 상관 없는 거면 뭐 00044 //static volatile bool isItDoItRFInit; 00045 //static volatile bool isItDoItSPIInit; 00046 00047 00048 00049 00050 /*** Missing Cube External Declarations ***/ 00051 extern "C" void SpiritManagementSetFrequencyBase(uint32_t); 00052 00053 00054 /*** UnlockedSPI for Usage in IRQ context ***/ 00055 class UnlockedSPI : public SPI 00056 { 00057 public: 00058 UnlockedSPI(PinName mosi, PinName miso, PinName sclk) : 00059 SPI(mosi, miso, sclk) { } 00060 virtual ~UnlockedSPI() {} 00061 virtual void lock() { } 00062 virtual void unlock() { } 00063 }; 00064 00065 00066 /*** A Simple Spirit1 Class ***/ 00067 // NOTE: must be a singleton (due to mix of MBED/CUBE code)!!! 00068 // NOTE: implementation is IRQ-save but (intentionally) NOT thread-safe!!! 00069 /** Simple Spirit1 Class 00070 * 00071 * @Note Synchronization level: implementation is IRQ-save but (intentionally) NOT thread-safe!!! 00072 * 00073 * Example: 00074 * @code 00075 * #include "mbed.h" 00076 * #include "SimpleSpirit1.h" 00077 * 00078 * static char send_buf[] = "Hello World!"; 00079 * 00080 * static SimpleSpirit1 &myspirit = SimpleSpirit1::CreateInstance(D11, D12, D3, D9, D10, D2); 00081 * 00082 * static volatile bool tx_done_flag = false; 00083 * 00084 * static void callback_func(int event) 00085 * { 00086 * if (event == SimpleSpirit1::TX_DONE) { 00087 * tx_done_flag = true; 00088 * } 00089 * } 00090 * 00091 * int main() 00092 * { 00093 * myspirit.attach_irq_callback(callback_func); 00094 * myspirit.on(); 00095 * 00096 * while(1) 00097 * { 00098 * size_t curr_len = strlen((const char*)send_buf); 00099 * myspirit.send(send_buf, curr_len); 00100 * 00101 * while(!tx_done_flag); 00102 * tx_done_flag = false; 00103 * } 00104 * } 00105 * @endcode 00106 */ 00107 class SimpleSpirit1 00108 { 00109 protected: 00110 static SimpleSpirit1 *_singleton; 00111 00112 /** Communication Interface Instance Variables **/ 00113 UnlockedSPI _spi; // betzw - NOTE: Morpho/Zio pins are valid only for NUCLEO-F401RE 00114 // mosi: PA_7 (D11) 00115 // miso: PA_6 (D12) 00116 // sclk: PB_3 (D3) or 00117 // PA_5 (D13) (only in case you unmount R4 & mount R7, 00118 // (note: in this case you may not use LED1 on some platforms) 00119 // bits: 8-bit 00120 // mode: 0 00121 // ordr: MSB 00122 // freq: max 10MHz 00123 InterruptIn _irq; // PC_7 (D9) (falling) 00124 DigitalOut _chip_select; // PB_6 (D10) ('1' == chip unselected) 00125 DigitalOut _shut_down; // PA_10 (D2) ('1' == shut_down) 00126 DigitalOut _led; // PB_4 (D5) (optional) 00127 00128 Callback<void(int)> _current_irq_callback; 00129 Timeout _rx_receiving_timeout; 00130 00131 void rx_timeout_handler(void) 00132 { 00133 set_ready_state(); 00134 cmd_strobe(SPIRIT1_STROBE_RX); 00135 #ifdef DEBUG_IRQ 00136 debug("\r\n%s (%d)\r\n", __func__, __LINE__); 00137 #endif 00138 } 00139 00140 void start_rx_timeout(void) 00141 { 00142 _rx_receiving_timeout.attach_us(Callback<void()>(this, &SimpleSpirit1::rx_timeout_handler), 100 * 1000); // 100ms 00143 } 00144 00145 void stop_rx_timeout(void) 00146 { 00147 _rx_receiving_timeout.detach(); 00148 } 00149 00150 /** Static Variables from Cube Implementation **/ 00151 /* 00152 * The buffers which hold incoming data. 00153 * The +1 because of the first byte, 00154 * which will contain the length of the packet. 00155 */ 00156 volatile uint16_t spirit_tx_len; 00157 volatile bool _spirit_tx_started; 00158 volatile uint16_t spirit_rx_len; 00159 volatile uint16_t _spirit_rx_pos; 00160 volatile bool _spirit_rx_err; 00161 uint8_t spirit_rx_buf[MAX_PACKET_LEN]; 00162 volatile bool _is_receiving; 00163 00164 00165 00166 /** Status Variables from Cube Implementation **/ 00167 unsigned int spirit_on; 00168 uint8_t last_rssi; //MGR 00169 uint8_t last_sqi; //MGR 00170 00171 /** Low Level Instance Variables **/ 00172 unsigned int _nr_of_irq_disables; 00173 00174 //HJM : SPI 셋팅 변수 00175 volatile uint32_t _uint32SpiClkSettingValue; 00176 00177 00178 00179 /** Low Level Instance Methods **/ 00180 void disable_spirit_irq(void) 00181 { 00182 _irq.disable_irq(); 00183 _nr_of_irq_disables++; 00184 #ifndef NDEBUG 00185 debug_if(_nr_of_irq_disables == 0, "\r\nassert failed in: %s (%d)\r\n", __func__, __LINE__); 00186 #endif 00187 } 00188 00189 void enable_spirit_irq(void) 00190 { 00191 #ifndef NDEBUG 00192 debug_if(_nr_of_irq_disables == 0, "\r\nassert failed in: %s (%d)\r\n", __func__, __LINE__); 00193 #endif 00194 if(--_nr_of_irq_disables == 0) 00195 _irq.enable_irq(); 00196 } 00197 00198 void chip_select() { _chip_select = 0; } 00199 void chip_unselect() { _chip_select = 1; } 00200 00201 void enter_shutdown() { 00202 _shut_down = 1; 00203 wait_ms(5); // wait 5 milliseconds (to allow Spirit1 to shut down) 00204 } 00205 00206 void exit_shutdown() { 00207 _shut_down = 0; 00208 wait_ms(10); // wait 10 milliseconds (to allow Spirit1 a proper boot-up sequence) 00209 } 00210 00211 void cs_to_sclk_delay(void) 00212 { 00213 wait_us(1); // heuristic value 00214 } 00215 00216 /** 00217 * @brief Write and read a buffer to/from the SPI peripheral device at the same time 00218 * in 8-bit data mode using synchronous SPI communication. 00219 * @param[in] pBufferToWrite pointer to the buffer of data to send. 00220 * @param[out] pBufferToRead pointer to the buffer to read data into. 00221 * @param[in] NumBytes number of bytes to read and write. 00222 * @retval 0 if ok. 00223 * @retval -1 if data format error. 00224 * @note When using the SPI in Interrupt-mode, remember to disable interrupts 00225 * before calling this function and to enable them again after. 00226 */ 00227 void spi_write_read(uint8_t* pBufferToWrite, uint8_t* pBufferToRead, uint16_t NumBytes) 00228 { 00229 /* Read and write data at the same time. */ 00230 for (int i = 0; i < NumBytes; i++) { 00231 pBufferToRead[i] = _spi.write(pBufferToWrite[i]); 00232 } 00233 } 00234 00235 /** Radio Instance Methods **/ 00236 void radio_set_xtal_freq(uint32_t freq) { 00237 SpiritRadioSetXtalFrequency(freq); 00238 } 00239 00240 void radio_set_pa_level_dbm(uint8_t cIndex, float fPowerdBm) { 00241 SpiritRadioSetPALeveldBm(cIndex, fPowerdBm); 00242 } 00243 00244 void radio_set_pa_level_max_index(uint8_t cIndex) { 00245 SpiritRadioSetPALevelMaxIndex(cIndex); 00246 } 00247 00248 uint8_t radio_init(SRadioInit *init_struct) { 00249 return SpiritRadioInit(init_struct); 00250 } 00251 00252 void radio_persistent_rx(SpiritFunctionalState xNewState) { 00253 SpiritRadioPersistenRx(xNewState); 00254 } 00255 00256 void radio_afc_freeze_on_sync(SpiritFunctionalState xNewState) { 00257 SpiritRadioAFCFreezeOnSync(xNewState); 00258 } 00259 00260 /** Packet System Instance Methods **/ 00261 void pkt_basic_init(PktBasicInit* pxPktBasicInit) { 00262 SpiritPktBasicInit(pxPktBasicInit); 00263 } 00264 00265 void pkt_basic_set_payload_length(uint16_t nPayloadLength) { 00266 SpiritPktBasicSetPayloadLength(nPayloadLength); 00267 } 00268 00269 uint16_t pkt_basic_get_received_pkt_length(void) { 00270 return SpiritPktBasicGetReceivedPktLength(); 00271 } 00272 00273 /** IRQ Instance Methods **/ 00274 void irq_de_init(SpiritIrqs* pxIrqInit) { 00275 SpiritIrqDeInit(pxIrqInit); 00276 } 00277 00278 void irq_clear_status(void) { 00279 SpiritIrqClearStatus(); 00280 } 00281 00282 void irq_set_status(IrqList xIrq, SpiritFunctionalState xNewState) { 00283 SpiritIrq(xIrq, xNewState); 00284 } 00285 00286 void irq_get_status(SpiritIrqs* pxIrqStatus) { 00287 SpiritIrqGetStatus(pxIrqStatus); 00288 } 00289 00290 /** Management Instance Methods **/ 00291 void mgmt_set_freq_base(uint32_t freq) { 00292 SpiritManagementSetFrequencyBase(freq); 00293 } 00294 00295 void mgmt_refresh_status(void) { 00296 SpiritRefreshStatus(); 00297 } 00298 00299 /** Spirit GPIO Instance Methods **/ 00300 void spirit_gpio_init(SGpioInit* pxGpioInitStruct) { 00301 SpiritGpioInit(pxGpioInitStruct); 00302 } 00303 00304 /** Qi Instance Methods **/ 00305 void qi_set_sqi_threshold(SqiThreshold xSqiThr) { 00306 SpiritQiSetSqiThreshold(xSqiThr); 00307 } 00308 00309 void qi_sqi_check(SpiritFunctionalState xNewState) { 00310 SpiritQiSqiCheck(xNewState); 00311 } 00312 00313 void qi_set_rssi_threshold_dbm(int nDbmValue) { 00314 SpiritQiSetRssiThresholddBm(nDbmValue); 00315 } 00316 00317 float qi_get_rssi_dbm() { 00318 last_rssi = qi_get_rssi(); 00319 return get_last_rssi_dbm(); 00320 } 00321 00322 uint8_t qi_get_rssi() { 00323 return SpiritQiGetRssi(); 00324 } 00325 00326 uint8_t qi_get_sqi() { 00327 return SpiritQiGetSqi(); 00328 } 00329 00330 /** Timer Instance Methods **/ 00331 void timer_set_rx_timeout_stop_condition(RxTimeoutStopCondition xStopCondition) { 00332 SpiritTimerSetRxTimeoutStopCondition(xStopCondition); 00333 } 00334 00335 void timer_set_rx_timeout_counter(uint8_t cCounter) { 00336 SpiritTimerSetRxTimeoutCounter(cCounter); 00337 } 00338 00339 void timer_set_infinite_rx_timeout(void) { 00340 timer_set_rx_timeout_counter(0); 00341 } 00342 00343 /** CSMA/CA Instance Methods **/ 00344 void csma_ca_state(SpiritFunctionalState xNewState) { 00345 SpiritCsma(xNewState); 00346 } 00347 00348 void csma_ca_init(CsmaInit* pxCsmaInit) { 00349 csma_ca_state(S_DISABLE); // Disabled at init 00350 SpiritCsmaInit(pxCsmaInit); 00351 SpiritCsmaSeedReloadMode(S_DISABLE); // always disable seed reload 00352 } 00353 00354 /** Command Instance Methods**/ 00355 void cmd_strobe(uint8_t cmd) { 00356 SpiritCmdStrobeCommand((SpiritCmd)cmd); 00357 } 00358 00359 void cmd_strobe_flush_rx_fifo() { 00360 SpiritCmdStrobeCommand(CMD_FLUSHRXFIFO); 00361 } 00362 00363 /** SPI Instance Methods **/ 00364 StatusBytes spi_write_linear_fifo(uint8_t cNbBytes, uint8_t* pcBuffer) { 00365 return SdkEvalSpiWriteFifo(cNbBytes, pcBuffer); 00366 } 00367 00368 StatusBytes spi_read_linear_fifo(uint8_t cNbBytes, uint8_t* pcBuffer) { 00369 return SdkEvalSpiReadFifo(cNbBytes, pcBuffer); 00370 } 00371 00372 /** Linear FIFO Instance Methods **/ 00373 uint8_t linear_fifo_read_num_elements_rx_fifo(void) { 00374 return SpiritLinearFifoReadNumElementsRxFifo(); 00375 } 00376 00377 uint8_t linear_fifo_read_num_elements_tx_fifo(void) { 00378 return SpiritLinearFifoReadNumElementsTxFifo(); 00379 } 00380 00381 void linear_fifo_set_almost_full_thr_rx(uint8_t cThrRxFifo) { 00382 SpiritLinearFifoSetAlmostFullThresholdRx(cThrRxFifo); 00383 } 00384 00385 /** Calibration Instance Methods **/ 00386 void calibration_rco(SpiritFunctionalState xNewState) { 00387 SpiritCalibrationRco(xNewState); 00388 } 00389 00390 /** Internal Spirit Methods */ 00391 int set_ready_state(void); 00392 uint8_t refresh_state(void); 00393 00394 /** Friend Functions **/ 00395 friend StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer); 00396 friend StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer); 00397 friend StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode); 00398 friend StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer); 00399 friend StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer); 00400 00401 /** Sdk Instance Methods **/ 00402 StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer); 00403 StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer); 00404 StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode); 00405 StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer); 00406 StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer); 00407 00408 /** Helper Instance Methods **/ 00409 void chip_sync_select() { 00410 disable_spirit_irq(); 00411 chip_select(); 00412 cs_to_sclk_delay(); 00413 } 00414 00415 void chip_sync_unselect() { 00416 chip_unselect(); 00417 enable_spirit_irq(); 00418 } 00419 00420 /** Init Instance Method **/ 00421 void init(); 00422 00423 /** Spirit Irq Callback */ 00424 void IrqHandler(); 00425 00426 00427 00428 /** Constructor **/ 00429 SimpleSpirit1(PinName mosi, PinName miso, PinName sclk, 00430 PinName irq, PinName cs, PinName sdn, 00431 PinName led, 00432 uint32_t uint32SClkSettingValue); 00433 00434 /** Destructor **/ 00435 ~SimpleSpirit1(void); // should never be called! 00436 00437 00438 00439 00440 00441 00442 00443 00444 00445 00446 00447 00448 public: 00449 enum 00450 { 00451 RX_DONE, 00452 TX_DONE, 00453 TX_ERR 00454 }; 00455 00456 00457 00458 00459 00460 00461 /** Create singleton instance of 'SimpleSpirit1' 00462 * 00463 * @param mosi 'PinName' of mosi pin to use 00464 * @param miso 'PinName' of miso pin to use 00465 * @param sclk 'PinName' of clock pin to use 00466 * @param irq 'PinName' of interrupt pin to use 00467 * @param cs 'PinName' of chip-select pin pin to use 00468 * @param sdn 'PinName' of pin to use for device shutdown 00469 * 00470 * @returns reference to singleton instance 00471 */ 00472 static SimpleSpirit1& CreateInstance( 00473 PinName mosi, PinName miso, PinName sclk, 00474 PinName irq, PinName cs, PinName sdn, 00475 PinName led = NC, 00476 uint32_t uint32SClkSettingValue = 6500000 //6.5Mhz, SPI CLK speed 초기값, 최고 속도 00477 ) 00478 { 00479 if(_singleton == NULL) 00480 { 00481 _singleton = new SimpleSpirit1(mosi, miso, sclk, 00482 irq, cs, sdn, led, uint32SClkSettingValue); 00483 printf("[INIT_REVISE] init start..\n"); 00484 // isItDoItRFInit = false; 00485 // isItDoItSPIInit = false; 00486 wait(0.1); 00487 _singleton->init(); 00488 printf("[INIT_REVISE] init end..\n"); 00489 } 00490 else 00491 { 00492 error("SimpleSpirit1 singleton already created!\n"); 00493 } 00494 00495 return *_singleton; 00496 } 00497 00498 00499 00500 00501 00502 /** Get singleton instance of 'SimpleSpirit1' 00503 * 00504 * @returns reference to singleton instance 00505 */ 00506 static SimpleSpirit1& Instance() 00507 { 00508 if(_singleton == NULL) 00509 { 00510 error("SimpleSpirit1 must be created before used!\n"); 00511 } 00512 00513 return *_singleton; 00514 } 00515 00516 00517 00518 00519 00520 00521 00522 00523 00524 00525 00526 00527 00528 /** Attach a function to be called by the Spirit Irq handler when an event has occurred 00529 * 00530 * @param func A void(int) callback, or 0 to set as none 00531 * 00532 * @note Function 'func' will be executed in interrupt context! 00533 * @note Function 'func' will be call with either 'RX_DONE', 'TX_DONE', or 'TX_ERR' as parameter 00534 * to indicate which event has occurred. 00535 */ 00536 void attach_irq_callback(Callback<void(int)> func) 00537 { 00538 _current_irq_callback = func; 00539 } 00540 00541 /** Switch Radio On 00542 */ 00543 int on(void); 00544 00545 /** Switch Radio Off 00546 */ 00547 int off(void); 00548 00549 /** Set Channel 00550 */ 00551 void set_channel(uint8_t channel) { 00552 SpiritRadioSetChannel(channel); 00553 } 00554 00555 /** Send a Buffer 00556 * 00557 * @param payload pointer to buffer to be send 00558 * @param payload_len length of payload buffer in bytes 00559 * @param use_csma_ca should CSMA/CA be enabled for transmission 00560 * 00561 * @returns zero in case of success, non-zero error code otherwise 00562 * 00563 * @note the maximum payload size in bytes allowed is defined by macro 'SPIRIT1_MAX_PAYLOAD' 00564 */ 00565 int send(const void *payload, unsigned int payload_len, bool use_csma_ca = true); 00566 00567 /** Copy received data into buffer 00568 * 00569 * @param buf pointer to buffer to be filled 00570 * @param bufsize size of buffer 00571 * 00572 * @returns number of bytes copied into the buffer 00573 * 00574 * @note the buffer should be (at least) of size 'SPIRIT1_MAX_PAYLOAD' (in bytes). 00575 */ 00576 int read(void *buf, unsigned int bufsize); 00577 00578 /** Perform a Clear-Channel Assessment (CCA) to find out whether the medium is idle or not. 00579 * 00580 * @returns 1 if the medium is busy. 00581 */ 00582 int channel_clear(void); 00583 00584 /** Check if the radio driver has just received a packet 00585 */ 00586 int get_pending_packet(void); 00587 00588 /** Is radio currently receiving 00589 */ 00590 bool is_receiving(void) { 00591 return _is_receiving; 00592 } 00593 00594 /** Get latest value of RSSI (in dBm) 00595 */ 00596 float get_last_rssi_dbm(void) { 00597 get_last_rssi_raw(); 00598 return (-120.0+((float)(last_rssi-20))/2); 00599 } 00600 00601 /** Get latest value of RSSI (as Spirit1 raw value) 00602 */ 00603 uint8_t get_last_rssi_raw(void) { 00604 if(last_rssi == 0) { 00605 last_rssi = qi_get_rssi(); 00606 } 00607 return last_rssi; 00608 } 00609 00610 /** Get latest value of LQI (scaled to 8-bit) 00611 */ 00612 uint8_t get_last_sqi(void) { 00613 const uint8_t max_sqi = 8 * ((SYNC_LENGTH>>1)+1); 00614 if(last_sqi == 0) { 00615 last_sqi = qi_get_sqi(); 00616 } 00617 if(last_sqi > max_sqi) last_sqi = max_sqi; 00618 00619 return (last_sqi * 255 / max_sqi); 00620 } 00621 00622 /** Reset Board 00623 */ 00624 void reset_board() 00625 { 00626 printf("[INIT_REVISE]reset board ...\n"); 00627 init(); 00628 printf("[INIT_REVISE]reset board end.\n"); 00629 } 00630 00631 00632 00633 00634 00635 00636 00637 00638 00639 00640 00641 00642 00643 00644 00645 //************************************************************************************* 00646 //HJM SUDO code : SPI 클럭 셋팅 가능 함수 00647 //************************************************************************************* 00648 /** Set SPI Clock 00649 */ 00650 void set_spi_clock(uint32_t ) 00651 { 00652 00653 } 00654 00655 00656 00657 00658 00659 //************************************************************************************* 00660 00661 00662 00663 00664 }; 00665 00666 00667 00668 00669 /* 00670 HJM SUDO code : 고려 상황 정리 00671 1. 올바르지 않은 행동을 할 인스턴스가 생성 되었을 시는 어떻게 하나?? 00672 -> 생성자를 사용했을 시 포인터를 반환 하도록 해서, 올바르지 않은 인스턴스가 만들어졌을 시에는 반환 객체 주소 값을 반환하지 않도록 하면 된다. 00673 => ex> 00674 test *t; 00675 t = new test(); 00676 if(NULL == t) 00677 { 00678 printf("올바르지 않은 객체가 생성되었습니다!\n"); 00679 return; 00680 } 00681 00682 00683 00684 00685 00686 */ 00687 00688 00689
Generated on Wed Jul 13 2022 00:11:56 by
1.7.2
