diff options
| author | Keith Packard <keithp@keithp.com> | 2012-06-25 06:51:36 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2012-06-25 06:51:36 -0700 | 
| commit | 09761fe0f6ed40ff74317fbb47d6a74068fb4ce4 (patch) | |
| tree | 294de35ab62833f4f24bef66ca99c9736c017570 | |
| parent | 628076aa90e7bc9a894646e417dd8e1fe149b60d (diff) | |
altos: Incremental viterbi decode
Decode radio input one interleave block at a time. This overlaps the
decode computation with the packet reception, leading to lower latency
in an attempt to keep up with the transmitter.
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | src/core/ao_fec.h | 4 | ||||
| -rw-r--r-- | src/core/ao_viterbi.c | 14 | ||||
| -rw-r--r-- | src/drivers/ao_cc1120.c | 28 | ||||
| -rw-r--r-- | src/test/ao_fec_test.c | 4 | 
4 files changed, 39 insertions, 11 deletions
diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index e3c55d6e..4fd398eb 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -66,8 +66,10 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out);   * 'out' must be len/8 bytes long   */ +#define AO_FEC_DECODE_BLOCK	(8 * 32)	/* callback must return multiples of this many bits */ +  uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)());  /*   * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 77681556..69e9c1f5 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -91,7 +91,7 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b)   */  uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)())  {  	static uint16_t	cost[2][NUM_STATE];		/* path cost */  	static uint16_t	bits[2][NUM_STATE];		/* save bits to quickly output them */ @@ -105,6 +105,7 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len)  	const uint8_t	*whiten = ao_fec_whiten_table;  	uint16_t	interleave;			/* input byte array index */  	struct ao_soft_sym	s;			/* input symbol pair */ +	uint16_t	avail;  	p = 0;  	for (state = 0; state < NUM_STATE; state++) { @@ -113,11 +114,22 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len)  	}  	cost[0][0] = 0; +	if (callback) +		avail = 0; +	else +		avail = len; +  	o = 0;  	for (i = 0; i < len; i += 2) {  		b = i/2;  		n = p ^ 1; +		if (!avail) { +			avail = callback(); +			if (!avail) +				break; +		} +  		/* Fetch one pair of input bytes, de-interleaving  		 * the input.  		 */ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index b42ca54c..394cf7c5 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -400,6 +400,7 @@ ao_radio_send(void *d, uint8_t size)  static uint8_t	rx_data[2048];  static uint16_t	rx_data_count; +static uint16_t	rx_data_consumed;  static uint16_t rx_data_cur;  static uint8_t	rx_ignore; @@ -408,9 +409,9 @@ ao_radio_rx_isr(void)  {  	if (rx_ignore == 0) {  		rx_data[rx_data_cur++] = stm_spi2.dr; -		if (rx_data_cur >= rx_data_count) { +		if (rx_data_cur >= rx_data_count)  			ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); -			ao_radio_wake = 1; +		if (rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {  			ao_wakeup(&ao_radio_wake);  		}  	} else { @@ -420,6 +421,19 @@ ao_radio_rx_isr(void)  	stm_spi2.dr = 0x00;  } +static uint16_t +ao_radio_rx_wait(void) +{ +	cli(); +	while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && +	       !ao_radio_abort) +		ao_sleep(&ao_radio_wake); +	sei(); +	if (ao_radio_abort) +		return 0; +	return AO_FEC_DECODE_BLOCK; +} +  uint8_t  ao_radio_recv(__xdata void *d, uint8_t size)  { @@ -433,6 +447,7 @@ ao_radio_recv(__xdata void *d, uint8_t size)  	len *= 2;			/* 1/2 rate convolution */  	rx_data_count = len * 8;	/* bytes to bits */  	rx_data_cur = 0; +	rx_data_consumed = 0;  	rx_ignore = 2;  	printf ("len %d rx_data_count %d\n", len, rx_data_count); @@ -461,10 +476,9 @@ ao_radio_recv(__xdata void *d, uint8_t size)  	ao_radio_strobe(CC1120_SRX);  	ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); -	cli(); -	while (!ao_radio_wake && !ao_radio_abort) -		ao_sleep(&ao_radio_wake); -	sei(); + +	ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); +  	ao_radio_burst_read_stop();  	/* Convert from 'real' rssi to cc1111-style values */ @@ -477,7 +491,7 @@ ao_radio_recv(__xdata void *d, uint8_t size)  	/* Construct final packet */ -	ao_fec_decode(rx_data, rx_data_cur, d, size + 2); +	ao_fec_decode(rx_data, rx_data_cur, d, size + 2, 0);  	if (ao_fec_check_crc(d, size))  		((uint8_t *) d)[size + 1] = 0x80; diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 98067486..e8d3d8b1 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -266,7 +266,7 @@ ao_real_packet(void)  	int off;  	for (off = 0; off < sizeof (real_packet) - 576;  off++) { -		decode_len = ao_fec_decode(real_packet+off, 576, decode); +		decode_len = ao_fec_decode(real_packet+off, 576, decode, 34, NULL);  		if (ao_fec_check_crc(decode, 32)) {  			printf ("match at %d\n", off); @@ -317,7 +317,7 @@ main(int argc, char **argv)  		receive_len = transmit_len;  		/* Decode it */ -		decode_len = ao_fec_decode(receive, receive_len, decode); +		decode_len = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL);  		/* Check to see if we received the right data */  		error = 0;  | 
