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.
xtrxoutputgui.cpp
Go to the documentation of this file.
1 // Copyright (C) 2019 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include <algorithm>
19 
20 #include <QDebug>
21 #include <QMessageBox>
22 
23 #include "ui_xtrxoutputgui.h"
24 #include "gui/colormapper.h"
25 #include "gui/glspectrum.h"
26 #include "gui/crightclickenabler.h"
28 #include "dsp/dspengine.h"
29 #include "dsp/dspcommands.h"
30 #include "device/deviceapi.h"
31 #include "device/deviceuiset.h"
32 #include "xtrxoutputgui.h"
33 
34 XTRXOutputGUI::XTRXOutputGUI(DeviceUISet *deviceUISet, QWidget* parent) :
35  QWidget(parent),
36  ui(new Ui::XTRXOutputGUI),
37  m_deviceUISet(deviceUISet),
38  m_settings(),
39  m_sampleRateMode(true),
40  m_sampleRate(0),
41  m_lastEngineState(DeviceAPI::StNotStarted),
42  m_doApplySettings(true),
43  m_forceSettings(true),
44  m_statusCounter(0),
45  m_deviceStatusCounter(0)
46 {
48 
49  ui->setupUi(this);
50 
51  float minF, maxF, stepF;
52 
53  m_XTRXOutput->getLORange(minF, maxF, stepF);
54  ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
55  ui->centerFrequency->setValueRange(7, ((uint32_t) minF)/1000, ((uint32_t) maxF)/1000); // frequency dial is in kHz
56 
57  m_XTRXOutput->getSRRange(minF, maxF, stepF);
58  ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
59  ui->sampleRate->setValueRange(8, (uint32_t) minF, (uint32_t) maxF);
60 
61  m_XTRXOutput->getLPRange(minF, maxF, stepF);
62  ui->lpf->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
63  ui->lpf->setValueRange(6, (minF/1000)+1, maxF/1000);
64 
65  ui->ncoFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
66 
67  ui->channelNumberText->setText(tr("#%1").arg(m_XTRXOutput->getChannelIndex()));
68 
69  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
70  connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
71  m_statusTimer.start(500);
72 
73  CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
74  connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
75 
77 
78  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
79 }
80 
82 {
83  delete ui;
84 }
85 
87 {
88  delete this;
89 }
90 
91 void XTRXOutputGUI::setName(const QString& name)
92 {
93  setObjectName(name);
94 }
95 
96 QString XTRXOutputGUI::getName() const
97 {
98  return objectName();
99 }
100 
102 {
104  displaySettings();
105  sendSettings();
106 }
107 
109 {
111 }
112 
113 void XTRXOutputGUI::setCenterFrequency(qint64 centerFrequency)
114 {
116  displaySettings();
117  sendSettings();
118 }
119 
120 QByteArray XTRXOutputGUI::serialize() const
121 {
122  return m_settings.serialize();
123 }
124 
125 bool XTRXOutputGUI::deserialize(const QByteArray& data)
126 {
127  if (m_settings.deserialize(data))
128  {
129  displaySettings();
130  m_forceSettings = true;
131  sendSettings();
132  return true;
133  }
134  else
135  {
136  resetToDefaults();
137  return false;
138  }
139 }
140 
142 {
143 
145  {
149 
150  if (!report.getRxElseTx()) {
152  }
153 
154  blockApplySettings(true);
155  displaySettings();
156  blockApplySettings(false);
157 
158  return true;
159  }
161  {
164  m_settings.m_extClock = report.getExtClock();
165 
166  blockApplySettings(true);
167  ui->extClock->setExternalClockFrequency(m_settings.m_extClockFreq);
168  ui->extClock->setExternalClockActive(m_settings.m_extClock);
169  blockApplySettings(false);
170 
171  return true;
172  }
174  {
176 
177  blockApplySettings(true);
178  displaySettings();
179  blockApplySettings(false);
180 
181  return true;
182  }
183  else if (XTRXOutput::MsgReportStreamInfo::match(message))
184  {
186 
187  if (report.getSuccess())
188  {
189  if (report.getActive()) {
190  ui->streamStatusLabel->setStyleSheet("QLabel { background-color : green; }");
191  } else {
192  ui->streamStatusLabel->setStyleSheet("QLabel { background-color : blue; }");
193  }
194 
195  ui->fifoBar->setMaximum(report.getFifoSize());
196  ui->fifoBar->setValue(report.getFifoFilledCount());
197  ui->fifoBar->setToolTip(tr("FIFO fill %1/%2 samples").arg(QString::number(report.getFifoFilledCount())).arg(QString::number(report.getFifoSize())));
198  }
199  else
200  {
201  ui->streamStatusLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
202  }
203 
204  return true;
205  }
207  {
209  ui->temperatureText->setText(tr("%1C").arg(QString::number(report.getTemperature(), 'f', 0)));
210 
211  if (report.getGPSLocked()) {
212  ui->gpsStatusLabel->setStyleSheet("QLabel { background-color : green; }");
213  } else {
214  ui->gpsStatusLabel->setStyleSheet("QLabel { background:rgb(48,48,48); }");
215  }
216 
217  return true;
218  }
219  else if (XTRXOutput::MsgStartStop::match(message))
220  {
222  blockApplySettings(true);
223  ui->startStop->setChecked(notif.getStartStop());
224  blockApplySettings(false);
225 
226  return true;
227  }
228  return false;
229 }
230 
232 {
233  Message* message;
234 
235  while ((message = m_inputMessageQueue.pop()) != 0)
236  {
237  if (DSPSignalNotification::match(*message))
238  {
239  DSPSignalNotification* notif = (DSPSignalNotification*) message;
240  m_sampleRate = notif->getSampleRate();
242  qDebug("XTRXOutputGUI::handleInputMessages: DSPSignalNotification: SampleRate: %d, CenterFrequency: %llu", notif->getSampleRate(), notif->getCenterFrequency());
244 
245  delete message;
246  }
247  else if (XTRXOutput::MsgConfigureXTRX::match(*message))
248  {
249  qDebug("XTRXOutputGUI::handleInputMessages: MsgConfigureXTRX");
251  m_settings = cfg.getSettings();
252  displaySettings();
253 
254  delete message;
255  }
256  else
257  {
258  if (handleMessage(*message)) {
259  delete message;
260  }
261  }
262  }
263 }
264 
266 {
267  uint32_t dacRate = m_XTRXOutput->getClockGen() / 4;
268 
269  if (dacRate < 100000000) {
270  ui->dacRateLabel->setText(tr("%1k").arg(QString::number(dacRate / 1000.0f, 'g', 5)));
271  } else {
272  ui->dacRateLabel->setText(tr("%1M").arg(QString::number(dacRate / 1000000.0f, 'g', 5)));
273  }
274 }
275 
277 {
281 }
282 
284 {
285  float minF, maxF, stepF;
286  m_XTRXOutput->getSRRange(minF, maxF, stepF);
287 
288  ui->sampleRate->blockSignals(true);
289 
290  if (m_sampleRateMode)
291  {
292  ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(60,60,60); }");
293  ui->sampleRateMode->setText("SR");
294  ui->sampleRate->setValueRange(8, (uint32_t) minF, (uint32_t) maxF);
295  ui->sampleRate->setValue(m_settings.m_devSampleRate);
296  ui->sampleRate->setToolTip("Device to host sample rate (S/s)");
297  ui->deviceRateText->setToolTip("Baseband sample rate (S/s)");
299  ui->deviceRateText->setText(tr("%1k").arg(QString::number(basebandSampleRate / 1000.0f, 'g', 5)));
300  }
301  else
302  {
303  ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(50,50,50); }");
304  ui->sampleRateMode->setText("BB");
305  ui->sampleRate->setValueRange(8, (uint32_t) minF/(1<<m_settings.m_log2SoftInterp), (uint32_t) maxF/(1<<m_settings.m_log2SoftInterp));
306  ui->sampleRate->setValue(m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftInterp));
307  ui->sampleRate->setToolTip("Baseband sample rate (S/s)");
308  ui->deviceRateText->setToolTip("Device to host sample rate (S/s)");
309  ui->deviceRateText->setText(tr("%1k").arg(QString::number(m_settings.m_devSampleRate / 1000.0f, 'g', 5)));
310  }
311 
312  ui->sampleRate->blockSignals(false);
313 }
314 
316 {
317  ui->extClock->setExternalClockFrequency(m_settings.m_extClockFreq);
318  ui->extClock->setExternalClockActive(m_settings.m_extClock);
319 
322 
323  ui->hwInterp->setCurrentIndex(m_settings.m_log2HardInterp);
324  ui->swInterp->setCurrentIndex(m_settings.m_log2SoftInterp);
325 
326  updateDACRate();
327 
328  ui->lpf->setValue(m_settings.m_lpfBW / 1000);
329  ui->pwrmode->setCurrentIndex(m_settings.m_pwrmode);
330 
331  ui->gain->setValue(m_settings.m_gain);
332  ui->gainText->setText(tr("%1").arg(m_settings.m_gain));
333 
334  ui->antenna->setCurrentIndex((int) m_settings.m_antennaPath - (int) XTRX_TX_H);
335 
336  setNCODisplay();
337 
338  ui->ncoEnable->setChecked(m_settings.m_ncoEnable);
339 }
340 
342 {
343  int ncoHalfRange = (m_settings.m_devSampleRate * (1<<(m_settings.m_log2HardInterp)))/2;
344  ui->ncoFrequency->setValueRange(
345  false,
346  8,
347  -ncoHalfRange,
348  ncoHalfRange);
349 
350  ui->ncoFrequency->blockSignals(true);
351  ui->ncoFrequency->setToolTip(QString("NCO frequency shift in Hz (Range: +/- %1 kHz)").arg(ncoHalfRange/1000));
352  ui->ncoFrequency->setValue(m_settings.m_ncoFrequency);
353  ui->ncoFrequency->blockSignals(false);
354 }
355 
357 {
358  int64_t centerFrequency = m_settings.m_centerFrequency;
359  ui->centerFrequency->setToolTip(QString("Main center frequency in kHz (LO: %1 kHz)").arg(centerFrequency/1000));
360 
361  if (m_settings.m_ncoEnable) {
362  centerFrequency += m_settings.m_ncoFrequency;
363  }
364 
365  ui->centerFrequency->blockSignals(true);
366  ui->centerFrequency->setValue(centerFrequency < 0 ? 0 : (uint64_t) centerFrequency/1000); // kHz
367  ui->centerFrequency->blockSignals(false);
368 }
369 
371 {
372  int64_t centerFrequency = kHzValue*1000;
373 
374  if (m_settings.m_ncoEnable) {
375  centerFrequency -= m_settings.m_ncoFrequency;
376  }
377 
378  m_settings.m_centerFrequency = centerFrequency < 0 ? 0 : (uint64_t) centerFrequency;
379  ui->centerFrequency->setToolTip(QString("Main center frequency in kHz (LO: %1 kHz)").arg(centerFrequency/1000));
380 }
381 
383 {
384  if(!m_updateTimer.isActive())
385  m_updateTimer.start(100);
386 }
387 
389 {
390  if (m_doApplySettings)
391  {
392  qDebug() << "XTRXOutputGUI::updateHardware";
395  m_forceSettings = false;
396  m_updateTimer.stop();
397  }
398 }
399 
401 {
402  int state = m_deviceUISet->m_deviceAPI->state();
403 
404  if(m_lastEngineState != state)
405  {
406  switch(state)
407  {
409  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
410  break;
411  case DeviceAPI::StIdle:
412  ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
413  break;
415  ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
416  break;
417  case DeviceAPI::StError:
418  ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
419  QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
420  break;
421  default:
422  break;
423  }
424 
425  m_lastEngineState = state;
426  }
427 
428  if (m_statusCounter < 1)
429  {
430  m_statusCounter++;
431  }
432  else
433  {
436  m_statusCounter = 0;
437  }
438 
439  if (m_deviceStatusCounter < 10)
440  {
442  }
443  else
444  {
446  {
449  }
450 
452  }
453 }
454 
456 {
457  m_doApplySettings = !block;
458 }
459 
461 {
462  if (m_doApplySettings)
463  {
466  }
467 }
468 
470 {
472  sendSettings();
473 }
474 
476 {
477  m_settings.m_ncoFrequency = value;
479  sendSettings();
480 }
481 
483 {
484  m_settings.m_ncoEnable = checked;
486  sendSettings();
487 }
488 
490 {
491  if (m_sampleRateMode) {
492  m_settings.m_devSampleRate = value;
493  } else {
495  }
496 
497  updateDACRate();
498  setNCODisplay();
499  sendSettings();}
500 
502 {
503  if ((index <0) || (index > 5)) {
504  return;
505  }
506 
508 
509  updateDACRate();
510  setNCODisplay();
511  sendSettings();
512 }
513 
515 {
516  if ((index <0) || (index > 6)) {
517  return;
518  }
519 
522 
523  if (m_sampleRateMode) {
524  m_settings.m_devSampleRate = ui->sampleRate->getValueNew();
525  } else {
526  m_settings.m_devSampleRate = ui->sampleRate->getValueNew() * (1 << m_settings.m_log2SoftInterp);
527  }
528 
529  sendSettings();
530 }
531 
532 void XTRXOutputGUI::on_lpf_changed(quint64 value)
533 {
534  m_settings.m_lpfBW = value * 1000;
535  sendSettings();
536 }
537 
539 {
540  m_settings.m_gain = value;
541  ui->gainText->setText(tr("%1").arg(m_settings.m_gain));
542  sendSettings();
543 }
544 
546 {
547  m_settings.m_antennaPath = (xtrx_antenna_t) (index + (int) XTRX_TX_H);
548  sendSettings();
549 }
550 
552 {
553  m_settings.m_extClock = ui->extClock->getExternalClockActive();
554  m_settings.m_extClockFreq = ui->extClock->getExternalClockFrequency();
555  qDebug("XTRXOutputGUI::on_extClock_clicked: %u Hz %s", m_settings.m_extClockFreq, m_settings.m_extClock ? "on" : "off");
556  sendSettings();
557 }
558 
560 {
561  m_settings.m_pwrmode = index;
562  sendSettings();
563 }
564 
566 {
567  m_sampleRateMode = checked;
569 }
570 
572 {
573  BasicDeviceSettingsDialog dialog(this);
578 
579  dialog.move(p);
580  dialog.exec();
581 
586 
587  sendSettings();
588 }
double getClockGen() const
Definition: xtrxoutput.cpp:526
Message * pop()
Pop message from queue.
const QString & getReverseAPIAddress() const
void setCenterFrequencyDisplay()
static MsgGetDeviceInfo * create()
Definition: xtrxoutput.h:83
QString getName() const
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
Definition: glspectrum.cpp:211
void getLPRange(float &minF, float &maxF, float &stepF) const
Definition: xtrxoutput.cpp:578
bool isBuddyLeader() const
Definition: deviceapi.h:163
virtual qint64 getCenterFrequency() const
void setUseReverseAPI(bool useReverseAPI)
QTimer m_statusTimer
Definition: xtrxoutputgui.h:62
static MsgConfigureXTRX * create(const XTRXOutputSettings &settings, bool force)
Definition: xtrxoutput.h:48
void handleInputMessages()
bool m_doApplySettings
Definition: xtrxoutputgui.h:66
bool m_extClock
True if external clock source.
uint32_t m_gain
Optimally distributed gain (dB)
int m_ncoFrequency
Actual NCO frequency (the resulting frequency with mixing is displayed)
uint32_t getDevSampleRate() const
Definition: xtrxoutput.cpp:504
void blockApplySettings(bool block)
static MsgGetStreamInfo * create()
Definition: xtrxoutput.h:68
xtrx_antenna_t m_antennaPath
Ui::XTRXOutputGUI * ui
Definition: xtrxoutputgui.h:55
std::size_t getChannelIndex()
Definition: xtrxoutput.cpp:555
bool deserialize(const QByteArray &data)
void on_ncoEnable_toggled(bool checked)
virtual ~XTRXOutputGUI()
QString errorMessage()
Last error message from the device engine.
Definition: deviceapi.cpp:290
void on_sampleRateMode_toggled(bool checked)
bool m_ncoEnable
Enable TSP NCO and mixing.
void on_pwrmode_currentIndexChanged(int index)
DeviceSampleSink * getSampleSink()
Return pointer to the device sample sink (single Tx) or nullptr.
Definition: deviceapi.cpp:222
void on_sampleRate_changed(quint64 value)
__int64 int64_t
Definition: rtptypes_win.h:47
void on_ncoFrequency_changed(qint64 value)
XTRXOutputSettings m_settings
Definition: xtrxoutputgui.h:59
unsigned int uint32_t
Definition: rtptypes_win.h:46
void displaySettings()
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
void openDeviceSettingsDialog(const QPoint &p)
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
QByteArray serialize() const
quint64 m_deviceCenterFrequency
Center frequency in device.
Definition: xtrxoutputgui.h:64
void on_extClock_clicked()
DeviceAPI * m_deviceAPI
Definition: deviceuiset.h:48
engine is idle
Definition: deviceapi.h:54
MessageQueue * getInputMessageQueue()
void on_antenna_currentIndexChanged(int index)
uint16_t m_reverseAPIDeviceIndex
XTRXOutput * m_XTRXOutput
Same object as above but gives easy access to XTRXInput methods and attributes that are used intensiv...
Definition: xtrxoutputgui.h:58
uint32_t m_extClockFreq
Frequency (Hz) of external clock source.
QByteArray serialize() const
DeviceUISet * m_deviceUISet
Definition: xtrxoutputgui.h:57
void on_hwInterp_currentIndexChanged(int index)
void setName(const QString &name)
static bool match(const Message *message)
Definition: message.cpp:45
virtual bool handleMessage(const Message &message)
bool m_sampleRateMode
true: device, false: base band sample rate update mode
Definition: xtrxoutputgui.h:60
void on_lpf_changed(quint64 value)
uint32_t getFifoSize() const
Definition: xtrxoutput.h:116
bool m_forceSettings
Definition: xtrxoutputgui.h:67
bool deserialize(const QByteArray &data)
XTRXOutputGUI(DeviceUISet *deviceUISet, QWidget *parent=0)
const XTRXOutputSettings & getSettings() const
Definition: xtrxoutput.h:45
QTimer m_updateTimer
Definition: xtrxoutputgui.h:61
void setCenterFrequencySetting(uint64_t kHzValue)
virtual void destroy()
bool getStartStop() const
Definition: xtrxoutput.h:158
void on_gain_valueChanged(int value)
int getSampleRate() const
Definition: dspcommands.h:328
void on_swInterp_currentIndexChanged(int index)
int m_deviceStatusCounter
Definition: xtrxoutputgui.h:69
void setCenterFrequency(qint64 frequency)
Definition: glspectrum.cpp:175
void setReverseAPIAddress(const QString &address)
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
void updateSampleRateAndFrequency()
static MsgStartStop * create(bool startStop)
Definition: xtrxoutput.h:160
void getLORange(float &minF, float &maxF, float &stepF) const
Definition: xtrxoutput.cpp:560
engine is running
Definition: deviceapi.h:56
float m_lpfBW
LMS analog lowpass filter bandwidth (Hz)
void getSRRange(float &minF, float &maxF, float &stepF) const
Definition: xtrxoutput.cpp:569
void on_centerFrequency_changed(quint64 value)
virtual void setCenterFrequency(qint64 centerFrequency)
uint32_t getFifoFilledCount() const
Definition: xtrxoutput.h:115
engine is in error
Definition: deviceapi.h:57
void resetToDefaults()
MessageQueue m_inputMessageQueue
Definition: xtrxoutputgui.h:70
void displaySampleRate()
unsigned __int64 uint64_t
Definition: rtptypes_win.h:48
void on_startStop_toggled(bool checked)