- renamded
git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@890 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -0,0 +1,433 @@
|
||||
#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.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_
|
||||
Reference in New Issue
Block a user