Prototype RF driver for STM Sub-1 GHz RF expansion board based on the SPSGRF-868 module for STM32 Nucleo.
Dependents: DISCO_IOT-wifi_client
Fork of stm-spirit1-rf-driver by
Revision 69:22e9b407effa, committed 2017-07-10
- Comitter:
- Wolfgang Betz
- Date:
- Mon Jul 10 13:54:43 2017 +0200
- Parent:
- 68:247fd6e0ab66
- Child:
- 70:19b5f9b9ba80
- Commit message:
- Better handling of race condition around `_spirit_tx_started`
Changed in this revision
| source/SimpleSpirit1.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/source/SimpleSpirit1.cpp Thu Jul 06 14:15:57 2017 +0200
+++ b/source/SimpleSpirit1.cpp Mon Jul 10 13:54:43 2017 +0200
@@ -10,10 +10,10 @@
#define XO_ON (0x1)
#define BUSYWAIT_UNTIL(cond, millisecs) \
- do { \
- uint32_t start = us_ticker_read(); \
- while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U)); \
- } while(0)
+ do { \
+ uint32_t start = us_ticker_read(); \
+ while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U)); \
+ } while(0)
#define st_lib_spirit_irqs SpiritIrqs
@@ -28,599 +28,603 @@
/** Constructor **/
SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
- PinName irq, PinName cs, PinName sdn,
- PinName led) :
- _spi(mosi, miso, sclk),
- _irq(irq),
- _chip_select(cs),
- _shut_down(sdn),
- _led(led),
- _current_irq_callback(),
- _rx_receiving_timeout()
+ PinName irq, PinName cs, PinName sdn,
+ PinName led) :
+ _spi(mosi, miso, sclk),
+ _irq(irq),
+ _chip_select(cs),
+ _shut_down(sdn),
+ _led(led),
+ _current_irq_callback(),
+ _rx_receiving_timeout()
{
}
/** Init Function **/
void SimpleSpirit1::init() {
- /* reset irq disable counter and irq callback & disable irq */
- _nr_of_irq_disables = 0;
- disable_spirit_irq();
+ /* reset irq disable counter and irq callback & disable irq */
+ _nr_of_irq_disables = 0;
+ disable_spirit_irq();
- /* unselect chip */
- chip_unselect();
+ /* unselect chip */
+ chip_unselect();
- /* configure spi */
- _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
- _spi.frequency(10000000); // 10MHz (i.e. max speed allowed for Spirit1)
+ /* configure spi */
+ _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
+ _spi.frequency(10000000); // 10MHz (i.e. max speed allowed for Spirit1)
- /* install irq handler */
- _irq.mode(PullUp);
- _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler));
+ /* install irq handler */
+ _irq.mode(PullUp);
+ _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler));
- /* init cube vars */
- spirit_on = OFF;
- last_rssi = 0 ; //MGR
- last_sqi = 0 ; //MGR
+ /* init cube vars */
+ spirit_on = OFF;
+ last_rssi = 0 ; //MGR
+ last_sqi = 0 ; //MGR
- /* set frequencies */
- radio_set_xtal_freq(XTAL_FREQUENCY);
- mgmt_set_freq_base((uint32_t)BASE_FREQUENCY);
+ /* set frequencies */
+ radio_set_xtal_freq(XTAL_FREQUENCY);
+ mgmt_set_freq_base((uint32_t)BASE_FREQUENCY);
- /* restart board */
- enter_shutdown();
- exit_shutdown();
+ /* restart board */
+ enter_shutdown();
+ exit_shutdown();
- /* soft core reset */
- cmd_strobe(SPIRIT1_STROBE_SRES);
+ /* soft core reset */
+ cmd_strobe(SPIRIT1_STROBE_SRES);
- /* Configures the SPIRIT1 radio part */
- SRadioInit x_radio_init = {
- XTAL_OFFSET_PPM,
- (uint32_t)BASE_FREQUENCY,
- (uint32_t)CHANNEL_SPACE,
- CHANNEL_NUMBER,
- MODULATION_SELECT,
- DATARATE,
- (uint32_t)FREQ_DEVIATION,
- (uint32_t)BANDWIDTH
- };
- radio_init(&x_radio_init);
- radio_set_pa_level_dbm(0,POWER_DBM);
- radio_set_pa_level_max_index(0);
+ /* Configures the SPIRIT1 radio part */
+ SRadioInit x_radio_init = {
+ XTAL_OFFSET_PPM,
+ (uint32_t)BASE_FREQUENCY,
+ (uint32_t)CHANNEL_SPACE,
+ CHANNEL_NUMBER,
+ MODULATION_SELECT,
+ DATARATE,
+ (uint32_t)FREQ_DEVIATION,
+ (uint32_t)BANDWIDTH
+ };
+ radio_init(&x_radio_init);
+ radio_set_pa_level_dbm(0,POWER_DBM);
+ radio_set_pa_level_max_index(0);
- /* Configures the SPIRIT1 packet handler part*/
- PktBasicInit x_basic_init = {
- PREAMBLE_LENGTH,
- SYNC_LENGTH,
- SYNC_WORD,
- LENGTH_TYPE,
- LENGTH_WIDTH,
- CRC_MODE,
- CONTROL_LENGTH,
- EN_ADDRESS,
- EN_FEC,
- EN_WHITENING
- };
- pkt_basic_init(&x_basic_init);
+ /* Configures the SPIRIT1 packet handler part*/
+ PktBasicInit x_basic_init = {
+ PREAMBLE_LENGTH,
+ SYNC_LENGTH,
+ SYNC_WORD,
+ LENGTH_TYPE,
+ LENGTH_WIDTH,
+ CRC_MODE,
+ CONTROL_LENGTH,
+ EN_ADDRESS,
+ EN_FEC,
+ EN_WHITENING
+ };
+ pkt_basic_init(&x_basic_init);
- /* Enable the following interrupt sources, routed to GPIO */
- irq_de_init(NULL);
- irq_clear_status();
- irq_set_status(TX_DATA_SENT, S_ENABLE);
- irq_set_status(RX_DATA_READY,S_ENABLE);
- irq_set_status(RX_DATA_DISC, S_ENABLE);
- irq_set_status(VALID_SYNC, S_ENABLE);
- irq_set_status(TX_FIFO_ERROR, S_ENABLE);
- irq_set_status(RX_FIFO_ERROR, S_ENABLE);
+ /* Enable the following interrupt sources, routed to GPIO */
+ irq_de_init(NULL);
+ irq_clear_status();
+ irq_set_status(TX_DATA_SENT, S_ENABLE);
+ irq_set_status(RX_DATA_READY,S_ENABLE);
+ irq_set_status(RX_DATA_DISC, S_ENABLE);
+ irq_set_status(VALID_SYNC, S_ENABLE);
+ irq_set_status(TX_FIFO_ERROR, S_ENABLE);
+ irq_set_status(RX_FIFO_ERROR, S_ENABLE);
#ifndef RX_FIFO_THR_WA
- irq_set_status(TX_FIFO_ALMOST_EMPTY, S_ENABLE);
- irq_set_status(RX_FIFO_ALMOST_FULL, S_ENABLE);
+ irq_set_status(TX_FIFO_ALMOST_EMPTY, S_ENABLE);
+ irq_set_status(RX_FIFO_ALMOST_FULL, S_ENABLE);
#endif // !RX_FIFO_THR_WA
- /* Configure Spirit1 */
- radio_persistent_rx(S_ENABLE);
- qi_set_sqi_threshold(SQI_TH_0);
- qi_sqi_check(S_ENABLE);
- qi_set_rssi_threshold_dbm(CCA_THRESHOLD);
- timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD);
- timer_set_infinite_rx_timeout();
- radio_afc_freeze_on_sync(S_ENABLE);
- calibration_rco(S_ENABLE);
+ /* Configure Spirit1 */
+ radio_persistent_rx(S_ENABLE);
+ qi_set_sqi_threshold(SQI_TH_0);
+ qi_sqi_check(S_ENABLE);
+ qi_set_rssi_threshold_dbm(CCA_THRESHOLD);
+ timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD);
+ timer_set_infinite_rx_timeout();
+ radio_afc_freeze_on_sync(S_ENABLE);
+ calibration_rco(S_ENABLE);
- spirit_on = OFF;
- CLEAR_TXBUF();
- CLEAR_RXBUF();
- _spirit_tx_started = false;
- _is_receiving = false;
+ spirit_on = OFF;
+ CLEAR_TXBUF();
+ CLEAR_RXBUF();
+ _spirit_tx_started = false;
+ _is_receiving = false;
- /* Configure the radio to route the IRQ signal to its GPIO 3 */
- SGpioInit x_gpio_init = {
- SPIRIT_GPIO_IRQ,
- SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP,
- SPIRIT_GPIO_DIG_OUT_IRQ
- };
- spirit_gpio_init(&x_gpio_init);
+ /* Configure the radio to route the IRQ signal to its GPIO 3 */
+ SGpioInit x_gpio_init = {
+ SPIRIT_GPIO_IRQ,
+ SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP,
+ SPIRIT_GPIO_DIG_OUT_IRQ
+ };
+ spirit_gpio_init(&x_gpio_init);
- /* Setup CSMA/CA */
- CsmaInit x_csma_init = {
- S_ENABLE, // enable persistent mode
- TBIT_TIME_64, // Tcca time
- TCCA_TIME_3, // Lcca length
- 5, // max nr of backoffs (<8)
- 1, // BU counter seed
- 8 // BU prescaler
- };
- csma_ca_init(&x_csma_init);
+ /* Setup CSMA/CA */
+ CsmaInit x_csma_init = {
+ S_ENABLE, // enable persistent mode
+ TBIT_TIME_64, // Tcca time
+ TCCA_TIME_3, // Lcca length
+ 5, // max nr of backoffs (<8)
+ 1, // BU counter seed
+ 8 // BU prescaler
+ };
+ csma_ca_init(&x_csma_init);
#ifdef USE_STANDBY_STATE
- /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
- cmd_strobe(SPIRIT1_STROBE_STANDBY);
+ /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
+ cmd_strobe(SPIRIT1_STROBE_STANDBY);
#endif // USE_STANDBY_STATE
}
-static volatile int tx_fifo_remaining = 0; // to be used in irq handler
-static volatile int tx_buffer_pos = 0; // to be used in irq handler
-const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler
+static volatile int tx_fifo_remaining = 0; // to be used in irq handler
+static volatile int tx_buffer_pos = 0; // to be used in irq handler
+static const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler
int SimpleSpirit1::send(const void *payload, unsigned int payload_len, bool use_csma_ca) {
- /* Checks if the payload length is supported */
- if(payload_len > MAX_PACKET_LEN) {
- return RADIO_TX_ERR;
- }
+ /* Checks if the payload length is supported */
+ if(payload_len > MAX_PACKET_LEN) {
+ return RADIO_TX_ERR;
+ }
- disable_spirit_irq();
+ disable_spirit_irq();
- BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
#ifndef NDEBUG
- if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
- debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
- }
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
+ debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
+ }
#endif
- /* Reset State to Ready */
- set_ready_state();
+ /* Reset State to Ready */
+ set_ready_state();
- cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer
+ cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer
#ifndef NDEBUG
- debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
#endif
- pkt_basic_set_payload_length(payload_len); // set desired payload len
+ pkt_basic_set_payload_length(payload_len); // set desired payload len
- if(use_csma_ca) {
- csma_ca_state(S_ENABLE); // enable CSMA/CA
- }
+ if(use_csma_ca) {
+ csma_ca_state(S_ENABLE); // enable CSMA/CA
+ }
- /* Init buffer & number of bytes to be send */
- tx_fifo_remaining = payload_len;
- tx_fifo_buffer = (const uint8_t*)payload;
+ /* Init buffer & number of bytes to be send */
+ tx_fifo_remaining = payload_len;
+ tx_fifo_buffer = (const uint8_t*)payload;
- int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
- int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
+ int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
+ int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
- tx_fifo_remaining -= to_send;
+ tx_fifo_remaining -= to_send;
- /* Fill FIFO Buffer */
- if(to_send > 0) {
- spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
- }
+ /* Fill FIFO Buffer */
+ if(to_send > 0) {
+ spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
+ }
- tx_buffer_pos = to_send;
- _spirit_tx_started = true;
+ tx_buffer_pos = to_send;
+ _spirit_tx_started = true;
- enable_spirit_irq();
+ enable_spirit_irq();
- /* Start transmitting */
- cmd_strobe(SPIRIT1_STROBE_TX);
+ /* Start transmitting */
+ cmd_strobe(SPIRIT1_STROBE_TX);
- while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
+ while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
- BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
+ BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
#ifdef HEAVY_DEBUG
- debug("\r\n%s (%d): state=%x, _spirit_tx_started=%d\r\n", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
+ debug("\r\n%s (%d): state=%x, _spirit_tx_started=%d\r\n", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
#endif
if(use_csma_ca) {
csma_ca_state(S_DISABLE); // disable CSMA/CA
}
- cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
+ cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
- if(_spirit_tx_started) { // in case of state timeout
- _spirit_tx_started = false;
- return RADIO_TX_ERR;
- } else {
- return RADIO_TX_OK;
- }
+ disable_spirit_irq();
+ if(_spirit_tx_started) { // in case of state timeout
+ _spirit_tx_started = false;
+ enable_spirit_irq();
+ return RADIO_TX_ERR;
+ } else {
+ enable_spirit_irq();
+ return RADIO_TX_OK;
+ }
}
/** Set Ready State **/
void SimpleSpirit1::set_ready_state(void) {
- uint16_t state;
+ uint16_t state;
- disable_spirit_irq();
+ disable_spirit_irq();
- _spirit_tx_started = false;
- _is_receiving = false;
- stop_rx_timeout();
+ _spirit_tx_started = false;
+ _is_receiving = false;
+ stop_rx_timeout();
- cmd_strobe(SPIRIT1_STROBE_FRX);
- CLEAR_RXBUF();
- CLEAR_TXBUF();
+ cmd_strobe(SPIRIT1_STROBE_FRX);
+ CLEAR_RXBUF();
+ CLEAR_TXBUF();
- state = SPIRIT1_STATUS();
- if(state == SPIRIT1_STATE_STANDBY) {
- cmd_strobe(SPIRIT1_STROBE_READY);
- } else if(state == SPIRIT1_STATE_RX) {
- cmd_strobe(SPIRIT1_STROBE_SABORT);
- } else if(state != SPIRIT1_STATE_READY) {
+ state = SPIRIT1_STATUS();
+ if(state == SPIRIT1_STATE_STANDBY) {
+ cmd_strobe(SPIRIT1_STROBE_READY);
+ } else if(state == SPIRIT1_STATE_RX) {
+ cmd_strobe(SPIRIT1_STROBE_SABORT);
+ } else if(state != SPIRIT1_STATE_READY) {
#ifndef NDEBUG
- debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, state>>1);
+ debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, state>>1);
#endif
- }
+ }
- BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
- if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
- error("\r\nSpirit1: failed to become ready (%x) => pls. reset!\r\n", last_state);
- enable_spirit_irq();
- return;
- }
+ BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
+ if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
+ error("\r\nSpirit1: failed to become ready (%x) => pls. reset!\r\n", last_state);
+ enable_spirit_irq();
+ return;
+ }
- irq_clear_status();
+ irq_clear_status();
- enable_spirit_irq();
+ enable_spirit_irq();
}
int SimpleSpirit1::off(void) {
- if(spirit_on == ON) {
- /* Disables the mcu to get IRQ from the SPIRIT1 */
- disable_spirit_irq();
+ if(spirit_on == ON) {
+ /* Disables the mcu to get IRQ from the SPIRIT1 */
+ disable_spirit_irq();
- /* first stop rx/tx */
- set_ready_state();
+ /* first stop rx/tx */
+ set_ready_state();
#ifdef USE_STANDBY_STATE
- /* Puts the SPIRIT1 in STANDBY */
- cmd_strobe(SPIRIT1_STROBE_STANDBY);
- BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
- if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
- error("\r\nSpirit1: failed to enter standby (%x)\r\n", last_state>>1);
- return 1;
- }
+ /* Puts the SPIRIT1 in STANDBY */
+ cmd_strobe(SPIRIT1_STROBE_STANDBY);
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
+ error("\r\nSpirit1: failed to enter standby (%x)\r\n", last_state>>1);
+ return 1;
+ }
#endif // USE_STANDBY_STATE
- spirit_on = OFF;
- _nr_of_irq_disables = 1;
- }
- return 0;
+ spirit_on = OFF;
+ _nr_of_irq_disables = 1;
+ }
+ return 0;
}
int SimpleSpirit1::on(void) {
- if(spirit_on == OFF) {
- set_ready_state();
+ if(spirit_on == OFF) {
+ set_ready_state();
- /* now we go to Rx */
- cmd_strobe(SPIRIT1_STROBE_RX);
+ /* now we go to Rx */
+ cmd_strobe(SPIRIT1_STROBE_RX);
- BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
- if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
- error("\r\nSpirit1: failed to enter rx (%x) => retry\r\n", last_state>>1);
- }
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
+ error("\r\nSpirit1: failed to enter rx (%x) => retry\r\n", last_state>>1);
+ }
- /* Enables the mcu to get IRQ from the SPIRIT1 */
- spirit_on = ON;
+ /* Enables the mcu to get IRQ from the SPIRIT1 */
+ spirit_on = ON;
#ifndef NDEBUG
- debug_if(!(_nr_of_irq_disables == 1), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ debug_if(!(_nr_of_irq_disables == 1), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
#endif
- enable_spirit_irq();
- }
+ enable_spirit_irq();
+ }
#ifndef NDEBUG
- if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
- debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
- }
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+ debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
+ }
#endif
- return 0;
+ return 0;
}
uint8_t SimpleSpirit1::refresh_state(void) {
- uint8_t mcstate;
+ uint8_t mcstate;
- SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
+ SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
- return mcstate;
+ return mcstate;
}
int SimpleSpirit1::read(void *buf, unsigned int bufsize)
{
- disable_spirit_irq();
+ disable_spirit_irq();
- /* Checks if the RX buffer is empty */
- if(IS_RXBUF_EMPTY()) {
+ /* Checks if the RX buffer is empty */
+ if(IS_RXBUF_EMPTY()) {
#ifndef NDEBUG
- debug("\r\nBuffer is empty\r\n");
+ debug("\r\nBuffer is empty\r\n");
#endif
- set_ready_state();
+ set_ready_state();
- cmd_strobe(SPIRIT1_STROBE_RX);
- BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
- enable_spirit_irq();
- return 0;
- }
+ cmd_strobe(SPIRIT1_STROBE_RX);
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+ enable_spirit_irq();
+ return 0;
+ }
- if(bufsize < spirit_rx_len) {
- enable_spirit_irq();
+ if(bufsize < spirit_rx_len) {
+ enable_spirit_irq();
- /* If buf has the correct size */
+ /* If buf has the correct size */
#ifndef NDEBUG
- debug("\r\nTOO SMALL BUF\r\n");
+ debug("\r\nTOO SMALL BUF\r\n");
#endif
- return 0;
- } else {
- /* Copies the packet received */
- memcpy(buf, spirit_rx_buf, spirit_rx_len);
+ return 0;
+ } else {
+ /* Copies the packet received */
+ memcpy(buf, spirit_rx_buf, spirit_rx_len);
- bufsize = spirit_rx_len;
- CLEAR_RXBUF();
+ bufsize = spirit_rx_len;
+ CLEAR_RXBUF();
- enable_spirit_irq();
+ enable_spirit_irq();
- return bufsize;
- }
+ return bufsize;
+ }
}
int SimpleSpirit1::channel_clear(void)
{
- float rssi_value;
- /* Local variable used to memorize the SPIRIT1 state */
- uint8_t spirit_state = ON;
+ float rssi_value;
+ /* Local variable used to memorize the SPIRIT1 state */
+ uint8_t spirit_state = ON;
- if(spirit_on == OFF) {
- /* Wakes up the SPIRIT1 */
- on();
- spirit_state = OFF;
- }
+ if(spirit_on == OFF) {
+ /* Wakes up the SPIRIT1 */
+ on();
+ spirit_state = OFF;
+ }
#ifndef NDEBUG
- if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
- debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
- }
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+ debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
+ }
#endif
- disable_spirit_irq();
+ disable_spirit_irq();
- /* Reset State to Ready */
- set_ready_state();
+ /* Reset State to Ready */
+ set_ready_state();
- /* Stores the RSSI value */
- rssi_value = qi_get_rssi_dbm();
+ /* Stores the RSSI value */
+ rssi_value = qi_get_rssi_dbm();
- enable_spirit_irq();
+ enable_spirit_irq();
- /* Puts the SPIRIT1 in its previous state */
- if(spirit_state==OFF) {
- off();
+ /* Puts the SPIRIT1 in its previous state */
+ if(spirit_state==OFF) {
+ off();
#ifndef NDEBUG
#ifdef USE_STANDBY_STATE
- if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
#else
- if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
#endif
- debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
- }
+ debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
+ }
#endif
- } else {
- disable_spirit_irq();
+ } else {
+ disable_spirit_irq();
- set_ready_state();
+ set_ready_state();
- cmd_strobe(SPIRIT1_STROBE_RX);
- BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
- if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
- error("\r\nSpirit1: (#2) failed to enter rx (%x) => retry\r\n", last_state>>1);
- }
+ cmd_strobe(SPIRIT1_STROBE_RX);
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
+ error("\r\nSpirit1: (#2) failed to enter rx (%x) => retry\r\n", last_state>>1);
+ }
- enable_spirit_irq();
+ enable_spirit_irq();
#ifndef NDEBUG
- if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
- debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
- }
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+ debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1);
+ }
#endif
- }
+ }
- /* Checks the RSSI value with the threshold */
- if(rssi_value<CCA_THRESHOLD) {
- return 0;
- } else {
- return 1;
- }
-}
+ /* Checks the RSSI value with the threshold */
+ if(rssi_value<CCA_THRESHOLD) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
-int SimpleSpirit1::get_pending_packet(void)
-{
- return !IS_RXBUF_EMPTY();
-}
+ int SimpleSpirit1::get_pending_packet(void)
+ {
+ return !IS_RXBUF_EMPTY();
+ }
-/** Spirit Irq Callback **/
-/* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */
-void SimpleSpirit1::IrqHandler() {
- st_lib_spirit_irqs x_irq_status;
+ /** Spirit Irq Callback **/
+ /* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */
+ void SimpleSpirit1::IrqHandler() {
+ st_lib_spirit_irqs x_irq_status;
- /* get interrupt source from radio */
- irq_get_status(&x_irq_status);
+ /* get interrupt source from radio */
+ irq_get_status(&x_irq_status);
- /* The IRQ_TX_DATA_SENT notifies the packet has been sent. Puts the SPIRIT1 in RX */
- if(x_irq_status.IRQ_TX_DATA_SENT) { /* betzw - NOTE: MUST be handled before `IRQ_RX_DATA_READY` for Nanostack integration!
+ /* The IRQ_TX_DATA_SENT notifies the packet has been sent. Puts the SPIRIT1 in RX */
+ if(x_irq_status.IRQ_TX_DATA_SENT) { /* betzw - NOTE: MUST be handled before `IRQ_RX_DATA_READY` for Nanostack integration!
Logically, Nanostack only expects the "DONE" after "SUCCESS" (if it gets
DONE before SUCCESS, it assumes you're not going to bother to send SUCCESS).
- */
+ */
#ifdef DEBUG_IRQ
- uint32_t *tmp = (uint32_t*)&x_irq_status;
- debug_if(!_spirit_tx_started, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
- debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
- debug_if(tx_fifo_remaining != 0, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ debug_if(tx_fifo_remaining != 0, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
#endif
- tx_fifo_buffer = NULL;
- _spirit_tx_started = false;
+ if(_spirit_tx_started) {
+ _spirit_tx_started = false;
- /* call user callback */
- if(_current_irq_callback) {
- _current_irq_callback(TX_DONE);
- }
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(TX_DONE);
+ }
+ }
- /* Disable handling of other TX flags */
- x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET;
- }
+ /* Disable handling of other TX flags */
+ x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET;
+ tx_fifo_buffer = NULL;
+ }
#ifndef RX_FIFO_THR_WA
- /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
- if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
+ /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
+ if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
#ifdef DEBUG_IRQ
- uint32_t *tmp = (uint32_t*)&x_irq_status;
- debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
- debug_if(!_spirit_tx_started, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
- debug_if(tx_fifo_buffer == NULL, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ debug_if(!_spirit_tx_started, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ debug_if(tx_fifo_buffer == NULL, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
#endif
- int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
- int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
+ int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
+ int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
- tx_fifo_remaining -= to_send;
+ tx_fifo_remaining -= to_send;
- /* Fill FIFO Buffer */
- if(to_send > 0) {
- spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
- }
- tx_buffer_pos += to_send;
- }
+ /* Fill FIFO Buffer */
+ if(to_send > 0) {
+ spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
+ }
+ tx_buffer_pos += to_send;
+ }
#endif // !RX_FIFO_THR_WA
- /* TX FIFO underflow/overflow error */
- if(x_irq_status.IRQ_TX_FIFO_ERROR) {
+ /* TX FIFO underflow/overflow error */
+ if(x_irq_status.IRQ_TX_FIFO_ERROR) {
#ifdef DEBUG_IRQ
- uint32_t *tmp = (uint32_t*)&x_irq_status;
- debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
- debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
+ debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
#endif
- if(_spirit_tx_started) {
- _spirit_tx_started = false;
- /* call user callback */
- if(_current_irq_callback) {
- _current_irq_callback(TX_ERR);
- }
- }
+ if(_spirit_tx_started) {
+ _spirit_tx_started = false;
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(TX_ERR);
+ }
+ }
- /* reset data still to be sent */
- tx_fifo_remaining = 0;
- }
+ /* reset data still to be sent */
+ tx_fifo_remaining = 0;
+ }
- /* The IRQ_RX_DATA_READY notifies a new packet arrived */
- if(x_irq_status.IRQ_RX_DATA_READY) {
+ /* The IRQ_RX_DATA_READY notifies a new packet arrived */
+ if(x_irq_status.IRQ_RX_DATA_READY) {
#ifdef DEBUG_IRQ
- uint32_t *tmp = (uint32_t*)&x_irq_status;
- debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
#endif
- if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!)
+ if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!)
#ifdef HEAVY_DEBUG
- debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
+ debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
#endif
- } else {
- _is_receiving = false; // Finished receiving
- stop_rx_timeout();
+ } else {
+ _is_receiving = false; // Finished receiving
+ stop_rx_timeout();
- spirit_rx_len = pkt_basic_get_received_pkt_length();
+ spirit_rx_len = pkt_basic_get_received_pkt_length();
#ifdef DEBUG_IRQ
- debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
+ debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
#endif
- if(spirit_rx_len <= MAX_PACKET_LEN) {
- uint8_t to_receive = spirit_rx_len - _spirit_rx_pos;
- if(to_receive > 0) {
- spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]);
- _spirit_rx_pos += to_receive;
- }
- }
+ if(spirit_rx_len <= MAX_PACKET_LEN) {
+ uint8_t to_receive = spirit_rx_len - _spirit_rx_pos;
+ if(to_receive > 0) {
+ spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]);
+ _spirit_rx_pos += to_receive;
+ }
+ }
- cmd_strobe(SPIRIT1_STROBE_FRX);
+ cmd_strobe(SPIRIT1_STROBE_FRX);
- last_rssi = qi_get_rssi(); //MGR
- last_sqi = qi_get_sqi(); //MGR
+ last_rssi = qi_get_rssi(); //MGR
+ last_sqi = qi_get_sqi(); //MGR
- /* call user callback */
- if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) {
- _current_irq_callback(RX_DONE);
- }
+ /* call user callback */
+ if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) {
+ _current_irq_callback(RX_DONE);
+ }
- /* Disable handling of other RX flags */
- x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
- }
- }
+ /* Disable handling of other RX flags */
+ x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
+ }
+ }
#ifndef RX_FIFO_THR_WA
- /* RX FIFO almost full */
- if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) {
+ /* RX FIFO almost full */
+ if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) {
#ifdef DEBUG_IRQ
- uint32_t *tmp = (uint32_t*)&x_irq_status;
- debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
#endif
- if(!_is_receiving) { // spurious irq?!?
+ if(!_is_receiving) { // spurious irq?!?
#ifdef DEBUG_IRQ
- debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
+ debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
#endif
- } else {
- uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
- if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) {
- spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
- _spirit_rx_pos += fifo_available;
- } else {
+ } else {
+ uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
+ if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) {
+ spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
+ _spirit_rx_pos += fifo_available;
+ } else {
#ifdef DEBUG_IRQ
- debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
+ debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
#endif
- }
- }
- }
+ }
+ }
+ }
#endif // !RX_FIFO_THR_WA
- /* Reception errors */
- if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
+ /* Reception errors */
+ if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
#ifdef DEBUG_IRQ
- uint32_t *tmp = (uint32_t*)&x_irq_status;
- debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
- debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
+ debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
#endif
- rx_timeout_handler();
- if(_spirit_tx_started) {
- _spirit_tx_started = false;
- /* call user callback */
- if(_current_irq_callback) {
- _current_irq_callback(TX_ERR);
- }
- }
- }
+ rx_timeout_handler();
+ if(_spirit_tx_started) {
+ _spirit_tx_started = false;
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(TX_ERR);
+ }
+ }
+ }
- /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
- if(x_irq_status.IRQ_VALID_SYNC) {
+ /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
+ if(x_irq_status.IRQ_VALID_SYNC) {
#ifdef DEBUG_IRQ
- uint32_t *tmp = (uint32_t*)&x_irq_status;
- debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__);
#endif
- /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and
- * the MCU trying to send a packet, which gets resolved in favor of
- * sending.
- */
- if(_spirit_tx_started) {
+ /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and
+ * the MCU trying to send a packet, which gets resolved in favor of
+ * sending.
+ */
+ if(_spirit_tx_started) {
#ifdef DEBUG_IRQ
- debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
+ debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp);
#endif
- } else {
- _is_receiving = true;
- start_rx_timeout();
- }
- }
-}
+ } else {
+ _is_receiving = true;
+ start_rx_timeout();
+ }
+ }
+ }
