/* * File: Equalizer.hpp * Author: jens * * Created on 20. Dezember 2014, 09:24 */ #ifndef _RADIO_EQUALIZER_HPP_ #define _RADIO_EQUALIZER_HPP_ #include "Vector.hpp" #include "FirComplex.hpp" namespace Radio { namespace Equalizer { class AEqualizer : public FirComplex { public: AEqualizer(size_t numTaps) : FirComplex(numTaps) , m_w(numTaps) { } virtual ~AEqualizer() {} void setNumTaps(size_t numTaps) { FirComplex::setNumTaps(numTaps); m_w.resize(numTaps); } void setUnit(size_t delay) { m_w = ComplexScalar(0, 0); m_w[delay] = ComplexScalar(1, 0); } const CVec& getWeights() { return m_w; } const AEqualizer& operator=(const AEqualizer &rhs) { this->m_w = rhs.m_w; return *this; } protected: CVec m_w; }; class Lms : public AEqualizer { public: Lms(size_t numTaps) : AEqualizer(numTaps) { } ~Lms() { } void update(ComplexScalar const &e, RealScalar const &mu) { m_w += m_state * conj(e) * mu; } private: }; class Cma : public Lms { public: Cma(size_t numTaps=0) : Lms(numTaps) , m_xLast(0) , m_power(0) { } void init(size_t numTaps) { setNumTaps(numTaps); } ComplexScalar process(ComplexScalar const &x) { RealScalar x1, x2; x1 = abs(x); x2 = abs(m_state[m_numTaps-1]); m_power = std::max(RealScalar(0), m_power + (x1*x1 - m_xLast)); m_xLast = x2*x2; FirComplex::feed(x); return FirComplex::process(m_w); } // Proakis: page 698 void trainGodard(ComplexScalar const &sym_s_eq, RealScalar const &mag_h, RealScalar R2, RealScalar mu) { ComplexScalar d; ComplexScalar e; RealScalar mag_s, t; mag_s = abs(sym_s_eq); t = (RealScalar)((mag_h + R2*mag_s - mag_s*mag_s*mag_s)/(1E-4+mag_h)); d = sym_s_eq * t; e = d - sym_s_eq; mu /= (1+m_power); Lms::update(e, mu); } // "Sliced Multi-modulus Blind Equalization Algorithm", // ETRI Journal, Volume 27, Number 3, June 2005, // Shafayat Abrar and Roy A. Axford Jr. void trainMma(ComplexScalar const &sym_s_eq, ComplexScalar const &R, RealScalar mu) { ComplexScalar e(sym_s_eq.real()*(R.real() - sym_s_eq.real()*sym_s_eq.real()), sym_s_eq.imag()*(R.imag() - sym_s_eq.imag()*sym_s_eq.imag())); mu /= (1+m_power); Lms::update(e, mu); } // "Sliced Multi-modulus Blind Equalization Algorithm", // ETRI Journal, Volume 27, Number 3, June 2005, // Shafayat Abrar and Roy A. Axford Jr. void trainSmma(ComplexScalar const &sym_s_eq, RealScalar const &mag_h, ComplexScalar const &R, RealScalar mu) { ComplexScalar e(sym_s_eq.real()*(mag_h*R.real() - sym_s_eq.real()*sym_s_eq.real()), sym_s_eq.imag()*(mag_h*R.imag() - sym_s_eq.imag()*sym_s_eq.imag())); mu /= (1+m_power); Lms::update(e, mu); } private: RealScalar m_xLast; RealScalar m_power; }; class Dfe : public Lms { public: Dfe(size_t k=0) : Lms(2*k+1) , m_numFeedforward(k+1) , m_numFeedBack(k) { } ~Dfe() { } void init(size_t k) { setNumTaps(2*k+1); m_numFeedforward = k+1; m_numFeedBack = k; } ComplexScalar process(ComplexScalar const &xs, ComplexScalar const &xh) { // P-Code // x(0:size-1) = [xs, x(0:m_numFeedforward-2), xh, x(m_numFeedforward:size-2)] auto sv_xs = subvector(m_state, 0, m_numFeedforward); insert_left(sv_xs, xs); auto sv_xh = subvector(m_state, m_numFeedforward, m_numFeedBack); insert_left(sv_xh, xh); return FirComplex::process(m_w); } void train(ComplexScalar e, RealScalar mu) { Lms::update(e, mu); } private: size_t m_numFeedforward; size_t m_numFeedBack; }; } // Radio::Equalizer } // ::Radio #endif /* _RADIO_EQUALIZER_HPP_ */