GNU Radio 3.6.4.1 C++ API
digital_kurtotic_equalizer_cc.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2011 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 #ifndef INCLUDED_DIGITAL_KURTOTIC_EQUALIZER_CC_H
24 #define INCLUDED_DIGITAL_KURTOTIC_EQUALIZER_CC_H
25 
26 #include <digital_api.h>
27 #include <gr_adaptive_fir_ccc.h>
28 #include <gr_math.h>
29 #include <iostream>
30 
33 
35 digital_make_kurtotic_equalizer_cc(int num_taps, float mu);
36 
37 /*!
38  * \brief Implements a kurtosis-based adaptive equalizer on complex stream
39  * \ingroup eq_blk
40  * \ingroup digital
41  *
42  * "Y. Guo, J. Zhao, Y. Sun, "Sign kurtosis maximization based blind
43  * equalization algorithm," IEEE Conf. on Control, Automation,
44  * Robotics and Vision, Vol. 3, Dec. 2004, pp. 2052 - 2057."
45  */
47 {
48 private:
49  float d_mu;
50  float d_p, d_m;
51  gr_complex d_q, d_u;
52  float d_alpha_p, d_alpha_q, d_alpha_m;
53 
55  float mu);
56  digital_kurtotic_equalizer_cc(int num_taps, float mu);
57 
58  gr_complex sign(gr_complex x)
59  {
60  float re = (float)(x.real() >= 0.0f);
61  float im = (float)(x.imag() >= 0.0f);
62  return gr_complex(re, im);
63  }
64 
65 protected:
66 
67  virtual gr_complex error(const gr_complex &out)
68  {
69 
70  // p = E[|z|^2]
71  // q = E[z^2]
72  // m = E[|z|^4]
73  // u = E[kurtosis(z)]
74 
75  float nrm = norm(out);
76  gr_complex cnj = conj(out);
77  float epsilon_f = 1e-12;
78  gr_complex epsilon_c = gr_complex(1e-12, 1e-12);
79 
80 
81  d_p = (1-d_alpha_p)*d_p + (d_alpha_p)*nrm + epsilon_f;
82  d_q = (1-d_alpha_q)*d_q + (d_alpha_q)*out*out + epsilon_c;
83  d_m = (1-d_alpha_m)*d_m + (d_alpha_m)*nrm*nrm + epsilon_f;
84  d_u = d_m - 2.0f*(d_p*d_p) - d_q*d_q;
85 
86  gr_complex F = (1.0f / (d_p*d_p*d_p)) *
87  (sign(d_u) * (nrm*cnj - 2.0f*d_p*cnj - conj(d_q)*out) -
88  abs(d_u)*cnj);
89 
90  //std::cout << "out: " << out << " p: " << d_p << " q: " << d_q;
91  //std::cout << " m: " << d_m << " u: " << d_u << std::endl;
92  //std::cout << "error: " << F << std::endl;
93 
94  float re = gr_clip(F.real(), 1.0);
95  float im = gr_clip(F.imag(), 1.0);
96  return gr_complex(re, im);
97  }
98 
99  virtual void update_tap(gr_complex &tap, const gr_complex &in)
100  {
101  tap += d_mu*in*d_error;
102  }
103 
104 public:
105  void set_gain(float mu)
106  {
107  if(mu < 0)
108  throw std::out_of_range("digital_kurtotic_equalizer::set_gain: Gain value must be >= 0");
109  d_mu = mu;
110  }
111 };
112 
113 #endif