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:
Mon Nov 14 11:26:03 2016 +0100
Parent:
24:03e351bfc9c9
Child:
26:45dae8d48029
Commit message:
Enable the automatic RCO calibration

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
mbed_driver_api.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/SimpleSpirit1.cpp	Thu Nov 10 15:25:59 2016 +0100
+++ b/SimpleSpirit1.cpp	Mon Nov 14 11:26:03 2016 +0100
@@ -4,7 +4,7 @@
 
 #define SPIRIT_GPIO_IRQ			(SPIRIT_GPIO_3)
 
-#define SPIRIT1_STATUS()		(arch_refresh_status() & SPIRIT1_STATE_STATEBITS)
+#define SPIRIT1_STATUS()		(((uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS)
 
 #define BUSYWAIT_UNTIL(cond, millisecs)                                        					\
 		do {                                                                 					 		\
@@ -17,6 +17,7 @@
 
 #define st_lib_spirit_irqs		SpiritIrqs
 
+#define STATE_TIMEOUT           (1000)
 
 /*** Class Implementation ***/
 /** Static Class Variables **/
@@ -119,9 +120,8 @@
 	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);
 
-	/* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
-	cmd_strobe(SPIRIT1_STROBE_STANDBY);
 	spirit_on = OFF;
 	CLEAR_TXBUF();
 	CLEAR_RXBUF();
@@ -151,6 +151,9 @@
 #ifdef RX_FIFO_THR_WA
 	linear_fifo_set_almost_full_thr_rx(SPIRIT_MAX_FIFO_LEN-(MAX_PACKET_LEN+1));
 #endif
+
+	/* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
+	cmd_strobe(SPIRIT1_STROBE_STANDBY);
 }
 
 int SimpleSpirit1::send(const void *payload, unsigned int payload_len) {
@@ -159,12 +162,17 @@
 		return RADIO_TX_ERR;
 	}
 
+#ifndef NDEBUG
+	debug_if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX, "\n\rassert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1);
+#endif
+
 	disable_spirit_irq();
 
 	/* Reset State to Ready */
 	set_ready_state();
 
 	cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer
+
 #ifndef NDEBUG
 	debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__);
 #endif
@@ -200,9 +208,10 @@
 
 	enable_spirit_irq();
 
-	BUSYWAIT_UNTIL(SPIRIT1_STATUS() != SPIRIT1_STATE_TX, 50);
+	BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+
 #ifndef NDEBUG
-	// debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__);
+	debug_if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX, "\n\rassert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1);
 #endif
 
 	return RADIO_TX_OK;
@@ -210,16 +219,31 @@
 
 /** Set Ready State **/
 void SimpleSpirit1::set_ready_state(void) {
+	uint16_t state;
+
 	disable_spirit_irq();
 
 	_is_receiving = false;
 	stop_rx_timeout();
 
-	if(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY) {
+	state = SPIRIT1_STATUS();
+	if(state == SPIRIT1_STATE_STANDBY) {
 		cmd_strobe(SPIRIT1_STROBE_READY);
-	} else if(SPIRIT1_STATUS() == SPIRIT1_STATE_RX) {
+	} else if(state == SPIRIT1_STATE_RX) {
 		cmd_strobe(SPIRIT1_STROBE_SABORT);
+	} else if(state != SPIRIT1_STATE_READY) {
+#ifndef NDEBUG
+		debug("\n\rassert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, state>>1);
+#endif
 	}
+
+	BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, STATE_TIMEOUT);
+	if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
+		error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", SPIRIT1_STATUS()>>1);
+		enable_spirit_irq();
+		return;
+	}
+
 	irq_clear_status();
 
 	enable_spirit_irq();
@@ -231,26 +255,13 @@
 		disable_spirit_irq();
 
 		/* first stop rx/tx */
-		cmd_strobe(SPIRIT1_STROBE_SABORT);
-
-		/* Clear any pending irqs */
-		irq_clear_status();
-
-		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 3000);
-		if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
-#ifndef NDEBUG
-			debug("\n\rSpirit1: failed off->ready\n\r");
-#endif
-			return 1;
-		}
+		set_ready_state();
 
 		/* Puts the SPIRIT1 in STANDBY */
 		cmd_strobe(SPIRIT1_STROBE_STANDBY);
