센서보드 RF IRQ 테스트 중 and bug fix?
Fork of EV-COG-AD3029LZ by
stm-spirit1-rf-driver/SimpleSpirit1.h@64:28ef790e4ef7, 2017-07-03 (annotated)
- 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?
User | Revision | Line number | New 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 | }; |