센서보드 RF IRQ 테스트 중 and bug fix?

Fork of EV-COG-AD3029LZ by JunMo Hong

Committer:
Wolfgang Betz
Date:
Mon Jul 03 14:39:01 2017 +0200
Revision:
64:28ef790e4ef7
Parent:
57:8cc871dc6cac
Child:
68:247fd6e0ab66
Implement indications received by Kevin Bracey

Date: Mon, 3 Jul 2017 10:14:23 +0000
From: Kevin Bracey <notifications@github.com>

https://github.com/ARMmbed/mbed-os-example-client/issues/266#issuecomment-312606944

I've just spent a little while reviewing the Spirit driver code, just to see if I can see any obvious flaws. (Hard to say much without knowing the hardware, but I can look for general issues.)

I'm a bit wary about the software ack handling - can be tricky.

There is one specific problem that could be affecting performance now - it seems to me the acks are sent with a common send() routine that enables hardware CSMA-CD. An ack should be being sent 192us after transmission completion, without CSMA. Backing off the ack will greatly reduce the chance of packets being successfully acknowledged.

Other notes on ack reception - you're calling TX_DONE whenever tx_sequence == seq_number, whether you were expecting an ack or not. This could cause stack confusion in various ways (eg if you were backing off while someone else used the same sequence number). You should only process an ACK when you actually expect one (TX completed, and AR bit was set in it)

