Added support for the WNC M14A2A Cellular LTE Data Module.
Dependencies: WNC14A2AInterface
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 Performance (due to singleton) ***/ 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 Tue Jul 12 2022 19:09:04 by 1.7.2