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.
soapysdrinputgui.cpp
Go to the documentation of this file.
1 // Copyright (C) 2018 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 <QMessageBox>
19 #include <QCheckBox>
20 
21 #include "dsp/dspengine.h"
22 #include "dsp/dspcommands.h"
23 #include "device/deviceapi.h"
24 #include "device/deviceuiset.h"
25 #include "util/simpleserializer.h"
26 #include "gui/glspectrum.h"
27 #include "gui/crightclickenabler.h"
35 #include "soapygui/arginfogui.h"
37 
38 #include "ui_soapysdrinputgui.h"
39 #include "soapysdrinputgui.h"
40 
41 SoapySDRInputGui::SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
42  QWidget(parent),
43  ui(new Ui::SoapySDRInputGui),
44  m_deviceUISet(deviceUISet),
45  m_forceSettings(true),
46  m_doApplySettings(true),
47  m_sampleSource(0),
48  m_sampleRate(0),
49  m_deviceCenterFrequency(0),
50  m_lastEngineState(DeviceAPI::StNotStarted),
51  m_antennas(0),
52  m_sampleRateGUI(0),
53  m_bandwidthGUI(0),
54  m_gainSliderGUI(0),
55  m_autoGain(0),
56  m_dcCorrectionGUI(0),
57  m_iqCorrectionGUI(0),
58  m_autoDCCorrection(0),
59  m_autoIQCorrection(0)
60 {
62  ui->setupUi(this);
63 
64  ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
65  uint64_t f_min, f_max;
66  m_sampleSource->getFrequencyRange(f_min, f_max);
67  ui->centerFrequency->setValueRange(7, f_min/1000, f_max/1000);
68 
82 
83  if (m_sampleRateGUI) {
84  connect(m_sampleRateGUI, SIGNAL(valueChanged(double)), this, SLOT(sampleRateChanged(double)));
85  }
86  if (m_bandwidthGUI) {
87  connect(m_bandwidthGUI, SIGNAL(valueChanged(double)), this, SLOT(bandwidthChanged(double)));
88  }
89 
90  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
91  connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
92  m_statusTimer.start(500);
93 
94  CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
95  connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
96 
98 
99  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
101 
102  sendSettings();
103 }
104 
106 {
107  delete ui;
108 }
109 
111 {
112  delete this;
113 }
114 
116  ItemSettingGUI **settingGUI,
117  const SoapySDR::RangeList& rangeList,
118  const QString& text,
119  const QString& unit)
120 {
121  if (rangeList.size() == 0) { // return early if the range list is empty
122  return;
123  }
124 
125  bool rangeDiscrete = true; // discretes values
126  bool rangeInterval = true; // intervals
127 
128  for (const auto &it : rangeList)
129  {
130  if (it.minimum() != it.maximum()) {
131  rangeDiscrete = false;
132  } else {
133  rangeInterval = false;
134  }
135  }
136 
137  if (rangeDiscrete)
138  {
139  DiscreteRangeGUI *rangeGUI = new DiscreteRangeGUI(this);
140  rangeGUI->setLabel(text);
141  rangeGUI->setUnits(QString("k%1").arg(unit));
142 
143  for (const auto &it : rangeList) {
144  rangeGUI->addItem(QString("%1").arg(QString::number(it.minimum()/1000.0, 'f', 0)), it.minimum());
145  }
146 
147  *settingGUI = rangeGUI;
148  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
149  layout->addWidget(rangeGUI);
150  }
151  else if (rangeInterval)
152  {
153  IntervalRangeGUI *rangeGUI = new IntervalRangeGUI(ui->scrollAreaWidgetContents);
154  rangeGUI->setLabel(text);
155  rangeGUI->setUnits(unit);
156 
157  for (const auto &it : rangeList) {
158  rangeGUI->addInterval(it.minimum(), it.maximum());
159  }
160 
161  rangeGUI->reset();
162 
163  *settingGUI = rangeGUI;
164  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
165  layout->addWidget(rangeGUI);
166  }
167 }
168 
169 void SoapySDRInputGui::createAntennasControl(const std::vector<std::string>& antennaList)
170 {
171  if (antennaList.size() == 0) { // return early if the antenna list is empty
172  return;
173  }
174 
175  m_antennas = new StringRangeGUI(this);
176  m_antennas->setLabel(QString("RF in"));
177  m_antennas->setUnits(QString("Port"));
178 
179  for (const auto &it : antennaList) {
180  m_antennas->addItem(QString(it.c_str()), it);
181  }
182 
183  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
184  layout->addWidget(m_antennas);
185 
186  connect(m_antennas, SIGNAL(valueChanged()), this, SLOT(antennasChanged()));
187 }
188 
189 void SoapySDRInputGui::createTunableElementsControl(const std::vector<DeviceSoapySDRParams::FrequencySetting>& tunableElementsList)
190 {
191  if (tunableElementsList.size() <= 1) { // This list is created for other elements than the main one (RF) which is always at index 0
192  return;
193  }
194 
195  std::vector<DeviceSoapySDRParams::FrequencySetting>::const_iterator it = tunableElementsList.begin() + 1;
196 
197  for (int i = 0; it != tunableElementsList.end(); ++it, i++)
198  {
199  if (it->m_ranges.size() == 0) { // skip empty ranges lists
200  continue;
201  }
202 
203  ItemSettingGUI *rangeGUI;
205  &rangeGUI,
206  it->m_ranges,
207  QString("%1 freq").arg(it->m_name.c_str()),
208  QString((it->m_name == "CORR") ? "ppm" : "Hz"));
209  DynamicItemSettingGUI *gui = new DynamicItemSettingGUI(rangeGUI, QString(it->m_name.c_str()));
210  m_tunableElementsGUIs.push_back(gui);
211  connect(m_tunableElementsGUIs.back(), SIGNAL(valueChanged(QString, double)), this, SLOT(tunableElementChanged(QString, double)));
212  }
213 }
214 
216 {
218  int min, max;
220  m_gainSliderGUI->setInterval(min, max);
221  m_gainSliderGUI->setLabel(QString("Global gain"));
222  m_gainSliderGUI->setUnits(QString(""));
223 
224  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
225 
226  QFrame *line = new QFrame(this);
227  line->setFrameShape(QFrame::HLine);
228  line->setFrameShadow(QFrame::Sunken);
229  layout->addWidget(line);
230 
232  {
233  m_autoGain = new QCheckBox(this);
234  m_autoGain->setText(QString("AGC"));
235  m_autoGain->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}");
236  layout->addWidget(m_autoGain);
237 
238  connect(m_autoGain, SIGNAL(toggled(bool)), this, SLOT(autoGainChanged(bool)));
239  }
240 
241  layout->addWidget(m_gainSliderGUI);
242 
243  connect(m_gainSliderGUI, SIGNAL(valueChanged(double)), this, SLOT(globalGainChanged(double)));
244 }
245 
246 void SoapySDRInputGui::createIndividualGainsControl(const std::vector<DeviceSoapySDRParams::GainSetting>& individualGainsList)
247 {
248  if (individualGainsList.size() == 0) { // Leave early if list of individual gains is empty
249  return;
250  }
251 
252  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
253  std::vector<DeviceSoapySDRParams::GainSetting>::const_iterator it = individualGainsList.begin();
254 
255  for (int i = 0; it != individualGainsList.end(); ++it, i++)
256  {
257  IntervalSliderGUI *gainGUI = new IntervalSliderGUI(this);
258  gainGUI->setInterval(it->m_range.minimum(), it->m_range.maximum());
259  gainGUI->setLabel(QString("%1 gain").arg(it->m_name.c_str()));
260  gainGUI->setUnits(QString(""));
261  DynamicItemSettingGUI *gui = new DynamicItemSettingGUI(gainGUI, QString(it->m_name.c_str()));
262  layout->addWidget(gainGUI);
263  m_individualGainsGUIs.push_back(gui);
264  connect(m_individualGainsGUIs.back(), SIGNAL(valueChanged(QString, double)), this, SLOT(individualGainChanged(QString, double)));
265  }
266 }
267 
269 {
270  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
271 
272  if (m_sampleSource->hasDCCorrectionValue()) // complex GUI
273  {
275  m_dcCorrectionGUI->setLabel(QString("DC corr"));
276  m_dcCorrectionGUI->setToolTip(QString("Hardware DC offset correction"));
278  layout->addWidget(m_dcCorrectionGUI);
279 
280  connect(m_dcCorrectionGUI, SIGNAL(moduleChanged(double)), this, SLOT(dcCorrectionModuleChanged(double)));
281  connect(m_dcCorrectionGUI, SIGNAL(argumentChanged(double)), this, SLOT(dcCorrectionArgumentChanged(double)));
282 
284  connect(m_dcCorrectionGUI, SIGNAL(automaticChanged(bool)), this, SLOT(autoDCCorrectionChanged(bool)));
285  }
286  }
287  else if (m_sampleSource->hasDCAutoCorrection()) // simple checkbox
288  {
289  m_autoDCCorrection = new QCheckBox(this);
290  m_autoDCCorrection->setText(QString("Auto DC corr"));
291  m_autoDCCorrection->setToolTip(QString("Automatic hardware DC offset correction"));
292  m_autoDCCorrection->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}");
293  layout->addWidget(m_autoDCCorrection);
294 
295  connect(m_autoDCCorrection, SIGNAL(toggled(bool)), this, SLOT(autoDCCorrectionChanged(bool)));
296  }
297 
298  if (m_sampleSource->hasIQCorrectionValue()) // complex GUI
299  {
301  m_iqCorrectionGUI->setLabel(QString("IQ corr"));
302  m_iqCorrectionGUI->setToolTip(QString("Hardware IQ imbalance correction"));
304  layout->addWidget(m_iqCorrectionGUI);
305 
306  connect(m_iqCorrectionGUI, SIGNAL(moduleChanged(double)), this, SLOT(iqCorrectionModuleChanged(double)));
307  connect(m_iqCorrectionGUI, SIGNAL(argumentChanged(double)), this, SLOT(iqCorrectionArgumentChanged(double)));
308 
310  connect(m_iqCorrectionGUI, SIGNAL(automaticChanged(bool)), this, SLOT(autoIQCorrectionChanged(bool)));
311  }
312  }
313  else if (m_sampleSource->hasIQAutoCorrection()) // simple checkbox
314  {
315  m_autoIQCorrection = new QCheckBox(this);
316  m_autoIQCorrection->setText(QString("Auto IQ corr"));
317  m_autoIQCorrection->setToolTip(QString("Automatic hardware IQ imbalance correction"));
318  m_autoIQCorrection->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}");
319  layout->addWidget(m_autoIQCorrection);
320 
321  connect(m_autoIQCorrection, SIGNAL(toggled(bool)), this, SLOT(autoIQCorrectionChanged(bool)));
322  }
323 }
324 
325 void SoapySDRInputGui::createArgumentsControl(const SoapySDR::ArgInfoList& argInfoList, bool deviceArguments)
326 {
327  if (argInfoList.size() == 0) { // return early if list is empty
328  return;
329  }
330 
331  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
332 
333  QFrame *line = new QFrame(this);
334  line->setFrameShape(QFrame::HLine);
335  line->setFrameShadow(QFrame::Sunken);
336  layout->addWidget(line);
337 
338  std::vector<SoapySDR::ArgInfo>::const_iterator it = argInfoList.begin();
339 
340  for (; it != argInfoList.end(); ++it)
341  {
343  ArgInfoGUI *argGUI;
344 
345  if (it->type == SoapySDR::ArgInfo::BOOL) {
346  valueType = ArgInfoGUI::ArgInfoValueBool;
347  } else if (it->type == SoapySDR::ArgInfo::INT) {
348  valueType = ArgInfoGUI::ArgInfoValueInt;
349  } else if (it->type == SoapySDR::ArgInfo::FLOAT) {
350  valueType = ArgInfoGUI::ArgInfoValueFloat;
351  } else if (it->type == SoapySDR::ArgInfo::STRING) {
352  valueType = ArgInfoGUI::ArgInfoValueString;
353  } else {
354  continue;
355  }
356 
357  if (valueType == ArgInfoGUI::ArgInfoValueBool)
358  {
360  }
361  else if (it->options.size() == 0)
362  {
363  argGUI = new ArgInfoGUI(ArgInfoGUI::ArgInfoContinuous, valueType, this);
364  }
365  else
366  {
367  argGUI = new ArgInfoGUI(ArgInfoGUI::ArgInfoDiscrete, valueType, this);
368  std::vector<std::string>::const_iterator optionIt = it->options.begin();
369  std::vector<std::string>::const_iterator optionNameIt = it->optionNames.begin();
370 
371  for (int i = 0; optionIt != it->options.end(); ++optionIt, i++)
372  {
373  QString name(optionNameIt == it->optionNames.end() ? optionIt->c_str() : optionNameIt->c_str());
374 
375  if (optionNameIt != it->optionNames.end()) {
376  ++optionNameIt;
377  }
378 
379  if (valueType == ArgInfoGUI::ArgInfoValueInt) {
380  argGUI->addIntValue(name, atoi(optionIt->c_str()));
381  } else if (valueType == ArgInfoGUI::ArgInfoValueFloat) {
382  argGUI->addFloatValue(name, atof(optionIt->c_str()));
383  } else if (valueType == ArgInfoGUI::ArgInfoValueString) {
384  argGUI->addStringValue(name, QString(optionIt->c_str()));
385  }
386  }
387  }
388 
389  if ((it->range.minimum() != 0) || (it->range.maximum() != 0)) {
390  argGUI->setRange(it->range.minimum(), it->range.maximum());
391  }
392 
393  argGUI->setLabel(QString(it->name.size() == 0 ? it->key.c_str() : it->name.c_str()));
394  argGUI->setUnits(QString(it->units.c_str()));
395 
396  if (it->description.size() != 0) {
397  argGUI->setToolTip(QString(it->description.c_str()));
398  }
399 
400  layout->addWidget(argGUI);
401 
402  DynamicArgSettingGUI *gui = new DynamicArgSettingGUI(argGUI, QString(it->key.c_str()));
403 
404  // This could be made more elegant but let's make it more simple
405  if (deviceArguments)
406  {
407  m_deviceArgsGUIs.push_back(gui);
408  connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(deviceArgChanged(QString, QVariant)));
409  }
410  else
411  {
412  m_streamArgsGUIs.push_back(gui);
413  connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(streamArgChanged(QString, QVariant)));
414  }
415  }
416 }
417 
418 void SoapySDRInputGui::setName(const QString& name)
419 {
420  setObjectName(name);
421 }
422 
424 {
425  return objectName();
426 }
427 
429 {
431  displaySettings();
432  sendSettings();
433 }
434 
436 {
438 }
439 
440 void SoapySDRInputGui::setCenterFrequency(qint64 centerFrequency)
441 {
442  m_settings.m_centerFrequency = centerFrequency;
443  displaySettings();
444  sendSettings();
445 }
446 
447 QByteArray SoapySDRInputGui::serialize() const
448 {
449  return m_settings.serialize();
450 }
451 
452 bool SoapySDRInputGui::deserialize(const QByteArray& data)
453 {
454  if (m_settings.deserialize(data))
455  {
456  displaySettings();
457  m_forceSettings = true;
458  sendSettings();
459  return true;
460  }
461  else
462  {
463  resetToDefaults();
464  return false;
465  }
466 }
467 
469 {
471  {
473  m_settings = cfg.getSettings();
474  blockApplySettings(true);
475  displaySettings();
476  blockApplySettings(false);
477 
478  return true;
479  }
481  {
483  const SoapySDRInputSettings& gainSettings = report.getSettings();
484 
485  if (report.getGlobalGain()) {
486  m_settings.m_globalGain = gainSettings.m_globalGain;
487  }
488  if (report.getIndividualGains()) {
490  }
491 
492  blockApplySettings(true);
493  displaySettings();
494  blockApplySettings(false);
495 
496  return true;
497  }
499  {
503 
504  return true;
505  }
506  else if (SoapySDRInput::MsgStartStop::match(message))
507  {
509  blockApplySettings(true);
510  ui->startStop->setChecked(notif.getStartStop());
511  blockApplySettings(false);
512 
513  return true;
514  }
515  else
516  {
517  return false;
518  }
519 }
520 
522 {
523  Message* message;
524 
525  while ((message = m_inputMessageQueue.pop()) != 0)
526  {
527  qDebug("SoapySDRInputGui::handleInputMessages: message: %s", message->getIdentifier());
528 
529  if (DSPSignalNotification::match(*message))
530  {
531  DSPSignalNotification* notif = (DSPSignalNotification*) message;
532  m_sampleRate = notif->getSampleRate();
534  qDebug("SoapySDRInputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
536 
537  delete message;
538  }
539  else
540  {
541  if (handleMessage(*message))
542  {
543  delete message;
544  }
545  }
546  }
547 }
548 
550 {
551  const std::string& antennaStr = m_antennas->getCurrentValue();
552  m_settings.m_antenna = QString(antennaStr.c_str());
553 
554  sendSettings();
555 }
556 
557 void SoapySDRInputGui::sampleRateChanged(double sampleRate)
558 {
559  m_settings.m_devSampleRate = round(sampleRate);
560  sendSettings();
561 }
562 
564 {
565  m_settings.m_bandwidth = round(bandwidth);
566  sendSettings();
567 }
568 
569 void SoapySDRInputGui::tunableElementChanged(QString name, double value)
570 {
571  m_settings.m_tunableElements[name] = value;
572  sendSettings();
573 }
574 
576 {
577  m_settings.m_globalGain = round(gain);
578  sendSettings();
579 }
580 
582 {
583  m_settings.m_autoGain = set;
584  sendSettings();
585 }
586 
587 void SoapySDRInputGui::individualGainChanged(QString name, double value)
588 {
589  m_settings.m_individualGains[name] = value;
590  sendSettings();
591 }
592 
594 {
596  sendSettings();
597 }
598 
600 {
602  sendSettings();
603 }
604 
606 {
607  std::complex<double> dcCorrection = std::polar<double>(value, arg(m_settings.m_dcCorrection));
608  m_settings.m_dcCorrection = dcCorrection;
609  sendSettings();
610 }
611 
613 {
614  double angleInRadians = (value / 180.0) * M_PI;
615  std::complex<double> dcCorrection = std::polar<double>(abs(m_settings.m_dcCorrection), angleInRadians);
616  m_settings.m_dcCorrection = dcCorrection;
617  sendSettings();
618 }
619 
621 {
622  std::complex<double> iqCorrection = std::polar<double>(value, arg(m_settings.m_iqCorrection));
623  m_settings.m_iqCorrection = iqCorrection;
624  sendSettings();
625 }
626 
628 {
629  double angleInRadians = (value / 180.0) * M_PI;
630  std::complex<double> iqCorrection = std::polar<double>(abs(m_settings.m_iqCorrection), angleInRadians);
631  m_settings.m_iqCorrection = iqCorrection;
632  sendSettings();
633 }
634 
635 void SoapySDRInputGui::streamArgChanged(QString itemName, QVariant value)
636 {
637  m_settings.m_streamArgSettings[itemName] = value;
638  sendSettings();
639 }
640 
641 void SoapySDRInputGui::deviceArgChanged(QString itemName, QVariant value)
642 {
643  m_settings.m_deviceArgSettings[itemName] = value;
644  sendSettings();
645 }
646 
648 {
649  m_settings.m_centerFrequency = value * 1000;
650  sendSettings();
651 }
652 
654 {
655  m_settings.m_softDCCorrection = checked;
656  sendSettings();
657 }
658 
660 {
661  m_settings.m_softIQCorrection = checked;
662  sendSettings();
663 }
664 
666 {
667  if ((index <0) || (index > 6))
668  return;
669  m_settings.m_log2Decim = index;
670  sendSettings();
671 }
672 
674 {
675  if (index == 0) {
677  sendSettings();
678  } else if (index == 1) {
680  sendSettings();
681  } else if (index == 2) {
683  sendSettings();
684  }
685 }
686 
688 {
689  m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive();
690  m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency();
691  qDebug("SoapySDRInputGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off");
693  setCenterFrequencySetting(ui->centerFrequency->getValueNew());
694  sendSettings();
695 }
696 
698 {
699  ui->LOppmText->setText(QString("%1").arg(QString::number(value/10.0, 'f', 1)));
700  m_settings.m_LOppmTenths = value;
701  sendSettings();
702 }
703 
705 {
706  if (m_doApplySettings)
707  {
710  }
711 }
712 
714 {
715  if (checked) {
716  ui->record->setStyleSheet("QToolButton { background-color : red; }");
717  } else {
718  ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
719  }
720 
723 }
724 
726 {
727  blockApplySettings(true);
728 
729  ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
730 
731  if (m_antennas) {
732  m_antennas->setValue(m_settings.m_antenna.toStdString());
733  }
734  if (m_sampleRateGUI)
735  {
738  }
739  if (m_bandwidthGUI)
740  {
743  }
744  if (m_gainSliderGUI)
745  {
748  }
749  if (m_autoGain) {
750  m_autoGain->setChecked(m_settings.m_autoGain);
751  }
752 
753  ui->dcOffset->setChecked(m_settings.m_softDCCorrection);
754  ui->iqImbalance->setChecked(m_settings.m_softIQCorrection);
755 
756  ui->decim->setCurrentIndex(m_settings.m_log2Decim);
757  ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos);
758 
759  ui->LOppm->setValue(m_settings.m_LOppmTenths);
760  ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1)));
761 
767 
768  blockApplySettings(false);
769 }
770 
772 {
773  for (const auto &it : m_tunableElementsGUIs)
774  {
775  QMap<QString, double>::const_iterator elIt = m_settings.m_tunableElements.find(it->getName());
776 
777  if (elIt != m_settings.m_tunableElements.end()) {
778  it->setValue(*elIt);
779  }
780  }
781 }
782 
784 {
785  for (const auto &it : m_individualGainsGUIs)
786  {
787  QMap<QString, double>::iterator elIt = m_settings.m_individualGains.find(it->getName());
788 
789  if (elIt != m_settings.m_individualGains.end())
790  {
791  it->setValue(*elIt);
792  *elIt = it->getValue();
793  }
794  }
795 }
796 
798 {
799  if (m_dcCorrectionGUI)
800  {
804  }
805 
806  if (m_iqCorrectionGUI)
807  {
811  }
812 
813  if (m_autoDCCorrection) {
815  }
816 
817  if (m_autoIQCorrection) {
819  }
820 }
821 
823 {
824  for (const auto &it : m_streamArgsGUIs)
825  {
826  QMap<QString, QVariant>::iterator elIt = m_settings.m_streamArgSettings.find(it->getName());
827 
828  if (elIt != m_settings.m_streamArgSettings.end())
829  {
830  it->setValue(elIt.value());
831  *elIt = it->getValue();
832  }
833  }
834 }
835 
837 {
838  for (const auto &it : m_deviceArgsGUIs)
839  {
840  QMap<QString, QVariant>::iterator elIt = m_settings.m_deviceArgSettings.find(it->getName());
841 
842  if (elIt != m_settings.m_deviceArgSettings.end())
843  {
844  it->setValue(elIt.value());
845  *elIt = it->getValue();
846  }
847  }
848 }
849 
851 {
852  if (!m_updateTimer.isActive()) {
853  m_updateTimer.start(100);
854  }
855 }
856 
858 {
861  ui->deviceRateText->setText(tr("%1k").arg(QString::number(m_sampleRate / 1000.0f, 'g', 5)));
862 }
863 
865 {
866  // values in kHz
867  uint64_t f_min, f_max;
868  qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0;
869  m_sampleSource->getFrequencyRange(f_min, f_max);
870  qint64 minLimit = f_min/1000 + deltaFrequency;
871  qint64 maxLimit = f_max/1000 + deltaFrequency;
872 
873  minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit;
874  maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit;
875 
876  qDebug("SoapySDRInputGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit);
877 
878  ui->centerFrequency->setValueRange(7, minLimit, maxLimit);
879 }
880 
882 {
883  int64_t centerFrequency = kHzValue*1000;
884 
885  m_settings.m_centerFrequency = centerFrequency < 0 ? 0 : (uint64_t) centerFrequency;
886  ui->centerFrequency->setToolTip(QString("Main center frequency in kHz (LO: %1 kHz)").arg(centerFrequency/1000));
887 }
888 
890 {
891  m_doApplySettings = !block;
892 }
893 
895 {
896  if (m_doApplySettings)
897  {
898  qDebug() << "SoapySDRInputGui::updateHardware";
901  m_forceSettings = false;
902  m_updateTimer.stop();
903  }
904 }
905 
907 {
908  int state = m_deviceUISet->m_deviceAPI->state();
909 
910  if(m_lastEngineState != state)
911  {
912  switch(state)
913  {
915  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
916  break;
917  case DeviceAPI::StIdle:
918  ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
919  break;
921  ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
922  break;
923  case DeviceAPI::StError:
924  ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
925  QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
926  break;
927  default:
928  break;
929  }
930 
931  m_lastEngineState = state;
932  }
933 }
934 
936 {
937  BasicDeviceSettingsDialog dialog(this);
942 
943  dialog.move(p);
944  dialog.exec();
945 
950 
951  sendSettings();
952 }
const SoapySDR::RangeList & getBandwidthRanges()
Message * pop()
Pop message from queue.
const QString & getReverseAPIAddress() const
const SoapySDR::RangeList & getRateRanges()
void on_centerFrequency_changed(quint64 value)
void individualGainChanged(QString name, double value)
QMap< QString, QVariant > m_streamArgSettings
virtual QByteArray serialize() const
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
Definition: glspectrum.cpp:211
const std::string & getCurrentValue()
void setUnits(const QString &units)
Definition: arginfogui.cpp:95
void createIndividualGainsControl(const std::vector< DeviceSoapySDRParams::GainSetting > &individualGainsList)
void setValue(const std::string &value)
void bandwidthChanged(double bandwidth)
const std::vector< DeviceSoapySDRParams::FrequencySetting > & getTunableElements()
ItemSettingGUI * m_bandwidthGUI
Ui::SoapySDRInputGui * ui
void setLabel(const QString &text)
void openDeviceSettingsDialog(const QPoint &p)
DeviceSampleSource * getSampleSource()
Return pointer to the device sample source (single Rx) or nullptr.
Definition: deviceapi.cpp:213
void setUseReverseAPI(bool useReverseAPI)
virtual void setValue(double value)=0
bool hasDCAutoCorrection()
QCheckBox * m_autoGain
MessageQueue * getInputMessageQueue()
void setUnits(const QString &units)
std::vector< DynamicArgSettingGUI * > m_deviceArgsGUIs
QCheckBox * m_autoDCCorrection
const QMap< QString, QVariant > & getDeviceArgSettings() const
SoapySDRInputSettings m_settings
virtual bool handleMessage(const Message &message)
virtual void destroy()
void setRange(double min, double max)
Definition: arginfogui.cpp:72
void on_decim_currentIndexChanged(int index)
void initGainSettings(SoapySDRInputSettings &settings)
virtual qint64 getCenterFrequency() const
bool hasDCCorrectionValue()
void streamArgChanged(QString itemName, QVariant value)
void on_record_toggled(bool checked)
Fixed< IntType, IntBits > abs(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2313
void sampleRateChanged(double sampleRate)
std::complex< double > m_iqCorrection
#define M_PI
Definition: rdsdemod.cpp:27
QString errorMessage()
Last error message from the device engine.
Definition: deviceapi.cpp:290
void autoGainChanged(bool set)
ComplexFactorGUI * m_dcCorrectionGUI
void on_LOppm_valueChanged(int value)
__int64 int64_t
Definition: rtptypes_win.h:47
QString getName() const
void createArgumentsControl(const SoapySDR::ArgInfoList &argInfoList, bool deviceArguments)
void initDeviceArgSettings(SoapySDRInputSettings &settings)
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
void createAntennasControl(const std::vector< std::string > &antennaList)
QMap< QString, QVariant > m_deviceArgSettings
GLSpectrum * getSpectrum()
Direct spectrum getter.
Definition: deviceuiset.h:57
engine is before initialization
Definition: deviceapi.h:53
qint64 getCenterFrequency() const
Definition: dspcommands.h:329
ComplexFactorGUI * m_iqCorrectionGUI
EngineState state() const
Return the state of the device engine corresponding to the stream type.
Definition: deviceapi.cpp:277
void setArgument(double value)
void on_fcPos_currentIndexChanged(int index)
void getFrequencyRange(uint64_t &min, uint64_t &max)
static MsgConfigureSoapySDRInput * create(const SoapySDRInputSettings &settings, bool force)
Definition: soapysdrinput.h:61
const SoapySDR::ArgInfoList & getStreamArgInfoList()
void setAutomatic(bool automatic)
DeviceAPI * m_deviceAPI
Definition: deviceuiset.h:48
engine is idle
Definition: deviceapi.h:54
void on_dcOffset_toggled(bool checked)
void setLabel(const QString &text)
void globalGainChanged(double gain)
QMap< QString, double > m_tunableElements
void setInterval(double minimum, double maximum)
void setLabel(const QString &text)
QCheckBox * m_autoIQCorrection
void setAutomaticEnable(bool enable)
static MsgFileRecord * create(bool startStop)
Definition: soapysdrinput.h:83
void addItem(const QString &itemStr, double itemValue)
bool deserialize(const QByteArray &data)
const std::vector< DeviceSoapySDRParams::GainSetting > & getIndividualGainsRanges()
int32_t i
Definition: decimators.h:244
std::complex< double > m_dcCorrection
QMap< QString, double > m_individualGains
static bool match(const Message *message)
Definition: message.cpp:45
ItemSettingGUI * m_sampleRateGUI
void setLabel(const QString &text)
QByteArray serialize() const
virtual double getCurrentValue()
void addItem(const QString &itemStr, const std::string &itemValue)
DeviceUISet * m_deviceUISet
void displayTunableElementsControlSettings()
std::vector< DynamicItemSettingGUI * > m_tunableElementsGUIs
int BOOL
Definition: fcdhid.h:37
void blockApplySettings(bool block)
quint64 m_deviceCenterFrequency
Center frequency in device.
virtual double getCurrentValue()=0
void dcCorrectionArgumentChanged(double value)
void deviceArgChanged(QString itemName, QVariant value)
const SoapySDRInputSettings & getSettings() const
Definition: soapysdrinput.h:58
void addIntValue(const QString &text, int value)
Definition: arginfogui.cpp:155
void setUnits(const QString &units)
void autoDCCorrectionChanged(bool set)
virtual void setCenterFrequency(qint64 centerFrequency)
void tunableElementChanged(QString name, double value)
const std::vector< std::string > & getAntennas()
void setCenterFrequencySetting(uint64_t kHzValue)
void initStreamArgSettings(SoapySDRInputSettings &settings)
void getGlobalGainRange(int &min, int &max)
bool hasIQCorrectionValue()
void setUnits(const QString &units)
void addInterval(double minimum, double maximum)
void createRangesControl(ItemSettingGUI **settingGUI, const SoapySDR::RangeList &rangeList, const QString &text, const QString &unit)
StringRangeGUI * m_antennas
void addFloatValue(const QString &text, double value)
Definition: arginfogui.cpp:186
void initTunableElementsSettings(SoapySDRInputSettings &settings)
void setModule(double value)
const SoapySDR::ArgInfoList & getDeviceArgInfoList()
void iqCorrectionArgumentChanged(double value)
void on_iqImbalance_toggled(bool checked)
void createTunableElementsControl(const std::vector< DeviceSoapySDRParams::FrequencySetting > &tunableElementsList)
int getSampleRate() const
Definition: dspcommands.h:328
std::vector< DynamicItemSettingGUI * > m_individualGainsGUIs
void setToolTip(const QString &text)
Definition: arginfogui.cpp:84
void setToolTip(const QString &text)
static MsgStartStop * create(bool startStop)
void autoIQCorrectionChanged(bool set)
SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget *parent=0)
void setCenterFrequency(qint64 frequency)
Definition: glspectrum.cpp:175
virtual const char * getIdentifier() const
Definition: message.cpp:35
void setReverseAPIAddress(const QString &address)
void iqCorrectionModuleChanged(double value)
bool hasIQAutoCorrection()
const SoapySDRInputSettings & getSettings() const
void displayIndividualGainsControlSettings()
MessageQueue m_inputMessageQueue
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
void on_startStop_toggled(bool checked)
void setLabel(const QString &text)
void setUnits(const QString &units)
engine is running
Definition: deviceapi.h:56
SoapySDRInput * m_sampleSource
virtual bool deserialize(const QByteArray &data)
void updateSampleRateAndFrequency()
std::vector< DynamicArgSettingGUI * > m_streamArgsGUIs
virtual void setValue(double value)
void setLabel(const QString &text)
Definition: arginfogui.cpp:79
engine is in error
Definition: deviceapi.h:57
T max(const T &x, const T &y)
Definition: framework.h:446
void addStringValue(const QString &text, const QString &value)
Definition: arginfogui.cpp:219
virtual void setMessageQueueToGUI(MessageQueue *queue)
void dcCorrectionModuleChanged(double value)
T min(const T &x, const T &y)
Definition: framework.h:440
void setName(const QString &name)
IntervalSliderGUI * m_gainSliderGUI
unsigned __int64 uint64_t
Definition: rtptypes_win.h:48
virtual void resetToDefaults()