Imported Upstream version 3.0
[debian/gnuradio] / gnuradio-core / src / lib / general / gr_lms_dfe_ff.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2005 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 2, 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 <gr_lms_dfe_ff.h>
28 #include <gr_io_signature.h>
29 #include <gr_misc.h>
30 #include <iostream>
31
32 float
33 slice(float val)
34 {
35   if (val>0)
36     return 1;
37   else
38     return -1;
39 }
40
41 gr_lms_dfe_ff_sptr
42 gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, 
43                     unsigned int num_fftaps, unsigned int num_fbtaps)
44 {
45   return gr_lms_dfe_ff_sptr (new gr_lms_dfe_ff (lambda_ff,lambda_fb,num_fftaps,num_fbtaps));
46 }
47
48 gr_lms_dfe_ff::gr_lms_dfe_ff (float lambda_ff, float lambda_fb , 
49                               unsigned int num_fftaps, unsigned int num_fbtaps)
50   : gr_sync_block ("lms_dfe_ff",
51                    gr_make_io_signature (1, 1, sizeof (float)),
52                    gr_make_io_signature (1, 1, sizeof (float))),
53     d_lambda_ff (lambda_ff), d_lambda_fb (lambda_fb), 
54     d_ff_delayline(gr_rounduppow2(num_fftaps)),
55     d_fb_delayline(gr_rounduppow2(num_fbtaps)),
56     d_ff_taps(num_fftaps), d_fb_taps(num_fbtaps),
57     d_ff_index(0), d_fb_index(0)
58 {
59   gr_zero_vector(d_ff_taps);
60   d_ff_taps [d_ff_taps.size()/2] = 1;
61
62   gr_zero_vector(d_fb_taps);
63   gr_zero_vector(d_ff_delayline);
64   gr_zero_vector(d_fb_delayline);
65 }
66
67 int
68 gr_lms_dfe_ff::work (int noutput_items,
69                    gr_vector_const_void_star &input_items,
70                    gr_vector_void_star &output_items)
71 {
72   const float *iptr = (const float *) input_items[0];
73   float *optr = (float *) output_items[0];
74   
75   float acc, decision, error;
76   unsigned int i;
77
78   unsigned int ff_mask = d_ff_delayline.size() - 1;     // size is power of 2
79   unsigned int fb_mask = d_fb_delayline.size() - 1;
80
81   int   size = noutput_items;
82   while(size-- > 0) {
83     acc = 0; 
84     d_ff_delayline[d_ff_index] = *iptr++;
85
86     // Compute output
87     for (i=0; i < d_ff_taps.size(); i++) 
88       acc += d_ff_delayline[(i+d_ff_index) & ff_mask] * d_ff_taps[i];
89     
90     for (i=0; i < d_fb_taps.size(); i++)
91       acc -= d_fb_delayline[(i+d_fb_index) & fb_mask] * d_fb_taps[i];
92
93     decision = slice(acc);
94     error = decision - acc;
95     
96     // Update taps
97     for (i=0; i < d_ff_taps.size(); i++)
98       d_ff_taps[i] += d_lambda_ff * error * d_ff_delayline[(i+d_ff_index) & ff_mask];
99     
100     for (i=0; i < d_fb_taps.size(); i++)
101       d_fb_taps[i] -= d_lambda_fb * error * d_fb_delayline[(i+d_fb_index) & fb_mask];
102     
103     d_fb_index = (d_fb_index - 1) & fb_mask;    // Decrement index
104     d_ff_index = (d_ff_index - 1) & ff_mask;    // Decrement index
105
106     d_fb_delayline[d_fb_index] = decision;      // Save decision in feedback
107
108     *optr++ = acc;   // Output decision
109   }
110
111   if (0){
112     std::cout << "FF Taps\t";
113     for(i=0;i<d_ff_taps.size();i++)
114       std::cout << d_ff_taps[i] << "\t";
115     std::cout << std::endl << "FB Taps\t";
116     for(i=0;i<d_fb_taps.size();i++)
117       std::cout << d_fb_taps[i] << "\t";
118     std::cout << std::endl;
119   }
120
121   return noutput_items;
122 }