altos: Incremental viterbi decode
authorKeith Packard <keithp@keithp.com>
Mon, 25 Jun 2012 13:51:36 +0000 (06:51 -0700)
committerKeith Packard <keithp@keithp.com>
Mon, 25 Jun 2012 13:51:36 +0000 (06:51 -0700)
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>
src/core/ao_fec.h
src/core/ao_viterbi.c
src/drivers/ao_cc1120.c
src/test/ao_fec_test.c

index e3c55d6e240527a3390ebd799a15381005b350bf..4fd398eb8c9f121c32ec234a93ff51789456a447 100644 (file)
@@ -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.
index 7768155669847c62ebb77ad87968f904bc3dd917..69e9c1f5b7da393f9757e9b88b6448a1cf95b31d 100644 (file)
@@ -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.
                 */
index b42ca54c1fdabf74c9103eebca808f2a505ddbff..394cf7c53f1b95b18fdf00f35ee1b1649d155c6a 100644 (file)
@@ -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;
index 9806748606c32afbe9fd9bc71477ae8a510ce9f5..e8d3d8b194eb8095b4537461bc98deb69875b576 100644 (file)
@@ -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;