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
Diff: SimpleSpirit1.cpp
- Revision:
- 28:6a71e15d5272
- Parent:
- 27:e68ffb6ac223
- Child:
- 29:fe1b113f71d0
--- a/SimpleSpirit1.cpp Tue Nov 15 12:07:07 2016 +0100
+++ b/SimpleSpirit1.cpp Thu Nov 17 08:24:29 2016 +0100
@@ -5,7 +5,9 @@
#define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_3)
static uint16_t last_state;
-#define SPIRIT1_STATUS() (last_state = (((uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS))
+#define SPIRIT1_STATUS() ((last_state = (uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS)
+
+#define XO_ON (0x1)
#define BUSYWAIT_UNTIL(cond, millisecs) \
do { \
@@ -13,13 +15,16 @@
while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U)); \
} while(0)
-extern volatile SpiritStatus g_xStatus;
-#define st_lib_g_x_status (g_xStatus)
-
#define st_lib_spirit_irqs SpiritIrqs
#define STATE_TIMEOUT (1000)
+// betzw: switching force & back from standby seems to be unstable
+// #define USE_STANDBY_STATE
+
+// betzw: enable beyond macro if you want debug messages also from IRQ handler
+#define DEBUG_IRQ
+
/*** Class Implementation ***/
/** Static Class Variables **/
SimpleSpirit1 *SimpleSpirit1::_singleton = NULL;
@@ -112,16 +117,17 @@
irq_set_status(RX_FIFO_ALMOST_FULL, S_ENABLE);
irq_set_status(VALID_SYNC, S_ENABLE);
irq_set_status(MAX_BO_CCA_REACH, S_ENABLE);
+ irq_set_status(READY, S_ENABLE); // betzw: gets never trigger ... WHY??? (to be investigated)
/* Configure Spirit1 */
- radio_persisten_rx(S_ENABLE);
+ 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);
+ calibration_rco(S_ENABLE); // betzw: test
spirit_on = OFF;
CLEAR_TXBUF();
@@ -140,7 +146,7 @@
/* Setup CSMA/CA */
CsmaInit x_csma_init = {
- S_DISABLE, // no persistent mode
+ S_ENABLE, // enable persistent mode // betzw: test
TBIT_TIME_64, // Tcca time
TCCA_TIME_3, // Lcca length
3, // max nr of backoffs (<8)
@@ -153,8 +159,10 @@
linear_fifo_set_almost_full_thr_rx(SPIRIT_MAX_FIFO_LEN-(MAX_PACKET_LEN+1));
#endif
+#ifdef USE_STANDBY_STATE
/* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
cmd_strobe(SPIRIT1_STROBE_STANDBY);
+#endif // USE_STANDBY_STATE
}
int SimpleSpirit1::send(const void *payload, unsigned int payload_len) {
@@ -163,14 +171,15 @@
return RADIO_TX_ERR;
}
+ disable_spirit_irq();
+
+ BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
#ifndef NDEBUG
- if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
}
#endif
- disable_spirit_irq();
-
/* Reset State to Ready */
set_ready_state();
@@ -187,11 +196,10 @@
csma_ca_state(S_ENABLE); // enable CSMA/CA
#endif
- cmd_strobe(SPIRIT1_STROBE_TX);
-
int i = 0;
int remaining = payload_len;
const uint8_t *buffer = (const uint8_t*)payload;
+ bool tx_triggered = false;
do {
uint8_t fifo_available = SPIRIT_MAX_FIFO_LEN - linear_fifo_read_num_elements_tx_fifo();
uint8_t to_send = (remaining > fifo_available) ? fifo_available : remaining;
@@ -201,6 +209,11 @@
spi_write_linear_fifo(to_send, (uint8_t*)&buffer[i]);
}
+ if(!tx_triggered) {
+ cmd_strobe(SPIRIT1_STROBE_TX);
+ tx_triggered = true;
+ }
+
i += to_send;
remaining -= to_send;
} while(remaining != 0);
@@ -209,14 +222,14 @@
enable_spirit_irq();
- BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
-
+ BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
#ifndef NDEBUG
- if(last_state != SPIRIT1_STATE_RX) {
- debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
- }
+ // debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
#endif
+ csma_ca_state(S_DISABLE); // disable CSMA/CA
+ cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
+
return RADIO_TX_OK;
}
@@ -240,9 +253,9 @@
#endif
}
- BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, STATE_TIMEOUT);
- if(last_state != SPIRIT1_STATE_READY) {
- error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state>>1);
+ BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
+ if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
+ error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state);
enable_spirit_irq();
return;
}
@@ -260,13 +273,15 @@
/* 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_STANDBY) {
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
error("\n\rSpirit1: failed to enter standby (%x)\n\r", last_state>>1);
return 1;
}
+#endif // USE_STANDBY_STATE
spirit_on = OFF;
_nr_of_irq_disables = 1;
@@ -288,7 +303,7 @@
cmd_strobe(SPIRIT1_STROBE_RX);
BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
- if(last_state != SPIRIT1_STATE_RX) {
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1);
}
@@ -398,7 +413,11 @@
if(spirit_state==OFF) {
off();
#ifndef NDEBUG
+#ifdef USE_STANDBY_STATE
if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
+#else
+ if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
+#endif
debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
}
#endif
@@ -409,7 +428,7 @@
cmd_strobe(SPIRIT1_STROBE_RX);
BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
- if(last_state != SPIRIT1_STATE_RX) {
+ if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1);
}
@@ -446,10 +465,20 @@
/* get interrupt source from radio */
irq_get_status(&x_irq_status);
+ /* Have become ready */
+ if(x_irq_status.IRQ_READY) { // betzw: gets never trigger ... WHY??? (to be investigated)
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug("\n\r%s (%d): irq=%x", __func__, __LINE__, *tmp);
+#endif
+ cmd_strobe(SPIRIT1_STROBE_RX);
+ }
+
/* Reception errors */
if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
-#ifndef NDEBUG
- debug("\n\r%s (%d)", __func__, __LINE__);
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug("\n\r%s (%d): irq=%x", __func__, __LINE__, *tmp);
#endif
_spirit_rx_err = true;
_is_receiving = false;
@@ -468,12 +497,13 @@
/* Transmission error */
if(x_irq_status.IRQ_TX_FIFO_ERROR) {
-#ifndef NDEBUG
- debug("\n\r%s (%d)", __func__, __LINE__);
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug("\n\r%s (%d): irq=%x", __func__, __LINE__, *tmp);
#endif
csma_ca_state(S_DISABLE); // disable CSMA/CA
cmd_strobe(SPIRIT1_STROBE_FTX);
- cmd_strobe(SPIRIT1_STROBE_RX);
+ // cmd_strobe(SPIRIT1_STROBE_SABORT); // betzw: we do not know in which state we are (most likely it's a not stable state)!
if(_spirit_tx_started) {
_spirit_tx_started = false;
CLEAR_TXBUF();
@@ -484,30 +514,17 @@
}
}
- /* The IRQ_VALID_SYNC is used to notify a new packet is coming */
- if(x_irq_status.IRQ_VALID_SYNC) {
- _is_receiving = true;
- _spirit_rx_err = false;
- CLEAR_RXBUF();
-#ifndef NDEBUG
- debug_if(_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
-#endif
- start_rx_timeout();
- }
-
/* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
if(x_irq_status.IRQ_TX_DATA_SENT) {
-#ifndef NDEBUG
+#ifdef DEBUG_IRQ
debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
#endif
- csma_ca_state(S_DISABLE); // disable CSMA/CA
- cmd_strobe(SPIRIT1_STROBE_FRX);
- cmd_strobe(SPIRIT1_STROBE_RX);
+ _spirit_rx_err = false;
+ _spirit_tx_started = false;
+ // cmd_strobe(SPIRIT1_STROBE_RX); // data-sheet says that we will return to READY state automatically (furthermore we are in a not stable state)!
CLEAR_TXBUF();
CLEAR_RXBUF();
- _spirit_rx_err = false;
- _spirit_tx_started = false;
/* call user callback */
if(_current_irq_callback) {
@@ -554,7 +571,7 @@
} else {
spirit_rx_len = pkt_basic_get_received_pkt_length();
-#ifndef NDEBUG
+#ifdef DEBUG_IRQ
debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
#endif
@@ -580,21 +597,32 @@
/* Max number of back-off during CCA */
if(x_irq_status.IRQ_MAX_BO_CCA_REACH) {
-#ifndef NDEBUG
- debug("\n\r%s (%d)", __func__, __LINE__);
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug("\n\r%s (%d): irq=%x", __func__, __LINE__, *tmp);
#endif
+
+ _spirit_rx_err = false;
+ _spirit_tx_started = false;
csma_ca_state(S_DISABLE); // disable CSMA/CA
- cmd_strobe(SPIRIT1_STROBE_FRX);
- cmd_strobe(SPIRIT1_STROBE_RX);
+ // cmd_strobe(SPIRIT1_STROBE_RX); // data-sheet says that we will return to READY state automatically!
CLEAR_TXBUF();
CLEAR_RXBUF();
- _spirit_rx_err = false;
- _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) {
+ _is_receiving = true;
+ _spirit_rx_err = false;
+ CLEAR_RXBUF();
+#ifdef DEBUG_IRQ
+ debug_if(_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+ start_rx_timeout();
}
}
