git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@929 b431acfa-c32f-4a4a-93f1-934dc6c82436
437 lines
9.4 KiB
C++
437 lines
9.4 KiB
C++
#ifndef _RECEIVER_H_
|
|
#define _RECEIVER_H_
|
|
|
|
#include <cstdint>
|
|
#include <radio/symbol.h>
|
|
#include <radio/synchronization.h>
|
|
#include <radio/interpolation.h>
|
|
#include <radio/statistics.h>
|
|
#include <radio/agc.h>
|
|
#include <cpp/radio/Frame.hpp>
|
|
|
|
#include <JuceHeader.h>
|
|
#include "LogComponent.h"
|
|
|
|
#include <cpp/radio/Vector.hpp>
|
|
#include <cpp/radio/FirComplex.hpp>
|
|
#include <cpp/radio/Equalizer.hpp>
|
|
#include <cpp/radio/interpolation/Farrow.hpp>
|
|
#include <cpp/radio/interpolation/DownSampler.hpp>
|
|
#include <cpp/radio/interpolation/PolyPhase.hpp>
|
|
|
|
#include <cpp/radio/Nco.hpp>
|
|
|
|
#ifdef _WINDOWS
|
|
#include <float.h>
|
|
#define isnan _isnan
|
|
#define isinf(x) (!_finite(x))
|
|
#endif
|
|
|
|
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 ¶ms) = 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(RVec const &rf, 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 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 ¶ms) 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_
|