- CPR/STR: no automatic change of ACQ and TRK states base on SNR
- No use for clock stuff, since buffer_ip is decimated - use Costas Loop for acquisition git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@1052 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
+40
-30
@@ -345,14 +345,14 @@ void Receiver::timerCallback()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Control
|
// Control
|
||||||
m_params.cprState = cpr_state_acquisition;
|
// m_params.cprState = cpr_state_acquisition;
|
||||||
m_params.strState = str_state_acquisition;
|
// m_params.strState = str_state_acquisition;
|
||||||
if (getStatus().snrCurrent_dB > 30)
|
// if (getStatus().snrCurrent_dB > 30)
|
||||||
{
|
// {
|
||||||
// statusHasChanged = (m_params.cprState != cpr_state_track) || (m_params.strState != str_state_track);
|
// statusHasChanged = (m_params.cprState != cpr_state_track) || (m_params.strState != str_state_track);
|
||||||
m_params.cprState = cpr_state_track;
|
// m_params.cprState = cpr_state_track;
|
||||||
m_params.strState = str_state_track;
|
// m_params.strState = str_state_track;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Announce status changed
|
// Announce status changed
|
||||||
if (statusHasChanged)
|
if (statusHasChanged)
|
||||||
@@ -477,32 +477,21 @@ void Receiver::processBaseband(CVec const &iq, uint32_t len)
|
|||||||
m_polyPhase.process();
|
m_polyPhase.process();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Further BB processing
|
|
||||||
// @2 x symbolrate
|
|
||||||
while(m_buffer_ip.len())
|
|
||||||
{
|
|
||||||
ComplexScalar iq_mf = m_buffer_ip.readAt(0);
|
|
||||||
|
|
||||||
// -----------------------------------------------------
|
|
||||||
// Carrier Derotator
|
|
||||||
// @2 x symbolrate
|
|
||||||
// -----------------------------------------------------
|
|
||||||
IQ_cpr = toCpx(m_nco_cpr.mixComplexS(iq_mf, ComplexScalar(1,1)));
|
|
||||||
m_nco_cpr.process(m_dOmega_vco, m_params.CPR_phase);
|
|
||||||
|
|
||||||
IQ_eq_in = IQ_cpr;
|
|
||||||
|
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
// Big and ugly processing loop
|
// Big and ugly processing loop
|
||||||
|
// Further BB processing
|
||||||
// @1 x symbolrate
|
// @1 x symbolrate
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
if (ClockIsTick(&m_symClock, 1))
|
while(m_buffer_ip.len())
|
||||||
{
|
{
|
||||||
|
// Buffer contains every 2nd sample from interpolator
|
||||||
|
ComplexScalar iq_mf = m_buffer_ip.readAt(0);
|
||||||
|
|
||||||
#ifndef DISABLE_UNUSED_STATISTICS
|
#ifndef DISABLE_UNUSED_STATISTICS
|
||||||
minMaxProcess(&m_statistics.ddcMinMax, IQ_eq_in);
|
minMaxProcess(&m_statistics.ddcMinMax, iq_mf);
|
||||||
#endif
|
#endif
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
// AGC Blind process samples
|
// AGC Tracker based training
|
||||||
// @1 x symbolrate
|
// @1 x symbolrate
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
if (m_params.agc_mode != agc_mode_disabled)
|
if (m_params.agc_mode != agc_mode_disabled)
|
||||||
@@ -519,6 +508,22 @@ void Receiver::processBaseband(CVec const &iq, uint32_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------
|
||||||
|
// Carrier Derotator
|
||||||
|
// @1 x symbolrate
|
||||||
|
// -----------------------------------------------------
|
||||||
|
IQ_cpr = toCpx(m_nco_cpr.mixComplexS(iq_mf, ComplexScalar(1,1)));
|
||||||
|
m_nco_cpr.process(m_dOmega_vco, m_params.CPR_phase);
|
||||||
|
|
||||||
|
// Carrier Phase Recovery
|
||||||
|
if (m_params.cprState == cpr_state_acquisition)
|
||||||
|
{
|
||||||
|
// Costas loop
|
||||||
|
vPfdCpr = PhaseErrQPSK(IQ_cpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IQ_eq_in = IQ_cpr;
|
||||||
|
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
// Equalizer Process samples
|
// Equalizer Process samples
|
||||||
// @1 x symbolrate
|
// @1 x symbolrate
|
||||||
@@ -552,12 +557,19 @@ void Receiver::processBaseband(CVec const &iq, uint32_t len)
|
|||||||
IQ_hard = sym_err.hard_sym;
|
IQ_hard = sym_err.hard_sym;
|
||||||
|
|
||||||
// Carrier Phase Recovery
|
// Carrier Phase Recovery
|
||||||
if (m_params.cpr_mode == cpr_mode_enabled)
|
if (m_params.cprState == cpr_state_track)
|
||||||
{
|
{
|
||||||
// state-based PFD
|
// state-based PFD
|
||||||
vPfdCpr = PfdProcess(&m_pfdCpr, sym_err.err_phi, dabs(sym_err.mag));
|
vPfdCpr = PfdProcess(&m_pfdCpr, sym_err.err_phi, dabs(sym_err.mag));
|
||||||
|
}
|
||||||
|
|
||||||
// use phase error from symbol mapper
|
if (m_params.cpr_mode == cpr_mode_enabled)
|
||||||
|
{
|
||||||
|
// Update frequency from Carrier Derotator
|
||||||
|
// vPfdCpr comes from PhaseErrQPSK forming a Costas Loop when
|
||||||
|
// cprState == cpr_state_acquisition
|
||||||
|
// vPfdCpr comes from SymMapper forming a decision directed phase correction loop when
|
||||||
|
// cprState == cpr_state_track
|
||||||
m_dOmega_vco = LeadLagProcess(&m_loop_filter_cpr, &m_params.cpr_loopfilter_coeff[m_params.cpr_loopfilter_coeff_index], vPfdCpr);
|
m_dOmega_vco = LeadLagProcess(&m_loop_filter_cpr, &m_params.cpr_loopfilter_coeff[m_params.cpr_loopfilter_coeff_index], vPfdCpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,13 +659,11 @@ void Receiver::processBaseband(CVec const &iq, uint32_t len)
|
|||||||
|
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
m_pSymbolBuffer[m_numSymsInBuffer++] = sym_err;
|
m_pSymbolBuffer[m_numSymsInBuffer++] = sym_err;
|
||||||
if ((m_params.strState == str_state_track) && (m_params.cprState == cpr_state_track))
|
|
||||||
{
|
|
||||||
// Update per-symbol statistic
|
// Update per-symbol statistic
|
||||||
SymStatUpDate(&m_sym_stat, sym, &sym_err);
|
SymStatUpDate(&m_sym_stat, sym, &sym_err);
|
||||||
m_frameReceiver.process((symbol_t)sym);
|
m_frameReceiver.process((symbol_t)sym);
|
||||||
}
|
|
||||||
if (m_pDataListener)
|
if (m_pDataListener)
|
||||||
|
{
|
||||||
m_pDataListener->receiverDataChanged(this);
|
m_pDataListener->receiverDataChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -306,7 +306,7 @@ class TimingGeneratorGardner : public Interpolation::TimingGenerator
|
|||||||
coeff = pCoeff;
|
coeff = pCoeff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void process(ComplexScalar const &iq)
|
bool process(ComplexScalar const &iq)
|
||||||
{
|
{
|
||||||
// @2 x symbolrate
|
// @2 x symbolrate
|
||||||
// Symbol timing recovery
|
// Symbol timing recovery
|
||||||
@@ -320,6 +320,8 @@ class TimingGeneratorGardner : public Interpolation::TimingGenerator
|
|||||||
is_time = not is_time;
|
is_time = not is_time;
|
||||||
|
|
||||||
update(m_omega);
|
update(m_omega);
|
||||||
|
|
||||||
|
return not is_time;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user