From 6e3795d3d0a1365ff8a61ab3528ba437934a5a2d Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 21 Mar 2023 11:33:49 +0000 Subject: [PATCH] Move Morse demod to separate class to share with ILS. --- plugins/channelrx/demodvor/vordemod.cpp | 7 +- plugins/channelrx/demodvor/vordemodgui.cpp | 4 +- plugins/channelrx/demodvor/vordemodreport.cpp | 2 +- plugins/channelrx/demodvor/vordemodreport.h | 21 --- .../channelrx/demodvor/vordemodsettings.cpp | 2 + plugins/channelrx/demodvor/vordemodsink.cpp | 139 ++---------------- plugins/channelrx/demodvor/vordemodsink.h | 21 +-- 7 files changed, 22 insertions(+), 174 deletions(-) diff --git a/plugins/channelrx/demodvor/vordemod.cpp b/plugins/channelrx/demodvor/vordemod.cpp index 38388bc4b..571deda73 100644 --- a/plugins/channelrx/demodvor/vordemod.cpp +++ b/plugins/channelrx/demodvor/vordemod.cpp @@ -34,6 +34,7 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" +#include "dsp/morsedemod.h" #include "device/deviceapi.h" #include "feature/feature.h" #include "settings/serializable.h" @@ -215,14 +216,14 @@ bool VORDemod::handleMessage(const Message& cmd) return true; } - else if (VORDemodReport::MsgReportIdent::match(cmd)) + else if (MorseDemod::MsgReportIdent::match(cmd)) { - VORDemodReport::MsgReportIdent& report = (VORDemodReport::MsgReportIdent&) cmd; + MorseDemod::MsgReportIdent& report = (MorseDemod::MsgReportIdent&) cmd; m_morseIdent = report.getIdent(); if (m_guiMessageQueue) { - VORDemodReport::MsgReportIdent *msg = new VORDemodReport::MsgReportIdent(report); + MorseDemod::MsgReportIdent *msg = new MorseDemod::MsgReportIdent(report); m_guiMessageQueue->push(msg); } diff --git a/plugins/channelrx/demodvor/vordemodgui.cpp b/plugins/channelrx/demodvor/vordemodgui.cpp index f4c23927b..e11f6e609 100644 --- a/plugins/channelrx/demodvor/vordemodgui.cpp +++ b/plugins/channelrx/demodvor/vordemodgui.cpp @@ -136,9 +136,9 @@ bool VORDemodGUI::handleMessage(const Message& message) return true; } - else if (VORDemodReport::MsgReportIdent::match(message)) + else if (MorseDemod::MsgReportIdent::match(message)) { - VORDemodReport::MsgReportIdent& report = (VORDemodReport::MsgReportIdent&) message; + MorseDemod::MsgReportIdent& report = (MorseDemod::MsgReportIdent&) message; QString ident = report.getIdent(); QString identString = Morse::toString(ident); // Convert Morse to a string diff --git a/plugins/channelrx/demodvor/vordemodreport.cpp b/plugins/channelrx/demodvor/vordemodreport.cpp index 96fcbc7f6..48169e9a6 100644 --- a/plugins/channelrx/demodvor/vordemodreport.cpp +++ b/plugins/channelrx/demodvor/vordemodreport.cpp @@ -18,4 +18,4 @@ #include "vordemodreport.h" MESSAGE_CLASS_DEFINITION(VORDemodReport::MsgReportRadial, Message) -MESSAGE_CLASS_DEFINITION(VORDemodReport::MsgReportIdent, Message) + diff --git a/plugins/channelrx/demodvor/vordemodreport.h b/plugins/channelrx/demodvor/vordemodreport.h index 8a053620d..1d07468d3 100644 --- a/plugins/channelrx/demodvor/vordemodreport.h +++ b/plugins/channelrx/demodvor/vordemodreport.h @@ -53,27 +53,6 @@ public: } }; - class MsgReportIdent : public Message { - MESSAGE_CLASS_DECLARATION - - public: - QString getIdent() const { return m_ident; } - - static MsgReportIdent* create(QString ident) - { - return new MsgReportIdent(ident); - } - - private: - QString m_ident; - - MsgReportIdent(QString ident) : - Message(), - m_ident(ident) - { - } - }; - public: VORDemodReport() {} ~VORDemodReport() {} diff --git a/plugins/channelrx/demodvor/vordemodsettings.cpp b/plugins/channelrx/demodvor/vordemodsettings.cpp index 9c12911ce..2107e0974 100644 --- a/plugins/channelrx/demodvor/vordemodsettings.cpp +++ b/plugins/channelrx/demodvor/vordemodsettings.cpp @@ -62,6 +62,7 @@ QByteArray VORDemodSettings::serialize() const s.writeS32(3, m_streamIndex); s.writeS32(4, m_volume*10); s.writeS32(5, m_squelch); + s.writeBool(10, m_audioMute); if (m_channelMarker) { s.writeBlob(6, m_channelMarker->serialize()); @@ -114,6 +115,7 @@ bool VORDemodSettings::deserialize(const QByteArray& data) m_volume = tmp * 0.1; d.readS32(5, &tmp, -40); m_squelch = tmp; + d.readBool(10, &m_audioMute, false); if (m_channelMarker) { diff --git a/plugins/channelrx/demodvor/vordemodsink.cpp b/plugins/channelrx/demodvor/vordemodsink.cpp index a346bea85..18b9e2153 100644 --- a/plugins/channelrx/demodvor/vordemodsink.cpp +++ b/plugins/channelrx/demodvor/vordemodsink.cpp @@ -44,9 +44,6 @@ VORDemodSCSink::VORDemodSCSink() : m_volumeAGC(0.003), m_audioFifo(48000), m_refPrev(0.0f), - m_movingAverageIdent(5000), - m_prevBit(0), - m_bitTime(0), m_varGoertzel(30, VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE), m_refGoertzel(30, VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE) { @@ -249,104 +246,14 @@ void VORDemodSCSink::processOneSample(Complex &ci) else m_refGoertzel.filter(phi); - // Ident demod - // Filter to remove voice - Complex c1 = m_bandpassIdent.filter(magc); - // Remove ident sub-carrier offset - c1 *= m_ncoIdent.nextIQ(); - // Filter other signals - Complex c2 = std::abs(m_lowpassIdent.filter(c1)); + // Decode Morse ident + m_morseDemod.processOneSample(magc); +} - // Filter noise with moving average (moving average preserves edges) - m_movingAverageIdent(c2.real()); - Real mav = m_movingAverageIdent.asFloat(); - - // Caclulate noise floor - if (mav > m_identMaxs[m_binCnt]) - m_identMaxs[m_binCnt] = mav; - m_binSampleCnt++; - if (m_binSampleCnt >= m_samplesPerDot10wpm/4) - { - // Calc minimum of maximums - m_identNoise = 1.0f; - for (int i = 0; i < m_identBins; i++) - { - m_identNoise = std::min(m_identNoise, m_identMaxs[i]); - } - m_binSampleCnt = 0; - m_binCnt++; - if (m_binCnt == m_identBins) - m_binCnt = 0; - m_identMaxs[m_binCnt] = 0.0f; - - // Prevent divide by zero - if (m_identNoise == 0.0f) - m_identNoise = 1e-20f; - } - - // CW demod - int bit = (mav / m_identNoise) >= m_settings.m_identThreshold; - //m_stream << mav << "," << m_identNoise << "," << bit << "," << (mav / m_identNoise) << "\n"; - if ((m_prevBit == 0) && (bit == 1)) - { - if (m_bitTime > 7*m_samplesPerDot10wpm) - { - if (m_ident.trimmed().size() > 2) // Filter out noise that may appear as one or two characters - { - qDebug() << "VORDemodSCSink::processOneSample:" << m_ident << " " << Morse::toString(m_ident); - - if (getMessageQueueToChannel()) - { - VORDemodReport::MsgReportIdent *msg = VORDemodReport::MsgReportIdent::create(m_ident); - getMessageQueueToChannel()->push(msg); - } - } - m_ident = ""; - } - else if (m_bitTime > 2.5*m_samplesPerDot10wpm) - { - m_ident.append(" "); - } - m_bitTime = 0; - } - else if (bit == 1) - { - m_bitTime++; - } - else if ((m_prevBit == 1) && (bit == 0)) - { - if (m_bitTime > 2*m_samplesPerDot10wpm) - { - m_ident.append("-"); - } - else if (m_bitTime > 0.2*m_samplesPerDot10wpm) - { - m_ident.append("."); - } - m_bitTime = 0; - } - else - { - m_bitTime++; - if (m_bitTime > 10*m_samplesPerDot7wpm) - { - m_ident = m_ident.simplified(); - if (m_ident.trimmed().size() > 2) // Filter out noise that may appear as one or two characters - { - qDebug() << "VORDemodSCSink::processOneSample:" << m_ident << " " << Morse::toString(m_ident); - - if (getMessageQueueToChannel()) - { - VORDemodReport::MsgReportIdent *msg = VORDemodReport::MsgReportIdent::create(m_ident); - getMessageQueueToChannel()->push(msg); - } - - } - m_ident = ""; - m_bitTime = 0; - } - } - m_prevBit = bit; +void VORDemodSCSink::setMessageQueueToChannel(MessageQueue *messageQueue) +{ + m_messageQueueToChannel = messageQueue; + m_morseDemod.setMessageQueueToChannel(messageQueue); } void VORDemodSCSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force) @@ -367,30 +274,10 @@ void VORDemodSCSink::applyChannelSettings(int channelSampleRate, int channelFreq m_interpolatorDistanceRemain = 0; m_interpolatorDistance = (Real) channelSampleRate / (Real) VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE; - m_samplesPerDot7wpm = VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE*60/(50*7); - m_samplesPerDot10wpm = VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE*60/(50*10); - - m_ncoIdent.setFreq(-1020, VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE); // +-50Hz source offset allowed m_ncoRef.setFreq(-9960, VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE); - m_bandpassIdent.create(1001, VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE, 970.0f, 1070.0f); // Ident at 1020 - //m_bandpassIdent.printTaps("bpf"); - m_highpassIdent.create(1001, VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE, 900.0f); - //m_highpassIdent.printTaps("hpf"); - //m_file.setFileName("morse.txt"); - //m_file.open(QIODevice::WriteOnly); - //m_stream.setDevice(&m_file); - - m_lowpassIdent.create(301, VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE, 100.0f); m_lowpassRef.create(301, VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE, 600.0f); // Max deviation is 480Hz - m_movingAverageIdent.resize(m_samplesPerDot10wpm/5); // Needs to be short enough for noise floor calculation - m_binSampleCnt = 0; - m_binCnt = 0; - m_identNoise = 0.0001f; - for (int i = 0; i < m_identBins; i++) - { - m_identMaxs[i] = 0.0f; - } + m_morseDemod.applyChannelSettings(VORDemodSettings::VORDEMOD_CHANNEL_SAMPLE_RATE); } m_channelSampleRate = channelSampleRate; @@ -414,14 +301,7 @@ void VORDemodSCSink::applySettings(const VORDemodSettings& settings, bool force) if (m_settings.m_navId != settings.m_navId) { // Reset state when navId changes, so we don't report old ident for new navId - m_binSampleCnt = 0; - m_binCnt = 0; - m_identNoise = 0.0001f; - for (int i = 0; i < m_identBins; i++) - { - m_identMaxs[i] = 0.0f; - } - m_ident = ""; + m_morseDemod.reset(); m_refGoertzel.reset(); m_varGoertzel.reset(); } @@ -437,6 +317,7 @@ void VORDemodSCSink::applySettings(const VORDemodSettings& settings, bool force) } m_settings = settings; + m_morseDemod.applySettings(m_settings.m_identThreshold); } void VORDemodSCSink::applyAudioSampleRate(int sampleRate) diff --git a/plugins/channelrx/demodvor/vordemodsink.h b/plugins/channelrx/demodvor/vordemodsink.h index 2266dffe0..782c87fe2 100644 --- a/plugins/channelrx/demodvor/vordemodsink.h +++ b/plugins/channelrx/demodvor/vordemodsink.h @@ -25,6 +25,7 @@ #include "dsp/agc.h" #include "dsp/firfilter.h" #include "dsp/goertzel.h" +#include "dsp/morsedemod.h" #include "audio/audiofifo.h" #include "util/movingaverage.h" #include "util/doublebufferfifo.h" @@ -43,7 +44,7 @@ public: void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false); void applySettings(const VORDemodSettings& settings, bool force = false); - void setMessageQueueToChannel(MessageQueue *messageQueue) { m_messageQueueToChannel = messageQueue; } + void setMessageQueueToChannel(MessageQueue *messageQueue); void applyAudioSampleRate(int sampleRate); int getAudioSampleRate() const { return m_audioSampleRate; } @@ -116,28 +117,12 @@ private: AudioFifo m_audioFifo; uint32_t m_audioBufferFill; - NCO m_ncoIdent; NCO m_ncoRef; Lowpass m_lowpassRef; - Bandpass m_bandpassIdent; - Lowpass m_lowpassIdent; - Highpass m_highpassIdent; Complex m_refPrev; - MovingAverageUtilVar m_movingAverageIdent; - static const int m_identBins = 20; - Real m_identMaxs[m_identBins]; - Real m_identNoise; - int m_binSampleCnt; - int m_binCnt; - int m_samplesPerDot7wpm; - int m_samplesPerDot10wpm; - int m_prevBit; - int m_bitTime; - QString m_ident; Goertzel m_varGoertzel; Goertzel m_refGoertzel; - //QFile m_file; - //QTextStream m_stream; + MorseDemod m_morseDemod; void processOneSample(Complex &ci); void processOneAudioSample(Complex &ci);