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.
testsourcegui.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 <QDebug>
19 
20 #include <QTime>
21 #include <QDateTime>
22 #include <QString>
23 #include <QMessageBox>
24 
25 #include "ui_testsourcegui.h"
26 #include "plugin/pluginapi.h"
27 #include "gui/colormapper.h"
28 #include "gui/glspectrum.h"
29 #include "gui/crightclickenabler.h"
31 #include "dsp/dspengine.h"
32 #include "dsp/dspcommands.h"
33 #include "util/db.h"
34 
35 #include "mainwindow.h"
36 
37 #include "testsourcegui.h"
38 #include "device/deviceapi.h"
39 #include "device/deviceuiset.h"
40 
41 TestSourceGui::TestSourceGui(DeviceUISet *deviceUISet, QWidget* parent) :
42  QWidget(parent),
43  ui(new Ui::TestSourceGui),
44  m_deviceUISet(deviceUISet),
45  m_settings(),
46  m_doApplySettings(true),
47  m_forceSettings(true),
48  m_sampleSource(0),
49  m_tickCount(0),
50  m_lastEngineState(DeviceAPI::StNotStarted)
51 {
52  qDebug("TestSourceGui::TestSourceGui");
54 
55  ui->setupUi(this);
56  ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
57  ui->centerFrequency->setValueRange(7, 0, 9999999);
58  ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
59  ui->sampleRate->setValueRange(7, 48000, 9999999);
60  ui->frequencyShift->setColorMapper(ColorMapper(ColorMapper::GrayGold));
61  ui->frequencyShift->setValueRange(false, 7, -9999999, 9999999);
62  ui->frequencyShiftLabel->setText(QString("%1").arg(QChar(0x94, 0x03)));
63 
65 
66  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
67  connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
68  m_statusTimer.start(500);
69 
70  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
72 
73  CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
74  connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
75 }
76 
78 {
79  delete ui;
80 }
81 
83 {
84  delete this;
85 }
86 
87 void TestSourceGui::setName(const QString& name)
88 {
89  setObjectName(name);
90 }
91 
92 QString TestSourceGui::getName() const
93 {
94  return objectName();
95 }
96 
98 {
100  displaySettings();
101  sendSettings();
102 }
103 
105 {
107 }
108 
109 void TestSourceGui::setCenterFrequency(qint64 centerFrequency)
110 {
111  m_settings.m_centerFrequency = centerFrequency;
112  displaySettings();
113  sendSettings();
114 }
115 
116 QByteArray TestSourceGui::serialize() const
117 {
118  return m_settings.serialize();
119 }
120 
121 bool TestSourceGui::deserialize(const QByteArray& data)
122 {
123  if(m_settings.deserialize(data)) {
124  displaySettings();
125  m_forceSettings = true;
126  sendSettings();
127  return true;
128  } else {
129  resetToDefaults();
130  return false;
131  }
132 }
133 
135 {
136  if (m_doApplySettings)
137  {
140  }
141 }
142 
144 {
145  m_settings.m_centerFrequency = value * 1000;
146  sendSettings();
147 }
148 
150 {
151  if ((index < 0) || (index > TestSourceSettings::AutoCorrLast)) {
152  return;
153  }
154 
156  sendSettings();
157 }
158 
160 {
162  sendSettings();
163 }
164 
166 {
167  if ((index < 0) || (index > 6)) {
168  return;
169  }
170 
171  m_settings.m_log2Decim = index;
172  sendSettings();
173 }
174 
176 {
177  if ((index < 0) || (index > 2)) {
178  return;
179  }
180 
182  sendSettings();
183 }
184 
186 {
188  m_settings.m_frequencyShift = ui->frequencyShift->getValueNew();
189  m_settings.m_sampleRate = value;
190  sendSettings();
191 }
192 
194 {
195  if ((index < 0) || (index > 2)) {
196  return;
197  }
198 
202  m_settings.m_amplitudeBits = ui->amplitudeCoarse->value() * 100 + ui->amplitudeFine->value();
204  sendSettings();
205 }
206 
208 {
209  (void) value;
212  m_settings.m_amplitudeBits = ui->amplitudeCoarse->value() * 100 + ui->amplitudeFine->value();
213  sendSettings();
214 }
215 
217 {
218  (void) value;
220  m_settings.m_amplitudeBits = ui->amplitudeCoarse->value() * 100 + ui->amplitudeFine->value();
221  sendSettings();
222 }
223 
225 {
226  if ((index < 0) || (index > TestSourceSettings::ModulationLast)) {
227  return;
228  }
229 
231  sendSettings();
232 }
233 
235 {
237  ui->modulationFrequencyText->setText(QString("%1").arg(m_settings.m_modulationTone / 100.0, 0, 'f', 2));
238  sendSettings();
239 }
240 
242 {
243  m_settings.m_amModulation = value;
244  ui->amModulationText->setText(QString("%1").arg(m_settings.m_amModulation));
245  sendSettings();
246 }
247 
249 {
250  m_settings.m_fmDeviation = value;
251  ui->fmDeviationText->setText(QString("%1").arg(m_settings.m_fmDeviation / 10.0, 0, 'f', 1));
252  sendSettings();
253 }
254 
256 {
257  ui->dcBiasText->setText(QString(tr("%1 %").arg(value)));
258  m_settings.m_dcFactor = value / 100.0f;
259  sendSettings();
260 }
261 
263 {
264  ui->iBiasText->setText(QString(tr("%1 %").arg(value)));
265  m_settings.m_iFactor = value / 100.0f;
266  sendSettings();
267 }
268 
270 {
271  ui->qBiasText->setText(QString(tr("%1 %").arg(value)));
272  m_settings.m_qFactor = value / 100.0f;
273  sendSettings();
274 }
275 
277 {
278  ui->phaseImbalanceText->setText(QString(tr("%1 %").arg(value)));
279  m_settings.m_phaseImbalance = value / 100.0f;
280  sendSettings();
281 }
282 
284 {
285  if (checked) {
286  ui->record->setStyleSheet("QToolButton { background-color : red; }");
287  } else {
288  ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
289  }
290 
293 }
294 
296 {
297  int amplitudeInt = ui->amplitudeCoarse->value() * 100 + ui->amplitudeFine->value();
298  double power;
299 
300  switch (ui->sampleSize->currentIndex())
301  {
302  case 0: // 8 bits: 128
303  power = (double) amplitudeInt*amplitudeInt / (double) (1<<14);
304  break;
305  case 1: // 12 bits 2048
306  power = (double) amplitudeInt*amplitudeInt / (double) (1<<22);
307  break;
308  case 2: // 16 bits 32768
309  default:
310  power = (double) amplitudeInt*amplitudeInt / (double) (1<<30);
311  break;
312  }
313 
314  ui->amplitudeBits->setText(QString(tr("%1 b").arg(amplitudeInt)));
315  double powerDb = CalcDb::dbPower(power);
316  ui->power->setText(QString(tr("%1 dB").arg(QString::number(powerDb, 'f', 1))));
317 }
318 
320 {
321  switch (ui->sampleSize->currentIndex())
322  {
323  case 0: // 8 bits: 128
324  ui->amplitudeCoarse->setMaximum(1);
325  break;
326  case 1: // 12 bits 2048
327  ui->amplitudeCoarse->setMaximum(20);
328  break;
329  case 2: // 16 bits 32768
330  default:
331  ui->amplitudeCoarse->setMaximum(327);
332  break;
333  }
334 }
335 
337 {
338  switch (ui->sampleSize->currentIndex())
339  {
340  case 0: // 8 bits: 128
341  if (ui->amplitudeCoarse->value() == 1) {
342  ui->amplitudeFine->setMaximum(27);
343  } else {
344  ui->amplitudeFine->setMaximum(99);
345  }
346  break;
347  case 1: // 12 bits 2048
348  if (ui->amplitudeCoarse->value() == 20) {
349  ui->amplitudeFine->setMaximum(47);
350  } else {
351  ui->amplitudeFine->setMaximum(99);
352  }
353  break;
354  case 2: // 16 bits 32768
355  default:
356  if (ui->amplitudeCoarse->value() == 327) {
357  ui->amplitudeFine->setMaximum(67);
358  } else {
359  ui->amplitudeFine->setMaximum(99);
360  }
361  break;
362  }
363 }
364 
366 {
367  int sampleRate = ui->sampleRate->getValueNew();
368  ui->frequencyShift->setValueRange(false, 7, -sampleRate, sampleRate);
369 }
370 
372 {
373  blockApplySettings(true);
374  ui->sampleSize->blockSignals(true);
375 
376  ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
377  ui->decimation->setCurrentIndex(m_settings.m_log2Decim);
378  ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos);
379  ui->sampleRate->setValue(m_settings.m_sampleRate);
381  ui->frequencyShift->setValue(m_settings.m_frequencyShift);
382  ui->sampleSize->setCurrentIndex(m_settings.m_sampleSizeIndex);
384  int amplitudeBits = m_settings.m_amplitudeBits;
385  ui->amplitudeCoarse->setValue(amplitudeBits/100);
387  ui->amplitudeFine->setValue(amplitudeBits%100);
389  int dcBiasPercent = roundf(m_settings.m_dcFactor * 100.0f);
390  ui->dcBias->setValue((int) dcBiasPercent);
391  ui->dcBiasText->setText(QString(tr("%1 %").arg(dcBiasPercent)));
392  int iBiasPercent = roundf(m_settings.m_iFactor * 100.0f);
393  ui->iBias->setValue((int) iBiasPercent);
394  ui->iBiasText->setText(QString(tr("%1 %").arg(iBiasPercent)));
395  int qBiasPercent = roundf(m_settings.m_qFactor * 100.0f);
396  ui->qBias->setValue((int) qBiasPercent);
397  ui->qBiasText->setText(QString(tr("%1 %").arg(qBiasPercent)));
398  int phaseImbalancePercent = roundf(m_settings.m_phaseImbalance * 100.0f);
399  ui->phaseImbalance->setValue((int) phaseImbalancePercent);
400  ui->phaseImbalanceText->setText(QString(tr("%1 %").arg(phaseImbalancePercent)));
401  ui->autoCorr->setCurrentIndex(m_settings.m_autoCorrOptions);
402  ui->sampleSize->blockSignals(false);
403  ui->modulation->setCurrentIndex((int) m_settings.m_modulation);
404  ui->modulationFrequency->setValue(m_settings.m_modulationTone);
405  ui->modulationFrequencyText->setText(QString("%1").arg(m_settings.m_modulationTone / 100.0, 0, 'f', 2));
406  ui->amModulation->setValue(m_settings.m_amModulation);
407  ui->amModulationText->setText(QString("%1").arg(m_settings.m_amModulation));
408  ui->fmDeviation->setValue(m_settings.m_fmDeviation);
409  ui->fmDeviationText->setText(QString("%1").arg(m_settings.m_fmDeviation / 10.0, 0, 'f', 1));
410  blockApplySettings(false);
411 }
412 
414 {
415  if(!m_updateTimer.isActive()) {
416  m_updateTimer.start(100);
417  }
418 }
419 
421 {
422  if (m_doApplySettings)
423  {
426  m_forceSettings = false;
427  m_updateTimer.stop();
428  }
429 }
430 
432 {
433  int state = m_deviceUISet->m_deviceAPI->state();
434 
435  if(m_lastEngineState != state)
436  {
437  switch(state)
438  {
440  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
441  break;
442  case DeviceAPI::StIdle:
443  ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
444  break;
446  ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
447  break;
448  case DeviceAPI::StError:
449  ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
450  QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
451  break;
452  default:
453  break;
454  }
455 
456  m_lastEngineState = state;
457  }
458 }
459 
461 {
463  {
464  qDebug("TestSourceGui::handleMessage: MsgConfigureTestSource");
466  m_settings = cfg.getSettings();
467  displaySettings();
468  return true;
469  }
470  else if (TestSourceInput::MsgStartStop::match(message))
471  {
472  qDebug("TestSourceGui::handleMessage: MsgStartStop");
474  blockApplySettings(true);
475  ui->startStop->setChecked(notif.getStartStop());
476  blockApplySettings(false);
477 
478  return true;
479  }
480  else
481  {
482  return false;
483  }
484 }
485 
487 {
488  Message* message;
489 
490  while ((message = m_inputMessageQueue.pop()) != 0)
491  {
492  if (DSPSignalNotification::match(*message))
493  {
494  DSPSignalNotification* notif = (DSPSignalNotification*) message;
497  qDebug("TestSourceGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu",
498  notif->getSampleRate(),
499  notif->getCenterFrequency());
501 
502  delete message;
503  }
504  else
505  {
506  if (handleMessage(*message))
507  {
508  delete message;
509  }
510  }
511  }
512 }
513 
515 {
518  ui->deviceRateText->setText(tr("%1k").arg((float)m_deviceSampleRate / 1000));
519 }
520 
522 {
523  BasicDeviceSettingsDialog dialog(this);
528 
529  dialog.move(p);
530  dialog.exec();
531 
536 
537  sendSettings();
538 }
void on_startStop_toggled(bool checked)
void on_iBias_valueChanged(int value)
Message * pop()
Pop message from queue.
const QString & getReverseAPIAddress() const
QString getName() const
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
Definition: glspectrum.cpp:211
void resetToDefaults()
static MsgFileRecord * create(bool startStop)
void on_amModulation_valueChanged(int value)
static double dbPower(double magsq, double floor=1e-12)
Definition: db.cpp:22
virtual ~TestSourceGui()
virtual bool handleMessage(const Message &message)
DeviceSampleSource * getSampleSource()
Return pointer to the device sample source (single Rx) or nullptr.
Definition: deviceapi.cpp:213
void setUseReverseAPI(bool useReverseAPI)
bool deserialize(const QByteArray &data)
void displaySettings()
MessageQueue * getInputMessageQueue()
float m_qFactor
-1.0 < x < 1.0
void updateSampleRateAndFrequency()
MessageQueue m_inputMessageQueue
Definition: testsourcegui.h:69
void on_amplitudeCoarse_valueChanged(int value)
void updateAmpCoarseLimit()
float m_phaseImbalance
-1.0 < x < 1.0
QByteArray serialize() const
virtual void setCenterFrequency(qint64 centerFrequency)
void updateAmpFineLimit()
void blockApplySettings(bool block)
Definition: testsourcegui.h:71
QString errorMessage()
Last error message from the device engine.
Definition: deviceapi.cpp:290
AutoCorrOptions m_autoCorrOptions
void openDeviceSettingsDialog(const QPoint &p)
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
GLSpectrum * getSpectrum()
Direct spectrum getter.
Definition: deviceuiset.h:57
engine is before initialization
Definition: deviceapi.h:53
qint64 getCenterFrequency() const
Definition: dspcommands.h:329
virtual qint64 getCenterFrequency() const
EngineState state() const
Return the state of the device engine corresponding to the stream type.
Definition: deviceapi.cpp:277
Ui::TestSourceGui * ui
Definition: testsourcegui.h:56
QTimer m_updateTimer
Definition: testsourcegui.h:60
void on_fmDeviation_valueChanged(int value)
DeviceAPI * m_deviceAPI
Definition: deviceuiset.h:48
engine is idle
Definition: deviceapi.h:54
void updateFrequencyShiftLimit()
float m_iFactor
-1.0 < x < 1.0
void on_dcBias_valueChanged(int value)
static MsgConfigureTestSource * create(const TestSourceSettings &settings, bool force)
DeviceSampleSource * m_sampleSource
Definition: testsourcegui.h:64
TestSourceGui(DeviceUISet *deviceUISet, QWidget *parent=0)
void on_modulation_currentIndexChanged(int index)
void on_frequencyShift_changed(qint64 value)
void on_centerFrequency_changed(quint64 value)
uint16_t m_reverseAPIDeviceIndex
bool deserialize(const QByteArray &data)
void displayAmplitude()
void on_sampleSize_currentIndexChanged(int index)
static bool match(const Message *message)
Definition: message.cpp:45
int m_deviceSampleRate
Definition: testsourcegui.h:66
void handleInputMessages()
void on_amplitudeFine_valueChanged(int value)
void on_phaseImbalance_valueChanged(int value)
void on_record_toggled(bool checked)
DeviceUISet * m_deviceUISet
Definition: testsourcegui.h:58
void on_sampleRate_changed(quint64 value)
QTimer m_statusTimer
Definition: testsourcegui.h:61
int m_modulationTone
10&#39;Hz
int getSampleRate() const
Definition: dspcommands.h:328
void on_qBias_valueChanged(int value)
static MsgStartStop * create(bool startStop)
void on_fcPos_currentIndexChanged(int index)
void setCenterFrequency(qint64 frequency)
Definition: glspectrum.cpp:175
bool m_doApplySettings
Definition: testsourcegui.h:62
void setReverseAPIAddress(const QString &address)
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
bool m_forceSettings
Definition: testsourcegui.h:63
void on_decimation_currentIndexChanged(int index)
TestSourceSettings m_settings
Definition: testsourcegui.h:59
void on_autoCorr_currentIndexChanged(int index)
virtual void setMessageQueueToGUI(MessageQueue *queue)=0
engine is running
Definition: deviceapi.h:56
quint64 m_deviceCenterFrequency
Center frequency in device.
Definition: testsourcegui.h:67
int m_fmDeviation
100&#39;Hz
QByteArray serialize() const
engine is in error
Definition: deviceapi.h:57
const TestSourceSettings & getSettings() const
void on_modulationFrequency_valueChanged(int value)
void setName(const QString &name)
virtual void destroy()
int m_amModulation
percent
float m_dcFactor
-1.0 < x < 1.0