1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-09-28 15:56:33 -04:00

Move Morse demod to separate class to share with ILS.

This commit is contained in:
Jon Beniston 2023-03-21 11:33:49 +00:00
parent 8201bfba20
commit 6e3795d3d0
7 changed files with 22 additions and 174 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -18,4 +18,4 @@
#include "vordemodreport.h"
MESSAGE_CLASS_DEFINITION(VORDemodReport::MsgReportRadial, Message)
MESSAGE_CLASS_DEFINITION(VORDemodReport::MsgReportIdent, Message)

View File

@ -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() {}

View File

@ -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)
{

View File

@ -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)

View File

@ -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<Complex> m_lowpassRef;
Bandpass<Complex> m_bandpassIdent;
Lowpass<Complex> m_lowpassIdent;
Highpass<Real> m_highpassIdent;
Complex m_refPrev;
MovingAverageUtilVar<Real, double> 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);