Dependencies:   MMA7660 LM75B

Committer:
MACRUM
Date:
Sat Jun 30 01:40:30 2018 +0000
Revision:
0:119624335925
Initial commit

Who changed what in which revision?

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