Merge commit 'v3.3.0' into upstream
[debian/gnuradio] / gr-atsc / src / lib / atsci_viterbi_decoder.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2002 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 #include <atsci_viterbi_decoder.h>
24 #include <assert.h>
25 #include <stdio.h>
26 #include <cmath>
27 #include "atsci_viterbi_mux.cc"
28 #include <string.h>
29
30
31 /* How many separate Trellis encoders / Viterbi decoders run in parallel */
32 static const int        NCODERS = 12;
33
34 static const float      DSEG_SYNC_SYM1 =  5;
35 static const float      DSEG_SYNC_SYM2 = -5;
36 static const float      DSEG_SYNC_SYM3 = -5;
37 static const float      DSEG_SYNC_SYM4 =  5;
38
39 atsci_viterbi_decoder::atsci_viterbi_decoder ()
40 {
41   debug = true;
42
43   /*
44    * These fifo's handle the alignment problem caused by the
45    * inherent decoding delay of the individual viterbi decoders.
46    * The net result is that this entire block has a pipeline latency
47    * of 12 complete segments.
48    *
49    * If anybody cares, it is possible to do it with less delay, but
50    * this approach is at least somewhat understandable...
51    */
52   
53   // the -4 is for the 4 sync symbols
54   int   fifo_size = ATSC_DATA_SEGMENT_LENGTH - 4 - viterbi[0].delay ();
55   for (int i = 0; i < NCODERS; i++)
56     fifo[i] = new fifo_t(fifo_size);
57
58   reset ();
59 }
60
61 atsci_viterbi_decoder::~atsci_viterbi_decoder ()
62 {
63   for (int i = 0; i < NCODERS; i++)
64     delete fifo[i];
65 }
66
67 void
68 atsci_viterbi_decoder::reset ()
69 {
70   for (int i = 0; i < NCODERS; i++){
71     viterbi[i].reset ();
72     fifo[i]->reset ();
73   }
74 }
75
76
77 void
78 atsci_viterbi_decoder::decode (atsc_mpeg_packet_rs_encoded out[NCODERS],
79                               const atsc_soft_data_segment in[NCODERS])
80 {
81   unsigned char out_copy[OUTPUT_SIZE];
82   float         in_copy[INPUT_SIZE];
83
84   // copy input into continguous temporary buffer
85   for (int i = 0; i < NCODERS; i++){
86     assert (in[i].pli.regular_seg_p ());
87     memcpy (&in_copy[i * INPUT_SIZE/NCODERS],
88             &in[i].data[0],
89             ATSC_DATA_SEGMENT_LENGTH * sizeof (in_copy[0]));
90   }
91
92   memset (out_copy, 0, sizeof (out_copy));      // sanity check
93   
94   // do the deed...
95   decode_helper (out_copy, in_copy);
96
97   // copy output from contiguous temp buffer into final output
98   for (int i = 0; i < NCODERS; i++){
99     memcpy (&out[i].data[0],
100             &out_copy[i * OUTPUT_SIZE/NCODERS],
101             ATSC_MPEG_RS_ENCODED_LENGTH * sizeof (out_copy[0]));
102             
103             
104     // adjust pipeline info to reflect 12 segment delay
105     plinfo::delay (out[i].pli, in[i].pli, NCODERS);
106   }
107 }
108
109 void
110 atsci_viterbi_decoder::decode_helper (unsigned char out[OUTPUT_SIZE],
111                                      const float symbols_in[INPUT_SIZE])
112 {
113   int encoder;
114   unsigned int i;
115   int dbi;
116   int dbwhere;
117   int dbindex;
118   int shift;
119   unsigned char dibit;
120   float symbol;
121
122   /* Memset is not necessary if it's all working... */
123   memset (out, 0, OUTPUT_SIZE);
124
125 #define VERBOSE 0
126
127 #if 1
128   /* Check for sync symbols in the incoming data stream */
129   /* For now, all we do is complain to stdout.  FIXME, pass it back to
130      caller as an error/quality signal.  */
131   for (i = 0; i < sync_symbol_indices_max; i++) {
132     int j = sync_symbol_indices[i];
133     if (fabsf (symbols_in[j] - DSEG_SYNC_SYM1) > 1.0)
134       if (VERBOSE) fprintf (stderr, "** Missing dataseg sync 1 at %d, expect %g, got %g.\n",
135                             j, DSEG_SYNC_SYM1, symbols_in[j]);
136     j++;
137     if (fabsf (symbols_in[j] - DSEG_SYNC_SYM2) > 1.0)
138       if (VERBOSE) fprintf (stderr, "** Missing dataseg sync 2 at %d, expect %g, got %g.\n",
139                             j, DSEG_SYNC_SYM2, symbols_in[j]);
140     j++;
141     if (fabsf (symbols_in[j] - DSEG_SYNC_SYM3) > 1.0)
142       if (VERBOSE) fprintf (stderr, "** Missing dataseg sync 3 at %d, expect %g, got %g.\n",
143                             j, DSEG_SYNC_SYM3, symbols_in[j]);
144     j++;
145     if (fabsf (symbols_in[j] - DSEG_SYNC_SYM4) > 1.0)
146       if (VERBOSE) fprintf (stderr, "** Missing dataseg sync 4 at %d, expect %g, got %g.\n",
147                             j, DSEG_SYNC_SYM4, symbols_in[j]);
148   }
149 #endif
150 #undef VERBOSE
151
152   // printf ("@@@ DIBITS @@@\n");
153   
154   /* Now run each of the 12 Trellis encoders over their subset of
155      the input symbols */
156   for (encoder = 0; encoder < NCODERS; encoder++) {
157     dbi = 0;                    /* Reinitialize dibit index for new encoder */
158     fifo_t      *dibit_fifo = fifo[encoder];
159     
160     /* Feed all the incoming symbols into one encoder;
161        pump them into the relevant dibits. */
162     for (i = 0; i < enco_which_max; i++) {
163       symbol = symbols_in[enco_which_syms[encoder][i]];
164       dibit = dibit_fifo->stuff (viterbi[encoder].decode (symbol));
165       // printf ("%d\n", dibit);
166       /* Store the dibit into the output data segment */
167       dbwhere = enco_which_dibits[encoder][dbi++];
168       dbindex = dbwhere >> 3;
169       shift = dbwhere & 0x7;
170       out[dbindex] =
171         (out[dbindex] & ~(0x03 << shift)) | (dibit << shift);
172     } /* Symbols fed into one encoder */
173   } /* Encoders */
174
175   // fflush (stdout);
176 }