altos: decode cc1120 received packets
[fw/altos] / src / core / ao_viterbi.c
index 17464cd1df3fd94cbf3a80638e2d17890a9cd901..7768155669847c62ebb77ad87968f904bc3dd917 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;
 };
@@ -26,16 +55,19 @@ struct ao_soft_sym {
 #define NUM_HIST       8
 #define MOD_HIST(b)    ((b) & 7)
 
+#define V_0            0xc0
+#define V_1            0x40
+
 static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = {
 /* next        0              1                 state */
-       { { 0x00, 0x00 }, { 0xff, 0xff } } ,    /* 000 */
-       { { 0x00, 0xff }, { 0xff, 0x00 } },     /* 001 */
-       { { 0xff, 0xff }, { 0x00, 0x00 } },     /* 010 */
-       { { 0xff, 0x00 }, { 0x00, 0xff } },     /* 011 */
-       { { 0xff, 0xff }, { 0x00, 0x00 } },     /* 100 */
-       { { 0xff, 0x00 }, { 0x00, 0xff } },     /* 101 */
-       { { 0x00, 0x00 }, { 0xff, 0xff } },     /* 110 */
-       { { 0x00, 0xff }, { 0xff, 0x00 } }      /* 111 */
+       { { V_0, V_0 }, { V_1, V_1 } } ,        /* 000 */
+       { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */
+       { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */
+       { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */
+       { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */
+       { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */
+       { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */
+       { { V_0, V_1 }, { V_1, V_0 } }  /* 111 */
 };
 
 static inline uint8_t
@@ -59,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)
+ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len)
 {
        static uint16_t cost[2][NUM_STATE];             /* path cost */
        static uint16_t bits[2][NUM_STATE];             /* save bits to quickly output them */
@@ -70,6 +102,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 +117,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 +200,13 @@ 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;
+                       if (out_len) {
+                               *out++ = (bits[p][min_state] >> dist) ^ *whiten++;
+                               --out_len;
+                       }
                        o += 8;
                }
        }