Added support for the WNC M14A2A Cellular LTE Data Module.

Dependencies:   WNC14A2AInterface

Easy Connect

Easily add all supported connectivity methods to your mbed OS project

This project is derived from https://developer.mbed.org/teams/sandbox/code/simple-mbed-client-example/file/dd6231df71bb/easy-connect.lib. It give user the ability to switch between connectivity methods and includes support for the WNC14A2A Data Module. The `NetworkInterface` API makes this easy, but you still need a mechanism for the user to select the connection method, The selection is made by modifying the `mbed_app.json` file and using `easy_connect()` from your application.

Specifying connectivity method

To add support for the WNC14A2A, add the following to your ``mbed_app.json`` file:

mbed_app.json

{
    "config": {
        "network-interface":{
            "help": "options are ETHERNET,WIFI_ESP8266,WIFI_ODIN,MESH_LOWPAN_ND,MESH_THREAD,WNC14A2A",
            "value": "WNC14A2A"
        }
    },
}

After you choose `WNC14A2A` you'll also need to indicate if you want debug output or not by Enabling (true) or Disabling (false) WNC_DEBUG.

If WNC_DEBUG is enabled, there are 3 different levels of debug output (selected via bit settings). These debug levels are set using the following values:

ValueDescription
1Basic WNC driver debug output
2Comprehensive WNC driver debug output
4Network Layer debug output

You can have any combination of these three bit values for a total value of 0 – 7.

WNC Debug Settings

    "config": {
        "WNC_DEBUG": {
            "value": false
        },
        "WNC_DEBUG_SETTING": {
            "value": 4
        },
    }

Using Easy Connect from your application

Easy Connect has just one function which will either return a `NetworkInterface`-pointer or `NULL`:

Sample Code

#include "easy-connect.h"

int main(int, char**) {
    NetworkInterface* network = easy_connect(true); /* has 1 argument, enable_logging (pass in true to log to serial port) */
    if (!network) {
        printf("Connecting to the network failed... See serial output.\r\n");
        return 1;
    }
 
    // Rest of your program
}

Tested on

  • K64F with Ethernet.
  • AT&T Cellular IoT Starter Kit with WNC M14A2A Cellular Data Module

The WNCInterface class currently supports the following version(s):

  • MPSS: M14A2A_v11.50.164451 APSS: M14A2A_v11.53.164451

License

This library is released under the Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License and may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Committer:
group-Avnet
Date:
Wed Apr 19 01:08:11 2017 +0000
Revision:
0:478cfd88041f
Initial commit

Who changed what in which revision?

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