180718 HJM : 8 Count sensing data RF send, certTest, temp(cold)Test

Fork of EV-COG-AD3029LZ by JunMo Hong

Committer:
Wolfgang Betz
Date:
Thu Jul 13 09:21:06 2017 +0200
Revision:
70:19b5f9b9ba80
Parent:
69:22e9b407effa
Child:
71:4a7772415d9c
Handle overflow situations in busy wait

Who changed what in which revision?

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