Files
cpp/radio/Equalizer.hpp
T
jens f66d39c11c - refactored
- use blaze matrix library instead of Eigen

git-svn-id: http://moon:8086/svn/software/trunk/libsrc/cpp@943 b431acfa-c32f-4a4a-93f1-934dc6c82436
2022-06-11 08:56:42 +00:00

205 lines
3.5 KiB
C++

/*
* 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_ */