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.
dsddemod.cpp
Go to the documentation of this file.
1 // Copyright (C) 2016 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
19 
20 #include <string.h>
21 #include <stdio.h>
22 #include <complex.h>
23 
24 #include <QTime>
25 #include <QDebug>
26 #include <QNetworkAccessManager>
27 #include <QNetworkReply>
28 #include <QBuffer>
29 
30 #include "SWGChannelSettings.h"
31 #include "SWGDSDDemodSettings.h"
32 #include "SWGChannelReport.h"
33 #include "SWGDSDDemodReport.h"
34 #include "SWGRDSReport.h"
35 
36 #include "audio/audiooutput.h"
37 #include "dsp/dspengine.h"
39 #include "dsp/downchannelizer.h"
40 #include "dsp/dspcommands.h"
41 #include "device/deviceapi.h"
42 #include "util/db.h"
43 
44 #include "dsddemod.h"
45 
49 
50 const QString DSDDemod::m_channelIdURI = "sdrangel.channel.dsddemod";
51 const QString DSDDemod::m_channelId = "DSDDemod";
52 const int DSDDemod::m_udpBlockSize = 512;
53 
55  ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink),
56  m_deviceAPI(deviceAPI),
57  m_inputSampleRate(48000),
58  m_inputFrequencyOffset(0),
59  m_interpolatorDistance(0.0f),
60  m_interpolatorDistanceRemain(0.0f),
61  m_sampleCount(0),
62  m_squelchCount(0),
63  m_squelchGate(0),
64  m_squelchLevel(1e-4),
65  m_squelchOpen(false),
66  m_squelchDelayLine(24000),
67  m_audioFifo1(48000),
68  m_audioFifo2(48000),
69  m_scopeXY(0),
70  m_scopeEnabled(true),
71  m_dsdDecoder(),
72  m_signalFormat(signalFormatNone),
73  m_settingsMutex(QMutex::Recursive)
74 {
75  setObjectName(m_channelId);
76 
77  m_audioBuffer.resize(1<<14);
79 
80  m_sampleBuffer = new FixReal[1<<17]; // 128 kS
82  m_scaleFromShort = SDR_RX_SAMP_SZ < sizeof(short)*8 ? 1 : 1<<(SDR_RX_SAMP_SZ - sizeof(short)*8);
83 
84  m_magsq = 0.0f;
85  m_magsqSum = 0.0f;
86  m_magsqPeak = 0.0f;
87  m_magsqCount = 0;
88 
92 
95 
96  m_channelizer = new DownChannelizer(this);
100 
101  m_networkManager = new QNetworkAccessManager();
102  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
103 }
104 
106 {
107  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
108  delete m_networkManager;
109  delete[] m_sampleBuffer;
112 
115  delete m_threadedChannelizer;
116  delete m_channelizer;
117 }
118 
119 void DSDDemod::configureMyPosition(MessageQueue* messageQueue, float myLatitude, float myLongitude)
120 {
121  Message* cmd = MsgConfigureMyPosition::create(myLatitude, myLongitude);
122  messageQueue->push(cmd);
123 }
124 
125 void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst)
126 {
127  (void) firstOfBurst;
128  Complex ci;
129  int samplesPerSymbol = m_dsdDecoder.getSamplesPerSymbol();
130 
131  m_settingsMutex.lock();
132  m_scopeSampleBuffer.clear();
133 
134  m_dsdDecoder.enableMbelib(!DSPEngine::instance()->hasDVSerialSupport()); // disable mbelib if DV serial support is present and activated else enable it
135 
136  for (SampleVector::const_iterator it = begin; it != end; ++it)
137  {
138  Complex c(it->real(), it->imag());
139  c *= m_nco.nextIQ();
140 
142  {
143  FixReal sample, delayedSample;
144  qint16 sampleDSD;
145 
146  Real re = ci.real() / SDR_RX_SCALED;
147  Real im = ci.imag() / SDR_RX_SCALED;
148  Real magsq = re*re + im*im;
149  m_movingAverage(magsq);
150 
151  m_magsqSum += magsq;
152 
153  if (magsq > m_magsqPeak)
154  {
155  m_magsqPeak = magsq;
156  }
157 
158  m_magsqCount++;
159 
160  Real demod = m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_demodGain; // [-1.0:1.0]
161  m_sampleCount++;
162 
163  // AF processing
164 
166  {
167  if (m_squelchGate > 0)
168  {
169 
170  if (m_squelchCount < m_squelchGate*2) {
171  m_squelchCount++;
172  }
173 
174  m_squelchDelayLine.write(demod);
176  }
177  else
178  {
179  m_squelchOpen = true;
180  }
181  }
182  else
183  {
184  if (m_squelchGate > 0)
185  {
186  if (m_squelchCount > 0) {
187  m_squelchCount--;
188  }
189 
192  }
193  else
194  {
195  m_squelchOpen = false;
196  }
197  }
198 
199  if (m_squelchOpen)
200  {
201  if (m_squelchGate > 0)
202  {
203  sampleDSD = m_squelchDelayLine.readBack(m_squelchGate) * 32768.0f; // DSD decoder takes int16 samples
204  sample = m_squelchDelayLine.readBack(m_squelchGate) * SDR_RX_SCALEF; // scale to sample size
205  }
206  else
207  {
208  sampleDSD = demod * 32768.0f; // DSD decoder takes int16 samples
209  sample = demod * SDR_RX_SCALEF; // scale to sample size
210  }
211  }
212  else
213  {
214  sampleDSD = 0;
215  sample = 0;
216  }
217 
218  m_dsdDecoder.pushSample(sampleDSD);
219 
220  if (m_settings.m_enableCosineFiltering) { // show actual input to FSK demod
222  }
223 
224  if (m_sampleBufferIndex < (1<<17)-1) {
226  } else {
228  }
229 
231 
232  if (m_sampleBufferIndex < samplesPerSymbol) {
233  delayedSample = m_sampleBuffer[(1<<17) - samplesPerSymbol + m_sampleBufferIndex]; // wrap
234  } else {
235  delayedSample = m_sampleBuffer[m_sampleBufferIndex - samplesPerSymbol];
236  }
237 
239  {
241  m_scopeSampleBuffer.push_back(s);
242  }
243  else
244  {
245  Sample s(sample, delayedSample); // I=signal, Q=signal delayed by 20 samples (2400 baud: lowest rate)
246  m_scopeSampleBuffer.push_back(s);
247  }
248 
249  if (DSPEngine::instance()->hasDVSerialSupport())
250  {
252  {
253  if (!m_settings.m_audioMute)
254  {
258  m_settings.m_volume * 10.0,
259  m_settings.m_tdmaStereo ? 1 : 3, // left or both channels
261  m_audioSampleRate/8000, // upsample from native 8k
262  &m_audioFifo1);
263  }
264 
266  }
267 
269  {
270  if (!m_settings.m_audioMute)
271  {
275  m_settings.m_volume * 10.0,
276  m_settings.m_tdmaStereo ? 2 : 3, // right or both channels
278  m_audioSampleRate/8000, // upsample from native 8k
279  &m_audioFifo2);
280  }
281 
283  }
284  }
285 
286 // if (DSPEngine::instance()->hasDVSerialSupport() && m_dsdDecoder.mbeDVReady1())
287 // {
288 // if (!m_settings.m_audioMute)
289 // {
290 // DSPEngine::instance()->pushMbeFrame(m_dsdDecoder.getMbeDVFrame1(), m_dsdDecoder.getMbeRateIndex(), m_settings.m_volume, &m_audioFifo1);
291 // }
292 //
293 // m_dsdDecoder.resetMbeDV1();
294 // }
295 
297  }
298  }
299 
300  if (!DSPEngine::instance()->hasDVSerialSupport())
301  {
302  if (m_settings.m_slot1On)
303  {
304  int nbAudioSamples;
305  short *dsdAudio = m_dsdDecoder.getAudio1(nbAudioSamples);
306 
307  if (nbAudioSamples > 0)
308  {
309  if (!m_settings.m_audioMute) {
310  m_audioFifo1.write((const quint8*) dsdAudio, nbAudioSamples);
311  }
312 
314  }
315  }
316 
317  if (m_settings.m_slot2On)
318  {
319  int nbAudioSamples;
320  short *dsdAudio = m_dsdDecoder.getAudio2(nbAudioSamples);
321 
322  if (nbAudioSamples > 0)
323  {
324  if (!m_settings.m_audioMute) {
325  m_audioFifo2.write((const quint8*) dsdAudio, nbAudioSamples);
326  }
327 
329  }
330  }
331 
332 // int nbAudioSamples;
333 // short *dsdAudio = m_dsdDecoder.getAudio1(nbAudioSamples);
334 //
335 // if (nbAudioSamples > 0)
336 // {
337 // if (!m_settings.m_audioMute) {
338 // uint res = m_audioFifo1.write((const quint8*) dsdAudio, nbAudioSamples, 10);
339 // }
340 //
341 // m_dsdDecoder.resetAudio1();
342 // }
343  }
344 
345  if ((m_scopeXY != 0) && (m_scopeEnabled))
346  {
347  m_scopeXY->feed(m_scopeSampleBuffer.begin(), m_scopeSampleBuffer.end(), true); // true = real samples for what it's worth
348  }
349 
350  m_settingsMutex.unlock();
351 }
352 
354 {
359 }
360 
362 {
363 }
364 
366 {
367  qDebug() << "DSDDemod::handleMessage";
368 
370  {
372  qDebug() << "DSDDemod::handleMessage: MsgChannelizerNotification: inputSampleRate: " << notif.getSampleRate()
373  << " inputFrequencyOffset: " << notif.getFrequencyOffset();
374 
376 
377  return true;
378  }
379  else if (MsgConfigureChannelizer::match(cmd))
380  {
382  qDebug("DSDDemod::handleMessage: MsgConfigureChannelizer");
383 
385  cfg.getSampleRate(),
386  cfg.getCenterFrequency());
387 
388  return true;
389  }
390  else if (MsgConfigureDSDDemod::match(cmd))
391  {
393  qDebug("DSDDemod::handleMessage: MsgConfigureDSDDemod: m_rfBandwidth");
394 
395  applySettings(cfg.getSettings(), cfg.getForce());
396 
397  return true;
398  }
399  else if (MsgConfigureMyPosition::match(cmd))
400  {
403  return true;
404  }
405  else if (DSPConfigureAudio::match(cmd))
406  {
407  DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd;
408  uint32_t sampleRate = cfg.getSampleRate();
409 
410  qDebug() << "DSDDemod::handleMessage: DSPConfigureAudio:"
411  << " sampleRate: " << sampleRate;
412 
413  if (sampleRate != m_audioSampleRate) {
414  applyAudioSampleRate(sampleRate);
415  }
416 
417  return true;
418  }
420  {
421  return true;
422  }
423  else if (DSPSignalNotification::match(cmd))
424  {
425  return true;
426  }
427  else
428  {
429  return false;
430  }
431 }
432 
433 void DSDDemod::applyAudioSampleRate(int sampleRate)
434 {
435  int upsampling = sampleRate / 8000;
436 
437  qDebug("DSDDemod::applyAudioSampleRate: audio rate: %d upsample by %d", sampleRate, upsampling);
438 
439  if (sampleRate % 8000 != 0) {
440  qDebug("DSDDemod::applyAudioSampleRate: audio will sound best with sample rates that are integer multiples of 8 kS/s");
441  }
442 
443  m_dsdDecoder.setUpsampling(upsampling);
444  m_audioSampleRate = sampleRate;
445 }
446 
447 void DSDDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force)
448 {
449  qDebug() << "DSDDemod::applyChannelSettings:"
450  << " inputSampleRate: " << inputSampleRate
451  << " inputFrequencyOffset: " << inputFrequencyOffset;
452 
453  if ((inputFrequencyOffset != m_inputFrequencyOffset) ||
454  (inputSampleRate != m_inputSampleRate) || force)
455  {
456  m_nco.setFreq(-inputFrequencyOffset, inputSampleRate);
457  }
458 
459  if ((inputSampleRate != m_inputSampleRate) || force)
460  {
461  m_settingsMutex.lock();
462  m_interpolator.create(16, inputSampleRate, (m_settings.m_rfBandwidth) / 2.2);
464  m_interpolatorDistance = (Real) inputSampleRate / (Real) 48000;
465  m_settingsMutex.unlock();
466  }
467 
468  m_inputSampleRate = inputSampleRate;
469  m_inputFrequencyOffset = inputFrequencyOffset;
470 }
471 
472 void DSDDemod::applySettings(const DSDDemodSettings& settings, bool force)
473 {
474  qDebug() << "DSDDemod::applySettings: "
475  << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
476  << " m_rfBandwidth: " << settings.m_rfBandwidth
477  << " m_fmDeviation: " << settings.m_fmDeviation
478  << " m_demodGain: " << settings.m_demodGain
479  << " m_volume: " << settings.m_volume
480  << " m_baudRate: " << settings.m_baudRate
481  << " m_squelchGate" << settings.m_squelchGate
482  << " m_squelch: " << settings.m_squelch
483  << " m_audioMute: " << settings.m_audioMute
484  << " m_enableCosineFiltering: " << settings.m_enableCosineFiltering
485  << " m_syncOrConstellation: " << settings.m_syncOrConstellation
486  << " m_slot1On: " << settings.m_slot1On
487  << " m_slot2On: " << settings.m_slot2On
488  << " m_tdmaStereo: " << settings.m_tdmaStereo
489  << " m_pllLock: " << settings.m_pllLock
490  << " m_highPassFilter: "<< settings.m_highPassFilter
491  << " m_audioDeviceName: " << settings.m_audioDeviceName
492  << " m_traceLengthMutliplier: " << settings.m_traceLengthMutliplier
493  << " m_traceStroke: " << settings.m_traceStroke
494  << " m_traceDecay: " << settings.m_traceDecay
495  << " force: " << force;
496 
497  QList<QString> reverseAPIKeys;
498 
499  if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) {
500  reverseAPIKeys.append("inputFrequencyOffset");
501  }
502  if ((settings.m_demodGain != m_settings.m_demodGain) || force) {
503  reverseAPIKeys.append("demodGain");
504  }
505  if ((settings.m_audioMute != m_settings.m_audioMute) || force) {
506  reverseAPIKeys.append("audioMute");
507  }
508  if ((settings.m_syncOrConstellation != m_settings.m_syncOrConstellation) || force) {
509  reverseAPIKeys.append("syncOrConstellation");
510  }
511  if ((settings.m_slot1On != m_settings.m_slot1On) || force) {
512  reverseAPIKeys.append("slot1On");
513  }
514  if ((settings.m_slot2On != m_settings.m_slot2On) || force) {
515  reverseAPIKeys.append("slot2On");
516  }
517  if ((settings.m_demodGain != m_settings.m_demodGain) || force) {
518  reverseAPIKeys.append("demodGain");
519  }
520  if ((settings.m_traceLengthMutliplier != m_settings.m_traceLengthMutliplier) || force) {
521  reverseAPIKeys.append("traceLengthMutliplier");
522  }
523 
524  if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force)
525  {
526  reverseAPIKeys.append("rfBandwidth");
527  m_settingsMutex.lock();
528  m_interpolator.create(16, m_inputSampleRate, (settings.m_rfBandwidth) / 2.2);
531  //m_phaseDiscri.setFMScaling((float) settings.m_rfBandwidth / (float) settings.m_fmDeviation);
532  m_settingsMutex.unlock();
533  }
534 
535  if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force)
536  {
537  reverseAPIKeys.append("fmDeviation");
538  m_phaseDiscri.setFMScaling(48000.0f / (2.0f*settings.m_fmDeviation));
539  }
540 
541  if ((settings.m_squelchGate != m_settings.m_squelchGate) || force)
542  {
543  reverseAPIKeys.append("squelchGate");
544  m_squelchGate = 480 * settings.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate
545  m_squelchCount = 0; // reset squelch open counter
546  }
547 
548  if ((settings.m_squelch != m_settings.m_squelch) || force)
549  {
550  reverseAPIKeys.append("squelch");
551  // input is a value in dB
552  m_squelchLevel = std::pow(10.0, settings.m_squelch / 10.0);
553  }
554 
555  if ((settings.m_volume != m_settings.m_volume) || force)
556  {
557  reverseAPIKeys.append("volume");
559  }
560 
561  if ((settings.m_baudRate != m_settings.m_baudRate) || force)
562  {
563  reverseAPIKeys.append("baudRate");
565  }
566 
568  {
569  reverseAPIKeys.append("enableCosineFiltering");
571  }
572 
573  if ((settings.m_tdmaStereo != m_settings.m_tdmaStereo) || force)
574  {
575  reverseAPIKeys.append("tdmaStereo");
577  }
578 
579  if ((settings.m_pllLock != m_settings.m_pllLock) || force)
580  {
581  reverseAPIKeys.append("pllLock");
583  }
584 
585  if ((settings.m_highPassFilter != m_settings.m_highPassFilter) || force)
586  {
587  reverseAPIKeys.append("highPassFilter");
589  }
590 
591  if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
592  {
593  reverseAPIKeys.append("audioDeviceName");
595  int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_audioDeviceName);
596  //qDebug("AMDemod::applySettings: audioDeviceName: %s audioDeviceIndex: %d", qPrintable(settings.m_audioDeviceName), audioDeviceIndex);
597  audioDeviceManager->addAudioSink(&m_audioFifo1, getInputMessageQueue(), audioDeviceIndex);
598  audioDeviceManager->addAudioSink(&m_audioFifo2, getInputMessageQueue(), audioDeviceIndex);
599  uint32_t audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
600 
601  if (m_audioSampleRate != audioSampleRate) {
602  applyAudioSampleRate(audioSampleRate);
603  }
604  }
605 
606  if (settings.m_useReverseAPI)
607  {
608  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
613  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
614  }
615 
616  m_settings = settings;
617 }
618 
619 QByteArray DSDDemod::serialize() const
620 {
621  return m_settings.serialize();
622 }
623 
624 bool DSDDemod::deserialize(const QByteArray& data)
625 {
626  if (m_settings.deserialize(data))
627  {
630  return true;
631  }
632  else
633  {
637  return false;
638  }
639 }
640 
642 {
644  return m_formatStatusText;
645 }
646 
648 {
649  switch (getDecoder().getSyncType())
650  {
651  case DSDcc::DSDDecoder::DSDSyncDMRDataMS:
652  case DSDcc::DSDDecoder::DSDSyncDMRDataP:
653  case DSDcc::DSDDecoder::DSDSyncDMRVoiceMS:
654  case DSDcc::DSDDecoder::DSDSyncDMRVoiceP:
656  {
657  strcpy(m_formatStatusText, "Sta: __ S1: __________________________ S2: __________________________");
658  }
659 
660  switch (getDecoder().getStationType())
661  {
662  case DSDcc::DSDDecoder::DSDBaseStation:
663  memcpy(&m_formatStatusText[5], "BS ", 3);
664  break;
665  case DSDcc::DSDDecoder::DSDMobileStation:
666  memcpy(&m_formatStatusText[5], "MS ", 3);
667  break;
668  default:
669  memcpy(&m_formatStatusText[5], "NA ", 3);
670  break;
671  }
672 
673  memcpy(&m_formatStatusText[12], getDecoder().getDMRDecoder().getSlot0Text(), 26);
674  memcpy(&m_formatStatusText[43], getDecoder().getDMRDecoder().getSlot1Text(), 26);
676  break;
677  case DSDcc::DSDDecoder::DSDSyncDStarHeaderN:
678  case DSDcc::DSDDecoder::DSDSyncDStarHeaderP:
679  case DSDcc::DSDDecoder::DSDSyncDStarN:
680  case DSDcc::DSDDecoder::DSDSyncDStarP:
682  {
683  // 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8
684  // 0....5....0....5....0....5....0....5....0....5....0....5....0....5....0....5....0..
685  strcpy(m_formatStatusText, "________/____>________|________>________|____________________|______:___/_____._");
686  // MY UR RPT1 RPT2 Info Loc Target
687  }
688 
689  {
690  const std::string& rpt1 = getDecoder().getDStarDecoder().getRpt1();
691  const std::string& rpt2 = getDecoder().getDStarDecoder().getRpt2();
692  const std::string& mySign = getDecoder().getDStarDecoder().getMySign();
693  const std::string& yrSign = getDecoder().getDStarDecoder().getYourSign();
694 
695  if (rpt1.length() > 0) { // 0 or 8
696  memcpy(&m_formatStatusText[23], rpt1.c_str(), 8);
697  }
698  if (rpt2.length() > 0) { // 0 or 8
699  memcpy(&m_formatStatusText[32], rpt2.c_str(), 8);
700  }
701  if (yrSign.length() > 0) { // 0 or 8
702  memcpy(&m_formatStatusText[14], yrSign.c_str(), 8);
703  }
704  if (mySign.length() > 0) { // 0 or 13
705  memcpy(&m_formatStatusText[0], mySign.c_str(), 13);
706  }
707  memcpy(&m_formatStatusText[41], getDecoder().getDStarDecoder().getInfoText(), 20);
708  memcpy(&m_formatStatusText[62], getDecoder().getDStarDecoder().getLocator(), 6);
709  snprintf(&m_formatStatusText[69], 82-69, "%03d/%07.1f",
710  getDecoder().getDStarDecoder().getBearing(),
711  getDecoder().getDStarDecoder().getDistance());
712  }
713 
714  m_formatStatusText[82] = '\0';
716  break;
717  case DSDcc::DSDDecoder::DSDSyncDPMR:
718  snprintf(m_formatStatusText, 82, "%s CC: %04d OI: %08d CI: %08d",
719  DSDcc::DSDdPMR::dpmrFrameTypes[(int) getDecoder().getDPMRDecoder().getFrameType()],
720  getDecoder().getDPMRDecoder().getColorCode(),
721  getDecoder().getDPMRDecoder().getOwnId(),
722  getDecoder().getDPMRDecoder().getCalledId());
724  break;
725  case DSDcc::DSDDecoder::DSDSyncNXDNP:
726  case DSDcc::DSDDecoder::DSDSyncNXDNN:
727  if (getDecoder().getNXDNDecoder().getRFChannel() == DSDcc::DSDNXDN::NXDNRCCH)
728  {
729  // 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8
730  // 0....5....0....5....0....5....0....5....0....5....0....5....0....5....0....5....0..
731  // RC r cc mm llllll ssss
732  snprintf(m_formatStatusText, 82, "RC %s %02d %02X %06X %02X",
733  getDecoder().getNXDNDecoder().isFullRate() ? "F" : "H",
734  getDecoder().getNXDNDecoder().getRAN(),
735  getDecoder().getNXDNDecoder().getMessageType(),
736  getDecoder().getNXDNDecoder().getLocationId(),
737  getDecoder().getNXDNDecoder().getServicesFlag());
738  }
739  else if ((getDecoder().getNXDNDecoder().getRFChannel() == DSDcc::DSDNXDN::NXDNRTCH)
740  || (getDecoder().getNXDNDecoder().getRFChannel() == DSDcc::DSDNXDN::NXDNRDCH))
741  {
742  if (getDecoder().getNXDNDecoder().isIdle()) {
743  snprintf(m_formatStatusText, 82, "%s IDLE", getDecoder().getNXDNDecoder().getRFChannelStr());
744  }
745  else
746  {
747  // 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8
748  // 0....5....0....5....0....5....0....5....0....5....0....5....0....5....0....5....0..
749  // Rx r cc mm sssss>gddddd
750  snprintf(m_formatStatusText, 82, "%s %s %02d %02X %05d>%c%05d",
751  getDecoder().getNXDNDecoder().getRFChannelStr(),
752  getDecoder().getNXDNDecoder().isFullRate() ? "F" : "H",
753  getDecoder().getNXDNDecoder().getRAN(),
754  getDecoder().getNXDNDecoder().getMessageType(),
755  getDecoder().getNXDNDecoder().getSourceId(),
756  getDecoder().getNXDNDecoder().isGroupCall() ? 'G' : 'I',
757  getDecoder().getNXDNDecoder().getDestinationId());
758  }
759  }
760  else
761  {
762  // 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8
763  // 0....5....0....5....0....5....0....5....0....5....0....5....0....5....0....5....0..
764  // RU
765  snprintf(m_formatStatusText, 82, "RU");
766  }
768  break;
769  case DSDcc::DSDDecoder::DSDSyncYSF:
770  // 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8
771  // 0....5....0....5....0....5....0....5....0....5....0....5....0....5....0....5....0..
772  // C V2 RI 0:7 WL000|ssssssssss>dddddddddd |UUUUUUUUUU>DDDDDDDDDD|44444
773  if (getDecoder().getYSFDecoder().getFICHError() == DSDcc::DSDYSF::FICHNoError)
774  {
775  snprintf(m_formatStatusText, 82, "%s ", DSDcc::DSDYSF::ysfChannelTypeText[(int) getDecoder().getYSFDecoder().getFICH().getFrameInformation()]);
776  }
777  else
778  {
779  snprintf(m_formatStatusText, 82, "%d ", (int) getDecoder().getYSFDecoder().getFICHError());
780  }
781 
782  snprintf(&m_formatStatusText[2], 80, "%s %s %d:%d %c%c",
783  DSDcc::DSDYSF::ysfDataTypeText[(int) getDecoder().getYSFDecoder().getFICH().getDataType()],
784  DSDcc::DSDYSF::ysfCallModeText[(int) getDecoder().getYSFDecoder().getFICH().getCallMode()],
785  getDecoder().getYSFDecoder().getFICH().getBlockTotal(),
786  getDecoder().getYSFDecoder().getFICH().getFrameTotal(),
787  (getDecoder().getYSFDecoder().getFICH().isNarrowMode() ? 'N' : 'W'),
788  (getDecoder().getYSFDecoder().getFICH().isInternetPath() ? 'I' : 'L'));
789 
790  if (getDecoder().getYSFDecoder().getFICH().isSquelchCodeEnabled())
791  {
792  snprintf(&m_formatStatusText[14], 82-14, "%03d", getDecoder().getYSFDecoder().getFICH().getSquelchCode());
793  }
794  else
795  {
796  strncpy(&m_formatStatusText[14], "---", 82-14);
797  }
798 
799  char dest[13];
800 
801  if (getDecoder().getYSFDecoder().radioIdMode())
802  {
803  snprintf(dest, 12, "%-5s:%-5s",
804  getDecoder().getYSFDecoder().getDestId(),
805  getDecoder().getYSFDecoder().getSrcId());
806  }
807  else
808  {
809  snprintf(dest, 11, "%-10s", getDecoder().getYSFDecoder().getDest());
810  }
811 
812  snprintf(&m_formatStatusText[17], 82-17, "|%-10s>%s|%-10s>%-10s|%-5s",
813  getDecoder().getYSFDecoder().getSrc(),
814  dest,
815  getDecoder().getYSFDecoder().getUplink(),
816  getDecoder().getYSFDecoder().getDownlink(),
817  getDecoder().getYSFDecoder().getRem4());
818 
820  break;
821  default:
823  m_formatStatusText[0] = '\0';
824  break;
825  }
826 
827  m_formatStatusText[82] = '\0'; // guard
828 }
829 
832  QString& errorMessage)
833 {
834  (void) errorMessage;
836  response.getDsdDemodSettings()->init();
838  return 200;
839 }
840 
842  bool force,
843  const QStringList& channelSettingsKeys,
845  QString& errorMessage)
846 {
847  (void) errorMessage;
848  DSDDemodSettings settings = m_settings;
849  bool frequencyOffsetChanged = false;
850 
851  if (channelSettingsKeys.contains("inputFrequencyOffset"))
852  {
854  frequencyOffsetChanged = true;
855  }
856  if (channelSettingsKeys.contains("rfBandwidth")) {
857  settings.m_rfBandwidth = response.getDsdDemodSettings()->getRfBandwidth();
858  }
859  if (channelSettingsKeys.contains("fmDeviation")) {
860  settings.m_fmDeviation = response.getDsdDemodSettings()->getFmDeviation();
861  }
862  if (channelSettingsKeys.contains("demodGain")) {
863  settings.m_demodGain = response.getDsdDemodSettings()->getDemodGain();
864  }
865  if (channelSettingsKeys.contains("volume")) {
866  settings.m_volume = response.getDsdDemodSettings()->getVolume();
867  }
868  if (channelSettingsKeys.contains("baudRate")) {
869  settings.m_baudRate = response.getDsdDemodSettings()->getBaudRate();
870  }
871  if (channelSettingsKeys.contains("squelchGate")) {
872  settings.m_squelchGate = response.getDsdDemodSettings()->getSquelchGate();
873  }
874  if (channelSettingsKeys.contains("squelch")) {
875  settings.m_squelch = response.getDsdDemodSettings()->getSquelch();
876  }
877  if (channelSettingsKeys.contains("audioMute")) {
878  settings.m_audioMute = response.getDsdDemodSettings()->getAudioMute() != 0;
879  }
880  if (channelSettingsKeys.contains("enableCosineFiltering")) {
882  }
883  if (channelSettingsKeys.contains("syncOrConstellation")) {
885  }
886  if (channelSettingsKeys.contains("slot1On")) {
887  settings.m_slot1On = response.getDsdDemodSettings()->getSlot1On() != 0;
888  }
889  if (channelSettingsKeys.contains("slot2On")) {
890  settings.m_slot2On = response.getDsdDemodSettings()->getSlot2On() != 0;
891  }
892  if (channelSettingsKeys.contains("tdmaStereo")) {
893  settings.m_tdmaStereo = response.getDsdDemodSettings()->getTdmaStereo() != 0;
894  }
895  if (channelSettingsKeys.contains("pllLock")) {
896  settings.m_pllLock = response.getDsdDemodSettings()->getPllLock() != 0;
897  }
898  if (channelSettingsKeys.contains("rgbColor")) {
899  settings.m_rgbColor = response.getDsdDemodSettings()->getRgbColor();
900  }
901  if (channelSettingsKeys.contains("title")) {
902  settings.m_title = *response.getDsdDemodSettings()->getTitle();
903  }
904  if (channelSettingsKeys.contains("audioDeviceName")) {
905  settings.m_audioDeviceName = *response.getDsdDemodSettings()->getAudioDeviceName();
906  }
907  if (channelSettingsKeys.contains("highPassFilter")) {
908  settings.m_highPassFilter = response.getDsdDemodSettings()->getHighPassFilter() != 0;
909  }
910  if (channelSettingsKeys.contains("traceLengthMutliplier")) {
912  }
913  if (channelSettingsKeys.contains("traceStroke")) {
914  settings.m_traceStroke = response.getDsdDemodSettings()->getTraceStroke();
915  }
916  if (channelSettingsKeys.contains("traceDecay")) {
917  settings.m_traceDecay = response.getDsdDemodSettings()->getTraceDecay();
918  }
919  if (channelSettingsKeys.contains("useReverseAPI")) {
920  settings.m_useReverseAPI = response.getDsdDemodSettings()->getUseReverseApi() != 0;
921  }
922  if (channelSettingsKeys.contains("reverseAPIAddress")) {
924  }
925  if (channelSettingsKeys.contains("reverseAPIPort")) {
926  settings.m_reverseAPIPort = response.getDsdDemodSettings()->getReverseApiPort();
927  }
928  if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
930  }
931  if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
933  }
934 
935  if (frequencyOffsetChanged)
936  {
939  m_inputMessageQueue.push(channelConfigMsg);
940  }
941 
942  MsgConfigureDSDDemod *msg = MsgConfigureDSDDemod::create(settings, force);
944 
945  qDebug("DSDDemod::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
946  if (m_guiMessageQueue) // forward to GUI if any
947  {
948  MsgConfigureDSDDemod *msgToGUI = MsgConfigureDSDDemod::create(settings, force);
949  m_guiMessageQueue->push(msgToGUI);
950  }
951 
952  webapiFormatChannelSettings(response, settings);
953 
954  return 200;
955 }
956 
959  QString& errorMessage)
960 {
961  (void) errorMessage;
963  response.getDsdDemodReport()->init();
964  webapiFormatChannelReport(response);
965  return 200;
966 }
967 
969 {
971  response.getDsdDemodSettings()->setRfBandwidth(settings.m_rfBandwidth);
972  response.getDsdDemodSettings()->setFmDeviation(settings.m_fmDeviation);
973  response.getDsdDemodSettings()->setDemodGain(settings.m_demodGain);
974  response.getDsdDemodSettings()->setVolume(settings.m_volume);
975  response.getDsdDemodSettings()->setBaudRate(settings.m_baudRate);
976  response.getDsdDemodSettings()->setSquelchGate(settings.m_squelchGate);
977  response.getDsdDemodSettings()->setSquelch(settings.m_squelch);
978  response.getDsdDemodSettings()->setAudioMute(settings.m_audioMute ? 1 : 0);
981  response.getDsdDemodSettings()->setSlot1On(settings.m_slot1On ? 1 : 0);
982  response.getDsdDemodSettings()->setSlot2On(settings.m_slot2On ? 1 : 0);
983  response.getDsdDemodSettings()->setTdmaStereo(settings.m_tdmaStereo ? 1 : 0);
984  response.getDsdDemodSettings()->setPllLock(settings.m_pllLock ? 1 : 0);
985  response.getDsdDemodSettings()->setRgbColor(settings.m_rgbColor);
986 
987  if (response.getDsdDemodSettings()->getTitle()) {
988  *response.getDsdDemodSettings()->getTitle() = settings.m_title;
989  } else {
990  response.getDsdDemodSettings()->setTitle(new QString(settings.m_title));
991  }
992 
993  if (response.getDsdDemodSettings()->getAudioDeviceName()) {
994  *response.getDsdDemodSettings()->getAudioDeviceName() = settings.m_audioDeviceName;
995  } else {
996  response.getDsdDemodSettings()->setAudioDeviceName(new QString(settings.m_audioDeviceName));
997  }
998 
999  response.getDsdDemodSettings()->setHighPassFilter(settings.m_highPassFilter ? 1 : 0);
1001  response.getDsdDemodSettings()->setTraceStroke(settings.m_traceStroke);
1002  response.getDsdDemodSettings()->setTraceDecay(settings.m_traceDecay);
1003  response.getDsdDemodSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
1004 
1005  if (response.getDsdDemodSettings()->getReverseApiAddress()) {
1007  } else {
1008  response.getDsdDemodSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
1009  }
1010 
1014 
1015 }
1016 
1018 {
1019  double magsqAvg, magsqPeak;
1020  int nbMagsqSamples;
1021  getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
1022 
1023  response.getDsdDemodReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg));
1026  response.getDsdDemodReport()->setSquelch(m_squelchOpen ? 1 : 0);
1027  response.getDsdDemodReport()->setPllLocked(getDecoder().getSymbolPLLLocked() ? 1 : 0);
1028  response.getDsdDemodReport()->setSlot1On(getDecoder().getVoice1On() ? 1 : 0);
1029  response.getDsdDemodReport()->setSlot2On(getDecoder().getVoice2On() ? 1 : 0);
1030  response.getDsdDemodReport()->setSyncType(new QString(getDecoder().getFrameTypeText()));
1031  response.getDsdDemodReport()->setInLevel(getDecoder().getInLevel());
1032  response.getDsdDemodReport()->setCarierPosition(getDecoder().getCarrierPos());
1033  response.getDsdDemodReport()->setZeroCrossingPosition(getDecoder().getZeroCrossingPos());
1034  response.getDsdDemodReport()->setSyncRate(getDecoder().getSymbolSyncQuality());
1035  response.getDsdDemodReport()->setStatusText(new QString(updateAndGetStatusText()));
1036 }
1037 
1038 void DSDDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const DSDDemodSettings& settings, bool force)
1039 {
1041  swgChannelSettings->setDirection(0); // single sink (Rx)
1042  swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
1043  swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
1044  swgChannelSettings->setChannelType(new QString("DSDDemod"));
1045  swgChannelSettings->setDsdDemodSettings(new SWGSDRangel::SWGDSDDemodSettings());
1046  SWGSDRangel::SWGDSDDemodSettings *swgDSDDemodSettings = swgChannelSettings->getDsdDemodSettings();
1047 
1048  // transfer data that has been modified. When force is on transfer all data except reverse API data
1049 
1050  if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
1051  swgDSDDemodSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
1052  }
1053  if (channelSettingsKeys.contains("rfBandwidth") || force) {
1054  swgDSDDemodSettings->setRfBandwidth(settings.m_rfBandwidth);
1055  }
1056  if (channelSettingsKeys.contains("fmDeviation") || force) {
1057  swgDSDDemodSettings->setFmDeviation(settings.m_fmDeviation);
1058  }
1059  if (channelSettingsKeys.contains("demodGain") || force) {
1060  swgDSDDemodSettings->setDemodGain(settings.m_demodGain);
1061  }
1062  if (channelSettingsKeys.contains("volume") || force) {
1063  swgDSDDemodSettings->setVolume(settings.m_volume);
1064  }
1065  if (channelSettingsKeys.contains("baudRate") || force) {
1066  swgDSDDemodSettings->setBaudRate(settings.m_baudRate);
1067  }
1068  if (channelSettingsKeys.contains("squelchGate") || force) {
1069  swgDSDDemodSettings->setSquelchGate(settings.m_squelchGate);
1070  }
1071  if (channelSettingsKeys.contains("squelch") || force) {
1072  swgDSDDemodSettings->setSquelch(settings.m_squelch);
1073  }
1074  if (channelSettingsKeys.contains("audioMute") || force) {
1075  swgDSDDemodSettings->setAudioMute(settings.m_audioMute ? 1 : 0);
1076  }
1077  if (channelSettingsKeys.contains("enableCosineFiltering") || force) {
1078  swgDSDDemodSettings->setEnableCosineFiltering(settings.m_enableCosineFiltering ? 1 : 0);
1079  }
1080  if (channelSettingsKeys.contains("syncOrConstellation") || force) {
1081  swgDSDDemodSettings->setSyncOrConstellation(settings.m_syncOrConstellation ? 1 : 0);
1082  }
1083  if (channelSettingsKeys.contains("slot1On") || force) {
1084  swgDSDDemodSettings->setSlot1On(settings.m_slot1On ? 1 : 0);
1085  }
1086  if (channelSettingsKeys.contains("slot2On") || force) {
1087  swgDSDDemodSettings->setSlot2On(settings.m_slot2On ? 1 : 0);
1088  }
1089  if (channelSettingsKeys.contains("tdmaStereo") || force) {
1090  swgDSDDemodSettings->setTdmaStereo(settings.m_tdmaStereo ? 1 : 0);
1091  }
1092  if (channelSettingsKeys.contains("pllLock") || force) {
1093  swgDSDDemodSettings->setPllLock(settings.m_pllLock ? 1 : 0);
1094  }
1095  if (channelSettingsKeys.contains("rgbColor") || force) {
1096  swgDSDDemodSettings->setRgbColor(settings.m_rgbColor);
1097  }
1098  if (channelSettingsKeys.contains("title") || force) {
1099  swgDSDDemodSettings->setTitle(new QString(settings.m_title));
1100  }
1101  if (channelSettingsKeys.contains("audioDeviceName") || force) {
1102  swgDSDDemodSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName));
1103  }
1104  if (channelSettingsKeys.contains("highPassFilter") || force) {
1105  swgDSDDemodSettings->setHighPassFilter(settings.m_highPassFilter ? 1 : 0);
1106  }
1107  if (channelSettingsKeys.contains("traceLengthMutliplier") || force) {
1108  swgDSDDemodSettings->setTraceLengthMutliplier(settings.m_traceLengthMutliplier);
1109  }
1110  if (channelSettingsKeys.contains("traceStroke") || force) {
1111  swgDSDDemodSettings->setTraceStroke(settings.m_traceStroke);
1112  }
1113  if (channelSettingsKeys.contains("traceDecay") || force) {
1114  swgDSDDemodSettings->setTraceDecay(settings.m_traceDecay);
1115  }
1116 
1117  QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
1118  .arg(settings.m_reverseAPIAddress)
1119  .arg(settings.m_reverseAPIPort)
1120  .arg(settings.m_reverseAPIDeviceIndex)
1121  .arg(settings.m_reverseAPIChannelIndex);
1122  m_networkRequest.setUrl(QUrl(channelSettingsURL));
1123  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
1124 
1125  QBuffer *buffer=new QBuffer();
1126  buffer->open((QBuffer::ReadWrite));
1127  buffer->write(swgChannelSettings->asJson().toUtf8());
1128  buffer->seek(0);
1129 
1130  // Always use PATCH to avoid passing reverse API settings
1131  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
1132 
1133  delete swgChannelSettings;
1134 }
1135 
1136 void DSDDemod::networkManagerFinished(QNetworkReply *reply)
1137 {
1138  QNetworkReply::NetworkError replyError = reply->error();
1139 
1140  if (replyError)
1141  {
1142  qWarning() << "DSDDemod::networkManagerFinished:"
1143  << " error(" << (int) replyError
1144  << "): " << replyError
1145  << ": " << reply->errorString();
1146  return;
1147  }
1148 
1149  QString answer = reply->readAll();
1150  answer.chop(1); // remove last \n
1151  qDebug("DSDDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
1152 }
void setPllLocked(qint32 pll_locked)
void setOriginatorChannelIndex(qint32 originator_channel_index)
void addAudioSink(AudioFifo *audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex=-1)
Add the audio sink.
PhaseDiscriminators m_phaseDiscri
Definition: dsddemod.h:261
QByteArray serialize() const
void setSquelchGate(qint32 squelch_gate)
int getOutputSampleRate(int outputDeviceIndex=-1)
void resetAudio2()
Definition: dsddecoder.h:39
int m_squelchCount
Definition: dsddemod.h:232
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
Definition: dsddemod.cpp:830
const DSDcc::DSDDstar & getDStarDecoder() const
Definition: dsddecoder.h:66
Complex nextIQ()
Return next complex sample.
Definition: nco.cpp:61
bool decimate(Real *distance, const Complex &next, Complex *result)
Definition: interpolator.h:38
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
void setChannelSampleRate(qint32 channel_sample_rate)
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const DSDDemodSettings &settings)
Definition: dsddemod.cpp:968
void getMagSqLevels(double &avg, double &peak, int &nbSamples)
Definition: dsddemod.h:133
void push(Message *message, bool emitSignal=true)
Push message onto queue.
AudioVector m_audioBuffer
Definition: dsddemod.h:246
ThreadedBasebandSampleSink * m_threadedChannelizer
Definition: dsddemod.h:219
MovingAverageUtil< Real, double, 16 > m_movingAverage
Definition: dsddemod.h:238
void removeChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:163
char m_formatStatusText[82+1]
Fixed signal format dependent status text.
Definition: dsddemod.h:259
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 create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
static const QString m_channelIdURI
Definition: dsddemod.h:167
DeviceAPI * m_deviceAPI
Definition: dsddemod.h:218
void setFMScaling(Real fmScaling)
Definition: phasediscri.h:42
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
Definition: dsddemod.cpp:841
virtual bool deserialize(const QByteArray &data)
Definition: dsddemod.cpp:624
void clear()
Definition: audiofifo.cpp:156
int getDeviceSetIndex() const
Definition: channelapi.h:89
void setTraceStroke(qint32 trace_stroke)
int getOutputDeviceIndex(const QString &deviceName) const
void setUseReverseApi(qint32 use_reverse_api)
bool mbeDVReady2() const
Definition: dsddecoder.h:45
static const int m_udpBlockSize
Definition: dsddemod.h:268
void setDsdDemodReport(SWGDSDDemodReport *dsd_demod_report)
void removeAudioSink(AudioFifo *audioFifo)
Remove the audio sink.
void setBaudRate(int baudRate)
Definition: dsddecoder.cpp:50
int m_inputFrequencyOffset
Definition: dsddemod.h:223
double m_magsqPeak
Definition: dsddemod.h:241
SampleVector m_scopeSampleBuffer
Definition: dsddemod.h:245
static MsgConfigureMyPosition * create(float myLatitude, float myLongitude)
Definition: dsddemod.h:198
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void setSyncOrConstellation(qint32 sync_or_constellation)
AudioFifo m_audioFifo1
Definition: dsddemod.h:252
void setStatusText(QString *status_text)
void setHighPassFilter(qint32 high_pass_filter)
SWGDSDDemodReport * getDsdDemodReport()
void useHPMbelib(bool useHP)
Definition: dsddecoder.h:75
void setChannelPowerDb(float channel_power_db)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool po)
Definition: dsddemod.cpp:125
void setChannelType(QString *channel_type)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool positiveOnly)=0
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
int m_sampleBufferIndex
Definition: dsddemod.h:249
void applySettings(const DSDDemodSettings &settings, bool force=false)
Definition: dsddemod.cpp:472
qint64 m_inputFrequencyOffset
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
quint32 m_audioSampleRate
Definition: dsddemod.h:225
AudioFifo m_audioFifo2
Definition: dsddemod.h:253
void write(const T &element)
unsigned int uint32_t
Definition: rtptypes_win.h:46
int getSamplesPerSymbol() const
Definition: dsddecoder.h:60
void setTDMAStereo(bool tdmaStereo)
Definition: dsddecoder.h:51
void enableMbelib(bool enable)
Definition: dsddecoder.h:41
#define SDR_RX_SCALEF
Definition: dsptypes.h:33
int m_magsqCount
Definition: dsddemod.h:242
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const DSDDemodSettings &settings, bool force)
Definition: dsddemod.cpp:1038
uint16_t m_reverseAPIDeviceIndex
void setAudioSampleRate(qint32 audio_sample_rate)
int m_squelchGate
Definition: dsddemod.h:233
#define SDR_RX_SAMP_SZ
Definition: dsptypes.h:32
void setTdmaStereo(qint32 tdma_stereo)
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
void setUpsampling(int upsampling)
Definition: dsddecoder.cpp:45
QMutex m_settingsMutex
Definition: dsddemod.h:266
short getFilteredSample() const
Definition: dsddecoder.h:33
SWGDSDDemodSettings * getDsdDemodSettings()
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
void resetMbeDV1()
Definition: dsddecoder.h:44
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
Definition: dsddemod.cpp:1017
DownChannelizer * m_channelizer
Definition: dsddemod.h:220
double m_squelchLevel
Definition: dsddemod.h:234
int getSampleRate() const
Definition: dspcommands.h:390
static DSPEngine * instance()
Definition: dspengine.cpp:51
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
Definition: dsddemod.cpp:957
void setAudioDeviceName(QString *audio_device_name)
void formatStatusText()
Definition: dsddemod.cpp:647
DoubleBufferFIFO< Real > m_squelchDelayLine
Definition: dsddemod.h:236
Interpolator m_interpolator
Definition: dsddemod.h:228
uint16_t m_reverseAPIPort
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
Definition: dsddemod.cpp:365
NCO m_nco
Definition: dsddemod.h:227
void pushMbeFrame(const unsigned char *mbeFrame, int mbeRateIndex, int mbeVolumeIndex, unsigned char channels, bool useHP, int upsampling, AudioFifo *audioFifo)
Definition: dspengine.cpp:177
void resetMbeDV2()
Definition: dsddecoder.h:46
void setReverseApiAddress(QString *reverse_api_address)
BasebandSampleSink * m_scopeXY
Definition: dsddemod.h:254
int getMbeRateIndex() const
Definition: dsddecoder.h:54
bool deserialize(const QByteArray &data)
Real phaseDiscriminator(const Complex &sample)
Definition: phasediscri.h:51
static bool match(const Message *message)
Definition: message.cpp:45
DSDDemodSettings m_settings
Definition: dsddemod.h:224
void applyAudioSampleRate(int sampleRate)
Definition: dsddemod.cpp:433
bool mbeDVReady1() const
Definition: dsddecoder.h:43
short * getAudio2(int &nbSamples)
Definition: dsddecoder.h:38
void setFreq(Real freq, Real sampleRate)
Definition: nco.cpp:49
void setFmDeviation(float fm_deviation)
uint m_audioBufferFill
Definition: dsddemod.h:247
DSDDemod(DeviceAPI *deviceAPI)
Definition: dsddemod.cpp:54
void networkManagerFinished(QNetworkReply *reply)
Definition: dsddemod.cpp:1136
void setTraceLengthMutliplier(qint32 trace_length_mutliplier)
bool m_scopeEnabled
Definition: dsddemod.h:255
void removeChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Remove a channel sink (Rx)
Definition: deviceapi.cpp:127
virtual void stop()
Definition: dsddemod.cpp:361
void enableCosineFiltering(bool on)
Definition: dsddecoder.h:61
void setTraceDecay(qint32 trace_decay)
void setZeroCrossingPosition(qint32 zero_crossing_position)
void setCarierPosition(qint32 carier_position)
FixReal * m_sampleBuffer
samples ring buffer
Definition: dsddemod.h:248
int m_sampleCount
Definition: dsddemod.h:231
void configureMyPosition(MessageQueue *messageQueue, float myLatitude, float myLongitude)
Definition: dsddemod.cpp:119
SignalFormat m_signalFormat
Used to keep formatting during successive calls for the same standard type.
Definition: dsddemod.h:260
Real m_interpolatorDistance
Definition: dsddemod.h:229
void setRfBandwidth(float rf_bandwidth)
const DSDDemodSettings & getSettings() const
Definition: dsddemod.h:57
virtual QString asJson() override
short getSymbolSyncSample() const
Definition: dsddecoder.h:34
double m_magsqSum
Definition: dsddemod.h:240
Real m_interpolatorDistanceRemain
Definition: dsddemod.h:230
int m_inputSampleRate
Definition: dsddemod.h:222
T & readBack(int delay)
AudioDeviceManager * getAudioDeviceManager()
Definition: dspengine.h:55
void addChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Add a channel sink (Rx)
Definition: deviceapi.cpp:118
static const QString m_channelId
Definition: dsddemod.h:168
const char * updateAndGetStatusText()
Definition: dsddemod.cpp:641
void setAudioGain(float gain)
Definition: dsddecoder.h:72
virtual QByteArray serialize() const
Definition: dsddemod.cpp:619
QNetworkAccessManager * m_networkManager
Definition: dsddemod.h:263
void setDsdDemodSettings(SWGDSDDemodSettings *dsd_demod_settings)
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
void setMyPoint(float lat, float lon)
Definition: dsddecoder.h:71
uint16_t m_reverseAPIChannelIndex
int m_scaleFromShort
Definition: dsddemod.h:250
static MsgConfigureChannelizer * create(int sampleRate, int centerFrequency)
Definition: dsddemod.h:83
void resetAudio1()
Definition: dsddecoder.h:37
DSDDecoder m_dsdDecoder
Definition: dsddemod.h:257
const unsigned char * getMbeDVFrame1() const
Definition: dsddecoder.h:47
virtual void start()
Definition: dsddemod.cpp:353
void pushSample(short sample)
Definition: dsddecoder.h:32
void setSymbolPLLLock(bool pllLock)
Definition: dsddecoder.h:74
short * getAudio1(int &nbSamples)
Definition: dsddecoder.h:36
int getIndexInDeviceSet() const
Definition: channelapi.h:87
void setSyncType(QString *sync_type)
std::complex< Real > Complex
Definition: dsptypes.h:43
const unsigned char * getMbeDVFrame2() const
Definition: dsddecoder.h:48
double asDouble() const
Definition: movingaverage.h:57
const DSDDecoder & getDecoder() const
Definition: dsddemod.h:131
QString m_reverseAPIAddress
#define SDR_RX_SCALED
Definition: dsptypes.h:34
float Real
Definition: dsptypes.h:42
double m_magsq
Definition: dsddemod.h:239
void setEnableCosineFiltering(qint32 enable_cosine_filtering)
qint16 FixReal
Definition: dsptypes.h:35
uint32_t write(const quint8 *data, uint32_t numSamples)
Definition: audiofifo.cpp:66
bool m_squelchOpen
Definition: dsddemod.h:235
static MsgConfigureDSDDemod * create(const DSDDemodSettings &settings, bool force)
Definition: dsddemod.h:60
QNetworkRequest m_networkRequest
Definition: dsddemod.h:264
void setReverseApiPort(qint32 reverse_api_port)
void setSyncRate(qint32 sync_rate)
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force=false)
Definition: dsddemod.cpp:447
void setInputFrequencyOffset(qint64 input_frequency_offset)