Also, while expecting an ack, it can be beneficial to report TX_FAIL and stop expecting when you receive anything other then an ack with the expected sequence number. The stack will eventually time out if it doesn't get TX_DONE, but receipt of anything else (including a wrongly-numbered ack) indicates a lack of acknowledgment, which can be reported immediately.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wolfgang Betz 34:edda6a7238ec 1 /*** Mbed Includes ***/
Wolfgang Betz 34:edda6a7238ec 2 #include "mbed.h"
Wolfgang Betz 34:edda6a7238ec 3 #include "mbed_debug.h"
Wolfgang Betz 34:edda6a7238ec 4
Wolfgang Betz 34:edda6a7238ec 5
Wolfgang Betz 34:edda6a7238ec 6 /*** Cube Includes ***/
Wolfgang Betz 34:edda6a7238ec 7 #include "SPIRIT_Radio.h"
Wolfgang Betz 34:edda6a7238ec 8 #include "SPIRIT_Management.h"
Wolfgang Betz 34:edda6a7238ec 9 #include "SPIRIT_Commands.h"
Wolfgang Betz 34:edda6a7238ec 10 #include "MCU_Interface.h"
Wolfgang Betz 34:edda6a7238ec 11
Wolfgang Betz 34:edda6a7238ec 12
Wolfgang Betz 34:edda6a7238ec 13 /*** Contiki Lib Includes ***/
Wolfgang Betz 34:edda6a7238ec 14 #include "spirit1.h"
Wolfgang Betz 34:edda6a7238ec 15 #include "spirit1-config.h"
Wolfgang Betz 34:edda6a7238ec 16 #include "spirit1-const.h"
Wolfgang Betz 34:edda6a7238ec 17
Wolfgang Betz 34:edda6a7238ec 18
Wolfgang Betz 34:edda6a7238ec 19 // betzw: enable beyond macro if you want debug messages also from IRQ handler
Wolfgang Betz 51:d46b4cc970c5 20 // #define DEBUG_IRQ
Wolfgang Betz 34:edda6a7238ec 21
Wolfgang Betz 34:edda6a7238ec 22
Wolfgang Betz 34:edda6a7238ec 23 /*** Macros from Cube Implementation ***/
Wolfgang Betz 34:edda6a7238ec 24 #define CLEAR_TXBUF() (spirit_tx_len = 0)
Wolfgang Betz 34:edda6a7238ec 25 #define IS_RXBUF_EMPTY() (spirit_rx_len == 0)
Wolfgang Betz 34:edda6a7238ec 26 #define CLEAR_RXBUF() do { \
Wolfgang Betz 34:edda6a7238ec 27 spirit_rx_len = 0; \
Wolfgang Betz 34:edda6a7238ec 28 _spirit_rx_pos = 0; \
Wolfgang Betz 34:edda6a7238ec 29 } while(0)
Wolfgang Betz 34:edda6a7238ec 30
Wolfgang Betz 34:edda6a7238ec 31
Wolfgang Betz 34:edda6a7238ec 32 /*** Macros from Cube Implementation ***/
Wolfgang Betz 34:edda6a7238ec 33 /* transceiver state. */
Wolfgang Betz 34:edda6a7238ec 34 #define ON 0
Wolfgang Betz 34:edda6a7238ec 35 #define OFF 1
Wolfgang Betz 34:edda6a7238ec 36
Wolfgang Betz 34:edda6a7238ec 37
Wolfgang Betz 34:edda6a7238ec 38 /*** Missing Cube External Declarations ***/
Wolfgang Betz 34:edda6a7238ec 39 extern "C" void SpiritManagementSetFrequencyBase(uint32_t);
Wolfgang Betz 34:edda6a7238ec 40
Wolfgang Betz 34:edda6a7238ec 41
Wolfgang Betz 57:8cc871dc6cac 42 /*** UnlockedSPI for Usage in IRQ context ***/
Wolfgang Betz 34:edda6a7238ec 43 class UnlockedSPI : public SPI {
Wolfgang Betz 34:edda6a7238ec 44 public:
Wolfgang Betz 34:edda6a7238ec 45 UnlockedSPI(PinName mosi, PinName miso, PinName sclk) :
Wolfgang Betz 34:edda6a7238ec 46 SPI(mosi, miso, sclk) { }
Wolfgang Betz 34:edda6a7238ec 47 virtual ~UnlockedSPI() {}
Wolfgang Betz 34:edda6a7238ec 48 virtual void lock() { }
Wolfgang Betz 34:edda6a7238ec 49 virtual void unlock() { }
Wolfgang Betz 34:edda6a7238ec 50 };
Wolfgang Betz 34:edda6a7238ec 51
Wolfgang Betz 34:edda6a7238ec 52
Wolfgang Betz 34:edda6a7238ec 53 /*** A Simple Spirit1 Class ***/
Wolfgang Betz 34:edda6a7238ec 54 // NOTE: must be a singleton (due to mix of MBED/CUBE code)!!!
Wolfgang Betz 34:edda6a7238ec 55 // NOTE: implementation is IRQ-save but (intentionally) NOT thread-safe!!!
Wolfgang Betz 34:edda6a7238ec 56 class SimpleSpirit1 {
Wolfgang Betz 34:edda6a7238ec 57 protected:
Wolfgang Betz 34:edda6a7238ec 58 static SimpleSpirit1 *_singleton;
Wolfgang Betz 34:edda6a7238ec 59
Wolfgang Betz 34:edda6a7238ec 60 /** Communication Interface Instance Variables **/
Wolfgang Betz 37:bc043030b55a 61 UnlockedSPI _spi; // betzw - NOTE: Morpho/Zio pins are valid only for NUCLEO-F401RE
Wolfgang Betz 34:edda6a7238ec 62 // mosi: PA_7 (D11)
Wolfgang Betz 34:edda6a7238ec 63 // miso: PA_6 (D12)
Wolfgang Betz 34:edda6a7238ec 64 // sclk: PB_3 (D3) or
Wolfgang Betz 34:edda6a7238ec 65 // PA_5 (D13) (only in case you unmount R4 & mount R7,
Wolfgang Betz 34:edda6a7238ec 66 // (note: in this case you may not use LED1 on some platforms)
Wolfgang Betz 34:edda6a7238ec 67 // bits: 8-bit
Wolfgang Betz 34:edda6a7238ec 68 // mode: 0
Wolfgang Betz 34:edda6a7238ec 69 // ordr: MSB
Wolfgang Betz 34:edda6a7238ec 70 // freq: max 10MHz
Wolfgang Betz 34:edda6a7238ec 71 InterruptIn _irq; // PC_7 (D9) (falling)
Wolfgang Betz 34:edda6a7238ec 72 DigitalOut _chip_select; // PB_6 (D10) ('1' == chip unselected)
Wolfgang Betz 34:edda6a7238ec 73 DigitalOut _shut_down; // PA_10 (D2) ('1' == shut_down)
Wolfgang Betz 34:edda6a7238ec 74 DigitalOut _led; // PB_4 (D5) (optional)
Wolfgang Betz 34:edda6a7238ec 75
Wolfgang Betz 34:edda6a7238ec 76 Callback<void(int)> _current_irq_callback;
Wolfgang Betz 34:edda6a7238ec 77 Timeout _rx_receiving_timeout;
Wolfgang Betz 34:edda6a7238ec 78
Wolfgang Betz 34:edda6a7238ec 79 void rx_timeout_handler(void) {
Wolfgang Betz 34:edda6a7238ec 80 set_ready_state();
Wolfgang Betz 34:edda6a7238ec 81 cmd_strobe(SPIRIT1_STROBE_RX);
Wolfgang Betz 34:edda6a7238ec 82 #ifdef DEBUG_IRQ
Wolfgang Betz 34:edda6a7238ec 83 debug("\n\r%s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 34:edda6a7238ec 84 #endif
Wolfgang Betz 34:edda6a7238ec 85 }
Wolfgang Betz 34:edda6a7238ec 86
Wolfgang Betz 34:edda6a7238ec 87 void start_rx_timeout(void) {
Wolfgang Betz 37:bc043030b55a 88 _rx_receiving_timeout.attach_us(Callback<void()>(this, &SimpleSpirit1::rx_timeout_handler), 100 * 1000); // 100ms
Wolfgang Betz 34:edda6a7238ec 89 }
Wolfgang Betz 34:edda6a7238ec 90
Wolfgang Betz 34:edda6a7238ec 91 void stop_rx_timeout(void) {
Wolfgang Betz 34:edda6a7238ec 92 _rx_receiving_timeout.detach();
Wolfgang Betz 34:edda6a7238ec 93 }
Wolfgang Betz 34:edda6a7238ec 94
Wolfgang Betz 34:edda6a7238ec 95 /** Static Variables from Cube Implementation **/
Wolfgang Betz 34:edda6a7238ec 96 /*
Wolfgang Betz 34:edda6a7238ec 97 * The buffers which hold incoming data.
Wolfgang Betz 34:edda6a7238ec 98 * The +1 because of the first byte,
Wolfgang Betz 34:edda6a7238ec 99 * which will contain the length of the packet.
Wolfgang Betz 34:edda6a7238ec 100 */
Wolfgang Betz 34:edda6a7238ec 101 volatile uint16_t spirit_tx_len;
Wolfgang Betz 34:edda6a7238ec 102 volatile bool _spirit_tx_started;
Wolfgang Betz 34:edda6a7238ec 103 volatile uint16_t spirit_rx_len;
Wolfgang Betz 34:edda6a7238ec 104 volatile uint16_t _spirit_rx_pos;
Wolfgang Betz 34:edda6a7238ec 105 volatile bool _spirit_rx_err;
Wolfgang Betz 34:edda6a7238ec 106 uint8_t spirit_rx_buf[MAX_PACKET_LEN];
Wolfgang Betz 34:edda6a7238ec 107 volatile bool _is_receiving;
Wolfgang Betz 34:edda6a7238ec 108
Wolfgang Betz 34:edda6a7238ec 109 /** Status Variables from Cube Implementation **/
Wolfgang Betz 34:edda6a7238ec 110 unsigned int spirit_on;
Wolfgang Betz 34:edda6a7238ec 111 uint8_t last_rssi; //MGR
Wolfgang Betz 34:edda6a7238ec 112 uint8_t last_sqi; //MGR
Wolfgang Betz 34:edda6a7238ec 113
Wolfgang Betz 34:edda6a7238ec 114 /** Low Level Instance Variables **/
Wolfgang Betz 34:edda6a7238ec 115 unsigned int _nr_of_irq_disables;
Wolfgang Betz 34:edda6a7238ec 116
Wolfgang Betz 34:edda6a7238ec 117 /** Low Level Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 118 void disable_spirit_irq(void) {
Wolfgang Betz 34:edda6a7238ec 119 _irq.disable_irq();
Wolfgang Betz 34:edda6a7238ec 120 _nr_of_irq_disables++;
Wolfgang Betz 34:edda6a7238ec 121 #ifndef NDEBUG
Wolfgang Betz 34:edda6a7238ec 122 debug_if(_nr_of_irq_disables == 0, "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 34:edda6a7238ec 123 #endif
Wolfgang Betz 34:edda6a7238ec 124 }
Wolfgang Betz 34:edda6a7238ec 125
Wolfgang Betz 34:edda6a7238ec 126 void enable_spirit_irq(void) {
Wolfgang Betz 34:edda6a7238ec 127 #ifndef NDEBUG
Wolfgang Betz 34:edda6a7238ec 128 debug_if(_nr_of_irq_disables == 0, "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__);
Wolfgang Betz 34:edda6a7238ec 129 #endif
Wolfgang Betz 34:edda6a7238ec 130 if(--_nr_of_irq_disables == 0)
Wolfgang Betz 34:edda6a7238ec 131 _irq.enable_irq();
Wolfgang Betz 34:edda6a7238ec 132 }
Wolfgang Betz 34:edda6a7238ec 133
Wolfgang Betz 34:edda6a7238ec 134 void chip_select() { _chip_select = 0; }
Wolfgang Betz 34:edda6a7238ec 135 void chip_unselect() { _chip_select = 1; }
Wolfgang Betz 34:edda6a7238ec 136
Wolfgang Betz 34:edda6a7238ec 137 void enter_shutdown() {
Wolfgang Betz 34:edda6a7238ec 138 _shut_down = 1;
Wolfgang Betz 34:edda6a7238ec 139 wait_ms(5); // wait 5 milliseconds (to allow Spirit1 to shut down)
Wolfgang Betz 34:edda6a7238ec 140 }
Wolfgang Betz 34:edda6a7238ec 141
Wolfgang Betz 34:edda6a7238ec 142 void exit_shutdown() {
Wolfgang Betz 34:edda6a7238ec 143 _shut_down = 0;
Wolfgang Betz 34:edda6a7238ec 144 wait_ms(10); // wait 10 milliseconds (to allow Spirit1 a proper boot-up sequence)
Wolfgang Betz 34:edda6a7238ec 145 }
Wolfgang Betz 34:edda6a7238ec 146
Wolfgang Betz 34:edda6a7238ec 147 void cs_to_sclk_delay(void) {
Wolfgang Betz 34:edda6a7238ec 148 wait_us(1); // heuristic value
Wolfgang Betz 34:edda6a7238ec 149 }
Wolfgang Betz 34:edda6a7238ec 150
Wolfgang Betz 34:edda6a7238ec 151 /**
Wolfgang Betz 34:edda6a7238ec 152 * @brief Write and read a buffer to/from the SPI peripheral device at the same time
Wolfgang Betz 34:edda6a7238ec 153 * in 8-bit data mode using synchronous SPI communication.
Wolfgang Betz 34:edda6a7238ec 154 * @param[in] pBufferToWrite pointer to the buffer of data to send.
Wolfgang Betz 34:edda6a7238ec 155 * @param[out] pBufferToRead pointer to the buffer to read data into.
Wolfgang Betz 34:edda6a7238ec 156 * @param[in] NumBytes number of bytes to read and write.
Wolfgang Betz 34:edda6a7238ec 157 * @retval 0 if ok.
Wolfgang Betz 34:edda6a7238ec 158 * @retval -1 if data format error.
Wolfgang Betz 34:edda6a7238ec 159 * @note When using the SPI in Interrupt-mode, remember to disable interrupts
Wolfgang Betz 34:edda6a7238ec 160 * before calling this function and to enable them again after.
Wolfgang Betz 34:edda6a7238ec 161 */
Wolfgang Betz 34:edda6a7238ec 162 void spi_write_read(uint8_t* pBufferToWrite, uint8_t* pBufferToRead, uint16_t NumBytes)
Wolfgang Betz 34:edda6a7238ec 163 {
Wolfgang Betz 34:edda6a7238ec 164 /* Read and write data at the same time. */
Wolfgang Betz 34:edda6a7238ec 165 for (int i = 0; i < NumBytes; i++) {
Wolfgang Betz 34:edda6a7238ec 166 pBufferToRead[i] = _spi.write(pBufferToWrite[i]);
Wolfgang Betz 34:edda6a7238ec 167 }
Wolfgang Betz 34:edda6a7238ec 168 }
Wolfgang Betz 34:edda6a7238ec 169
Wolfgang Betz 34:edda6a7238ec 170 /** Radio Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 171 void radio_set_xtal_freq(uint32_t freq) {
Wolfgang Betz 34:edda6a7238ec 172 SpiritRadioSetXtalFrequency(freq);
Wolfgang Betz 34:edda6a7238ec 173 }
Wolfgang Betz 34:edda6a7238ec 174
Wolfgang Betz 34:edda6a7238ec 175 void radio_set_pa_level_dbm(uint8_t cIndex, float fPowerdBm) {
Wolfgang Betz 34:edda6a7238ec 176 SpiritRadioSetPALeveldBm(cIndex, fPowerdBm);
Wolfgang Betz 34:edda6a7238ec 177 }
Wolfgang Betz 34:edda6a7238ec 178
Wolfgang Betz 34:edda6a7238ec 179 void radio_set_pa_level_max_index(uint8_t cIndex) {
Wolfgang Betz 34:edda6a7238ec 180 SpiritRadioSetPALevelMaxIndex(cIndex);
Wolfgang Betz 34:edda6a7238ec 181 }
Wolfgang Betz 34:edda6a7238ec 182
Wolfgang Betz 34:edda6a7238ec 183 uint8_t radio_init(SRadioInit *init_struct) {
Wolfgang Betz 34:edda6a7238ec 184 return SpiritRadioInit(init_struct);
Wolfgang Betz 34:edda6a7238ec 185 }
Wolfgang Betz 34:edda6a7238ec 186
Wolfgang Betz 34:edda6a7238ec 187 void radio_persistent_rx(SpiritFunctionalState xNewState) {
Wolfgang Betz 34:edda6a7238ec 188 SpiritRadioPersistenRx(xNewState);
Wolfgang Betz 34:edda6a7238ec 189 }
Wolfgang Betz 34:edda6a7238ec 190
Wolfgang Betz 34:edda6a7238ec 191 void radio_afc_freeze_on_sync(SpiritFunctionalState xNewState) {
Wolfgang Betz 34:edda6a7238ec 192 SpiritRadioAFCFreezeOnSync(xNewState);
Wolfgang Betz 34:edda6a7238ec 193 }
Wolfgang Betz 34:edda6a7238ec 194
Wolfgang Betz 34:edda6a7238ec 195 /** Packet System Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 196 void pkt_basic_init(PktBasicInit* pxPktBasicInit) {
Wolfgang Betz 34:edda6a7238ec 197 SpiritPktBasicInit(pxPktBasicInit);
Wolfgang Betz 34:edda6a7238ec 198 }
Wolfgang Betz 34:edda6a7238ec 199
Wolfgang Betz 34:edda6a7238ec 200 void pkt_basic_set_payload_length(uint16_t nPayloadLength) {
Wolfgang Betz 34:edda6a7238ec 201 SpiritPktBasicSetPayloadLength(nPayloadLength);
Wolfgang Betz 34:edda6a7238ec 202 }
Wolfgang Betz 34:edda6a7238ec 203
Wolfgang Betz 34:edda6a7238ec 204 uint16_t pkt_basic_get_received_pkt_length(void) {
Wolfgang Betz 34:edda6a7238ec 205 return SpiritPktBasicGetReceivedPktLength();
Wolfgang Betz 34:edda6a7238ec 206 }
Wolfgang Betz 34:edda6a7238ec 207
Wolfgang Betz 34:edda6a7238ec 208 /** IRQ Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 209 void irq_de_init(SpiritIrqs* pxIrqInit) {
Wolfgang Betz 34:edda6a7238ec 210 SpiritIrqDeInit(pxIrqInit);
Wolfgang Betz 34:edda6a7238ec 211 }
Wolfgang Betz 34:edda6a7238ec 212
Wolfgang Betz 34:edda6a7238ec 213 void irq_clear_status(void) {
Wolfgang Betz 34:edda6a7238ec 214 SpiritIrqClearStatus();
Wolfgang Betz 34:edda6a7238ec 215 }
Wolfgang Betz 34:edda6a7238ec 216
Wolfgang Betz 34:edda6a7238ec 217 void irq_set_status(IrqList xIrq, SpiritFunctionalState xNewState) {
Wolfgang Betz 34:edda6a7238ec 218 SpiritIrq(xIrq, xNewState);
Wolfgang Betz 34:edda6a7238ec 219 }
Wolfgang Betz 34:edda6a7238ec 220
Wolfgang Betz 34:edda6a7238ec 221 void irq_get_status(SpiritIrqs* pxIrqStatus) {
Wolfgang Betz 34:edda6a7238ec 222 SpiritIrqGetStatus(pxIrqStatus);
Wolfgang Betz 34:edda6a7238ec 223 }
Wolfgang Betz 34:edda6a7238ec 224
Wolfgang Betz 34:edda6a7238ec 225 /** Management Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 226 void mgmt_set_freq_base(uint32_t freq) {
Wolfgang Betz 34:edda6a7238ec 227 SpiritManagementSetFrequencyBase(freq);
Wolfgang Betz 34:edda6a7238ec 228 }
Wolfgang Betz 34:edda6a7238ec 229
Wolfgang Betz 34:edda6a7238ec 230 void mgmt_refresh_status(void) {
Wolfgang Betz 34:edda6a7238ec 231 SpiritRefreshStatus();
Wolfgang Betz 34:edda6a7238ec 232 }
Wolfgang Betz 34:edda6a7238ec 233
Wolfgang Betz 34:edda6a7238ec 234 /** Spirit GPIO Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 235 void spirit_gpio_init(SGpioInit* pxGpioInitStruct) {
Wolfgang Betz 34:edda6a7238ec 236 SpiritGpioInit(pxGpioInitStruct);
Wolfgang Betz 34:edda6a7238ec 237 }
Wolfgang Betz 34:edda6a7238ec 238
Wolfgang Betz 34:edda6a7238ec 239 /** Qi Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 240 void qi_set_sqi_threshold(SqiThreshold xSqiThr) {
Wolfgang Betz 34:edda6a7238ec 241 SpiritQiSetSqiThreshold(xSqiThr);
Wolfgang Betz 34:edda6a7238ec 242 }
Wolfgang Betz 34:edda6a7238ec 243
Wolfgang Betz 34:edda6a7238ec 244 void qi_sqi_check(SpiritFunctionalState xNewState) {
Wolfgang Betz 34:edda6a7238ec 245 SpiritQiSqiCheck(xNewState);
Wolfgang Betz 34:edda6a7238ec 246 }
Wolfgang Betz 34:edda6a7238ec 247
Wolfgang Betz 34:edda6a7238ec 248 void qi_set_rssi_threshold_dbm(int nDbmValue) {
Wolfgang Betz 34:edda6a7238ec 249 SpiritQiSetRssiThresholddBm(nDbmValue);
Wolfgang Betz 34:edda6a7238ec 250 }
Wolfgang Betz 34:edda6a7238ec 251
Wolfgang Betz 34:edda6a7238ec 252 float qi_get_rssi_dbm() {
Wolfgang Betz 34:edda6a7238ec 253 last_rssi = qi_get_rssi();
Wolfgang Betz 34:edda6a7238ec 254 return get_last_rssi_dbm();
Wolfgang Betz 34:edda6a7238ec 255 }
Wolfgang Betz 34:edda6a7238ec 256
Wolfgang Betz 34:edda6a7238ec 257 uint8_t qi_get_rssi() {
Wolfgang Betz 34:edda6a7238ec 258 return SpiritQiGetRssi();
Wolfgang Betz 34:edda6a7238ec 259 }
Wolfgang Betz 34:edda6a7238ec 260
Wolfgang Betz 34:edda6a7238ec 261 uint8_t qi_get_sqi() {
Wolfgang Betz 34:edda6a7238ec 262 return SpiritQiGetSqi();
Wolfgang Betz 34:edda6a7238ec 263 }
Wolfgang Betz 34:edda6a7238ec 264
Wolfgang Betz 34:edda6a7238ec 265 /** Timer Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 266 void timer_set_rx_timeout_stop_condition(RxTimeoutStopCondition xStopCondition) {
Wolfgang Betz 34:edda6a7238ec 267 SpiritTimerSetRxTimeoutStopCondition(xStopCondition);
Wolfgang Betz 34:edda6a7238ec 268 }
Wolfgang Betz 34:edda6a7238ec 269
Wolfgang Betz 34:edda6a7238ec 270 void timer_set_rx_timeout_counter(uint8_t cCounter) {
Wolfgang Betz 34:edda6a7238ec 271 SpiritTimerSetRxTimeoutCounter(cCounter);
Wolfgang Betz 34:edda6a7238ec 272 }
Wolfgang Betz 34:edda6a7238ec 273
Wolfgang Betz 34:edda6a7238ec 274 void timer_set_infinite_rx_timeout(void) {
Wolfgang Betz 34:edda6a7238ec 275 timer_set_rx_timeout_counter(0);
Wolfgang Betz 34:edda6a7238ec 276 }
Wolfgang Betz 34:edda6a7238ec 277
Wolfgang Betz 34:edda6a7238ec 278 /** CSMA/CA Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 279 void csma_ca_state(SpiritFunctionalState xNewState) {
Wolfgang Betz 34:edda6a7238ec 280 SpiritCsma(xNewState);
Wolfgang Betz 34:edda6a7238ec 281 }
Wolfgang Betz 34:edda6a7238ec 282
Wolfgang Betz 34:edda6a7238ec 283 void csma_ca_init(CsmaInit* pxCsmaInit) {
Wolfgang Betz 34:edda6a7238ec 284 csma_ca_state(S_DISABLE); // Disabled at init
Wolfgang Betz 34:edda6a7238ec 285 SpiritCsmaInit(pxCsmaInit);
Wolfgang Betz 34:edda6a7238ec 286 SpiritCsmaSeedReloadMode(S_DISABLE); // always disable seed reload
Wolfgang Betz 34:edda6a7238ec 287 }
Wolfgang Betz 34:edda6a7238ec 288
Wolfgang Betz 34:edda6a7238ec 289 /** Command Instance Methods**/
Wolfgang Betz 34:edda6a7238ec 290 void cmd_strobe(uint8_t cmd) {
Wolfgang Betz 34:edda6a7238ec 291 SpiritCmdStrobeCommand((SpiritCmd)cmd);
Wolfgang Betz 34:edda6a7238ec 292 }
Wolfgang Betz 34:edda6a7238ec 293
Wolfgang Betz 34:edda6a7238ec 294 void cmd_strobe_flush_rx_fifo() {
Wolfgang Betz 34:edda6a7238ec 295 SpiritCmdStrobeCommand(CMD_FLUSHRXFIFO);
Wolfgang Betz 34:edda6a7238ec 296 }
Wolfgang Betz 34:edda6a7238ec 297
Wolfgang Betz 34:edda6a7238ec 298 /** SPI Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 299 StatusBytes spi_write_linear_fifo(uint8_t cNbBytes, uint8_t* pcBuffer) {
Wolfgang Betz 34:edda6a7238ec 300 return SdkEvalSpiWriteFifo(cNbBytes, pcBuffer);
Wolfgang Betz 34:edda6a7238ec 301 }
Wolfgang Betz 34:edda6a7238ec 302
Wolfgang Betz 34:edda6a7238ec 303 StatusBytes spi_read_linear_fifo(uint8_t cNbBytes, uint8_t* pcBuffer) {
Wolfgang Betz 34:edda6a7238ec 304 return SdkEvalSpiReadFifo(cNbBytes, pcBuffer);
Wolfgang Betz 34:edda6a7238ec 305 }
Wolfgang Betz 34:edda6a7238ec 306
Wolfgang Betz 34:edda6a7238ec 307 /** Linear FIFO Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 308 uint8_t linear_fifo_read_num_elements_rx_fifo(void) {
Wolfgang Betz 34:edda6a7238ec 309 return SpiritLinearFifoReadNumElementsRxFifo();
Wolfgang Betz 34:edda6a7238ec 310 }
Wolfgang Betz 34:edda6a7238ec 311
Wolfgang Betz 34:edda6a7238ec 312 uint8_t linear_fifo_read_num_elements_tx_fifo(void) {
Wolfgang Betz 34:edda6a7238ec 313 return SpiritLinearFifoReadNumElementsTxFifo();
Wolfgang Betz 34:edda6a7238ec 314 }
Wolfgang Betz 34:edda6a7238ec 315
Wolfgang Betz 34:edda6a7238ec 316 void linear_fifo_set_almost_full_thr_rx(uint8_t cThrRxFifo) {
Wolfgang Betz 34:edda6a7238ec 317 SpiritLinearFifoSetAlmostFullThresholdRx(cThrRxFifo);
Wolfgang Betz 34:edda6a7238ec 318 }
Wolfgang Betz 34:edda6a7238ec 319
Wolfgang Betz 34:edda6a7238ec 320 /** Calibration Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 321 void calibration_rco(SpiritFunctionalState xNewState) {
Wolfgang Betz 34:edda6a7238ec 322 SpiritCalibrationRco(xNewState);
Wolfgang Betz 34:edda6a7238ec 323 }
Wolfgang Betz 34:edda6a7238ec 324
Wolfgang Betz 34:edda6a7238ec 325 /** Internal Spirit Methods */
Wolfgang Betz 34:edda6a7238ec 326 void set_ready_state(void);
Wolfgang Betz 34:edda6a7238ec 327 uint8_t refresh_state(void);
Wolfgang Betz 34:edda6a7238ec 328
Wolfgang Betz 34:edda6a7238ec 329 /** Friend Functions **/
Wolfgang Betz 34:edda6a7238ec 330 friend StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 34:edda6a7238ec 331 friend StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 34:edda6a7238ec 332 friend StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode);
Wolfgang Betz 34:edda6a7238ec 333 friend StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 34:edda6a7238ec 334 friend StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 34:edda6a7238ec 335
Wolfgang Betz 34:edda6a7238ec 336 /** Sdk Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 337 StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 34:edda6a7238ec 338 StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 34:edda6a7238ec 339 StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode);
Wolfgang Betz 34:edda6a7238ec 340 StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 34:edda6a7238ec 341 StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
Wolfgang Betz 34:edda6a7238ec 342
Wolfgang Betz 34:edda6a7238ec 343 /** Helper Instance Methods **/
Wolfgang Betz 34:edda6a7238ec 344 void chip_sync_select() {
Wolfgang Betz 34:edda6a7238ec 345 disable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 346 chip_select();
Wolfgang Betz 34:edda6a7238ec 347 cs_to_sclk_delay();
Wolfgang Betz 34:edda6a7238ec 348 }
Wolfgang Betz 34:edda6a7238ec 349
Wolfgang Betz 34:edda6a7238ec 350 void chip_sync_unselect() {
Wolfgang Betz 34:edda6a7238ec 351 chip_unselect();
Wolfgang Betz 34:edda6a7238ec 352 enable_spirit_irq();
Wolfgang Betz 34:edda6a7238ec 353 }
Wolfgang Betz 34:edda6a7238ec 354
Wolfgang Betz 34:edda6a7238ec 355 /** Init Instance Method **/
Wolfgang Betz 34:edda6a7238ec 356 void init();
Wolfgang Betz 34:edda6a7238ec 357
Wolfgang Betz 34:edda6a7238ec 358 /** Spirit Irq Callback */
Wolfgang Betz 34:edda6a7238ec 359 void IrqHandler();
Wolfgang Betz 34:edda6a7238ec 360
Wolfgang Betz 34:edda6a7238ec 361 /** Constructor **/
Wolfgang Betz 34:edda6a7238ec 362 SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
Wolfgang Betz 34:edda6a7238ec 363 PinName irq, PinName cs, PinName sdn,
Wolfgang Betz 34:edda6a7238ec 364 PinName led);
Wolfgang Betz 34:edda6a7238ec 365
Wolfgang Betz 34:edda6a7238ec 366 /** Destructor **/
Wolfgang Betz 34:edda6a7238ec 367 ~SimpleSpirit1(void); // should never be called!
Wolfgang Betz 34:edda6a7238ec 368
Wolfgang Betz 34:edda6a7238ec 369 public:
Wolfgang Betz 34:edda6a7238ec 370 enum {
Wolfgang Betz 34:edda6a7238ec 371 RX_DONE,
Wolfgang Betz 34:edda6a7238ec 372 TX_DONE,
Wolfgang Betz 34:edda6a7238ec 373 TX_ERR
Wolfgang Betz 34:edda6a7238ec 374 };
Wolfgang Betz 34:edda6a7238ec 375
Wolfgang Betz 34:edda6a7238ec 376 static SimpleSpirit1& CreateInstance(PinName mosi, PinName miso, PinName sclk,
Wolfgang Betz 34:edda6a7238ec 377 PinName irq, PinName cs, PinName sdn,
Wolfgang Betz 34:edda6a7238ec 378 PinName led = NC) {
Wolfgang Betz 34:edda6a7238ec 379
Wolfgang Betz 34:edda6a7238ec 380 if(_singleton == NULL) {
Wolfgang Betz 34:edda6a7238ec 381 _singleton = new SimpleSpirit1(mosi, miso, sclk,
Wolfgang Betz 34:edda6a7238ec 382 irq, cs, sdn, led);
Wolfgang Betz 34:edda6a7238ec 383 _singleton->init();
Wolfgang Betz 34:edda6a7238ec 384 } else {
Wolfgang Betz 34:edda6a7238ec 385 error("SimpleSpirit1 singleton already created!\n");
Wolfgang Betz 34:edda6a7238ec 386 }
Wolfgang Betz 34:edda6a7238ec 387
Wolfgang Betz 34:edda6a7238ec 388 return *_singleton;
Wolfgang Betz 34:edda6a7238ec 389 }
Wolfgang Betz 34:edda6a7238ec 390
Wolfgang Betz 34:edda6a7238ec 391 static SimpleSpirit1& Instance() {
Wolfgang Betz 34:edda6a7238ec 392 if(_singleton == NULL) {
Wolfgang Betz 34:edda6a7238ec 393 error("SimpleSpirit1 must be created before used!\n");
Wolfgang Betz 34:edda6a7238ec 394 }
Wolfgang Betz 34:edda6a7238ec 395
Wolfgang Betz 34:edda6a7238ec 396 return *_singleton;
Wolfgang Betz 34:edda6a7238ec 397 }
Wolfgang Betz 34:edda6a7238ec 398
Wolfgang Betz 34:edda6a7238ec 399 /** Attach a function to be called by the Spirit Irq handler when packet has arrived
Wolfgang Betz 34:edda6a7238ec 400 *
Wolfgang Betz 34:edda6a7238ec 401 * @param func A void() callback, or 0 to set as none
Wolfgang Betz 34:edda6a7238ec 402 *
Wolfgang Betz 34:edda6a7238ec 403 * @note Function 'func' will be executed in interrupt context!
Wolfgang Betz 34:edda6a7238ec 404 */
Wolfgang Betz 34:edda6a7238ec 405 void attach_irq_callback(Callback<void(int)> func) {
Wolfgang Betz 34:edda6a7238ec 406 _current_irq_callback = func;
Wolfgang Betz 34:edda6a7238ec 407 }
Wolfgang Betz 34:edda6a7238ec 408
Wolfgang Betz 34:edda6a7238ec 409 /** Switch Radio On/Off **/
Wolfgang Betz 34:edda6a7238ec 410 int on(void);
Wolfgang Betz 34:edda6a7238ec 411 int off(void);
Wolfgang Betz 34:edda6a7238ec 412
Wolfgang Betz 34:edda6a7238ec 413 /** Set Channel **/
Wolfgang Betz 34:edda6a7238ec 414 void set_channel(uint8_t channel) {
Wolfgang Betz 34:edda6a7238ec 415 SpiritRadioSetChannel(channel);
Wolfgang Betz 34:edda6a7238ec 416 }
Wolfgang Betz 34:edda6a7238ec 417
Wolfgang Betz 34:edda6a7238ec 418 /** Send a Buffer **/
Wolfgang Betz 64:28ef790e4ef7 419 int send(const void *payload, unsigned int payload_len, bool use_csma_ca = true);
Wolfgang Betz 34:edda6a7238ec 420
Wolfgang Betz 34:edda6a7238ec 421 /** Read into Buffer **/
Wolfgang Betz 34:edda6a7238ec 422 int read(void *buf, unsigned int bufsize);
Wolfgang Betz 34:edda6a7238ec 423
Wolfgang Betz 34:edda6a7238ec 424 /** Perform a Clear-Channel Assessment (CCA) to find out if there is
Wolfgang Betz 34:edda6a7238ec 425 a packet in the air or not.
Wolfgang Betz 34:edda6a7238ec 426 Returns 1 if packet has been seen.
Wolfgang Betz 34:edda6a7238ec 427 */
Wolfgang Betz 34:edda6a7238ec 428 int channel_clear(void);
Wolfgang Betz 34:edda6a7238ec 429
Wolfgang Betz 34:edda6a7238ec 430 /** Check if the radio driver has just received a packet **/
Wolfgang Betz 34:edda6a7238ec 431 int get_pending_packet(void);
Wolfgang Betz 34:edda6a7238ec 432
Wolfgang Betz 34:edda6a7238ec 433 /** Is radio currently receiving **/
Wolfgang Betz 34:edda6a7238ec 434 bool is_receiving(void) {
Wolfgang Betz 34:edda6a7238ec 435 return _is_receiving;
Wolfgang Betz 34:edda6a7238ec 436 }
Wolfgang Betz 34:edda6a7238ec 437
Wolfgang Betz 34:edda6a7238ec 438 /** Get latest value of RSSI (in dBm) **/
Wolfgang Betz 34:edda6a7238ec 439 float get_last_rssi_dbm(void) {
Wolfgang Betz 34:edda6a7238ec 440 get_last_rssi_raw();
Wolfgang Betz 34:edda6a7238ec 441 return (-120.0+((float)(last_rssi-20))/2);
Wolfgang Betz 34:edda6a7238ec 442 }
Wolfgang Betz 34:edda6a7238ec 443
Wolfgang Betz 34:edda6a7238ec 444 /** Get latest value of RSSI (as Spirit1 raw value) **/
Wolfgang Betz 34:edda6a7238ec 445 uint8_t get_last_rssi_raw(void) {
Wolfgang Betz 34:edda6a7238ec 446 if(last_rssi == 0) {
Wolfgang Betz 34:edda6a7238ec 447 last_rssi = qi_get_rssi();
Wolfgang Betz 34:edda6a7238ec 448 }
Wolfgang Betz 34:edda6a7238ec 449 return last_rssi;
Wolfgang Betz 34:edda6a7238ec 450 }
Wolfgang Betz 34:edda6a7238ec 451
Wolfgang Betz 34:edda6a7238ec 452 /** Get latest value of LQI (scaled to 8-bit) **/
Wolfgang Betz 34:edda6a7238ec 453 uint8_t get_last_sqi(void) {
Wolfgang Betz 34:edda6a7238ec 454 const uint8_t max_sqi = 8 * ((SYNC_LENGTH>>1)+1);
Wolfgang Betz 34:edda6a7238ec 455 if(last_sqi == 0) {
Wolfgang Betz 34:edda6a7238ec 456 last_sqi = qi_get_sqi();
Wolfgang Betz 34:edda6a7238ec 457 }
Wolfgang Betz 34:edda6a7238ec 458 if(last_sqi > max_sqi) last_sqi = max_sqi;
Wolfgang Betz 34:edda6a7238ec 459
Wolfgang Betz 34:edda6a7238ec 460 return (last_sqi * 255 / max_sqi);
Wolfgang Betz 34:edda6a7238ec 461 }
Wolfgang Betz 34:edda6a7238ec 462
Wolfgang Betz 34:edda6a7238ec 463 /** Reset Board **/
Wolfgang Betz 34:edda6a7238ec 464 void reset_board() {
Wolfgang Betz 34:edda6a7238ec 465 init();
Wolfgang Betz 34:edda6a7238ec 466 }
Wolfgang Betz 34:edda6a7238ec 467 };