GNU Radio 3.5.1 C++ API
digital_lms_dd_equalizer_cc.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2011 Free Software Foundation, Inc.
00004  * 
00005  * This file is part of GNU Radio
00006  * 
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 3, or (at your option)
00010  * any later version.
00011  * 
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with GNU Radio; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #ifndef INCLUDED_DIGITAL_LMS_DD_EQUALIZER_CC_H
00024 #define INCLUDED_DIGITAL_LMS_DD_EQUALIZER_CC_H
00025 
00026 #include <digital_api.h>
00027 #include <gr_adaptive_fir_ccc.h>
00028 #include <digital_constellation.h>
00029 
00030 class digital_lms_dd_equalizer_cc;
00031 typedef boost::shared_ptr<digital_lms_dd_equalizer_cc> digital_lms_dd_equalizer_cc_sptr;
00032 
00033 DIGITAL_API digital_lms_dd_equalizer_cc_sptr digital_make_lms_dd_equalizer_cc (int num_taps,
00034                                                                    float mu, int sps,
00035                                                                    digital_constellation_sptr cnst);
00036                                                                    
00037 /*!
00038  * \brief Least-Mean-Square Decision Directed Equalizer (complex in/out)
00039  * \ingroup eq_blk
00040  * \ingroup digital
00041  *
00042  * This block implements an LMS-based decision-directed equalizer.
00043  * It uses a set of weights, w, to correlate against the inputs, u,
00044  * and a decisions is then made from this output. The error
00045  * in the decision is used to update teh weight vector.
00046  *
00047  * y[n] = conj(w[n]) u[n]
00048  * d[n] = decision(y[n])
00049  * e[n] = d[n] - y[n]
00050  * w[n+1] = w[n] + mu u[n] conj(e[n])
00051  *
00052  * Where mu is a gain value (between 0 and 1 and usualy small,
00053  * around 0.001 - 0.01.
00054  *
00055  * This block uses the digital_constellation object for making
00056  * the decision from y[n]. Create the constellation object for
00057  * whatever constellation is to be used and pass in the object.
00058  * In Python, you can use something like:
00059  *    self.constellation = digital.constellation_qpsk()
00060  * To create a QPSK constellation (see the digital_constellation
00061  * block for more details as to what constellations are available
00062  * or how to create your own). You then pass the object to this
00063  * block as an sptr, or using "self.constellation.base()".
00064  *
00065  * The theory for this algorithm can be found in Chapter 9 of:
00066  * S. Haykin, Adaptive Filter Theory, Upper Saddle River, NJ:
00067  *    Prentice Hall, 1996.
00068  *
00069  */
00070 class DIGITAL_API digital_lms_dd_equalizer_cc : public gr_adaptive_fir_ccc
00071 {
00072 private:
00073   friend DIGITAL_API digital_lms_dd_equalizer_cc_sptr digital_make_lms_dd_equalizer_cc (int num_taps,
00074                                                                             float mu, int sps,
00075                                                                             digital_constellation_sptr cnst);
00076   
00077   float d_mu;
00078   std::vector<gr_complex>  d_taps;
00079   digital_constellation_sptr d_cnst;
00080 
00081   digital_lms_dd_equalizer_cc (int num_taps,
00082                                float mu, int sps,
00083                                digital_constellation_sptr cnst);
00084 
00085 protected:
00086 
00087   virtual gr_complex error(const gr_complex &out) 
00088   { 
00089     gr_complex decision, error;
00090     d_cnst->map_to_points(d_cnst->decision_maker(&out), &decision);
00091     error = decision - out;
00092     return error;
00093   }
00094 
00095   virtual void update_tap(gr_complex &tap, const gr_complex &in) 
00096   {
00097     tap += d_mu*conj(in)*d_error;
00098   }
00099 
00100 public:
00101   float get_gain()
00102   {
00103     return d_mu;
00104   }
00105   
00106   void set_gain(float mu)
00107   {
00108     if(mu < 0.0f || mu > 1.0f) {
00109       throw std::out_of_range("digital_lms_dd_equalizer::set_mu: Gain value must in [0, 1]");
00110     }
00111     else {
00112       d_mu = mu;
00113     }
00114   }
00115   
00116 };
00117 
00118 #endif