-		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, 3000);
+		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
 		if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
-#ifndef NDEBUG
-			debug("\n\rSpirit1: failed off->standby\n\r");
-#endif
+			error("\n\rSpirit1: failed to enter standby (%x)\n\r", SPIRIT1_STATUS()>>1);
 			return 1;
 		}
 
@@ -267,28 +278,18 @@
 }
 
 int SimpleSpirit1::on(void) {
-	cmd_strobe(SPIRIT1_STROBE_SABORT);
 	if(spirit_on == OFF) {
-		/* ensure we are in READY state as we go from there to Rx */
-		cmd_strobe(SPIRIT1_STROBE_READY);
-		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 3000);
-		if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
-#ifndef NDEBUG
-			debug("\n\rSpirit1: failed to turn on\n\r");
-#endif
-			return 1;
+		set_ready_state();
+
+		/* now we go to Rx */
+		cmd_strobe(SPIRIT1_STROBE_RX);
+
+		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+		if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+			error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", SPIRIT1_STATUS()>>1);
 		}
 
-		/* now we go to Rx */
 		cmd_strobe(SPIRIT1_STROBE_FRX);
-		cmd_strobe(SPIRIT1_STROBE_RX);
-		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 3000);
-		if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
-#ifndef NDEBUG
-			debug("\n\rSpirit1: failed to enter rx\n\r");
-#endif
-			return 1;
-		}
 		CLEAR_RXBUF();
 		_spirit_rx_err = false;
 		_is_receiving = false;
@@ -302,27 +303,17 @@
 		enable_spirit_irq();
 	}
 
+#ifndef NDEBUG
+	debug_if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX, "\n\rassert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1);
+#endif
+
 	return 0;
 }
 
-uint16_t SimpleSpirit1::arch_refresh_status(void) {
-	uint16_t mcstate;
-	uint8_t header[2];
-	header[0]=READ_HEADER;
-	header[1]=MC_STATE1_BASE;
-
-	/* Puts the SPI chip select low to start the transaction */
-	chip_sync_select();
+uint8_t SimpleSpirit1::refresh_state(void) {
+	uint8_t mcstate;
 
-	/* Write the aHeader bytes and read the SPIRIT1 status bytes */
-	mcstate = _spi.write(header[0]);
-	mcstate = mcstate<<8;
-
-	/* Write the aHeader bytes and read the SPIRIT1 status bytes */
-	mcstate |= _spi.write(header[1]);
-
-	/* Puts the SPI chip select high to end the transaction */
-	chip_sync_unselect();
+	SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
 
 	return mcstate;
 }
@@ -334,12 +325,11 @@
 	/* Checks if the RX buffer is empty */
 	if(IS_RXBUF_EMPTY()) {
 		CLEAR_RXBUF();
-		cmd_strobe(SPIRIT1_STROBE_SABORT);
-		cmd_strobe(SPIRIT1_STROBE_READY);
-		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_READY, 3000);
+		set_ready_state();
+
 		cmd_strobe(SPIRIT1_STROBE_FRX);
 		cmd_strobe(SPIRIT1_STROBE_RX);
-		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 3000);
+		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
 		_spirit_rx_err = false;
 		_is_receiving = false;
 		stop_rx_timeout();
@@ -383,23 +373,14 @@
 		spirit_state = OFF;
 	}
 
+#ifndef NDEBUG
+	debug_if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX, "\n\rassert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1);
+#endif
+
 	disable_spirit_irq();
 
 	/* Reset State to Ready */
 	set_ready_state();
