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