diff options
Diffstat (limited to 'src/core/ao_fec_tx.c')
| -rw-r--r-- | src/core/ao_fec_tx.c | 118 | 
1 files changed, 76 insertions, 42 deletions
diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index c5f410b8..c9c0a3d6 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -19,9 +19,9 @@  #include <stdio.h>  void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name)  { -	uint8_t	i; +	uint16_t	i;  	printf ("%s (%d):", name, len);  	for (i = 0; i < len; i++) { @@ -57,41 +57,76 @@ ao_fec_crc(uint8_t *bytes, uint8_t len)  	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(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; +} + +uint8_t +ao_fec_prepare(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"  }; +#if 0  void  ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out)  { -	const uint8_t	*w = whiten; +	const uint8_t	*w = ao_fec_whiten_table;  	while (len--)  		*out++ = *in++ ^ *w++;  } +/* + * Unused as interleaving is now built in to ao_fec_encode + */ + +static void +ao_fec_interleave(uint8_t *d, uint8_t len) +{ +	uint8_t	i, j; + +	for (i = 0; i < len; i += 4) { +		uint32_t	interleaved = 0; + +		for (j = 0; j < 4 * 4; j++) { +			interleaved <<= 2; +			interleaved |= (d[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; +		} +		d[i+0] = interleaved >> 24; +		d[i+1] = interleaved >> 16; +		d[i+2] = interleaved >> 8; +		d[i+3] = interleaved; +	} +} +#endif +  static const uint8_t ao_fec_encode_table[16] = {  /* next 0  1	  state */  	0, 3,	/* 000 */ @@ -107,38 +142,37 @@ static const uint8_t ao_fec_encode_table[16] = {  uint8_t  ao_fec_encode(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;  }  | 