-	{
-		uint32_t timeout = us_ticker_read() + 5000;
-		do {
-			mgmt_refresh_status();
-		} while((st_lib_g_x_status.MC_STATE != MC_STATE_READY) && (us_ticker_read() < timeout));
-		if(st_lib_g_x_status.MC_STATE != MC_STATE_READY) {
-			enable_spirit_irq();
-#ifndef NDEBUG
-			debug("\n\rSpirit1: channel clear failed\n\r");
-#endif
-			return 1;
-		}
-	}
 
 	/* Stores the RSSI value */
 	rssi_value = qi_get_rssi_dbm();
@@ -409,16 +390,29 @@
 	/* Puts the SPIRIT1 in its previous state */
 	if(spirit_state==OFF) {
 		off();
+#ifndef NDEBUG
+		debug_if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY, "\n\rassert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1);
+#endif
 	} else {
 		disable_spirit_irq();
-		cmd_strobe(SPIRIT1_STROBE_FRX);
+
+        set_ready_state();
+
 		cmd_strobe(SPIRIT1_STROBE_RX);
-		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, 10);
+		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+		if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+			error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", SPIRIT1_STATUS()>>1);
+		}
+
 		CLEAR_RXBUF();
 		_spirit_rx_err = false;
 		_is_receiving = false;
 		stop_rx_timeout();
 		enable_spirit_irq();
+
+#ifndef NDEBUG
+		debug_if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX, "\n\rassert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1);
+#endif
 	}
 
 	/* Checks the RSSI value with the threshold */
@@ -440,7 +434,6 @@
 
 	/* get interrupt source from radio */
 	irq_get_status(&x_irq_status);
-	// betzw - WAS: irq_clear_status(); BUT already cleared by get status!
 
 	/* Reception errors */
 	if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC) || (x_irq_status.IRQ_RX_TIMEOUT)) {
@@ -469,6 +462,7 @@
 #endif
 		csma_ca_state(S_DISABLE); // disable CSMA/CA
 		cmd_strobe(SPIRIT1_STROBE_FTX);
+		cmd_strobe(SPIRIT1_STROBE_RX);
 		if(_spirit_tx_started) {
 			_spirit_tx_started = false;
 			CLEAR_TXBUF();
@@ -548,18 +542,13 @@
 			cmd_strobe(SPIRIT1_STROBE_FRX);
 		} else {
 			spirit_rx_len = pkt_basic_get_received_pkt_length();
-			unsigned int remaining = 0;
-			// uint8_t fifo_available = 0; // betzw: optimized out in favor of a request less to SPIRIT device
-			uint8_t to_receive = 0;
 
 #ifndef NDEBUG
 			debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__);
 #endif
 
 			for(; _spirit_rx_pos < spirit_rx_len;) {
-				remaining = spirit_rx_len - _spirit_rx_pos;
-				// fifo_available = linear_fifo_read_num_elements_rx_fifo();  // betzw: optimized out in favor of a request less to SPIRIT device
-				to_receive = remaining; // betzw - WAS: (remaining < fifo_available) ? remaining : fifo_available;
+				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;
--- a/SimpleSpirit1.h	Thu Nov 10 15:25:59 2016 +0100
+++ b/SimpleSpirit1.h	Mon Nov 14 11:26:03 2016 +0100
@@ -134,11 +134,14 @@
     void chip_select() { _chip_select = 0; }
     void chip_unselect() { _chip_select = 1; }
 
-    void enter_shutdown() { _shut_down = 1; }
+    void enter_shutdown() {
+    	_shut_down = 1;
+    	wait_ms(5); // wait 5 milliseconds (to allow Spirit1 to shut down)
+    }
+
     void exit_shutdown() {
-    	wait_ms(2); // wait two milliseconds (to allow Spirit1 to shut down)
     	_shut_down = 0;
-    	wait_ms(10); // wait ten milliseconds (to allow Spirit1 a proper boot-up sequence)
+    	wait_ms(10); // wait 10 milliseconds (to allow Spirit1 a proper boot-up sequence)
     }
 
     void cs_to_sclk_delay(void) {
@@ -314,9 +317,14 @@
     	SpiritLinearFifoSetAlmostFullThresholdRx(cThrRxFifo);
     }
 
+    /** Calibration Instance Methods **/
+    void calibration_rco(SpiritFunctionalState xNewState) {
+    	SpiritCalibrationRco(xNewState);
+    }
+
     /** Internal Spirit Methods */
     void set_ready_state(void);
-    uint16_t arch_refresh_status(void);
+    uint8_t refresh_state(void);
 
     /** Friend Functions **/
     friend StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
@@ -345,7 +353,7 @@
     }
 
     /** Init Instance Method **/
-    void init(void);
+    void init();
 
     /** Spirit Irq Callback */
     void IrqHandler();
@@ -444,7 +452,7 @@
     }
 
     /** Reset Board **/
