diff --git a/plugins/channelrx/freqtracker/freqtracker.cpp b/plugins/channelrx/freqtracker/freqtracker.cpp index 78a4db5de..5cd70d82c 100644 --- a/plugins/channelrx/freqtracker/freqtracker.cpp +++ b/plugins/channelrx/freqtracker/freqtracker.cpp @@ -18,6 +18,7 @@ #include "freqtracker.h" #include +#include #include #include #include @@ -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<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; + } +} \ No newline at end of file diff --git a/plugins/channelrx/freqtracker/freqtracker.h b/plugins/channelrx/freqtracker/freqtracker.h index 97e5125d6..4bbd76fd0 100644 --- a/plugins/channelrx/freqtracker/freqtracker.h +++ b/plugins/channelrx/freqtracker/freqtracker.h @@ -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& channelSettingsKeys, const FreqTrackerSettings& settings, bool force); @@ -236,7 +247,7 @@ private: private slots: void networkManagerFinished(QNetworkReply *reply); - + void tick(); }; #endif // INCLUDE_FREQTRACKER_H diff --git a/plugins/channelrx/freqtracker/freqtrackergui.cpp b/plugins/channelrx/freqtracker/freqtrackergui.cpp index 12421965e..4afbd4278 100644 --- a/plugins/channelrx/freqtracker/freqtrackergui.cpp +++ b/plugins/channelrx/freqtracker/freqtrackergui.cpp @@ -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))); diff --git a/sdrbase/dsp/downchannelizer.cpp b/sdrbase/dsp/downchannelizer.cpp index 3b76144d1..e82403032 100644 --- a/sdrbase/dsp/downchannelizer.cpp +++ b/sdrbase/dsp/downchannelizer.cpp @@ -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; }