1 //
2 // sandbox/fecsoft_conv_test.c
3 //
4 // This script simulates soft vs. hard decoding of convolutional codes.
5 //
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <math.h>
10 #include <complex.h>
11 #include <time.h>
12 #include <getopt.h>
13 
14 #include "liquid.internal.h"
15 
16 #define OUTPUT_FILENAME "fecsoft_conv_test.m"
17 
usage()18 void usage()
19 {
20     printf("fecsoft_conv_test\n");
21     printf("  Simulates soft decoding of convoluational codes\n");
22     printf("options:\n");
23     printf("  u/h   : print usage/help\n");
24     printf("  s     : SNR start [dB], default: -5\n");
25     printf("  x     : SNR max [dB], default: 5\n");
26     printf("  n     : number of SNR steps, default: 21\n");
27     printf("  t     : number of trials, default: 1000\n");
28     printf("  c     : convoluational coding scheme: v27, v29, v39, v615, punctured\n");
29 }
30 
main(int argc,char * argv[])31 int main(int argc, char *argv[]) {
32     // set initial seed to random
33     srand(time(NULL));
34 
35     // options
36     fec_scheme fs = LIQUID_FEC_CONV_V27;    // convolutional FEC scheme
37     unsigned int n = 64;                    // original message length
38     float SNRdB_min = -5.0f;                // signal-to-noise ratio (minimum)
39     float SNRdB_max =  5.0f;                // signal-to-noise ratio (maximum)
40     unsigned int num_snr = 21;              // number of SNR steps
41     unsigned int num_trials=100;            // number of trials
42 
43     // get command-line options
44     int dopt;
45     while((dopt = getopt(argc,argv,"uhs:x:n:t:c:")) != EOF){
46         switch (dopt) {
47         case 'h':
48         case 'u': usage(); return 0;
49         case 's': SNRdB_min = atof(optarg);     break;
50         case 'x': SNRdB_max = atof(optarg);     break;
51         case 'n': num_snr = atoi(optarg);       break;
52         case 't': num_trials = atoi(optarg);    break;
53         case 'c':
54             fs = liquid_getopt_str2fec(optarg);
55             if (fs == LIQUID_FEC_UNKNOWN ) {
56                 fprintf(stderr,"error: %s, unknown/unsupported fec scheme \"%s\"\n\n",argv[0], optarg);
57                 exit(1);
58             } else if ( !fec_scheme_is_convolutional(fs) ) {
59                 fprintf(stderr,"error: %s, input fec scheme '%s' is not convolutional\n\n",argv[0], optarg);
60                 exit(1);
61             }
62             break;
63         default:
64             exit(1);
65         }
66     }
67 
68     unsigned int i;
69 
70     // derived values
71     unsigned int k = fec_get_enc_msg_length(fs, n);   // encoded message length
72 
73     // create forward error-correction object
74     fec q = fec_create(fs, NULL);
75     fec_print(q);
76 
77     //
78     // data arrays
79     //
80 #if 0
81     unsigned int sym_org;       // original symbol
82     float complex sym_enc[7];   // encoded symbol
83     float complex sym_rec[7];   // received symbol
84 #endif
85     unsigned char msg_org[n];           // original message
86     unsigned char msg_enc[k];           // encoded message
87     float complex mod_sym[8*k];         // modulated symbols
88     unsigned char msg_rec_soft[8*k];    // received 'soft' bits
89     unsigned char msg_rec_hard[8*k];    // received 'hard' bits
90     unsigned char msg_dec_soft[n];      // soft-decision decoding
91     unsigned char msg_dec_hard[n];      // hard-decision decoding
92 
93     unsigned int bit_errors_soft[num_snr];
94     unsigned int bit_errors_hard[num_snr];
95 
96     //
97     // set up parameters
98     //
99     float SNRdB_step = (SNRdB_max - SNRdB_min) / (num_snr-1);
100 
101     //
102     // start trials
103     //
104 #if 0
105     // test
106     sym_org = 13;
107     fecsoft_hamming74_encode(sym_org, sym_enc);
108     fecsoft_hamming74_decode(sym_enc, &sym_dec_soft);
109     exit(1);
110 #endif
111 
112     printf("  %8s [%6s] %6s %6s\n", "SNR [dB]", "trials", "soft", "hard");
113     unsigned int s;
114     for (s=0; s<num_snr; s++) {
115         // compute SNR for this level
116         float SNRdB = SNRdB_min + s*SNRdB_step;
117         float nstd = powf(10.0f, -SNRdB/20.0f);
118 
119         // reset results
120         bit_errors_soft[s] = 0;
121         bit_errors_hard[s] = 0;
122 
123         unsigned int t;
124         for (t=0; t<num_trials; t++) {
125 
126             // generate data
127             for (i=0; i<n; i++)
128                 msg_org[i] = rand() & 0xff;
129 
130             // encode
131             if ( fec_scheme_is_punctured(fs) ) {
132                 fec_conv_punctured_encode(q, n, msg_org, msg_enc);
133             } else {
134                 fec_conv_encode(q, n, msg_org, msg_enc);
135             }
136 
137             // expand and modulate (BPSK)
138             for (i=0; i<k; i++) {
139                 mod_sym[8*i+0] = ((msg_enc[i] >> 7) & 0x01) ? 1.0f : -1.0f;
140                 mod_sym[8*i+1] = ((msg_enc[i] >> 6) & 0x01) ? 1.0f : -1.0f;
141                 mod_sym[8*i+2] = ((msg_enc[i] >> 5) & 0x01) ? 1.0f : -1.0f;
142                 mod_sym[8*i+3] = ((msg_enc[i] >> 4) & 0x01) ? 1.0f : -1.0f;
143                 mod_sym[8*i+4] = ((msg_enc[i] >> 3) & 0x01) ? 1.0f : -1.0f;
144                 mod_sym[8*i+5] = ((msg_enc[i] >> 2) & 0x01) ? 1.0f : -1.0f;
145                 mod_sym[8*i+6] = ((msg_enc[i] >> 1) & 0x01) ? 1.0f : -1.0f;
146                 mod_sym[8*i+7] = ((msg_enc[i]     ) & 0x01) ? 1.0f : -1.0f;
147             }
148 
149             // add noise
150             for (i=0; i<8*k; i++)
151                 mod_sym[i] += nstd*randnf()*cexpf(_Complex_I*2*M_PI*randf());
152 
153             // 'demodulate' hard/soft
154             for (i=0; i<8*k; i++) {
155                 // hard decision
156                 msg_rec_hard[i] = ( crealf(mod_sym[i]) > 0.0f ) ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0;
157 
158                 // soft decision
159 #if 0
160                 float soft_bit = (255*( 0.5f + 0.5f*tanhf(crealf(mod_sym[i])) ));
161                 if (soft_bit < 0)        msg_rec_soft[i] = 0;
162                 else if (soft_bit > 255) msg_rec_soft[i] = 255;
163                 else                     msg_rec_soft[i] = (unsigned char) soft_bit;
164 #else
165                 msg_rec_soft[i] = (unsigned char)(255*( 0.5f + 0.5f*tanhf(crealf(mod_sym[i])) ));
166 #endif
167 
168                 //printf("  hard : %3u, soft : %3u\n", msg_rec_hard[i], msg_rec_soft[i]);
169             }
170 
171             // decode using 'soft' algorithm
172             if ( fec_scheme_is_punctured(fs) ) {
173                 fec_conv_punctured_decode_soft(q, n, msg_rec_hard, msg_dec_hard);
174                 fec_conv_punctured_decode_soft(q, n, msg_rec_soft, msg_dec_soft);
175             } else {
176                 fec_conv_decode_soft(q, n, msg_rec_hard, msg_dec_hard);
177                 fec_conv_decode_soft(q, n, msg_rec_soft, msg_dec_soft);
178             }
179 
180             // count bit errors and tabulate results
181             bit_errors_hard[s] += count_bit_errors_array(msg_org, msg_dec_hard, n);
182             bit_errors_soft[s] += count_bit_errors_array(msg_org, msg_dec_soft, n);
183         }
184 
185         // print results for this SNR step
186         printf("  %8.3f [%6u] %6u %6u\n",
187                 SNRdB,
188                 8*n*num_trials,
189                 bit_errors_soft[s],
190                 bit_errors_hard[s]);
191     }
192 
193     // destroy forward error-correction object
194     fec_destroy(q);
195 
196 
197     //
198     // export output file
199     //
200     FILE * fid = fopen(OUTPUT_FILENAME, "w");
201     fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
202     fprintf(fid,"\n\n");
203     fprintf(fid,"clear all\n");
204     fprintf(fid,"close all\n");
205     fprintf(fid,"n = %u;\n", n);
206     fprintf(fid,"k = %u;\n", k);
207     fprintf(fid,"num_trials = %u;\n", num_trials);
208     fprintf(fid,"total_bits = %u;\n", 8*n*num_trials);
209     fprintf(fid,"num_snr = %u;\n", num_snr);
210     fprintf(fid,"num_trials = %u;\n", num_trials);
211     for (i=0; i<num_snr; i++) {
212         fprintf(fid,"SNRdB(%4u) = %12.8f;\n",i+1, SNRdB_min + i*SNRdB_step);
213         fprintf(fid,"bit_errors_soft(%6u) = %u;\n", i+1, bit_errors_soft[i]);
214         fprintf(fid,"bit_errors_hard(%6u) = %u;\n", i+1, bit_errors_hard[i]);
215     }
216     fprintf(fid,"\n\n");
217     fprintf(fid,"figure;\n");
218     fprintf(fid,"semilogy(SNRdB, bit_errors_soft / total_bits + 1e-12,\n");
219     fprintf(fid,"         SNRdB, bit_errors_hard / total_bits + 1e-12);\n");
220     fprintf(fid,"axis([%f %f 1e-4 1]);\n", SNRdB_min, SNRdB_max);
221     fprintf(fid,"legend('soft','hard',1);\n");
222     fprintf(fid,"xlabel('SNR [dB]');\n");
223     fprintf(fid,"ylabel('Bit Error Rate');\n");
224     fprintf(fid,"title('Bit error rate for %s');\n", fec_scheme_str[fs][1]);
225     fprintf(fid,"grid on;\n");
226 
227     fclose(fid);
228     printf("results written to %s\n", OUTPUT_FILENAME);
229 
230     printf("done.\n");
231     return 0;
232 }
233 
234 #if !LIBFEC_ENABLED
235 //
236 // libfec is not installed; need to define internal methods used in this
237 // program, even though they don't do anything
238 //
fec_conv_encode(fec _q,unsigned int _dec_msg_len,unsigned char * _msg_dec,unsigned char * _msg_enc)239 void fec_conv_encode(fec _q,
240                      unsigned int _dec_msg_len,
241                      unsigned char * _msg_dec,
242                      unsigned char * _msg_enc)
243 {
244     printf("fec_conv_encode(): libfec not installed; this sandbox program won't run\n");
245 }
246 
fec_conv_decode_soft(fec _q,unsigned int _dec_msg_len,unsigned char * _msg_enc,unsigned char * _msg_dec)247 void fec_conv_decode_soft(fec _q,
248                           unsigned int _dec_msg_len,
249                           unsigned char * _msg_enc,
250                           unsigned char * _msg_dec)
251 {
252     printf("fec_conv_decode_soft(): libfec not installed; this sandbox program won't run\n");
253 }
254 
fec_conv_punctured_decode_soft(fec _q,unsigned int _dec_msg_len,unsigned char * _msg_enc,unsigned char * _msg_dec)255 void fec_conv_punctured_decode_soft(fec _q,
256                                     unsigned int _dec_msg_len,
257                                     unsigned char * _msg_enc,
258                                     unsigned char * _msg_dec)
259 {
260     printf("fec_conv_punctured_decode_soft(): libfec not installed; this sandbox program won't run\n");
261 }
262 #endif
263 
264