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.
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 /*** Missing Cube External Declarations ***/ 00039 extern "C" void SpiritManagementSetFrequencyBase(uint32_t); 00040 00041 00042 /*** UnlockedSPI for Usage in IRQ context ***/ 00043 class UnlockedSPI : public SPI { 00044 public: 00045 UnlockedSPI(PinName mosi, PinName miso, PinName sclk) : 00046 SPI(mosi, miso, sclk) { } 00047 virtual ~UnlockedSPI() {} 00048 virtual void lock() { } 00049 virtual void unlock() { } 00050 }; 00051 00052 00053 /*** A Simple Spirit1 Class ***/ 00054 // NOTE: must be a singleton (due to mix of MBED/CUBE code)!!! 00055 // NOTE: implementation is IRQ-save but (intentionally) NOT thread-safe!!! 00056 class SimpleSpirit1 { 00057 protected: 00058 static SimpleSpirit1 *_singleton; 00059 00060 /** Communication Interface Instance Variables **/ 00061 UnlockedSPI _spi; // betzw - NOTE: Morpho/Zio pins are valid only for NUCLEO-F401RE 00062 // mosi: PA_7 (D11) 00063 // miso: PA_6 (D12) 00064 // sclk: PB_3 (D3) or 00065 // PA_5 (D13) (only in case you unmount R4 & mount R7, 00066 // (note: in this case you may not use LED1 on some platforms) 00067 // bits: 8-bit 00068 // mode: 0 00069 // ordr: MSB 00070 // freq: max 10MHz 00071 InterruptIn _irq; // PC_7 (D9) (falling) 00072 DigitalOut _chip_select; // PB_6 (D10) ('1' == chip unselected) 00073 DigitalOut _shut_down; // PA_10 (D2) ('1' == shut_down) 00074 DigitalOut _led; // PB_4 (D5) (optional) 00075 00076 Callback<void(int)> _current_irq_callback; 00077 Timeout _rx_receiving_timeout; 00078 00079 void rx_timeout_handler(void) { 00080 set_ready_state(); 00081 cmd_strobe(SPIRIT1_STROBE_RX); 00082 #ifdef DEBUG_IRQ 00083 debug("\n\r%s (%d)\n\r", __func__, __LINE__); 00084 #endif 00085 } 00086 00087 void start_rx_timeout(void) { 00088 _rx_receiving_timeout.attach_us(Callback<void()>(this, &SimpleSpirit1::rx_timeout_handler), 100 * 1000); // 100ms 00089 } 00090 00091 void stop_rx_timeout(void) { 00092 _rx_receiving_timeout.detach(); 00093 } 00094 00095 /** Static Variables from Cube Implementation **/ 00096 /* 00097 * The buffers which hold incoming data. 00098 * The +1 because of the first byte, 00099 * which will contain the length of the packet. 00100 */ 00101 volatile uint16_t spirit_tx_len; 00102 volatile bool _spirit_tx_started; 00103 volatile uint16_t spirit_rx_len; 00104 volatile uint16_t _spirit_rx_pos; 00105 volatile bool _spirit_rx_err; 00106 uint8_t spirit_rx_buf[MAX_PACKET_LEN]; 00107 volatile bool _is_receiving; 00108 00109 /** Status Variables from Cube Implementation **/ 00110 unsigned int spirit_on; 00111 uint8_t last_rssi; //MGR 00112 uint8_t last_sqi; //MGR 00113 00114 /** Low Level Instance Variables **/ 00115 unsigned int _nr_of_irq_disables; 00116 00117 /** Low Level Instance Methods **/ 00118 void disable_spirit_irq(void) { 00119 _irq.disable_irq(); 00120 _nr_of_irq_disables++; 00121 #ifndef NDEBUG 00122 debug_if(_nr_of_irq_disables == 0, "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__); 00123 #endif 00124 } 00125 00126 void enable_spirit_irq(void) { 00127 #ifndef NDEBUG 00128 debug_if(_nr_of_irq_disables == 0, "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__); 00129 #endif 00130 if(--_nr_of_irq_disables == 0) 00131 _irq.enable_irq(); 00132 } 00133 00134 void chip_select() { _chip_select = 0; } 00135 void chip_unselect() { _chip_select = 1; } 00136 00137 void enter_shutdown() { 00138 _shut_down = 1; 00139 wait_ms(5); // wait 5 milliseconds (to allow Spirit1 to shut down) 00140 } 00141 00142 void exit_shutdown() { 00143 _shut_down = 0; 00144 wait_ms(10); // wait 10 milliseconds (to allow Spirit1 a proper boot-up sequence) 00145 } 00146 00147 void cs_to_sclk_delay(void) { 00148 wait_us(1); // heuristic value 00149 } 00150 00151 /** 00152 * @brief Write and read a buffer to/from the SPI peripheral device at the same time 00153 * in 8-bit data mode using synchronous SPI communication. 00154 * @param[in] pBufferToWrite pointer to the buffer of data to send. 00155 * @param[out] pBufferToRead pointer to the buffer to read data into. 00156 * @param[in] NumBytes number of bytes to read and write. 00157 * @retval 0 if ok. 00158 * @retval -1 if data format error. 00159 * @note When using the SPI in Interrupt-mode, remember to disable interrupts 00160 * before calling this function and to enable them again after. 00161 */ 00162 void spi_write_read(uint8_t* pBufferToWrite, uint8_t* pBufferToRead, uint16_t NumBytes) 00163 { 00164 /* Read and write data at the same time. */ 00165 for (int i = 0; i < NumBytes; i++) { 00166 pBufferToRead[i] = _spi.write(pBufferToWrite[i]); 00167 } 00168 } 00169 00170 /** Radio Instance Methods **/ 00171 void radio_set_xtal_freq(uint32_t freq) { 00172 SpiritRadioSetXtalFrequency(freq); 00173 } 00174 00175 void radio_set_pa_level_dbm(uint8_t cIndex, float fPowerdBm) { 00176 SpiritRadioSetPALeveldBm(cIndex, fPowerdBm); 00177 } 00178 00179 void radio_set_pa_level_max_index(uint8_t cIndex) { 00180 SpiritRadioSetPALevelMaxIndex(cIndex); 00181 } 00182 00183 uint8_t radio_init(SRadioInit *init_struct) { 00184 return SpiritRadioInit(init_struct); 00185 } 00186 00187 void radio_persistent_rx(SpiritFunctionalState xNewState) { 00188 SpiritRadioPersistenRx(xNewState); 00189 } 00190 00191 void radio_afc_freeze_on_sync(SpiritFunctionalState xNewState) { 00192 SpiritRadioAFCFreezeOnSync(xNewState); 00193 } 00194 00195 /** Packet System Instance Methods **/ 00196 void pkt_basic_init(PktBasicInit* pxPktBasicInit) { 00197 SpiritPktBasicInit(pxPktBasicInit); 00198 } 00199 00200 void pkt_basic_set_payload_length(uint16_t nPayloadLength) { 00201 SpiritPktBasicSetPayloadLength(nPayloadLength); 00202 } 00203 00204 uint16_t pkt_basic_get_received_pkt_length(void) { 00205 return SpiritPktBasicGetReceivedPktLength(); 00206 } 00207 00208 /** IRQ Instance Methods **/ 00209 void irq_de_init(SpiritIrqs* pxIrqInit) { 00210 SpiritIrqDeInit(pxIrqInit); 00211 } 00212 00213 void irq_clear_status(void) { 00214 SpiritIrqClearStatus(); 00215 } 00216 00217 void irq_set_status(IrqList xIrq, SpiritFunctionalState xNewState) { 00218 SpiritIrq(xIrq, xNewState); 00219 } 00220 00221 void irq_get_status(SpiritIrqs* pxIrqStatus) { 00222 SpiritIrqGetStatus(pxIrqStatus); 00223 } 00224 00225 /** Management Instance Methods **/ 00226 void mgmt_set_freq_base(uint32_t freq) { 00227 SpiritManagementSetFrequencyBase(freq); 00228 } 00229 00230 void mgmt_refresh_status(void) { 00231 SpiritRefreshStatus(); 00232 } 00233 00234 /** Spirit GPIO Instance Methods **/ 00235 void spirit_gpio_init(SGpioInit* pxGpioInitStruct) { 00236 SpiritGpioInit(pxGpioInitStruct); 00237 } 00238 00239 /** Qi Instance Methods **/ 00240 void qi_set_sqi_threshold(SqiThreshold xSqiThr) { 00241 SpiritQiSetSqiThreshold(xSqiThr); 00242 } 00243 00244 void qi_sqi_check(SpiritFunctionalState xNewState) { 00245 SpiritQiSqiCheck(xNewState); 00246 } 00247 00248 void qi_set_rssi_threshold_dbm(int nDbmValue) { 00249 SpiritQiSetRssiThresholddBm(nDbmValue); 00250 } 00251 00252 float qi_get_rssi_dbm() { 00253 last_rssi = qi_get_rssi(); 00254 return get_last_rssi_dbm(); 00255 } 00256 00257 uint8_t qi_get_rssi() { 00258 return SpiritQiGetRssi(); 00259 } 00260 00261 uint8_t qi_get_sqi() { 00262 return SpiritQiGetSqi(); 00263 } 00264 00265 /** Timer Instance Methods **/ 00266 void timer_set_rx_timeout_stop_condition(RxTimeoutStopCondition xStopCondition) { 00267 SpiritTimerSetRxTimeoutStopCondition(xStopCondition); 00268 } 00269 00270 void timer_set_rx_timeout_counter(uint8_t cCounter) { 00271 SpiritTimerSetRxTimeoutCounter(cCounter); 00272 } 00273 00274 void timer_set_infinite_rx_timeout(void) { 00275 timer_set_rx_timeout_counter(0); 00276 } 00277 00278 /** CSMA/CA Instance Methods **/ 00279 void csma_ca_state(SpiritFunctionalState xNewState) { 00280 SpiritCsma(xNewState); 00281 } 00282 00283 void csma_ca_init(CsmaInit* pxCsmaInit) { 00284 csma_ca_state(S_DISABLE); // Disabled at init 00285 SpiritCsmaInit(pxCsmaInit); 00286 SpiritCsmaSeedReloadMode(S_DISABLE); // always disable seed reload 00287 } 00288 00289 /** Command Instance Methods**/ 00290 void cmd_strobe(uint8_t cmd) { 00291 SpiritCmdStrobeCommand((SpiritCmd)cmd); 00292 } 00293 00294 void cmd_strobe_flush_rx_fifo() { 00295 SpiritCmdStrobeCommand(CMD_FLUSHRXFIFO); 00296 } 00297 00298 /** SPI Instance Methods **/ 00299 StatusBytes spi_write_linear_fifo(uint8_t cNbBytes, uint8_t* pcBuffer) { 00300 return SdkEvalSpiWriteFifo(cNbBytes, pcBuffer); 00301 } 00302 00303 StatusBytes spi_read_linear_fifo(uint8_t cNbBytes, uint8_t* pcBuffer) { 00304 return SdkEvalSpiReadFifo(cNbBytes, pcBuffer); 00305 } 00306 00307 /** Linear FIFO Instance Methods **/ 00308 uint8_t linear_fifo_read_num_elements_rx_fifo(void) { 00309 return SpiritLinearFifoReadNumElementsRxFifo(); 00310 } 00311 00312 uint8_t linear_fifo_read_num_elements_tx_fifo(void) { 00313 return SpiritLinearFifoReadNumElementsTxFifo(); 00314 } 00315 00316 void linear_fifo_set_almost_full_thr_rx(uint8_t cThrRxFifo) { 00317 SpiritLinearFifoSetAlmostFullThresholdRx(cThrRxFifo); 00318 } 00319 00320 /** Calibration Instance Methods **/ 00321 void calibration_rco(SpiritFunctionalState xNewState) { 00322 SpiritCalibrationRco(xNewState); 00323 } 00324 00325 /** Internal Spirit Methods */ 00326 void set_ready_state(void); 00327 uint8_t refresh_state(void); 00328 00329 /** Friend Functions **/ 00330 friend StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer); 00331 friend StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer); 00332 friend StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode); 00333 friend StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer); 00334 friend StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer); 00335 00336 /** Sdk Instance Methods **/ 00337 StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer); 00338 StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer); 00339 StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode); 00340 StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer); 00341 StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer); 00342 00343 /** Helper Instance Methods **/ 00344 void chip_sync_select() { 00345 disable_spirit_irq(); 00346 chip_select(); 00347 cs_to_sclk_delay(); 00348 } 00349 00350 void chip_sync_unselect() { 00351 chip_unselect(); 00352 enable_spirit_irq(); 00353 } 00354 00355 /** Init Instance Method **/ 00356 void init(); 00357 00358 /** Spirit Irq Callback */ 00359 void IrqHandler(); 00360 00361 /** Constructor **/ 00362 SimpleSpirit1(PinName mosi, PinName miso, PinName sclk, 00363 PinName irq, PinName cs, PinName sdn, 00364 PinName led); 00365 00366 /** Destructor **/ 00367 ~SimpleSpirit1(void); // should never be called! 00368 00369 public: 00370 enum { 00371 RX_DONE, 00372 TX_DONE, 00373 TX_ERR 00374 }; 00375 00376 static SimpleSpirit1& CreateInstance(PinName mosi, PinName miso, PinName sclk, 00377 PinName irq, PinName cs, PinName sdn, 00378 PinName led = NC) { 00379 00380 if(_singleton == NULL) { 00381 _singleton = new SimpleSpirit1(mosi, miso, sclk, 00382 irq, cs, sdn, led); 00383 _singleton->init(); 00384 } else { 00385 error("SimpleSpirit1 singleton already created!\n"); 00386 } 00387 00388 return *_singleton; 00389 } 00390 00391 static SimpleSpirit1& Instance() { 00392 if(_singleton == NULL) { 00393 error("SimpleSpirit1 must be created before used!\n"); 00394 } 00395 00396 return *_singleton; 00397 } 00398 00399 /** Attach a function to be called by the Spirit Irq handler when packet has arrived 00400 * 00401 * @param func A void() callback, or 0 to set as none 00402 * 00403 * @note Function 'func' will be executed in interrupt context! 00404 */ 00405 void attach_irq_callback(Callback<void(int)> func) { 00406 _current_irq_callback = func; 00407 } 00408 00409 /** Switch Radio On/Off **/ 00410 int on(void); 00411 int off(void); 00412 00413 /** Set Channel **/ 00414 void set_channel(uint8_t channel) { 00415 SpiritRadioSetChannel(channel); 00416 } 00417 00418 /** Send a Buffer **/ 00419 int send(const void *payload, unsigned int payload_len); 00420 00421 /** Read into Buffer **/ 00422 int read(void *buf, unsigned int bufsize); 00423 00424 /** Perform a Clear-Channel Assessment (CCA) to find out if there is 00425 a packet in the air or not. 00426 Returns 1 if packet has been seen. 00427 */ 00428 int channel_clear(void); 00429 00430 /** Check if the radio driver has just received a packet **/ 00431 int get_pending_packet(void); 00432 00433 /** Is radio currently receiving **/ 00434 bool is_receiving(void) { 00435 return _is_receiving; 00436 } 00437 00438 /** Get latest value of RSSI (in dBm) **/ 00439 float get_last_rssi_dbm(void) { 00440 get_last_rssi_raw(); 00441 return (-120.0+((float)(last_rssi-20))/2); 00442 } 00443 00444 /** Get latest value of RSSI (as Spirit1 raw value) **/ 00445 uint8_t get_last_rssi_raw(void) { 00446 if(last_rssi == 0) { 00447 last_rssi = qi_get_rssi(); 00448 } 00449 return last_rssi; 00450 } 00451 00452 /** Get latest value of LQI (scaled to 8-bit) **/ 00453 uint8_t get_last_sqi(void) { 00454 const uint8_t max_sqi = 8 * ((SYNC_LENGTH>>1)+1); 00455 if(last_sqi == 0) { 00456 last_sqi = qi_get_sqi(); 00457 } 00458 if(last_sqi > max_sqi) last_sqi = max_sqi; 00459 00460 return (last_sqi * 255 / max_sqi); 00461 } 00462 00463 /** Reset Board **/ 00464 void reset_board() { 00465 init(); 00466 } 00467 };
Generated on Wed Jul 13 2022 01:16:06 by
