altos: improve FEC apis to reduce data copying
[fw/altos] / src / core / ao_viterbi.c
index 17464cd1df3fd94cbf3a80638e2d17890a9cd901..bb93bc83b798540782e928a8c5ac4e0bf448c0fb 100644 (file)
 #include <ao_fec.h>
 #include <stdio.h>
 
+/* 
+ * byte order repeats through 3 2 1 0
+ *     
+ * bit-pair order repeats through
+ *
+ *  1/0 3/2 5/4 7/6
+ *
+ * So, the over all order is:
+ *
+ *     3,1/0   2,1/0   1,1/0   0,1/0
+ *     3,3/2   2,3/2   1,3/2   0,3/2
+ *     3,5/4   2,5/4   1,5/4   0,5/4
+ *     3,7/6   2,7/6   1,7/6   0,7/6
+ *
+ * The raw bit order is thus
+ *
+ *     1e/1f   16/17   0e/0f   06/07
+ *     1c/1d   14/15   0c/0d   04/05
+ *     1a/1b   12/13   0a/0b   02/03
+ *     18/19   10/11   08/09   00/01
+ */
+
+static inline uint16_t ao_interleave_index(uint16_t i) {
+       uint8_t         l = i & 0x1e;
+       uint16_t        h = i & ~0x1e;
+       uint8_t         o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18));
+       return h | o;
+}
+
 struct ao_soft_sym {
        uint8_t a, b;
 };
@@ -70,6 +99,9 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out)
        uint8_t         n;                              /* next cost/bits index */
        uint8_t         state;                          /* state index */
        uint8_t         bit;                            /* original encoded bit index */
+       const uint8_t   *whiten = ao_fec_whiten_table;
+       uint16_t        interleave;                     /* input byte array index */
+       struct ao_soft_sym      s;                      /* input symbol pair */
 
        p = 0;
        for (state = 0; state < NUM_STATE; state++) {
@@ -82,7 +114,13 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out)
        for (i = 0; i < len; i += 2) {
                b = i/2;
                n = p ^ 1;
-               struct ao_soft_sym s = { .a = in[i], .b = in[i+1] };
+
+               /* Fetch one pair of input bytes, de-interleaving
+                * the input.
+                */
+               interleave = ao_interleave_index(i);
+               s.a = in[interleave];
+               s.b = in[interleave+1];
 
                /* Reset next costs to 'impossibly high' values so that
                 * the first path through this state is cheaper than this
@@ -159,10 +197,10 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out)
                        }
 
 #if 0
-                       printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n",
-                               i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff);
+                       printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n",
+                               i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten);
 #endif
-                       out[o >> 3] = bits[p][min_state] >> dist;
+                       *out++ = (bits[p][min_state] >> dist) ^ *whiten++;
                        o += 8;
                }
        }