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.
airspyhfgui.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 <libairspyhf/airspyhf.h>
22 
23 #include <device/deviceapi.h>
24 #include "device/deviceuiset.h"
25 #include <dsp/filerecord.h>
26 
27 #include "ui_airspyhfgui.h"
28 #include "gui/colormapper.h"
29 #include "gui/glspectrum.h"
30 #include "gui/crightclickenabler.h"
32 #include "dsp/dspengine.h"
33 #include "dsp/dspcommands.h"
34 #include "airspyhfgui.h"
35 
36 AirspyHFGui::AirspyHFGui(DeviceUISet *deviceUISet, QWidget* parent) :
37  QWidget(parent),
38  ui(new Ui::AirspyHFGui),
39  m_deviceUISet(deviceUISet),
40  m_doApplySettings(true),
41  m_forceSettings(true),
42  m_settings(),
43  m_sampleSource(0),
44  m_lastEngineState(DeviceAPI::StNotStarted)
45 {
47 
48  ui->setupUi(this);
49  ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
51 
52  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
53  connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
54  m_statusTimer.start(500);
55 
56  CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
57  connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
58 
60 
61  m_rates = ((AirspyHFInput*) m_sampleSource)->getSampleRates();
63  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
65 
66  sendSettings();
67 }
68 
70 {
71  delete ui;
72 }
73 
75 {
76  delete this;
77 }
78 
79 void AirspyHFGui::setName(const QString& name)
80 {
81  setObjectName(name);
82 }
83 
84 QString AirspyHFGui::getName() const
85 {
86  return objectName();
87 }
88 
90 {
93  sendSettings();
94 }
95 
97 {
99 }
100 
101 void AirspyHFGui::setCenterFrequency(qint64 centerFrequency)
102 {
103  m_settings.m_centerFrequency = centerFrequency;
104  displaySettings();
105  sendSettings();
106 }
107 
108 QByteArray AirspyHFGui::serialize() const
109 {
110  return m_settings.serialize();
111 }
112 
113 bool AirspyHFGui::deserialize(const QByteArray& data)
114 {
115  if(m_settings.deserialize(data)) {
116  displaySettings();
117  m_forceSettings = true;
118  sendSettings();
119  return true;
120  } else {
121  resetToDefaults();
122  return false;
123  }
124 }
125 
127 {
129  {
131  m_settings = cfg.getSettings();
132  blockApplySettings(true);
133  displaySettings();
134  blockApplySettings(false);
135  return true;
136  }
137  else if (AirspyHFInput::MsgStartStop::match(message))
138  {
140  blockApplySettings(true);
141  ui->startStop->setChecked(notif.getStartStop());
142  blockApplySettings(false);
143 
144  return true;
145  }
146  else
147  {
148  return false;
149  }
150 }
151 
153 {
154  Message* message;
155 
156  while ((message = m_inputMessageQueue.pop()) != 0)
157  {
158  qDebug("AirspyHFGui::handleInputMessages: message: %s", message->getIdentifier());
159 
160  if (DSPSignalNotification::match(*message))
161  {
162  DSPSignalNotification* notif = (DSPSignalNotification*) message;
163  m_sampleRate = notif->getSampleRate();
165  qDebug("AirspyGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
167 
168  delete message;
169  }
170  else
171  {
172  if (handleMessage(*message))
173  {
174  delete message;
175  }
176  }
177  }
178 }
179 
181 {
184  ui->deviceRateText->setText(tr("%1k").arg((float)m_sampleRate / 1000));
185 }
186 
188 {
189  // values in kHz
190  qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0;
191 
192  qint64 minLimit;
193  qint64 maxLimit;
194 
195  switch(m_settings.m_bandIndex)
196  {
197  case 1:
198  minLimit = AirspyHFInput::loLowLimitFreqVHF/1000 + deltaFrequency;
199  maxLimit = AirspyHFInput::loHighLimitFreqVHF/1000 + deltaFrequency;
200  break;
201  case 0:
202  default:
203  minLimit = AirspyHFInput::loLowLimitFreqHF/1000 + deltaFrequency;
204  maxLimit = AirspyHFInput::loHighLimitFreqHF/1000 + deltaFrequency;
205  break;
206  }
207 
208  minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit;
209  maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit;
210 
211  qDebug("AirspyHFGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit);
212 
213  ui->centerFrequency->setValueRange(7, minLimit, maxLimit);
214 }
215 
217 {
218  blockApplySettings(true);
219  ui->band->blockSignals(true);
220  m_settings.m_bandIndex = m_settings.m_centerFrequency <= 31000000UL ? 0 : 1; // override
221  ui->band->setCurrentIndex(m_settings.m_bandIndex);
223  ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency);
224  ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode);
225  ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
226  ui->LOppm->setValue(m_settings.m_LOppmTenths);
227  ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1)));
228  ui->sampleRate->setCurrentIndex(m_settings.m_devSampleRateIndex);
229  ui->decim->setCurrentIndex(m_settings.m_log2Decim);
230  ui->band->blockSignals(false);
231  ui->dsp->setChecked(m_settings.m_useDSP);
232  ui->lna->setChecked(m_settings.m_useLNA);
233  ui->att->setCurrentIndex(m_settings.m_attenuatorSteps);
234  ui->dcOffset->setChecked(m_settings.m_dcBlock);
235  ui->iqImbalance->setChecked(m_settings.m_iqCorrection);
236  displayAGC();
237  blockApplySettings(false);
238 }
239 
241 {
242  unsigned int savedIndex = m_settings.m_devSampleRateIndex;
243  ui->sampleRate->blockSignals(true);
244 
245  if (m_rates.size() > 0)
246  {
247  ui->sampleRate->clear();
248 
249  for (unsigned int i = 0; i < m_rates.size(); i++)
250  {
251  int sampleRate = m_rates[i]/1000;
252  ui->sampleRate->addItem(QString("%1").arg(QString("%1").arg(sampleRate, 5, 10, QChar(' '))));
253  }
254  }
255 
256  ui->sampleRate->blockSignals(false);
257 
258  if (savedIndex < m_rates.size())
259  {
260  ui->sampleRate->setCurrentIndex(savedIndex);
261  }
262  else
263  {
264  ui->sampleRate->setCurrentIndex((int) m_rates.size()-1);
265  }
266 }
267 
269 {
270  if (m_settings.m_useAGC)
271  {
272  if (m_settings.m_agcHigh) {
273  ui->agc->setCurrentIndex(2);
274  } else {
275  ui->agc->setCurrentIndex(1);
276  }
277  }
278  else
279  {
280  ui->agc->setCurrentIndex(0);
281  }
282 }
283 
285 {
286  if(!m_updateTimer.isActive())
287  m_updateTimer.start(100);
288 }
289 
291 {
292  m_settings.m_centerFrequency = value * 1000;
293  sendSettings();
294 }
295 
297 {
298  m_settings.m_LOppmTenths = value;
299  ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1)));
300  sendSettings();
301 }
302 
304 {
305  ui->LOppm->setValue(0);
306 }
307 
309 {
311  sendSettings();
312 }
313 
315 {
316  if ((index < 0) || (index > 6))
317  return;
318  m_settings.m_log2Decim = index;
319  sendSettings();
320 }
321 
323 {
324  if (m_doApplySettings)
325  {
328  }
329 }
330 
332 {
333  if (checked) {
334  ui->record->setStyleSheet("QToolButton { background-color : red; }");
335  } else {
336  ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
337  }
338 
341 }
342 
344 {
345  m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive();
346  m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency();
347  qDebug("AirspyHFGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off");
349  m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000;
350  sendSettings();
351 }
352 
354 {
355  if ((index < 0) || (index > 1)) {
356  return;
357  }
358 
359  m_settings.m_bandIndex = index;
361  qDebug("AirspyHFGui::on_band_currentIndexChanged: freq: %llu", ui->centerFrequency->getValueNew() * 1000);
362  m_settings.m_centerFrequency = ui->centerFrequency->getValueNew() * 1000;
363  sendSettings();
364 }
365 
366 void AirspyHFGui::on_dsp_toggled(bool checked)
367 {
368  m_settings.m_useDSP = checked;
369  sendSettings();
370 }
371 
372 void AirspyHFGui::on_lna_toggled(bool checked)
373 {
374  m_settings.m_useLNA = checked;
375  sendSettings();
376 }
377 
379 {
380  if (index == 0)
381  {
382  m_settings.m_useAGC = false;
383  sendSettings();
384  }
385  else if (index <= 2)
386  {
387  m_settings.m_useAGC = true;
388 
389  if (index == 1) {
390  m_settings.m_agcHigh = false;
391  } else {
392  m_settings.m_agcHigh = true;
393  }
394 
395  sendSettings();
396  }
397 }
398 
400 {
401  if ((index >= 0) && (index <= 8))
402  {
404  sendSettings();
405  }
406 }
407 
409 {
410  m_settings.m_dcBlock = checked;
411  sendSettings();
412 }
413 
415 {
416  m_settings.m_iqCorrection = checked;
417  sendSettings();
418 }
419 
421 {
422  qDebug() << "AirspyHFGui::updateHardware";
425  m_forceSettings = false;
426  m_updateTimer.stop();
427 }
428 
430 {
431  int state = m_deviceUISet->m_deviceAPI->state();
432 
433  if(m_lastEngineState != state)
434  {
435  switch(state)
436  {
438  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
439  break;
440  case DeviceAPI::StIdle:
441  ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
442  break;
444  ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
445  break;
446  case DeviceAPI::StError:
447  ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
448  QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
449  break;
450  default:
451  break;
452  }
453 
454  m_lastEngineState = state;
455  }
456 }
457 
458 uint32_t AirspyHFGui::getDevSampleRate(unsigned int rate_index)
459 {
460  if (rate_index < m_rates.size())
461  {
462  return m_rates[rate_index];
463  }
464  else
465  {
466  return m_rates[0];
467  }
468 }
469 
471 {
472  for (unsigned int i=0; i < m_rates.size(); i++)
473  {
474  if (sampeRate == m_rates[i])
475  {
476  return i;
477  }
478  }
479 
480  return -1;
481 }
482 
484 {
485  BasicDeviceSettingsDialog dialog(this);
490 
491  dialog.move(p);
492  dialog.exec();
493 
498 
499  sendSettings();
500 }
bool m_doApplySettings
Definition: airspyhfgui.h:61
static const qint64 loHighLimitFreqVHF
static MsgConfigureAirspyHF * create(const AirspyHFSettings &settings, bool force)
Definition: airspyhfinput.h:46
bool deserialize(const QByteArray &data)
void displayAGC()
void sendSettings()
void displaySettings()
void on_resetLOppm_clicked()
Message * pop()
Pop message from queue.
const QString & getReverseAPIAddress() const
static MsgStartStop * create(bool startStop)
Definition: airspyhfinput.h:87
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
Definition: glspectrum.cpp:211
static const qint64 loLowLimitFreqVHF
void on_transverter_clicked()
void on_agc_currentIndexChanged(int index)
void displaySampleRates()
DeviceSampleSource * getSampleSource()
Return pointer to the device sample source (single Rx) or nullptr.
Definition: deviceapi.cpp:213
bool m_forceSettings
Definition: airspyhfgui.h:62
void setUseReverseAPI(bool useReverseAPI)
void blockApplySettings(bool block)
Definition: airspyhfgui.h:73
MessageQueue * getInputMessageQueue()
QTimer m_updateTimer
Definition: airspyhfgui.h:64
uint16_t m_reverseAPIDeviceIndex
bool deserialize(const QByteArray &data)
void on_lna_toggled(bool checked)
uint16_t m_reverseAPIPort
QString errorMessage()
Last error message from the device engine.
Definition: deviceapi.cpp:290
QTimer m_statusTimer
Definition: airspyhfgui.h:65
void on_startStop_toggled(bool checked)
void on_sampleRate_currentIndexChanged(int index)
void handleInputMessages()
int getDevSampleRateIndex(uint32_t sampleRate)
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
uint32_t getDevSampleRate(unsigned int index)
engine is before initialization
Definition: deviceapi.h:53
virtual qint64 getCenterFrequency() const
Definition: airspyhfgui.cpp:96
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
void updateStatus()
DeviceAPI * m_deviceAPI
Definition: deviceuiset.h:48
void on_centerFrequency_changed(quint64 value)
engine is idle
Definition: deviceapi.h:54
static MsgFileRecord * create(bool startStop)
Definition: airspyhfinput.h:68
void updateHardware()
AirspyHFSettings m_settings
Definition: airspyhfgui.h:63
void resetToDefaults()
Definition: airspyhfgui.cpp:89
qint64 m_transverterDeltaFrequency
DeviceUISet * m_deviceUISet
Definition: airspyhfgui.h:60
void on_LOppm_valueChanged(int value)
int32_t i
Definition: decimators.h:244
void on_iqImbalance_toggled(bool checked)
static bool match(const Message *message)
Definition: message.cpp:45
QString m_reverseAPIAddress
virtual void setCenterFrequency(qint64 centerFrequency)
static const qint64 loLowLimitFreqHF
void on_dcOffset_toggled(bool checked)
quint32 m_devSampleRateIndex
MessageQueue m_inputMessageQueue
Definition: airspyhfgui.h:71
QString getName() const
Definition: airspyhfgui.cpp:84
int m_sampleRate
Definition: airspyhfgui.h:68
QByteArray serialize() const
void on_att_currentIndexChanged(int index)
static const qint64 loHighLimitFreqHF
int m_lastEngineState
Definition: airspyhfgui.h:70
AirspyHFGui(DeviceUISet *deviceUISet, QWidget *parent=0)
Definition: airspyhfgui.cpp:36
void updateSampleRateAndFrequency()
std::vector< uint32_t > m_rates
Definition: airspyhfgui.h:66
void on_band_currentIndexChanged(int index)
virtual void destroy()
Definition: airspyhfgui.cpp:74
quint64 m_deviceCenterFrequency
Center frequency in device.
Definition: airspyhfgui.h:69
void updateFrequencyLimits()
int getSampleRate() const
Definition: dspcommands.h:328
void on_record_toggled(bool checked)
QByteArray serialize() const
void setCenterFrequency(qint64 frequency)
Definition: glspectrum.cpp:175
virtual const char * getIdentifier() const
Definition: message.cpp:35
void setReverseAPIAddress(const QString &address)
void on_dsp_toggled(bool checked)
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
void openDeviceSettingsDialog(const QPoint &p)
virtual void setMessageQueueToGUI(MessageQueue *queue)=0
engine is running
Definition: deviceapi.h:56
void setName(const QString &name)
Definition: airspyhfgui.cpp:79
DeviceSampleSource * m_sampleSource
Definition: airspyhfgui.h:67
void on_decim_currentIndexChanged(int index)
const AirspyHFSettings & getSettings() const
Definition: airspyhfinput.h:43
virtual ~AirspyHFGui()
Definition: airspyhfgui.cpp:69
engine is in error
Definition: deviceapi.h:57
Ui::AirspyHFGui * ui
Definition: airspyhfgui.h:58
virtual bool handleMessage(const Message &message)