From fa68a8ff2bbc47fc180b1de396c59e97a9157bfa Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 8 Nov 2020 02:04:17 +0100 Subject: [PATCH] NFM: RF, AF bandwidth and FM deviation independent setting. Implements #691 --- plugins/channelrx/demodnfm/nfmdemodgui.cpp | 58 +++-- plugins/channelrx/demodnfm/nfmdemodgui.h | 4 +- plugins/channelrx/demodnfm/nfmdemodgui.ui | 213 +++++++++++------- .../channelrx/demodnfm/nfmdemodsettings.cpp | 112 +++++++-- plugins/channelrx/demodnfm/nfmdemodsettings.h | 13 +- plugins/channelrx/demodnfm/nfmdemodsink.cpp | 4 +- plugins/channeltx/modnfm/nfmmodgui.cpp | 56 +++-- plugins/channeltx/modnfm/nfmmodgui.h | 3 +- plugins/channeltx/modnfm/nfmmodgui.ui | 84 ++++--- plugins/channeltx/modnfm/nfmmodsettings.cpp | 105 ++++++++- plugins/channeltx/modnfm/nfmmodsettings.h | 11 +- 11 files changed, 480 insertions(+), 183 deletions(-) diff --git a/plugins/channelrx/demodnfm/nfmdemodgui.cpp b/plugins/channelrx/demodnfm/nfmdemodgui.cpp index ec1cfa69c..8568c2cba 100644 --- a/plugins/channelrx/demodnfm/nfmdemodgui.cpp +++ b/plugins/channelrx/demodnfm/nfmdemodgui.cpp @@ -107,20 +107,46 @@ void NFMDemodGUI::on_deltaFrequency_changed(qint64 value) applySettings(); } -void NFMDemodGUI::on_rfBW_currentIndexChanged(int index) +void NFMDemodGUI::on_channelSpacing_currentIndexChanged(int index) { - qDebug() << "NFMDemodGUI::on_rfBW_currentIndexChanged" << index; - //ui->rfBWText->setText(QString("%1 k").arg(m_rfBW[value] / 1000.0)); - m_channelMarker.setBandwidth(NFMDemodSettings::getRFBW(index)); m_settings.m_rfBandwidth = NFMDemodSettings::getRFBW(index); - m_settings.m_fmDeviation = NFMDemodSettings::getFMDev(index); + m_settings.m_afBandwidth = NFMDemodSettings::getAFBW(index); + m_settings.m_fmDeviation = 2.0 * NFMDemodSettings::getFMDev(index); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); + ui->rfBW->blockSignals(true); + ui->afBW->blockSignals(true); + ui->fmDev->blockSignals(true); + ui->rfBWText->setText(QString("%1k").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1)); + ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0); + ui->afBWText->setText(QString("%1k").arg(m_settings.m_afBandwidth / 1000.0, 0, 'f', 1)); + ui->afBW->setValue(m_settings.m_afBandwidth / 100.0); + ui->fmDevText->setText(QString("%1k").arg(m_settings.m_fmDeviation / 2000.0, 0, 'f', 1)); + ui->fmDev->setValue(m_settings.m_fmDeviation / 200.0); + ui->rfBW->blockSignals(false); + ui->afBW->blockSignals(false); + ui->fmDev->blockSignals(false); + applySettings(); +} + +void NFMDemodGUI::on_rfBW_valueChanged(int value) +{ + ui->rfBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_rfBandwidth = value * 100.0; + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); applySettings(); } void NFMDemodGUI::on_afBW_valueChanged(int value) { - ui->afBWText->setText(QString("%1 k").arg(value)); - m_settings.m_afBandwidth = value * 1000.0; + ui->afBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_afBandwidth = value * 100.0; + applySettings(); +} + +void NFMDemodGUI::on_fmDev_valueChanged(int value) +{ + ui->fmDevText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_fmDeviation = value * 200.0; applySettings(); } @@ -281,12 +307,14 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban blockApplySettings(true); - ui->rfBW->clear(); + ui->channelSpacing->clear(); - for (int i = 0; i < NFMDemodSettings::m_nbRfBW; i++) { - ui->rfBW->addItem(QString("%1").arg(NFMDemodSettings::getRFBW(i) / 1000.0, 0, 'f', 2)); + for (int i = 0; i < NFMDemodSettings::m_nbChannelSpacings; i++) { + ui->channelSpacing->addItem(QString("%1").arg(NFMDemodSettings::getChannelSpacing(i) / 1000.0, 0, 'f', 2)); } + ui->channelSpacing->setCurrentIndex(NFMDemodSettings::getChannelSpacingIndex(12500)); + int ctcss_nbTones; const Real *ctcss_tones = m_nfmDemod->getCtcssToneSet(ctcss_nbTones); @@ -363,10 +391,14 @@ void NFMDemodGUI::displaySettings() ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); - ui->rfBW->setCurrentIndex(NFMDemodSettings::getRFBWIndex(m_settings.m_rfBandwidth)); + ui->rfBWText->setText(QString("%1k").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1)); + ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0); - ui->afBWText->setText(QString("%1 k").arg(m_settings.m_afBandwidth / 1000.0)); - ui->afBW->setValue(m_settings.m_afBandwidth / 1000.0); + ui->afBWText->setText(QString("%1k").arg(m_settings.m_afBandwidth / 1000.0, 0, 'f', 1)); + ui->afBW->setValue(m_settings.m_afBandwidth / 100.0); + + ui->fmDevText->setText(QString("%1k").arg(m_settings.m_fmDeviation / 2000.0, 0, 'f', 1)); + ui->fmDev->setValue(m_settings.m_fmDeviation / 200.0); ui->volumeText->setText(QString("%1").arg(m_settings.m_volume*100.0, 0, 'f', 0)); ui->volume->setValue(m_settings.m_volume * 100.0); diff --git a/plugins/channelrx/demodnfm/nfmdemodgui.h b/plugins/channelrx/demodnfm/nfmdemodgui.h index 8a75fd5d1..a7e27f43b 100644 --- a/plugins/channelrx/demodnfm/nfmdemodgui.h +++ b/plugins/channelrx/demodnfm/nfmdemodgui.h @@ -64,8 +64,10 @@ private: private slots: void on_deltaFrequency_changed(qint64 value); - void on_rfBW_currentIndexChanged(int index); + void on_channelSpacing_currentIndexChanged(int index); + void on_rfBW_valueChanged(int value); void on_afBW_valueChanged(int value); + void on_fmDev_valueChanged(int value); void on_volume_valueChanged(int value); void on_squelchGate_valueChanged(int value); void on_deltaSquelch_toggled(bool checked); diff --git a/plugins/channelrx/demodnfm/nfmdemodgui.ui b/plugins/channelrx/demodnfm/nfmdemodgui.ui index 8d3eb29f8..f424e458e 100644 --- a/plugins/channelrx/demodnfm/nfmdemodgui.ui +++ b/plugins/channelrx/demodnfm/nfmdemodgui.ui @@ -7,7 +7,7 @@ 0 0 302 - 178 + 182 @@ -204,14 +204,14 @@ - + - RFBW + CS - + 60 @@ -219,23 +219,58 @@ - RF demodulator bandwidth (kHz) + Apply channel spacing settings - + + + RF + + + + + - 10 + 0 + 0 + + + + RF bandwidth (kHz) + + + 1 + + + 400 + + + 1 + + + 110 + + + Qt::Horizontal + + + + + + + + 35 0 - k + 20.0k - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -252,23 +287,10 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - AFBW + AF @@ -287,13 +309,13 @@ 1 - 20 + 200 1 - 3 + 30 Qt::Horizontal @@ -304,12 +326,12 @@ - 25 + 35 0 - 3 k + 20.0k Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -321,79 +343,60 @@ - + - Vol + FMd - - - - 24 - 24 - - - - Sound volume (%) - - - 200 - - - 1 - - - 1 - - - 100 - - - - - + 0 0 - + + FM peak deviation (kHz) + + + 1 + + + 200 + + + 1 + + + 25 + + + Qt::Horizontal + + + + + + - 30 - 16777215 + 35 + 0 - - Sound volume (%) - - 100 + 20.0k Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - Qt::Horizontal - - - - 40 - 20 - - - - - Sq + Sq @@ -565,17 +568,61 @@ - - - Qt::Horizontal + + + Vol - + + + + + - 40 - 20 + 24 + 24 - + + Sound volume (%) + + + 200 + + + 1 + + + 1 + + + 100 + + + + + + + + 0 + 0 + + + + + 30 + 16777215 + + + + Sound volume (%) + + + 100 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + diff --git a/plugins/channelrx/demodnfm/nfmdemodsettings.cpp b/plugins/channelrx/demodnfm/nfmdemodsettings.cpp index de5c3479a..6fd1ac579 100644 --- a/plugins/channelrx/demodnfm/nfmdemodsettings.cpp +++ b/plugins/channelrx/demodnfm/nfmdemodsettings.cpp @@ -23,15 +23,23 @@ #include "nfmdemodsettings.h" -// fixed |Carson (3k) |Carson (6k) -// | 11F3 16F3 | -const int NFMDemodSettings::m_rfBW[] = { - 5000, 6250, 8330, 11000, 16000, 20000, 25000, 40000 +// Standard channel spacings (kHz) using Carson rule +// beta based ............ 11F3 16F3 (36F9) +// 5 6.25 7.5 8.33 12.5 25 40 Spacing +// 0.43 0.43 0.43 0.43 0.83 1.67 1.0 Beta +const int NFMDemodSettings::m_channelSpacings[] = { + 5000, 6250, 7500, 8333, 12500, 25000, 40000 }; -const int NFMDemodSettings::m_fmDev[] = { - 2500, 2500, 3330, 5000, 10000, 14000, 19000, 28000 +const int NFMDemodSettings::m_rfBW[] = { // RF bandwidth (Hz) + 4800, 6000, 7200, 8000, 11000, 16000, 36000 }; -const int NFMDemodSettings::m_nbRfBW = 8; +const int NFMDemodSettings::m_afBW[] = { // audio bandwidth (Hz) + 1700, 2100, 2500, 2800, 3000, 3000, 9000 +}; +const int NFMDemodSettings::m_fmDev[] = { // peak deviation (Hz) - full is double + 731, 903, 1075, 1204, 2500, 5000, 9000 +}; +const int NFMDemodSettings::m_nbChannelSpacings = 7; NFMDemodSettings::NFMDemodSettings() : m_channelMarker(0) @@ -44,7 +52,7 @@ void NFMDemodSettings::resetToDefaults() m_inputFrequencyOffset = 0; m_rfBandwidth = 12500; m_afBandwidth = 3000; - m_fmDeviation = 2000; + m_fmDeviation = 5000; m_squelchGate = 5; // 10s of ms at 48000 Hz sample rate. Corresponds to 2400 for AGC attack m_deltaSquelch = false; m_squelch = -30.0; @@ -68,8 +76,8 @@ QByteArray NFMDemodSettings::serialize() const { SimpleSerializer s(1); s.writeS32(1, m_inputFrequencyOffset); - s.writeS32(2, getRFBWIndex(m_rfBandwidth)); - s.writeS32(3, m_afBandwidth/1000.0); + s.writeReal(2, m_rfBandwidth); + s.writeReal(3, m_afBandwidth); s.writeS32(4, m_volume*10.0); s.writeS32(5, static_cast(m_squelch)); s.writeBool(6, m_highPass); @@ -92,6 +100,7 @@ QByteArray NFMDemodSettings::serialize() const s.writeU32(19, m_reverseAPIDeviceIndex); s.writeU32(20, m_reverseAPIChannelIndex); s.writeS32(21, m_streamIndex); + s.writeReal(22, m_fmDeviation); return s.final(); } @@ -120,11 +129,8 @@ bool NFMDemodSettings::deserialize(const QByteArray& data) d.readS32(1, &tmp, 0); m_inputFrequencyOffset = tmp; - d.readS32(2, &tmp, 4); - m_rfBandwidth = getRFBW(tmp); - m_fmDeviation = getFMDev(tmp); - d.readS32(3, &tmp, 3); - m_afBandwidth = tmp * 1000.0; + d.readReal(2, &m_rfBandwidth, 12500.0); + d.readReal(3, &m_afBandwidth, 3000.0); d.readS32(4, &tmp, 20); m_volume = tmp / 10.0; d.readS32(5, &tmp, -30); @@ -153,6 +159,7 @@ bool NFMDemodSettings::deserialize(const QByteArray& data) d.readU32(20, &utmp, 0); m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp; d.readS32(21, &m_streamIndex, 0); + d.readReal(22, &m_fmDeviation, 5000.0); return true; } @@ -163,37 +170,94 @@ bool NFMDemodSettings::deserialize(const QByteArray& data) } } +int NFMDemodSettings::getChannelSpacing(int index) +{ + if (index < 0) { + return m_channelSpacings[0]; + } else if (index < m_nbChannelSpacings) { + return m_channelSpacings[index]; + } else { + return m_channelSpacings[m_nbChannelSpacings-1]; + } +} + +int NFMDemodSettings::getChannelSpacingIndex(int channelSpacing) +{ + for (int i = 0; i < m_nbChannelSpacings; i++) + { + if (channelSpacing <= m_channelSpacings[i]) { + return i; + } + } + + return m_nbChannelSpacings-1; +} + int NFMDemodSettings::getRFBW(int index) { if (index < 0) { return m_rfBW[0]; - } else if (index < m_nbRfBW) { + } else if (index < m_nbChannelSpacings) { return m_rfBW[index]; } else { - return m_rfBW[m_nbRfBW-1]; + return m_rfBW[m_nbChannelSpacings-1]; } } +int NFMDemodSettings::getRFBWIndex(int rfbw) +{ + for (int i = 0; i < m_nbChannelSpacings; i++) + { + if (rfbw <= m_rfBW[i]) { + return i; + } + } + + return m_nbChannelSpacings-1; +} + +int NFMDemodSettings::getAFBW(int index) +{ + if (index < 0) { + return m_afBW[0]; + } else if (index < m_nbChannelSpacings) { + return m_afBW[index]; + } else { + return m_afBW[m_nbChannelSpacings-1]; + } +} + +int NFMDemodSettings::getAFBWIndex(int afbw) +{ + for (int i = 0; i < m_nbChannelSpacings; i++) + { + if (afbw <= m_afBW[i]) { + return i; + } + } + + return m_nbChannelSpacings-1; +} + int NFMDemodSettings::getFMDev(int index) { if (index < 0) { return m_fmDev[0]; - } else if (index < m_nbRfBW) { + } else if (index < m_nbChannelSpacings) { return m_fmDev[index]; } else { - return m_fmDev[m_nbRfBW-1]; + return m_fmDev[m_nbChannelSpacings-1]; } } -int NFMDemodSettings::getRFBWIndex(int rfbw) +int NFMDemodSettings::getFMDevIndex(int fmDev) { - for (int i = 0; i < m_nbRfBW; i++) + for (int i = 0; i < m_nbChannelSpacings; i++) { - if (rfbw <= m_rfBW[i]) - { + if (fmDev <= m_rfBW[i]) { return i; } } - return m_nbRfBW-1; + return m_nbChannelSpacings-1; } diff --git a/plugins/channelrx/demodnfm/nfmdemodsettings.h b/plugins/channelrx/demodnfm/nfmdemodsettings.h index 6d2bc332f..8ae968391 100644 --- a/plugins/channelrx/demodnfm/nfmdemodsettings.h +++ b/plugins/channelrx/demodnfm/nfmdemodsettings.h @@ -24,14 +24,16 @@ class Serializable; struct NFMDemodSettings { - static const int m_nbRfBW; + static const int m_nbChannelSpacings; + static const int m_channelSpacings[]; static const int m_rfBW[]; + static const int m_afBW[]; static const int m_fmDev[]; int32_t m_inputFrequencyOffset; Real m_rfBandwidth; Real m_afBandwidth; - int m_fmDeviation; + Real m_fmDeviation; int m_squelchGate; bool m_deltaSquelch; Real m_squelch; //!< deci-Bels @@ -58,9 +60,14 @@ struct NFMDemodSettings QByteArray serialize() const; bool deserialize(const QByteArray& data); + static int getChannelSpacing(int index); + static int getChannelSpacingIndex(int channelSpacing); static int getRFBW(int index); - static int getFMDev(int index); static int getRFBWIndex(int rfbw); + static int getAFBW(int index); + static int getAFBWIndex(int rfbw); + static int getFMDev(int index); + static int getFMDevIndex(int fmDev); }; diff --git a/plugins/channelrx/demodnfm/nfmdemodsink.cpp b/plugins/channelrx/demodnfm/nfmdemodsink.cpp index c5fbadb97..33d96b773 100644 --- a/plugins/channelrx/demodnfm/nfmdemodsink.cpp +++ b/plugins/channelrx/demodnfm/nfmdemodsink.cpp @@ -236,7 +236,7 @@ void NFMDemodSink::applyChannelSettings(int channelSampleRate, int channelFreque if ((channelSampleRate != m_channelSampleRate) || force) { - m_interpolator.create(16, channelSampleRate, m_settings.m_fmDeviation); + m_interpolator.create(16, channelSampleRate, m_settings.m_rfBandwidth / 2.2); m_interpolatorDistance = Real(channelSampleRate) / Real(m_audioSampleRate); m_interpolatorDistanceRemain = m_interpolatorDistance; @@ -269,7 +269,7 @@ void NFMDemodSink::applySettings(const NFMDemodSettings& settings, bool force) if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) { - m_interpolator.create(16, m_channelSampleRate, settings.m_fmDeviation); + m_interpolator.create(16, m_channelSampleRate, settings.m_rfBandwidth / 2.2); m_interpolatorDistance = Real(m_channelSampleRate) / Real(m_audioSampleRate); m_interpolatorDistanceRemain = m_interpolatorDistance; } diff --git a/plugins/channeltx/modnfm/nfmmodgui.cpp b/plugins/channeltx/modnfm/nfmmodgui.cpp index 9f90275fd..62e58f63f 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.cpp +++ b/plugins/channeltx/modnfm/nfmmodgui.cpp @@ -137,24 +137,46 @@ void NFMModGUI::on_deltaFrequency_changed(qint64 value) applySettings(); } -void NFMModGUI::on_rfBW_currentIndexChanged(int index) +void NFMModGUI::on_channelSpacing_currentIndexChanged(int index) { - m_channelMarker.setBandwidth(NFMModSettings::getRFBW(index)); m_settings.m_rfBandwidth = NFMModSettings::getRFBW(index); + m_settings.m_afBandwidth = NFMModSettings::getAFBW(index); + m_settings.m_fmDeviation = 2.0 * NFMModSettings::getFMDev(index); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); + ui->rfBW->blockSignals(true); + ui->afBW->blockSignals(true); + ui->fmDev->blockSignals(true); + ui->rfBWText->setText(QString("%1k").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1)); + ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0); + ui->afBWText->setText(QString("%1k").arg(m_settings.m_afBandwidth / 1000.0, 0, 'f', 1)); + ui->afBW->setValue(m_settings.m_afBandwidth / 100.0); + ui->fmDevText->setText(QString("%1k").arg(m_settings.m_fmDeviation / 2000.0, 0, 'f', 1)); + ui->fmDev->setValue(m_settings.m_fmDeviation / 200.0); + ui->rfBW->blockSignals(false); + ui->afBW->blockSignals(false); + ui->fmDev->blockSignals(false); + applySettings(); +} + +void NFMModGUI::on_rfBW_valueChanged(int value) +{ + ui->rfBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_rfBandwidth = value * 100.0; + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); applySettings(); } void NFMModGUI::on_afBW_valueChanged(int value) { - ui->afBWText->setText(QString("%1k").arg(value)); - m_settings.m_afBandwidth = value * 1000.0; + ui->afBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_afBandwidth = value * 100.0; applySettings(); } void NFMModGUI::on_fmDev_valueChanged(int value) { ui->fmDevText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); - m_settings.m_fmDeviation = value * 100.0; + m_settings.m_fmDeviation = value * 200.0; applySettings(); } @@ -352,15 +374,15 @@ NFMModGUI::NFMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); - blockApplySettings(true); + ui->channelSpacing->blockSignals(true); + ui->channelSpacing->clear(); - ui->rfBW->clear(); - for (int i = 0; i < NFMModSettings::m_nbRfBW; i++) { - ui->rfBW->addItem(QString("%1").arg(NFMModSettings::getRFBW(i) / 1000.0, 0, 'f', 2)); + for (int i = 0; i < NFMModSettings::m_nbChannelSpacings; i++) { + ui->channelSpacing->addItem(QString("%1").arg(NFMModSettings::getChannelSpacing(i) / 1000.0, 0, 'f', 2)); } - ui->rfBW->setCurrentIndex(6); - blockApplySettings(false); + ui->channelSpacing->setCurrentIndex(NFMModSettings::getChannelSpacingIndex(25000)); + ui->channelSpacing->blockSignals(false); connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); @@ -439,7 +461,6 @@ void NFMModGUI::displaySettings() m_channelMarker.blockSignals(true); m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); m_channelMarker.setTitle(m_settings.m_title); - m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); m_channelMarker.blockSignals(false); m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only @@ -451,13 +472,14 @@ void NFMModGUI::displaySettings() ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); - ui->rfBW->setCurrentIndex(NFMModSettings::getRFBWIndex(m_settings.m_rfBandwidth)); + ui->rfBWText->setText(QString("%1k").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1)); + ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0); - ui->afBWText->setText(QString("%1k").arg(m_settings.m_afBandwidth / 1000.0)); - ui->afBW->setValue(m_settings.m_afBandwidth / 1000.0); + ui->afBWText->setText(QString("%1k").arg(m_settings.m_afBandwidth / 1000.0, 0, 'f', 1)); + ui->afBW->setValue(m_settings.m_afBandwidth / 100.0); - ui->fmDevText->setText(QString("%1k").arg(m_settings.m_fmDeviation / 1000.0, 0, 'f', 1)); - ui->fmDev->setValue(m_settings.m_fmDeviation / 100.0); + ui->fmDevText->setText(QString("%1k").arg(m_settings.m_fmDeviation / 2000.0, 0, 'f', 1)); + ui->fmDev->setValue(m_settings.m_fmDeviation / 200.0); ui->volumeText->setText(QString("%1").arg(m_settings.m_volumeFactor, 0, 'f', 1)); ui->volume->setValue(m_settings.m_volumeFactor * 10.0); diff --git a/plugins/channeltx/modnfm/nfmmodgui.h b/plugins/channeltx/modnfm/nfmmodgui.h index 7606ba076..b44a1a70c 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.h +++ b/plugins/channeltx/modnfm/nfmmodgui.h @@ -89,7 +89,8 @@ private slots: void handleSourceMessages(); void on_deltaFrequency_changed(qint64 value); - void on_rfBW_currentIndexChanged(int index); + void on_channelSpacing_currentIndexChanged(int index); + void on_rfBW_valueChanged(int value); void on_afBW_valueChanged(int value); void on_fmDev_valueChanged(int value); void on_toneFrequency_valueChanged(int value); diff --git a/plugins/channeltx/modnfm/nfmmodgui.ui b/plugins/channeltx/modnfm/nfmmodgui.ui index ea064368f..59ae43e78 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.ui +++ b/plugins/channeltx/modnfm/nfmmodgui.ui @@ -186,35 +186,22 @@ - + - RFBW + CS - + 60 16777215 - - - - - - - 10 - 0 - - - - k - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + Apply channel spacing settings @@ -235,19 +222,19 @@ - Audio bandwidth + Audio bandwidth (kHz) 1 - 20 + 200 1 - 3 + 30 Qt::Horizontal @@ -258,12 +245,12 @@ - 25 + 35 0 - 3k + 20.0k Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -274,6 +261,51 @@ + + + + RFBW + + + + + + + RF bandwidth (kHz) + + + 1 + + + 480 + + + 1 + + + 160 + + + Qt::Horizontal + + + + + + + + 35 + 0 + + + + 25.0k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + @@ -296,10 +328,10 @@ - Modulation percentage + FM peak deviation (kHz) - 300 + 200 1 @@ -316,7 +348,7 @@ - 30 + 35 0 diff --git a/plugins/channeltx/modnfm/nfmmodsettings.cpp b/plugins/channeltx/modnfm/nfmmodsettings.cpp index a20842346..b8b245899 100644 --- a/plugins/channeltx/modnfm/nfmmodsettings.cpp +++ b/plugins/channeltx/modnfm/nfmmodsettings.cpp @@ -24,10 +24,23 @@ #include "settings/serializable.h" #include "nfmmodsettings.h" -const int NFMModSettings::m_rfBW[] = { - 3000, 4000, 5000, 6250, 8330, 10000, 12500, 15000, 20000, 25000, 40000 +// Standard channel spacings (kHz) using Carson rule +// beta based ............ 11F3 16F3 (36F9) +// 5 6.25 7.5 8.33 12.5 25 40 Spacing +// 0.43 0.43 0.43 0.43 0.83 1.67 1.0 Beta +const int NFMModSettings::m_channelSpacings[] = { + 5000, 6250, 7500, 8333, 12500, 25000, 40000 }; -const int NFMModSettings::m_nbRfBW = 11; +const int NFMModSettings::m_rfBW[] = { // RF bandwidth (Hz) + 4800, 6000, 7200, 8000, 11000, 16000, 36000 +}; +const int NFMModSettings::m_afBW[] = { // audio bandwidth (Hz) + 1700, 2100, 2500, 2800, 3000, 3000, 9000 +}; +const int NFMModSettings::m_fmDev[] = { // peak deviation (Hz) - full is double + 731, 903, 1075, 1204, 2500, 5000, 9000 +}; +const int NFMModSettings::m_nbChannelSpacings = 7; NFMModSettings::NFMModSettings() : @@ -41,8 +54,8 @@ void NFMModSettings::resetToDefaults() { m_afBandwidth = 3000; m_inputFrequencyOffset = 0; - m_rfBandwidth = 12500.0f; - m_fmDeviation = 3000.0f; + m_rfBandwidth = 16000.0f; + m_fmDeviation = 10000.0f; //!< full deviation m_toneFrequency = 1000.0f; m_volumeFactor = 1.0f; m_channelMute = false; @@ -124,7 +137,7 @@ bool NFMModSettings::deserialize(const QByteArray& data) m_inputFrequencyOffset = tmp; d.readReal(2, &m_rfBandwidth, 12500.0); d.readReal(3, &m_afBandwidth, 1000.0); - d.readReal(4, &m_fmDeviation, 3000.0); + d.readReal(4, &m_fmDeviation, 10000.0); d.readU32(5, &m_rgbColor); d.readReal(6, &m_toneFrequency, 1000.0); d.readReal(7, &m_volumeFactor, 1.0); @@ -184,28 +197,96 @@ bool NFMModSettings::deserialize(const QByteArray& data) } } +int NFMModSettings::getChannelSpacing(int index) +{ + if (index < 0) { + return m_channelSpacings[0]; + } else if (index < m_nbChannelSpacings) { + return m_channelSpacings[index]; + } else { + return m_channelSpacings[m_nbChannelSpacings-1]; + } +} + +int NFMModSettings::getChannelSpacingIndex(int channelSpacing) +{ + for (int i = 0; i < m_nbChannelSpacings; i++) + { + if (channelSpacing <= m_channelSpacings[i]) { + return i; + } + } + + return m_nbChannelSpacings-1; +} + int NFMModSettings::getRFBW(int index) { if (index < 0) { return m_rfBW[0]; - } else if (index < m_nbRfBW) { + } else if (index < m_nbChannelSpacings) { return m_rfBW[index]; } else { - return m_rfBW[m_nbRfBW-1]; + return m_rfBW[m_nbChannelSpacings-1]; } } int NFMModSettings::getRFBWIndex(int rfbw) { - for (int i = 0; i < m_nbRfBW; i++) + for (int i = 0; i < m_nbChannelSpacings; i++) { - if (rfbw <= m_rfBW[i]) - { + if (rfbw <= m_rfBW[i]) { return i; } } - return m_nbRfBW-1; + return m_nbChannelSpacings-1; +} + +int NFMModSettings::getAFBW(int index) +{ + if (index < 0) { + return m_afBW[0]; + } else if (index < m_nbChannelSpacings) { + return m_afBW[index]; + } else { + return m_afBW[m_nbChannelSpacings-1]; + } +} + +int NFMModSettings::getAFBWIndex(int afbw) +{ + for (int i = 0; i < m_nbChannelSpacings; i++) + { + if (afbw <= m_afBW[i]) { + return i; + } + } + + return m_nbChannelSpacings-1; +} + +int NFMModSettings::getFMDev(int index) +{ + if (index < 0) { + return m_fmDev[0]; + } else if (index < m_nbChannelSpacings) { + return m_fmDev[index]; + } else { + return m_fmDev[m_nbChannelSpacings-1]; + } +} + +int NFMModSettings::getFMDevIndex(int fmDev) +{ + for (int i = 0; i < m_nbChannelSpacings; i++) + { + if (fmDev <= m_fmDev[i]) { + return i; + } + } + + return m_nbChannelSpacings-1; } int NFMModSettings::getNbCTCSSFreq() diff --git a/plugins/channeltx/modnfm/nfmmodsettings.h b/plugins/channeltx/modnfm/nfmmodsettings.h index 9a72a093f..2f55f9f16 100644 --- a/plugins/channeltx/modnfm/nfmmodsettings.h +++ b/plugins/channeltx/modnfm/nfmmodsettings.h @@ -35,8 +35,11 @@ struct NFMModSettings NFMModInputCWTone } NFMModInputAF; - static const int m_nbRfBW; + static const int m_nbChannelSpacings; + static const int m_channelSpacings[]; static const int m_rfBW[]; + static const int m_afBW[]; + static const int m_fmDev[]; qint64 m_inputFrequencyOffset; Real m_rfBandwidth; @@ -76,8 +79,14 @@ struct NFMModSettings const CWKeyerSettings& getCWKeyerSettings() const { return m_cwKeyerSettings; } void setCWKeyerSettings(const CWKeyerSettings& cwKeyerSettings) { m_cwKeyerSettings = cwKeyerSettings; } + static int getChannelSpacing(int index); + static int getChannelSpacingIndex(int channelSpacing); static int getRFBW(int index); static int getRFBWIndex(int rfbw); + static int getAFBW(int index); + static int getAFBWIndex(int afbw); + static int getFMDev(int index); + static int getFMDevIndex(int fmDev); static int getNbCTCSSFreq(); static float getCTCSSFreq(int index); static int getCTCSSFreqIndex(float ctcssFreq);