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.
bfmdemodgui.cpp
Go to the documentation of this file.
1 // Copyright (C) 2015 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
19 #include "bfmdemodgui.h"
20 
21 #include "device/deviceuiset.h"
22 #include <dsp/downchannelizer.h>
23 #include <QDockWidget>
24 #include <QMainWindow>
25 #include <QDebug>
26 #include "boost/format.hpp"
27 #include <sstream>
28 #include <iostream>
29 #include <iomanip>
30 
32 #include "dsp/dspengine.h"
33 #include "dsp/spectrumvis.h"
34 #include "gui/glspectrum.h"
35 #include "plugin/pluginapi.h"
36 #include "util/simpleserializer.h"
37 #include "util/db.h"
39 #include "gui/crightclickenabler.h"
40 #include "gui/audioselectdialog.h"
41 #include "mainwindow.h"
42 
43 #include "bfmdemodsettings.h"
44 #include "bfmdemod.h"
45 #include "rdstmc.h"
46 #include "ui_bfmdemodgui.h"
47 
49 {
50  BFMDemodGUI* gui = new BFMDemodGUI(pluginAPI, deviceUIset, rxChannel);
51  return gui;
52 }
53 
55 {
56  delete this;
57 }
58 
59 void BFMDemodGUI::setName(const QString& name)
60 {
61  setObjectName(name);
62 }
63 
64 QString BFMDemodGUI::getName() const
65 {
66  return objectName();
67 }
68 
70 {
72 }
73 
74 void BFMDemodGUI::setCenterFrequency(qint64 centerFrequency)
75 {
76  m_channelMarker.setCenterFrequency(centerFrequency);
77  applySettings();
78 }
79 
81 {
84 
85  blockApplySettings(true);
86  ui->g00AltFrequenciesBox->setEnabled(false);
87  ui->g14MappedFrequencies->setEnabled(false);
88  ui->g14AltFrequencies->setEnabled(false);
89  blockApplySettings(false);
90 
91  applySettings();
92 }
93 
94 QByteArray BFMDemodGUI::serialize() const
95 {
96  return m_settings.serialize();
97 }
98 
99 bool BFMDemodGUI::deserialize(const QByteArray& data)
100 {
101  if(m_settings.deserialize(data)) {
102  displaySettings();
103  applySettings(true);
104  return true;
105  } else {
106  resetToDefaults();
107  return false;
108  }
109 }
110 
112 {
114  {
116  m_rate = report.getSampleRate();
117  qDebug("BFMDemodGUI::handleMessage: MsgReportChannelSampleRateChanged: %d S/s", m_rate);
118  ui->glSpectrum->setCenterFrequency(m_rate / 4);
119  ui->glSpectrum->setSampleRate(m_rate / 2);
120  return true;
121  }
122  else if (BFMDemod::MsgConfigureBFMDemod::match(message))
123  {
124  qDebug("BFMDemodGUI::handleMessage: BFMDemod::MsgConfigureBFMDemod");
126  m_settings = cfg.getSettings();
127  blockApplySettings(true);
128  displaySettings();
129  blockApplySettings(false);
130  return true;
131  }
132  else
133  {
134  return false;
135  }
136 }
137 
139 {
140  Message* message;
141 
142  while ((message = getInputMessageQueue()->pop()) != 0)
143  {
144  if (handleMessage(*message))
145  {
146  delete message;
147  }
148  }
149 }
150 
152 {
153  ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
155  applySettings();
156 }
157 
159 {
161 }
162 
164 {
167  applySettings();
168 }
169 
171 {
172  ui->rfBWText->setText(QString("%1 kHz").arg(BFMDemodSettings::getRFBW(value) / 1000.0));
175  applySettings();
176 }
177 
179 {
180  ui->afBWText->setText(QString("%1 kHz").arg(value));
181  m_settings.m_afBandwidth = value * 1000.0;
182  applySettings();
183 }
184 
186 {
187  ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
188  m_settings.m_volume = value / 10.0;
189  applySettings();
190 }
191 
193 {
194  ui->squelchText->setText(QString("%1 dB").arg(value));
195  m_settings.m_squelch = value;
196  applySettings();
197 }
198 
200 {
201  if (!stereo)
202  {
203  ui->audioStereo->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
204  }
205 
206  m_settings.m_audioStereo = stereo;
207  applySettings();
208 }
209 
211 {
212  m_settings.m_lsbStereo = lsb;
213  applySettings();
214 }
215 
217 {
218  m_settings.m_showPilot = ui->showPilot->isChecked();
219  applySettings();
220 }
221 
223 {
224  m_settings.m_rdsActive = ui->rds->isChecked();
225  applySettings();
226 }
227 
229 {
230  (void) checked;
231  if (ui->rds->isChecked())
232  {
234 
235  ui->g14ProgServiceNames->clear();
236  ui->g14MappedFrequencies->clear();
237  ui->g14AltFrequencies->clear();
238 
239  ui->g00AltFrequenciesBox->setEnabled(false);
240  ui->g14MappedFrequencies->setEnabled(false);
241  ui->g14AltFrequencies->setEnabled(false);
242 
243  rdsUpdate(true);
244  }
245 }
246 
248 {
249  uint32_t index = _index & 0x7FFFFFF;
250 
251  if (index < m_g14ComboIndex.size())
252  {
253  unsigned int piKey = m_g14ComboIndex[index];
254  RDSParser::freqs_map_t::const_iterator mIt = m_bfmDemod->getRDSParser().m_g14_mapped_freqs.find(piKey);
255 
256  if (mIt != m_bfmDemod->getRDSParser().m_g14_mapped_freqs.end())
257  {
258  ui->g14MappedFrequencies->clear();
259  RDSParser::freqs_set_t::iterator sIt = (mIt->second).begin();
260  const RDSParser::freqs_set_t::iterator sItEnd = (mIt->second).end();
261 
262  for (; sIt != sItEnd; ++sIt)
263  {
264  std::ostringstream os;
265  os << std::fixed << std::showpoint << std::setprecision(2) << *sIt;
266  ui->g14MappedFrequencies->addItem(os.str().c_str());
267  }
268 
269  ui->g14MappedFrequencies->setEnabled(ui->g14MappedFrequencies->count() > 0);
270  }
271 
272  mIt = m_bfmDemod->getRDSParser().m_g14_alt_freqs.find(piKey);
273 
274  if (mIt != m_bfmDemod->getRDSParser().m_g14_alt_freqs.end())
275  {
276  ui->g14AltFrequencies->clear();
277  RDSParser::freqs_set_t::iterator sIt = (mIt->second).begin();
278  const RDSParser::freqs_set_t::iterator sItEnd = (mIt->second).end();
279 
280  for (; sIt != sItEnd; ++sIt)
281  {
282  std::ostringstream os;
283  os << std::fixed << std::showpoint << std::setprecision(2) << *sIt;
284  ui->g14AltFrequencies->addItem(os.str().c_str());
285  }
286 
287  ui->g14AltFrequencies->setEnabled(ui->g14AltFrequencies->count() > 0);
288  }
289  }
290 }
291 
293 {
294  (void) index;
295  qint64 f = (qint64) ((ui->g00AltFrequenciesBox->currentText()).toDouble() * 1e6);
296  changeFrequency(f);
297 }
298 
300 {
301  (void) index;
302  qint64 f = (qint64) ((ui->g14MappedFrequencies->currentText()).toDouble() * 1e6);
303  changeFrequency(f);
304 }
305 
307 {
308  (void) index;
309  qint64 f = (qint64) ((ui->g14AltFrequencies->currentText()).toDouble() * 1e6);
310  changeFrequency(f);
311 }
312 
313 void BFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
314 {
315  (void) widget;
316  (void) rollDown;
317 }
318 
319 void BFMDemodGUI::onMenuDialogCalled(const QPoint &p)
320 {
322  {
329 
330  dialog.move(p);
331  dialog.exec();
332 
341 
342  setWindowTitle(m_settings.m_title);
344 
345  applySettings();
346  }
347 
349 }
350 
351 BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) :
352  RollupWidget(parent),
353  ui(new Ui::BFMDemodGUI),
354  m_pluginAPI(pluginAPI),
355  m_deviceUISet(deviceUISet),
356  m_channelMarker(this),
357  m_rdsTimerCount(0),
358  m_rate(625000)
359 {
360  ui->setupUi(this);
361  ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
362  ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
363  ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
364  ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue);
365 
366  CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioStereo);
367  connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect()));
368 
369  setAttribute(Qt::WA_DeleteOnClose, true);
370  connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
371  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
372  connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
373 
374  m_spectrumVis = new SpectrumVis(SDR_RX_SCALEF, ui->glSpectrum);
375  m_bfmDemod = (BFMDemod*) rxChannel; //new BFMDemod(m_deviceUISet->m_deviceSourceAPI);
378 
379  ui->glSpectrum->setCenterFrequency(m_rate / 4);
380  ui->glSpectrum->setSampleRate(m_rate / 2);
381  ui->glSpectrum->setDisplayWaterfall(false);
382  ui->glSpectrum->setDisplayMaxHold(false);
383  ui->glSpectrum->setSsbSpectrum(true);
386  64, // FFT size
387  10, // overlapping %
388  0, // number of averaging samples
389  0, // no averaging
391  false); // logarithmic scale
392  connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
393 
394  m_channelMarker.blockSignals(true);
398  m_channelMarker.setTitle("Broadcast FM Demod");
399  m_channelMarker.blockSignals(false);
400  m_channelMarker.setVisible(true); // activate signal on the last setting only
401 
403 
405  m_settings.setSpectrumGUI(ui->spectrumGUI);
406 
410 
411  connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
412  connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
413 
414  ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
415 
416  ui->g00AltFrequenciesBox->setEnabled(false);
417  ui->g14MappedFrequencies->setEnabled(false);
418  ui->g14AltFrequencies->setEnabled(false);
419 
421  rdsUpdate(true);
422  displaySettings();
423  applySettings(true);
424 }
425 
427 {
429  delete m_bfmDemod; // TODO: check this: when the GUI closes it has to delete the demodulator
430  delete m_spectrumVis;
431  delete ui;
432 }
433 
435 {
436  m_doApplySettings = !block;
437 }
438 
440 {
441  if (m_doApplySettings)
442  {
446  m_bfmDemod->getInputMessageQueue()->push(msgChan);
447 
449  m_bfmDemod->getInputMessageQueue()->push(msgConfig);
450  }
451 }
452 
454 {
455  m_channelMarker.blockSignals(true);
459  m_channelMarker.blockSignals(false);
460  m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
461 
463  setWindowTitle(m_channelMarker.getTitle());
464 
465  blockApplySettings(true);
466 
467  ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
468 
470  ui->rfBWText->setText(QString("%1 kHz").arg(m_settings.m_rfBandwidth / 1000.0));
471 
472  ui->afBW->setValue(m_settings.m_afBandwidth/1000.0);
473  ui->afBWText->setText(QString("%1 kHz").arg(m_settings.m_afBandwidth/1000.0));
474 
475  ui->volume->setValue(m_settings.m_volume * 10.0);
476  ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1));
477 
478  ui->squelch->setValue(m_settings.m_squelch);
479  ui->squelchText->setText(QString("%1 dB").arg(m_settings.m_squelch));
480 
481  ui->audioStereo->setChecked(m_settings.m_audioStereo);
482  ui->lsbStereo->setChecked(m_settings.m_lsbStereo);
483  ui->showPilot->setChecked(m_settings.m_showPilot);
484  ui->rds->setChecked(m_settings.m_rdsActive);
485 
486  blockApplySettings(false);
487 }
488 
490 {
492 }
493 
495 {
497 }
498 
500 {
501  qDebug("BFMDemodGUI::audioSelect");
503  audioSelect.exec();
504 
505  if (audioSelect.m_selected)
506  {
508  applySettings();
509  }
510 }
511 
513 {
514  double magsqAvg, magsqPeak;
515  int nbMagsqSamples;
516  m_bfmDemod->getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
517  Real powDbAvg = CalcDb::dbPower(magsqAvg);
518  Real powDbPeak = CalcDb::dbPower(magsqPeak);
519 
520  ui->channelPowerMeter->levelChanged(
521  (100.0f + powDbAvg) / 100.0f,
522  (100.0f + powDbPeak) / 100.0f,
523  nbMagsqSamples);
524 
525  ui->channelPower->setText(QString::number(powDbAvg, 'f', 1));
526 
527  Real pilotPowDb = CalcDb::dbPower(m_bfmDemod->getPilotLevel());
528  QString pilotPowDbStr;
529  pilotPowDbStr.sprintf("%+02.1f", pilotPowDb);
530  ui->pilotPower->setText(pilotPowDbStr);
531 
532  if (m_bfmDemod->getPilotLock())
533  {
534  if (ui->audioStereo->isChecked())
535  {
536  ui->audioStereo->setStyleSheet("QToolButton { background-color : green; }");
537  }
538  }
539  else
540  {
541  if (ui->audioStereo->isChecked())
542  {
543  ui->audioStereo->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
544  }
545  }
546 
547  if (ui->rds->isChecked() && (m_rdsTimerCount == 0))
548  {
549  rdsUpdate(false);
550  }
551 
552  m_rdsTimerCount = (m_rdsTimerCount + 1) % 25;
553 
554  //qDebug() << "Pilot lock: " << m_bfmDemod->getPilotLock() << ":" << m_bfmDemod->getPilotLevel(); TODO: update a GUI item with status
555 }
556 
558 {
559  ui->g00Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[0].c_str());
560  ui->g01Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[1].c_str());
561  ui->g02Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[2].c_str());
562  ui->g03Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[3].c_str());
563  ui->g04Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[4].c_str());
564  //ui->g05Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[5].c_str());
565  //ui->g06Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[6].c_str());
566  //ui->g07Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[7].c_str());
567  ui->g08Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[8].c_str());
568  ui->g09Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[9].c_str());
569  ui->g14Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[14].c_str());
570 
571  ui->g00CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[0].c_str());
572  ui->g01CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[1].c_str());
573  ui->g02CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[2].c_str());
574  ui->g03CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[3].c_str());
575  ui->g04CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[4].c_str());
576  ui->g05CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[5].c_str());
577  ui->g06CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[6].c_str());
578  ui->g07CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[7].c_str());
579  ui->g08CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[8].c_str());
580  ui->g09CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[9].c_str());
581  ui->g14CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[14].c_str());
582 }
583 
584 void BFMDemodGUI::rdsUpdate(bool force)
585 {
586  // Quality metrics
587  ui->demodQText->setText(QString("%1 %").arg(m_bfmDemod->getDemodQua(), 0, 'f', 0));
588  ui->decoderQText->setText(QString("%1 %").arg(m_bfmDemod->getDecoderQua(), 0, 'f', 0));
589  Real accDb = CalcDb::dbPower(std::fabs(m_bfmDemod->getDemodAcc()));
590  ui->accumText->setText(QString("%1 dB").arg(accDb, 0, 'f', 1));
591  ui->fclkText->setText(QString("%1 Hz").arg(m_bfmDemod->getDemodFclk(), 0, 'f', 2));
592 
593  if (m_bfmDemod->getDecoderSynced()) {
594  ui->decoderQLabel->setStyleSheet("QLabel { background-color : green; }");
595  } else {
596  ui->decoderQLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
597  }
598 
599  // PI group
600  if (m_bfmDemod->getRDSParser().m_pi_updated || force)
601  {
602  ui->piLabel->setStyleSheet("QLabel { background-color : green; }");
603  ui->piCountText->setNum((int) m_bfmDemod->getRDSParser().m_pi_count);
604  QString pistring(str(boost::format("%04X") % m_bfmDemod->getRDSParser().m_pi_program_identification).c_str());
605  ui->piText->setText(pistring);
606 
608  ui->piTPIndicator->setStyleSheet("QLabel { background-color : green; }");
609  } else {
610  ui->piTPIndicator->setStyleSheet("QLabel { background:rgb(79,79,79); }");
611  }
612 
613  ui->piType->setText(QString(m_bfmDemod->getRDSParser().pty_table[m_bfmDemod->getRDSParser().m_pi_program_type].c_str()));
614  ui->piCoverage->setText(QString(m_bfmDemod->getRDSParser().coverage_area_codes[m_bfmDemod->getRDSParser().m_pi_area_coverage_index].c_str()));
615  }
616  else
617  {
618  ui->piLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
619  }
620 
621  // G0 group
622  if (m_bfmDemod->getRDSParser().m_g0_updated || force)
623  {
624  ui->g00Label->setStyleSheet("QLabel { background-color : green; }");
625  ui->g00CountText->setNum((int) m_bfmDemod->getRDSParser().m_g0_count);
626 
627  if (m_bfmDemod->getRDSParser().m_g0_psn_bitmap == 0b1111) {
628  ui->g00ProgServiceName->setText(QString(m_bfmDemod->getRDSParser().m_g0_program_service_name));
629  }
630 
632  ui->g00TrafficAnnouncement->setStyleSheet("QLabel { background-color : green; }");
633  } else {
634  ui->g00TrafficAnnouncement->setStyleSheet("QLabel { background:rgb(79,79,79); }");
635  }
636 
637  ui->g00MusicSpeech->setText(QString((m_bfmDemod->getRDSParser().m_g0_music_speech ? "Music" : "Speech")));
638  ui->g00MonoStereo->setText(QString((m_bfmDemod->getRDSParser().m_g0_mono_stereo ? "Mono" : "Stereo")));
639 
641  {
642  ui->g00AltFrequenciesBox->clear();
643 
644  for (std::set<double>::iterator it = m_bfmDemod->getRDSParser().m_g0_alt_freq.begin(); it != m_bfmDemod->getRDSParser().m_g0_alt_freq.end(); ++it)
645  {
646  if (*it > 76.0)
647  {
648  std::ostringstream os;
649  os << std::fixed << std::showpoint << std::setprecision(2) << *it;
650  ui->g00AltFrequenciesBox->addItem(QString(os.str().c_str()));
651  }
652  }
653 
654  ui->g00AltFrequenciesBox->setEnabled(ui->g00AltFrequenciesBox->count() > 0);
655  }
656  }
657  else
658  {
659  ui->g00Label->setStyleSheet("QLabel { background:rgb(79,79,79); }");
660  }
661 
662  // G1 group
663  if (m_bfmDemod->getRDSParser().m_g1_updated || force)
664  {
665  ui->g01Label->setStyleSheet("QLabel { background-color : green; }");
666  ui->g01CountText->setNum((int) m_bfmDemod->getRDSParser().m_g1_count);
667 
670  }
671 
673  ui->g01Language->setText(QString(m_bfmDemod->getRDSParser().language_codes[m_bfmDemod->getRDSParser().m_g1_language_index].c_str()));
674  }
675 
676  ui->g01DHM->setText(QString(str(boost::format("%id:%i:%i") % m_bfmDemod->getRDSParser().m_g1_pin_day % m_bfmDemod->getRDSParser().m_g1_pin_hour % m_bfmDemod->getRDSParser().m_g1_pin_minute).c_str()));
677  }
678  else
679  {
680  ui->g01Label->setStyleSheet("QLabel { background:rgb(79,79,79); }");
681  }
682 
683  // G2 group
684  if (m_bfmDemod->getRDSParser().m_g2_updated || force)
685  {
686  ui->g02Label->setStyleSheet("QLabel { background-color : green; }");
687  ui->g02CountText->setNum((int) m_bfmDemod->getRDSParser().m_g2_count);
688  ui->go2Text->setText(QString(m_bfmDemod->getRDSParser().m_g2_radiotext));
689  }
690  else
691  {
692  ui->g02Label->setStyleSheet("QLabel { background:rgb(79,79,79); }");
693  }
694 
695  // G3 group
696  if (m_bfmDemod->getRDSParser().m_g3_updated || force)
697  {
698  ui->g03Label->setStyleSheet("QLabel { background-color : green; }");
699  ui->g03CountText->setNum((int) m_bfmDemod->getRDSParser().m_g3_count);
700  std::string g3str = str(boost::format("%02X%c %04X %04X") % m_bfmDemod->getRDSParser().m_g3_appGroup % (m_bfmDemod->getRDSParser().m_g3_groupB ? 'B' : 'A') % m_bfmDemod->getRDSParser().m_g3_message % m_bfmDemod->getRDSParser().m_g3_aid);
701  ui->g03Data->setText(QString(g3str.c_str()));
702  }
703  else
704  {
705  ui->g03Label->setStyleSheet("QLabel { background:rgb(79,79,79); }");
706  }
707 
708  // G4 group
709  if (m_bfmDemod->getRDSParser().m_g4_updated || force)
710  {
711  ui->g04Label->setStyleSheet("QLabel { background-color : green; }");
712  ui->g04CountText->setNum((int) m_bfmDemod->getRDSParser().m_g4_count);
713  std::string time = str(boost::format("%4i-%02i-%02i %02i:%02i (%+.1fh)")\
715  ui->g04Time->setText(QString(time.c_str()));
716  }
717  else
718  {
719  ui->g04Label->setStyleSheet("QLabel { background:rgb(79,79,79); }");
720  }
721 
722  // G5 group
723  if (m_bfmDemod->getRDSParser().m_g5_updated || force)
724  {
725  ui->g05CountText->setNum((int) m_bfmDemod->getRDSParser().m_g5_count);
726  }
727 
728  // G6 group
729  if (m_bfmDemod->getRDSParser().m_g6_updated || force)
730  {
731  ui->g06CountText->setNum((int) m_bfmDemod->getRDSParser().m_g6_count);
732  }
733 
734  // G7 group
735  if (m_bfmDemod->getRDSParser().m_g7_updated || force)
736  {
737  ui->g07CountText->setNum((int) m_bfmDemod->getRDSParser().m_g7_count);
738  }
739 
740  // G8 group
741  if (m_bfmDemod->getRDSParser().m_g8_updated || force)
742  {
743  ui->g08Label->setStyleSheet("QLabel { background-color : green; }");
744  ui->g08CountText->setNum((int) m_bfmDemod->getRDSParser().m_g8_count);
745 
746  std::ostringstream os;
747  os << (m_bfmDemod->getRDSParser().m_g8_sign ? "-" : "+") << m_bfmDemod->getRDSParser().m_g8_extent + 1;
748  ui->g08Extent->setText(QString(os.str().c_str()));
750  ui->g08TMCEvent->setText(QString(RDSTMC::get_tmc_events(event_line, 1).c_str()));
751  QString pistring(str(boost::format("%04X") % m_bfmDemod->getRDSParser().m_g8_location).c_str());
752  ui->g08Location->setText(pistring);
753 
755  ui->g08Description->setText(QString(m_bfmDemod->getRDSParser().label_descriptions[m_bfmDemod->getRDSParser().m_g8_label_index].c_str()));
756  }
757 
758  ui->g08Content->setNum(m_bfmDemod->getRDSParser().m_g8_content);
759  }
760  else
761  {
762  ui->g08Label->setStyleSheet("QLabel { background:rgb(79,79,79); }");
763  }
764 
765  // G9 group
766  if (m_bfmDemod->getRDSParser().m_g9_updated || force)
767  {
768  ui->g09Label->setStyleSheet("QLabel { background-color : green; }");
769  ui->g09CountText->setNum((int) m_bfmDemod->getRDSParser().m_g9_count);
770  std::string g9str = str(boost::format("%02X %04X %04X %02X %04X") % m_bfmDemod->getRDSParser().m_g9_varA % m_bfmDemod->getRDSParser().m_g9_cA % m_bfmDemod->getRDSParser().m_g9_dA % m_bfmDemod->getRDSParser().m_g9_varB % m_bfmDemod->getRDSParser().m_g9_dB);
771  ui->g09Data->setText(QString(g9str.c_str()));
772  }
773  else
774  {
775  ui->g09Label->setStyleSheet("QLabel { background:rgb(79,79,79); }");
776  }
777 
778  // G14 group
779  if (m_bfmDemod->getRDSParser().m_g14_updated || force)
780  {
781  ui->g14CountText->setNum((int) m_bfmDemod->getRDSParser().m_g14_count);
782 
784  {
785  ui->g14Label->setStyleSheet("QLabel { background-color : green; }");
786  m_g14ComboIndex.clear();
787  ui->g14ProgServiceNames->clear();
788 
789  RDSParser::psns_map_t::iterator it = m_bfmDemod->getRDSParser().m_g14_program_service_names.begin();
790  const RDSParser::psns_map_t::iterator itEnd = m_bfmDemod->getRDSParser().m_g14_program_service_names.end();
791  int i = 0;
792 
793  for (; it != itEnd; ++it, i++)
794  {
795  m_g14ComboIndex.push_back(it->first);
796  QString pistring(str(boost::format("%04X:%s") % it->first % it->second).c_str());
797  ui->g14ProgServiceNames->addItem(pistring);
798  }
799  }
800  else
801  {
802  ui->g14Label->setStyleSheet("QLabel { background:rgb(79,79,79); }");
803  }
804  }
805 
807 }
808 
810 {
811  qint64 df = m_channelMarker.getCenterFrequency();
812  qDebug() << "BFMDemodGUI::changeFrequency: " << f - df;
813 }
unsigned int m_g0_count
Definition: rdsparser.h:58
unsigned int m_g6_count
Definition: rdsparser.h:108
unsigned int m_g8_event
Definition: rdsparser.h:118
unsigned int m_pi_program_identification
Definition: rdsparser.h:49
static MainWindow * getInstance()
Definition: mainwindow.h:73
QByteArray serialize() const
Definition: bfmdemodgui.cpp:94
const QString & getReverseAPIAddress() const
void onWidgetRolled(QWidget *widget, bool rollDown)
unsigned int m_g14_count
Definition: rdsparser.h:144
QString m_reverseAPIAddress
std::vector< unsigned int > m_g14ComboIndex
Definition: bfmdemodgui.h:75
int m_g8_content
Definition: rdsparser.h:121
unsigned int m_pi_count
Definition: rdsparser.h:48
unsigned int m_g9_cA
Definition: rdsparser.h:127
int getCenterFrequency() const
Definition: channelmarker.h:42
bool getDecoderSynced() const
Definition: bfmdemod.h:158
bool m_g0_mono_stereo
Definition: rdsparser.h:63
bool deserialize(const QByteArray &data)
Definition: bfmdemodgui.cpp:99
void push(Message *message, bool emitSignal=true)
Push message onto queue.
BFMDemod * m_bfmDemod
Definition: bfmdemodgui.h:73
int m_rdsTimerCount
Definition: bfmdemodgui.h:69
bool deserialize(const QByteArray &data)
virtual bool handleMessage(const Message &message)
unsigned int m_g2_count
Definition: rdsparser.h:81
void on_squelch_valueChanged(int value)
uint16_t m_reverseAPIChannelIndex
static double dbPower(double magsq, double floor=1e-12)
Definition: db.cpp:22
bool m_doApplySettings
Definition: bfmdemodgui.h:68
static const QString m_channelIdURI
Definition: bfmdemod.h:206
qint64 m_inputFrequencyOffset
void changeFrequency(qint64 f)
virtual qint64 getCenterFrequency() const
Definition: bfmdemodgui.cpp:69
bool m_g3_groupB
Definition: rdsparser.h:87
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
unsigned int m_g9_dB
Definition: rdsparser.h:130
unsigned int m_g9_dA
Definition: rdsparser.h:128
BFMDemodSettings m_settings
Definition: bfmdemodgui.h:67
void channelMarkerChangedByCursor()
void enterEvent(QEvent *)
void clearAllFields()
Definition: rdsparser.cpp:270
static const std::string pty_table[32]
Definition: rdsparser.h:163
Real getDemodAcc() const
Definition: bfmdemod.h:159
unsigned int m_g9_count
Definition: rdsparser.h:125
ChannelMarker m_channelMarker
Definition: bfmdemodgui.h:66
QString getName() const
Definition: bfmdemodgui.cpp:64
bool m_g1_updated
Definition: rdsparser.h:70
virtual ~BFMDemodGUI()
bool m_g7_updated
Definition: rdsparser.h:106
unsigned int m_g4_year
Definition: rdsparser.h:98
static int getRFBWIndex(int rfbw)
void audioSelect()
void channelMarkerHighlightedByCursor()
void resetToDefaults()
Definition: bfmdemodgui.cpp:80
bool m_g6_updated
Definition: rdsparser.h:105
psns_map_t m_g14_program_service_names
key: PI, value: PSN
Definition: rdsparser.h:145
char m_g0_program_service_name[8+1]
Definition: rdsparser.h:59
void on_rfBW_valueChanged(int value)
void rdsUpdate(bool force)
bool m_pi_traffic_program
Definition: rdsparser.h:51
static MsgConfigureChannelizer * create(int sampleRate, int centerFrequency)
Definition: bfmdemod.h:88
bool m_g14_updated
Definition: rdsparser.h:143
void setReverseAPIChannelIndex(uint16_t channelIndex)
freqs_map_t m_g14_mapped_freqs
key: PI, value: set of mapped frequencies (MHz)
Definition: rdsparser.h:147
bool m_g9_updated
Definition: rdsparser.h:124
void resetContextMenuType()
Definition: rollupwidget.h:50
void addChannelMarker(ChannelMarker *channelMarker)
Add channel marker to spectrum.
Definition: deviceuiset.cpp:72
freqs_map_t m_g14_alt_freqs
key: PI, value: set of alternate frequencies (MHz)
Definition: rdsparser.h:146
void on_afBW_valueChanged(int value)
void rdsUpdateFixedFields()
void on_g14AltFrequencies_activated(int index)
unsigned int m_g1_count
Definition: rdsparser.h:71
unsigned char m_pi_program_type
Definition: rdsparser.h:50
bool m_g2_updated
Definition: rdsparser.h:80
uint16_t m_reverseAPIDeviceIndex
unsigned int m_g8_location
Definition: rdsparser.h:119
static int requiredBW(int rfBW)
Definition: bfmdemod.h:197
unsigned int uint32_t
Definition: rtptypes_win.h:46
static int getRFBW(int index)
ContextMenuType m_contextMenuType
Definition: rollupwidget.h:33
unsigned int m_g1_pin_minute
Definition: rdsparser.h:77
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
void setSampleSink(BasebandSampleSink *sampleSink)
Definition: bfmdemod.h:127
unsigned int m_g8_extent
Definition: rdsparser.h:117
void on_showPilot_clicked()
#define SDR_RX_SCALEF
Definition: dsptypes.h:33
QByteArray serialize() const
static const std::string rds_group_acronym_tags[16]
Definition: rdsparser.h:167
bool m_g14_data_available
Definition: rdsparser.h:152
static const std::string label_descriptions[16]
Definition: rdsparser.h:171
static const std::string language_codes[44]
Definition: rdsparser.h:168
unsigned int m_g1_pin_day
Definition: rdsparser.h:75
bool m_g0_traffic_announcement
Definition: rdsparser.h:61
unsigned int m_g9_varB
Definition: rdsparser.h:129
int m_g1_country_index
negative if not received
Definition: rdsparser.h:73
bool m_g0_updated
Definition: rdsparser.h:56
unsigned int m_g4_minutes
Definition: rdsparser.h:96
virtual void setMessageQueueToGUI(MessageQueue *queue)
unsigned char m_g0_psn_bitmap
Definition: rdsparser.h:60
static DSPEngine * instance()
Definition: dspengine.cpp:51
void on_g14ProgServiceNames_currentIndexChanged(int index)
void setTitleColor(const QColor &c)
std::set< double > m_g0_alt_freq
Definition: rdsparser.h:67
void setHighlighted(bool highlighted)
unsigned int m_g7_count
Definition: rdsparser.h:109
unsigned int m_g4_month
Definition: rdsparser.h:99
uint16_t m_reverseAPIPort
char m_g2_radiotext[64+1]
Definition: rdsparser.h:82
void onMenuDialogCalled(const QPoint &p)
void registerRxChannelInstance(const QString &channelName, PluginInstanceGUI *pluginGUI)
Definition: deviceuiset.cpp:82
static const std::string pi_country_codes[15][5]
Definition: rdsparser.h:164
int32_t i
Definition: decimators.h:244
void addRollupWidget(QWidget *widget)
Add rollup widget to channel window.
Definition: deviceuiset.cpp:77
bool m_g0_af_updated
Definition: rdsparser.h:57
void removeRxChannelInstance(PluginInstanceGUI *pluginGUI)
Definition: deviceuiset.cpp:94
void setSpectrumGUI(Serializable *spectrumGUI)
const QString & getTitle() const
Definition: channelmarker.h:38
unsigned int m_g3_appGroup
Definition: rdsparser.h:88
static bool match(const Message *message)
Definition: message.cpp:45
bool getHighlighted() const
Definition: channelmarker.h:61
unsigned int m_g8_count
Definition: rdsparser.h:113
static const std::string coverage_area_codes[16]
Definition: rdsparser.h:165
unsigned int m_g9_varA
Definition: rdsparser.h:126
void on_rds_clicked()
int m_g8_label_index
negative if not received
Definition: rdsparser.h:120
void handleInputMessages()
unsigned int m_g3_message
Definition: rdsparser.h:89
unsigned int m_g4_day
Definition: rdsparser.h:100
void setName(const QString &name)
Definition: bfmdemodgui.cpp:59
bool m_g5_updated
Definition: rdsparser.h:104
bool m_pi_updated
Definition: rdsparser.h:47
void applySettings(bool force=false)
void blockApplySettings(bool block)
virtual void destroy()
Definition: bfmdemodgui.cpp:54
bool m_g3_updated
Definition: rdsparser.h:85
void setReverseAPIAddress(const QString &address)
int m_g1_language_index
negative if not received
Definition: rdsparser.h:74
static int get_tmc_event_code_index(unsigned int i, unsigned int j)
Definition: rdstmc.cpp:3703
static MsgConfigureBFMDemod * create(const BFMDemodSettings &settings, bool force)
Definition: bfmdemod.h:65
unsigned int m_g5_count
Definition: rdsparser.h:107
void setHighlighted(bool highlighted)
Real getDemodQua() const
Definition: bfmdemod.h:160
virtual MessageQueue * getInputMessageQueue()
Definition: bfmdemodgui.h:55
void on_volume_valueChanged(int value)
unsigned int m_g1_pin_hour
Definition: rdsparser.h:76
int m_pi_area_coverage_index
Definition: rdsparser.h:53
DeviceUISet * m_deviceUISet
Definition: bfmdemodgui.h:65
void setColor(const QColor &color)
Real getDecoderQua() const
Definition: bfmdemod.h:157
void setChannelMarker(Serializable *channelMarker)
void leaveEvent(QEvent *)
Real getDemodFclk() const
Definition: bfmdemod.h:161
Real getPilotLevel() const
Definition: bfmdemod.h:155
void displaySettings()
void getMagSqLevels(double &avg, double &peak, int &nbSamples)
Definition: bfmdemod.h:163
bool m_g8_updated
Definition: rdsparser.h:112
void on_lsbStereo_toggled(bool lsb)
void setVisible(bool visible)
PluginAPI * m_pluginAPI
Definition: bfmdemodgui.h:64
bool m_g4_updated
Definition: rdsparser.h:93
bool m_g0_music_speech
Definition: rdsparser.h:62
unsigned int m_g3_aid
Definition: rdsparser.h:90
void configure(MessageQueue *msgQueue, int fftSize, int overlapPercent, unsigned int averagingNb, int averagingMode, FFTWindow::Function window, bool m_linear)
Definition: spectrumvis.cpp:44
void setBandwidth(int bandwidth)
unsigned int m_g3_count
Definition: rdsparser.h:86
const QColor & getColor() const
Definition: channelmarker.h:64
void setTitle(const QString &title)
unsigned int m_g4_count
Definition: rdsparser.h:94
void clearUpdateFlags()
Definition: rdsparser.cpp:244
int m_g1_country_page_index
negative if not received
Definition: rdsparser.h:72
const BFMDemodSettings & getSettings() const
Definition: bfmdemod.h:62
static BFMDemodGUI * create(PluginAPI *pluginAPI, DeviceUISet *deviceAPI, BasebandSampleSink *rxChannel)
Definition: bfmdemodgui.cpp:48
void setCenterFrequency(int centerFrequency)
RDSParser & getRDSParser()
Definition: bfmdemod.h:181
void on_clearData_clicked(bool checked)
bool m_g8_sign
Definition: rdsparser.h:116
double m_g4_local_time_offset
Definition: rdsparser.h:101
void on_g00AltFrequenciesBox_activated(int index)
void widgetRolled(QWidget *widget, bool rollDown)
float Real
Definition: dsptypes.h:42
static std::string get_tmc_events(unsigned int i, unsigned int j)
Definition: rdstmc.cpp:3698
void on_g14MappedFrequencies_activated(int index)
SpectrumVis * m_spectrumVis
Definition: bfmdemodgui.h:71
void setUseReverseAPI(bool useReverseAPI)
unsigned int m_g4_hours
Definition: rdsparser.h:95
bool getPilotLock() const
Definition: bfmdemod.h:154
void on_audioStereo_toggled(bool stereo)
Ui::BFMDemodGUI * ui
Definition: bfmdemodgui.h:63
BFMDemodGUI(PluginAPI *pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget *parent=0)
virtual void setCenterFrequency(qint64 centerFrequency)
Definition: bfmdemodgui.cpp:74
void on_deltaFrequency_changed(qint64 value)