diff options
| -rw-r--r-- | src/ao.h | 31 | ||||
| -rw-r--r-- | src/ao_config.c | 2 | ||||
| -rw-r--r-- | src/ao_dma.c | 4 | ||||
| -rw-r--r-- | src/ao_monitor.c | 6 | ||||
| -rw-r--r-- | src/ao_packet.c | 98 | ||||
| -rw-r--r-- | src/ao_packet_master.c | 5 | ||||
| -rw-r--r-- | src/ao_packet_slave.c | 7 | ||||
| -rw-r--r-- | src/ao_radio.c | 68 | ||||
| -rw-r--r-- | src/ao_telemetry.c | 2 | 
9 files changed, 109 insertions, 114 deletions
@@ -391,14 +391,10 @@ ao_cmd_init(void);   * ao_dma.c   */ -/* Allocate a DMA channel. the 'done' parameter will be set - * when the dma is finished or aborted and will be used to - * wakeup any waiters +/* Allocate a DMA channel. the 'done' parameter will be set when the + * dma is finished and will be used to wakeup any waiters   */ -#define AO_DMA_DONE	1 -#define AO_DMA_ABORTED	2 -  uint8_t  ao_dma_alloc(__xdata uint8_t * done); @@ -838,6 +834,15 @@ struct ao_telemetry {  	struct ao_gps_tracking_data	gps_tracking;  }; +/* + * ao_radio_recv tacks on rssi and status bytes + */ +struct ao_telemetry_recv { +	struct ao_telemetry	telemetry; +	int8_t			rssi; +	uint8_t			status; +}; +  /* Set delay between telemetry reports (0 to disable) */  #define AO_TELEMETRY_INTERVAL_PAD	AO_MS_TO_TICKS(1000) @@ -880,22 +885,16 @@ void  ao_radio_set_rdf(void);  void -ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant; - -struct ao_radio_recv { -	struct ao_telemetry	telemetry; -	int8_t			rssi; -	uint8_t			status; -}; +ao_radio_send(__xdata void *data, uint8_t size) __reentrant;  uint8_t -ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; +ao_radio_recv(__xdata void *data, uint8_t size) __reentrant;  void -ao_radio_rdf(int ms); +ao_radio_recv_abort(void);  void -ao_radio_abort(void); +ao_radio_rdf(int ms);  void  ao_radio_rdf_abort(void); diff --git a/src/ao_config.c b/src/ao_config.c index 88b52dc0..fd33e2cc 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -141,7 +141,7 @@ ao_config_radio_channel_set(void) __reentrant  	ao_config_dirty = 1;  	ao_mutex_put(&ao_config_mutex);  	ao_config_radio_channel_show(); -	ao_radio_abort(); +	ao_radio_recv_abort();  }  #if HAS_ADC diff --git a/src/ao_dma.c b/src/ao_dma.c index 946666ab..6052964a 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -107,8 +107,6 @@ ao_dma_abort(uint8_t id)  	uint8_t	mask = (1 << id);  	DMAARM = 0x80 | mask;  	DMAIRQ &= ~mask; -	*(ao_dma_done[id]) |= AO_DMA_ABORTED; -	ao_wakeup(ao_dma_done[id]);  }  void @@ -124,7 +122,7 @@ ao_dma_isr(void) __interrupt 8  			DMAIF = 0;  			/* Clear the completed ID */  			DMAIRQ = ~mask; -			*(ao_dma_done[id]) |= AO_DMA_DONE; +			*(ao_dma_done[id]) = 1;  			ao_wakeup(ao_dma_done[id]);  			break;  		} diff --git a/src/ao_monitor.c b/src/ao_monitor.c index f019d3b4..1e7f5102 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -23,7 +23,7 @@ __pdata uint8_t ao_monitor_led;  void  ao_monitor(void)  { -	__xdata struct ao_radio_recv recv; +	__xdata struct ao_telemetry_recv recv;  	__xdata char callsign[AO_MAX_CALLSIGN+1];  	uint8_t state;  	int16_t rssi; @@ -31,7 +31,7 @@ ao_monitor(void)  	for (;;) {  		__critical while (!ao_monitoring)  			ao_sleep(&ao_monitoring); -		if (!ao_radio_recv(&recv)) +		if (!ao_radio_recv(&recv, sizeof (recv)))  			continue;  		state = recv.telemetry.flight_state; @@ -85,7 +85,7 @@ ao_set_monitor(uint8_t monitoring)  	ao_monitoring = monitoring;  	ao_wakeup(&ao_monitoring);  	if (!ao_monitoring) -		ao_radio_abort(); +		ao_radio_recv_abort();  }  static void diff --git a/src/ao_packet.c b/src/ao_packet.c index d52f2a68..9896149c 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -33,8 +33,6 @@ void  ao_packet_send(void)  {  	ao_led_on(AO_LED_RED); -	ao_radio_get(); -  	/* If any tx data is pending then copy it into the tx packet */  	if (ao_packet_tx_used && ao_tx_packet.len == 0) {  		memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); @@ -43,22 +41,7 @@ ao_packet_send(void)  		ao_packet_tx_used = 0;  		ao_wakeup(&tx_data);  	} -	ao_radio_done = 0; -	ao_dma_set_transfer(ao_radio_dma, -			    &ao_tx_packet, -			    &RFDXADDR, -			    sizeof (struct ao_packet), -			    DMA_CFG0_WORDSIZE_8 | -			    DMA_CFG0_TMODE_SINGLE | -			    DMA_CFG0_TRIGGER_RADIO, -			    DMA_CFG1_SRCINC_1 | -			    DMA_CFG1_DESTINC_0 | -			    DMA_CFG1_PRIORITY_HIGH); -	ao_dma_start(ao_radio_dma); -	RFST = RFST_STX; -	__critical while (!ao_radio_done) -		ao_sleep(&ao_radio_done); -	ao_radio_put(); +	ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet));  	ao_led_off(AO_LED_RED);  } @@ -70,51 +53,56 @@ ao_packet_recv(void)  #ifdef AO_LED_GREEN  	ao_led_on(AO_LED_GREEN);  #endif -	ao_radio_get(); -	ao_dma_set_transfer(ao_radio_dma, -			    &RFDXADDR, -			    &ao_rx_packet, -			    sizeof (struct ao_packet_recv), -			    DMA_CFG0_WORDSIZE_8 | -			    DMA_CFG0_TMODE_SINGLE | -			    DMA_CFG0_TRIGGER_RADIO, -			    DMA_CFG1_SRCINC_0 | -			    DMA_CFG1_DESTINC_1 | -			    DMA_CFG1_PRIORITY_HIGH); -	ao_dma_start(ao_radio_dma); -	RFST = RFST_SRX; -	__critical while (!ao_radio_dma_done) -			   if (ao_sleep(&ao_radio_dma_done) != 0) -				   ao_radio_abort(); -	dma_done = ao_radio_dma_done; -	ao_radio_put(); +	dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv));  #ifdef AO_LED_GREEN  	ao_led_off(AO_LED_GREEN);  #endif -	if (dma_done & AO_DMA_DONE) { -		if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) -			return AO_DMA_ABORTED; -		if (ao_rx_packet.packet.len == AO_PACKET_SYN) { +	/* Check to see if we got a valid packet */ +	if (!dma_done) +		return 0; +	if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) +		return 0; + +	/* SYN packets carry no data */ +	if (ao_rx_packet.packet.len == AO_PACKET_SYN) { +		rx_seq = ao_rx_packet.packet.seq; +		ao_tx_packet.seq = ao_rx_packet.packet.ack; +		ao_tx_packet.ack = rx_seq; +	} else if (ao_rx_packet.packet.len) { + +		/* Check for incoming data at the next sequence and +		 * for an empty data buffer +		 */ +		if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && +		    ao_packet_rx_used == ao_packet_rx_len) { + +			/* Copy data to the receive data buffer and set up the +			 * offsets +			 */ +			memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); +			ao_packet_rx_used = 0; +			ao_packet_rx_len = ao_rx_packet.packet.len; + +			/* Mark the sequence that we've received to +			 * let the sender know when we return a packet +			 */  			rx_seq = ao_rx_packet.packet.seq; -			ao_tx_packet.seq = ao_rx_packet.packet.ack;  			ao_tx_packet.ack = rx_seq; -		} else if (ao_rx_packet.packet.len) { -			if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && ao_packet_rx_used == ao_packet_rx_len) { -				memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); -				ao_packet_rx_used = 0; -				ao_packet_rx_len = ao_rx_packet.packet.len; -				rx_seq = ao_rx_packet.packet.seq; -				ao_tx_packet.ack = rx_seq; -				ao_wakeup(&ao_stdin_ready); -			} -		} -		if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { -			ao_tx_packet.len = 0; -			ao_wakeup(&ao_tx_packet); + +			/* Poke anyone looking for received data */ +			ao_wakeup(&ao_stdin_ready);  		}  	} -	return dma_done; + +	/* If the other side has seen the latest data we queued, +	 * wake up any task waiting to send data and let them go again +	 */ +	if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { +		ao_tx_packet.len = 0; +		ao_wakeup(&ao_tx_packet); +	} +	return 1;  }  #ifndef PACKET_HAS_MASTER diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 641b49f4..3b23ad92 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -77,8 +77,6 @@ ao_packet_master_check_busy(void)  void  ao_packet_master(void)  { -	uint8_t	status; -  	ao_config_get();  	ao_radio_set_packet();  	ao_tx_packet.addr = ao_serial_number; @@ -92,8 +90,7 @@ ao_packet_master(void)  			ao_packet_master_busy();  		ao_packet_master_check_busy();  		ao_alarm(ao_packet_master_delay); -		status = ao_packet_recv(); -		if (status & AO_DMA_DONE) { +		if (ao_packet_recv()) {  			/* if we can transmit data, do so */  			if (ao_packet_tx_used && ao_tx_packet.len == 0)  				continue; diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 9b78767f..3040d781 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -20,14 +20,11 @@  void  ao_packet_slave(void)  { -	uint8_t	status; -  	ao_radio_set_packet();  	ao_tx_packet.addr = ao_serial_number;  	ao_tx_packet.len = AO_PACKET_SYN;  	while (ao_packet_enable) { -		status = ao_packet_recv(); -		if (status & AO_DMA_DONE) { +		if (ao_packet_recv()) {  			memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);  			ao_packet_send();  		} @@ -47,7 +44,7 @@ ao_packet_slave_stop(void)  {  	if (ao_packet_enable) {  		ao_packet_enable = 0; -		ao_radio_abort(); +		ao_radio_recv_abort();  		while (ao_packet_task.wchan) {  			ao_wake_task(&ao_packet_task);  			ao_yield(); diff --git a/src/ao_radio.c b/src/ao_radio.c index cafa7010..362b73aa 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -272,6 +272,7 @@ static __code uint8_t packet_setup[] = {  __xdata uint8_t	ao_radio_dma;  __xdata uint8_t ao_radio_dma_done;  __xdata uint8_t ao_radio_done; +__xdata uint8_t ao_radio_abort;  __xdata uint8_t ao_radio_mutex;  void @@ -279,7 +280,7 @@ ao_radio_general_isr(void) __interrupt 16  {  	S1CON &= ~0x03;  	if (RFIF & RFIF_IM_TIMEOUT) { -		ao_dma_abort(ao_radio_dma); +		ao_radio_recv_abort();  		RFIF &= ~ RFIF_IM_TIMEOUT;  	} else if (RFIF & RFIF_IM_DONE) {  		ao_radio_done = 1; @@ -338,14 +339,14 @@ ao_radio_get(void)  void -ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant +ao_radio_send(__xdata void *packet, uint8_t size) __reentrant  {  	ao_radio_get();  	ao_radio_done = 0;  	ao_dma_set_transfer(ao_radio_dma, -			    telemetry, +			    packet,  			    &RFDXADDR, -			    sizeof (struct ao_telemetry), +			    size,  			    DMA_CFG0_WORDSIZE_8 |  			    DMA_CFG0_TMODE_SINGLE |  			    DMA_CFG0_TRIGGER_RADIO, @@ -360,13 +361,14 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant  }  uint8_t -ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant +ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant  { +	ao_radio_abort = 0;  	ao_radio_get();  	ao_dma_set_transfer(ao_radio_dma,  			    &RFDXADDR, -			    radio, -			    sizeof (struct ao_radio_recv), +			    packet, +			    size,  			    DMA_CFG0_WORDSIZE_8 |  			    DMA_CFG0_TMODE_SINGLE |  			    DMA_CFG0_TRIGGER_RADIO, @@ -375,13 +377,32 @@ ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant  			    DMA_CFG1_PRIORITY_HIGH);  	ao_dma_start(ao_radio_dma);  	RFST = RFST_SRX; -	__critical while (!ao_radio_dma_done) -		ao_sleep(&ao_radio_dma_done); +	__critical while (!ao_radio_dma_done && !ao_radio_abort) +			   ao_sleep(&ao_radio_dma_done); + +	/* If recv was aborted, clean up by stopping the DMA engine +	 * and idling the radio +	 */ +	if (!ao_radio_dma_done) { +		ao_dma_abort(ao_radio_dma); +		ao_radio_idle(); +	}  	ao_radio_put(); -	return (ao_radio_dma_done & AO_DMA_DONE); +	return ao_radio_dma_done; +} + +/* + * Wake up a task waiting to receive a radio packet + * and tell them to abort the transfer + */ + +void +ao_radio_recv_abort(void) +{ +	ao_radio_abort = 1; +	ao_wakeup(&ao_radio_dma_done);  } -__xdata ao_radio_rdf_running;  __xdata ao_radio_rdf_value = 0x55;  void @@ -390,8 +411,9 @@ ao_radio_rdf(int ms)  	uint8_t i;  	uint8_t pkt_len; +	ao_radio_abort = 0;  	ao_radio_get(); -	ao_radio_rdf_running = 1; +	ao_radio_done = 0;  	for (i = 0; i < sizeof (rdf_setup); i += 2)  		RF[rdf_setup[i]] = rdf_setup[i+1]; @@ -419,28 +441,22 @@ ao_radio_rdf(int ms)  			    DMA_CFG1_PRIORITY_HIGH);  	ao_dma_start(ao_radio_dma);  	RFST = RFST_STX; - -	__critical while (!ao_radio_dma_done) -		ao_sleep(&ao_radio_dma_done); -	ao_radio_rdf_running = 0; -	ao_radio_idle(); +	__critical while (!ao_radio_done && !ao_radio_abort) +			   ao_sleep(&ao_radio_done); +	if (!ao_radio_done) { +		ao_dma_abort(ao_radio_dma); +		ao_radio_idle(); +	}  	for (i = 0; i < sizeof (telemetry_setup); i += 2)  		RF[telemetry_setup[i]] = telemetry_setup[i+1];  	ao_radio_put();  }  void -ao_radio_abort(void) -{ -	ao_dma_abort(ao_radio_dma); -	ao_radio_idle(); -} - -void  ao_radio_rdf_abort(void)  { -	if (ao_radio_rdf_running) -		ao_radio_abort(); +	ao_radio_abort = 1; +	ao_wakeup(&ao_radio_done);  } diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 88ac142c..277c3ce0 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -52,7 +52,7 @@ ao_telemetry(void)  		memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data));  		memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data));  		ao_mutex_put(&ao_gps_mutex); -		ao_radio_send(&telemetry); +		ao_radio_send(&telemetry, sizeof (telemetry));  		ao_delay(ao_telemetry_interval);  		if (ao_rdf &&  		    (int16_t) (ao_time() - ao_rdf_time) >= 0)  | 
