From 09761fe0f6ed40ff74317fbb47d6a74068fb4ce4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 06:51:36 -0700 Subject: [PATCH] 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 --- src/core/ao_fec.h | 4 +++- src/core/ao_viterbi.c | 14 +++++++++++++- src/drivers/ao_cc1120.c | 28 +++++++++++++++++++++------- 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; -- 2.30.2