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 ST

Files at this revision

API Documentation at this revision

Comitter:
Wolfgang Betz
Date:
Fri Nov 18 13:35:27 2016 +0100
Parent:
29:fe1b113f71d0
Child:
31:a4d8072139f2
Commit message:
Improve RX error handling

Changed in this revision

SimpleSpirit1.cpp Show annotated file Show diff for this revision Revisions of this file
SimpleSpirit1.h Show annotated file Show diff for this revision Revisions of this file
libs/Contiki_STM32_Library/spirit1-config.h Show annotated file Show diff for this revision Revisions of this file
mbed_driver_api.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/SimpleSpirit1.cpp	Thu Nov 17 08:26:41 2016 +0100
+++ b/SimpleSpirit1.cpp	Fri Nov 18 13:35:27 2016 +0100
@@ -63,7 +63,7 @@
 	/* init cube vars */
 	spirit_on = OFF;
 	last_rssi = 0 ; //MGR
-	last_lqi = 0 ;  //MGR
+	last_sqi = 0 ;  //MGR
 
 	/* set frequencies */
 	radio_set_xtal_freq(XTAL_FREQUENCY);
@@ -153,7 +153,7 @@
 	};
 	csma_ca_init(&x_csma_init);
 
-#ifdef RX_FIFO_THR_WA
+#ifdef RX_FIFO_THR_AO_CSMA_WA
 	linear_fifo_set_almost_full_thr_rx(SPIRIT_MAX_FIFO_LEN-(MAX_PACKET_LEN+1));
 #endif
 
@@ -189,8 +189,8 @@
 
 	pkt_basic_set_payload_length(payload_len); // set desired payload len
 
-#ifdef RX_FIFO_THR_WA
-	// betzw - TODO: seems to be incompatible with TX FIFO usage (to be investigated)
+#ifdef RX_FIFO_THR_AO_CSMA_WA
+	// betzw - TODO: enabling CSMA/CA seems to be incompatible with TX FIFO usage (to be investigated)
 	csma_ca_state(S_ENABLE); // enable CSMA/CA
 #endif
 
@@ -221,8 +221,8 @@
 	enable_spirit_irq();
 
 	BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
-#ifndef NDEBUG
-	// debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
+#ifdef HEAVY_DEBUG
+	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
@@ -237,9 +237,15 @@
 
 	disable_spirit_irq();
 
+	_spirit_tx_started = false;
 	_is_receiving = false;
+	_spirit_rx_err = false;
 	stop_rx_timeout();
 
+	cmd_strobe(SPIRIT1_STROBE_FRX);
+	CLEAR_RXBUF();
+	CLEAR_TXBUF();
+
 	state = SPIRIT1_STATUS();
 	if(state == SPIRIT1_STATE_STANDBY) {
 		cmd_strobe(SPIRIT1_STROBE_READY);
@@ -283,12 +289,6 @@
 
 		spirit_on = OFF;
 		_nr_of_irq_disables = 1;
-		_spirit_tx_started = false;
-		_is_receiving = false;
-		stop_rx_timeout();
-
-		CLEAR_TXBUF();
-		CLEAR_RXBUF();
 	}
 	return 0;
 }
@@ -305,12 +305,6 @@
 			error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1);
 		}
 
-		cmd_strobe(SPIRIT1_STROBE_FRX);
-		CLEAR_RXBUF();
-		_spirit_rx_err = false;
-		_is_receiving = false;
-		stop_rx_timeout();
-
 		/* Enables the mcu to get IRQ from the SPIRIT1 */
 		spirit_on = ON;
 #ifndef NDEBUG
@@ -342,15 +336,10 @@
 
 	/* Checks if the RX buffer is empty */
 	if(IS_RXBUF_EMPTY()) {
-		CLEAR_RXBUF();
 		set_ready_state();
 
-		cmd_strobe(SPIRIT1_STROBE_FRX);
 		cmd_strobe(SPIRIT1_STROBE_RX);
 		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
-		_spirit_rx_err = false;
-		_is_receiving = false;
-		stop_rx_timeout();
 		enable_spirit_irq();
 		return 0;
 	}
@@ -368,8 +357,6 @@
 		memcpy(buf, spirit_rx_buf, spirit_rx_len);
 
 		bufsize = spirit_rx_len;
-		_is_receiving = false;
-		stop_rx_timeout();
 		CLEAR_RXBUF();
 
 		enable_spirit_irq();
