From 28bde131bad0c84ada9b67e017d75b289be416d0 Mon Sep 17 00:00:00 2001 From: Edouard Griffiths Date: Wed, 16 Dec 2015 21:12:12 +0100 Subject: [PATCH] NFM demod: adjust phase discriminator settings. Put in in a separate header --- CMakeLists.txt | 3 +- include/dsp/phasediscri.hpp | 50 ++++++++++++++++++++++++++++++++ plugins/channel/nfm/nfmdemod.cpp | 8 ++--- plugins/channel/nfm/nfmdemod.h | 29 +----------------- 4 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 include/dsp/phasediscri.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index cc40ba3a1..3b2c5eb1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,8 +167,9 @@ set(sdrbase_HEADERS include/dsp/misc.h include/dsp/movingaverage.h include/dsp/nco.h + include/dsp/phasediscri.hpp include/dsp/phaselock.h - sdrbase/dsp/pidcontroller.h + sdrbase/dsp/pidcontroller.h include/dsp/samplefifo.h include/dsp/samplesink.h include/dsp/nullsink.h diff --git a/include/dsp/phasediscri.hpp b/include/dsp/phasediscri.hpp new file mode 100644 index 000000000..b230001df --- /dev/null +++ b/include/dsp/phasediscri.hpp @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 F4EXB // +// written by Edouard Griffiths // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_DSP_PHASEDISCRI_H_ +#define INCLUDE_DSP_PHASEDISCRI_H_ + +/** + * Standard discriminator using atan2. On modern processors this is as efficient as the non atan2 one. + * This is better for high fidelity. + */ +Real phaseDiscriminator(const Complex& sample) +{ + Complex d(std::conj(m_m1Sample) * sample); + m_m1Sample = sample; + return (std::atan2(d.imag(), d.real()) / M_PI_2) * m_fmScaling; +} + +/** + * Alternative without atan at the expense of a slight distorsion on very wideband signals + * http://www.embedded.com/design/configurable-systems/4212086/DSP-Tricks--Frequency-demodulation-algorithms- + * in addition it needs scaling by instantaneous magnitude squared and volume (0..10) adjustment factor + */ +Real phaseDiscriminator2(const Complex& sample) +{ + Real ip = sample.real() - m_m2Sample.real(); + Real qp = sample.imag() - m_m2Sample.imag(); + Real h1 = m_m1Sample.real() * qp; + Real h2 = m_m1Sample.imag() * ip; + + m_m2Sample = m_m1Sample; + m_m1Sample = sample; + + return ((h1 - h2) / M_PI) * m_fmScaling; +} + +#endif /* INCLUDE_DSP_PHASEDISCRI_H_ */ diff --git a/plugins/channel/nfm/nfmdemod.cpp b/plugins/channel/nfm/nfmdemod.cpp index 9db1fab78..60f6aab58 100644 --- a/plugins/channel/nfm/nfmdemod.cpp +++ b/plugins/channel/nfm/nfmdemod.cpp @@ -38,8 +38,8 @@ NFMDemod::NFMDemod() : m_audioMute(false), m_afSquelch(2, afSqTones), m_audioFifo(4, 48000), - m_fmExcursion(4800), - m_fmScaling(384000/4800), + m_fmExcursion(2400), + m_fmScaling(384000/2400), m_settingsMutex(QMutex::Recursive) { setObjectName("NFMDemod"); @@ -141,7 +141,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto m_AGC.feed(ci); - Real demod = phaseDiscriminator2(ci, 0.5); + Real demod = phaseDiscriminator2(ci); m_m2Sample = m_m1Sample; m_m1Sample = ci; @@ -341,7 +341,7 @@ void NFMDemod::apply() m_settingsMutex.lock(); m_lowpass.create(301, m_config.m_audioSampleRate, 250.0); m_bandpass.create(301, m_config.m_audioSampleRate, 300.0, m_config.m_afBandwidth); - m_fmExcursion = m_config.m_afBandwidth; + m_fmExcursion = m_config.m_afBandwidth / 2.0f; m_fmScaling = m_config.m_inputSampleRate / m_fmExcursion; m_settingsMutex.unlock(); } diff --git a/plugins/channel/nfm/nfmdemod.h b/plugins/channel/nfm/nfmdemod.h index 9ca596c18..f739d24ad 100644 --- a/plugins/channel/nfm/nfmdemod.h +++ b/plugins/channel/nfm/nfmdemod.h @@ -188,34 +188,7 @@ private: NFMDemodGUI *m_nfmDemodGUI; QMutex m_settingsMutex; - /** - * Standard discriminator using atan2. On modern processors this is as efficient as the non atan2 one. - * This is better for high fidelity. - */ - Real phaseDiscriminator(const Complex& sample) - { - Complex d(std::conj(m_m1Sample) * sample); - m_m1Sample = sample; - return (std::atan2(d.imag(), d.real()) / M_PI_2) * m_fmScaling; - } - - /** - * Alternative without atan at the expense of a slight distorsion on very wideband signals - * http://www.embedded.com/design/configurable-systems/4212086/DSP-Tricks--Frequency-demodulation-algorithms- - * in addition it needs scaling by instantaneous magnitude squared and volume (0..10) adjustment factor - */ - Real phaseDiscriminator2(const Complex& sample, Real msq) - { - Real ip = sample.real() - m_m2Sample.real(); - Real qp = sample.imag() - m_m2Sample.imag(); - Real h1 = m_m1Sample.real() * qp; - Real h2 = m_m1Sample.imag() * ip; - - m_m2Sample = m_m1Sample; - m_m1Sample = sample; - - return ((h1 - h2) / (msq * M_PI)) * m_fmScaling; - } +#include "dsp/phasediscri.hpp" void apply(); };