commit b0490ad5f2a1daf8ef130b2b8b9cdd09d08cfa38 Author: Jens Ahrensfeld Date: Sat Dec 20 17:56:16 2014 +0000 - initial version git-svn-id: http://moon:8086/svn/software/trunk/libsrc/cpp@90 b431acfa-c32f-4a4a-93f1-934dc6c82436 diff --git a/radio/Equalizer.hpp b/radio/Equalizer.hpp new file mode 100644 index 0000000..dc5aaea --- /dev/null +++ b/radio/Equalizer.hpp @@ -0,0 +1,202 @@ +/* + * File: Equalizer.hpp + * Author: jens + * + * Created on 20. Dezember 2014, 09:24 + */ + +#ifndef EQUALIZER_HPP +#define EQUALIZER_HPP + +#include "Vector.hpp" +#include "FirComplex.hpp" + +namespace Radio +{ +namespace Equalizer +{ + +class AEqualizer : public FirComplex +{ +public: + AEqualizer(uint32_t numTaps) + : FirComplex(numTaps) + , m_w(numTaps) + { + + } + + virtual ~AEqualizer() {} + + void setNumTaps(uint32_t numTaps) + { + FirComplex::setNumTaps(numTaps); + m_w.resize(numTaps); + } + + void setUnit(uint32_t delay) + { + m_w.setZero(); + 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(uint32_t numTaps) + : AEqualizer(numTaps) + { + + } + ~Lms() + { + + } + + void update(ComplexScalar const &e, RealScalar const &mu) + { + m_w += m_x * conj(e) * mu; + } + +private: +}; + +class Cma : public Lms +{ +public: + Cma(uint32_t numTaps=0) + : Lms(numTaps) + , m_xLast(0) + , m_power(0) + { + } + + void init(uint32_t numTaps) + { + setNumTaps(numTaps); + } + + ComplexScalar process(ComplexScalar const &x) + { + RealScalar x1, x2; + + x1 = abs(x); + x2 = abs(m_x[m_numTaps-1]); + m_power = 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(uint32_t k=0) + : Lms(2*k+1) + , m_numFeedforward(k+1) + , m_numFeedBack(k) + { + + } + + ~Dfe() + { + + } + void init(uint32_t k) + { + setNumTaps(2*k+1); + m_numFeedforward = k+1; + m_numFeedBack = k; + } + + ComplexScalar process(ComplexScalar const &xs, ComplexScalar const &xh) + { + int32_t i; + CVec &x = m_x; + + // x(0:size-1) = [xs, x(0:m_numFeedforward-2), xh, x(m_numFeedforward:size-2)] + m_x.reverse() << m_x.segment(m_numFeedforward-1, m_numFeedBack).reverse(),xh,m_x.segment(0, m_numFeedforward-2).reverse(),xs; + + return FirComplex::process(m_w); + } + + void train(ComplexScalar e, RealScalar mu) + { + Lms::update(e, mu); + } + +private: + uint32_t m_numFeedforward; + uint32_t m_numFeedBack; + +}; + +} // Radio::Equalizer +} // ::Radio + + +#endif /* EQUALIZER_HPP */ + diff --git a/radio/FirComplex.hpp b/radio/FirComplex.hpp new file mode 100644 index 0000000..acc3b6b --- /dev/null +++ b/radio/FirComplex.hpp @@ -0,0 +1,58 @@ +/* + * File: FirComplex.hpp + * Author: jens + * + * Created on 20. Dezember 2014, 08:12 + */ + +#ifndef FIRCOMPLEX_HPP +#define FIRCOMPLEX_HPP + +#include "Vector.hpp" + +namespace Radio +{ + +class FirComplex +{ +public: + FirComplex(uint32_t numTaps = 0) + : m_numTaps(numTaps) + , m_x(numTaps) + { + } + virtual ~FirComplex() + { + + } + + void setNumTaps(uint32_t numTaps) + { + m_numTaps = numTaps; + m_x.resize(numTaps); +// m_x.fill(ComplexScalar(0,0)); + } + + void feed(ComplexScalar const &x) + { +// m_x.reverse().head(m_numTaps-1) = m_x.reverse().tail(m_numTaps-1); + + m_x.reverse() << m_x.head(m_numTaps-1).reverse(), x; +// m_x(0) = x; + } + + ComplexScalar process(CVec const &coeff) + { + return m_x.transpose() * coeff.conjugate(); + } + +protected: + uint32_t m_numTaps; + CVec m_x; + +}; + +} // ::Radio + +#endif /* FIRCOMPLEX_HPP */ + diff --git a/radio/Makefile b/radio/Makefile new file mode 100644 index 0000000..b8f7463 --- /dev/null +++ b/radio/Makefile @@ -0,0 +1,23 @@ +include ../config.mk + +SRCDIR := . +OBJS := real.o cpx.o ringbuf.o equalizer.o interpolation.o agc.o nco.o statistics.o symbol.o synchronization.o Frame.o + +LIB := $(BUILD_DIR)/libradio.a + +INCLUDES := . .. +DEFINES := radio_float_t=float fir_float_t=float + +all : $(LIB) + +$(LIB) : $(OBJS) + $(AR) -r $(LIB) $(OBJS) + +clean: + rm -f *.o + rm -f *.a + +.PHONY: clean + +include ../compile.mk + diff --git a/radio/Vector.hpp b/radio/Vector.hpp new file mode 100644 index 0000000..b57f093 --- /dev/null +++ b/radio/Vector.hpp @@ -0,0 +1,42 @@ +/* + * File: Vector.hpp + * Author: jens + * + * Created on 19. Dezember 2014, 18:24 + */ + +#ifndef VECTOR_HPP +#define VECTOR_HPP + +#include +#include "../radio/radio_types.h" +using namespace std; +using namespace Eigen; + +#ifndef radio_float_t +#define radio_float_t float +#endif + +namespace Radio +{ + +typedef radio_float_t RealScalar; +typedef complex ComplexScalar; + +typedef Matrix RVec; +typedef Matrix CVec; + +static ComplexScalar toComplexScalar(cpx_t v) +{ + return ComplexScalar(v.real, v.imag); +} + +static cpx_t toCpx(ComplexScalar v) +{ + return Cpx(v.real(), v.imag()); +} + +} // ::Radio + +#endif /* VECTOR_HPP */ +