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.
amdemodgui.cpp
Go to the documentation of this file.
1 // Copyright (C) 2016 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 <QDockWidget>
19 #include <QMainWindow>
20 #include <QDebug>
21 
22 #include "amdemodgui.h"
23 #include "amdemodssbdialog.h"
24 
25 #include "device/deviceuiset.h"
26 #include "dsp/downchannelizer.h"
27 #include "dsp/dspengine.h"
29 #include "ui_amdemodgui.h"
30 #include "plugin/pluginapi.h"
31 #include "util/simpleserializer.h"
32 #include "util/db.h"
35 #include "dsp/dspengine.h"
36 #include "mainwindow.h"
37 #include "gui/crightclickenabler.h"
38 #include "gui/audioselectdialog.h"
39 
40 #include "amdemod.h"
41 
43 {
44  AMDemodGUI* gui = new AMDemodGUI(pluginAPI, deviceUISet, rxChannel);
45  return gui;
46 }
47 
49 {
50  delete this;
51 }
52 
53 void AMDemodGUI::setName(const QString& name)
54 {
55  setObjectName(name);
56 }
57 
58 QString AMDemodGUI::getName() const
59 {
60  return objectName();
61 }
62 
65 }
66 
67 void AMDemodGUI::setCenterFrequency(qint64 centerFrequency)
68 {
69  m_channelMarker.setCenterFrequency(centerFrequency);
70  applySettings();
71 }
72 
74 {
77  applySettings(true);
78 }
79 
80 QByteArray AMDemodGUI::serialize() const
81 {
82  return m_settings.serialize();
83 }
84 
85 bool AMDemodGUI::deserialize(const QByteArray& data)
86 {
87  if(m_settings.deserialize(data)) {
89  applySettings(true);
90  return true;
91  } else {
93  return false;
94  }
95 }
96 
97 bool AMDemodGUI::handleMessage(const Message& message)
98 {
100  {
101  qDebug("AMDemodGUI::handleMessage: AMDemod::MsgConfigureAMDemod");
103  m_settings = cfg.getSettings();
104  blockApplySettings(true);
105  displaySettings();
106  blockApplySettings(false);
107  return true;
108  }
109 
110  return false;
111 }
112 
114 {
115  Message* message;
116 
117  while ((message = getInputMessageQueue()->pop()) != 0)
118  {
119  if (handleMessage(*message))
120  {
121  delete message;
122  }
123  }
124 }
125 
127 {
128  ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
130  applySettings();
131 }
132 
134 {
136 }
137 
139 {
142  applySettings();
143 }
144 
145 void AMDemodGUI::on_pll_toggled(bool checked)
146 {
147  if (!checked)
148  {
149  ui->pll->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
150  ui->pll->setToolTip(tr("PLL for synchronous AM"));
151  }
152 
153  m_settings.m_pll = checked;
154  applySettings();
155 }
156 
157 void AMDemodGUI::on_ssb_toggled(bool checked)
158 {
160  applySettings();
161 }
162 
164 {
165  m_settings.m_bandpassEnable = checked;
166  applySettings();
167 }
168 
170 {
171  ui->rfBWText->setText(QString("%1 kHz").arg(value / 10.0, 0, 'f', 1));
172  m_channelMarker.setBandwidth(value * 100);
173  m_settings.m_rfBandwidth = value * 100;
174  applySettings();
175 }
176 
178 {
179  ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
180  m_settings.m_volume = value / 10.0;
181  applySettings();
182 }
183 
185 {
186  ui->squelchText->setText(QString("%1 dB").arg(value));
187  m_settings.m_squelch = value;
188  applySettings();
189 }
190 
192 {
193  m_settings.m_audioMute = checked;
194  applySettings();
195 }
196 
197 void AMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
198 {
199  (void) widget;
200  (void) rollDown;
201  /*
202  if((widget == ui->spectrumContainer) && (m_nfmDemod != NULL))
203  m_nfmDemod->setSpectrum(m_threadedSampleSink->getMessageQueue(), rollDown);
204  */
205 }
206 
207 void AMDemodGUI::onMenuDialogCalled(const QPoint &p)
208 {
210  {
217  dialog.move(p);
218  dialog.exec();
219 
228 
229  setWindowTitle(m_settings.m_title);
231 
232  applySettings();
233  }
235  {
236  DeviceStreamSelectionDialog dialog(this);
239  dialog.move(p);
240  dialog.exec();
241 
245  applySettings();
246  }
247 
249 }
250 
251 AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) :
252  RollupWidget(parent),
253  ui(new Ui::AMDemodGUI),
254  m_pluginAPI(pluginAPI),
255  m_deviceUISet(deviceUISet),
256  m_channelMarker(this),
257  m_doApplySettings(true),
258  m_squelchOpen(false),
259  m_samUSB(true),
260  m_tickCount(0)
261 {
262  ui->setupUi(this);
263  setAttribute(Qt::WA_DeleteOnClose, true);
264  connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
265  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
266 
267  m_amDemod = reinterpret_cast<AMDemod*>(rxChannel); //new AMDemod(m_deviceUISet->m_deviceSourceAPI);
269 
270  connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms
271 
272  CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute);
273  connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect()));
274 
275  CRightClickEnabler *samSidebandRightClickEnabler = new CRightClickEnabler(ui->ssb);
276  connect(samSidebandRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(samSSBSelect()));
277 
278  ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
279  ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
280  ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
281  ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue);
282 
283  m_channelMarker.blockSignals(true);
284  m_channelMarker.setColor(Qt::yellow);
287  m_channelMarker.setTitle("AM Demodulator");
288  m_channelMarker.blockSignals(false);
289  m_channelMarker.setVisible(true); // activate signal on the last setting only
290 
293 
297 
298  connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
299  connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
300  connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
301 
302  m_iconDSBUSB.addPixmap(QPixmap("://dsb.png"), QIcon::Normal, QIcon::Off);
303  m_iconDSBUSB.addPixmap(QPixmap("://usb.png"), QIcon::Normal, QIcon::On);
304  m_iconDSBLSB.addPixmap(QPixmap("://dsb.png"), QIcon::Normal, QIcon::Off);
305  m_iconDSBLSB.addPixmap(QPixmap("://lsb.png"), QIcon::Normal, QIcon::On);
306 
307  displaySettings();
308  applySettings(true);
309 }
310 
312 {
314  delete m_amDemod; // TODO: check this: when the GUI closes it has to delete the demodulator
315  delete ui;
316 }
317 
319 {
320  m_doApplySettings = !block;
321 }
322 
324 {
325  if (m_doApplySettings)
326  {
329  m_amDemod->getInputMessageQueue()->push(channelConfigMsg);
330 
331 
333  m_amDemod->getInputMessageQueue()->push(message);
334  }
335 }
336 
338 {
339  m_channelMarker.blockSignals(true);
343  m_channelMarker.blockSignals(false);
344  m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
345 
347  setWindowTitle(m_channelMarker.getTitle());
348 
349  blockApplySettings(true);
350 
351  ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
352 
353  int displayValue = m_settings.m_rfBandwidth/100.0;
354  ui->rfBW->setValue(displayValue);
355  ui->rfBWText->setText(QString("%1 kHz").arg(displayValue / 10.0, 0, 'f', 1));
356 
357  ui->volume->setValue(m_settings.m_volume * 10.0);
358  ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1));
359 
360  ui->squelch->setValue(m_settings.m_squelch);
361  ui->squelchText->setText(QString("%1 dB").arg(m_settings.m_squelch));
362 
363  ui->audioMute->setChecked(m_settings.m_audioMute);
364  ui->bandpassEnable->setChecked(m_settings.m_bandpassEnable);
365  ui->pll->setChecked(m_settings.m_pll);
366 
367  qDebug() << "AMDemodGUI::displaySettings:"
368  << " m_pll: " << m_settings.m_pll
369  << " m_syncAMOperation: " << m_settings.m_syncAMOperation;
370 
371  if (m_settings.m_pll)
372  {
374  {
375  m_samUSB = false;
376  ui->ssb->setChecked(true);
377  ui->ssb->setIcon(m_iconDSBLSB);
378  }
380  {
381  m_samUSB = true;
382  ui->ssb->setChecked(true);
383  ui->ssb->setIcon(m_iconDSBUSB);
384  }
385  else
386  {
387  ui->ssb->setChecked(false);
388  }
389  }
390  else
391  {
392  ui->ssb->setChecked(false);
393  ui->ssb->setIcon(m_iconDSBUSB);
394  }
395 
397 
398  blockApplySettings(false);
399 }
400 
402 {
405  } else {
406  setStreamIndicator("S"); // single channel indicator
407  }
408 }
409 
411 {
413 }
414 
416 {
418 }
419 
421 {
422  qDebug("AMDemodGUI::audioSelect");
424  audioSelect.exec();
425 
426  if (audioSelect.m_selected)
427  {
429  applySettings();
430  }
431 }
432 
434 {
435  AMDemodSSBDialog ssbSelect(m_samUSB);
436  ssbSelect.exec();
437 
438  ui->ssb->setIcon(ssbSelect.isUsb() ? m_iconDSBUSB : m_iconDSBLSB);
439 
440  if (ssbSelect.isUsb() != m_samUSB)
441  {
442  qDebug("AMDemodGUI::samSSBSelect: %s", ssbSelect.isUsb() ? "usb" : "lsb");
443  m_samUSB = ssbSelect.isUsb();
444 
446  {
448  applySettings();
449  }
450  }
451 }
452 
454 {
455  double magsqAvg, magsqPeak;
456  int nbMagsqSamples;
457  m_amDemod->getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
458  double powDbAvg = CalcDb::dbPower(magsqAvg);
459  double powDbPeak = CalcDb::dbPower(magsqPeak);
460 
461  ui->channelPowerMeter->levelChanged(
462  (100.0f + powDbAvg) / 100.0f,
463  (100.0f + powDbPeak) / 100.0f,
464  nbMagsqSamples);
465 
466  if (m_tickCount % 4 == 0) {
467  ui->channelPower->setText(QString::number(powDbAvg, 'f', 1));
468  }
469 
470  bool squelchOpen = m_amDemod->getSquelchOpen();
471 
472  if (squelchOpen != m_squelchOpen)
473  {
474  m_squelchOpen = squelchOpen;
475 
476  if (m_squelchOpen) {
477  ui->audioMute->setStyleSheet("QToolButton { background-color : green; }");
478  } else {
479  ui->audioMute->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
480  }
481  }
482 
483  if (m_settings.m_pll)
484  {
485  if (m_amDemod->getPllLocked()) {
486  ui->pll->setStyleSheet("QToolButton { background-color : green; }");
487  } else {
488  ui->pll->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
489  }
490 
491  int freq = (m_amDemod->getPllFrequency() * m_amDemod->getAudioSampleRate()) / (2.0*M_PI);
492  ui->pll->setToolTip(tr("PLL for synchronous AM. Freq = %1 Hz").arg(freq));
493  }
494 
495  m_tickCount++;
496 }
497 
AMDemodSettings m_settings
Definition: amdemodgui.h:50
static MainWindow * getInstance()
Definition: mainwindow.h:73
const QString & getReverseAPIAddress() const
bool deserialize(const QByteArray &data)
Definition: amdemodgui.cpp:85
int getCenterFrequency() const
Definition: channelmarker.h:42
void samSSBSelect()
Definition: amdemodgui.cpp:433
void push(Message *message, bool emitSignal=true)
Push message onto queue.
uint32_t getNumberOfDeviceStreams() const
Definition: amdemod.cpp:111
static double dbPower(double magsq, double floor=1e-12)
Definition: db.cpp:22
virtual void destroy()
Definition: amdemodgui.cpp:48
void getMagSqLevels(double &avg, double &peak, int &nbSamples)
Definition: amdemod.h:143
void on_squelch_valueChanged(int value)
Definition: amdemodgui.cpp:184
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
QByteArray serialize() const
Definition: amdemodgui.cpp:80
AMDemodGUI(PluginAPI *pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget *parent=0)
Definition: amdemodgui.cpp:251
static MsgConfigureAMDemod * create(const AMDemodSettings &settings, bool force)
Definition: amdemod.h:58
void displayStreamIndex()
Definition: amdemodgui.cpp:401
void setName(const QString &name)
Definition: amdemodgui.cpp:53
void audioSelect()
Definition: amdemodgui.cpp:420
DeviceUISet * m_deviceUISet
Definition: amdemodgui.h:48
void on_audioMute_toggled(bool checked)
Definition: amdemodgui.cpp:191
uint32_t m_tickCount
Definition: amdemodgui.h:56
void setReverseAPIChannelIndex(uint16_t channelIndex)
void handleInputMessages()
Definition: amdemodgui.cpp:113
void resetContextMenuType()
Definition: rollupwidget.h:50
void addChannelMarker(ChannelMarker *channelMarker)
Add channel marker to spectrum.
Definition: deviceuiset.cpp:72
uint16_t m_reverseAPIChannelIndex
#define M_PI
Definition: rdsdemod.cpp:27
bool m_squelchOpen
Definition: amdemodgui.h:54
bool m_samUSB
Definition: amdemodgui.h:55
virtual qint64 getCenterFrequency() const
Definition: amdemodgui.cpp:63
ContextMenuType m_contextMenuType
Definition: rollupwidget.h:33
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
void leaveEvent(QEvent *)
Definition: amdemodgui.cpp:410
Real getPllFrequency() const
Definition: amdemod.h:141
int m_streamIndex
MIMO channel. Not relevant when connected to SI (single Rx).
AMDemod * m_amDemod
Definition: amdemodgui.h:53
void displaySettings()
Definition: amdemodgui.cpp:337
void setStreamIndex(int streamIndex)
Definition: channelmarker.h:77
uint16_t m_reverseAPIDeviceIndex
void onMenuDialogCalled(const QPoint &p)
Definition: amdemodgui.cpp:207
virtual void setMessageQueueToGUI(MessageQueue *queue)
virtual ~AMDemodGUI()
Definition: amdemodgui.cpp:311
static DSPEngine * instance()
Definition: dspengine.cpp:51
void setTitleColor(const QColor &c)
virtual void setCenterFrequency(qint64 centerFrequency)
Definition: amdemodgui.cpp:67
const AMDemodSettings & getSettings() const
Definition: amdemod.h:55
void setHighlighted(bool highlighted)
void channelMarkerHighlightedByCursor()
Definition: amdemodgui.cpp:133
void on_rfBW_valueChanged(int value)
Definition: amdemodgui.cpp:169
void on_volume_valueChanged(int value)
Definition: amdemodgui.cpp:177
bool isUsb() const
void registerRxChannelInstance(const QString &channelName, PluginInstanceGUI *pluginGUI)
Definition: deviceuiset.cpp:82
QByteArray serialize() const
virtual MessageQueue * getInputMessageQueue()
Definition: amdemodgui.h:38
void addRollupWidget(QWidget *widget)
Add rollup widget to channel window.
Definition: deviceuiset.cpp:77
void removeRxChannelInstance(PluginInstanceGUI *pluginGUI)
Definition: deviceuiset.cpp:94
SyncAMOperation m_syncAMOperation
QString m_audioDeviceName
const QString & getTitle() const
Definition: channelmarker.h:38
static bool match(const Message *message)
Definition: message.cpp:45
bool getHighlighted() const
Definition: channelmarker.h:61
bool deserialize(const QByteArray &data)
ChannelMarker m_channelMarker
Definition: amdemodgui.h:49
void enterEvent(QEvent *)
Definition: amdemodgui.cpp:415
void blockApplySettings(bool block)
Definition: amdemodgui.cpp:318
void on_deltaFrequency_changed(qint64 value)
Definition: amdemodgui.cpp:138
void setChannelMarker(Serializable *channelMarker)
void setStreamIndicator(const QString &indicator)
static MsgConfigureChannelizer * create(int sampleRate, int centerFrequency)
Definition: amdemod.h:81
uint32_t getAudioSampleRate() const
Definition: amdemod.h:137
void on_ssb_toggled(bool checked)
Definition: amdemodgui.cpp:157
void setReverseAPIAddress(const QString &address)
void onWidgetRolled(QWidget *widget, bool rollDown)
Definition: amdemodgui.cpp:197
void setHighlighted(bool highlighted)
void resetToDefaults()
Definition: amdemodgui.cpp:73
void setColor(const QColor &color)
PluginAPI * m_pluginAPI
Definition: amdemodgui.h:47
QString m_reverseAPIAddress
void on_bandpassEnable_toggled(bool checked)
Definition: amdemodgui.cpp:163
Ui::AMDemodGUI * ui
Definition: amdemodgui.h:46
bool m_doApplySettings
Definition: amdemodgui.h:51
void tick()
Definition: amdemodgui.cpp:453
bool getSquelchOpen() const
Definition: amdemod.h:139
uint16_t m_reverseAPIPort
void setVisible(bool visible)
void channelMarkerChangedByCursor()
Definition: amdemodgui.cpp:126
QString getName() const
Definition: amdemodgui.cpp:58
qint32 m_inputFrequencyOffset
void setBandwidth(int bandwidth)
const QColor & getColor() const
Definition: channelmarker.h:64
void applySettings(bool force=false)
Definition: amdemodgui.cpp:323
void setTitle(const QString &title)
void setCenterFrequency(int centerFrequency)
bool getPllLocked() const
Definition: amdemod.h:140
static const QString m_channelIdURI
Definition: amdemod.h:163
void on_pll_toggled(bool checked)
Definition: amdemodgui.cpp:145
QIcon m_iconDSBUSB
Definition: amdemodgui.h:59
void widgetRolled(QWidget *widget, bool rollDown)
void setUseReverseAPI(bool useReverseAPI)
DSPDeviceMIMOEngine * m_deviceMIMOEngine
Definition: deviceuiset.h:51
virtual bool handleMessage(const Message &message)
Definition: amdemodgui.cpp:97
static AMDemodGUI * create(PluginAPI *pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
Definition: amdemodgui.cpp:42
QIcon m_iconDSBLSB
Definition: amdemodgui.h:60