1 /*
2 FILE...: ldpc_dec.c
3 AUTHOR.: Matthew C. Valenti, Rohit Iyer Seshadri, David Rowe, Don Reid
4 CREATED: Sep 2016
5
6 Command line C LDPC decoder derived from MpDecode.c in the CML
7 library. Allows us to run the same decoder in Octave and C. The
8 code is defined by the parameters and array stored in the include
9 file below, which can be machine generated from the Octave function
10 ldpc_fsk_lib.m:ldpc_decode()
11
12 The include file also contains test input/output vectors for the LDPC
13 decoder for testing this program. If no input file "stm_in.raw" is found
14 then the built in test mode will run.
15
16 If there is an input is should be encoded data from the x86 ldpc_enc
17 program. Here is the suggested way to run:
18
19 ldpc_enc /dev/zero stm_in.raw --sd --code HRA_112_112 --testframes 6
20
21 ldpc_dec stm_in.raw ref_out.raw --sd --code HRA_112_112 --testframes
22
23 <Load stm32 and run>
24
25 cmp -l ref_out.raw stm_out.raw
26 << Check BER values in logs >>
27 */
28
29 #include <assert.h>
30 #include <errno.h>
31 #include <math.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37
38 #include "mpdecode_core.h"
39 #include "ofdm_internal.h"
40
41 #include "semihosting.h"
42 #include "stm32f4xx_conf.h"
43 #include "stm32f4xx.h"
44 #include "machdep.h"
45
46 /* generated by ldpc_fsk_lib.m:ldpc_decode() */
47 /* Machine generated consts, H_rows, H_cols, test input/output data to
48 change LDPC code regenerate this file. */
49
50 #include "HRA_112_112.h"
51
52 int testframes = 1;
53
54 static char fin_buffer[1024];
55 static __attribute__ ((section (".ccm"))) char fout_buffer[8*8192];
56
main(int argc,char * argv[])57 int main(int argc, char *argv[]) {
58 int CodeLength, NumberParityBits;
59 int i, parityCheckCount;
60 uint8_t out_data[HRA_112_112_CODELENGTH];
61 struct LDPC ldpc;
62 int data_bits_per_frame;
63 FILE *fout;
64 int iter, total_iters;
65 int Tbits, Terrs, Tbits_raw, Terrs_raw;
66
67 int nread, frame;
68
69 semihosting_init();
70
71 fprintf(stderr, "LDPC decode test and profile\n");
72
73 PROFILE_VAR(ldpc_decode);
74 machdep_profile_init();
75
76 ldpc.max_iter = HRA_112_112_MAX_ITER;
77 ldpc.dec_type = 0;
78 ldpc.q_scale_factor = 1;
79 ldpc.r_scale_factor = 1;
80 ldpc.CodeLength = HRA_112_112_CODELENGTH;
81 ldpc.NumberParityBits = HRA_112_112_NUMBERPARITYBITS;
82 ldpc.NumberRowsHcols = HRA_112_112_NUMBERROWSHCOLS;
83 ldpc.max_row_weight = HRA_112_112_MAX_ROW_WEIGHT;
84 ldpc.max_col_weight = HRA_112_112_MAX_COL_WEIGHT;
85 ldpc.H_rows = (uint16_t *)HRA_112_112_H_rows;
86 ldpc.H_cols = (uint16_t *)HRA_112_112_H_cols;
87
88 CodeLength = ldpc.CodeLength;
89 NumberParityBits = ldpc.NumberParityBits;
90 data_bits_per_frame = ldpc.NumberRowsHcols;
91 unsigned char ibits[data_bits_per_frame];
92 unsigned char pbits[NumberParityBits];
93
94 // // Allocate common space which can be shared with other functions.
95 // int size_common;
96 // uint8_t *common_array;
97
98 // ldpc_init(&ldpc, &size_common);
99 // fprintf(stderr, "ldpc needs %d bytes of shared memory\n", size_common);
100 // common_array = malloc(size_common);
101
102 testframes = 1;
103 total_iters = 0;
104
105 if (testframes) {
106 uint16_t r[data_bits_per_frame];
107 ofdm_rand(r, data_bits_per_frame);
108
109 for(i=0; i<data_bits_per_frame; i++) {
110 ibits[i] = r[i] > 16384;
111 }
112 encode(&ldpc, ibits, pbits);
113 Tbits = Terrs = Tbits_raw = Terrs_raw = 0;
114 }
115
116 FILE* fin = fopen("stm_in.raw", "rb");
117 if (fin == NULL) {
118 fprintf(stderr, "Error opening input file\n");
119 fflush(stderr);
120 exit(1);
121 }
122 setvbuf(fin, fin_buffer,_IOFBF,sizeof(fin_buffer));
123
124 fout = fopen("stm_out.raw", "wb");
125 if (fout == NULL) {
126 fprintf(stderr, "Error opening output file\n");
127 fflush(stderr);
128 exit(1);
129 }
130 setvbuf(fout, fout_buffer,_IOFBF,sizeof(fout_buffer));
131
132 float *input_float = calloc(CodeLength, sizeof(float));
133
134 nread = CodeLength;
135 fprintf(stderr, "CodeLength: %d\n", CodeLength);
136
137 frame = 0;
138 while(fread(input_float, sizeof(float) , nread, fin) == nread) {
139 fprintf(stderr, "frame %d\n", frame);
140
141 if (testframes) {
142 char in_char;
143 for (i=0; i<data_bits_per_frame; i++) {
144 in_char = input_float[i] < 0;
145 if (in_char != ibits[i]) {
146 Terrs_raw++;
147 }
148 Tbits_raw++;
149 }
150 for (i=0; i<NumberParityBits; i++) {
151 in_char = input_float[i+data_bits_per_frame] < 0;
152 if (in_char != pbits[i]) {
153 Terrs_raw++;
154 }
155 Tbits_raw++;
156 }
157 }
158 float llr[CodeLength];
159 sd_to_llr(llr, input_float, CodeLength);
160
161 PROFILE_SAMPLE(ldpc_decode);
162 iter = run_ldpc_decoder(&ldpc, out_data, llr, &parityCheckCount);
163 PROFILE_SAMPLE_AND_LOG2(ldpc_decode, "ldpc_decode");
164 //fprintf(stderr, "iter: %d\n", iter);
165 total_iters += iter;
166
167 fwrite(out_data, sizeof(char), data_bits_per_frame, fout);
168
169 if (testframes) {
170 for (i=0; i<data_bits_per_frame; i++) {
171 if (out_data[i] != ibits[i]) {
172 Terrs++;
173 //fprintf(stderr, "%d %d %d\n", i, out_data[i], ibits[i]);
174 }
175 Tbits++;
176 }
177 }
178
179 frame++;
180 }
181
182 fclose(fin);
183 fclose(fout);
184
185 fprintf(stderr, "total iters %d\n", total_iters);
186
187 if (testframes) {
188 fprintf(stderr, "Raw Tbits..: %d Terr: %d BER: %4.3f\n",
189 Tbits_raw, Terrs_raw, (double)(Terrs_raw/(Tbits_raw+1E-12)));
190 fprintf(stderr, "Coded Tbits: %d Terr: %d BER: %4.3f\n",
191 Tbits, Terrs, (double)(Terrs/(Tbits+1E-12)));
192 }
193
194 printf("\nStart Profile Data\n");
195 machdep_profile_print_logged_samples();
196 printf("End Profile Data\n");
197
198 fclose(stdout);
199 fclose(stderr);
200
201 return 0;
202 }
203
204 /* vi:set ts=4 et sts=4: */
205