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.
25 #define RANDOM_MAX 0x7fffffff
30 return (double) random() / (double) RANDOM_MAX;
34 gaussian_random(double mean, double dev)
36 static int save_x_valid = 0;
48 double normal_x1, normal_x2;
51 normal_x1 = 2 * rand_real () - 1;
52 normal_x2 = 2 * rand_real () - 1;
53 w = normal_x1*normal_x1 + normal_x2*normal_x2;
54 } while (w >= 1 || w < 1E-30);
56 w = sqrt(log(w)*(-2./w));
59 * normal_x1 and normal_x2 are independent normally
60 * distributed variates
64 /* save normal_x2 for next call */
65 save_x = normal_x2 * w;
68 return x * dev + mean;
71 #define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA)
72 #define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2)
73 #define INTERLEAVE_LEN(input_len) ENCODE_LEN(input_len)
76 ao_encode(uint8_t *input, int input_len, uint8_t *output)
78 uint8_t prepare[PREPARE_LEN(input_len)];
79 uint8_t encode[ENCODE_LEN(input_len)];
80 uint8_t interleave[INTERLEAVE_LEN(input_len)];
83 uint8_t interleave_len;
85 ao_fec_dump_bytes(input, input_len, "Input");
87 prepare_len = ao_fec_prepare(input, input_len, prepare);
89 ao_fec_dump_bytes(prepare, prepare_len, "Prepare");
91 encode_len = ao_fec_encode(prepare, prepare_len, encode);
93 ao_fec_dump_bytes(encode, encode_len, "Encode");
95 interleave_len = ao_fec_interleave(encode, encode_len, output);
97 ao_fec_dump_bytes(output, interleave_len, "Interleave");
99 return interleave_len;
102 #define RADIO_LEN(input_len) (INTERLEAVE_LEN(input_len) * 8)
105 ao_radio(uint8_t *bits, int bits_len, uint8_t *bytes)
107 uint8_t b, *bytes_orig = bytes;
108 uint8_t interleave[bits_len];
111 ao_fec_interleave(bits, bits_len, interleave);
113 ao_fec_dump_bytes(interleave, bits_len, "De-interleave");
115 for (i = 0; i < bits_len; i++) {
117 for (bit = 7; bit >= 0; bit--)
118 *bytes++ = ((b >> bit) & 1) * 0xff;
121 ao_fec_dump_bytes(bytes_orig, bits_len * 8, "Bytes");
127 ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev)
132 for (i = 0; i < in_len; i++) {
133 double error = gaussian_random(0, dev);
134 uint8_t byte = in[i];
149 printf ("Introduced %d errors\n", errors);
150 ao_fec_dump_bytes(out, in_len, "Fuzz");
155 ao_decode(uint8_t *bytes, int bytes_len, uint8_t *bits)
159 bits_len = ao_fec_decode(bytes, bytes_len, bits);
161 ao_fec_dump_bytes(bits, bits_len, "Decode");
165 main(int argc, char **argv)
167 uint8_t original[4] = { 3, 1, 2, 3 };
168 uint8_t encode[INTERLEAVE_LEN(sizeof(original))];
171 uint8_t transmit[RADIO_LEN(sizeof(original))];
174 uint8_t receive[RADIO_LEN(sizeof(original))];
177 uint8_t decode[INTERLEAVE_LEN(sizeof(original))];
180 encode_len = ao_encode(original, sizeof(original), encode);
182 transmit_len = ao_radio(encode, encode_len, transmit);
184 /* apply gaussian noise to test viterbi code against errors */
185 receive_len = ao_fuzz(transmit, transmit_len, receive, 0x80);
187 decode_len = ao_decode(receive, receive_len, decode);