-    void reset_board(void) {
+    void reset_board() {
     	init();
     }
 };
--- a/mbed_driver_api.cpp	Thu Nov 10 15:25:59 2016 +0100
+++ b/mbed_driver_api.cpp	Mon Nov 14 11:26:03 2016 +0100
@@ -138,10 +138,12 @@
     	/*Store TX handle*/
     	mac_tx_handle = tx_handle;
 
-    	tr_debug("%s (%d), len=%d, tx_handle=%x, tx_seq=%x, need_ack=%d (%x:%x, %x:%x, %x:%x, %x:%x)", __func__, __LINE__,
+// #ifdef HEAVY_TRACING
+    	tr_info("%s (%d), len=%d, tx_handle=%x, tx_seq=%x, need_ack=%d (%x:%x, %x:%x, %x:%x, %x:%x)", __func__, __LINE__,
     			data_length, tx_handle, tx_sequence, need_ack,
     			data_ptr[3], data_ptr[4], data_ptr[5], data_ptr[6],
 				data_ptr[7], data_ptr[8], data_ptr[9], data_ptr[10]);
+// #endif
 
         /*Send the packet*/
         rf_device->send(data_ptr, data_length);
@@ -335,9 +337,9 @@
 	uint8_t src_addr_mode = 0x0; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
 	uint8_t min_size = 3; // FCF & SeqNr
 	bool ret = false;
-#if !defined(SHORT_ACK_FRAMES) || defined(HEAVY_TRACING)
+// #if !defined(SHORT_ACK_FRAMES) || defined(HEAVY_TRACING)
 	bool panid_compr = false;
-#endif
+// #endif
 
 	if(len < 3) {
     	tr_debug("%s (%d)", __func__, __LINE__);
@@ -353,10 +355,10 @@
 	panid_compr = ((fcf & MAC_FCF_INTRA_PANID_MASK) >> MAC_FCF_INTRA_PANID_SHIFT);
 #endif
 
-#ifdef HEAVY_TRACING
-	tr_debug("%s (%d): len=%d, ftype=%x, snr=%x, ack=%d, dst=%x, src=%x, intra=%d", __func__, __LINE__, len, frame_type,
+// #ifdef HEAVY_TRACING
+	tr_info("%s (%d): len=%d, ftype=%x, snr=%x, ack=%d, dst=%x, src=%x, intra=%d", __func__, __LINE__, len, frame_type,
 			rf_rx_buf[2], (*ack_requested), dst_addr_mode, src_addr_mode, panid_compr);
-#endif
+// #endif
 
 	if(frame_type == FC_ACK_FRAME) { // betzw: we support up to two different forms of ACK frames!
 #ifdef SHORT_ACK_FRAMES
@@ -542,7 +544,7 @@
 	}
 
 #ifdef HEAVY_TRACING
-	tr_debug("%s (%d), ret=%d, ack=%d", __func__, __LINE__, ret, (*ack_requested));
+	tr_info("%s (%d), ret=%d, ack=%d", __func__, __LINE__, ret, (*ack_requested));
 #endif
 	return ret;
 }
@@ -565,7 +567,11 @@
     if(!rf_buffer_len)
         return;
 
-    /* Check if packet should be accepted */
+#ifdef HEAVY_TRACING
+    	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+
+    	/* Check if packet should be accepted */
     if(!rf_check_destination(rf_buffer_len, &ack_requested)) {
 #ifdef HEAVY_TRACING
     	tr_debug("%s (%d)", __func__, __LINE__);