@@ -430,10 +417,6 @@
 			error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1);
 		}
 
-		CLEAR_RXBUF();
-		_spirit_rx_err = false;
-		_is_receiving = false;
-		stop_rx_timeout();
 		enable_spirit_irq();
 
 #ifndef NDEBUG
@@ -473,7 +456,6 @@
 		_is_receiving = false;
 		CLEAR_RXBUF();
 		cmd_strobe(SPIRIT1_STROBE_FRX);
-		stop_rx_timeout();
 		if(_spirit_tx_started) {
 			_spirit_tx_started = false;
 			CLEAR_TXBUF();
@@ -527,7 +509,6 @@
 			_is_receiving = false;
 			cmd_strobe(SPIRIT1_STROBE_FRX);
 			CLEAR_RXBUF();
-			stop_rx_timeout();
 		} else {
 			uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
 			unsigned int remaining = MAX_PACKET_LEN - _spirit_rx_pos;
@@ -536,7 +517,6 @@
 				_is_receiving = false;
 				CLEAR_RXBUF();
 				cmd_strobe(SPIRIT1_STROBE_FRX);
-				stop_rx_timeout();
 			} else {
 				spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
 				_spirit_rx_pos += fifo_available;
@@ -575,7 +555,7 @@
 			cmd_strobe(SPIRIT1_STROBE_FRX);
 
 			last_rssi = qi_get_rssi(); //MGR
-			last_lqi  = qi_get_lqi();  //MGR
+			last_sqi  = qi_get_sqi();  //MGR
 
 			/* call user callback */
 			if(_current_irq_callback) {
--- a/SimpleSpirit1.h	Thu Nov 17 08:26:41 2016 +0100
+++ b/SimpleSpirit1.h	Fri Nov 18 13:35:27 2016 +0100
@@ -74,12 +74,7 @@
 
     void rx_timeout_handler(void) {
     	set_ready_state();
-		cmd_strobe(SPIRIT1_STROBE_FRX);
 	    cmd_strobe(SPIRIT1_STROBE_RX);
-	    CLEAR_TXBUF();
-	    CLEAR_RXBUF();
-	    _spirit_rx_err = false;
-	    _spirit_tx_started = false;
 #ifndef NDEBUG
 	    debug("\n\r%s (%d)\n\r", __func__, __LINE__);
 #endif
@@ -110,7 +105,7 @@
     /** Status Variables from Cube Implementation **/
     unsigned int spirit_on;
     uint8_t last_rssi; //MGR
-    uint8_t last_lqi;  //MGR
+    uint8_t last_sqi;  //MGR
 
     /** Low Level Instance Variables **/
     unsigned int _nr_of_irq_disables;
@@ -259,8 +254,8 @@
     	return SpiritQiGetRssi();
     }
 
-    uint8_t qi_get_lqi() {
-    	return SpiritQiGetLqi();
+    uint8_t qi_get_sqi() {
+    	return SpiritQiGetSqi();
     }
 
     /** Timer Instance Methods **/
@@ -436,20 +431,29 @@
     	return _is_receiving;
     }
 
-    /** Get latest value of RSSI **/
+    /** Get latest value of RSSI (in dBm) **/
     float get_last_rssi_dbm(void) {
+    	get_last_rssi_raw();
+		return (-120.0+((float)(last_rssi-20))/2);
+    }
+
+    /** Get latest value of RSSI (as Spirit1 raw value) **/
+    uint8_t get_last_rssi_raw(void) {
     	if(last_rssi == 0) {
     		last_rssi = qi_get_rssi();
     	}
-    	return (-120.0+((float)(last_rssi-20))/2);
+    	return last_rssi;
     }
 
-    /** Get latest value of LQI **/
-    uint8_t get_last_lqi(void) {
-    	if(last_lqi == 0) {
-    		last_lqi = qi_get_lqi();
+    /** Get latest value of LQI (scaled to 8-bit) **/
+    uint8_t get_last_sqi(void) {
+    	const uint8_t max_sqi = 8 * ((SYNC_LENGTH>>1)+1);
+    	if(last_sqi == 0) {
+    		last_sqi = qi_get_sqi();
     	}
-    	return last_lqi;
+    	if(last_sqi > max_sqi) last_sqi = max_sqi;
+
+    	return (last_sqi * 255 / max_sqi);
     }
 
     /** Reset Board **/
--- a/libs/Contiki_STM32_Library/spirit1-config.h	Thu Nov 17 08:26:41 2016 +0100
+++ b/libs/Contiki_STM32_Library/spirit1-config.h	Fri Nov 18 13:35:27 2016 +0100
@@ -46,9 +46,10 @@
  * Freescale - which suffers from a not yet analyzed (HW) bug in delivering/receiving
  * further interrupts by/from Spirit after having reached the RX FIFO threshold and
  * elaborated the corresponding 'IRQ_RX_FIFO_ALMOST_FULL' interrupt.
+ * Furthermore, enable this macro if you want to use CSMA/CA.
  * NOTE: this enables just a workaround!!!
  */
-#define RX_FIFO_THR_WA
+#define RX_FIFO_THR_AO_CSMA_WA
 
 /**    
  * The MAX_PACKET_LEN is an arbitrary value used to define the two array
@@ -56,7 +57,7 @@
  * The SPIRIT1 supports with its packet handler a length of 65,535 bytes,
  * and in direct mode (without packet handler) there is no limit of data.
  */
-#ifdef RX_FIFO_THR_WA
+#ifdef RX_FIFO_THR_AO_CSMA_WA
 #define MAX_PACKET_LEN              (SPIRIT_MAX_FIFO_LEN-1)
 #else
 #define MAX_PACKET_LEN              (255) // betzw - WAS: SPIRIT_MAX_FIFO_LEN, but LEN_WIDTH is set to 7 so the variable payload length is from 0 to 255 bytes
--- a/mbed_driver_api.cpp	Thu Nov 17 08:26:41 2016 +0100
+++ b/mbed_driver_api.cpp	Fri Nov 18 13:35:27 2016 +0100
@@ -226,14 +226,14 @@
         case PHY_EXTENSION_READ_CHANNEL_ENERGY:
             // TODO: *data_ptr = rf_get_channel_energy();
         	tr_debug("%s (%d)", __func__, __LINE__);
-           	*data_ptr = rf_device->get_last_rssi_dbm();
+           	*data_ptr = (int8_t)rf_device->get_last_rssi_dbm();
             break;
 
         /*Read status of the link*/
         case PHY_EXTENSION_READ_LINK_STATUS:
             // TODO: *data_ptr = rf_get_link_status();
         	tr_debug("%s (%d)", __func__, __LINE__);
-        	*data_ptr = rf_device->get_last_lqi()*17;
+        	*data_ptr = rf_device->get_last_sqi(); // use SQI as link quality
             break;
 
         default:
@@ -559,7 +559,7 @@
 /* Note: we are in IRQ context */
 static inline void rf_handle_rx_end(void)
 {
-    uint8_t rf_lqi;
+    uint8_t rf_sqi;
     int8_t rf_rssi;
     uint16_t rf_buffer_len;
     uint8_t ack_requested = 0;
@@ -602,12 +602,10 @@
 
     /* Get link information */
     rf_rssi = (int8_t)rf_device->get_last_rssi_dbm();
-    rf_lqi = (uint8_t)rf_device->get_last_lqi();
-    rf_lqi *= 17; // scale to 8-bit value
+    rf_sqi = (uint8_t)rf_device->get_last_sqi(); // use SQI as link quality
 
     /* Note: Checksum of the packet must be checked and removed before entering here */
     /* TODO - betzw: what to do? */
-    // rf_buffer_len -= 2;
 
 #ifdef HEAVY_TRACING
       	tr_debug("%s (%d)", __func__, __LINE__);
@@ -615,7 +613,7 @@
 
         	/* Send received data and link information to the network stack */
     if( device_driver.phy_rx_cb ){
-        device_driver.phy_rx_cb(rf_rx_buf, rf_buffer_len, rf_lqi, rf_rssi, rf_radio_driver_id);
+        device_driver.phy_rx_cb(rf_rx_buf, rf_buffer_len, rf_sqi, rf_rssi, rf_radio_driver_id);
     }
 }
 
@@ -878,14 +876,13 @@
  */
 extern "C" int8_t rf_read_random(void)
 {
-	float tmp;
+	uint8_t ret;
 
 	rf_device->channel_clear();
-	tmp = rf_device->get_last_rssi_dbm();
-	tmp *= -10;
+	ret = rf_device->get_last_rssi_raw();
 
-	tr_debug("%s (%d): ret=%d", __func__, __LINE__, (uint8_t)tmp);
-    return (uint8_t)tmp;
+	tr_debug("%s (%d): ret=%d", __func__, __LINE__, ret);
+    return ret;
 }
 
 /*