mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 10:05:46 -05:00
Frequency tracker (4)
This commit is contained in:
parent
e1662d2f4e
commit
459063d4f2
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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)));
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user