mirror of https://github.com/f4exb/sdrangel.git
Channel analyzer NG: return of the lock status indicator and PLL frequency shift for PSK modulated signals
This commit is contained in:
parent
6d95c04076
commit
9f48378677
|
@ -163,6 +163,7 @@ public:
|
||||||
int getChannelSampleRate() const { return m_running.m_channelSampleRate; }
|
int getChannelSampleRate() const { return m_running.m_channelSampleRate; }
|
||||||
double getMagSq() const { return m_magsq; }
|
double getMagSq() const { return m_magsq; }
|
||||||
bool isPllLocked() const { return m_running.m_pll && m_pll.locked(); }
|
bool isPllLocked() const { return m_running.m_pll && m_pll.locked(); }
|
||||||
|
Real getPllFrequency() const { return m_pll.getFreq(); }
|
||||||
Real getPllDeltaPhase() const { return m_pll.getDeltaPhi(); }
|
Real getPllDeltaPhase() const { return m_pll.getDeltaPhi(); }
|
||||||
Real getPllPhase() const { return m_pll.getPhiHat(); }
|
Real getPllPhase() const { return m_pll.getPhiHat(); }
|
||||||
|
|
||||||
|
|
|
@ -237,6 +237,12 @@ void ChannelAnalyzerNGGUI::tick()
|
||||||
} else {
|
} else {
|
||||||
ui->pll->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
|
ui->pll->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ui->pll->isChecked())
|
||||||
|
{
|
||||||
|
int freq = (m_channelAnalyzer->getPllFrequency() * m_channelAnalyzer->getChannelSampleRate()) / (2.0*M_PI);
|
||||||
|
ui->pll->setToolTip(tr("PLL lock. Freq = %1 Hz").arg(freq));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelAnalyzerNGGUI::on_channelSampleRate_changed(quint64 value)
|
void ChannelAnalyzerNGGUI::on_channelSampleRate_changed(quint64 value)
|
||||||
|
@ -251,8 +257,12 @@ void ChannelAnalyzerNGGUI::on_channelSampleRate_changed(quint64 value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelAnalyzerNGGUI::on_pll_toggled(bool checked __attribute__((unused)))
|
void ChannelAnalyzerNGGUI::on_pll_toggled(bool checked)
|
||||||
{
|
{
|
||||||
|
if (!checked) {
|
||||||
|
ui->pll->setToolTip(tr("PLL lock"));
|
||||||
|
}
|
||||||
|
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,10 @@ PhaseLockComplex::PhaseLockComplex() :
|
||||||
m_freq(0.0),
|
m_freq(0.0),
|
||||||
m_freqPrev(0.0),
|
m_freqPrev(0.0),
|
||||||
m_lockCount(0),
|
m_lockCount(0),
|
||||||
|
m_lockFreq(0.026f),
|
||||||
m_pskOrder(1),
|
m_pskOrder(1),
|
||||||
m_lockTime(480)
|
m_lockTime(480),
|
||||||
|
m_lockTimeCount(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +89,7 @@ void PhaseLockComplex::setPskOrder(unsigned int order)
|
||||||
void PhaseLockComplex::setSampleRate(unsigned int sampleRate)
|
void PhaseLockComplex::setSampleRate(unsigned int sampleRate)
|
||||||
{
|
{
|
||||||
m_lockTime = sampleRate / 100; // 10ms for order 1
|
m_lockTime = sampleRate / 100; // 10ms for order 1
|
||||||
|
m_lockFreq = (2.0*M_PI*5.0) / sampleRate; // +/- 5 Hz frequency swing
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +111,7 @@ void PhaseLockComplex::reset()
|
||||||
m_freq = 0.0f;
|
m_freq = 0.0f;
|
||||||
m_freqPrev = 0.0f;
|
m_freqPrev = 0.0f;
|
||||||
m_lockCount = 0;
|
m_lockCount = 0;
|
||||||
|
m_lockTimeCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhaseLockComplex::feed(float re, float im)
|
void PhaseLockComplex::feed(float re, float im)
|
||||||
|
@ -151,8 +155,41 @@ void PhaseLockComplex::feed(float re, float im)
|
||||||
m_phiHat += 2.0*M_PI;
|
m_phiHat += 2.0*M_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
// lock estimation
|
// lock and frequency estimation
|
||||||
if (m_pskOrder <= 1)
|
if (m_pskOrder > 1)
|
||||||
|
{
|
||||||
|
float dPhi = normalizeAngle(m_phiHat - m_phiHatPrev);
|
||||||
|
m_freq = 0.001*dPhi + 0.999*m_freqPrev;
|
||||||
|
|
||||||
|
if (m_lockTimeCount < m_lockTime-1)
|
||||||
|
{
|
||||||
|
m_lockTimeCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float dF = m_freq - m_freqTest;
|
||||||
|
|
||||||
|
if ((dF > -m_lockFreq) && (dF < m_lockFreq))
|
||||||
|
{
|
||||||
|
if (m_lockCount < 20) {
|
||||||
|
m_lockCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_lockCount > 0) {
|
||||||
|
m_lockCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_freqTest = m_freq;
|
||||||
|
m_lockTimeCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_freqPrev = m_freq;
|
||||||
|
m_phiHatPrev = m_phiHat;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
m_freq = (m_phiHat - m_phiHatPrev) / (2.0*M_PI);
|
m_freq = (m_phiHat - m_phiHatPrev) / (2.0*M_PI);
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,8 @@ public:
|
||||||
const std::complex<float>& getComplex() const { return m_y; }
|
const std::complex<float>& getComplex() const { return m_y; }
|
||||||
float getReal() const { return m_yRe; }
|
float getReal() const { return m_yRe; }
|
||||||
float getImag() const { return m_yIm; }
|
float getImag() const { return m_yIm; }
|
||||||
bool locked() const { return m_pskOrder > 1 ? false : m_lockCount > m_lockTime-2; }
|
bool locked() const { return m_pskOrder > 1 ? m_lockCount > 16 : m_lockCount > m_lockTime-2; }
|
||||||
|
float getFreq() const { return m_freq; }
|
||||||
float getDeltaPhi() const { return m_deltaPhi; }
|
float getDeltaPhi() const { return m_deltaPhi; }
|
||||||
float getPhiHat() const { return m_phiHat; }
|
float getPhiHat() const { return m_phiHat; }
|
||||||
|
|
||||||
|
@ -75,9 +76,12 @@ private:
|
||||||
float m_yIm;
|
float m_yIm;
|
||||||
float m_freq;
|
float m_freq;
|
||||||
float m_freqPrev;
|
float m_freqPrev;
|
||||||
|
float m_freqTest;
|
||||||
int m_lockCount;
|
int m_lockCount;
|
||||||
|
float m_lockFreq;
|
||||||
unsigned int m_pskOrder;
|
unsigned int m_pskOrder;
|
||||||
int m_lockTime;
|
int m_lockTime;
|
||||||
|
int m_lockTimeCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SDRBASE_DSP_PHASELOCKCOMPLEX_H_ */
|
#endif /* SDRBASE_DSP_PHASELOCKCOMPLEX_H_ */
|
||||||
|
|
|
@ -90,6 +90,11 @@ class MovingAverageUtilVar
|
||||||
m_samples.resize(size);
|
m_samples.resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int size() const
|
||||||
|
{
|
||||||
|
return m_samples.size();
|
||||||
|
}
|
||||||
|
|
||||||
void operator()(T sample)
|
void operator()(T sample)
|
||||||
{
|
{
|
||||||
if (m_num_samples < m_samples.size()) // fill up
|
if (m_num_samples < m_samples.size()) // fill up
|
||||||
|
|
Loading…
Reference in New Issue