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.
plutosdrinputgui.cpp
Go to the documentation of this file.
1 // Copyright (C) 2017 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 <stdio.h>
19 #include <QDebug>
20 #include <QMessageBox>
21 
22 #include "dsp/dspengine.h"
23 #include "dsp/dspcommands.h"
24 #include "gui/glspectrum.h"
25 #include "gui/crightclickenabler.h"
27 #include "device/deviceapi.h"
28 #include "device/deviceuiset.h"
30 #include "plutosdrinput.h"
31 #include "ui_plutosdrinputgui.h"
32 #include "plutosdrinputgui.h"
33 
34 PlutoSDRInputGui::PlutoSDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
35  QWidget(parent),
36  ui(new Ui::PlutoSDRInputGUI),
37  m_deviceUISet(deviceUISet),
38  m_settings(),
39  m_sampleRateMode(true),
40  m_forceSettings(true),
41  m_sampleSource(NULL),
42  m_sampleRate(0),
43  m_deviceCenterFrequency(0),
44  m_lastEngineState(DeviceAPI::StNotStarted),
45  m_doApplySettings(true),
46  m_statusCounter(0)
47 {
49 
50  ui->setupUi(this);
51  ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
53 
54  ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
56 
57  ui->lpf->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
58 
59  quint32 minLimit, maxLimit;
60  ((PlutoSDRInput *) m_sampleSource)->getbbLPRange(minLimit, maxLimit);
61  ui->lpf->setValueRange(5, minLimit/1000, maxLimit/1000);
62 
63  ui->lpFIR->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
64  ui->lpFIR->setValueRange(5, 1U, 56000U); // will be dynamically recalculated
65 
66  ui->swDecimLabel->setText(QString::fromUtf8("S\u2193"));
67  ui->lpFIRDecimationLabel->setText(QString::fromUtf8("\u2193"));
68 
69  CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
70  connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
71 
72  blockApplySettings(true);
74  blockApplySettings(false);
75 
76  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
77  connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
78  m_statusTimer.start(500);
79 
80  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
82 }
83 
85 {
86  delete ui;
87 }
88 
90 {
91  delete this;
92 }
93 
94 void PlutoSDRInputGui::setName(const QString& name)
95 {
96  setObjectName(name);
97 }
98 
100 {
101  return objectName();
102 }
103 
105 {
106 
107 }
108 
110 {
112 }
113 
114 void PlutoSDRInputGui::setCenterFrequency(qint64 centerFrequency)
115 {
116  m_settings.m_centerFrequency = centerFrequency;
117  displaySettings();
118  sendSettings();
119 }
120 
121 QByteArray PlutoSDRInputGui::serialize() const
122 {
123  return m_settings.serialize();
124 }
125 
126 bool PlutoSDRInputGui::deserialize(const QByteArray& data)
127 {
128  if(m_settings.deserialize(data))
129  {
130  blockApplySettings(true);
131  displaySettings();
132  blockApplySettings(false);
133  sendSettings(true);
134  return true;
135  }
136  else
137  {
138  resetToDefaults();
139  return false;
140  }
141 }
142 
144 {
146  {
148  m_settings = cfg.getSettings();
149  blockApplySettings(true);
150  displaySettings();
151  blockApplySettings(false);
152  return true;
153  }
154  else if (PlutoSDRInput::MsgStartStop::match(message))
155  {
157  blockApplySettings(true);
158  ui->startStop->setChecked(notif.getStartStop());
159  blockApplySettings(false);
160 
161  return true;
162  }
163  else if (DevicePlutoSDRShared::MsgCrossReportToBuddy::match(message)) // message from buddy
164  {
171  blockApplySettings(true);
172  displaySettings();
173  blockApplySettings(false);
174 
175  return true;
176  }
177  else
178  {
179  return false;
180  }
181 }
182 
184 {
185  if (m_doApplySettings)
186  {
189  }
190 }
191 
193 {
194  if (checked) {
195  ui->record->setStyleSheet("QToolButton { background-color : red; }");
196  } else {
197  ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
198  }
199 
202 }
203 
205 {
206  m_settings.m_centerFrequency = value * 1000;
207  sendSettings();
208 }
209 
211 {
212  ui->loPPMText->setText(QString("%1").arg(QString::number(value/10.0, 'f', 1)));
213  m_settings.m_LOppmTenths = value;
214  sendSettings();
215 }
216 
218 {
219  m_settings.m_dcBlock = checked;
220  sendSettings();
221 }
222 
224 {
225  m_settings.m_iqCorrection = checked;
226  sendSettings();
227 }
228 
230 {
231  m_settings.m_hwRFDCBlock = checked;
232  sendSettings();
233 }
234 
236 {
237  m_settings.m_hwBBDCBlock = checked;
238  sendSettings();
239 }
240 
242 {
243  m_settings.m_hwIQCorrection = checked;
244  sendSettings();
245 }
246 
247 
249 {
250  m_settings.m_log2Decim = index > 6 ? 6 : index;
252  m_settings.m_devSampleRate = ui->sampleRate->getValueNew();
253 
254  if (!m_sampleRateMode) {
256  }
257 
258  sendSettings();
259 }
260 
262 {
265  sendSettings();
266 }
267 
269 {
270  m_settings.m_devSampleRate = value;
271 
272  if (!m_sampleRateMode) {
274  }
275 
277  sendSettings();
278 }
279 
281 {
282  m_settings.m_lpfBW = value * 1000;
283  sendSettings();
284 }
285 
287 {
288  m_settings.m_lpfFIREnable = checked;
289  ui->lpFIRDecimation->setEnabled(checked);
290  ui->lpFIRGain->setEnabled(checked);
291  sendSettings();
292 }
293 
295 {
296  m_settings.m_lpfFIRBW = value * 1000;
297  sendSettings();
298 }
299 
301 {
302  m_settings.m_lpfFIRlog2Decim = index > 2 ? 2 : index;
304  sendSettings();
305 }
306 
308 {
309  m_settings.m_lpfFIRGain = 6*(index > 3 ? 3 : index) - 12;
310  sendSettings();
311 }
312 
314 {
317  sendSettings();
318 }
319 
321 {
322  ui->gainText->setText(tr("%1").arg(value));
323  m_settings.m_gain = value;
324  sendSettings();
325 }
326 
328 {
330  sendSettings();
331 }
332 
334 {
335  m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive();
336  m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency();
337  qDebug("PlutoSDRInputGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off");
339  m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000;
340  sendSettings();
341 }
342 
344 {
345  m_sampleRateMode = checked;
347 }
348 
350 {
351  ui->sampleRate->blockSignals(true);
353 
354  if (m_sampleRateMode)
355  {
356  ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(60,60,60); }");
357  ui->sampleRateMode->setText("SR");
358  ui->sampleRate->setValueRange(8, DevicePlutoSDR::srLowLimitFreq, DevicePlutoSDR::srHighLimitFreq);
359  ui->sampleRate->setValue(m_settings.m_devSampleRate);
360  ui->sampleRate->setToolTip("Device to host sample rate (S/s)");
361  ui->deviceRateText->setToolTip("Baseband sample rate (S/s)");
362  uint32_t basebandSampleRate = m_settings.m_devSampleRate/(1<<m_settings.m_log2Decim);
363  ui->deviceRateText->setText(tr("%1k").arg(QString::number(basebandSampleRate / 1000.0f, 'g', 5)));
364  }
365  else
366  {
367  ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(50,50,50); }");
368  ui->sampleRateMode->setText("BB");
370  ui->sampleRate->setValue(m_settings.m_devSampleRate/(1<<m_settings.m_log2Decim));
371  ui->sampleRate->setToolTip("Baseband sample rate (S/s)");
372  ui->deviceRateText->setToolTip("Device to host sample rate (S/s)");
373  ui->deviceRateText->setText(tr("%1k").arg(QString::number(m_settings.m_devSampleRate / 1000.0f, 'g', 5)));
374  }
375 
376  ui->sampleRate->blockSignals(false);
377 }
378 
380 {
385  DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD
386  );
387  ui->fcPos->setToolTip(tr("Relative position of device center frequency: %1 kHz").arg(QString::number(fShift / 1000.0f, 'g', 5)));
388 }
389 
391 {
392  ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency);
393  ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode);
395  ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
397 
398  ui->dcOffset->setChecked(m_settings.m_dcBlock);
399  ui->iqImbalance->setChecked(m_settings.m_iqCorrection);
400  ui->bbDCOffset->setChecked(m_settings.m_hwBBDCBlock);
401  ui->rfDCOffset->setChecked(m_settings.m_hwRFDCBlock);
402  ui->hwIQImbalance->setChecked(m_settings.m_hwIQCorrection);
403  ui->loPPM->setValue(m_settings.m_LOppmTenths);
404  ui->loPPMText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1)));
405 
406  ui->swDecim->setCurrentIndex(m_settings.m_log2Decim);
407  ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos);
408 
409  ui->lpf->setValue(m_settings.m_lpfBW / 1000);
410 
411  ui->lpFIREnable->setChecked(m_settings.m_lpfFIREnable);
412  ui->lpFIR->setValue(m_settings.m_lpfFIRBW / 1000);
413  ui->lpFIRDecimation->setCurrentIndex(m_settings.m_lpfFIRlog2Decim);
414  ui->lpFIRGain->setCurrentIndex((m_settings.m_lpfFIRGain + 12)/6);
415  ui->lpFIRDecimation->setEnabled(m_settings.m_lpfFIREnable);
416  ui->lpFIRGain->setEnabled(m_settings.m_lpfFIREnable);
417 
418  ui->gainMode->setCurrentIndex((int) m_settings.m_gainMode);
419  ui->gain->setValue(m_settings.m_gain);
420  ui->gainText->setText(tr("%1").arg(m_settings.m_gain));
421 
422  ui->antenna->setCurrentIndex((int) m_settings.m_antennaPath);
423 
424  setFIRBWLimits();
426 }
427 
428 void PlutoSDRInputGui::sendSettings(bool forceSettings)
429 {
430  m_forceSettings = forceSettings;
431  if(!m_updateTimer.isActive()) { m_updateTimer.start(100); }
432 }
433 
435 {
436  if (m_doApplySettings)
437  {
438  qDebug() << "PlutoSDRInputGui::updateHardware";
441  m_forceSettings = false;
442  m_updateTimer.stop();
443  }
444 }
445 
447 {
448  m_doApplySettings = !block;
449 }
450 
452 {
453  int state = m_deviceUISet->m_deviceAPI->state();
454 
455  if(m_lastEngineState != state)
456  {
457  switch(state)
458  {
460  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
461  break;
462  case DeviceAPI::StIdle:
463  ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
464  break;
466  ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
467  break;
468  case DeviceAPI::StError:
469  ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
470  QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
471  break;
472  default:
473  break;
474  }
475 
476  m_lastEngineState = state;
477  }
478 
479  if (m_statusCounter % 2 == 0) // 1s
480  {
481  uint32_t adcRate = ((PlutoSDRInput *) m_sampleSource)->getADCSampleRate();
482 
483  if (adcRate < 100000000) {
484  ui->adcRateText->setText(tr("%1k").arg(QString::number(adcRate / 1000.0f, 'g', 5)));
485  } else {
486  ui->adcRateText->setText(tr("%1M").arg(QString::number(adcRate / 1000000.0f, 'g', 5)));
487  }
488  }
489 
490  if (m_statusCounter % 4 == 0) // 2s
491  {
492  std::string rssiStr;
493  ((PlutoSDRInput *) m_sampleSource)->getRSSI(rssiStr);
494  ui->rssiText->setText(tr("-%1").arg(QString::fromStdString(rssiStr)));
495  int gaindB;
496  ((PlutoSDRInput *) m_sampleSource)->getGain(gaindB);
497  ui->actualGainText->setText(tr("%1").arg(gaindB));
498  }
499 
500  if (m_statusCounter % 10 == 0) // 5s
501  {
503  ((PlutoSDRInput *) m_sampleSource)->fetchTemperature();
504  }
505 
506  ui->temperatureText->setText(tr("%1C").arg(QString::number(((PlutoSDRInput *) m_sampleSource)->getTemperature(), 'f', 0)));
507  }
508 
509  m_statusCounter++;
510 }
511 
513 {
514  float high = DevicePlutoSDR::firBWHighLimitFactor * ((PlutoSDRInput *) m_sampleSource)->getFIRSampleRate();
515  float low = DevicePlutoSDR::firBWLowLimitFactor * ((PlutoSDRInput *) m_sampleSource)->getFIRSampleRate();
516  ui->lpFIR->setValueRange(5, (int(low)/1000)+1, (int(high)/1000)+1);
517  ui->lpFIR->setValue(m_settings.m_lpfFIRBW/1000);
518 }
519 
521 {
522  uint32_t low = ui->lpFIREnable->isChecked() ? DevicePlutoSDR::srLowLimitFreq / (1<<ui->lpFIRDecimation->currentIndex()) : DevicePlutoSDR::srLowLimitFreq;
523  ui->sampleRate->setValueRange(8, low, DevicePlutoSDR::srHighLimitFreq);
524  ui->sampleRate->setValue(m_settings.m_devSampleRate);
525 }
526 
528 {
529  qint64 minLimit, maxLimit;
530  // values should be in kHz
531  qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0;
532  ((PlutoSDRInput *) m_sampleSource)->getLORange(minLimit, maxLimit);
533 
534  minLimit = minLimit/1000 + deltaFrequency;
535  maxLimit = maxLimit/1000 + deltaFrequency;
536 
537  minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit;
538  maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit;
539 
540  qDebug("PlutoSDRInputGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit);
541 
542  ui->centerFrequency->setValueRange(7, minLimit, maxLimit);
543 }
544 
546 {
547  Message* message;
548 
549  while ((message = m_inputMessageQueue.pop()) != 0)
550  {
551  qDebug("PlutoSDRInputGui::handleInputMessages: message: %s", message->getIdentifier());
552 
553  if (DSPSignalNotification::match(*message))
554  {
555  DSPSignalNotification* notif = (DSPSignalNotification*) message;
556  m_sampleRate = notif->getSampleRate();
558  qDebug("PlutoSDRInputGui::handleInputMessages: DSPSignalNotification: SampleRate: %d, CenterFrequency: %llu", notif->getSampleRate(), notif->getCenterFrequency());
560  setFIRBWLimits();
561 
562  delete message;
563  }
564  else
565  {
566  if (handleMessage(*message))
567  {
568  delete message;
569  }
570  }
571  }
572 }
573 
575 {
579 }
580 
582 {
583  BasicDeviceSettingsDialog dialog(this);
588 
589  dialog.move(p);
590  dialog.exec();
591 
596 
597  sendSettings();
598 }
void on_lpFIREnable_toggled(bool checked)
Message * pop()
Pop message from queue.
const QString & getReverseAPIAddress() const
static const uint32_t srHighLimitFreq
Device sample rate higher limit in S/s.
virtual void destroy()
static qint32 calculateFrequencyShift(int log2Decim, fcPos_t fcPos, quint32 devSampleRate, FrequencyShiftScheme frequencyShiftScheme)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
Definition: glspectrum.cpp:211
static const float firBWHighLimitFactor
Factor by which the FIR working sample rate is multiplied to yield bandwidth higher limit...
bool m_lpfFIREnable
enable digital lowpass FIR filter
bool isBuddyLeader() const
Definition: deviceapi.h:163
void on_dcOffset_toggled(bool checked)
DeviceSampleSource * getSampleSource()
Return pointer to the device sample source (single Rx) or nullptr.
Definition: deviceapi.cpp:213
void setUseReverseAPI(bool useReverseAPI)
quint32 m_lpfFIRlog2Decim
digital lowpass FIR filter log2 of decimation factor (0..2)
void on_swDecim_currentIndexChanged(int index)
static MsgConfigurePlutoSDR * create(const PlutoSDRInputSettings &settings, bool force)
Definition: plutosdrinput.h:48
virtual QByteArray serialize() const
void on_gainMode_currentIndexChanged(int index)
MessageQueue * getInputMessageQueue()
void openDeviceSettingsDialog(const QPoint &p)
void on_bbDCOffset_toggled(bool checked)
PlutoSDRInputGui(DeviceUISet *deviceUISet, QWidget *parent=0)
void blockApplySettings(bool block)
void on_lpFIRGain_currentIndexChanged(int index)
QString errorMessage()
Last error message from the device engine.
Definition: deviceapi.cpp:290
void on_fcPos_currentIndexChanged(int index)
bool m_hwRFDCBlock
Hardware RF DC blocking.
void on_loPPM_valueChanged(int value)
DeviceSampleSource * m_sampleSource
Ui::PlutoSDRInputGUI * ui
unsigned int uint32_t
Definition: rtptypes_win.h:46
QByteArray serialize() const
static const uint32_t srLowLimitFreq
Device sample rate lower limit in S/s.
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
void on_lpf_changed(quint64 value)
virtual void setName(const QString &name)
GLSpectrum * getSpectrum()
Direct spectrum getter.
Definition: deviceuiset.h:57
engine is before initialization
Definition: deviceapi.h:53
uint32_t m_statusCounter
void on_rfDCOffset_toggled(bool checked)
bool m_hwIQCorrection
Hardware IQ correction.
qint64 getCenterFrequency() const
Definition: dspcommands.h:329
EngineState state() const
Return the state of the device engine corresponding to the stream type.
Definition: deviceapi.cpp:277
bool m_sampleRateMode
true: device, false: base band sample rate update mode
DeviceAPI * m_deviceAPI
Definition: deviceuiset.h:48
engine is idle
Definition: deviceapi.h:54
void sendSettings(bool forceSettings=false)
void on_startStop_toggled(bool checked)
void updateSampleRateAndFrequency()
quint64 m_devSampleRate
Host interface sample rate.
static bool match(const Message *message)
Definition: message.cpp:45
int int32_t
Definition: rtptypes_win.h:45
quint32 m_lpfBW
analog lowpass filter bandwidth (Hz)
quint32 m_gain
"hardware" gain
bool deserialize(const QByteArray &data)
virtual bool deserialize(const QByteArray &data)
virtual void setCenterFrequency(qint64 centerFrequency)
void on_antenna_currentIndexChanged(int index)
void on_iqImbalance_toggled(bool checked)
virtual void resetToDefaults()
MessageQueue m_inputMessageQueue
virtual qint64 getCenterFrequency() const
DeviceUISet * m_deviceUISet
qint32 m_LOppmTenths
XO correction.
virtual QString getName() const
const PlutoSDRInputSettings & getSettings() const
Definition: plutosdrinput.h:45
int getSampleRate() const
Definition: dspcommands.h:328
static const float firBWLowLimitFactor
Factor by which the FIR working sample rate is multiplied to yield bandwidth lower limit...
PlutoSDRInputSettings m_settings
void setCenterFrequency(qint64 frequency)
Definition: glspectrum.cpp:175
virtual const char * getIdentifier() const
Definition: message.cpp:35
void on_sampleRate_changed(quint64 value)
void setReverseAPIAddress(const QString &address)
bool m_hwBBDCBlock
Hardware baseband DC blocking.
virtual ~PlutoSDRInputGui()
static MsgStartStop * create(bool startStop)
Definition: plutosdrinput.h:89
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
quint32 m_lpfFIRBW
digital lowpass FIR filter bandwidth (Hz)
void on_sampleRateMode_toggled(bool checked)
void on_centerFrequency_changed(quint64 value)
virtual void setMessageQueueToGUI(MessageQueue *queue)=0
engine is running
Definition: deviceapi.h:56
virtual bool handleMessage(const Message &message)
void on_gain_valueChanged(int value)
static MsgFileRecord * create(bool startStop)
Definition: plutosdrinput.h:70
quint64 m_deviceCenterFrequency
Center frequency in device.
void on_lpFIR_changed(quint64 value)
engine is in error
Definition: deviceapi.h:57
void on_lpFIRDecimation_currentIndexChanged(int index)
void on_hwIQImbalance_toggled(bool checked)
void on_record_toggled(bool checked)
int m_lpfFIRGain
digital lowpass FIR filter gain (dB)