1 //
2 // fec_soft_example.c
3 //
4 // This example demonstrates the interface for forward error-correction
5 // (FEC) codes with soft-decision decoding. A buffer of data bytes is
6 // encoded before the data are corrupted with at least one error and
7 // noise. The decoder then attempts to recover the original data set
8 // from the soft input bits. The user may select the FEC scheme from
9 // the command-line interface.
10 //
11 // SEE ALSO: fec_example.c
12 // packetizer_soft_example.c
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <getopt.h>
18
19 #include "liquid.h"
20
21 // print usage/help message
usage()22 void usage()
23 {
24 printf("fecsoft_example [options]\n");
25 printf(" u/h : print usage\n");
26 printf(" v/q : verbose/queit (print soft bits?)\n");
27 printf(" n : input data size (number of uncoded bytes)\n");
28 printf(" c : coding scheme, (h74 default):\n");
29 liquid_print_fec_schemes();
30 }
31
32
main(int argc,char * argv[])33 int main(int argc, char*argv[])
34 {
35 // options
36 unsigned int n = 4; // data length (bytes)
37 unsigned int nmax = 2048; // maximum data length
38 fec_scheme fs = LIQUID_FEC_HAMMING74; // error-correcting scheme
39 int verbose = 1; // verbose?
40
41 int dopt;
42 while((dopt = getopt(argc,argv,"uhvqn:c:")) != EOF){
43 switch (dopt) {
44 case 'h':
45 case 'u': usage(); return 0;
46 case 'v': verbose = 1; break;
47 case 'q': verbose = 0; break;
48 case 'n': n = atoi(optarg); break;
49 case 'c':
50 fs = liquid_getopt_str2fec(optarg);
51 if (fs == LIQUID_FEC_UNKNOWN) {
52 fprintf(stderr,"error: unknown/unsupported fec scheme \"%s\"\n\n",optarg);
53 exit(1);
54 }
55 break;
56 default:
57 exit(1);
58 }
59 }
60
61 // ensure proper data length
62 n = (n > nmax) ? nmax : n;
63
64 // create arrays
65 unsigned int n_enc = fec_get_enc_msg_length(fs,n);
66 printf("dec msg len : %u\n", n);
67 printf("enc msg len : %u\n", n_enc);
68 unsigned char data[n]; // original data message
69 unsigned char msg_enc[n_enc]; // encoded data message
70 unsigned char msg_cor_soft[8*n_enc]; // corrupted data message (soft bits)
71 unsigned char msg_cor_hard[n_enc]; // corrupted data message (hard bits)
72 unsigned char msg_dec[n]; // decoded data message
73
74 // create object
75 fec q = fec_create(fs,NULL);
76 fec_print(q);
77
78 unsigned int i;
79
80 // create message
81 for (i=0; i<n; i++)
82 data[i] = rand() & 0xff;
83
84 // encode message
85 fec_encode(q, n, data, msg_enc);
86
87 // convert to soft bits and add 'noise'
88 for (i=0; i<n_enc; i++) {
89 msg_cor_soft[8*i+0] = (msg_enc[i] & 0x80) ? 255 : 0;
90 msg_cor_soft[8*i+1] = (msg_enc[i] & 0x40) ? 255 : 0;
91 msg_cor_soft[8*i+2] = (msg_enc[i] & 0x20) ? 255 : 0;
92 msg_cor_soft[8*i+3] = (msg_enc[i] & 0x10) ? 255 : 0;
93 msg_cor_soft[8*i+4] = (msg_enc[i] & 0x08) ? 255 : 0;
94 msg_cor_soft[8*i+5] = (msg_enc[i] & 0x04) ? 255 : 0;
95 msg_cor_soft[8*i+6] = (msg_enc[i] & 0x02) ? 255 : 0;
96 msg_cor_soft[8*i+7] = (msg_enc[i] & 0x01) ? 255 : 0;
97 }
98
99 // flip first bit (ensure error)
100 msg_cor_soft[0] = 255 - msg_cor_soft[0];
101
102 // add noise (but not so much that it would cause a bit error)
103 for (i=0; i<8*n_enc; i++) {
104 int soft_bit = 0.8*msg_cor_soft[i] + (int)(20*randnf());
105 if (soft_bit > 255) soft_bit = 255;
106 if (soft_bit < 0) soft_bit = 0;
107 msg_cor_soft[i] = soft_bit;
108 }
109
110 // convert to hard bits (printing purposes)
111 for (i=0; i<n_enc; i++) {
112 msg_cor_hard[i] = 0x00;
113
114 msg_cor_hard[i] |=(msg_cor_soft[8*i+0] >> 0) & 0x80;
115 msg_cor_hard[i] |=(msg_cor_soft[8*i+1] >> 1) & 0x40;
116 msg_cor_hard[i] |=(msg_cor_soft[8*i+2] >> 2) & 0x20;
117 msg_cor_hard[i] |=(msg_cor_soft[8*i+3] >> 3) & 0x10;
118 msg_cor_hard[i] |=(msg_cor_soft[8*i+4] >> 4) & 0x08;
119 msg_cor_hard[i] |=(msg_cor_soft[8*i+5] >> 5) & 0x04;
120 msg_cor_hard[i] |=(msg_cor_soft[8*i+6] >> 6) & 0x02;
121 msg_cor_hard[i] |=(msg_cor_soft[8*i+7] >> 7) & 0x01;
122 }
123
124 // decode message
125 fec_decode_soft(q, n, msg_cor_soft, msg_dec);
126
127 printf("original message: [%3u] ",n);
128 for (i=0; i<n; i++)
129 printf(" %.2X", (unsigned int) (data[i]));
130 printf("\n");
131
132 printf("encoded message: [%3u] ",n_enc);
133 for (i=0; i<n_enc; i++)
134 printf(" %.2X", (unsigned int) (msg_enc[i]));
135 printf("\n");
136
137 // print compact result
138 printf("corrupted message: [%3u] ",n_enc);
139 for (i=0; i<n_enc; i++)
140 printf("%c%.2X", msg_cor_hard[i]==msg_enc[i] ? ' ' : '*', (unsigned int) (msg_cor_hard[i]));
141 printf("\n");
142
143 if (verbose) {
144 // print expanded result (print each soft bit value)
145 for (i=0; i<n_enc; i++) {
146 printf("%5u: ", i);
147 unsigned int j;
148 for (j=0; j<8; j++) {
149 unsigned int bit_enc = (msg_enc[i] >> (8-j-1)) & 0x01;
150 unsigned int bit_rec = (msg_cor_soft[8*i+j] > 127) ? 1 : 0;
151 //printf("%1u %3u (%1u) %c", bit_enc, msg_cor_soft[i], bit_rec, bit_enc != bit_rec ? '*' : ' ');
152 printf("%4u%c", msg_cor_soft[8*i+j], bit_enc != bit_rec ? '*' : ' ');
153 }
154 printf(" : %c%.2X\n", msg_cor_hard[i]==msg_enc[i] ? ' ' : '*', (unsigned int) (msg_cor_hard[i]));
155 }
156 } // verbose
157
158 printf("decoded message: [%3u] ",n);
159 for (i=0; i<n; i++)
160 printf("%c%.2X", msg_dec[i] == data[i] ? ' ' : '*', (unsigned int) (msg_dec[i]));
161 printf("\n");
162 printf("\n");
163
164 // count bit errors
165 unsigned int j, num_sym_errors=0, num_bit_errors=0;
166 unsigned char e;
167 for (i=0; i<n; i++) {
168 num_sym_errors += (data[i] == msg_dec[i]) ? 0 : 1;
169
170 e = data[i] ^ msg_dec[i];
171 for (j=0; j<8; j++) {
172 num_bit_errors += e & 0x01;
173 e >>= 1;
174 }
175 }
176
177 //printf("number of symbol errors detected: %d\n", num_errors_detected);
178 printf("number of symbol errors received: %3u / %3u\n", num_sym_errors, n);
179 printf("number of bit errors received: %3u / %3u\n", num_bit_errors, n*8);
180
181 // clean up objects
182 fec_destroy(q);
183
184 return 0;
185 }
186
187