1 /* -*- c++ -*- */
2 /*
3  * Copyright 2013-2014 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include "cc_decoder_impl.h"
28 #include <math.h>
29 #include <stdio.h>
30 #include <volk/volk.h>
31 #include <boost/assign/list_of.hpp>
32 #include <sstream>
33 #include <vector>
34 
35 namespace gr {
36 namespace fec {
37 namespace code {
38 
make(int frame_size,int k,int rate,std::vector<int> polys,int start_state,int end_state,cc_mode_t mode,bool padded)39 generic_decoder::sptr cc_decoder::make(int frame_size,
40                                        int k,
41                                        int rate,
42                                        std::vector<int> polys,
43                                        int start_state,
44                                        int end_state,
45                                        cc_mode_t mode,
46                                        bool padded)
47 {
48     return generic_decoder::sptr(new cc_decoder_impl(
49         frame_size, k, rate, polys, start_state, end_state, mode, padded));
50 }
51 
cc_decoder_impl(int frame_size,int k,int rate,std::vector<int> polys,int start_state,int end_state,cc_mode_t mode,bool padded)52 cc_decoder_impl::cc_decoder_impl(int frame_size,
53                                  int k,
54                                  int rate,
55                                  std::vector<int> polys,
56                                  int start_state,
57                                  int end_state,
58                                  cc_mode_t mode,
59                                  bool padded)
60     : generic_decoder("cc_decoder"),
61       d_k(k),
62       d_rate(rate),
63       d_polys(polys),
64       d_mode(mode),
65       d_padding(0),
66       d_start_state_chaining(start_state),
67       d_start_state_nonchaining(start_state),
68       d_end_state_nonchaining(end_state)
69 {
70     // Set max frame size here; all buffers and settings will be
71     // based on this value.
72     d_max_frame_size = frame_size;
73     d_frame_size = frame_size;
74 
75     // set up a padding factor. If padding, the encoded frame was exteded
76     // by this many bits to fit into a full byte.
77     if (padded && (mode == CC_TERMINATED)) {
78         d_padding = static_cast<int>(8.0f * ceilf(d_rate * (d_k - 1) / 8.0f) -
79                                      (d_rate * (d_k - 1)));
80     }
81 
82     d_vp = new struct v;
83 
84     d_numstates = 1 << (d_k - 1);
85 
86     d_decision_t_size = d_numstates / 8; // packed bit array
87 
88     d_managed_in_size = 0;
89     switch (d_mode) {
90     case (CC_TAILBITING):
91         d_end_state = &d_end_state_chaining;
92         d_veclen = d_frame_size + (6 * (d_k - 1));
93         d_managed_in = (unsigned char*)volk_malloc(
94             d_veclen * d_rate * sizeof(unsigned char), volk_get_alignment());
95         d_managed_in_size = d_veclen * d_rate;
96         if (d_managed_in == NULL) {
97             throw std::runtime_error("cc_decoder: bad alloc for d_managed_in\n");
98         }
99         break;
100 
101     case (CC_TRUNCATED):
102         d_veclen = d_frame_size;
103         d_end_state = &d_end_state_chaining;
104         break;
105 
106     case (CC_TERMINATED):
107         d_veclen = d_frame_size + d_k - 1;
108         d_end_state =
109             (end_state == -1) ? &d_end_state_chaining : &d_end_state_nonchaining;
110         break;
111 
112     case (CC_STREAMING):
113         d_veclen = d_frame_size + d_k - 1;
114         d_end_state = &d_end_state_chaining;
115         break;
116 
117     default:
118         throw std::runtime_error("cc_decoder: mode not recognized");
119     }
120 
121     d_vp->metrics = (unsigned char*)volk_malloc(2 * sizeof(unsigned char) * d_numstates,
122                                                 volk_get_alignment());
123     if (d_vp->metrics == NULL) {
124         throw std::runtime_error("bad alloc for d_vp->metrics!\n");
125     }
126 
127     d_vp->metrics1.t = d_vp->metrics;
128     d_vp->metrics2.t = d_vp->metrics + d_numstates;
129 
130     d_vp->decisions = (unsigned char*)volk_malloc(
131         sizeof(unsigned char) * d_veclen * d_decision_t_size, volk_get_alignment());
132     if (d_vp->decisions == NULL) {
133         throw std::runtime_error("bad alloc for d_vp->decisions!\n");
134     }
135 
136     Branchtab = (unsigned char*)volk_malloc(
137         sizeof(unsigned char) * d_numstates / 2 * rate, volk_get_alignment());
138     if (Branchtab == NULL) {
139         throw std::runtime_error("bad alloc for d_vp->decisions!\n");
140     }
141 
142     create_viterbi();
143 
144     if (d_k - 1 < 8) {
145         d_ADDSHIFT = (8 - (d_k - 1));
146         d_SUBSHIFT = 0;
147     } else if (d_k - 1 > 8) {
148         d_ADDSHIFT = 0;
149         d_SUBSHIFT = ((d_k - 1) - 8);
150     } else {
151         d_ADDSHIFT = 0;
152         d_SUBSHIFT = 0;
153     }
154 
155     std::map<std::string, conv_kernel> yp_kernel =
156         boost::assign::map_list_of("k=7r=2", volk_8u_x4_conv_k7_r2_8u);
157 
158     std::string k_ = "k=";
159     std::string r_ = "r=";
160 
161     std::ostringstream kerneltype;
162     kerneltype << k_ << d_k << r_ << d_rate;
163 
164     d_kernel = yp_kernel[kerneltype.str()];
165     if (d_kernel == NULL) {
166         throw std::runtime_error("cc_decoder: parameters not supported");
167     }
168 }
169 
~cc_decoder_impl()170 cc_decoder_impl::~cc_decoder_impl()
171 {
172     volk_free(d_vp->decisions);
173     volk_free(Branchtab);
174     volk_free(d_vp->metrics);
175 
176     delete d_vp;
177 
178     if (d_mode == CC_TAILBITING) {
179         volk_free(d_managed_in);
180     }
181 }
182 
get_output_size()183 int cc_decoder_impl::get_output_size()
184 {
185     // unpacked bits
186     return d_frame_size;
187 }
188 
get_input_size()189 int cc_decoder_impl::get_input_size()
190 {
191     if (d_mode == CC_TERMINATED) {
192         return d_rate * (d_frame_size + d_k - 1) + d_padding;
193     } else {
194         return d_rate * d_frame_size;
195     }
196 }
197 
get_input_item_size()198 int cc_decoder_impl::get_input_item_size() { return 1; }
199 
get_history()200 int cc_decoder_impl::get_history()
201 {
202     if (d_mode == CC_STREAMING) {
203         return d_rate * (d_k - 1);
204     } else {
205         return 0;
206     }
207 }
208 
get_shift()209 float cc_decoder_impl::get_shift() { return 128.0; }
210 
get_input_conversion()211 const char* cc_decoder_impl::get_input_conversion() { return "uchar"; }
212 
create_viterbi()213 void cc_decoder_impl::create_viterbi()
214 {
215     int state;
216     unsigned int i;
217     partab_init();
218     for (state = 0; state < d_numstates / 2; state++) {
219         for (i = 0; i < d_rate; i++) {
220             Branchtab[i * d_numstates / 2 + state] =
221                 (d_polys[i] < 0) ^ parity((2 * state) & abs(d_polys[i])) ? 255 : 0;
222         }
223     }
224 
225     switch (d_mode) {
226     case (CC_STREAMING):
227         d_start_state = &d_start_state_chaining;
228         init_viterbi_unbiased(d_vp);
229         break;
230 
231     case (CC_TAILBITING):
232         d_start_state = &d_start_state_nonchaining;
233         init_viterbi_unbiased(d_vp);
234         break;
235 
236     case (CC_TRUNCATED):
237     case (CC_TERMINATED):
238         d_start_state = &d_start_state_nonchaining;
239         init_viterbi(d_vp, *d_start_state);
240         break;
241 
242     default:
243         throw std::runtime_error("cc_decoder: mode not recognized");
244     }
245 
246     return;
247 }
248 
parity(int x)249 int cc_decoder_impl::parity(int x)
250 {
251     x ^= (x >> 16);
252     x ^= (x >> 8);
253     return parityb(x);
254 }
255 
parityb(unsigned char x)256 int cc_decoder_impl::parityb(unsigned char x) { return Partab[x]; }
257 
partab_init(void)258 void cc_decoder_impl::partab_init(void)
259 {
260     int i, cnt, ti;
261 
262     /* Initialize parity lookup table */
263     for (i = 0; i < 256; i++) {
264         cnt = 0;
265         ti = i;
266         while (ti) {
267             if (ti & 1)
268                 cnt++;
269             ti >>= 1;
270         }
271         Partab[i] = cnt & 1;
272     }
273 }
274 
init_viterbi(struct v * vp,int starting_state)275 int cc_decoder_impl::init_viterbi(struct v* vp, int starting_state)
276 {
277     int i;
278 
279     if (vp == NULL)
280         return -1;
281     for (i = 0; i < d_numstates; i++) {
282         vp->metrics1.t[i] = 63;
283     }
284 
285     vp->old_metrics = vp->metrics1;
286     vp->new_metrics = vp->metrics2;
287     vp->old_metrics.t[starting_state & (d_numstates - 1)] =
288         0; /* Bias known start state */
289     return 0;
290 }
291 
init_viterbi_unbiased(struct v * vp)292 int cc_decoder_impl::init_viterbi_unbiased(struct v* vp)
293 {
294     int i;
295 
296     if (vp == NULL)
297         return -1;
298     for (i = 0; i < d_numstates; i++)
299         vp->metrics1.t[i] = 31;
300 
301     vp->old_metrics = vp->metrics1;
302     vp->new_metrics = vp->metrics2;
303     // no bias step
304     return 0;
305 }
306 
find_endstate()307 int cc_decoder_impl::find_endstate()
308 {
309     unsigned char* met =
310         ((d_k + d_veclen) % 2 == 0) ? d_vp->new_metrics.t : d_vp->old_metrics.t;
311 
312     unsigned char min = met[0];
313     int state = 0;
314     for (int i = 1; i < d_numstates; ++i) {
315         if (met[i] < min) {
316             min = met[i];
317             state = i;
318         }
319     }
320     // printf("min %d\n", state);
321     return state;
322 }
323 
update_viterbi_blk(unsigned char * syms,int nbits)324 int cc_decoder_impl::update_viterbi_blk(unsigned char* syms, int nbits)
325 {
326     unsigned char* d;
327 
328     d = d_vp->decisions;
329 
330     memset(d, 0, d_decision_t_size * nbits);
331 
332     d_kernel(d_vp->new_metrics.t,
333              d_vp->old_metrics.t,
334              syms,
335              d,
336              nbits - (d_k - 1),
337              d_k - 1,
338              Branchtab);
339 
340     return 0;
341 }
342 
chainback_viterbi(unsigned char * data,unsigned int nbits,unsigned int endstate,unsigned int tailsize)343 int cc_decoder_impl::chainback_viterbi(unsigned char* data,
344                                        unsigned int nbits,
345                                        unsigned int endstate,
346                                        unsigned int tailsize)
347 {
348     unsigned char* d;
349 
350     /* ADDSHIFT and SUBSHIFT make sure that the thing returned is a byte. */
351     d = d_vp->decisions;
352     /* Make room beyond the end of the encoder register so we can
353      * accumulate a full byte of decoded data
354      */
355 
356     endstate = (endstate % d_numstates) << d_ADDSHIFT;
357 
358     /* The store into data[] only needs to be done every 8 bits.
359      * But this avoids a conditional branch, and the writes will
360      * combine in the cache anyway
361      */
362 
363     d += tailsize * d_decision_t_size; /* Look past tail */
364     int retval;
365     int dif = tailsize - (d_k - 1);
366     decision_t dec;
367     while (nbits-- > d_frame_size - (d_k - 1)) {
368         int k;
369         dec.t = &d[nbits * d_decision_t_size];
370         k = (dec.w[(endstate >> d_ADDSHIFT) / 32] >> ((endstate >> d_ADDSHIFT) % 32)) & 1;
371 
372         endstate = (endstate >> 1) | (k << (d_k - 2 + d_ADDSHIFT));
373         data[((nbits + dif) % d_frame_size)] = k;
374 
375         retval = endstate;
376     }
377     nbits += 1;
378 
379     while (nbits-- != 0) {
380         int k;
381 
382         dec.t = &d[nbits * d_decision_t_size];
383 
384         k = (dec.w[(endstate >> d_ADDSHIFT) / 32] >> ((endstate >> d_ADDSHIFT) % 32)) & 1;
385 
386         endstate = (endstate >> 1) | (k << (d_k - 2 + d_ADDSHIFT));
387         data[((nbits + dif) % d_frame_size)] = k;
388     }
389 
390     return retval >> d_ADDSHIFT;
391 }
392 
set_frame_size(unsigned int frame_size)393 bool cc_decoder_impl::set_frame_size(unsigned int frame_size)
394 {
395     bool ret = true;
396     if (frame_size > d_max_frame_size) {
397         GR_LOG_INFO(
398             d_logger,
399             boost::format("cc_decoder: tried to set frame to %1%; max possible is %2%") %
400                 frame_size % d_max_frame_size);
401         frame_size = d_max_frame_size;
402         ret = false;
403     }
404 
405     d_frame_size = frame_size;
406 
407     switch (d_mode) {
408     case (CC_TAILBITING):
409         d_veclen = d_frame_size + (6 * (d_k - 1));
410         if (d_veclen * d_rate > d_managed_in_size) {
411             throw std::runtime_error(
412                 "cc_decoder: attempt to resize beyond d_managed_in buffer size!\n");
413         }
414         break;
415 
416     case (CC_TRUNCATED):
417         d_veclen = d_frame_size;
418         break;
419 
420     case (CC_STREAMING):
421         d_veclen = d_frame_size + d_k - 1;
422         break;
423 
424     case (CC_TERMINATED):
425         // If the input is being padded out to a byte, we know the
426         // real frame size is without the padding.
427         d_frame_size -= d_padding * d_rate;
428         d_veclen = d_frame_size + d_k - 1;
429         break;
430 
431     default:
432         throw std::runtime_error("cc_decoder: mode not recognized");
433     }
434 
435     return ret;
436 }
437 
rate()438 double cc_decoder_impl::rate() { return 1.0 / static_cast<double>(d_rate); }
439 
generic_work(void * inbuffer,void * outbuffer)440 void cc_decoder_impl::generic_work(void* inbuffer, void* outbuffer)
441 {
442     const unsigned char* in = (const unsigned char*)inbuffer;
443     unsigned char* out = (unsigned char*)outbuffer;
444 
445     switch (d_mode) {
446 
447     case (CC_TAILBITING):
448         memcpy(d_managed_in, in, d_frame_size * d_rate * sizeof(unsigned char));
449         memcpy(d_managed_in + d_frame_size * d_rate * sizeof(unsigned char),
450                in,
451                (d_veclen - d_frame_size) * d_rate * sizeof(unsigned char));
452         update_viterbi_blk(d_managed_in, d_veclen);
453         d_end_state_chaining = find_endstate();
454         chainback_viterbi(&out[0], d_frame_size, *d_end_state, d_veclen - d_frame_size);
455         init_viterbi_unbiased(d_vp);
456         break;
457 
458 
459     case (CC_TRUNCATED):
460         update_viterbi_blk((unsigned char*)(&in[0]), d_veclen);
461         d_end_state_chaining = find_endstate();
462         for (unsigned int i = 0; i < d_k - 1; ++i) {
463             out[d_veclen - 1 - i] = ((*d_end_state) >> i) & 1;
464         }
465         d_start_state_chaining =
466             chainback_viterbi(&out[0], d_frame_size - (d_k - 1), *d_end_state, d_k - 1);
467         init_viterbi(d_vp, *d_start_state);
468         break;
469 
470     case (CC_STREAMING):
471     case (CC_TERMINATED):
472         update_viterbi_blk((unsigned char*)(&in[0]), d_veclen);
473         d_end_state_chaining = find_endstate();
474         d_start_state_chaining = chainback_viterbi(
475             &out[0], d_frame_size, *d_end_state, d_veclen - d_frame_size);
476 
477         init_viterbi(d_vp, *d_start_state);
478         break;
479 
480     default:
481         throw std::runtime_error("cc_decoder: mode not recognized");
482     }
483 }
484 
485 } /* namespace code */
486 } /* namespace fec */
487 } /* namespace gr */
488