2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name)
27 printf ("%s (%d):", name, len);
28 for (i = 0; i < len; i++) {
30 printf ("\n\t%02x:", i);
31 printf(" %02x", bytes[i]);
38 ao_fec_crc(const uint8_t *bytes, uint8_t len)
40 uint16_t crc = AO_FEC_CRC_INIT;
43 crc = ao_fec_crc_byte(*bytes++, crc);
48 * len is the length of the data; the crc will be
49 * the fist two bytes after that
53 ao_fec_check_crc(const uint8_t *bytes, uint8_t len)
55 uint16_t computed_crc = ao_fec_crc(bytes, len);
56 uint16_t received_crc = (bytes[len] << 8) | (bytes[len+1]);
58 return computed_crc == received_crc;
62 * Compute CRC and trellis-terminator/interleave-pad bytes
65 ao_fec_prepare(const uint8_t *in, uint8_t len, uint8_t *extra)
67 uint16_t crc = ao_fec_crc (in, len);
72 extra[i++] = crc >> 8;
75 /* Append FEC -- 1 byte if odd, two bytes if even */
76 num_fec = 2 - (i & 1);
78 extra[i++] = AO_FEC_TRELLIS_TERMINATOR;
82 const uint8_t ao_fec_whiten_table[] = {
83 #include "ao_whiten.h"
86 static const uint8_t ao_fec_encode_table[16] = {
99 ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out)
101 uint8_t extra[AO_FEC_PREPARE_EXTRA];
103 uint32_t encode, interleave;
104 uint8_t pair, byte, bit;
106 const uint8_t *whiten = ao_fec_whiten_table;
108 extra_len = ao_fec_prepare(in, len, extra);
109 for (pair = 0; pair < len + extra_len; pair += 2) {
111 for (byte = 0; byte < 2; byte++) {
112 if (pair + byte == len)
114 fec |= *in++ ^ *whiten++;
115 for (bit = 0; bit < 8; bit++) {
116 encode = encode << 2 | ao_fec_encode_table[fec >> 7];
117 fec = (fec << 1) & 0x7ff;
122 for (bit = 0; bit < 4 * 4; bit++) {
123 uint8_t byte_shift = (bit & 0x3) << 3;
124 uint8_t bit_shift = (bit & 0xc) >> 1;
126 interleave = (interleave << 2) | ((encode >> (byte_shift + bit_shift)) & 0x3);
128 *out++ = interleave >> 24;
129 *out++ = interleave >> 16;
130 *out++ = interleave >> 8;
131 *out++ = interleave >> 0;
133 return (len + extra_len) * 2;