From 775a9775ebb47a5ed33f0978565f54bee8da48a7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 22 May 2018 02:20:36 +0200 Subject: [PATCH] Channel analyzer NG: implemented optional RRC filter --- .../channelrx/chanalyzerng/chanalyzerng.cpp | 26 ++++++++-- plugins/channelrx/chanalyzerng/chanalyzerng.h | 1 + .../chanalyzerng/chanalyzernggui.cpp | 17 ++++++ .../channelrx/chanalyzerng/chanalyzernggui.h | 2 + .../channelrx/chanalyzerng/chanalyzernggui.ui | 52 +++++++++++++++++++ .../chanalyzerng/chanalyzerngsettings.cpp | 6 +++ .../chanalyzerng/chanalyzerngsettings.h | 2 + sdrbase/dsp/fftfilt.h | 2 +- 8 files changed, 104 insertions(+), 4 deletions(-) diff --git a/plugins/channelrx/chanalyzerng/chanalyzerng.cpp b/plugins/channelrx/chanalyzerng/chanalyzerng.cpp index 148e53959..958c59b63 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerng.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzerng.cpp @@ -52,6 +52,7 @@ ChannelAnalyzerNG::ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI) : m_inputFrequencyOffset = 0; SSBFilter = new fftfilt(m_settings.m_lowCutoff / m_inputSampleRate, m_settings.m_bandwidth / m_inputSampleRate, ssbFftLen); DSBFilter = new fftfilt(m_settings.m_bandwidth / m_inputSampleRate, 2*ssbFftLen); + RRCFilter = new fftfilt(m_settings.m_bandwidth / m_inputSampleRate, 2*ssbFftLen); m_corr = new fftcorr(8*ssbFftLen); // 8k for 4k effective samples m_pll.computeCoefficients(0.002f, 0.5f, 10.0f); // bandwidth, damping factor, loop gain @@ -72,6 +73,7 @@ ChannelAnalyzerNG::~ChannelAnalyzerNG() delete m_channelizer; delete SSBFilter; delete DSBFilter; + delete RRCFilter; } void ChannelAnalyzerNG::configure(MessageQueue* messageQueue, @@ -129,10 +131,17 @@ void ChannelAnalyzerNG::processOneSample(Complex& c, fftfilt::cmplx *sideband) int n_out; int decim = 1<runSSB(c, &sideband, m_usb); - } else { - n_out = DSBFilter->runDSB(c, &sideband); + } + else + { + if (m_settings.m_rrc) { + n_out = RRCFilter->runFilt(c, &sideband); + } else { + n_out = DSBFilter->runDSB(c, &sideband); + } } for (int i = 0; i < n_out; i++) @@ -293,6 +302,7 @@ void ChannelAnalyzerNG::setFilters(int sampleRate, float bandwidth, float lowCut SSBFilter->create_filter(lowCutoff / sampleRate, bandwidth / sampleRate); DSBFilter->create_dsb_filter(bandwidth / sampleRate); + RRCFilter->create_rrc_filter(bandwidth / sampleRate, m_settings.m_rrcRolloff / 100.0); } void ChannelAnalyzerNG::applySettings(const ChannelAnalyzerNGSettings& settings, bool force) @@ -300,6 +310,8 @@ void ChannelAnalyzerNG::applySettings(const ChannelAnalyzerNGSettings& settings, qDebug() << "ChannelAnalyzerNG::applySettings:" << " m_downSample: " << settings.m_downSample << " m_downSampleRate: " << settings.m_downSampleRate + << " m_rcc: " << settings.m_rrc + << " m_rrcRolloff: " << settings.m_rrcRolloff / 100.0 << " m_bandwidth: " << settings.m_bandwidth << " m_lowCutoff: " << settings.m_lowCutoff << " m_spanLog2: " << settings.m_spanLog2 @@ -338,6 +350,14 @@ void ChannelAnalyzerNG::applySettings(const ChannelAnalyzerNGSettings& settings, m_settingsMutex.unlock(); } + if ((settings.m_rrcRolloff != m_settings.m_rrcRolloff) || force) + { + float sampleRate = settings.m_downSample ? (float) settings.m_downSampleRate : (float) m_inputSampleRate; + m_settingsMutex.lock(); + RRCFilter->create_rrc_filter(settings.m_bandwidth / sampleRate, settings.m_rrcRolloff / 100.0); + m_settingsMutex.unlock(); + } + if ((settings.m_spanLog2 != m_settings.m_spanLog2) || force) { int sampleRate = (settings.m_downSample ? settings.m_downSampleRate : m_inputSampleRate) / (1<spanLog2->setCurrentIndex(m_settings.m_spanLog2); displayPLLSettings(); ui->signalSelect->setCurrentIndex((int) m_settings.m_inputType); + ui->rrcFilter->setChecked(m_settings.m_rrc); + QString rolloffStr = QString::number(m_settings.m_rrcRolloff/100.0, 'f', 2); + ui->rrcRolloffText->setText(rolloffStr); blockApplySettings(false); } @@ -291,6 +294,20 @@ void ChannelAnalyzerNGGUI::on_deltaFrequency_changed(qint64 value) applySettings(); } +void ChannelAnalyzerNGGUI::on_rrcFilter_toggled(bool checked) +{ + m_settings.m_rrc = checked; + applySettings(); +} + +void ChannelAnalyzerNGGUI::on_rrcRolloff_valueChanged(int value) +{ + m_settings.m_rrcRolloff = value; + QString rolloffStr = QString::number(value/100.0, 'f', 2); + ui->rrcRolloffText->setText(rolloffStr); + applySettings(); +} + void ChannelAnalyzerNGGUI::on_BW_valueChanged(int value __attribute__((unused))) { setFiltersUIBoundaries(); diff --git a/plugins/channelrx/chanalyzerng/chanalyzernggui.h b/plugins/channelrx/chanalyzerng/chanalyzernggui.h index fb68d20eb..c19a10ec4 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzernggui.h +++ b/plugins/channelrx/chanalyzerng/chanalyzernggui.h @@ -99,6 +99,8 @@ private slots: void on_pllPskOrder_currentIndexChanged(int index); void on_useRationalDownsampler_toggled(bool checked); void on_signalSelect_currentIndexChanged(int index); + void on_rrcFilter_toggled(bool checked); + void on_rrcRolloff_valueChanged(int value); void on_BW_valueChanged(int value); void on_lowCut_valueChanged(int value); void on_spanLog2_currentIndexChanged(int index); diff --git a/plugins/channelrx/chanalyzerng/chanalyzernggui.ui b/plugins/channelrx/chanalyzerng/chanalyzernggui.ui index ecee494a2..0765ef73a 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzernggui.ui +++ b/plugins/channelrx/chanalyzerng/chanalyzernggui.ui @@ -419,6 +419,58 @@ + + + + Toggle RRC filter + + + + + + + :/dsb.png:/dsb.png + + + true + + + + + + + + 24 + 24 + + + + Tune RRC filter rolloff factor + + + 10 + + + 50 + + + 1 + + + 30 + + + + + + + RRC filter rolloff factor value + + + 0.00 + + + diff --git a/plugins/channelrx/chanalyzerng/chanalyzerngsettings.cpp b/plugins/channelrx/chanalyzerng/chanalyzerngsettings.cpp index bac4e1286..20ec8bf75 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerngsettings.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzerngsettings.cpp @@ -40,6 +40,8 @@ void ChannelAnalyzerNGSettings::resetToDefaults() m_ssb = false; m_pll = false; m_fll = false; + m_rrc = false; + m_rrcRolloff = 30; // 0.3 m_pllPskOrder = 1; m_inputType = InputSignal; m_rgbColor = QColor(128, 128, 128).rgb(); @@ -65,6 +67,8 @@ QByteArray ChannelAnalyzerNGSettings::serialize() const s.writeU32(13, m_pllPskOrder); s.writeS32(14, (int) m_inputType); s.writeString(15, m_title); + s.writeBool(16, m_rrc); + s.writeU32(17, m_rrcRolloff); return s.final(); } @@ -110,6 +114,8 @@ bool ChannelAnalyzerNGSettings::deserialize(const QByteArray& data) d.readS32(14, &tmp, 0); m_inputType = (InputType) tmp; d.readString(15, &m_title, "Channel Analyzer NG"); + d.readBool(16, &m_rrc, false); + d.readU32(17, &m_rrcRolloff, 30); return true; } diff --git a/plugins/channelrx/chanalyzerng/chanalyzerngsettings.h b/plugins/channelrx/chanalyzerng/chanalyzerngsettings.h index 55a9ff42d..df37a5282 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerngsettings.h +++ b/plugins/channelrx/chanalyzerng/chanalyzerngsettings.h @@ -39,6 +39,8 @@ struct ChannelAnalyzerNGSettings bool m_ssb; bool m_pll; bool m_fll; + bool m_rrc; + quint32 m_rrcRolloff; //!< in 100ths unsigned int m_pllPskOrder; InputType m_inputType; quint32 m_rgbColor; diff --git a/sdrbase/dsp/fftfilt.h b/sdrbase/dsp/fftfilt.h index 3c98fb7eb..5c3e0222c 100644 --- a/sdrbase/dsp/fftfilt.h +++ b/sdrbase/dsp/fftfilt.h @@ -69,7 +69,7 @@ protected: { float x = i/(float)len; // normalize to [0..1] x = 0.5-fabs(x-0.5); // apply symmetry: now both halves overlap near 0 - float tr = (fb*a)/2.0; // half the transition zone + float tr = fb*a; // half the transition zone if (x < fb-tr) {