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.
hackrfoutputgui.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 <QDebug>
19 #include <QMessageBox>
20 
21 #include <libhackrf/hackrf.h>
22 
23 #include "gui/colormapper.h"
24 #include "gui/glspectrum.h"
25 #include "gui/crightclickenabler.h"
27 #include "dsp/dspengine.h"
28 #include "dsp/dspcommands.h"
29 #include "device/deviceapi.h"
30 #include "device/deviceuiset.h"
33 
34 #include "hackrfoutputgui.h"
35 #include "ui_hackrfoutputgui.h"
36 
37 HackRFOutputGui::HackRFOutputGui(DeviceUISet *deviceUISet, QWidget* parent) :
38  QWidget(parent),
39  ui(new Ui::HackRFOutputGui),
40  m_deviceUISet(deviceUISet),
41  m_forceSettings(true),
42  m_settings(),
43  m_sampleRateMode(true),
44  m_deviceSampleSink(0),
45  m_lastEngineState(DeviceAPI::StNotStarted),
46  m_doApplySettings(true)
47 {
49 
50  ui->setupUi(this);
51  ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
52  ui->centerFrequency->setValueRange(7, 0U, 7250000U);
53 
54  ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
55  ui->sampleRate->setValueRange(8, 1000000U, 20000000U);
56 
57  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
58  connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
59  m_statusTimer.start(500);
60 
61  CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
62  connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
63 
66  sendSettings();
67 
68  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
69 }
70 
72 {
73  delete ui;
74 }
75 
77 {
78  delete this;
79 }
80 
81 void HackRFOutputGui::setName(const QString& name)
82 {
83  setObjectName(name);
84 }
85 
86 QString HackRFOutputGui::getName() const
87 {
88  return objectName();
89 }
90 
92 {
95  sendSettings();
96 }
97 
99 {
101 }
102 
103 void HackRFOutputGui::setCenterFrequency(qint64 centerFrequency)
104 {
105  m_settings.m_centerFrequency = centerFrequency;
106  displaySettings();
107  sendSettings();
108 }
109 
110 QByteArray HackRFOutputGui::serialize() const
111 {
112  return m_settings.serialize();
113 }
114 
115 bool HackRFOutputGui::deserialize(const QByteArray& data)
116 {
117  if(m_settings.deserialize(data))
118  {
119  displaySettings();
120  m_forceSettings = true;
121  sendSettings();
122  return true;
123  }
124  else
125  {
126  resetToDefaults();
127  return false;
128  }
129 }
130 
132 {
133  m_doApplySettings = !block;
134 }
135 
136 
138 {
140  {
142  m_settings = cfg.getSettings();
143  blockApplySettings(true);
144  displaySettings();
145  blockApplySettings(false);
146  return true;
147  }
148  else if (HackRFOutput::MsgReportHackRF::match(message))
149  {
150  displaySettings();
151  return true;
152  }
153  else if (HackRFOutput::MsgStartStop::match(message))
154  {
156  blockApplySettings(true);
157  ui->startStop->setChecked(notif.getStartStop());
158  blockApplySettings(false);
159  return true;
160  }
161  else
162  {
163  return false;
164  }
165 }
166 
168 {
169  Message* message;
170 
171  while ((message = m_inputMessageQueue.pop()) != 0)
172  {
173  qDebug("HackRFOutputGui::handleInputMessages: message: %s", message->getIdentifier());
174 
175  if (DSPSignalNotification::match(*message))
176  {
177  DSPSignalNotification* notif = (DSPSignalNotification*) message;
178  m_sampleRate = notif->getSampleRate();
180  qDebug("HackRFOutputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
182 
183  delete message;
184  }
185  else
186  {
187  if (handleMessage(*message))
188  {
189  delete message;
190  }
191  }
192  }
193 }
194 
196 {
200 }
201 
203 {
204  ui->sampleRate->blockSignals(true);
206 
207  if (m_sampleRateMode)
208  {
209  ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(60,60,60); }");
210  ui->sampleRateMode->setText("SR");
211  ui->sampleRate->setValueRange(8, 1000000U, 20000000U);
212  ui->sampleRate->setValue(m_settings.m_devSampleRate);
213  ui->sampleRate->setToolTip("Host to device sample rate (S/s)");
214  ui->deviceRateText->setToolTip("Baseband sample rate (S/s)");
215  uint32_t basebandSampleRate = m_settings.m_devSampleRate/(1<<m_settings.m_log2Interp);
216  ui->deviceRateText->setText(tr("%1k").arg(QString::number(basebandSampleRate / 1000.0f, 'g', 5)));
217  }
218  else
219  {
220  ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(50,50,50); }");
221  ui->sampleRateMode->setText("BB");
222  ui->sampleRate->setValueRange(8, 1000000U/(1<<m_settings.m_log2Interp), 20000000U/(1<<m_settings.m_log2Interp));
223  ui->sampleRate->setValue(m_settings.m_devSampleRate/(1<<m_settings.m_log2Interp));
224  ui->sampleRate->setToolTip("Baseband sample rate (S/s)");
225  ui->deviceRateText->setToolTip("Host to device sample rate (S/s)");
226  ui->deviceRateText->setText(tr("%1k").arg(QString::number(m_settings.m_devSampleRate / 1000.0f, 'g', 5)));
227  }
228 
229  ui->sampleRate->blockSignals(false);
230 }
231 
233 {
238  ui->fcPos->setToolTip(tr("Relative position of device center frequency: %1 kHz").arg(QString::number(fShift / 1000.0f, 'g', 5)));
239 }
240 
242 {
243  blockApplySettings(true);
244  ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
245 
246  ui->LOppm->setValue(m_settings.m_LOppmTenths);
247  ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1)));
248 
249  ui->biasT->setChecked(m_settings.m_biasT);
250 
252 
253  ui->interp->setCurrentIndex(m_settings.m_log2Interp);
254  ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos);
255 
256  ui->lnaExt->setChecked(m_settings.m_lnaExt);
257  ui->txvgaGainText->setText(tr("%1dB").arg(m_settings.m_vgaGain));
258  ui->txvga->setValue(m_settings.m_vgaGain);
259 
260  unsigned int bandwidthIndex = HackRFBandwidths::getBandwidthIndex(m_settings.m_bandwidth/1000);
261  ui->bbFilter->setCurrentIndex(bandwidthIndex);
262  blockApplySettings(false);
263 }
264 
266 {
267  blockApplySettings(true);
268  unsigned int savedIndex = HackRFBandwidths::getBandwidthIndex(m_settings.m_bandwidth/1000);
269  ui->bbFilter->blockSignals(true);
270  ui->bbFilter->clear();
271 
272  for (unsigned int i = 0; i < HackRFBandwidths::m_nb_bw; i++)
273  {
274  ui->bbFilter->addItem(QString("%1M").arg(QString::number(HackRFBandwidths::m_bw_k[i]/1000.0, 'f', 2)));
275  }
276 
277  ui->bbFilter->blockSignals(false);
278 
279  if (savedIndex < HackRFBandwidths::m_nb_bw)
280  {
281  ui->bbFilter->setCurrentIndex(savedIndex);
282  }
283  else
284  {
285  ui->bbFilter->setCurrentIndex((int) HackRFBandwidths::m_nb_bw-1);
286  }
287  blockApplySettings(false);
288 }
289 
291 {
292  if(!m_updateTimer.isActive())
293  m_updateTimer.start(100);
294 }
295 
297 {
298  m_settings.m_centerFrequency = value * 1000;
299  sendSettings();
300 }
301 
303 {
304  m_settings.m_devSampleRate = value;
305 
306  if (!m_sampleRateMode) {
308  }
309 
311  sendSettings();
312 }
313 
315 {
316  m_settings.m_LOppmTenths = value;
317  ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1)));
318  sendSettings();
319 }
320 
322 {
323  int newBandwidth = HackRFBandwidths::getBandwidth(index);
324  m_settings.m_bandwidth = newBandwidth * 1000;
325  sendSettings();
326 }
327 
329 {
330  m_settings.m_biasT = (state == Qt::Checked);
331  sendSettings();
332 }
333 
335 {
336  m_settings.m_lnaExt = (state == Qt::Checked);
337  sendSettings();
338 }
339 
341 {
342  if ((index <0) || (index > 6)) {
343  return;
344  }
345 
346  m_settings.m_log2Interp = index;
348  m_settings.m_devSampleRate = ui->sampleRate->getValueNew();
349 
350  if (!m_sampleRateMode) {
352  }
353 
354  sendSettings();
355 }
356 
358 {
359  m_settings.m_fcPos = (HackRFOutputSettings::fcPos_t) (index < 0 ? 0 : index > 2 ? 2 : index);
361  sendSettings();
362 }
363 
365 {
366  if ((value < 0) || (value > 47))
367  return;
368 
369  ui->txvgaGainText->setText(tr("%1dB").arg(value));
370  m_settings.m_vgaGain = value;
371  sendSettings();
372 }
373 
375 {
376  if (m_doApplySettings)
377  {
380  }
381 }
382 
384 {
385  m_sampleRateMode = checked;
387 }
388 
390 {
391  if (m_doApplySettings)
392  {
393  qDebug() << "HackRFOutputGui::updateHardware";
396  m_forceSettings = false;
397  m_updateTimer.stop();
398  }
399 }
400 
402 {
403  int state = m_deviceUISet->m_deviceAPI->state();
404 
405  if(m_lastEngineState != state)
406  {
407  switch(state)
408  {
410  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
411  break;
412  case DeviceAPI::StIdle:
413  ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
414  ui->startStop->setChecked(false);
415  break;
417  ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
418  break;
419  case DeviceAPI::StError:
420  ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
421  QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
422  break;
423  default:
424  break;
425  }
426 
427  m_lastEngineState = state;
428  }
429 }
430 
432 {
433  BasicDeviceSettingsDialog dialog(this);
438 
439  dialog.move(p);
440  dialog.exec();
441 
446 
447  sendSettings();
448 }
static const unsigned int m_nb_bw
virtual void destroy()
Message * pop()
Pop message from queue.
const QString & getReverseAPIAddress() const
void on_sampleRateMode_toggled(bool checked)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
Definition: glspectrum.cpp:211
void on_LOppm_valueChanged(int value)
virtual ~HackRFOutputGui()
void setUseReverseAPI(bool useReverseAPI)
static const unsigned int m_bw_k[]
void on_txvga_valueChanged(int value)
void on_sampleRate_changed(quint64 value)
static MsgConfigureHackRF * create(const HackRFOutputSettings &settings, bool force)
Definition: hackrfoutput.h:46
void blockApplySettings(bool block)
void on_interp_currentIndexChanged(int index)
HackRFOutputSettings m_settings
bool m_sampleRateMode
true: device, false: base band sample rate update mode
void on_centerFrequency_changed(quint64 value)
QString errorMessage()
Last error message from the device engine.
Definition: deviceapi.cpp:290
QString getName() const
void updateSampleRateAndFrequency()
DeviceSampleSink * getSampleSink()
Return pointer to the device sample sink (single Tx) or nullptr.
Definition: deviceapi.cpp:222
DeviceSampleSink * m_deviceSampleSink
unsigned int uint32_t
Definition: rtptypes_win.h:46
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
EngineState state() const
Return the state of the device engine corresponding to the stream type.
Definition: deviceapi.cpp:277
DeviceAPI * m_deviceAPI
Definition: deviceuiset.h:48
engine is idle
Definition: deviceapi.h:54
MessageQueue * getInputMessageQueue()
void openDeviceSettingsDialog(const QPoint &p)
int32_t i
Definition: decimators.h:244
MessageQueue m_inputMessageQueue
static bool match(const Message *message)
Definition: message.cpp:45
static unsigned int getBandwidth(unsigned int bandwidth_index)
static unsigned int getBandwidthIndex(unsigned int bandwidth)
virtual void setCenterFrequency(qint64 centerFrequency)
int int32_t
Definition: rtptypes_win.h:45
HackRFOutputGui(DeviceUISet *deviceUISet, QWidget *parent=0)
bool deserialize(const QByteArray &data)
DeviceUISet * m_deviceUISet
Ui::HackRFOutputGui * ui
void on_biasT_stateChanged(int state)
virtual bool handleMessage(const Message &message)
void on_startStop_toggled(bool checked)
void on_fcPos_currentIndexChanged(int index)
int getSampleRate() const
Definition: dspcommands.h:328
void setName(const QString &name)
void setCenterFrequency(qint64 frequency)
Definition: glspectrum.cpp:175
virtual const char * getIdentifier() const
Definition: message.cpp:35
void setReverseAPIAddress(const QString &address)
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
void on_bbFilter_currentIndexChanged(int index)
static qint32 calculateFrequencyShift(int log2Interp, fcPos_t fcPos, quint32 devSampleRate)
bool deserialize(const QByteArray &data)
virtual qint64 getCenterFrequency() const
engine is running
Definition: deviceapi.h:56
void on_lnaExt_stateChanged(int state)
quint64 m_deviceCenterFrequency
Center frequency in device.
static MsgStartStop * create(bool startStop)
Definition: hackrfoutput.h:68
QByteArray serialize() const
QByteArray serialize() const
const HackRFOutputSettings & getSettings() const
Definition: hackrfoutput.h:43
engine is in error
Definition: deviceapi.h:57