1 /*
2 * Copyright (c) 2007 - 2015 Joseph Gaeddert
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 //
24 // convolutional code (macros)
25 //
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <assert.h>
30
31 #include "liquid.internal.h"
32
33 #define VERBOSE_FEC_CONV 0
34
35 #if LIBFEC_ENABLED
36 #include "fec.h"
37
fec_conv_create(fec_scheme _fs)38 fec fec_conv_create(fec_scheme _fs)
39 {
40 fec q = (fec) malloc(sizeof(struct fec_s));
41
42 q->scheme = _fs;
43 q->rate = fec_get_rate(q->scheme);
44
45 q->encode_func = &fec_conv_encode;
46 q->decode_func = &fec_conv_decode_hard; // default to hard-decision decoding
47 q->decode_soft_func = &fec_conv_decode_soft;
48
49 switch (q->scheme) {
50 case LIQUID_FEC_CONV_V27: fec_conv_init_v27(q); break;
51 case LIQUID_FEC_CONV_V29: fec_conv_init_v29(q); break;
52 case LIQUID_FEC_CONV_V39: fec_conv_init_v39(q); break;
53 case LIQUID_FEC_CONV_V615: fec_conv_init_v615(q); break;
54 default:
55 fprintf(stderr,"error: fec_conv_create(), invalid type\n");
56 exit(1);
57 }
58
59 // convolutional-specific decoding
60 q->num_dec_bytes = 0;
61 q->enc_bits = NULL;
62 q->vp = NULL;
63
64 return q;
65 }
66
fec_conv_destroy(fec _q)67 void fec_conv_destroy(fec _q)
68 {
69 // delete viterbi decoder
70 if (_q->vp != NULL)
71 _q->delete_viterbi(_q->vp);
72
73 if (_q->enc_bits != NULL)
74 free(_q->enc_bits);
75
76 free(_q);
77 }
78
fec_conv_encode(fec _q,unsigned int _dec_msg_len,unsigned char * _msg_dec,unsigned char * _msg_enc)79 void fec_conv_encode(fec _q,
80 unsigned int _dec_msg_len,
81 unsigned char *_msg_dec,
82 unsigned char *_msg_enc)
83 {
84 unsigned int i,j,r; // bookkeeping
85 unsigned int sr=0; // convolutional shift register
86 unsigned int n=0; // output bit counter
87
88 unsigned char bit;
89 unsigned char byte_in;
90 unsigned char byte_out=0;
91
92 for (i=0; i<_dec_msg_len; i++) {
93 byte_in = _msg_dec[i];
94
95 // break byte into individual bits
96 for (j=0; j<8; j++) {
97 // shift bit starting with most significant
98 bit = (byte_in >> (7-j)) & 0x01;
99 sr = (sr << 1) | bit;
100
101 // compute parity bits for each polynomial
102 for (r=0; r<_q->R; r++) {
103 byte_out = (byte_out<<1) | parity(sr & _q->poly[r]);
104 _msg_enc[n/8] = byte_out;
105 n++;
106 }
107 }
108 }
109
110 // tail bits
111 for (i=0; i<(_q->K)-1; i++) {
112 // shift register: push zeros
113 sr = (sr << 1);
114
115 // compute parity bits for each polynomial
116 for (r=0; r<_q->R; r++) {
117 byte_out = (byte_out<<1) | parity(sr & _q->poly[r]);
118 _msg_enc[n/8] = byte_out;
119 n++;
120 }
121 }
122
123 // ensure even number of bytes
124 while (n%8) {
125 // shift zeros
126 byte_out <<= 1;
127 _msg_enc[n/8] = byte_out;
128 n++;
129 }
130
131 assert(n == 8*fec_get_enc_msg_length(_q->scheme,_dec_msg_len));
132 }
133
134 //unsigned int
fec_conv_decode_hard(fec _q,unsigned int _dec_msg_len,unsigned char * _msg_enc,unsigned char * _msg_dec)135 void fec_conv_decode_hard(fec _q,
136 unsigned int _dec_msg_len,
137 unsigned char *_msg_enc,
138 unsigned char *_msg_dec)
139 {
140 // re-allocate resources if necessary
141 fec_conv_setlength(_q, _dec_msg_len);
142
143 // unpack bytes
144 unsigned int num_written;
145 liquid_unpack_bytes(_msg_enc, // encoded message (bytes)
146 _q->num_enc_bytes, // encoded message length (#bytes)
147 _q->enc_bits, // encoded messsage (bits)
148 _q->num_enc_bytes*8, // encoded message length (#bits)
149 &num_written);
150
151 #if VERBOSE_FEC_CONV
152 unsigned int i;
153 printf("msg encoded (bits):\n");
154 for (i=0; i<8*_q->num_enc_bytes; i++) {
155 printf("%1u", _q->enc_bits[i]);
156 if (((i+1)%8)==0)
157 printf(" ");
158 }
159 printf("\n");
160 #endif
161
162 // invoke hard-decision scaling
163 unsigned int k;
164 for (k=0; k<8*_q->num_enc_bytes; k++)
165 _q->enc_bits[k] = _q->enc_bits[k] ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0;
166
167 // run internal decoder
168 fec_conv_decode(_q, _msg_dec);
169 }
170
171 //unsigned int
fec_conv_decode_soft(fec _q,unsigned int _dec_msg_len,unsigned char * _msg_enc,unsigned char * _msg_dec)172 void fec_conv_decode_soft(fec _q,
173 unsigned int _dec_msg_len,
174 unsigned char *_msg_enc,
175 unsigned char *_msg_dec)
176 {
177 // re-allocate resources if necessary
178 fec_conv_setlength(_q, _dec_msg_len);
179
180 // copy soft input bits
181 unsigned int k;
182 for (k=0; k<8*_q->num_enc_bytes; k++)
183 _q->enc_bits[k] = _msg_enc[k];
184
185 // run internal decoder
186 fec_conv_decode(_q, _msg_dec);
187 }
188
189 //unsigned int
fec_conv_decode(fec _q,unsigned char * _msg_dec)190 void fec_conv_decode(fec _q,
191 unsigned char *_msg_dec)
192 {
193 // run decoder
194 _q->init_viterbi(_q->vp,0);
195 _q->update_viterbi_blk(_q->vp, _q->enc_bits, 8*_q->num_dec_bytes+_q->K-1);
196 _q->chainback_viterbi(_q->vp, _msg_dec, 8*_q->num_dec_bytes, 0);
197
198 #if VERBOSE_FEC_CONV
199 for (i=0; i<_dec_msg_len; i++)
200 printf("%.2x ", _msg_dec[i]);
201 printf("\n");
202 #endif
203 }
204
fec_conv_setlength(fec _q,unsigned int _dec_msg_len)205 void fec_conv_setlength(fec _q, unsigned int _dec_msg_len)
206 {
207 // re-allocate resources as necessary
208 unsigned int num_dec_bytes = _dec_msg_len;
209
210 // return if length has not changed
211 if (num_dec_bytes == _q->num_dec_bytes)
212 return;
213
214 #if VERBOSE_FEC_CONV
215 printf("(re)creating viterbi decoder, %u frame bytes\n", num_dec_bytes);
216 #endif
217
218 // reset number of framebits
219 _q->num_dec_bytes = num_dec_bytes;
220 _q->num_enc_bytes = fec_get_enc_msg_length(_q->scheme,
221 _dec_msg_len);
222
223 // delete old decoder if necessary
224 if (_q->vp != NULL)
225 _q->delete_viterbi(_q->vp);
226
227 // re-create / re-allocate memory buffers
228 _q->vp = _q->create_viterbi(8*_q->num_dec_bytes);
229 _q->enc_bits = (unsigned char*) realloc(_q->enc_bits,
230 _q->num_enc_bytes*8*sizeof(unsigned char));
231 }
232
233 //
234 // internal
235 //
236
fec_conv_init_v27(fec _q)237 void fec_conv_init_v27(fec _q)
238 {
239 _q->R=2;
240 _q->K=7;
241 _q->poly = fec_conv27_poly;
242 _q->create_viterbi = create_viterbi27;
243 _q->init_viterbi = init_viterbi27;
244 _q->update_viterbi_blk = update_viterbi27_blk;
245 _q->chainback_viterbi = chainback_viterbi27;
246 _q->delete_viterbi = delete_viterbi27;
247 }
248
fec_conv_init_v29(fec _q)249 void fec_conv_init_v29(fec _q)
250 {
251 _q->R=2;
252 _q->K=9;
253 _q->poly = fec_conv29_poly;
254 _q->create_viterbi = create_viterbi29;
255 _q->init_viterbi = init_viterbi29;
256 _q->update_viterbi_blk = update_viterbi29_blk;
257 _q->chainback_viterbi = chainback_viterbi29;
258 _q->delete_viterbi = delete_viterbi29;
259 }
260
fec_conv_init_v39(fec _q)261 void fec_conv_init_v39(fec _q)
262 {
263 _q->R=3;
264 _q->K=9;
265 _q->poly = fec_conv39_poly;
266 _q->create_viterbi = create_viterbi39;
267 _q->init_viterbi = init_viterbi39;
268 _q->update_viterbi_blk = update_viterbi39_blk;
269 _q->chainback_viterbi = chainback_viterbi39;
270 _q->delete_viterbi = delete_viterbi39;
271 }
272
fec_conv_init_v615(fec _q)273 void fec_conv_init_v615(fec _q)
274 {
275 _q->R=6;
276 _q->K=15;
277 _q->poly = fec_conv615_poly;
278 _q->create_viterbi = create_viterbi615;
279 _q->init_viterbi = init_viterbi615;
280 _q->update_viterbi_blk = update_viterbi615_blk;
281 _q->chainback_viterbi = chainback_viterbi615;
282 _q->delete_viterbi = delete_viterbi615;
283 }
284
285
286
287 #else // LIBFEC_ENABLED
288
fec_conv_create(fec_scheme _fs)289 fec fec_conv_create(fec_scheme _fs)
290 {
291 return NULL;
292 }
293
fec_conv_destroy(fec _q)294 void fec_conv_destroy(fec _q)
295 {
296 }
297
298 #endif // LIBFEC_ENABLED
299
300