SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
freqtracker.cpp
Go to the documentation of this file.
1 // Copyright (C) 2019 Edouard Griffiths, F4EXB. //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include "freqtracker.h"
19 
20 #include <QTime>
21 #include <QTimer>
22 #include <QDebug>
23 #include <QNetworkAccessManager>
24 #include <QNetworkReply>
25 #include <QBuffer>
26 
27 #include <stdio.h>
28 #include <complex.h>
29 
30 #include "SWGChannelSettings.h"
31 #include "SWGFreqTrackerSettings.h"
32 #include "SWGChannelReport.h"
33 #include "SWGFreqTrackerReport.h"
34 
35 #include "dsp/downchannelizer.h"
36 #include "audio/audiooutput.h"
37 #include "dsp/dspengine.h"
39 #include "dsp/dspcommands.h"
40 #include "dsp/fftfilt.h"
41 #include "device/deviceapi.h"
42 #include "util/db.h"
43 #include "util/stepfunctions.h"
44 
48 
49 const QString FreqTracker::m_channelIdURI = "sdrangel.channel.freqtracker";
50 const QString FreqTracker::m_channelId = "FreqTracker";
51 const int FreqTracker::m_udpBlockSize = 512;
52 
54  ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink),
55  m_deviceAPI(deviceAPI),
56  m_deviceSampleRate(48000),
57  m_inputSampleRate(48000),
58  m_inputFrequencyOffset(0),
59  m_channelSampleRate(48000),
60  m_running(false),
61  m_squelchOpen(false),
62  m_squelchGate(0),
63  m_magsqSum(0.0f),
64  m_magsqPeak(0.0f),
65  m_magsqCount(0),
66  m_timerConnected(false),
67  m_tickCount(0),
68  m_lastCorrAbs(0),
69  m_avgDeltaFreq(0.0),
70  m_settingsMutex(QMutex::Recursive)
71 {
72  setObjectName(m_channelId);
73 
74 #ifdef USE_INTERNAL_TIMER
75 #warning "Uses internal timer"
76  m_timer = new QTimer();
77  m_timer->start(50);
78 #else
80 #endif
81  m_magsq = 0.0;
82 
84  m_pll.computeCoefficients(0.002f, 0.5f, 10.0f); // bandwidth, damping factor, loop gain
86 
87  m_channelizer = new DownChannelizer(this);
91 
92  m_networkManager = new QNetworkAccessManager();
93  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
94 }
95 
97 {
99 #ifdef USE_INTERNAL_TIMER
100  m_timer->stop();
101  delete m_timer;
102 #endif
103  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
104  delete m_networkManager;
107  delete m_threadedChannelizer;
108  delete m_channelizer;
109  delete m_rrcFilter;
110 }
111 
112 void FreqTracker::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst)
113 {
114  (void) firstOfBurst;
115  Complex ci;
116 
117  if (!m_running) {
118  return;
119  }
120 
121  m_settingsMutex.lock();
122 
123  for (SampleVector::const_iterator it = begin; it != end; ++it)
124  {
125  Complex c(it->real(), it->imag());
126  c *= m_nco.nextIQ();
127 
128  if (m_interpolatorDistance < 1.0f) // interpolate
129  {
130  processOneSample(ci);
131 
133  {
134  processOneSample(ci);
135  }
136 
138  }
139  else // decimate
140  {
142  {
143  processOneSample(ci);
145  }
146  }
147  }
148 
149  m_settingsMutex.unlock();
150 }
151 
153 {
154  fftfilt::cmplx *sideband;
155  int n_out;
156 
157  if (m_settings.m_rrc)
158  {
159  n_out = m_rrcFilter->runFilt(ci, &sideband);
160  }
161  else
162  {
163  n_out = 1;
164  sideband = &ci;
165  }
166 
167  for (int i = 0; i < n_out; i++)
168  {
169  Real re = sideband[i].real() / SDR_RX_SCALEF;
170  Real im = sideband[i].imag() / SDR_RX_SCALEF;
171  Real magsq = re*re + im*im;
172  m_movingAverage(magsq);
174  m_magsqSum += magsq;
175 
176  if (magsq > m_magsqPeak)
177  {
178  m_magsqPeak = magsq;
179  }
180 
181  m_magsqCount++;
182 
183  if (m_magsq < m_squelchLevel)
184  {
185  if (m_squelchGate > 0)
186  {
187  if (m_squelchCount > 0) {
188  m_squelchCount--;
189  }
190 
192  }
193  else
194  {
195  m_squelchOpen = false;
196  }
197  }
198  else
199  {
200  if (m_squelchGate > 0)
201  {
202  if (m_squelchCount < 2*m_squelchGate) {
203  m_squelchCount++;
204  }
205 
207  }
208  else
209  {
210  m_squelchOpen = true;
211  }
212  }
213 
214  if (m_squelchOpen)
215  {
217  {
218  m_fll.feed(re, im);
219  }
221  {
222  m_pll.feed(re, im);
223  }
224  }
225  }
226 }
227 
229 {
230  qDebug("FreqTracker::start");
231  m_squelchCount = 0;
233  m_running = true;
234 }
235 
237 {
238  qDebug("FreqTracker::stop");
239  m_running = false;
240 }
241 
243 {
245  return (m_pll.getFreq() * m_channelSampleRate) / (2.0 * M_PI);
247  return (m_fll.getFreq() * m_channelSampleRate) / (2.0 * M_PI);
248  } else {
249  return 0;
250  }
251 }
252 
254 {
256  {
259 
260  qDebug() << "FreqTracker::handleMessage: DSPSignalNotification:"
261  << " m_deviceSampleRate: " << m_deviceSampleRate
262  << " centerFrequency: " << notif.getCenterFrequency();
263 
265 
266  return true;
267  }
269  {
271 
272  if (!m_settings.m_tracking) {
273  qDebug() << "FreqTracker::handleMessage: MsgChannelizerNotification:"
274  << " inputSampleRate: " << notif.getSampleRate()
275  << " inputFrequencyOffset: " << notif.getFrequencyOffset();
276  }
277 
279  setInterpolator();
280 
281  return true;
282  }
283  else if (MsgConfigureFreqTracker::match(cmd))
284  {
286  qDebug() << "FreqTracker::handleMessage: MsgConfigureFreqTracker";
287  applySettings(cfg.getSettings(), cfg.getForce());
288 
289  return true;
290  }
291  else
292  {
293  return false;
294  }
295 }
296 
297 void FreqTracker::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force)
298 {
299  if (!m_settings.m_tracking) {
300  qDebug() << "FreqTracker::applyChannelSettings:"
301  << " inputSampleRate: " << inputSampleRate
302  << " inputFrequencyOffset: " << inputFrequencyOffset;
303  }
304 
305  if ((m_inputFrequencyOffset != inputFrequencyOffset) ||
306  (m_inputSampleRate != inputSampleRate) || force)
307  {
308  m_nco.setFreq(-inputFrequencyOffset, inputSampleRate);
309  }
310 
311  if ((m_inputSampleRate != inputSampleRate) || force) {
312  setInterpolator();
313  }
314 
315  m_inputSampleRate = inputSampleRate;
316  m_inputFrequencyOffset = inputFrequencyOffset;
317 }
318 
319 void FreqTracker::applySettings(const FreqTrackerSettings& settings, bool force)
320 {
321  if (!settings.m_tracking)
322  {
323  qDebug() << "FreqTracker::applySettings:"
324  << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
325  << " m_rfBandwidth: " << settings.m_rfBandwidth
326  << " m_log2Decim: " << settings.m_log2Decim
327  << " m_squelch: " << settings.m_squelch
328  << " m_rgbColor: " << settings.m_rgbColor
329  << " m_title: " << settings.m_title
330  << " m_alphaEMA: " << settings.m_alphaEMA
331  << " m_tracking: " << settings.m_tracking
332  << " m_trackerType: " << settings.m_trackerType
333  << " m_pllPskOrder: " << settings.m_pllPskOrder
334  << " m_rrc: " << settings.m_rrc
335  << " m_rrcRolloff: " << settings.m_rrcRolloff
336  << " m_useReverseAPI: " << settings.m_useReverseAPI
337  << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
338  << " m_reverseAPIPort: " << settings.m_reverseAPIPort
339  << " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex
340  << " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex
341  << " force: " << force;
342  }
343 
344  QList<QString> reverseAPIKeys;
345  bool updateChannelizer = false;
346  bool updateInterpolator = false;
347 
348  if ((m_settings.m_inputFrequencyOffset != settings.m_inputFrequencyOffset) || force)
349  {
350  reverseAPIKeys.append("inputFrequencyOffset");
351  updateChannelizer = true;
352  }
353 
354  if ((m_settings.m_log2Decim != settings.m_log2Decim) || force)
355  {
356  reverseAPIKeys.append("log2Decim");
357  updateChannelizer = true;
358  }
359 
360  if ((m_settings.m_rfBandwidth != settings.m_rfBandwidth) || force)
361  {
362  updateInterpolator = true;
363  reverseAPIKeys.append("rfBandwidth");
364  }
365 
366  if ((m_settings.m_squelch != settings.m_squelch) || force)
367  {
369  reverseAPIKeys.append("squelch");
370  }
371 
372  if ((m_settings.m_rgbColor != settings.m_rgbColor) || force) {
373  reverseAPIKeys.append("rgbColor");
374  }
375  if ((m_settings.m_title != settings.m_title) || force) {
376  reverseAPIKeys.append("title");
377  }
378  if ((m_settings.m_alphaEMA != settings.m_alphaEMA) || force) {
379  reverseAPIKeys.append("alphaEMA");
380  }
381 
382  if ((m_settings.m_tracking != settings.m_tracking) || force)
383  {
384  reverseAPIKeys.append("tracking");
385  m_avgDeltaFreq = 0.0;
386  m_lastCorrAbs = 0;
387 
388  if (settings.m_tracking)
389  {
390  m_pll.reset();
391  m_fll.reset();
392  }
393  }
394 
395  if ((m_settings.m_trackerType != settings.m_trackerType) || force)
396  {
397  reverseAPIKeys.append("trackerType");
398  m_lastCorrAbs = 0;
399  m_avgDeltaFreq = 0.0;
400 
402  m_fll.reset();
403  } else if (settings.m_trackerType == FreqTrackerSettings::TrackerPLL) {
404  m_pll.reset();
405  }
406 
408  disconnectTimer();
409  } else {
410  connectTimer();
411  }
412  }
413 
414  if ((m_settings.m_pllPskOrder != settings.m_pllPskOrder) || force)
415  {
416  reverseAPIKeys.append("pllPskOrder");
417 
418  if (settings.m_pllPskOrder < 32) {
419  m_pll.setPskOrder(settings.m_pllPskOrder);
420  }
421  }
422 
423  if ((m_settings.m_rrc != settings.m_rrc) || force) {
424  reverseAPIKeys.append("rrc");
425  }
426  if ((m_settings.m_rrcRolloff != settings.m_rrcRolloff) || force)
427  {
428  reverseAPIKeys.append("rrcRolloff");
429  updateInterpolator = true;
430  }
431  if ((m_settings.m_squelchGate != settings.m_squelchGate) || force)
432  {
433  reverseAPIKeys.append("squelchGate");
434  updateInterpolator = true;
435  }
436 
437  if (settings.m_useReverseAPI)
438  {
439  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
444  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
445  }
446 
447  m_settings = settings;
448 
449  if (updateChannelizer) {
451  } else if (updateInterpolator) {
452  setInterpolator();
453  }
454 }
455 
457 {
458  m_settingsMutex.lock();
463  m_squelchGate = (m_channelSampleRate / 100) * m_settings.m_squelchGate; // gate is given in 10s of ms at channel sample rate
464  m_settingsMutex.unlock();
465 }
466 
468 {
470  {
474  }
475 
476  if (!m_settings.m_tracking) {
477  qDebug() << "FreqTracker::configureChannelizer:"
478  << " sampleRate: " << m_channelSampleRate
479  << " inputFrequencyOffset: " << m_settings.m_inputFrequencyOffset;
480  }
481 
485 
486  if (m_guiMessageQueue)
487  {
491  m_guiMessageQueue->push(msg);
492  }
493 }
494 
496 {
497  if (!m_timerConnected)
498  {
499  m_tickCount = 0;
500  connect(m_timer, SIGNAL(timeout()), this, SLOT(tick()));
501  m_timerConnected = true;
502  }
503 }
504 
506 {
507  if (m_timerConnected)
508  {
509  disconnect(m_timer, SIGNAL(timeout()), this, SLOT(tick()));
510  m_timerConnected = false;
511  }
512 }
513 
514 QByteArray FreqTracker::serialize() const
515 {
516  return m_settings.serialize();
517 }
518 
519 bool FreqTracker::deserialize(const QByteArray& data)
520 {
521  if (m_settings.deserialize(data))
522  {
525  return true;
526  }
527  else
528  {
532  return false;
533  }
534 }
535 
538  QString& errorMessage)
539 {
540  (void) errorMessage;
542  response.getFreqTrackerSettings()->init();
544  return 200;
545 }
546 
548  bool force,
549  const QStringList& channelSettingsKeys,
551  QString& errorMessage)
552 {
553  (void) errorMessage;
554  FreqTrackerSettings settings = m_settings;
555 
556  if (channelSettingsKeys.contains("inputFrequencyOffset")) {
558  }
559  if (channelSettingsKeys.contains("rfBandwidth")) {
560  settings.m_rfBandwidth = response.getFreqTrackerSettings()->getRfBandwidth();
561  }
562  if (channelSettingsKeys.contains("log2Decim")) {
563  settings.m_log2Decim = response.getFreqTrackerSettings()->getLog2Decim();
564  }
565  if (channelSettingsKeys.contains("squelch")) {
566  settings.m_squelch = response.getFreqTrackerSettings()->getSquelch();
567  }
568  if (channelSettingsKeys.contains("rgbColor")) {
569  settings.m_rgbColor = response.getFreqTrackerSettings()->getRgbColor();
570  }
571  if (channelSettingsKeys.contains("title")) {
572  settings.m_title = *response.getFreqTrackerSettings()->getTitle();
573  }
574  if (channelSettingsKeys.contains("alphaEMA")) {
575  float alphaEMA = response.getFreqTrackerSettings()->getAlphaEma();
576  settings.m_alphaEMA = alphaEMA < 0.01 ? 0.01 : alphaEMA > 1.0 ? 1.0 : alphaEMA;
577  }
578  if (channelSettingsKeys.contains("tracking")) {
579  settings.m_tracking = response.getFreqTrackerSettings()->getTracking() ? 1 : 0;
580  }
581  if (channelSettingsKeys.contains("trackerType"))
582  {
583  int32_t trackerTypeCode = response.getFreqTrackerSettings()->getTrackerType();
584  settings.m_trackerType = trackerTypeCode < 0 ?
585  FreqTrackerSettings::TrackerFLL : trackerTypeCode > 1 ?
587  }
588  if (channelSettingsKeys.contains("pllPskOrder")) {
589  settings.m_pllPskOrder = response.getFreqTrackerSettings()->getPllPskOrder();
590  }
591  if (channelSettingsKeys.contains("rrc")) {
592  settings.m_rrc = response.getFreqTrackerSettings()->getRrc() ? 1 : 0;
593  }
594  if (channelSettingsKeys.contains("rrcRolloff")) {
595  settings.m_rrcRolloff = response.getFreqTrackerSettings()->getRrcRolloff();
596  }
597  if (channelSettingsKeys.contains("squelchGate")) {
598  settings.m_squelchGate = response.getFreqTrackerSettings()->getSquelchGate();
599  }
600  if (channelSettingsKeys.contains("useReverseAPI")) {
601  settings.m_useReverseAPI = response.getAmDemodSettings()->getUseReverseApi() != 0;
602  }
603  if (channelSettingsKeys.contains("reverseAPIAddress")) {
605  }
606  if (channelSettingsKeys.contains("reverseAPIPort")) {
607  settings.m_reverseAPIPort = response.getAmDemodSettings()->getReverseApiPort();
608  }
609  if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
611  }
612  if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
614  }
615 
618 
619  qDebug("FreqTracker::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
620  if (m_guiMessageQueue) // forward to GUI if any
621  {
622  MsgConfigureFreqTracker *msgToGUI = MsgConfigureFreqTracker::create(settings, force);
623  m_guiMessageQueue->push(msgToGUI);
624  }
625 
626  webapiFormatChannelSettings(response, settings);
627 
628  return 200;
629 }
630 
633  QString& errorMessage)
634 {
635  (void) errorMessage;
637  response.getFreqTrackerReport()->init();
638  webapiFormatChannelReport(response);
639  return 200;
640 }
641 
643 {
646  response.getFreqTrackerSettings()->setLog2Decim(settings.m_log2Decim);
647  response.getFreqTrackerSettings()->setSquelch(settings.m_squelch);
648  response.getFreqTrackerSettings()->setRgbColor(settings.m_rgbColor);
649 
650  if (response.getFreqTrackerSettings()->getTitle()) {
651  *response.getFreqTrackerSettings()->getTitle() = settings.m_title;
652  } else {
653  response.getFreqTrackerSettings()->setTitle(new QString(settings.m_title));
654  }
655 
660  response.getFreqTrackerSettings()->setRrc(m_settings.m_rrc ? 1 : 0);
663  response.getFreqTrackerSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
664 
665  if (response.getFreqTrackerSettings()->getReverseApiAddress()) {
667  } else {
668  response.getFreqTrackerSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
669  }
670 
674 }
675 
677 {
678  double magsqAvg, magsqPeak;
679  int nbMagsqSamples;
680  getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
681 
683  response.getFreqTrackerReport()->setSquelch(m_squelchOpen ? 1 : 0);
686 }
687 
688 void FreqTracker::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreqTrackerSettings& settings, bool force)
689 {
691  swgChannelSettings->setDirection(0); // single sink (Rx)
692  swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
693  swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
694  swgChannelSettings->setChannelType(new QString("FreqTracker"));
696  SWGSDRangel::SWGFreqTrackerSettings *swgFreqTrackerSettings = swgChannelSettings->getFreqTrackerSettings();
697 
698  // transfer data that has been modified. When force is on transfer all data except reverse API data
699 
700  if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
701  swgFreqTrackerSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
702  }
703  if (channelSettingsKeys.contains("rfBandwidth") || force) {
704  swgFreqTrackerSettings->setRfBandwidth(settings.m_rfBandwidth);
705  }
706  if (channelSettingsKeys.contains("rgbColor") || force) {
707  swgFreqTrackerSettings->setRgbColor(settings.m_rgbColor);
708  }
709  if (channelSettingsKeys.contains("squelch") || force) {
710  swgFreqTrackerSettings->setSquelch(settings.m_squelch);
711  }
712  if (channelSettingsKeys.contains("title") || force) {
713  swgFreqTrackerSettings->setTitle(new QString(settings.m_title));
714  }
715  if (channelSettingsKeys.contains("trackerType") || force) {
716  swgFreqTrackerSettings->setTrackerType((int) settings.m_trackerType);
717  }
718 
719  QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
720  .arg(settings.m_reverseAPIAddress)
721  .arg(settings.m_reverseAPIPort)
722  .arg(settings.m_reverseAPIDeviceIndex)
723  .arg(settings.m_reverseAPIChannelIndex);
724  m_networkRequest.setUrl(QUrl(channelSettingsURL));
725  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
726 
727  QBuffer *buffer=new QBuffer();
728  buffer->open((QBuffer::ReadWrite));
729  buffer->write(swgChannelSettings->asJson().toUtf8());
730  buffer->seek(0);
731 
732  // Always use PATCH to avoid passing reverse API settings
733  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
734 
735  delete swgChannelSettings;
736 }
737 
738 void FreqTracker::networkManagerFinished(QNetworkReply *reply)
739 {
740  QNetworkReply::NetworkError replyError = reply->error();
741 
742  if (replyError)
743  {
744  qWarning() << "FreqTracker::networkManagerFinished:"
745  << " error(" << (int) replyError
746  << "): " << replyError
747  << ": " << reply->errorString();
748  return;
749  }
750 
751  QString answer = reply->readAll();
752  answer.chop(1); // remove last \n
753  qDebug("FreqTracker::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
754 }
755 
757 {
758  if (getSquelchOpen()) {
760  }
761 
762  if (m_tickCount < 9)
763  {
764  m_tickCount++;
765  }
766  else
767  {
769  {
770  uint32_t decayDivider = 200.0 * m_settings.m_alphaEMA;
771  int decayAmount = m_channelSampleRate < decayDivider ? 1 : m_channelSampleRate / decayDivider;
772  int trim = m_channelSampleRate / 1000;
773 
774  if (m_lastCorrAbs < decayAmount)
775  {
777 
778  if (m_lastCorrAbs > trim)
779  {
780  FreqTrackerSettings settings = m_settings;
782  applySettings(settings);
783  }
784  }
785  else
786  {
787  m_lastCorrAbs -= decayAmount;
788  }
789  }
790 
791  m_tickCount = 0;
792  }
793 }
uint32_t m_squelchCount
Definition: freqtracker.h:225
void setOriginatorChannelIndex(qint32 originator_channel_index)
fftfilt * m_rrcFilter
Definition: freqtracker.h:222
void applySettings(const FreqTrackerSettings &settings, bool force=false)
bool decimate(Real *distance, const Complex &next, Complex *result)
Definition: interpolator.h:38
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
FreqTracker(DeviceAPI *deviceAPI)
Definition: freqtracker.cpp:53
void removeChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:163
static double dbPower(double magsq, double floor=1e-12)
Definition: db.cpp:22
void addChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:156
void setFreqTrackerReport(SWGFreqTrackerReport *freq_tracker_report)
FreqLockComplex m_fll
Definition: freqtracker.h:217
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
bool interpolate(Real *distance, const Complex &next, Complex *result)
Definition: interpolator.h:53
void setUseReverseApi(qint32 use_reverse_api)
double m_magsqSum
Definition: freqtracker.h:229
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
int getDeviceSetIndex() const
Definition: channelapi.h:89
bool m_timerConnected
Definition: freqtracker.h:241
ThreadedBasebandSampleSink * m_threadedChannelizer
Definition: freqtracker.h:205
SWGFreqTrackerReport * getFreqTrackerReport()
int m_squelchGate
in 10s of ms
int runFilt(const cmplx &in, cmplx **out)
Definition: fftfilt.cpp:260
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const FreqTrackerSettings &settings)
virtual void start()
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
void setInterpolator()
SWGFreqTrackerSettings * getFreqTrackerSettings()
static MsgSampleRateNotification * create(int sampleRate, int frequencyOffset)
Definition: freqtracker.h:102
void setReverseApiPort(qint32 reverse_api_port)
#define M_PI
Definition: rdsdemod.cpp:27
void setChannelType(QString *channel_type)
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
QMutex m_settingsMutex
Definition: freqtracker.h:245
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
uint32_t m_deviceSampleRate
Definition: freqtracker.h:209
std::complex< float > cmplx
Definition: fftfilt.h:21
Complex nextIQ()
Return next complex sample.
Definition: ncof.cpp:63
unsigned int uint32_t
Definition: rtptypes_win.h:46
void getMagSqLevels(double &avg, double &peak, int &nbSamples)
Definition: freqtracker.h:167
float getFreq() const
#define SDR_RX_SCALEF
Definition: dsptypes.h:33
uint32_t m_squelchGate
Squelch gate in samples.
Definition: freqtracker.h:227
static const QString m_channelIdURI
Definition: freqtracker.h:185
qint64 getCenterFrequency() const
Definition: dspcommands.h:329
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
MovingAverageUtil< Real, double, 16 > m_movingAverage
Definition: freqtracker.h:234
float getFreq() const
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool po)
Real m_interpolatorDistance
Definition: freqtracker.h:219
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
static const QString m_channelId
Definition: freqtracker.h:186
SWGAMDemodSettings * getAmDemodSettings()
static DSPEngine * instance()
Definition: dspengine.cpp:51
int m_magsqCount
Definition: freqtracker.h:231
double m_magsqPeak
Definition: freqtracker.h:230
int m_lastCorrAbs
Definition: freqtracker.h:243
QByteArray serialize() const
int m_inputSampleRate
Definition: freqtracker.h:210
uint32_t m_tickCount
Definition: freqtracker.h:242
int32_t i
Definition: decimators.h:244
bool getSquelchOpen() const
Definition: freqtracker.h:162
static bool match(const Message *message)
Definition: message.cpp:45
void processOneSample(Complex &ci)
Real m_squelchLevel
Definition: freqtracker.h:224
int m_inputFrequencyOffset
Definition: freqtracker.h:211
int int32_t
Definition: rtptypes_win.h:45
PhaseLockComplex m_pll
Definition: freqtracker.h:216
const QTimer * m_timer
Definition: freqtracker.h:240
void removeChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Remove a channel sink (Rx)
Definition: deviceapi.cpp:127
virtual QByteArray serialize() const
virtual QString asJson() override
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
bool m_running
Definition: freqtracker.h:213
Interpolator m_interpolator
Definition: freqtracker.h:218
FreqTrackerSettings m_settings
Definition: freqtracker.h:207
virtual void stop()
static const int m_udpBlockSize
Definition: freqtracker.h:236
const FreqTrackerSettings & getSettings() const
Definition: freqtracker.h:56
virtual bool deserialize(const QByteArray &data)
void addChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Add a channel sink (Rx)
Definition: deviceapi.cpp:118
void create_rrc_filter(float fb, float a)
root raised cosine. fb is half the band pass
Definition: fftfilt.cpp:222
void setFreqTrackerSettings(SWGFreqTrackerSettings *freq_tracker_settings)
int getSampleRate() const
Definition: dspcommands.h:328
Real m_avgDeltaFreq
Definition: freqtracker.h:244
uint32_t m_rrcRolloff
in 100ths
void networkManagerFinished(QNetworkReply *reply)
void setFreq(Real freq, Real sampleRate)
Definition: ncof.cpp:51
bool m_squelchOpen
Definition: freqtracker.h:226
void feed(float re, float im)
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
void setReverseApiAddress(QString *reverse_api_address)
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const FreqTrackerSettings &settings, bool force)
Real m_interpolatorDistanceRemain
Definition: freqtracker.h:220
bool deserialize(const QByteArray &data)
double m_magsq
Definition: freqtracker.h:228
void setChannelPowerDb(float channel_power_db)
void configureChannelizer()
void computeCoefficients(Real wn, Real zeta, Real K)
uint32_t m_channelSampleRate
Definition: freqtracker.h:212
void setPskOrder(unsigned int order)
int getIndexInDeviceSet() const
Definition: channelapi.h:87
Real getFrequency() const
DeviceAPI * m_deviceAPI
Definition: freqtracker.h:204
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
std::complex< Real > Complex
Definition: dsptypes.h:43
DownChannelizer * m_channelizer
Definition: freqtracker.h:206
double asDouble() const
Definition: movingaverage.h:57
static MsgConfigureFreqTracker * create(const FreqTrackerSettings &settings, bool force)
Definition: freqtracker.h:59
float Real
Definition: dsptypes.h:42
void setSampleRate(unsigned int sampleRate)
QNetworkAccessManager * m_networkManager
Definition: freqtracker.h:237
static double powerFromdB(double powerdB)
Definition: db.cpp:36
void feed(float re, float im)
float m_alphaEMA
alpha factor for delta frequency EMA
void disconnectTimer()
QNetworkRequest m_networkRequest
Definition: freqtracker.h:238
void connectTimer()
const QTimer & getMasterTimer() const
Definition: dspengine.h:84
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force=false)
void setChannelSampleRate(qint32 channel_sample_rate)
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
void setSampleRate(unsigned int sampleRate)
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
void setInputFrequencyOffset(qint64 input_frequency_offset)