Frequency tracker (4)

This commit is contained in:
f4exb 2019-05-04 22:00:24 +02:00
parent e1662d2f4e
commit 459063d4f2
4 changed files with 116 additions and 17 deletions

View File

@ -18,6 +18,7 @@
#include "freqtracker.h"
#include <QTime>
#include <QTimer>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
@ -61,10 +62,21 @@ FreqTracker::FreqTracker(DeviceSourceAPI *deviceAPI) :
m_magsqSum(0.0f),
m_magsqPeak(0.0f),
m_magsqCount(0),
m_timerConnected(false),
m_tickCount(0),
m_lastCorrAbs(0),
m_avgDeltaFreq(0.0),
m_settingsMutex(QMutex::Recursive)
{
setObjectName(m_channelId);
#ifdef USE_INTERNAL_TIMER
#warning "Uses internal timer"
m_timer = new QTimer();
m_timer->start(50);
#else
m_timer = &DSPEngine::instance()->getMasterTimer();
#endif
m_magsq = 0.0;
m_channelizer = new DownChannelizer(this);
@ -82,6 +94,11 @@ FreqTracker::FreqTracker(DeviceSourceAPI *deviceAPI) :
FreqTracker::~FreqTracker()
{
disconnectTimer();
#ifdef USE_INTERNAL_TIMER
m_timer->stop();
delete m_timer;
#endif
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
m_deviceAPI->removeChannelAPI(this);
@ -243,7 +260,7 @@ bool FreqTracker::handleMessage(const Message& cmd)
void FreqTracker::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force)
{
qDebug() << "AMDemod::applyChannelSettings:"
qDebug() << "FreqTracker::applyChannelSettings:"
<< " inputSampleRate: " << inputSampleRate
<< " inputFrequencyOffset: " << inputFrequencyOffset;
@ -320,16 +337,26 @@ void FreqTracker::applySettings(const FreqTrackerSettings& settings, bool force)
if ((m_settings.m_tracking != settings.m_tracking) || force)
{
reverseAPIKeys.append("tracking");
m_avgDeltaFreq = 0.0;
if (settings.m_tracking)
{
m_pll.reset();
m_fll.reset();
m_lastCorrAbs = 0;
connectTimer();
}
else
{
disconnectTimer();
}
}
if ((m_settings.m_trackerType != settings.m_trackerType) || force)
{
reverseAPIKeys.append("trackerType");
m_lastCorrAbs = 0;
m_avgDeltaFreq = 0.0;
if (settings.m_trackerType == FreqTrackerSettings::TrackerFLL) {
m_fll.reset();
@ -399,11 +426,32 @@ void FreqTracker::configureChannelizer()
if (m_guiMessageQueue)
{
MsgSampleRateNotification *msg = MsgSampleRateNotification::create(m_deviceSampleRate / (1<<m_settings.m_log2Decim));
MsgSampleRateNotification *msg = MsgSampleRateNotification::create(
m_deviceSampleRate / (1<<m_settings.m_log2Decim),
m_settings.m_inputFrequencyOffset);
m_guiMessageQueue->push(msg);
}
}
void FreqTracker::connectTimer()
{
if (!m_timerConnected)
{
m_tickCount = 0;
connect(m_timer, SIGNAL(timeout()), this, SLOT(tick()));
m_timerConnected = true;
}
}
void FreqTracker::disconnectTimer()
{
if (m_timerConnected)
{
disconnect(m_timer, SIGNAL(timeout()), this, SLOT(tick()));
m_timerConnected = false;
}
}
QByteArray FreqTracker::serialize() const
{
return m_settings.serialize();
@ -631,3 +679,38 @@ void FreqTracker::networkManagerFinished(QNetworkReply *reply)
answer.chop(1); // remove last \n
qDebug("FreqTracker::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}
void FreqTracker::tick()
{
if (getSquelchOpen() && (m_settings.m_trackerType != FreqTrackerSettings::TrackerNone)) {
m_avgDeltaFreq = 0.1*getFrequency() + 0.9*m_avgDeltaFreq;
}
if (m_tickCount < 19)
{
m_tickCount++;
}
else
{
if (getSquelchOpen() && (m_settings.m_trackerType != FreqTrackerSettings::TrackerNone))
{
int decayAmount = m_channelSampleRate < 100 ? 1 : m_channelSampleRate / 100;
if (m_lastCorrAbs < decayAmount)
{
FreqTrackerSettings settings = m_settings;
settings.m_inputFrequencyOffset += m_avgDeltaFreq;
m_lastCorrAbs = m_avgDeltaFreq < 0 ? m_avgDeltaFreq : m_avgDeltaFreq;
applySettings(settings);
}
else
{
if (m_lastCorrAbs >= decayAmount) {
m_lastCorrAbs -= decayAmount;
}
}
}
m_tickCount = 0;
}
}

View File

@ -43,6 +43,7 @@ class QNetworkReply;
class DeviceSourceAPI;
class DownChannelizer;
class ThreadedBasebandSampleSink;
class QTimer;
class fftfilt;
class FreqTracker : public BasebandSampleSink, public ChannelSinkAPI {
@ -98,20 +99,22 @@ public:
MESSAGE_CLASS_DECLARATION
public:
static MsgSampleRateNotification* create(int sampleRate) {
return new MsgSampleRateNotification(sampleRate);
static MsgSampleRateNotification* create(int sampleRate, int frequencyOffset) {
return new MsgSampleRateNotification(sampleRate, frequencyOffset);
}
int getSampleRate() const { return m_sampleRate; }
int getFrequencyOffset() const { return m_frequencyOffset; }
private:
MsgSampleRateNotification(int sampleRate) :
MsgSampleRateNotification(int sampleRate, int frequencyOffset) :
Message(),
m_sampleRate(sampleRate)
m_sampleRate(sampleRate),
m_frequencyOffset(frequencyOffset)
{ }
int m_sampleRate;
int m_frequencyOffset;
};
FreqTracker(DeviceSourceAPI *deviceAPI);
@ -149,6 +152,7 @@ public:
bool getSquelchOpen() const { return m_squelchOpen; }
bool getPllLocked() const { return (m_settings.m_trackerType == FreqTrackerSettings::TrackerPLL) && m_pll.locked(); }
Real getFrequency() const;
Real getAvgDeltaFreq() const { return m_avgDeltaFreq; }
void getMagSqLevels(double& avg, double& peak, int& nbSamples)
{
@ -222,12 +226,19 @@ private:
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
const QTimer *m_timer;
bool m_timerConnected;
uint32_t m_tickCount;
int m_lastCorrAbs;
Real m_avgDeltaFreq;
QMutex m_settingsMutex;
void applySettings(const FreqTrackerSettings& settings, bool force = false);
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force = false);
void setInterpolator();
void configureChannelizer();
void connectTimer();
void disconnectTimer();
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const FreqTrackerSettings& settings);
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreqTrackerSettings& settings, bool force);
@ -236,7 +247,7 @@ private:
private slots:
void networkManagerFinished(QNetworkReply *reply);
void tick();
};
#endif // INCLUDE_FREQTRACKER_H

View File

@ -111,6 +111,11 @@ bool FreqTrackerGUI::handleMessage(const Message& message)
const FreqTracker::MsgSampleRateNotification& cfg = (FreqTracker::MsgSampleRateNotification&) message;
m_channelSampleRate = cfg.getSampleRate();
ui->channelSampleRateText->setText(tr("%1k").arg(QString::number(m_channelSampleRate / 1000.0f, 'g', 5)));
blockApplySettings(true);
m_settings.m_inputFrequencyOffset = cfg.getFrequencyOffset();
ui->deltaFrequency->setValue(m_settings.m_inputFrequencyOffset);
m_channelMarker.setCenterFrequency(cfg.getFrequencyOffset());
blockApplySettings(false);
if (m_channelSampleRate > 1000) {
ui->rfBW->setMaximum(m_channelSampleRate/100);
@ -396,7 +401,7 @@ void FreqTrackerGUI::tick()
ui->tracking->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
}
int freq = m_freqTracker->getFrequency();
int freq = m_freqTracker->getAvgDeltaFreq();
QLocale loc;
ui->trackingFrequencyText->setText(tr("%1 Hz").arg(loc.toString(freq)));

View File

@ -153,9 +153,9 @@ bool DownChannelizer::handleMessage(const Message& cmd)
m_requestedOutputSampleRate = chan.getSampleRate();
m_requestedCenterFrequency = chan.getCenterFrequency();
qDebug() << "DownChannelizer::handleMessage: DSPConfigureChannelizer:"
<< " m_requestedOutputSampleRate: " << m_requestedOutputSampleRate
<< " m_requestedCenterFrequency: " << m_requestedCenterFrequency;
// qDebug() << "DownChannelizer::handleMessage: DSPConfigureChannelizer:"
// << " m_requestedOutputSampleRate: " << m_requestedOutputSampleRate
// << " m_requestedCenterFrequency: " << m_requestedCenterFrequency;
applyConfiguration();
@ -309,12 +309,12 @@ Real DownChannelizer::createFilterChain(Real sigStart, Real sigEnd, Real chanSta
Real sigBw = sigEnd - sigStart;
Real rot = sigBw / 4;
qDebug("DownChannelizer::createFilterChain: Signal [%.1f, %.1f] (BW %.1f), Channel [%.1f, %.1f], Rot %.1f", sigStart, sigEnd, sigBw, chanStart, chanEnd, rot);
//qDebug("DownChannelizer::createFilterChain: Signal [%.1f, %.1f] (BW %.1f), Channel [%.1f, %.1f], Rot %.1f", sigStart, sigEnd, sigBw, chanStart, chanEnd, rot);
// check if it fits into the left half
if(signalContainsChannel(sigStart, sigStart + sigBw / 2.0, chanStart, chanEnd))
{
qDebug("DownChannelizer::createFilterChain: -> take left half (rotate by +1/4 and decimate by 2)");
//qDebug("DownChannelizer::createFilterChain: -> take left half (rotate by +1/4 and decimate by 2)");
m_filterStages.push_back(new FilterStage(FilterStage::ModeLowerHalf));
return createFilterChain(sigStart, sigStart + sigBw / 2.0, chanStart, chanEnd);
}
@ -322,7 +322,7 @@ Real DownChannelizer::createFilterChain(Real sigStart, Real sigEnd, Real chanSta
// check if it fits into the right half
if(signalContainsChannel(sigEnd - sigBw / 2.0f, sigEnd, chanStart, chanEnd))
{
qDebug("DownChannelizer::createFilterChain: -> take right half (rotate by -1/4 and decimate by 2)");
//qDebug("DownChannelizer::createFilterChain: -> take right half (rotate by -1/4 and decimate by 2)");
m_filterStages.push_back(new FilterStage(FilterStage::ModeUpperHalf));
return createFilterChain(sigEnd - sigBw / 2.0f, sigEnd, chanStart, chanEnd);
}
@ -330,13 +330,13 @@ Real DownChannelizer::createFilterChain(Real sigStart, Real sigEnd, Real chanSta
// check if it fits into the center
if(signalContainsChannel(sigStart + rot, sigEnd - rot, chanStart, chanEnd))
{
qDebug("DownChannelizer::createFilterChain: -> take center half (decimate by 2)");
//qDebug("DownChannelizer::createFilterChain: -> take center half (decimate by 2)");
m_filterStages.push_back(new FilterStage(FilterStage::ModeCenter));
return createFilterChain(sigStart + rot, sigEnd - rot, chanStart, chanEnd);
}
Real ofs = ((chanEnd - chanStart) / 2.0 + chanStart) - ((sigEnd - sigStart) / 2.0 + sigStart);
qDebug("DownChannelizer::createFilterChain: -> complete (final BW %.1f, frequency offset %.1f)", sigBw, ofs);
//qDebug("DownChannelizer::createFilterChain: -> complete (final BW %.1f, frequency offset %.1f)", sigBw, ofs);
return ofs;
}