Merge branch 'dfsg-orig'
[debian/gnuradio] / gr-atsc / src / lib / atsci_single_viterbi.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 <math.h>
24 #include <atsci_single_viterbi.h>
25 #include <iostream>
26
27 using std::cerr;
28 using std::cout;
29
30 const float atsci_single_viterbi::was_sent[32] = {
31   -7,-3,-7,-3,-7,-3,-7,-3,
32   -5,-1,-5,-1,-5,-1,-5,-1,
33   1,5,1,5,1,5,1,5,
34   3,7,3,7,3,7,3,7
35 };
36
37 const int atsci_single_viterbi::transition_table[32] = {
38   0,2,4,6,
39   2,0,6,4,
40   1,3,5,7,
41   3,1,7,5,
42   4,6,0,2,
43   6,4,2,0,
44   5,7,1,3,
45   7,5,3,1
46 };
47
48 void
49 atsci_single_viterbi::reset()
50 {
51   for (unsigned int i = 0; i<2; i++)
52     for (unsigned int j = 0; j<8; j++) {
53       path_metrics[i][j] = 0;
54       traceback[i][j] = 0;
55     }
56   phase = 0;
57 }
58
59 atsci_single_viterbi::atsci_single_viterbi()
60 {
61   reset();
62 }
63
64 char
65 atsci_single_viterbi::decode(float input)
66 {
67   for (unsigned int next_state = 0; next_state < 8; next_state++) {
68     unsigned int index = next_state << 2;
69     int min_metric_symb = 0;
70     float min_metric = fabs(input - was_sent[index + 0]) +
71       path_metrics[phase][transition_table[index + 0]];
72
73     for (unsigned int symbol_sent = 1; symbol_sent < 4; symbol_sent++) 
74       if( (fabs(input-was_sent[index+symbol_sent]) + 
75            path_metrics[phase][transition_table[index+symbol_sent]])
76           < min_metric) {
77         min_metric = fabs(input-was_sent[index+symbol_sent]) + 
78           path_metrics[phase][transition_table[index+symbol_sent]];
79         min_metric_symb = symbol_sent;
80       }
81
82     path_metrics[phase^1][next_state] = min_metric;
83     traceback[phase^1][next_state] = (((unsigned long long)min_metric_symb) << 62) |
84       (traceback[phase][transition_table[index+min_metric_symb]] >> 2);
85   }
86   unsigned int best_state = 0;
87   float best_state_metric = path_metrics[phase^1][0];
88   for (unsigned int state = 1; state < 8; state++)
89     if(path_metrics[phase^1][state] < best_state_metric) {
90       best_state = state;
91       best_state_metric = path_metrics[phase^1][state];
92     }
93   if(best_state_metric > 10000) {
94     for(unsigned int state = 0; state < 8; state++)
95       path_metrics[phase^1][state] -= best_state_metric;
96     // cerr << "Resetting Path Metrics from " << best_state_metric << " to 0\n";
97   }
98   phase ^= 1;
99   return (0x3 & traceback[phase][best_state]);
100 }