- Use C++ Equalizer DFE and CMA
git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@91 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
+57
-55
@@ -55,6 +55,7 @@ Receiver::Receiver(LogHandler *pLogHandler)
|
||||
, m_pPolyphaseInterpolator(0)
|
||||
, m_pLagrangeInterpolator(0)
|
||||
, m_pFarrowInterpolator(0)
|
||||
|
||||
{
|
||||
m_stateArm_I = nullptr;
|
||||
m_stateArm_Q = nullptr;
|
||||
@@ -165,10 +166,10 @@ void Receiver::initDefaultParams()
|
||||
}
|
||||
|
||||
#if 0
|
||||
void UpdateWeigths(ComplexVector &x, ComplexVector &e, ComplexVector &w, ComplexVector &w_conj, radio_float_t mu)
|
||||
void UpdateWeigths(CVec &x, CVec &e, CVec &w, CVec &w_conj, radio_float_t mu)
|
||||
{
|
||||
|
||||
e *= ComplexVector(mu, 0);
|
||||
e *= CVec(mu, 0);
|
||||
e.print("e * mu");
|
||||
|
||||
w += x * e.conj();
|
||||
@@ -219,9 +220,10 @@ void Receiver::init()
|
||||
AGC_Init(&agcBlind, EQ_UPD_INTERVAL, AGC_INITIAL_VALUE);
|
||||
|
||||
// Channel estimation filter
|
||||
DFEComplexInit(&m_dfe_off, EQ_DFE_K);
|
||||
DFEComplexInit(&m_dfe_on, EQ_DFE_K);
|
||||
CMAInit(&m_cma, 2*EQ_DFE_K+1);
|
||||
m_cma2.init(2*EQ_DFE_K+1);
|
||||
m_dfe_off2.init(EQ_DFE_K);
|
||||
m_dfe_on2.init(EQ_DFE_K);
|
||||
|
||||
m_dfe_e_cpx.real = m_dfe_e_cpx.imag = 0.f;
|
||||
|
||||
cmaReset();
|
||||
@@ -372,20 +374,20 @@ void Receiver::init()
|
||||
//---------------------------
|
||||
// ComplexVector
|
||||
//---------------------------
|
||||
ComplexVector cv1(4);
|
||||
ComplexVector cv2(4);
|
||||
ComplexVector cv3(4);
|
||||
CVec cv1(4);
|
||||
CVec cv2(4);
|
||||
CVec cv3(4);
|
||||
|
||||
cv1.at(0) = ComplexVector(1,2);
|
||||
cv1.at(1) = ComplexVector(3,4);
|
||||
cv1.at(2) = ComplexVector(5,6);
|
||||
cv1.at(3) = ComplexVector(7,8);
|
||||
cv2.at(0) = ComplexVector(11,12);
|
||||
cv2.at(1) = ComplexVector(13,14);
|
||||
cv2.at(2) = ComplexVector(15,16);
|
||||
cv2.at(3) = ComplexVector(17,18);
|
||||
cv1.at(0) = CVec(1,2);
|
||||
cv1.at(1) = CVec(3,4);
|
||||
cv1.at(2) = CVec(5,6);
|
||||
cv1.at(3) = CVec(7,8);
|
||||
cv2.at(0) = CVec(11,12);
|
||||
cv2.at(1) = CVec(13,14);
|
||||
cv2.at(2) = CVec(15,16);
|
||||
cv2.at(3) = CVec(17,18);
|
||||
|
||||
const ComplexVector &c = -cv1;
|
||||
const CVec &c = -cv1;
|
||||
cv3 = c;
|
||||
|
||||
//---------------------------
|
||||
@@ -711,18 +713,18 @@ void Receiver::init()
|
||||
//---------------------------
|
||||
// Test
|
||||
//---------------------------
|
||||
ComplexVector w(32);
|
||||
ComplexVector w_conj(32);
|
||||
ComplexVector e(32);
|
||||
ComplexVector x(32);
|
||||
CVec w(32);
|
||||
CVec w_conj(32);
|
||||
CVec e(32);
|
||||
CVec x(32);
|
||||
|
||||
w = ComplexVector(1, 1);
|
||||
w_conj = ComplexVector(0.f, 0.f);
|
||||
e = ComplexVector (0.5f, 0.4f);
|
||||
x = ComplexVector(2.f, 2.f);
|
||||
x *= ComplexVector(10.f, 0);
|
||||
x += ComplexVector(0.5f, 0);
|
||||
x -= ComplexVector(5.f, 0);
|
||||
w = CVec(1, 1);
|
||||
w_conj = CVec(0.f, 0.f);
|
||||
e = CVec (0.5f, 0.4f);
|
||||
x = CVec(2.f, 2.f);
|
||||
x *= CVec(10.f, 0);
|
||||
x += CVec(0.5f, 0);
|
||||
x -= CVec(5.f, 0);
|
||||
x += w + w_conj;
|
||||
|
||||
w.print("w");
|
||||
@@ -733,14 +735,14 @@ void Receiver::init()
|
||||
//---------------------------
|
||||
// RealVector
|
||||
//---------------------------
|
||||
RealVector rv1(4, 0);
|
||||
RealVector rv2(4, 0);
|
||||
RealVector rv3(4, 0);
|
||||
RVec rv1(4, 0);
|
||||
RVec rv2(4, 0);
|
||||
RVec rv3(4, 0);
|
||||
|
||||
rv1 = 10.f;
|
||||
rv2 = 20.f;
|
||||
|
||||
const RealVector &r = -rv1;
|
||||
const RVec &r = -rv1;
|
||||
rv3 = r;
|
||||
rv3 = -rv1;
|
||||
rv3 = -rv1 * rv2 * rv2;
|
||||
@@ -947,11 +949,6 @@ void Receiver::free()
|
||||
// AGC
|
||||
AGC_Free(&agcBlind);
|
||||
|
||||
// Channel estimation filter
|
||||
DFEComplexFree(&m_dfe_off);
|
||||
DFEComplexFree(&m_dfe_on);
|
||||
CMAFree(&m_cma);
|
||||
|
||||
}
|
||||
|
||||
// The Receiver Controller
|
||||
@@ -1160,9 +1157,12 @@ void Receiver::processBaseband(cpx_t *pIF, uint32_t len)
|
||||
// Equalizer Process samples
|
||||
// -----------------------------------------------------
|
||||
SlidingVarGet(&m_statistics.I_CPR);
|
||||
IQ_cma = CMAProcess(&m_cma, IQ_cpr);
|
||||
IQ_dfeOn = DFEComplexProcess(&m_dfe_on, IQ_cpr, IQ_hard_last);
|
||||
|
||||
ComplexScalar __IQ_cma = m_cma2.process(toComplexScalar(IQ_cpr));
|
||||
IQ_cma = toCpx(__IQ_cma);
|
||||
|
||||
ComplexScalar __IQ_dfeOn = m_dfe_on2.process(toComplexScalar(IQ_cpr), toComplexScalar(IQ_hard_last));
|
||||
IQ_dfeOn = toCpx(__IQ_dfeOn);
|
||||
|
||||
IQ_eq = IQ_cpr;
|
||||
if (m_params.eq_mode == eq_mode_cma)
|
||||
{
|
||||
@@ -1206,32 +1206,34 @@ void Receiver::processBaseband(cpx_t *pIF, uint32_t len)
|
||||
if (m_params.cmaType == cma_type_cma)
|
||||
{
|
||||
// CMA: Train
|
||||
CMATrainGodard(&m_cma, IQ_cma, CpxMagS(sym_cma.rect), m_pSymMapper->R2_cma, m_params.eqMuCma);
|
||||
m_cma2.trainGodard(__IQ_cma, CpxMagS(sym_cma.rect), m_pSymMapper->R2_cma, m_params.eqMuCma);
|
||||
}
|
||||
if (m_params.cmaType == cma_type_mma)
|
||||
{
|
||||
// MMA: Train
|
||||
MMATrain(&m_cma, IQ_cma, m_pSymMapper->R_mma, m_params.eqMuCma);
|
||||
m_cma2.trainMma(__IQ_cma, toComplexScalar(m_pSymMapper->R_mma), m_params.eqMuCma);
|
||||
}
|
||||
if (m_params.cmaType == cma_type_smma)
|
||||
{
|
||||
// S-MMA: Train
|
||||
SMMATrain(&m_cma, IQ_cma, CpxMagS(sym_cma.rect), m_pSymMapper->R_smma, m_params.eqMuCma);
|
||||
m_cma2.trainSmma(__IQ_cma, CpxMagS(sym_cma.rect), toComplexScalar(m_pSymMapper->R_smma), m_params.eqMuCma);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_params.dfeMode == dfe_mode_training_enabled)
|
||||
{
|
||||
// DFE: LMS Update coefficients
|
||||
DFEAdaptLMS(&m_dfe_off, m_dfe_e_cpx, m_params.eqMuDfe); // last dfe_e_cpx
|
||||
m_dfe_off2.train(toComplexScalar(m_dfe_e_cpx), m_params.eqMuDfe);
|
||||
|
||||
// DFE: Calc offline response
|
||||
IQ_dfeOff = DFEComplexProcess(&m_dfe_off, IQ_cpr, sym_dfe_off.rect);
|
||||
|
||||
ComplexScalar __IQ_dfeOff = m_dfe_off2.process(toComplexScalar(IQ_cpr), toComplexScalar(sym_dfe_off.rect));
|
||||
IQ_dfeOff = toCpx(__IQ_dfeOff);
|
||||
|
||||
sym_dfe_off = SymMapGetSymbolInfo(m_pSymMapper, SymMapDemap(m_pSymMapper, IQ_soft));
|
||||
|
||||
// DFE: Calculate current error
|
||||
m_dfe_e_cpx = CpxSubS(sym_dfe_off.rect, IQ_dfeOff);
|
||||
ComplexScalar __dfe_e_cpx = toComplexScalar(sym_dfe_off.rect) - __IQ_dfeOff;
|
||||
m_dfe_e_cpx = toCpx(__dfe_e_cpx);
|
||||
}
|
||||
|
||||
// Calculate current error
|
||||
@@ -1576,6 +1578,9 @@ status_t& Receiver::getStatus()
|
||||
radio_float_t powerSoft_dB;
|
||||
radio_float_t powerHard_dB;
|
||||
|
||||
if (!m_pSymMapper)
|
||||
return status;
|
||||
|
||||
status.frameStatRx = m_frameReceiver.getStats();
|
||||
status.numSymbolsReceived = m_sym_stat.sym_cnt;
|
||||
status.noiseStr = powerDB(SlidingVarGet(&m_statistics.noise_str), 1.0f);
|
||||
@@ -1639,28 +1644,25 @@ void Receiver::cprReset()
|
||||
|
||||
void Receiver::dfeReset()
|
||||
{
|
||||
CoeffComplexUnitAt(m_dfe_off.eq.pW, m_dfe_off.N, EQ_GROUP_DELAY);
|
||||
CoeffComplexUnitAt(m_dfe_on.eq.pW, m_dfe_on.N, EQ_GROUP_DELAY);
|
||||
CoeffComplexUnitAt(m_dfe_off.eq.pW_conj, m_dfe_off.N, EQ_GROUP_DELAY);
|
||||
CoeffComplexUnitAt(m_dfe_on.eq.pW_conj, m_dfe_on.N, EQ_GROUP_DELAY);
|
||||
m_dfe_on2.setUnit(EQ_GROUP_DELAY);
|
||||
m_dfe_off2.setUnit(EQ_GROUP_DELAY);
|
||||
m_statusListeners.call(&ReceiverStatusListener::receiverStatusChanged, this);
|
||||
}
|
||||
|
||||
void Receiver::cmaReset()
|
||||
{
|
||||
CoeffComplexUnitAt(m_cma.eq.pW, m_cma.N, EQ_GROUP_DELAY);
|
||||
m_cma2.setUnit(EQ_GROUP_DELAY);
|
||||
m_statusListeners.call(&ReceiverStatusListener::receiverStatusChanged, this);
|
||||
}
|
||||
|
||||
void Receiver::dfeOffUpdateFromCma()
|
||||
{
|
||||
memcpy(m_dfe_off.eq.pW, m_cma.eq.pW, m_cma.N*sizeof(cpx_t));
|
||||
(Equalizer::AEqualizer &)m_dfe_off2 = (Equalizer::AEqualizer const &)m_cma2;
|
||||
m_statusListeners.call(&ReceiverStatusListener::receiverStatusChanged, this);
|
||||
}
|
||||
|
||||
void Receiver::dfeOnUpdateFromDfeOff()
|
||||
{
|
||||
memcpy(m_dfe_on.eq.pW, m_dfe_off.eq.pW, m_dfe_on.eq.N*sizeof(cpx_t));
|
||||
memcpy(m_dfe_on.eq.pW_conj, m_dfe_off.eq.pW_conj, m_dfe_on.eq.N*sizeof(cpx_t));
|
||||
m_dfe_on2 = m_dfe_off2;
|
||||
m_statusListeners.call(&ReceiverStatusListener::receiverStatusChanged, this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user