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 "SimpleSpirit1.h"
group-Avnet 0:478cfd88041f 3 #include "radio_spi.h"
group-Avnet 0:478cfd88041f 4
group-Avnet 0:478cfd88041f 5 #define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_3)
group-Avnet 0:478cfd88041f 6
group-Avnet 0:478cfd88041f 7 static uint16_t last_state;
group-Avnet 0:478cfd88041f 8 #define SPIRIT1_STATUS() ((last_state = (uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS)
group-Avnet 0:478cfd88041f 9
group-Avnet 0:478cfd88041f 10 #define XO_ON (0x1)
group-Avnet 0:478cfd88041f 11
group-Avnet 0:478cfd88041f 12 #define BUSYWAIT_UNTIL(cond, millisecs) \
group-Avnet 0:478cfd88041f 13 do { \
group-Avnet 0:478cfd88041f 14 uint32_t start = us_ticker_read(); \
group-Avnet 0:478cfd88041f 15 while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U)); \
group-Avnet 0:478cfd88041f 16 } while(0)
group-Avnet 0:478cfd88041f 17
group-Avnet 0:478cfd88041f 18 #define st_lib_spirit_irqs SpiritIrqs
group-Avnet 0:478cfd88041f 19
group-Avnet 0:478cfd88041f 20 #define STATE_TIMEOUT (100)
group-Avnet 0:478cfd88041f 21
group-Avnet 0:478cfd88041f 22 // betzw: switching force & back from standby is on some devices quite unstable
group-Avnet 0:478cfd88041f 23 #define USE_STANDBY_STATE
group-Avnet 0:478cfd88041f 24
group-Avnet 0:478cfd88041f 25 /*** Class Implementation ***/
group-Avnet 0:478cfd88041f 26 /** Static Class Variables **/
group-Avnet 0:478cfd88041f 27 SimpleSpirit1 *SimpleSpirit1::_singleton = NULL;
group-Avnet 0:478cfd88041f 28
group-Avnet 0:478cfd88041f 29 /** Constructor **/
group-Avnet 0:478cfd88041f 30 SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
group-Avnet 0:478cfd88041f 31 PinName irq, PinName cs, PinName sdn,
group-Avnet 0:478cfd88041f 32 PinName led) :
group-Avnet 0:478cfd88041f 33 _spi(mosi, miso, sclk),
group-Avnet 0:478cfd88041f 34 _irq(irq),
group-Avnet 0:478cfd88041f 35 _chip_select(cs),
group-Avnet 0:478cfd88041f 36 _shut_down(sdn),
group-Avnet 0:478cfd88041f 37 _led(led),
group-Avnet 0:478cfd88041f 38 _current_irq_callback(),
group-Avnet 0:478cfd88041f 39 _rx_receiving_timeout()
group-Avnet 0:478cfd88041f 40 {
group-Avnet 0:478cfd88041f 41 }
group-Avnet 0:478cfd88041f 42
group-Avnet 0:478cfd88041f 43 /** Init Function **/
group-Avnet 0:478cfd88041f 44 void SimpleSpirit1::init() {
group-Avnet 0:478cfd88041f 45 /* reset irq disable counter and irq callback & disable irq */
group-Avnet 0:478cfd88041f 46 _nr_of_irq_disables = 0;
group-Avnet 0:478cfd88041f 47 disable_spirit_irq();
group-Avnet 0:478cfd88041f 48
group-Avnet 0:478cfd88041f 49 /* unselect chip */
group-Avnet 0:478cfd88041f 50 chip_unselect();
group-Avnet 0:478cfd88041f 51
group-Avnet 0:478cfd88041f 52 /* configure spi */
group-Avnet 0:478cfd88041f 53 _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
group-Avnet 0:478cfd88041f 54 _spi.frequency(1000000); // 1MHz // betzw: heuristic value // betzw - NOTE: high frequencies lead to instability of Spirit1
group-Avnet 0:478cfd88041f 55
group-Avnet 0:478cfd88041f 56 /* install irq handler */
group-Avnet 0:478cfd88041f 57 _irq.mode(PullUp);
group-Avnet 0:478cfd88041f 58 _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler));
group-Avnet 0:478cfd88041f 59
group-Avnet 0:478cfd88041f 60 /* init cube vars */
group-Avnet 0:478cfd88041f 61 spirit_on = OFF;
group-Avnet 0:478cfd88041f 62 last_rssi = 0 ; //MGR
group-Avnet 0:478cfd88041f 63 last_sqi = 0 ; //MGR
group-Avnet 0:478cfd88041f 64
group-Avnet 0:478cfd88041f 65 /* set frequencies */
group-Avnet 0:478cfd88041f 66 radio_set_xtal_freq(XTAL_FREQUENCY);
group-Avnet 0:478cfd88041f 67 mgmt_set_freq_base((uint32_t)BASE_FREQUENCY);
group-Avnet 0:478cfd88041f 68
group-Avnet 0:478cfd88041f 69 /* restart board */
group-Avnet 0:478cfd88041f 70 enter_shutdown();
group-Avnet 0:478cfd88041f 71 exit_shutdown();
group-Avnet 0:478cfd88041f 72
group-Avnet 0:478cfd88041f 73 /* soft core reset */
group-Avnet 0:478cfd88041f 74 cmd_strobe(SPIRIT1_STROBE_SRES);
group-Avnet 0:478cfd88041f 75
group-Avnet 0:478cfd88041f 76 /* Configures the SPIRIT1 radio part */
group-Avnet 0:478cfd88041f 77 SRadioInit x_radio_init = {
group-Avnet 0:478cfd88041f 78 XTAL_OFFSET_PPM,
group-Avnet 0:478cfd88041f 79 (uint32_t)BASE_FREQUENCY,
group-Avnet 0:478cfd88041f 80 (uint32_t)CHANNEL_SPACE,
group-Avnet 0:478cfd88041f 81 CHANNEL_NUMBER,
group-Avnet 0:478cfd88041f 82 MODULATION_SELECT,
group-Avnet 0:478cfd88041f 83 DATARATE,
group-Avnet 0:478cfd88041f 84 (uint32_t)FREQ_DEVIATION,
group-Avnet 0:478cfd88041f 85 (uint32_t)BANDWIDTH
group-Avnet 0:478cfd88041f 86 };
group-Avnet 0:478cfd88041f 87 radio_init(&x_radio_init);
group-Avnet 0:478cfd88041f 88 radio_set_pa_level_dbm(0,POWER_DBM);
group-Avnet 0:478cfd88041f 89 radio_set_pa_level_max_index(0);
group-Avnet 0:478cfd88041f 90
group-Avnet 0:478cfd88041f 91 /* Configures the SPIRIT1 packet handler part*/
group-Avnet 0:478cfd88041f 92 PktBasicInit x_basic_init = {
group-Avnet 0:478cfd88041f 93 PREAMBLE_LENGTH,
group-Avnet 0:478cfd88041f 94 SYNC_LENGTH,
group-Avnet 0:478cfd88041f 95 SYNC_WORD,
group-Avnet 0:478cfd88041f 96 LENGTH_TYPE,
group-Avnet 0:478cfd88041f 97 LENGTH_WIDTH,
group-Avnet 0:478cfd88041f 98 CRC_MODE,
group-Avnet 0:478cfd88041f 99 CONTROL_LENGTH,
group-Avnet 0:478cfd88041f 100 EN_ADDRESS,
group-Avnet 0:478cfd88041f 101 EN_FEC,
group-Avnet 0:478cfd88041f 102 EN_WHITENING
group-Avnet 0:478cfd88041f 103 };
group-Avnet 0:478cfd88041f 104 pkt_basic_init(&x_basic_init);
group-Avnet 0:478cfd88041f 105
group-Avnet 0:478cfd88041f 106 /* Enable the following interrupt sources, routed to GPIO */
group-Avnet 0:478cfd88041f 107 irq_de_init(NULL);
group-Avnet 0:478cfd88041f 108 irq_clear_status();
group-Avnet 0:478cfd88041f 109 irq_set_status(TX_DATA_SENT, S_ENABLE);
group-Avnet 0:478cfd88041f 110 irq_set_status(RX_DATA_READY,S_ENABLE);
group-Avnet 0:478cfd88041f 111 irq_set_status(RX_DATA_DISC, S_ENABLE);
group-Avnet 0:478cfd88041f 112 irq_set_status(VALID_SYNC, S_ENABLE);
group-Avnet 0:478cfd88041f 113 irq_set_status(TX_FIFO_ERROR, S_ENABLE);
group-Avnet 0:478cfd88041f 114 irq_set_status(RX_FIFO_ERROR, S_ENABLE);
group-Avnet 0:478cfd88041f 115 #ifndef RX_FIFO_THR_WA
group-Avnet 0:478cfd88041f 116 irq_set_status(TX_FIFO_ALMOST_EMPTY, S_ENABLE);
group-Avnet 0:478cfd88041f 117 irq_set_status(RX_FIFO_ALMOST_FULL, S_ENABLE);
group-Avnet 0:478cfd88041f 118 #endif // !RX_FIFO_THR_WA
group-Avnet 0:478cfd88041f 119
group-Avnet 0:478cfd88041f 120 /* Configure Spirit1 */
group-Avnet 0:478cfd88041f 121 radio_persistent_rx(S_ENABLE);
group-Avnet 0:478cfd88041f 122 qi_set_sqi_threshold(SQI_TH_0);
group-Avnet 0:478cfd88041f 123 qi_sqi_check(S_ENABLE);
group-Avnet 0:478cfd88041f 124 qi_set_rssi_threshold_dbm(CCA_THRESHOLD);
group-Avnet 0:478cfd88041f 125 timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD);
group-Avnet 0:478cfd88041f 126 timer_set_infinite_rx_timeout();
group-Avnet 0:478cfd88041f 127 radio_afc_freeze_on_sync(S_ENABLE);
group-Avnet 0:478cfd88041f 128 calibration_rco(S_ENABLE);
group-Avnet 0:478cfd88041f 129
group-Avnet 0:478cfd88041f 130 spirit_on = OFF;
group-Avnet 0:478cfd88041f 131 CLEAR_TXBUF();
group-Avnet 0:478cfd88041f 132 CLEAR_RXBUF();
group-Avnet 0:478cfd88041f 133 _spirit_tx_started = false;
group-Avnet 0:478cfd88041f 134 _is_receiving = false;
group-Avnet 0:478cfd88041f 135
group-Avnet 0:478cfd88041f 136 /* Configure the radio to route the IRQ signal to its GPIO 3 */
group-Avnet 0:478cfd88041f 137 SGpioInit x_gpio_init = {
group-Avnet 0:478cfd88041f 138 SPIRIT_GPIO_IRQ,
group-Avnet 0:478cfd88041f 139 SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP,
group-Avnet 0:478cfd88041f 140 SPIRIT_GPIO_DIG_OUT_IRQ
group-Avnet 0:478cfd88041f 141 };
group-Avnet 0:478cfd88041f 142 spirit_gpio_init(&x_gpio_init);
group-Avnet 0:478cfd88041f 143
group-Avnet 0:478cfd88041f 144 /* Setup CSMA/CA */
group-Avnet 0:478cfd88041f 145 CsmaInit x_csma_init = {
group-Avnet 0:478cfd88041f 146 S_ENABLE, // enable persistent mode
group-Avnet 0:478cfd88041f 147 TBIT_TIME_64, // Tcca time
group-Avnet 0:478cfd88041f 148 TCCA_TIME_3, // Lcca length
group-Avnet 0:478cfd88041f 149 3, // max nr of backoffs (<8)
group-Avnet 0:478cfd88041f 150 1, // BU counter seed
group-Avnet 0:478cfd88041f 151 8 // BU prescaler
group-Avnet 0:478cfd88041f 152 };
group-Avnet 0:478cfd88041f 153 csma_ca_init(&x_csma_init);
group-Avnet 0:478cfd88041f 154
group-Avnet 0:478cfd88041f 155 #ifdef USE_STANDBY_STATE
group-Avnet 0:478cfd88041f 156 /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
group-Avnet 0:478cfd88041f 157 cmd_strobe(SPIRIT1_STROBE_STANDBY);
group-Avnet 0:478cfd88041f 158 #endif // USE_STANDBY_STATE
group-Avnet 0:478cfd88041f 159 }
group-Avnet 0:478cfd88041f 160
group-Avnet 0:478cfd88041f 161 static volatile int tx_fifo_remaining = 0; // to be used in irq handler
group-Avnet 0:478cfd88041f 162 static volatile int tx_buffer_pos = 0; // to be used in irq handler
group-Avnet 0:478cfd88041f 163 const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler
group-Avnet 0:478cfd88041f 164 int SimpleSpirit1::send(const void *payload, unsigned int payload_len) {
group-Avnet 0:478cfd88041f 165 /* Checks if the payload length is supported */
group-Avnet 0:478cfd88041f 166 if(payload_len > MAX_PACKET_LEN) {
group-Avnet 0:478cfd88041f 167 return RADIO_TX_ERR;
group-Avnet 0:478cfd88041f 168 }
group-Avnet 0:478cfd88041f 169
group-Avnet 0:478cfd88041f 170 disable_spirit_irq();
group-Avnet 0:478cfd88041f 171
group-Avnet 0:478cfd88041f 172 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
group-Avnet 0:478cfd88041f 173 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 174 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
group-Avnet 0:478cfd88041f 175 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
group-Avnet 0:478cfd88041f 176 }
group-Avnet 0:478cfd88041f 177 #endif
group-Avnet 0:478cfd88041f 178
group-Avnet 0:478cfd88041f 179 /* Reset State to Ready */
group-Avnet 0:478cfd88041f 180 set_ready_state();
group-Avnet 0:478cfd88041f 181
group-Avnet 0:478cfd88041f 182 cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer
group-Avnet 0:478cfd88041f 183
group-Avnet 0:478cfd88041f 184 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 185 debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 186 #endif
group-Avnet 0:478cfd88041f 187
group-Avnet 0:478cfd88041f 188 pkt_basic_set_payload_length(payload_len); // set desired payload len
group-Avnet 0:478cfd88041f 189
group-Avnet 0:478cfd88041f 190 csma_ca_state(S_ENABLE); // enable CSMA/CA
group-Avnet 0:478cfd88041f 191
group-Avnet 0:478cfd88041f 192 /* Init buffer & number of bytes to be send */
group-Avnet 0:478cfd88041f 193 tx_fifo_remaining = payload_len;
group-Avnet 0:478cfd88041f 194 tx_fifo_buffer = (const uint8_t*)payload;
group-Avnet 0:478cfd88041f 195
group-Avnet 0:478cfd88041f 196 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
group-Avnet 0:478cfd88041f 197 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
group-Avnet 0:478cfd88041f 198
group-Avnet 0:478cfd88041f 199 tx_fifo_remaining -= to_send;
group-Avnet 0:478cfd88041f 200
group-Avnet 0:478cfd88041f 201 /* Fill FIFO Buffer */
group-Avnet 0:478cfd88041f 202 if(to_send > 0) {
group-Avnet 0:478cfd88041f 203 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
group-Avnet 0:478cfd88041f 204 }
group-Avnet 0:478cfd88041f 205
group-Avnet 0:478cfd88041f 206 tx_buffer_pos = to_send;
group-Avnet 0:478cfd88041f 207 _spirit_tx_started = true;
group-Avnet 0:478cfd88041f 208
group-Avnet 0:478cfd88041f 209 enable_spirit_irq();
group-Avnet 0:478cfd88041f 210
group-Avnet 0:478cfd88041f 211 /* Start transmitting */
group-Avnet 0:478cfd88041f 212 cmd_strobe(SPIRIT1_STROBE_TX);
group-Avnet 0:478cfd88041f 213
group-Avnet 0:478cfd88041f 214 while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
group-Avnet 0:478cfd88041f 215
group-Avnet 0:478cfd88041f 216 BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
group-Avnet 0:478cfd88041f 217 #ifdef HEAVY_DEBUG
group-Avnet 0:478cfd88041f 218 debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
group-Avnet 0:478cfd88041f 219 #endif
group-Avnet 0:478cfd88041f 220
group-Avnet 0:478cfd88041f 221 _spirit_tx_started = false; // in case of state timeout
group-Avnet 0:478cfd88041f 222
group-Avnet 0:478cfd88041f 223 csma_ca_state(S_DISABLE); // disable CSMA/CA
group-Avnet 0:478cfd88041f 224
group-Avnet 0:478cfd88041f 225 cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
group-Avnet 0:478cfd88041f 226
group-Avnet 0:478cfd88041f 227 return RADIO_TX_OK;
group-Avnet 0:478cfd88041f 228 }
group-Avnet 0:478cfd88041f 229
group-Avnet 0:478cfd88041f 230 /** Set Ready State **/
group-Avnet 0:478cfd88041f 231 void SimpleSpirit1::set_ready_state(void) {
group-Avnet 0:478cfd88041f 232 uint16_t state;
group-Avnet 0:478cfd88041f 233
group-Avnet 0:478cfd88041f 234 disable_spirit_irq();
group-Avnet 0:478cfd88041f 235
group-Avnet 0:478cfd88041f 236 _spirit_tx_started = false;
group-Avnet 0:478cfd88041f 237 _is_receiving = false;
group-Avnet 0:478cfd88041f 238 stop_rx_timeout();
group-Avnet 0:478cfd88041f 239
group-Avnet 0:478cfd88041f 240 cmd_strobe(SPIRIT1_STROBE_FRX);
group-Avnet 0:478cfd88041f 241 CLEAR_RXBUF();
group-Avnet 0:478cfd88041f 242 CLEAR_TXBUF();
group-Avnet 0:478cfd88041f 243
group-Avnet 0:478cfd88041f 244 state = SPIRIT1_STATUS();
group-Avnet 0:478cfd88041f 245 if(state == SPIRIT1_STATE_STANDBY) {
group-Avnet 0:478cfd88041f 246 cmd_strobe(SPIRIT1_STROBE_READY);
group-Avnet 0:478cfd88041f 247 } else if(state == SPIRIT1_STATE_RX) {
group-Avnet 0:478cfd88041f 248 cmd_strobe(SPIRIT1_STROBE_SABORT);
group-Avnet 0:478cfd88041f 249 } else if(state != SPIRIT1_STATE_READY) {
group-Avnet 0:478cfd88041f 250 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 251 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, state>>1);
group-Avnet 0:478cfd88041f 252 #endif
group-Avnet 0:478cfd88041f 253 }
group-Avnet 0:478cfd88041f 254
group-Avnet 0:478cfd88041f 255 BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
group-Avnet 0:478cfd88041f 256 if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
group-Avnet 0:478cfd88041f 257 error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state);
group-Avnet 0:478cfd88041f 258 enable_spirit_irq();
group-Avnet 0:478cfd88041f 259 return;
group-Avnet 0:478cfd88041f 260 }
group-Avnet 0:478cfd88041f 261
group-Avnet 0:478cfd88041f 262 irq_clear_status();
group-Avnet 0:478cfd88041f 263
group-Avnet 0:478cfd88041f 264 enable_spirit_irq();
group-Avnet 0:478cfd88041f 265 }
group-Avnet 0:478cfd88041f 266
group-Avnet 0:478cfd88041f 267 int SimpleSpirit1::off(void) {
group-Avnet 0:478cfd88041f 268 if(spirit_on == ON) {
group-Avnet 0:478cfd88041f 269 /* Disables the mcu to get IRQ from the SPIRIT1 */
group-Avnet 0:478cfd88041f 270 disable_spirit_irq();
group-Avnet 0:478cfd88041f 271
group-Avnet 0:478cfd88041f 272 /* first stop rx/tx */
group-Avnet 0:478cfd88041f 273 set_ready_state();
group-Avnet 0:478cfd88041f 274
group-Avnet 0:478cfd88041f 275 #ifdef USE_STANDBY_STATE
group-Avnet 0:478cfd88041f 276 /* Puts the SPIRIT1 in STANDBY */
group-Avnet 0:478cfd88041f 277 cmd_strobe(SPIRIT1_STROBE_STANDBY);
group-Avnet 0:478cfd88041f 278 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
group-Avnet 0:478cfd88041f 279 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
group-Avnet 0:478cfd88041f 280 error("\n\rSpirit1: failed to enter standby (%x)\n\r", last_state>>1);
group-Avnet 0:478cfd88041f 281 return 1;
group-Avnet 0:478cfd88041f 282 }
group-Avnet 0:478cfd88041f 283 #endif // USE_STANDBY_STATE
group-Avnet 0:478cfd88041f 284
group-Avnet 0:478cfd88041f 285 spirit_on = OFF;
group-Avnet 0:478cfd88041f 286 _nr_of_irq_disables = 1;
group-Avnet 0:478cfd88041f 287 }
group-Avnet 0:478cfd88041f 288 return 0;
group-Avnet 0:478cfd88041f 289 }
group-Avnet 0:478cfd88041f 290
group-Avnet 0:478cfd88041f 291 int SimpleSpirit1::on(void) {
group-Avnet 0:478cfd88041f 292 if(spirit_on == OFF) {
group-Avnet 0:478cfd88041f 293 set_ready_state();
group-Avnet 0:478cfd88041f 294
group-Avnet 0:478cfd88041f 295 /* now we go to Rx */
group-Avnet 0:478cfd88041f 296 cmd_strobe(SPIRIT1_STROBE_RX);
group-Avnet 0:478cfd88041f 297
group-Avnet 0:478cfd88041f 298 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
group-Avnet 0:478cfd88041f 299 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
group-Avnet 0:478cfd88041f 300 error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1);
group-Avnet 0:478cfd88041f 301 }
group-Avnet 0:478cfd88041f 302
group-Avnet 0:478cfd88041f 303 /* Enables the mcu to get IRQ from the SPIRIT1 */
group-Avnet 0:478cfd88041f 304 spirit_on = ON;
group-Avnet 0:478cfd88041f 305 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 306 debug_if(!(_nr_of_irq_disables == 1), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 307 #endif
group-Avnet 0:478cfd88041f 308 enable_spirit_irq();
group-Avnet 0:478cfd88041f 309 }
group-Avnet 0:478cfd88041f 310
group-Avnet 0:478cfd88041f 311 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 312 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
group-Avnet 0:478cfd88041f 313 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
group-Avnet 0:478cfd88041f 314 }
group-Avnet 0:478cfd88041f 315 #endif
group-Avnet 0:478cfd88041f 316
group-Avnet 0:478cfd88041f 317 return 0;
group-Avnet 0:478cfd88041f 318 }
group-Avnet 0:478cfd88041f 319
group-Avnet 0:478cfd88041f 320 uint8_t SimpleSpirit1::refresh_state(void) {
group-Avnet 0:478cfd88041f 321 uint8_t mcstate;
group-Avnet 0:478cfd88041f 322
group-Avnet 0:478cfd88041f 323 SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
group-Avnet 0:478cfd88041f 324
group-Avnet 0:478cfd88041f 325 return mcstate;
group-Avnet 0:478cfd88041f 326 }
group-Avnet 0:478cfd88041f 327
group-Avnet 0:478cfd88041f 328 int SimpleSpirit1::read(void *buf, unsigned int bufsize)
group-Avnet 0:478cfd88041f 329 {
group-Avnet 0:478cfd88041f 330 disable_spirit_irq();
group-Avnet 0:478cfd88041f 331
group-Avnet 0:478cfd88041f 332 /* Checks if the RX buffer is empty */
group-Avnet 0:478cfd88041f 333 if(IS_RXBUF_EMPTY()) {
group-Avnet 0:478cfd88041f 334 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 335 debug("\n\rBuffer is empty\n\r");
group-Avnet 0:478cfd88041f 336 #endif
group-Avnet 0:478cfd88041f 337 set_ready_state();
group-Avnet 0:478cfd88041f 338
group-Avnet 0:478cfd88041f 339 cmd_strobe(SPIRIT1_STROBE_RX);
group-Avnet 0:478cfd88041f 340 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
group-Avnet 0:478cfd88041f 341 enable_spirit_irq();
group-Avnet 0:478cfd88041f 342 return 0;
group-Avnet 0:478cfd88041f 343 }
group-Avnet 0:478cfd88041f 344
group-Avnet 0:478cfd88041f 345 if(bufsize < spirit_rx_len) {
group-Avnet 0:478cfd88041f 346 enable_spirit_irq();
group-Avnet 0:478cfd88041f 347
group-Avnet 0:478cfd88041f 348 /* If buf has the correct size */
group-Avnet 0:478cfd88041f 349 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 350 debug("\n\rTOO SMALL BUF\n\r");
group-Avnet 0:478cfd88041f 351 #endif
group-Avnet 0:478cfd88041f 352 return 0;
group-Avnet 0:478cfd88041f 353 } else {
group-Avnet 0:478cfd88041f 354 /* Copies the packet received */
group-Avnet 0:478cfd88041f 355 memcpy(buf, spirit_rx_buf, spirit_rx_len);
group-Avnet 0:478cfd88041f 356
group-Avnet 0:478cfd88041f 357 bufsize = spirit_rx_len;
group-Avnet 0:478cfd88041f 358 CLEAR_RXBUF();
group-Avnet 0:478cfd88041f 359
group-Avnet 0:478cfd88041f 360 enable_spirit_irq();
group-Avnet 0:478cfd88041f 361
group-Avnet 0:478cfd88041f 362 return bufsize;
group-Avnet 0:478cfd88041f 363 }
group-Avnet 0:478cfd88041f 364
group-Avnet 0:478cfd88041f 365 }
group-Avnet 0:478cfd88041f 366
group-Avnet 0:478cfd88041f 367 int SimpleSpirit1::channel_clear(void)
group-Avnet 0:478cfd88041f 368 {
group-Avnet 0:478cfd88041f 369 float rssi_value;
group-Avnet 0:478cfd88041f 370 /* Local variable used to memorize the SPIRIT1 state */
group-Avnet 0:478cfd88041f 371 uint8_t spirit_state = ON;
group-Avnet 0:478cfd88041f 372
group-Avnet 0:478cfd88041f 373 if(spirit_on == OFF) {
group-Avnet 0:478cfd88041f 374 /* Wakes up the SPIRIT1 */
group-Avnet 0:478cfd88041f 375 on();
group-Avnet 0:478cfd88041f 376 spirit_state = OFF;
group-Avnet 0:478cfd88041f 377 }
group-Avnet 0:478cfd88041f 378
group-Avnet 0:478cfd88041f 379 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 380 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
group-Avnet 0:478cfd88041f 381 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
group-Avnet 0:478cfd88041f 382 }
group-Avnet 0:478cfd88041f 383 #endif
group-Avnet 0:478cfd88041f 384
group-Avnet 0:478cfd88041f 385 disable_spirit_irq();
group-Avnet 0:478cfd88041f 386
group-Avnet 0:478cfd88041f 387 /* Reset State to Ready */
group-Avnet 0:478cfd88041f 388 set_ready_state();
group-Avnet 0:478cfd88041f 389
group-Avnet 0:478cfd88041f 390 /* Stores the RSSI value */
group-Avnet 0:478cfd88041f 391 rssi_value = qi_get_rssi_dbm();
group-Avnet 0:478cfd88041f 392
group-Avnet 0:478cfd88041f 393 enable_spirit_irq();
group-Avnet 0:478cfd88041f 394
group-Avnet 0:478cfd88041f 395 /* Puts the SPIRIT1 in its previous state */
group-Avnet 0:478cfd88041f 396 if(spirit_state==OFF) {
group-Avnet 0:478cfd88041f 397 off();
group-Avnet 0:478cfd88041f 398 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 399 #ifdef USE_STANDBY_STATE
group-Avnet 0:478cfd88041f 400 if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
group-Avnet 0:478cfd88041f 401 #else
group-Avnet 0:478cfd88041f 402 if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
group-Avnet 0:478cfd88041f 403 #endif
group-Avnet 0:478cfd88041f 404 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
group-Avnet 0:478cfd88041f 405 }
group-Avnet 0:478cfd88041f 406 #endif
group-Avnet 0:478cfd88041f 407 } else {
group-Avnet 0:478cfd88041f 408 disable_spirit_irq();
group-Avnet 0:478cfd88041f 409
group-Avnet 0:478cfd88041f 410 set_ready_state();
group-Avnet 0:478cfd88041f 411
group-Avnet 0:478cfd88041f 412 cmd_strobe(SPIRIT1_STROBE_RX);
group-Avnet 0:478cfd88041f 413 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
group-Avnet 0:478cfd88041f 414 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
group-Avnet 0:478cfd88041f 415 error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1);
group-Avnet 0:478cfd88041f 416 }
group-Avnet 0:478cfd88041f 417
group-Avnet 0:478cfd88041f 418 enable_spirit_irq();
group-Avnet 0:478cfd88041f 419
group-Avnet 0:478cfd88041f 420 #ifndef NDEBUG
group-Avnet 0:478cfd88041f 421 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
group-Avnet 0:478cfd88041f 422 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
group-Avnet 0:478cfd88041f 423 }
group-Avnet 0:478cfd88041f 424 #endif
group-Avnet 0:478cfd88041f 425 }
group-Avnet 0:478cfd88041f 426
group-Avnet 0:478cfd88041f 427 /* Checks the RSSI value with the threshold */
group-Avnet 0:478cfd88041f 428 if(rssi_value<CCA_THRESHOLD) {
group-Avnet 0:478cfd88041f 429 return 0;
group-Avnet 0:478cfd88041f 430 } else {
group-Avnet 0:478cfd88041f 431 return 1;
group-Avnet 0:478cfd88041f 432 }
group-Avnet 0:478cfd88041f 433 }
group-Avnet 0:478cfd88041f 434
group-Avnet 0:478cfd88041f 435 int SimpleSpirit1::get_pending_packet(void)
group-Avnet 0:478cfd88041f 436 {
group-Avnet 0:478cfd88041f 437 return !IS_RXBUF_EMPTY();
group-Avnet 0:478cfd88041f 438 }
group-Avnet 0:478cfd88041f 439
group-Avnet 0:478cfd88041f 440 /** Spirit Irq Callback **/
group-Avnet 0:478cfd88041f 441 void SimpleSpirit1::IrqHandler() {
group-Avnet 0:478cfd88041f 442 st_lib_spirit_irqs x_irq_status;
group-Avnet 0:478cfd88041f 443
group-Avnet 0:478cfd88041f 444 /* get interrupt source from radio */
group-Avnet 0:478cfd88041f 445 irq_get_status(&x_irq_status);
group-Avnet 0:478cfd88041f 446
group-Avnet 0:478cfd88041f 447 /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
group-Avnet 0:478cfd88041f 448 if(x_irq_status.IRQ_TX_DATA_SENT) {
group-Avnet 0:478cfd88041f 449 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 450 uint32_t *tmp = (uint32_t*)&x_irq_status;
group-Avnet 0:478cfd88041f 451 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 452 debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 453 debug_if(tx_fifo_remaining != 0, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 454 #endif
group-Avnet 0:478cfd88041f 455
group-Avnet 0:478cfd88041f 456 tx_fifo_buffer = NULL;
group-Avnet 0:478cfd88041f 457 _spirit_tx_started = false;
group-Avnet 0:478cfd88041f 458
group-Avnet 0:478cfd88041f 459 /* call user callback */
group-Avnet 0:478cfd88041f 460 if(_current_irq_callback) {
group-Avnet 0:478cfd88041f 461 _current_irq_callback(TX_DONE);
group-Avnet 0:478cfd88041f 462 }
group-Avnet 0:478cfd88041f 463
group-Avnet 0:478cfd88041f 464 /* Disable handling of other TX flags */
group-Avnet 0:478cfd88041f 465 x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET;
group-Avnet 0:478cfd88041f 466 }
group-Avnet 0:478cfd88041f 467
group-Avnet 0:478cfd88041f 468 #ifndef RX_FIFO_THR_WA
group-Avnet 0:478cfd88041f 469 /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
group-Avnet 0:478cfd88041f 470 if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
group-Avnet 0:478cfd88041f 471 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 472 uint32_t *tmp = (uint32_t*)&x_irq_status;
group-Avnet 0:478cfd88041f 473 debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 474 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 475 debug_if(tx_fifo_buffer == NULL, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 476 #endif
group-Avnet 0:478cfd88041f 477
group-Avnet 0:478cfd88041f 478 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
group-Avnet 0:478cfd88041f 479 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
group-Avnet 0:478cfd88041f 480
group-Avnet 0:478cfd88041f 481 tx_fifo_remaining -= to_send;
group-Avnet 0:478cfd88041f 482
group-Avnet 0:478cfd88041f 483 /* Fill FIFO Buffer */
group-Avnet 0:478cfd88041f 484 if(to_send > 0) {
group-Avnet 0:478cfd88041f 485 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
group-Avnet 0:478cfd88041f 486 }
group-Avnet 0:478cfd88041f 487 tx_buffer_pos += to_send;
group-Avnet 0:478cfd88041f 488 }
group-Avnet 0:478cfd88041f 489 #endif // !RX_FIFO_THR_WA
group-Avnet 0:478cfd88041f 490
group-Avnet 0:478cfd88041f 491 /* Transmission error */
group-Avnet 0:478cfd88041f 492 if(x_irq_status.IRQ_TX_FIFO_ERROR) {
group-Avnet 0:478cfd88041f 493 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 494 uint32_t *tmp = (uint32_t*)&x_irq_status;
group-Avnet 0:478cfd88041f 495 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
group-Avnet 0:478cfd88041f 496 debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 497 #endif
group-Avnet 0:478cfd88041f 498 if(_spirit_tx_started) {
group-Avnet 0:478cfd88041f 499 _spirit_tx_started = false;
group-Avnet 0:478cfd88041f 500 /* call user callback */
group-Avnet 0:478cfd88041f 501 if(_current_irq_callback) {
group-Avnet 0:478cfd88041f 502 _current_irq_callback(TX_ERR);
group-Avnet 0:478cfd88041f 503 }
group-Avnet 0:478cfd88041f 504 }
group-Avnet 0:478cfd88041f 505
group-Avnet 0:478cfd88041f 506 /* reset data still to be sent */
group-Avnet 0:478cfd88041f 507 tx_fifo_remaining = 0;
group-Avnet 0:478cfd88041f 508 }
group-Avnet 0:478cfd88041f 509
group-Avnet 0:478cfd88041f 510 /* The IRQ_RX_DATA_READY notifies a new packet arrived */
group-Avnet 0:478cfd88041f 511 if(x_irq_status.IRQ_RX_DATA_READY) {
group-Avnet 0:478cfd88041f 512 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 513 uint32_t *tmp = (uint32_t*)&x_irq_status;
group-Avnet 0:478cfd88041f 514 debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 515 #endif
group-Avnet 0:478cfd88041f 516
group-Avnet 0:478cfd88041f 517 if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!)
group-Avnet 0:478cfd88041f 518 #ifdef HEAVY_DEBUG
group-Avnet 0:478cfd88041f 519 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
group-Avnet 0:478cfd88041f 520 #endif
group-Avnet 0:478cfd88041f 521 } else {
group-Avnet 0:478cfd88041f 522 _is_receiving = false; // Finished receiving
group-Avnet 0:478cfd88041f 523 stop_rx_timeout();
group-Avnet 0:478cfd88041f 524
group-Avnet 0:478cfd88041f 525 spirit_rx_len = pkt_basic_get_received_pkt_length();
group-Avnet 0:478cfd88041f 526
group-Avnet 0:478cfd88041f 527 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 528 debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
group-Avnet 0:478cfd88041f 529 #endif
group-Avnet 0:478cfd88041f 530
group-Avnet 0:478cfd88041f 531 if(spirit_rx_len <= MAX_PACKET_LEN) {
group-Avnet 0:478cfd88041f 532 uint8_t to_receive = spirit_rx_len - _spirit_rx_pos;
group-Avnet 0:478cfd88041f 533 if(to_receive > 0) {
group-Avnet 0:478cfd88041f 534 spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]);
group-Avnet 0:478cfd88041f 535 _spirit_rx_pos += to_receive;
group-Avnet 0:478cfd88041f 536 }
group-Avnet 0:478cfd88041f 537 }
group-Avnet 0:478cfd88041f 538
group-Avnet 0:478cfd88041f 539 cmd_strobe(SPIRIT1_STROBE_FRX);
group-Avnet 0:478cfd88041f 540
group-Avnet 0:478cfd88041f 541 last_rssi = qi_get_rssi(); //MGR
group-Avnet 0:478cfd88041f 542 last_sqi = qi_get_sqi(); //MGR
group-Avnet 0:478cfd88041f 543
group-Avnet 0:478cfd88041f 544 /* call user callback */
group-Avnet 0:478cfd88041f 545 if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) {
group-Avnet 0:478cfd88041f 546 _current_irq_callback(RX_DONE);
group-Avnet 0:478cfd88041f 547 }
group-Avnet 0:478cfd88041f 548
group-Avnet 0:478cfd88041f 549 /* Disable handling of other RX flags */
group-Avnet 0:478cfd88041f 550 x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
group-Avnet 0:478cfd88041f 551 }
group-Avnet 0:478cfd88041f 552 }
group-Avnet 0:478cfd88041f 553
group-Avnet 0:478cfd88041f 554 #ifndef RX_FIFO_THR_WA
group-Avnet 0:478cfd88041f 555 /* RX FIFO almost full */
group-Avnet 0:478cfd88041f 556 if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) {
group-Avnet 0:478cfd88041f 557 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 558 uint32_t *tmp = (uint32_t*)&x_irq_status;
group-Avnet 0:478cfd88041f 559 debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 560 #endif
group-Avnet 0:478cfd88041f 561 if(!_is_receiving) { // spurious irq?!?
group-Avnet 0:478cfd88041f 562 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 563 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
group-Avnet 0:478cfd88041f 564 #endif
group-Avnet 0:478cfd88041f 565 } else {
group-Avnet 0:478cfd88041f 566 uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
group-Avnet 0:478cfd88041f 567 if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) {
group-Avnet 0:478cfd88041f 568 spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
group-Avnet 0:478cfd88041f 569 _spirit_rx_pos += fifo_available;
group-Avnet 0:478cfd88041f 570 } else {
group-Avnet 0:478cfd88041f 571 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 572 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
group-Avnet 0:478cfd88041f 573 #endif
group-Avnet 0:478cfd88041f 574 }
group-Avnet 0:478cfd88041f 575 }
group-Avnet 0:478cfd88041f 576 }
group-Avnet 0:478cfd88041f 577 #endif // !RX_FIFO_THR_WA
group-Avnet 0:478cfd88041f 578
group-Avnet 0:478cfd88041f 579 /* Reception errors */
group-Avnet 0:478cfd88041f 580 if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
group-Avnet 0:478cfd88041f 581 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 582 uint32_t *tmp = (uint32_t*)&x_irq_status;
group-Avnet 0:478cfd88041f 583 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
group-Avnet 0:478cfd88041f 584 debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 585 #endif
group-Avnet 0:478cfd88041f 586 rx_timeout_handler();
group-Avnet 0:478cfd88041f 587 if(_spirit_tx_started) {
group-Avnet 0:478cfd88041f 588 _spirit_tx_started = false;
group-Avnet 0:478cfd88041f 589 /* call user callback */
group-Avnet 0:478cfd88041f 590 if(_current_irq_callback) {
group-Avnet 0:478cfd88041f 591 _current_irq_callback(TX_ERR);
group-Avnet 0:478cfd88041f 592 }
group-Avnet 0:478cfd88041f 593 }
group-Avnet 0:478cfd88041f 594 }
group-Avnet 0:478cfd88041f 595
group-Avnet 0:478cfd88041f 596 /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
group-Avnet 0:478cfd88041f 597 if(x_irq_status.IRQ_VALID_SYNC) {
group-Avnet 0:478cfd88041f 598 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 599 uint32_t *tmp = (uint32_t*)&x_irq_status;
group-Avnet 0:478cfd88041f 600 debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
group-Avnet 0:478cfd88041f 601 #endif
group-Avnet 0:478cfd88041f 602 /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and
group-Avnet 0:478cfd88041f 603 * the MCU trying to send a packet, which gets resolved in favor of
group-Avnet 0:478cfd88041f 604 * sending.
group-Avnet 0:478cfd88041f 605 */
group-Avnet 0:478cfd88041f 606 if(_spirit_tx_started) {
group-Avnet 0:478cfd88041f 607 #ifdef DEBUG_IRQ
group-Avnet 0:478cfd88041f 608 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
group-Avnet 0:478cfd88041f 609 #endif
group-Avnet 0:478cfd88041f 610 } else {
group-Avnet 0:478cfd88041f 611 _is_receiving = true;
group-Avnet 0:478cfd88041f 612 start_rx_timeout();
group-Avnet 0:478cfd88041f 613 }
group-Avnet 0:478cfd88041f 614 }
group-Avnet 0:478cfd88041f 615 }