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.
bladerf2inputgui.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 #include <QMessageBox>
20 
21 #include <libbladeRF.h>
22 
23 #include "ui_bladerf2inputgui.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 
33 #include "bladerf2inputgui.h"
34 
35 BladeRF2InputGui::BladeRF2InputGui(DeviceUISet *deviceUISet, QWidget* parent) :
36  QWidget(parent),
37  ui(new Ui::Bladerf2InputGui),
38  m_deviceUISet(deviceUISet),
39  m_forceSettings(true),
40  m_doApplySettings(true),
41  m_settings(),
42  m_sampleRateMode(true),
43  m_sampleSource(0),
44  m_sampleRate(0),
45  m_lastEngineState(DeviceAPI::StNotStarted)
46 {
48  int max, min, step;
49  uint64_t f_min, f_max;
50 
51  ui->setupUi(this);
52 
53  m_sampleSource->getFrequencyRange(f_min, f_max, step);
54  ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
55  ui->centerFrequency->setValueRange(7, f_min/1000, f_max/1000);
56 
57  m_sampleSource->getSampleRateRange(min, max, step);
58  ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
59  ui->sampleRate->setValueRange(8, min, max);
60 
61  m_sampleSource->getBandwidthRange(min, max, step);
62  ui->bandwidth->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
63  ui->bandwidth->setValueRange(5, min/1000, max/1000);
64 
65  const std::vector<BladeRF2Input::GainMode>& modes = m_sampleSource->getGainModes();
66  std::vector<BladeRF2Input::GainMode>::const_iterator it = modes.begin();
67 
68  ui->gainMode->blockSignals(true);
69 
70  for (; it != modes.end(); ++it) {
71  ui->gainMode->addItem(it->m_name);
72  }
73 
74  ui->gainMode->blockSignals(false);
75 
76  m_sampleSource->getGlobalGainRange(min, max, step);
77  ui->gain->setMinimum(min);
78  ui->gain->setMaximum(max);
79  ui->gain->setPageStep(step);
80  ui->gain->setSingleStep(step);
81 
82  ui->label_decim->setText(QString::fromUtf8("D\u2193"));
83 
84  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
85  connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
86  m_statusTimer.start(500);
87 
88  CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
89  connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
90 
92 
93  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
95 
96  sendSettings();
97 }
98 
100 {
101  delete ui;
102 }
103 
105 {
106  delete this;
107 }
108 
109 void BladeRF2InputGui::setName(const QString& name)
110 {
111  setObjectName(name);
112 }
113 
115 {
116  return objectName();
117 }
118 
120 {
122  displaySettings();
123  sendSettings();
124 }
125 
127 {
129 }
130 
131 void BladeRF2InputGui::setCenterFrequency(qint64 centerFrequency)
132 {
133  m_settings.m_centerFrequency = centerFrequency;
134  displaySettings();
135  sendSettings();
136 }
137 
138 QByteArray BladeRF2InputGui::serialize() const
139 {
140  return m_settings.serialize();
141 }
142 
143 bool BladeRF2InputGui::deserialize(const QByteArray& data)
144 {
145  if(m_settings.deserialize(data)) {
146  displaySettings();
147  m_forceSettings = true;
148  sendSettings();
149  return true;
150  } else {
151  resetToDefaults();
152  return false;
153  }
154 }
155 
157 {
158  // values in kHz
159  uint64_t f_min, f_max;
160  int step;
161  qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0;
162  m_sampleSource->getFrequencyRange(f_min, f_max, step);
163  qint64 minLimit = f_min/1000 + deltaFrequency;
164  qint64 maxLimit = f_max/1000 + deltaFrequency;
165 
166  minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit;
167  maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit;
168 
169  qDebug("BladeRF2OutputGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit);
170 
171  ui->centerFrequency->setValueRange(7, minLimit, maxLimit);
172 }
173 
175 {
176  int64_t centerFrequency = kHzValue*1000;
177 
178  m_settings.m_centerFrequency = centerFrequency < 0 ? 0 : (uint64_t) centerFrequency;
179  ui->centerFrequency->setToolTip(QString("Main center frequency in kHz (LO: %1 kHz)").arg(centerFrequency/1000));
180 }
181 
183 {
185  {
187  m_settings = cfg.getSettings();
188  blockApplySettings(true);
189  int min, max, step;
190  m_sampleSource->getGlobalGainRange(min, max, step);
191  ui->gain->setMinimum(min);
192  ui->gain->setMaximum(max);
193  ui->gain->setPageStep(step);
194  ui->gain->setSingleStep(step);
195  displaySettings();
196  blockApplySettings(false);
197 
198  return true;
199  }
201  {
203  ui->gain->setMinimum(cfg.getMin());
204  ui->gain->setMaximum(cfg.getMax());
205  ui->gain->setSingleStep(cfg.getStep());
206  ui->gain->setPageStep(cfg.getStep());
207 
208  return true;
209  }
210  else if (BladeRF2Input::MsgStartStop::match(message))
211  {
213  blockApplySettings(true);
214  ui->startStop->setChecked(notif.getStartStop());
215  blockApplySettings(false);
216 
217  return true;
218  }
219  else
220  {
221  return false;
222  }
223 }
224 
226 {
227  Message* message;
228 
229  while ((message = m_inputMessageQueue.pop()) != 0)
230  {
231  qDebug("BladeRF2InputGui::handleInputMessages: message: %s", message->getIdentifier());
232 
233  if (DSPSignalNotification::match(*message))
234  {
235  DSPSignalNotification* notif = (DSPSignalNotification*) message;
236  m_sampleRate = notif->getSampleRate();
238  qDebug("BladeRF2InputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
240 
241  delete message;
242  }
243  else
244  {
245  if (handleMessage(*message))
246  {
247  delete message;
248  }
249  }
250  }
251 }
252 
254 {
258 }
259 
261 {
262  int max, min, step;
263  m_sampleSource->getSampleRateRange(min, max, step);
264 
265  ui->sampleRate->blockSignals(true);
267 
268  if (m_sampleRateMode)
269  {
270  ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(60,60,60); }");
271  ui->sampleRateMode->setText("SR");
272  // BladeRF can go as low as 80 kS/s but because of buffering in practice experience is not good below 330 kS/s
273  ui->sampleRate->setValueRange(8, min, max);
274  ui->sampleRate->setValue(m_settings.m_devSampleRate);
275  ui->sampleRate->setToolTip("Device to host sample rate (S/s)");
276  ui->deviceRateText->setToolTip("Baseband sample rate (S/s)");
277  uint32_t basebandSampleRate = m_settings.m_devSampleRate/(1<<m_settings.m_log2Decim);
278  ui->deviceRateText->setText(tr("%1k").arg(QString::number(basebandSampleRate / 1000.0f, 'g', 5)));
279  }
280  else
281  {
282  ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(50,50,50); }");
283  ui->sampleRateMode->setText("BB");
284  // BladeRF can go as low as 80 kS/s but because of buffering in practice experience is not good below 330 kS/s
285  ui->sampleRate->setValueRange(8, min/(1<<m_settings.m_log2Decim), max/(1<<m_settings.m_log2Decim));
286  ui->sampleRate->setValue(m_settings.m_devSampleRate/(1<<m_settings.m_log2Decim));
287  ui->sampleRate->setToolTip("Baseband sample rate (S/s)");
288  ui->deviceRateText->setToolTip("Device to host sample rate (S/s)");
289  ui->deviceRateText->setText(tr("%1k").arg(QString::number(m_settings.m_devSampleRate / 1000.0f, 'g', 5)));
290  }
291 
292  ui->sampleRate->blockSignals(false);
293 }
294 
296 {
301  DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD
302  );
303  ui->fcPos->setToolTip(tr("Relative position of device center frequency: %1 kHz").arg(QString::number(fShift / 1000.0f, 'g', 5)));
304 }
305 
307 {
308  blockApplySettings(true);
309 
310  ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency);
311  ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode);
312 
313  ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
314  ui->LOppm->setValue(m_settings.m_LOppmTenths);
315  ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1)));
317  ui->bandwidth->setValue(m_settings.m_bandwidth / 1000);
318 
319  ui->dcOffset->setChecked(m_settings.m_dcBlock);
320  ui->iqImbalance->setChecked(m_settings.m_iqCorrection);
321  ui->biasTee->setChecked(m_settings.m_biasTee);
322 
323  ui->decim->setCurrentIndex(m_settings.m_log2Decim);
324  ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos);
325 
326  ui->gainMode->setCurrentIndex(m_settings.m_gainMode);
327  ui->gainText->setText(tr("%1 dB").arg(m_settings.m_globalGain));
328  ui->gain->setValue(m_settings.m_globalGain);
329 
330  if (m_settings.m_gainMode == BLADERF_GAIN_MANUAL) {
331  ui->gain->setEnabled(true);
332  } else {
333  ui->gain->setEnabled(false);
334  }
335 
336  blockApplySettings(false);
337 }
338 
340 {
341  if(!m_updateTimer.isActive())
342  m_updateTimer.start(100);
343 }
344 
346 {
347  m_settings.m_centerFrequency = value * 1000;
348  sendSettings();
349 }
350 
352 {
353  ui->LOppmText->setText(QString("%1").arg(QString::number(value/10.0, 'f', 1)));
354  m_settings.m_LOppmTenths = value;
355  sendSettings();
356 }
357 
359 {
360  if (m_sampleRateMode) {
361  m_settings.m_devSampleRate = value;
362  } else {
364  }
365 
367  sendSettings();
368 }
369 
371 {
372  m_settings.m_dcBlock = checked;
373  sendSettings();
374 }
375 
377 {
378  m_settings.m_iqCorrection = checked;
379  sendSettings();
380 }
381 
383 {
384  m_settings.m_biasTee = checked;
385  sendSettings();
386 }
387 
389 {
390  m_settings.m_bandwidth = value * 1000;
391  sendSettings();
392 }
393 
395 {
396  if ((index <0) || (index > 6)) {
397  return;
398  }
399 
400  m_settings.m_log2Decim = index;
402 
403  if (m_sampleRateMode) {
404  m_settings.m_devSampleRate = ui->sampleRate->getValueNew();
405  } else {
406  m_settings.m_devSampleRate = ui->sampleRate->getValueNew() * (1 << m_settings.m_log2Decim);
407  }
408 
409  sendSettings();
410 }
411 
413 {
414  m_settings.m_fcPos = (BladeRF2InputSettings::fcPos_t) (index < 0 ? 0 : index > 2 ? 2 : index);
416  sendSettings();
417 }
418 
420 {
421  const std::vector<BladeRF2Input::GainMode>& modes = m_sampleSource->getGainModes();
422  unsigned int uindex = index < 0 ? 0 : (unsigned int) index;
423 
424  if (uindex < modes.size())
425  {
426  BladeRF2Input::GainMode mode = modes[index];
427 
428  if (m_settings.m_gainMode != mode.m_value)
429  {
430  if (mode.m_value == BLADERF_GAIN_MANUAL)
431  {
432  m_settings.m_globalGain = ui->gain->value();
433  ui->gain->setEnabled(true);
434  } else {
435  ui->gain->setEnabled(false);
436  }
437  }
438 
440  sendSettings();
441  }
442 }
443 
445 {
446  ui->gainText->setText(tr("%1 dB").arg(value));
447  m_settings.m_globalGain = value;
448  sendSettings();
449 }
450 
452 {
453  m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive();
454  m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency();
455  qDebug("BladeRF2InputGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off");
457  setCenterFrequencySetting(ui->centerFrequency->getValueNew());
458  sendSettings();
459 }
460 
462 {
463  if (m_doApplySettings)
464  {
467  }
468 }
469 
471 {
472  if (checked) {
473  ui->record->setStyleSheet("QToolButton { background-color : red; }");
474  } else {
475  ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
476  }
477 
480 }
481 
483 {
484  m_sampleRateMode = checked;
486 }
487 
489 {
490  if (m_doApplySettings)
491  {
492  qDebug() << "BladeRF2InputGui::updateHardware";
495  m_forceSettings = false;
496  m_updateTimer.stop();
497  }
498 }
499 
501 {
502  m_doApplySettings = !block;
503 }
504 
506 {
507  int state = m_deviceUISet->m_deviceAPI->state();
508 
509  if(m_lastEngineState != state)
510  {
511  switch(state)
512  {
514  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
515  break;
516  case DeviceAPI::StIdle:
517  ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
518  break;
520  ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
521  break;
522  case DeviceAPI::StError:
523  ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
524  QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
525  break;
526  default:
527  break;
528  }
529 
530  m_lastEngineState = state;
531  }
532 }
533 
535 {
536  BasicDeviceSettingsDialog dialog(this);
541 
542  dialog.move(p);
543  dialog.exec();
544 
549 
550  sendSettings();
551 }
void on_decim_currentIndexChanged(int index)
QByteArray serialize() const
void on_record_toggled(bool checked)
Message * pop()
Pop message from queue.
const QString & getReverseAPIAddress() const
void on_gainMode_currentIndexChanged(int index)
void on_bandwidth_changed(quint64 value)
static qint32 calculateFrequencyShift(int log2Decim, fcPos_t fcPos, quint32 devSampleRate, FrequencyShiftScheme frequencyShiftScheme)
void updateSampleRateAndFrequency()
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
Definition: glspectrum.cpp:211
void blockApplySettings(bool block)
virtual qint64 getCenterFrequency() const
virtual void setMessageQueueToGUI(MessageQueue *queue)
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)
Ui::Bladerf2InputGui * ui
MessageQueue * getInputMessageQueue()
const std::vector< GainMode > & getGainModes()
DeviceUISet * m_deviceUISet
void on_sampleRateMode_toggled(bool checked)
void getFrequencyRange(uint64_t &min, uint64_t &max, int &step)
void getGlobalGainRange(int &min, int &max, int &step)
void setCenterFrequencySetting(uint64_t kHzValue)
virtual bool deserialize(const QByteArray &data)
QString errorMessage()
Last error message from the device engine.
Definition: deviceapi.cpp:290
void on_startStop_toggled(bool checked)
__int64 int64_t
Definition: rtptypes_win.h:47
virtual ~BladeRF2InputGui()
void getBandwidthRange(int &min, int &max, int &step)
static MsgStartStop * create(bool startStop)
Definition: bladerf2input.h:90
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
BladeRF2InputSettings m_settings
virtual QByteArray serialize() const
virtual void resetToDefaults()
virtual void setCenterFrequency(qint64 centerFrequency)
BladeRF2InputGui(DeviceUISet *deviceUISet, QWidget *parent=0)
static bool match(const Message *message)
Definition: message.cpp:45
quint64 m_deviceCenterFrequency
Center frequency in device.
void on_fcPos_currentIndexChanged(int index)
int int32_t
Definition: rtptypes_win.h:45
QString getName() const
void on_gain_valueChanged(int value)
static MsgFileRecord * create(bool startStop)
Definition: bladerf2input.h:71
virtual bool handleMessage(const Message &message)
virtual void destroy()
int getSampleRate() const
Definition: dspcommands.h:328
void getSampleRateRange(int &min, int &max, int &step)
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_dcOffset_toggled(bool checked)
engine is running
Definition: deviceapi.h:56
void on_iqImbalance_toggled(bool checked)
static MsgConfigureBladeRF2 * create(const BladeRF2InputSettings &settings, bool force)
Definition: bladerf2input.h:49
void on_LOppm_valueChanged(int value)
void on_sampleRate_changed(quint64 value)
BladeRF2Input * m_sampleSource
const BladeRF2InputSettings & getSettings() const
Definition: bladerf2input.h:46
void on_centerFrequency_changed(quint64 value)
engine is in error
Definition: deviceapi.h:57
T max(const T &x, const T &y)
Definition: framework.h:446
bool deserialize(const QByteArray &data)
void on_biasTee_toggled(bool checked)
MessageQueue m_inputMessageQueue
T min(const T &x, const T &y)
Definition: framework.h:440
bool m_sampleRateMode
true: device, false: base band sample rate update mode
unsigned __int64 uint64_t
Definition: rtptypes_win.h:48