altos: struct ao_log_mega doesn't have a ground temp value
[fw/altos] / src / core / ao_fec_tx.c
index c5f410b887ab7cc0b50ffea5df7ced23830c7bc5..4941d74581254ec26402218b9ed952cdbc03138b 100644 (file)
 #include <ao_fec.h>
 #include <stdio.h>
 
+#if AO_FEC_DEBUG
 void
-ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name)
+ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name)
 {
-       uint8_t i;
+       uint16_t        i;
 
        printf ("%s (%d):", name, len);
        for (i = 0; i < len; i++) {
@@ -31,67 +32,57 @@ ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name)
        }
        printf ("\n");
 }
-
-static uint16_t inline
-crc_byte(uint8_t byte, uint16_t crc)
-{
-       uint8_t bit;
-
-       for (bit = 0; bit < 8; bit++) {
-               if (((crc & 0x8000) >> 8) ^ (byte & 0x80))
-                       crc = (crc << 1) ^ 0x8005;
-               else
-                       crc = (crc << 1);
-               byte <<= 1;
-       }
-       return crc;
-}
+#endif
 
 uint16_t
-ao_fec_crc(uint8_t *bytes, uint8_t len)
+ao_fec_crc(const uint8_t *bytes, uint8_t len)
 {
        uint16_t        crc = AO_FEC_CRC_INIT;
 
        while (len--)
-               crc = crc_byte(*bytes++, crc);
+               crc = ao_fec_crc_byte(*bytes++, crc);
        return crc;
 }
 
+/*
+ * len is the length of the data; the crc will be
+ * the fist two bytes after that
+ */
+
 uint8_t
-ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out)
+ao_fec_check_crc(const uint8_t *bytes, uint8_t len)
+{
+       uint16_t        computed_crc = ao_fec_crc(bytes, len);
+       uint16_t        received_crc = (bytes[len] << 8) | (bytes[len+1]);
+
+       return computed_crc == received_crc;
+}
+
+/*
+ * Compute CRC and trellis-terminator/interleave-pad bytes
+ */
+static uint8_t
+ao_fec_prepare(const uint8_t *in, uint8_t len, uint8_t *extra)
 {
        uint16_t        crc = ao_fec_crc (in, len);
-       uint8_t         i;
+       uint8_t         i = 0;
        uint8_t         num_fec;
 
-       /* Copy data */
-       for (i = 0; i < len; i++)
-               out[i] = in[i];
-
        /* Append CRC */
-       out[i++] = crc >> 8;
-       out[i++] = crc;
+       extra[i++] = crc >> 8;
+       extra[i++] = crc;
 
        /* Append FEC -- 1 byte if odd, two bytes if even */
        num_fec = 2 - (i & 1);
        while (num_fec--)
-               out[i++] = AO_FEC_TRELLIS_TERMINATOR;
+               extra[i++] = AO_FEC_TRELLIS_TERMINATOR;
        return i;
 }
 
-static const uint8_t whiten[] = {
+const uint8_t ao_fec_whiten_table[] = {
 #include "ao_whiten.h"
 };
 
-void
-ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out)
-{
-       const uint8_t   *w = whiten;
-
-       while (len--)
-               *out++ = *in++ ^ *w++;
-}
-
 static const uint8_t ao_fec_encode_table[16] = {
 /* next 0  1     state */
        0, 3,   /* 000 */
@@ -105,40 +96,39 @@ static const uint8_t ao_fec_encode_table[16] = {
 };
 
 uint8_t
-ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out)
+ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out)
 {
-       uint16_t        fec = 0, output;
-       uint8_t         byte, bit;
-
-       for (byte = 0; byte < len; byte++) {
-               fec = (fec & 0x700) | in[byte];
-               output = 0;
-               for (bit = 0; bit < 8; bit++) {
-                       output = output << 2 | ao_fec_encode_table[fec >> 7];
-                       fec = (fec << 1) & 0x7ff;
+       uint8_t         extra[AO_FEC_PREPARE_EXTRA];
+       uint8_t         extra_len;
+       uint32_t        encode, interleave;
+       uint8_t         pair, byte, bit;
+       uint16_t        fec = 0;
+       const uint8_t   *whiten = ao_fec_whiten_table;
+
+       extra_len = ao_fec_prepare(in, len, extra);
+       for (pair = 0; pair < len + extra_len; pair += 2) {
+               encode = 0;
+               for (byte = 0; byte < 2; byte++) {
+                       if (pair + byte == len)
+                               in = extra;
+                       fec |= *in++ ^ *whiten++;
+                       for (bit = 0; bit < 8; bit++) {
+                               encode = encode << 2 | ao_fec_encode_table[fec >> 7];
+                               fec = (fec << 1) & 0x7ff;
+                       }
                }
-               out[byte * 2] = output >> 8;
-               out[byte * 2 + 1] = output;
-       }
-       return len * 2;
-}
-
-uint8_t
-ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out)
-{
-       uint8_t i, j;
 
-       for (i = 0; i < len; i += 4) {
-               uint32_t        interleaved = 0;
+               interleave = 0;
+               for (bit = 0; bit < 4 * 4; bit++) {
+                       uint8_t byte_shift = (bit & 0x3) << 3;
+                       uint8_t bit_shift = (bit & 0xc) >> 1;
 
-               for (j = 0; j < 4 * 4; j++) {
-                       interleaved <<= 2;
-                       interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03;
+                       interleave = (interleave << 2) | ((encode >> (byte_shift + bit_shift)) & 0x3);
                }
-               out[i+0] = interleaved >> 24;
-               out[i+1] = interleaved >> 16;
-               out[i+2] = interleaved >> 8;
-               out[i+3] = interleaved;
+               *out++ = interleave >> 24;
+               *out++ = interleave >> 16;
+               *out++ = interleave >> 8;
+               *out++ = interleave >> 0;
        }
-       return len;
+       return (len + extra_len) * 2;
 }