Files
mpsk_rx_gui/Source/Receiver.h
T
jens 3c40649d6e - changed processBaseband args
- don't process CMA and DFE if they are not selected
- ToDo: encapsulate DFE-on and DFE-off in one class. Always feed X to prevent switch artifacts


git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@103 b431acfa-c32f-4a4a-93f1-934dc6c82436
2014-12-21 19:56:52 +00:00

428 lines
9.2 KiB
C++

#ifndef _RECEIVER_H_
#define _RECEIVER_H_
#include <cstdint>
#include <radio/symbol.h>
#include <radio/nco.h>
#include <radio/synchronization.h>
#include <radio/interpolation.h>
#include <radio/statistics.h>
#include <radio/equalizer.h>
#include <radio/agc.h>
#include <radio/Frame.hpp>
#include "JuceHeader.h"
#include "LogComponent.h"
#include <radio/FirComplex.hpp>
#include <radio/Equalizer.hpp>
#include <radio/Interpolation.hpp>
using namespace Radio;
// ---------------------------------------------------
#define NUM_PASSBAND_SAMPLES_PER_SYM 4
#define NUM_BASEBAND_SAMPLES_PER_SYM 2
#define MODE_PROCESS_PASSBAND 0
#define MODE_PROCESS_BASEBAND 1
#define RCF_TYPE_POLYPHASE_DISCRETE 0
#define RCF_TYPE_POLYPHASE_FARROW 1
#define EQ_ENABLE 1
#define MODULATION_TYPE MAP_MODE_QAM
#define RCF_TYPE RCF_TYPE_POLYPHASE_FARROW
#define MAX_NUMBITS_PERSYM 16
// ---------------------------------------------------
enum eq_mode
{
eq_mode_disabled,
eq_mode_cma,
eq_mode_dfe
};
enum cma_type
{
cma_type_cma = 0,
cma_type_mma,
cma_type_smma
};
enum cma_mode
{
cma_mode_training_disabled = 0,
cma_mode_training_enabled
};
enum dfe_mode
{
dfe_mode_training_disabled = 0,
dfe_mode_training_enabled
};
enum agc_mode
{
agc_mode_disabled = 0,
agc_mode_enabled
};
enum agc_state
{
agc_state_acquisition = 0,
agc_state_track
};
enum cpr_mode
{
cpr_mode_disabled = 0,
cpr_mode_enabled
};
enum cpr_state
{
cpr_state_acquisition = 0,
cpr_state_track
};
enum str_mode
{
str_mode_disabled = 0,
str_mode_enabled
};
enum str_state
{
str_state_acquisition = 0,
str_state_track
};
typedef struct _minmax_t
{
float min, max;
} minmax_t;
typedef struct _cpx_minmax_t
{
cpx_t min, max;
float magMin, magMax;
float phiAtMinI;
float phiAtMaxI;
float phiAtMinQ;
float phiAtMaxQ;
} cpx_minmax_t;
typedef struct _statistics_t
{
sl_var_t RF;
sl_var_t I_DDC;
sl_var_t Q_DDC;
sl_var_t I_MF;
sl_var_t Q_MF;
sl_var_t I_CPR;
sl_var_t Q_CPR;
sl_var_t I_AGC;
sl_var_t Q_AGC;
sl_var_t I_EQ;
sl_var_t Q_EQ;
sl_var_t I_decision;
sl_var_t Q_decision;
sl_var_t MagDecision;
sl_var_t PhiDecision;
sl_var_t sym_err_mag;
sl_var_t sym_err_phi;
sl_var_t noise;
sl_var_t noise_cma;
sl_var_t noise_str;
sl_var_t noise_cpr;
sl_var_t noise_dfe_on;
sl_var_t noise_dfe_off;
sl_minmax_t sl_min_I;
sl_minmax_t sl_max_I;
sl_minmax_t sl_min_Q;
sl_minmax_t sl_max_Q;
sl_minmax_t sl_min_mag;
sl_minmax_t sl_max_mag;
cpx_minmax_t ddcMinMax;
} statistics_t;
typedef struct _params_t
{
uint32_t numBitsPerSymbol;
float symbolrate;
float samplerate;
float ddc_freq;
float CPR_phase;
bool dfeAutoUpdateEnable;
bool strAutoControlEnable;
bool cprAutoControlEnable;
bool agcAutoControlEnable;
enum str_mode str_mode;
enum cpr_mode cpr_mode;
enum agc_mode agc_mode;
enum eq_mode eq_mode;
enum cma_type cmaType;
enum cma_mode cmaMode;
enum dfe_mode dfeMode;
lead_lag_coeff_t str_loopfilter_coeff[2];
uint32_t str_loopfilter_coeff_index;
lead_lag_coeff_t cpr_loopfilter_coeff[2];
uint32_t cpr_loopfilter_coeff_index;
float eqMuCma;
float eqMuDfe;
float agcMu[2];
uint32_t agcMu_index;
enum str_state strState;
enum cpr_state cprState;
enum agc_state agc_state;
} params_t;
typedef struct _status_t
{
uint32 numSymbolsReceived;
frame_statistics_t frameStatRx;
float noiseStr;
float noiseCpr;
float EB_N0;
float powerRF_dB;
float powerDDC_dB;
float powerMF_dB;
float powerCPR_dB;
float powerAGC_dB;
float powerEQ_dB;
float powerDecison_dB;
float powerMagDecision_dB;
float powerPhiDecision_dB;
float snrCurrent_dB;
float snrCma_dB;
float snrDfeOn_dB;
float snrDfeOff_dB;
float snrSymbolMagnitude_dB;
float snrSymbolPhase_dB;
float deltaFrequencyCPR;
float deltaFrequencySTR;
float agcGain[2];
minmax_t rfMinMax;
cpx_minmax_t ddcMinMax;
} status_t;
class Receiver;
// ---------------------------------------------------
class ReceiverInterface
{
public:
ReceiverInterface() {}
virtual ~ReceiverInterface() {}
virtual void setSamplerate(float samplerate_hz) = 0;
virtual void setParams(const params_t &params) = 0;
virtual const params_t& getParams() = 0;
virtual const status_t& getStatus() = 0;
virtual const cpx_t& getTracker(uint32 index) = 0;
virtual void reset() = 0;
virtual void statisticsReset() = 0;
virtual void strReset() = 0;
virtual void cprReset() = 0;
virtual void cmaReset() = 0;
virtual void dfeReset() = 0;
virtual void dfeOffUpdateFromCma() = 0;
virtual void dfeOnUpdateFromDfeOff() = 0;
virtual const CVec& getWeightsCMA() = 0;
virtual const CVec& getWeightsDFE() = 0;
};
class ReceiverStatusListener
{
public:
ReceiverStatusListener() {}
virtual ~ReceiverStatusListener() {}
virtual void receiverStatusChanged(ReceiverInterface *pReceiver) = 0;
};
class ReceiverDataListener
{
public:
ReceiverDataListener() {}
virtual ~ReceiverDataListener() {}
virtual void receiverDataChanged(Receiver *pObj) = 0;
};
class Receiver : public ReceiverInterface, public IDeFormatter, public Timer
{
public:
Receiver(LogHandler *pLogHandler);
~Receiver(void);
void init();
void free();
void processBaseband(float *pI, float *pQ, uint32_t len);
void processPassband(float *pRF, uint32_t len);
void setBufSize(uint32 size);
uint32 getNumSoftSym();
sym_err_t getSoftSym(uint32 index);
sym_err_t* getSoftSyms();
void initDefaultParams();
void addStatusListener(ReceiverStatusListener *pListener);
void addDataListener(ReceiverDataListener *pListener);
private:
ListenerList<ReceiverStatusListener> m_statusListeners;
LogComponent m_log;
ReceiverDataListener *m_pDataListener;
CriticalSection m_lock;
cpx_t *m_pPassbandBuffer;
cpx_t *m_pBasebandBuffer;
CVec m_passbandBuffer;
CVec m_basebandBuffer;
sym_err_t *m_pSymbolBuffer;
uint32_t m_numSymsInBuffer;
uint32_t m_bufsize;
bool m_ReceiverEnable;
sample_clock_t m_symClock;
pfd_t m_pfdCpr;
cpx_t m_trackers_[4];
cpx_t m_trackers[4];
// Filter
Interpolation::DownSampler m_firArmDown;
// Interpolators
Interpolation::PolyPhase m_polyPhase;
Interpolation::Farrow m_farrow;
// NCOs
nco_t m_nco_ddc, m_nco_cpr;
radio_float_t m_dOmega_vco;
// Loop-Filter
lead_lag_filter_t m_loop_filter_str;
lead_lag_filter_t m_loop_filter_cpr;
// Gardner Symbol Timing Recovery
str_t m_SymbolTimingRevovery;
timing_corrector_t m_timing_corrector;
radio_float_t m_Vc;
// AGC
// Blind
agc_t agcBlind;
// Equalizer
// Decision directed EQ
Equalizer::Dfe m_dfe_on2;
Equalizer::Dfe m_dfe_off2;
cpx_t m_dfe_e_cpx;
// Blind EQ
Equalizer::Cma m_cma2;
// Symbol demapper
sym_map_t *m_pSymMapper;
// Staticstics
sym_stat_t m_sym_stat;
statistics_t m_statistics;
FrameReceiver m_frameReceiver;
params_t m_params;
void timerCallback();
void processBaseband(CVec const &iq, uint32_t len);
void minMaxInit(minmax_t *pObj, radio_float_t min_initial, radio_float_t max_initial)
{
pObj->min = min_initial;
pObj->max = max_initial;
}
void minMaxInit(cpx_minmax_t *pObj, cpx_t min_initial, cpx_t max_initial)
{
pObj->min = min_initial;
pObj->max = max_initial;
pObj->magMin = 1000;
pObj->magMax = -1000;
}
void minMaxProcess(minmax_t *pObj, radio_float_t x)
{
pObj->min = dmin(pObj->min, x);
pObj->max = dmax(pObj->max, x);
}
void minMaxProcess(cpx_minmax_t *pObj, cpx_t x)
{
if (CpxMagS(x) >= pObj->magMax)
{
if (x.real > 0 && x.imag > 0)
pObj->phiAtMaxI = CpxPhiS(x);
if (x.real > 0 && x.imag < 0)
pObj->phiAtMaxQ = CpxPhiS(x);
if (x.real < 0 && x.imag < 0)
pObj->phiAtMinQ = CpxPhiS(x);
if (x.real < 0 && x.imag > 0)
pObj->phiAtMinI = CpxPhiS(x);
}
pObj->min.real = SlidingMinMaxProcess(&m_statistics.sl_min_I, x.real);
pObj->max.real = SlidingMinMaxProcess(&m_statistics.sl_max_I, x.real);
pObj->min.imag = SlidingMinMaxProcess(&m_statistics.sl_min_Q, x.imag);
pObj->max.imag = SlidingMinMaxProcess(&m_statistics.sl_max_Q, x.imag);
pObj->magMin = SlidingMinMaxProcess(&m_statistics.sl_min_mag, CpxMagS(x));
pObj->magMax = SlidingMinMaxProcess(&m_statistics.sl_max_mag, CpxMagS(x));
}
void initFilterArm();
void initFilterRcf();
void initSymbolMapper();
void initSTR();
void initCPR();
void initDDC();
// Interface
void setSamplerate(float samplerate_hz) override;
void setParams(const params_t &params) override;
params_t& getParams() override;
status_t& getStatus() override;
void reset() override;
void strReset() override;
void cprReset() override;
void dfeReset() override;
void cmaReset() override;
void statisticsReset() override;
void dfeOffUpdateFromCma() override;
void dfeOnUpdateFromDfeOff() override;
cpx_t& getTracker(uint32 index) override;
void onData(void *pData, uint32_t size) override
{
// Received raw data
(void)pData;
(void)size;
}
const CVec& getWeightsCMA() override
{
return m_cma2.getWeights();
}
const CVec& getWeightsDFE() override
{
return m_dfe_off2.getWeights();
}
trace_t m_trace;
};
#endif // _RECEIVER_H_