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