GNU Radio 3.5.1 C++ API
|
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