modified to get more signal info

Dependencies:   WNC14A2AInterface

Fork of easy-connect by Jim Flynn

Committer:
tdMBED
Date:
Sat Nov 25 21:52:06 2017 +0000
Revision:
7:b7ed55f374be
Parent:
0:2563b0415d1f
modified to get more signal info

Who changed what in which revision?

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