From 4ad038ed9d8f065d3efdcf444e2812a61580134f Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 8 Nov 2017 14:23:49 +0100 Subject: [PATCH] Created demod constructor method in all Rx channel plugins --- plugins/channelrx/chanalyzer/chanalyzer.cpp | 473 +++++++-------- plugins/channelrx/chanalyzer/chanalyzer.h | 310 +++++----- .../channelrx/chanalyzer/chanalyzergui.cpp | 4 +- plugins/channelrx/chanalyzer/chanalyzergui.h | 2 - .../channelrx/chanalyzer/chanalyzerplugin.cpp | 17 +- .../channelrx/chanalyzer/chanalyzerplugin.h | 2 + .../channelrx/chanalyzerng/chanalyzerng.cpp | 503 ++++++++-------- plugins/channelrx/chanalyzerng/chanalyzerng.h | 486 ++++++++-------- .../chanalyzerng/chanalyzernggui.cpp | 4 +- .../channelrx/chanalyzerng/chanalyzernggui.h | 2 - .../chanalyzerng/chanalyzerngplugin.cpp | 21 +- .../chanalyzerng/chanalyzerngplugin.h | 2 + plugins/channelrx/demodam/amdemod.cpp | 1 + plugins/channelrx/demodam/amdemod.h | 456 +++++++-------- plugins/channelrx/demodam/amdemodgui.cpp | 4 +- plugins/channelrx/demodam/amdemodgui.h | 2 - plugins/channelrx/demodam/amdemodplugin.cpp | 6 +- plugins/channelrx/demodatv/atvdemod.cpp | 1 + plugins/channelrx/demodatv/atvdemod.h | 2 + plugins/channelrx/demodatv/atvdemodgui.cpp | 4 +- plugins/channelrx/demodatv/atvdemodgui.h | 2 - plugins/channelrx/demodatv/atvdemodplugin.cpp | 19 +- plugins/channelrx/demodatv/atvdemodplugin.h | 2 + plugins/channelrx/demodbfm/bfmdemod.cpp | 1 + plugins/channelrx/demodbfm/bfmdemod.h | 440 +++++++------- plugins/channelrx/demodbfm/bfmdemodgui.cpp | 4 +- plugins/channelrx/demodbfm/bfmdemodgui.h | 2 - plugins/channelrx/demodbfm/bfmplugin.cpp | 17 +- plugins/channelrx/demodbfm/bfmplugin.h | 1 + plugins/channelrx/demoddsd/dsddemod.cpp | 1 + plugins/channelrx/demoddsd/dsddemod.h | 389 ++++++------- plugins/channelrx/demoddsd/dsddemodgui.cpp | 4 +- plugins/channelrx/demoddsd/dsddemodgui.h | 2 - plugins/channelrx/demoddsd/dsddemodplugin.cpp | 18 +- plugins/channelrx/demoddsd/dsddemodplugin.h | 2 + plugins/channelrx/demodlora/lorademod.cpp | 2 + plugins/channelrx/demodlora/lorademod.h | 2 + plugins/channelrx/demodlora/lorademodgui.cpp | 4 +- plugins/channelrx/demodlora/lorademodgui.h | 2 - plugins/channelrx/demodlora/loraplugin.cpp | 18 +- plugins/channelrx/demodlora/loraplugin.h | 2 + plugins/channelrx/demodnfm/nfmdemod.cpp | 2 + plugins/channelrx/demodnfm/nfmdemod.h | 2 + plugins/channelrx/demodnfm/nfmdemodgui.cpp | 4 +- plugins/channelrx/demodnfm/nfmdemodgui.h | 2 - plugins/channelrx/demodnfm/nfmplugin.cpp | 18 +- plugins/channelrx/demodnfm/nfmplugin.h | 2 + plugins/channelrx/demodssb/ssbdemod.cpp | 2 + plugins/channelrx/demodssb/ssbdemod.h | 542 +++++++++--------- plugins/channelrx/demodssb/ssbdemodgui.cpp | 4 +- plugins/channelrx/demodssb/ssbdemodgui.h | 2 - plugins/channelrx/demodssb/ssbplugin.cpp | 18 +- plugins/channelrx/demodssb/ssbplugin.h | 2 + plugins/channelrx/demodwfm/wfmdemod.cpp | 2 + plugins/channelrx/demodwfm/wfmdemod.h | 2 + plugins/channelrx/demodwfm/wfmdemodgui.cpp | 4 +- plugins/channelrx/demodwfm/wfmdemodgui.h | 2 - plugins/channelrx/demodwfm/wfmplugin.cpp | 18 +- plugins/channelrx/demodwfm/wfmplugin.h | 2 + plugins/channelrx/tcpsrc/tcpsrc.cpp | 2 + plugins/channelrx/tcpsrc/tcpsrc.h | 2 + plugins/channelrx/tcpsrc/tcpsrcgui.cpp | 4 +- plugins/channelrx/tcpsrc/tcpsrcgui.h | 2 - plugins/channelrx/tcpsrc/tcpsrcplugin.cpp | 18 +- plugins/channelrx/tcpsrc/tcpsrcplugin.h | 2 + plugins/channelrx/udpsrc/udpsrc.cpp | 2 + plugins/channelrx/udpsrc/udpsrc.h | 1 + plugins/channelrx/udpsrc/udpsrcgui.cpp | 4 +- plugins/channelrx/udpsrc/udpsrcgui.h | 2 - plugins/channelrx/udpsrc/udpsrcplugin.cpp | 16 +- plugins/channelrx/udpsrc/udpsrcplugin.h | 2 + 71 files changed, 2036 insertions(+), 1887 deletions(-) diff --git a/plugins/channelrx/chanalyzer/chanalyzer.cpp b/plugins/channelrx/chanalyzer/chanalyzer.cpp index d7c42629f..70c2adf17 100644 --- a/plugins/channelrx/chanalyzer/chanalyzer.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzer.cpp @@ -1,236 +1,237 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2015 Edouard Griffiths, F4EXB // -// // -// 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 . // -/////////////////////////////////////////////////////////////////////////////////// - -#include "chanalyzer.h" - -#include -#include -#include - -#include -#include "dsp/threadedbasebandsamplesink.h" -#include "device/devicesourceapi.h" -#include "audio/audiooutput.h" - - -MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgConfigureChannelAnalyzer, Message) -MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgConfigureChannelizer, Message) -MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgReportChannelSampleRateChanged, Message) - -ChannelAnalyzer::ChannelAnalyzer(DeviceSourceAPI *deviceAPI) : - m_deviceAPI(deviceAPI), - m_sampleSink(0), - m_settingsMutex(QMutex::Recursive) -{ - m_Bandwidth = 5000; - m_LowCutoff = 300; - m_spanLog2 = 3; - m_sampleRate = 96000; - m_frequency = 0; - m_nco.setFreq(m_frequency, m_sampleRate); - m_undersampleCount = 0; - m_sum = 0; - m_usb = true; - m_ssb = true; - m_magsq = 0; - SSBFilter = new fftfilt(m_LowCutoff / m_sampleRate, m_Bandwidth / m_sampleRate, ssbFftLen); - DSBFilter = new fftfilt(m_Bandwidth / m_sampleRate, 2*ssbFftLen); - - m_channelizer = new DownChannelizer(this); - m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); - connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged())); - m_deviceAPI->addThreadedSink(m_threadedChannelizer); -} - -ChannelAnalyzer::~ChannelAnalyzer() -{ - if (SSBFilter) delete SSBFilter; - if (DSBFilter) delete DSBFilter; - m_deviceAPI->removeThreadedSink(m_threadedChannelizer); - delete m_threadedChannelizer; - delete m_channelizer; -} - -void ChannelAnalyzer::configure(MessageQueue* messageQueue, - Real Bandwidth, - Real LowCutoff, - int spanLog2, - bool ssb) -{ - Message* cmd = MsgConfigureChannelAnalyzer::create(Bandwidth, LowCutoff, spanLog2, ssb); - messageQueue->push(cmd); -} - -void ChannelAnalyzer::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused))) -{ - fftfilt::cmplx *sideband; - int n_out; - int decim = 1<real() / 32768.0f, it->imag() / 32768.0f); - Complex c(it->real(), it->imag()); - c *= m_nco.nextIQ(); - - if (m_ssb) - { - n_out = SSBFilter->runSSB(c, &sideband, m_usb); - } - else - { - n_out = DSBFilter->runDSB(c, &sideband); - } - - for (int i = 0; i < n_out; i++) - { - // Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display - // smart decimation with bit gain using float arithmetic (23 bits significand) - - m_sum += sideband[i]; - - if (!(m_undersampleCount++ & decim_mask)) - { - m_sum /= decim; - m_magsq = (m_sum.real() * m_sum.real() + m_sum.imag() * m_sum.imag())/ (1<<30); - - if (m_ssb & !m_usb) - { // invert spectrum for LSB - //m_sampleBuffer.push_back(Sample(m_sum.imag() * 32768.0, m_sum.real() * 32768.0)); - m_sampleBuffer.push_back(Sample(m_sum.imag(), m_sum.real())); - } - else - { - //m_sampleBuffer.push_back(Sample(m_sum.real() * 32768.0, m_sum.imag() * 32768.0)); - m_sampleBuffer.push_back(Sample(m_sum.real(), m_sum.imag())); - } - - m_sum = 0; - } - } - } - - if(m_sampleSink != NULL) - { - m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), m_ssb); // m_ssb = positive only - } - - m_sampleBuffer.clear(); - - m_settingsMutex.unlock(); -} - -void ChannelAnalyzer::start() -{ -} - -void ChannelAnalyzer::stop() -{ -} - -void ChannelAnalyzer::channelSampleRateChanged() -{ - MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create(); - getMessageQueueToGUI()->push(msg); -} - -bool ChannelAnalyzer::handleMessage(const Message& cmd) -{ - float band, lowCutoff; - - qDebug() << "ChannelAnalyzer::handleMessage"; - - if (DownChannelizer::MsgChannelizerNotification::match(cmd)) - { - DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; - - m_sampleRate = notif.getSampleRate(); - m_nco.setFreq(-notif.getFrequencyOffset(), m_sampleRate); - - qDebug() << "ChannelAnalyzer::handleMessage: MsgChannelizerNotification: m_sampleRate: " << m_sampleRate - << " frequencyOffset: " << notif.getFrequencyOffset(); - - return true; - } - else if (MsgConfigureChannelizer::match(cmd)) - { - MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; - - m_channelizer->configure(m_channelizer->getInputMessageQueue(), - m_channelizer->getInputSampleRate(), - cfg.getCenterFrequency()); - - return true; - } - else if (MsgConfigureChannelAnalyzer::match(cmd)) - { - MsgConfigureChannelAnalyzer& cfg = (MsgConfigureChannelAnalyzer&) cmd; - - band = cfg.getBandwidth(); - lowCutoff = cfg.getLoCutoff(); - - if (band < 0) - { - band = -band; - lowCutoff = -lowCutoff; - m_usb = false; - } - else - { - m_usb = true; - } - - if (band < 100.0f) - { - band = 100.0f; - lowCutoff = 0; - } - - m_settingsMutex.lock(); - - m_Bandwidth = band; - m_LowCutoff = lowCutoff; - - SSBFilter->create_filter(m_LowCutoff / m_sampleRate, m_Bandwidth / m_sampleRate); - DSBFilter->create_dsb_filter(m_Bandwidth / m_sampleRate); - - m_spanLog2 = cfg.getSpanLog2(); - m_ssb = cfg.getSSB(); - - m_settingsMutex.unlock(); - - qDebug() << " - MsgConfigureChannelAnalyzer: m_Bandwidth: " << m_Bandwidth - << " m_LowCutoff: " << m_LowCutoff - << " m_spanLog2: " << m_spanLog2 - << " m_ssb: " << m_ssb; - - return true; - } - else - { - if (m_sampleSink != 0) - { - return m_sampleSink->handleMessage(cmd); - } - else - { - return false; - } - } -} +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 Edouard Griffiths, F4EXB // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "chanalyzer.h" + +#include +#include +#include + +#include +#include "dsp/threadedbasebandsamplesink.h" +#include "device/devicesourceapi.h" +#include "audio/audiooutput.h" + +MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgConfigureChannelAnalyzer, Message) +MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgConfigureChannelizer, Message) +MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgReportChannelSampleRateChanged, Message) + +const QString ChannelAnalyzer::m_channelID = "org.f4exb.sdrangelove.channel.chanalyzer"; + +ChannelAnalyzer::ChannelAnalyzer(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_sampleSink(0), + m_settingsMutex(QMutex::Recursive) +{ + m_Bandwidth = 5000; + m_LowCutoff = 300; + m_spanLog2 = 3; + m_sampleRate = 96000; + m_frequency = 0; + m_nco.setFreq(m_frequency, m_sampleRate); + m_undersampleCount = 0; + m_sum = 0; + m_usb = true; + m_ssb = true; + m_magsq = 0; + SSBFilter = new fftfilt(m_LowCutoff / m_sampleRate, m_Bandwidth / m_sampleRate, ssbFftLen); + DSBFilter = new fftfilt(m_Bandwidth / m_sampleRate, 2*ssbFftLen); + + m_channelizer = new DownChannelizer(this); + m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); + connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged())); + m_deviceAPI->addThreadedSink(m_threadedChannelizer); +} + +ChannelAnalyzer::~ChannelAnalyzer() +{ + if (SSBFilter) delete SSBFilter; + if (DSBFilter) delete DSBFilter; + m_deviceAPI->removeThreadedSink(m_threadedChannelizer); + delete m_threadedChannelizer; + delete m_channelizer; +} + +void ChannelAnalyzer::configure(MessageQueue* messageQueue, + Real Bandwidth, + Real LowCutoff, + int spanLog2, + bool ssb) +{ + Message* cmd = MsgConfigureChannelAnalyzer::create(Bandwidth, LowCutoff, spanLog2, ssb); + messageQueue->push(cmd); +} + +void ChannelAnalyzer::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused))) +{ + fftfilt::cmplx *sideband; + int n_out; + int decim = 1<real() / 32768.0f, it->imag() / 32768.0f); + Complex c(it->real(), it->imag()); + c *= m_nco.nextIQ(); + + if (m_ssb) + { + n_out = SSBFilter->runSSB(c, &sideband, m_usb); + } + else + { + n_out = DSBFilter->runDSB(c, &sideband); + } + + for (int i = 0; i < n_out; i++) + { + // Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display + // smart decimation with bit gain using float arithmetic (23 bits significand) + + m_sum += sideband[i]; + + if (!(m_undersampleCount++ & decim_mask)) + { + m_sum /= decim; + m_magsq = (m_sum.real() * m_sum.real() + m_sum.imag() * m_sum.imag())/ (1<<30); + + if (m_ssb & !m_usb) + { // invert spectrum for LSB + //m_sampleBuffer.push_back(Sample(m_sum.imag() * 32768.0, m_sum.real() * 32768.0)); + m_sampleBuffer.push_back(Sample(m_sum.imag(), m_sum.real())); + } + else + { + //m_sampleBuffer.push_back(Sample(m_sum.real() * 32768.0, m_sum.imag() * 32768.0)); + m_sampleBuffer.push_back(Sample(m_sum.real(), m_sum.imag())); + } + + m_sum = 0; + } + } + } + + if(m_sampleSink != NULL) + { + m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), m_ssb); // m_ssb = positive only + } + + m_sampleBuffer.clear(); + + m_settingsMutex.unlock(); +} + +void ChannelAnalyzer::start() +{ +} + +void ChannelAnalyzer::stop() +{ +} + +void ChannelAnalyzer::channelSampleRateChanged() +{ + MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create(); + getMessageQueueToGUI()->push(msg); +} + +bool ChannelAnalyzer::handleMessage(const Message& cmd) +{ + float band, lowCutoff; + + qDebug() << "ChannelAnalyzer::handleMessage"; + + if (DownChannelizer::MsgChannelizerNotification::match(cmd)) + { + DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; + + m_sampleRate = notif.getSampleRate(); + m_nco.setFreq(-notif.getFrequencyOffset(), m_sampleRate); + + qDebug() << "ChannelAnalyzer::handleMessage: MsgChannelizerNotification: m_sampleRate: " << m_sampleRate + << " frequencyOffset: " << notif.getFrequencyOffset(); + + return true; + } + else if (MsgConfigureChannelizer::match(cmd)) + { + MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; + + m_channelizer->configure(m_channelizer->getInputMessageQueue(), + m_channelizer->getInputSampleRate(), + cfg.getCenterFrequency()); + + return true; + } + else if (MsgConfigureChannelAnalyzer::match(cmd)) + { + MsgConfigureChannelAnalyzer& cfg = (MsgConfigureChannelAnalyzer&) cmd; + + band = cfg.getBandwidth(); + lowCutoff = cfg.getLoCutoff(); + + if (band < 0) + { + band = -band; + lowCutoff = -lowCutoff; + m_usb = false; + } + else + { + m_usb = true; + } + + if (band < 100.0f) + { + band = 100.0f; + lowCutoff = 0; + } + + m_settingsMutex.lock(); + + m_Bandwidth = band; + m_LowCutoff = lowCutoff; + + SSBFilter->create_filter(m_LowCutoff / m_sampleRate, m_Bandwidth / m_sampleRate); + DSBFilter->create_dsb_filter(m_Bandwidth / m_sampleRate); + + m_spanLog2 = cfg.getSpanLog2(); + m_ssb = cfg.getSSB(); + + m_settingsMutex.unlock(); + + qDebug() << " - MsgConfigureChannelAnalyzer: m_Bandwidth: " << m_Bandwidth + << " m_LowCutoff: " << m_LowCutoff + << " m_spanLog2: " << m_spanLog2 + << " m_ssb: " << m_ssb; + + return true; + } + else + { + if (m_sampleSink != 0) + { + return m_sampleSink->handleMessage(cmd); + } + else + { + return false; + } + } +} diff --git a/plugins/channelrx/chanalyzer/chanalyzer.h b/plugins/channelrx/chanalyzer/chanalyzer.h index 7dd26732f..4c333c7a9 100644 --- a/plugins/channelrx/chanalyzer/chanalyzer.h +++ b/plugins/channelrx/chanalyzer/chanalyzer.h @@ -1,154 +1,156 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2015 Edouard Griffiths, F4EXB // -// // -// 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_CHANALYZER_H -#define INCLUDE_CHANALYZER_H - -#include -#include -#include -#include "dsp/ncof.h" -#include "dsp/fftfilt.h" -#include "audio/audiofifo.h" -#include "util/message.h" - -#define ssbFftLen 1024 - -class DeviceSourceAPI; -class ThreadedBasebandSampleSink; -class DownChannelizer; - -class ChannelAnalyzer : public BasebandSampleSink { -public: - class MsgConfigureChannelAnalyzer : public Message { - MESSAGE_CLASS_DECLARATION - - public: - Real getBandwidth() const { return m_Bandwidth; } - Real getLoCutoff() const { return m_LowCutoff; } - int getSpanLog2() const { return m_spanLog2; } - bool getSSB() const { return m_ssb; } - - static MsgConfigureChannelAnalyzer* create(Real Bandwidth, - Real LowCutoff, - int spanLog2, - bool ssb) - { - return new MsgConfigureChannelAnalyzer(Bandwidth, LowCutoff, spanLog2, ssb); - } - - private: - Real m_Bandwidth; - Real m_LowCutoff; - int m_spanLog2; - bool m_ssb; - - MsgConfigureChannelAnalyzer(Real Bandwidth, - Real LowCutoff, - int spanLog2, - bool ssb) : - Message(), - m_Bandwidth(Bandwidth), - m_LowCutoff(LowCutoff), - m_spanLog2(spanLog2), - m_ssb(ssb) - { } - }; - - class MsgConfigureChannelizer : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getCenterFrequency() const { return m_centerFrequency; } - - static MsgConfigureChannelizer* create(int centerFrequency) - { - return new MsgConfigureChannelizer(centerFrequency); - } - - private: - int m_centerFrequency; - - MsgConfigureChannelizer(int centerFrequency) : - Message(), - m_centerFrequency(centerFrequency) - { } - }; - - class MsgReportChannelSampleRateChanged : public Message { - MESSAGE_CLASS_DECLARATION - - public: - - static MsgReportChannelSampleRateChanged* create() - { - return new MsgReportChannelSampleRateChanged(); - } - - private: - - MsgReportChannelSampleRateChanged() : - Message() - { } - }; - - ChannelAnalyzer(DeviceSourceAPI *deviceAPI); - virtual ~ChannelAnalyzer(); - void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; } - - void configure(MessageQueue* messageQueue, - Real Bandwidth, - Real LowCutoff, - int spanLog2, - bool ssb); - - int getSampleRate() const { return m_sampleRate; } - Real getMagSq() const { return m_magsq; } - - virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); - virtual void start(); - virtual void stop(); - virtual bool handleMessage(const Message& cmd); - -private slots: - void channelSampleRateChanged(); - -private: - DeviceSourceAPI *m_deviceAPI; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; - - Real m_Bandwidth; - Real m_LowCutoff; - int m_spanLog2; - int m_undersampleCount; - fftfilt::cmplx m_sum; - int m_sampleRate; - int m_frequency; - bool m_usb; - bool m_ssb; - Real m_magsq; - - NCOF m_nco; - fftfilt* SSBFilter; - fftfilt* DSBFilter; - - BasebandSampleSink* m_sampleSink; - SampleVector m_sampleBuffer; - QMutex m_settingsMutex; -}; - -#endif // INCLUDE_CHANALYZER_H +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 Edouard Griffiths, F4EXB // +// // +// 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_CHANALYZER_H +#define INCLUDE_CHANALYZER_H + +#include +#include +#include +#include "dsp/ncof.h" +#include "dsp/fftfilt.h" +#include "audio/audiofifo.h" +#include "util/message.h" + +#define ssbFftLen 1024 + +class DeviceSourceAPI; +class ThreadedBasebandSampleSink; +class DownChannelizer; + +class ChannelAnalyzer : public BasebandSampleSink { +public: + class MsgConfigureChannelAnalyzer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + Real getBandwidth() const { return m_Bandwidth; } + Real getLoCutoff() const { return m_LowCutoff; } + int getSpanLog2() const { return m_spanLog2; } + bool getSSB() const { return m_ssb; } + + static MsgConfigureChannelAnalyzer* create(Real Bandwidth, + Real LowCutoff, + int spanLog2, + bool ssb) + { + return new MsgConfigureChannelAnalyzer(Bandwidth, LowCutoff, spanLog2, ssb); + } + + private: + Real m_Bandwidth; + Real m_LowCutoff; + int m_spanLog2; + bool m_ssb; + + MsgConfigureChannelAnalyzer(Real Bandwidth, + Real LowCutoff, + int spanLog2, + bool ssb) : + Message(), + m_Bandwidth(Bandwidth), + m_LowCutoff(LowCutoff), + m_spanLog2(spanLog2), + m_ssb(ssb) + { } + }; + + class MsgConfigureChannelizer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getCenterFrequency() const { return m_centerFrequency; } + + static MsgConfigureChannelizer* create(int centerFrequency) + { + return new MsgConfigureChannelizer(centerFrequency); + } + + private: + int m_centerFrequency; + + MsgConfigureChannelizer(int centerFrequency) : + Message(), + m_centerFrequency(centerFrequency) + { } + }; + + class MsgReportChannelSampleRateChanged : public Message { + MESSAGE_CLASS_DECLARATION + + public: + + static MsgReportChannelSampleRateChanged* create() + { + return new MsgReportChannelSampleRateChanged(); + } + + private: + + MsgReportChannelSampleRateChanged() : + Message() + { } + }; + + ChannelAnalyzer(DeviceSourceAPI *deviceAPI); + virtual ~ChannelAnalyzer(); + void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; } + + void configure(MessageQueue* messageQueue, + Real Bandwidth, + Real LowCutoff, + int spanLog2, + bool ssb); + + int getSampleRate() const { return m_sampleRate; } + Real getMagSq() const { return m_magsq; } + + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); + virtual void start(); + virtual void stop(); + virtual bool handleMessage(const Message& cmd); + + static const QString m_channelID; + +private slots: + void channelSampleRateChanged(); + +private: + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; + + Real m_Bandwidth; + Real m_LowCutoff; + int m_spanLog2; + int m_undersampleCount; + fftfilt::cmplx m_sum; + int m_sampleRate; + int m_frequency; + bool m_usb; + bool m_ssb; + Real m_magsq; + + NCOF m_nco; + fftfilt* SSBFilter; + fftfilt* DSBFilter; + + BasebandSampleSink* m_sampleSink; + SampleVector m_sampleBuffer; + QMutex m_settingsMutex; +}; + +#endif // INCLUDE_CHANALYZER_H diff --git a/plugins/channelrx/chanalyzer/chanalyzergui.cpp b/plugins/channelrx/chanalyzer/chanalyzergui.cpp index 107f8e1ee..f31599742 100644 --- a/plugins/channelrx/chanalyzer/chanalyzergui.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzergui.cpp @@ -38,8 +38,6 @@ #include "chanalyzer.h" -const QString ChannelAnalyzerGUI::m_channelID = "org.f4exb.sdrangelove.channel.chanalyzer"; - ChannelAnalyzerGUI* ChannelAnalyzerGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { ChannelAnalyzerGUI* gui = new ChannelAnalyzerGUI(pluginAPI, deviceUISet); @@ -370,7 +368,7 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceUISet *device connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(ChannelAnalyzer::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/chanalyzer/chanalyzergui.h b/plugins/channelrx/chanalyzer/chanalyzergui.h index a56f91a2d..476ff3c71 100644 --- a/plugins/channelrx/chanalyzer/chanalyzergui.h +++ b/plugins/channelrx/chanalyzer/chanalyzergui.h @@ -55,8 +55,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void viewChanged(); void on_deltaFrequency_changed(quint64 value); diff --git a/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp b/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp index 97f370c8e..bf772dd0c 100644 --- a/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp @@ -4,6 +4,7 @@ #include "plugin/pluginapi.h" #include "chanalyzergui.h" +#include "chanalyzer.h" const PluginDescriptor ChannelAnalyzerPlugin::m_pluginDescriptor = { QString("Channel Analyzer"), @@ -30,12 +31,12 @@ void ChannelAnalyzerPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register demodulator - m_pluginAPI->registerRxChannel(ChannelAnalyzerGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(ChannelAnalyzer::m_channelID, this); } PluginInstanceGUI* ChannelAnalyzerPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == ChannelAnalyzerGUI::m_channelID) + if(channelName == ChannelAnalyzer::m_channelID) { ChannelAnalyzerGUI* gui = ChannelAnalyzerGUI::create(m_pluginAPI, deviceUISet); return gui; @@ -43,3 +44,15 @@ PluginInstanceGUI* ChannelAnalyzerPlugin::createRxChannelGUI(const QString& chan return NULL; } } + + +BasebandSampleSink* ChannelAnalyzerPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == ChannelAnalyzer::m_channelID) + { + ChannelAnalyzer* sink = new ChannelAnalyzer(deviceAPI); + return sink; + } else { + return 0; + } +} diff --git a/plugins/channelrx/chanalyzer/chanalyzerplugin.h b/plugins/channelrx/chanalyzer/chanalyzerplugin.h index 267393132..20624353f 100644 --- a/plugins/channelrx/chanalyzer/chanalyzerplugin.h +++ b/plugins/channelrx/chanalyzer/chanalyzerplugin.h @@ -5,6 +5,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class ChannelAnalyzerPlugin : public QObject, PluginInterface { Q_OBJECT @@ -18,6 +19,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/chanalyzerng/chanalyzerng.cpp b/plugins/channelrx/chanalyzerng/chanalyzerng.cpp index ddfa63fc3..5bbd82369 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerng.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzerng.cpp @@ -1,251 +1,252 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017 Edouard Griffiths, F4EXB // -// // -// 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 . // -/////////////////////////////////////////////////////////////////////////////////// - -#include "chanalyzerng.h" - -#include -#include -#include - -#include "device/devicesourceapi.h" -#include "audio/audiooutput.h" -#include "dsp/threadedbasebandsamplesink.h" -#include "dsp/downchannelizer.h" - - -MESSAGE_CLASS_DEFINITION(ChannelAnalyzerNG::MsgConfigureChannelAnalyzer, Message) -MESSAGE_CLASS_DEFINITION(ChannelAnalyzerNG::MsgConfigureChannelizer, Message) -MESSAGE_CLASS_DEFINITION(ChannelAnalyzerNG::MsgReportChannelSampleRateChanged, Message) - -ChannelAnalyzerNG::ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI) : - m_deviceAPI(deviceAPI), - m_sampleSink(0), - m_settingsMutex(QMutex::Recursive) -{ - m_undersampleCount = 0; - m_sum = 0; - m_usb = true; - m_magsq = 0; - m_useInterpolator = false; - m_interpolatorDistance = 1.0f; - m_interpolatorDistanceRemain = 0.0f; - SSBFilter = new fftfilt(m_config.m_LowCutoff / m_config.m_inputSampleRate, m_config.m_Bandwidth / m_config.m_inputSampleRate, ssbFftLen); - DSBFilter = new fftfilt(m_config.m_Bandwidth / m_config.m_inputSampleRate, 2*ssbFftLen); - - m_channelizer = new DownChannelizer(this); - m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); - connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelizerInputSampleRateChanged())); - m_deviceAPI->addThreadedSink(m_threadedChannelizer); - - apply(true); -} - -ChannelAnalyzerNG::~ChannelAnalyzerNG() -{ - if (SSBFilter) delete SSBFilter; - if (DSBFilter) delete DSBFilter; - m_deviceAPI->removeThreadedSink(m_threadedChannelizer); - delete m_threadedChannelizer; - delete m_channelizer; -} - -void ChannelAnalyzerNG::configure(MessageQueue* messageQueue, - int channelSampleRate, - Real Bandwidth, - Real LowCutoff, - int spanLog2, - bool ssb) -{ - Message* cmd = MsgConfigureChannelAnalyzer::create(channelSampleRate, Bandwidth, LowCutoff, spanLog2, ssb); - messageQueue->push(cmd); -} - -void ChannelAnalyzerNG::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused))) -{ - fftfilt::cmplx *sideband = 0; - Complex ci; - - m_settingsMutex.lock(); - - for(SampleVector::const_iterator it = begin; it < end; ++it) - { - Complex c(it->real(), it->imag()); - c *= m_nco.nextIQ(); - - if (m_useInterpolator) - { - if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) - { - processOneSample(ci, sideband); - m_interpolatorDistanceRemain += m_interpolatorDistance; - } - } - else - { - processOneSample(c, sideband); - } - } - - if(m_sampleSink != 0) - { - m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), m_running.m_ssb); // m_ssb = positive only - } - - m_sampleBuffer.clear(); - - m_settingsMutex.unlock(); -} - -void ChannelAnalyzerNG::start() -{ -} - -void ChannelAnalyzerNG::stop() -{ -} - -void ChannelAnalyzerNG::channelizerInputSampleRateChanged() -{ - MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create(); - getMessageQueueToGUI()->push(msg); -} - -bool ChannelAnalyzerNG::handleMessage(const Message& cmd) -{ - qDebug() << "ChannelAnalyzerNG::handleMessage: " << cmd.getIdentifier(); - - if (DownChannelizer::MsgChannelizerNotification::match(cmd)) - { - DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; - - m_config.m_inputSampleRate = notif.getSampleRate(); - m_config.m_frequency = notif.getFrequencyOffset(); - - qDebug() << "ChannelAnalyzerNG::handleMessage: MsgChannelizerNotification:" - << " m_sampleRate: " << m_config.m_inputSampleRate - << " frequencyOffset: " << m_config.m_frequency; - - apply(); - return true; - } - else if (MsgConfigureChannelizer::match(cmd)) - { - MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; - m_channelizer->configure(m_channelizer->getInputMessageQueue(), - cfg.getSampleRate(), - cfg.getCenterFrequency()); - return true; - } - else if (MsgConfigureChannelAnalyzer::match(cmd)) - { - MsgConfigureChannelAnalyzer& cfg = (MsgConfigureChannelAnalyzer&) cmd; - - m_config.m_channelSampleRate = cfg.getChannelSampleRate(); - m_config.m_Bandwidth = cfg.getBandwidth(); - m_config.m_LowCutoff = cfg.getLoCutoff(); - m_config.m_spanLog2 = cfg.getSpanLog2(); - m_config.m_ssb = cfg.getSSB(); - - qDebug() << "ChannelAnalyzerNG::handleMessage: MsgConfigureChannelAnalyzer:" - << " m_channelSampleRate: " << m_config.m_channelSampleRate - << " m_Bandwidth: " << m_config.m_Bandwidth - << " m_LowCutoff: " << m_config.m_LowCutoff - << " m_spanLog2: " << m_config.m_spanLog2 - << " m_ssb: " << m_config.m_ssb; - - apply(); - return true; - } - else - { - if (m_sampleSink != 0) - { - return m_sampleSink->handleMessage(cmd); - } - else - { - return false; - } - } -} - - - -void ChannelAnalyzerNG::apply(bool force) -{ - if ((m_running.m_frequency != m_config.m_frequency) || - (m_running.m_inputSampleRate != m_config.m_inputSampleRate) || - force) - { - m_nco.setFreq(-m_config.m_frequency, m_config.m_inputSampleRate); - } - - if ((m_running.m_inputSampleRate != m_config.m_inputSampleRate) || - (m_running.m_channelSampleRate != m_config.m_channelSampleRate) || - force) - { - m_settingsMutex.lock(); - m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_inputSampleRate / 2.2); - m_interpolatorDistanceRemain = 0.0f; - m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_channelSampleRate; - m_useInterpolator = (m_config.m_inputSampleRate != m_config.m_channelSampleRate); // optim - m_settingsMutex.unlock(); - } - - if ((m_running.m_channelSampleRate != m_config.m_channelSampleRate) || - (m_running.m_Bandwidth != m_config.m_Bandwidth) || - (m_running.m_LowCutoff != m_config.m_LowCutoff) || - force) - { - float bandwidth = m_config.m_Bandwidth; - float lowCutoff = m_config.m_LowCutoff; - - if (bandwidth < 0) - { - bandwidth = -bandwidth; - lowCutoff = -lowCutoff; - m_usb = false; - } - else - { - m_usb = true; - } - - if (bandwidth < 100.0f) - { - bandwidth = 100.0f; - lowCutoff = 0; - } - - m_settingsMutex.lock(); - - SSBFilter->create_filter(lowCutoff / m_config.m_channelSampleRate, bandwidth / m_config.m_channelSampleRate); - DSBFilter->create_dsb_filter(bandwidth / m_config.m_channelSampleRate); - - m_settingsMutex.unlock(); - } - - m_running.m_frequency = m_config.m_frequency; - m_running.m_channelSampleRate = m_config.m_channelSampleRate; - m_running.m_inputSampleRate = m_config.m_inputSampleRate; - m_running.m_Bandwidth = m_config.m_Bandwidth; - m_running.m_LowCutoff = m_config.m_LowCutoff; - - //m_settingsMutex.lock(); - m_running.m_spanLog2 = m_config.m_spanLog2; - m_running.m_ssb = m_config.m_ssb; - //m_settingsMutex.unlock(); -} +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "chanalyzerng.h" + +#include +#include +#include + +#include "device/devicesourceapi.h" +#include "audio/audiooutput.h" +#include "dsp/threadedbasebandsamplesink.h" +#include "dsp/downchannelizer.h" + +MESSAGE_CLASS_DEFINITION(ChannelAnalyzerNG::MsgConfigureChannelAnalyzer, Message) +MESSAGE_CLASS_DEFINITION(ChannelAnalyzerNG::MsgConfigureChannelizer, Message) +MESSAGE_CLASS_DEFINITION(ChannelAnalyzerNG::MsgReportChannelSampleRateChanged, Message) + +const QString ChannelAnalyzerNG::m_channelID = "sdrangel.channel.chanalyzerng"; + +ChannelAnalyzerNG::ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_sampleSink(0), + m_settingsMutex(QMutex::Recursive) +{ + m_undersampleCount = 0; + m_sum = 0; + m_usb = true; + m_magsq = 0; + m_useInterpolator = false; + m_interpolatorDistance = 1.0f; + m_interpolatorDistanceRemain = 0.0f; + SSBFilter = new fftfilt(m_config.m_LowCutoff / m_config.m_inputSampleRate, m_config.m_Bandwidth / m_config.m_inputSampleRate, ssbFftLen); + DSBFilter = new fftfilt(m_config.m_Bandwidth / m_config.m_inputSampleRate, 2*ssbFftLen); + + m_channelizer = new DownChannelizer(this); + m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); + connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelizerInputSampleRateChanged())); + m_deviceAPI->addThreadedSink(m_threadedChannelizer); + + apply(true); +} + +ChannelAnalyzerNG::~ChannelAnalyzerNG() +{ + if (SSBFilter) delete SSBFilter; + if (DSBFilter) delete DSBFilter; + m_deviceAPI->removeThreadedSink(m_threadedChannelizer); + delete m_threadedChannelizer; + delete m_channelizer; +} + +void ChannelAnalyzerNG::configure(MessageQueue* messageQueue, + int channelSampleRate, + Real Bandwidth, + Real LowCutoff, + int spanLog2, + bool ssb) +{ + Message* cmd = MsgConfigureChannelAnalyzer::create(channelSampleRate, Bandwidth, LowCutoff, spanLog2, ssb); + messageQueue->push(cmd); +} + +void ChannelAnalyzerNG::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused))) +{ + fftfilt::cmplx *sideband = 0; + Complex ci; + + m_settingsMutex.lock(); + + for(SampleVector::const_iterator it = begin; it < end; ++it) + { + Complex c(it->real(), it->imag()); + c *= m_nco.nextIQ(); + + if (m_useInterpolator) + { + if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci, sideband); + m_interpolatorDistanceRemain += m_interpolatorDistance; + } + } + else + { + processOneSample(c, sideband); + } + } + + if(m_sampleSink != 0) + { + m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), m_running.m_ssb); // m_ssb = positive only + } + + m_sampleBuffer.clear(); + + m_settingsMutex.unlock(); +} + +void ChannelAnalyzerNG::start() +{ +} + +void ChannelAnalyzerNG::stop() +{ +} + +void ChannelAnalyzerNG::channelizerInputSampleRateChanged() +{ + MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create(); + getMessageQueueToGUI()->push(msg); +} + +bool ChannelAnalyzerNG::handleMessage(const Message& cmd) +{ + qDebug() << "ChannelAnalyzerNG::handleMessage: " << cmd.getIdentifier(); + + if (DownChannelizer::MsgChannelizerNotification::match(cmd)) + { + DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; + + m_config.m_inputSampleRate = notif.getSampleRate(); + m_config.m_frequency = notif.getFrequencyOffset(); + + qDebug() << "ChannelAnalyzerNG::handleMessage: MsgChannelizerNotification:" + << " m_sampleRate: " << m_config.m_inputSampleRate + << " frequencyOffset: " << m_config.m_frequency; + + apply(); + return true; + } + else if (MsgConfigureChannelizer::match(cmd)) + { + MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; + m_channelizer->configure(m_channelizer->getInputMessageQueue(), + cfg.getSampleRate(), + cfg.getCenterFrequency()); + return true; + } + else if (MsgConfigureChannelAnalyzer::match(cmd)) + { + MsgConfigureChannelAnalyzer& cfg = (MsgConfigureChannelAnalyzer&) cmd; + + m_config.m_channelSampleRate = cfg.getChannelSampleRate(); + m_config.m_Bandwidth = cfg.getBandwidth(); + m_config.m_LowCutoff = cfg.getLoCutoff(); + m_config.m_spanLog2 = cfg.getSpanLog2(); + m_config.m_ssb = cfg.getSSB(); + + qDebug() << "ChannelAnalyzerNG::handleMessage: MsgConfigureChannelAnalyzer:" + << " m_channelSampleRate: " << m_config.m_channelSampleRate + << " m_Bandwidth: " << m_config.m_Bandwidth + << " m_LowCutoff: " << m_config.m_LowCutoff + << " m_spanLog2: " << m_config.m_spanLog2 + << " m_ssb: " << m_config.m_ssb; + + apply(); + return true; + } + else + { + if (m_sampleSink != 0) + { + return m_sampleSink->handleMessage(cmd); + } + else + { + return false; + } + } +} + + + +void ChannelAnalyzerNG::apply(bool force) +{ + if ((m_running.m_frequency != m_config.m_frequency) || + (m_running.m_inputSampleRate != m_config.m_inputSampleRate) || + force) + { + m_nco.setFreq(-m_config.m_frequency, m_config.m_inputSampleRate); + } + + if ((m_running.m_inputSampleRate != m_config.m_inputSampleRate) || + (m_running.m_channelSampleRate != m_config.m_channelSampleRate) || + force) + { + m_settingsMutex.lock(); + m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_inputSampleRate / 2.2); + m_interpolatorDistanceRemain = 0.0f; + m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_channelSampleRate; + m_useInterpolator = (m_config.m_inputSampleRate != m_config.m_channelSampleRate); // optim + m_settingsMutex.unlock(); + } + + if ((m_running.m_channelSampleRate != m_config.m_channelSampleRate) || + (m_running.m_Bandwidth != m_config.m_Bandwidth) || + (m_running.m_LowCutoff != m_config.m_LowCutoff) || + force) + { + float bandwidth = m_config.m_Bandwidth; + float lowCutoff = m_config.m_LowCutoff; + + if (bandwidth < 0) + { + bandwidth = -bandwidth; + lowCutoff = -lowCutoff; + m_usb = false; + } + else + { + m_usb = true; + } + + if (bandwidth < 100.0f) + { + bandwidth = 100.0f; + lowCutoff = 0; + } + + m_settingsMutex.lock(); + + SSBFilter->create_filter(lowCutoff / m_config.m_channelSampleRate, bandwidth / m_config.m_channelSampleRate); + DSBFilter->create_dsb_filter(bandwidth / m_config.m_channelSampleRate); + + m_settingsMutex.unlock(); + } + + m_running.m_frequency = m_config.m_frequency; + m_running.m_channelSampleRate = m_config.m_channelSampleRate; + m_running.m_inputSampleRate = m_config.m_inputSampleRate; + m_running.m_Bandwidth = m_config.m_Bandwidth; + m_running.m_LowCutoff = m_config.m_LowCutoff; + + //m_settingsMutex.lock(); + m_running.m_spanLog2 = m_config.m_spanLog2; + m_running.m_ssb = m_config.m_ssb; + //m_settingsMutex.unlock(); +} diff --git a/plugins/channelrx/chanalyzerng/chanalyzerng.h b/plugins/channelrx/chanalyzerng/chanalyzerng.h index bee680725..000222cb8 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerng.h +++ b/plugins/channelrx/chanalyzerng/chanalyzerng.h @@ -1,242 +1,244 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017 Edouard Griffiths, F4EXB // -// // -// 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_CHANALYZERNG_H -#define INCLUDE_CHANALYZERNG_H - -#include -#include -#include - -#include "dsp/interpolator.h" -#include "dsp/ncof.h" -#include "dsp/fftfilt.h" -#include "audio/audiofifo.h" -#include "util/message.h" - -#define ssbFftLen 1024 - -class DeviceSourceAPI; -class ThreadedBasebandSampleSink; -class DownChannelizer; - -class ChannelAnalyzerNG : public BasebandSampleSink { -public: - class MsgConfigureChannelAnalyzer : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getChannelSampleRate() const { return m_channelSampleRate; } - Real getBandwidth() const { return m_Bandwidth; } - Real getLoCutoff() const { return m_LowCutoff; } - int getSpanLog2() const { return m_spanLog2; } - bool getSSB() const { return m_ssb; } - - static MsgConfigureChannelAnalyzer* create( - int channelSampleRate, - Real Bandwidth, - Real LowCutoff, - int spanLog2, - bool ssb) - { - return new MsgConfigureChannelAnalyzer( - channelSampleRate, - Bandwidth, - LowCutoff, - spanLog2, - ssb); - } - - private: - int m_channelSampleRate; - Real m_Bandwidth; - Real m_LowCutoff; - int m_spanLog2; - bool m_ssb; - - MsgConfigureChannelAnalyzer( - int channelSampleRate, - Real Bandwidth, - Real LowCutoff, - int spanLog2, - bool ssb) : - Message(), - m_channelSampleRate(channelSampleRate), - m_Bandwidth(Bandwidth), - m_LowCutoff(LowCutoff), - m_spanLog2(spanLog2), - m_ssb(ssb) - { } - }; - - class MsgConfigureChannelizer : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getSampleRate() const { return m_sampleRate; } - int getCenterFrequency() const { return m_centerFrequency; } - - static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) - { - return new MsgConfigureChannelizer(sampleRate, centerFrequency); - } - - private: - int m_sampleRate; - int m_centerFrequency; - - MsgConfigureChannelizer(int sampleRate, int centerFrequency) : - Message(), - m_sampleRate(sampleRate), - m_centerFrequency(centerFrequency) - { } - }; - - class MsgReportChannelSampleRateChanged : public Message { - MESSAGE_CLASS_DECLARATION - - public: - - static MsgReportChannelSampleRateChanged* create() - { - return new MsgReportChannelSampleRateChanged(); - } - - private: - - MsgReportChannelSampleRateChanged() : - Message() - { } - }; - - ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI); - virtual ~ChannelAnalyzerNG(); - void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; } - - void configure(MessageQueue* messageQueue, - int channelSampleRate, - Real Bandwidth, - Real LowCutoff, - int spanLog2, - bool ssb); - - DownChannelizer *getChannelizer() { return m_channelizer; } - int getInputSampleRate() const { return m_running.m_inputSampleRate; } - int getChannelSampleRate() const { return m_running.m_channelSampleRate; } - double getMagSq() const { return m_magsq; } - - virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); - virtual void start(); - virtual void stop(); - virtual bool handleMessage(const Message& cmd); - -private slots: - void channelizerInputSampleRateChanged(); - -private: - - struct Config - { - int m_frequency; - int m_inputSampleRate; - int m_channelSampleRate; - Real m_Bandwidth; - Real m_LowCutoff; - int m_spanLog2; - bool m_ssb; - - Config() : - m_frequency(0), - m_inputSampleRate(96000), - m_channelSampleRate(96000), - m_Bandwidth(5000), - m_LowCutoff(300), - m_spanLog2(3), - m_ssb(false) - {} - }; - - Config m_config; - Config m_running; - - DeviceSourceAPI *m_deviceAPI; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; - - int m_undersampleCount; - fftfilt::cmplx m_sum; - bool m_usb; - double m_magsq; - bool m_useInterpolator; - - NCOF m_nco; - Interpolator m_interpolator; - Real m_interpolatorDistance; - Real m_interpolatorDistanceRemain; - - fftfilt* SSBFilter; - fftfilt* DSBFilter; - - BasebandSampleSink* m_sampleSink; - SampleVector m_sampleBuffer; - QMutex m_settingsMutex; - - void apply(bool force = false); - - void processOneSample(Complex& c, fftfilt::cmplx *sideband) - { - int n_out; - int decim = 1<runSSB(c, &sideband, m_usb); - } - else - { - n_out = DSBFilter->runDSB(c, &sideband); - } - - for (int i = 0; i < n_out; i++) - { - // Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display - // smart decimation with bit gain using float arithmetic (23 bits significand) - - m_sum += sideband[i]; - - if (!(m_undersampleCount++ & (decim - 1))) // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1) - { - m_sum /= decim; - m_magsq = (m_sum.real() * m_sum.real() + m_sum.imag() * m_sum.imag())/ (1<<30); - - if (m_running.m_ssb & !m_usb) - { // invert spectrum for LSB - //m_sampleBuffer.push_back(Sample(m_sum.imag() * 32768.0, m_sum.real() * 32768.0)); - m_sampleBuffer.push_back(Sample(m_sum.imag(), m_sum.real())); - } - else - { - //m_sampleBuffer.push_back(Sample(m_sum.real() * 32768.0, m_sum.imag() * 32768.0)); - m_sampleBuffer.push_back(Sample(m_sum.real(), m_sum.imag())); - } - - m_sum = 0; - } - } - } -}; - -#endif // INCLUDE_CHANALYZERNG_H +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB // +// // +// 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_CHANALYZERNG_H +#define INCLUDE_CHANALYZERNG_H + +#include +#include +#include + +#include "dsp/interpolator.h" +#include "dsp/ncof.h" +#include "dsp/fftfilt.h" +#include "audio/audiofifo.h" +#include "util/message.h" + +#define ssbFftLen 1024 + +class DeviceSourceAPI; +class ThreadedBasebandSampleSink; +class DownChannelizer; + +class ChannelAnalyzerNG : public BasebandSampleSink { +public: + class MsgConfigureChannelAnalyzer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getChannelSampleRate() const { return m_channelSampleRate; } + Real getBandwidth() const { return m_Bandwidth; } + Real getLoCutoff() const { return m_LowCutoff; } + int getSpanLog2() const { return m_spanLog2; } + bool getSSB() const { return m_ssb; } + + static MsgConfigureChannelAnalyzer* create( + int channelSampleRate, + Real Bandwidth, + Real LowCutoff, + int spanLog2, + bool ssb) + { + return new MsgConfigureChannelAnalyzer( + channelSampleRate, + Bandwidth, + LowCutoff, + spanLog2, + ssb); + } + + private: + int m_channelSampleRate; + Real m_Bandwidth; + Real m_LowCutoff; + int m_spanLog2; + bool m_ssb; + + MsgConfigureChannelAnalyzer( + int channelSampleRate, + Real Bandwidth, + Real LowCutoff, + int spanLog2, + bool ssb) : + Message(), + m_channelSampleRate(channelSampleRate), + m_Bandwidth(Bandwidth), + m_LowCutoff(LowCutoff), + m_spanLog2(spanLog2), + m_ssb(ssb) + { } + }; + + class MsgConfigureChannelizer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + int getCenterFrequency() const { return m_centerFrequency; } + + static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) + { + return new MsgConfigureChannelizer(sampleRate, centerFrequency); + } + + private: + int m_sampleRate; + int m_centerFrequency; + + MsgConfigureChannelizer(int sampleRate, int centerFrequency) : + Message(), + m_sampleRate(sampleRate), + m_centerFrequency(centerFrequency) + { } + }; + + class MsgReportChannelSampleRateChanged : public Message { + MESSAGE_CLASS_DECLARATION + + public: + + static MsgReportChannelSampleRateChanged* create() + { + return new MsgReportChannelSampleRateChanged(); + } + + private: + + MsgReportChannelSampleRateChanged() : + Message() + { } + }; + + ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI); + virtual ~ChannelAnalyzerNG(); + void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; } + + void configure(MessageQueue* messageQueue, + int channelSampleRate, + Real Bandwidth, + Real LowCutoff, + int spanLog2, + bool ssb); + + DownChannelizer *getChannelizer() { return m_channelizer; } + int getInputSampleRate() const { return m_running.m_inputSampleRate; } + int getChannelSampleRate() const { return m_running.m_channelSampleRate; } + double getMagSq() const { return m_magsq; } + + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); + virtual void start(); + virtual void stop(); + virtual bool handleMessage(const Message& cmd); + + static const QString m_channelID; + +private slots: + void channelizerInputSampleRateChanged(); + +private: + + struct Config + { + int m_frequency; + int m_inputSampleRate; + int m_channelSampleRate; + Real m_Bandwidth; + Real m_LowCutoff; + int m_spanLog2; + bool m_ssb; + + Config() : + m_frequency(0), + m_inputSampleRate(96000), + m_channelSampleRate(96000), + m_Bandwidth(5000), + m_LowCutoff(300), + m_spanLog2(3), + m_ssb(false) + {} + }; + + Config m_config; + Config m_running; + + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; + + int m_undersampleCount; + fftfilt::cmplx m_sum; + bool m_usb; + double m_magsq; + bool m_useInterpolator; + + NCOF m_nco; + Interpolator m_interpolator; + Real m_interpolatorDistance; + Real m_interpolatorDistanceRemain; + + fftfilt* SSBFilter; + fftfilt* DSBFilter; + + BasebandSampleSink* m_sampleSink; + SampleVector m_sampleBuffer; + QMutex m_settingsMutex; + + void apply(bool force = false); + + void processOneSample(Complex& c, fftfilt::cmplx *sideband) + { + int n_out; + int decim = 1<runSSB(c, &sideband, m_usb); + } + else + { + n_out = DSBFilter->runDSB(c, &sideband); + } + + for (int i = 0; i < n_out; i++) + { + // Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display + // smart decimation with bit gain using float arithmetic (23 bits significand) + + m_sum += sideband[i]; + + if (!(m_undersampleCount++ & (decim - 1))) // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1) + { + m_sum /= decim; + m_magsq = (m_sum.real() * m_sum.real() + m_sum.imag() * m_sum.imag())/ (1<<30); + + if (m_running.m_ssb & !m_usb) + { // invert spectrum for LSB + //m_sampleBuffer.push_back(Sample(m_sum.imag() * 32768.0, m_sum.real() * 32768.0)); + m_sampleBuffer.push_back(Sample(m_sum.imag(), m_sum.real())); + } + else + { + //m_sampleBuffer.push_back(Sample(m_sum.real() * 32768.0, m_sum.imag() * 32768.0)); + m_sampleBuffer.push_back(Sample(m_sum.real(), m_sum.imag())); + } + + m_sum = 0; + } + } + } +}; + +#endif // INCLUDE_CHANALYZERNG_H diff --git a/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp b/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp index 255fec1d1..38c872202 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp @@ -38,8 +38,6 @@ #include "chanalyzerng.h" -const QString ChannelAnalyzerNGGUI::m_channelID = "sdrangel.channel.chanalyzerng"; - ChannelAnalyzerNGGUI* ChannelAnalyzerNGGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { ChannelAnalyzerNGGUI* gui = new ChannelAnalyzerNGGUI(pluginAPI, deviceUISet); @@ -407,7 +405,7 @@ ChannelAnalyzerNGGUI::ChannelAnalyzerNGGUI(PluginAPI* pluginAPI, DeviceUISet *de connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(ChannelAnalyzerNG::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/chanalyzerng/chanalyzernggui.h b/plugins/channelrx/chanalyzerng/chanalyzernggui.h index 1b71d1de1..b1c26f625 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzernggui.h +++ b/plugins/channelrx/chanalyzerng/chanalyzernggui.h @@ -55,8 +55,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void viewChanged(); // void channelizerInputSampleRateChanged(); diff --git a/plugins/channelrx/chanalyzerng/chanalyzerngplugin.cpp b/plugins/channelrx/chanalyzerng/chanalyzerngplugin.cpp index f5881edec..d61d48721 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerngplugin.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzerngplugin.cpp @@ -19,10 +19,11 @@ #include "plugin/pluginapi.h" #include "chanalyzerngplugin.h" #include "chanalyzernggui.h" +#include "chanalyzerng.h" const PluginDescriptor ChannelAnalyzerNGPlugin::m_pluginDescriptor = { QString("Channel Analyzer NG"), - QString("3.8.0"), + QString("3.8.2"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -45,16 +46,28 @@ void ChannelAnalyzerNGPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register demodulator - m_pluginAPI->registerRxChannel(ChannelAnalyzerNGGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(ChannelAnalyzerNG::m_channelID, this); } PluginInstanceGUI* ChannelAnalyzerNGPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == ChannelAnalyzerNGGUI::m_channelID) + if(channelName == ChannelAnalyzerNG::m_channelID) { ChannelAnalyzerNGGUI* gui = ChannelAnalyzerNGGUI::create(m_pluginAPI, deviceUISet); return gui; } else { - return NULL; + return 0; } } + +BasebandSampleSink* ChannelAnalyzerNGPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == ChannelAnalyzerNG::m_channelID) + { + ChannelAnalyzerNG* sink = new ChannelAnalyzerNG(deviceAPI); + return sink; + } else { + return 0; + } +} + diff --git a/plugins/channelrx/chanalyzerng/chanalyzerngplugin.h b/plugins/channelrx/chanalyzerng/chanalyzerngplugin.h index 90993336e..04ed80427 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerngplugin.h +++ b/plugins/channelrx/chanalyzerng/chanalyzerngplugin.h @@ -22,6 +22,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class ChannelAnalyzerNGPlugin : public QObject, PluginInterface { Q_OBJECT @@ -35,6 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodam/amdemod.cpp b/plugins/channelrx/demodam/amdemod.cpp index 7e4e3c0fe..9392965a5 100644 --- a/plugins/channelrx/demodam/amdemod.cpp +++ b/plugins/channelrx/demodam/amdemod.cpp @@ -32,6 +32,7 @@ MESSAGE_CLASS_DEFINITION(AMDemod::MsgConfigureAMDemod, Message) MESSAGE_CLASS_DEFINITION(AMDemod::MsgConfigureChannelizer, Message) +const QString AMDemod::m_channelID = "de.maintech.sdrangelove.channel.am"; const int AMDemod::m_udpBlockSize = 512; AMDemod::AMDemod(DeviceSourceAPI *deviceAPI) : diff --git a/plugins/channelrx/demodam/amdemod.h b/plugins/channelrx/demodam/amdemod.h index 8c48c2914..a7a0a5bff 100644 --- a/plugins/channelrx/demodam/amdemod.h +++ b/plugins/channelrx/demodam/amdemod.h @@ -1,227 +1,229 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2015 Edouard Griffiths, F4EXB. // -// // -// 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_AMDEMOD_H -#define INCLUDE_AMDEMOD_H - -#include -#include -#include -#include "dsp/nco.h" -#include "dsp/interpolator.h" -#include "dsp/movingaverage.h" -#include "dsp/agc.h" -#include "dsp/bandpass.h" -#include "audio/audiofifo.h" -#include "util/message.h" -#include "amdemodsettings.h" - -class DeviceSourceAPI; -class DownChannelizer; -class ThreadedBasebandSampleSink; - -class AMDemod : public BasebandSampleSink { - Q_OBJECT -public: - class MsgConfigureAMDemod : public Message { - MESSAGE_CLASS_DECLARATION - - public: - const AMDemodSettings& getSettings() const { return m_settings; } - bool getForce() const { return m_force; } - - static MsgConfigureAMDemod* create(const AMDemodSettings& settings, bool force) - { - return new MsgConfigureAMDemod(settings, force); - } - - private: - AMDemodSettings m_settings; - bool m_force; - - MsgConfigureAMDemod(const AMDemodSettings& settings, bool force) : - Message(), - m_settings(settings), - m_force(force) - { } - }; - - class MsgConfigureChannelizer : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getSampleRate() const { return m_sampleRate; } - int getCenterFrequency() const { return m_centerFrequency; } - - static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) - { - return new MsgConfigureChannelizer(sampleRate, centerFrequency); - } - - private: - int m_sampleRate; - int m_centerFrequency; - - MsgConfigureChannelizer(int sampleRate, int centerFrequency) : - Message(), - m_sampleRate(sampleRate), - m_centerFrequency(centerFrequency) - { } - }; - - AMDemod(DeviceSourceAPI *deviceAPI); - ~AMDemod(); - - virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); - virtual void start(); - virtual void stop(); - virtual bool handleMessage(const Message& cmd); - - double getMagSq() const { return m_magsq; } - bool getSquelchOpen() const { return m_squelchOpen; } - - void getMagSqLevels(double& avg, double& peak, int& nbSamples) - { - avg = m_magsqCount == 0 ? 1e-10 : m_magsqSum / m_magsqCount; - peak = m_magsqPeak == 0.0 ? 1e-10 : m_magsqPeak; - nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; - m_magsqSum = 0.0f; - m_magsqPeak = 0.0f; - m_magsqCount = 0; - } - -private: - enum RateState { - RSInitialFill, - RSRunning - }; - - DeviceSourceAPI *m_deviceAPI; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; - - AMDemodSettings m_settings; - - NCO m_nco; - Interpolator m_interpolator; - Real m_interpolatorDistance; - Real m_interpolatorDistanceRemain; - - Real m_squelchLevel; - uint32_t m_squelchCount; - bool m_squelchOpen; - double m_magsq; - double m_magsqSum; - double m_magsqPeak; - int m_magsqCount; - - MovingAverage m_movingAverage; - SimpleAGC m_volumeAGC; - Bandpass m_bandpass; - - AudioVector m_audioBuffer; - uint32_t m_audioBufferFill; - AudioFifo m_audioFifo; - UDPSink *m_udpBufferAudio; - - static const int m_udpBlockSize; - - QMutex m_settingsMutex; - -// void apply(bool force = false); - void applySettings(const AMDemodSettings& settings, bool force = false); - - void processOneSample(Complex &ci) - { - Real magsq = ci.real() * ci.real() + ci.imag() * ci.imag(); - magsq /= (1<<30); - m_movingAverage.feed(magsq); - m_magsq = m_movingAverage.average(); - m_magsqSum += magsq; - - if (magsq > m_magsqPeak) - { - m_magsqPeak = magsq; - } - - m_magsqCount++; - - if (m_magsq >= m_squelchLevel) - { - if (m_squelchCount <= m_settings.m_audioSampleRate / 10) - { - if (m_squelchCount == m_settings.m_audioSampleRate / 20) { - m_volumeAGC.fill(1.0); - } - - m_squelchCount++; - } - } - else - { - if (m_squelchCount > 1) - { - m_squelchCount -= 2; - } - } - - qint16 sample; - - if ((m_squelchCount >= m_settings.m_audioSampleRate / 20) && !m_settings.m_audioMute) - { - Real demod = sqrt(magsq); - m_volumeAGC.feed(demod); - demod = (demod - m_volumeAGC.getValue()) / m_volumeAGC.getValue(); - - if (m_settings.m_bandpassEnable) - { - demod = m_bandpass.filter(demod); - demod /= 301.0f; - } - - Real attack = (m_squelchCount - 0.05f * m_settings.m_audioSampleRate) / (0.05f * m_settings.m_audioSampleRate); - sample = demod * attack * 2048 * m_settings.m_volume; - if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(demod * attack * 32768); - - m_squelchOpen = true; - } - else - { - sample = 0; - if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(0); - m_squelchOpen = false; - } - - m_audioBuffer[m_audioBufferFill].l = sample; - m_audioBuffer[m_audioBufferFill].r = sample; - ++m_audioBufferFill; - - if (m_audioBufferFill >= m_audioBuffer.size()) - { - uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10); - - if (res != m_audioBufferFill) - { - qDebug("AMDemod::feed: %u/%u audio samples written", res, m_audioBufferFill); - } - - m_audioBufferFill = 0; - } - } - -}; - -#endif // INCLUDE_AMDEMOD_H +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 Edouard Griffiths, F4EXB. // +// // +// 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_AMDEMOD_H +#define INCLUDE_AMDEMOD_H + +#include +#include +#include +#include "dsp/nco.h" +#include "dsp/interpolator.h" +#include "dsp/movingaverage.h" +#include "dsp/agc.h" +#include "dsp/bandpass.h" +#include "audio/audiofifo.h" +#include "util/message.h" +#include "amdemodsettings.h" + +class DeviceSourceAPI; +class DownChannelizer; +class ThreadedBasebandSampleSink; + +class AMDemod : public BasebandSampleSink { + Q_OBJECT +public: + class MsgConfigureAMDemod : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const AMDemodSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureAMDemod* create(const AMDemodSettings& settings, bool force) + { + return new MsgConfigureAMDemod(settings, force); + } + + private: + AMDemodSettings m_settings; + bool m_force; + + MsgConfigureAMDemod(const AMDemodSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgConfigureChannelizer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + int getCenterFrequency() const { return m_centerFrequency; } + + static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) + { + return new MsgConfigureChannelizer(sampleRate, centerFrequency); + } + + private: + int m_sampleRate; + int m_centerFrequency; + + MsgConfigureChannelizer(int sampleRate, int centerFrequency) : + Message(), + m_sampleRate(sampleRate), + m_centerFrequency(centerFrequency) + { } + }; + + AMDemod(DeviceSourceAPI *deviceAPI); + ~AMDemod(); + + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); + virtual void start(); + virtual void stop(); + virtual bool handleMessage(const Message& cmd); + + double getMagSq() const { return m_magsq; } + bool getSquelchOpen() const { return m_squelchOpen; } + + void getMagSqLevels(double& avg, double& peak, int& nbSamples) + { + avg = m_magsqCount == 0 ? 1e-10 : m_magsqSum / m_magsqCount; + peak = m_magsqPeak == 0.0 ? 1e-10 : m_magsqPeak; + nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; + m_magsqSum = 0.0f; + m_magsqPeak = 0.0f; + m_magsqCount = 0; + } + + static const QString m_channelID; + +private: + enum RateState { + RSInitialFill, + RSRunning + }; + + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; + + AMDemodSettings m_settings; + + NCO m_nco; + Interpolator m_interpolator; + Real m_interpolatorDistance; + Real m_interpolatorDistanceRemain; + + Real m_squelchLevel; + uint32_t m_squelchCount; + bool m_squelchOpen; + double m_magsq; + double m_magsqSum; + double m_magsqPeak; + int m_magsqCount; + + MovingAverage m_movingAverage; + SimpleAGC m_volumeAGC; + Bandpass m_bandpass; + + AudioVector m_audioBuffer; + uint32_t m_audioBufferFill; + AudioFifo m_audioFifo; + UDPSink *m_udpBufferAudio; + + static const int m_udpBlockSize; + + QMutex m_settingsMutex; + +// void apply(bool force = false); + void applySettings(const AMDemodSettings& settings, bool force = false); + + void processOneSample(Complex &ci) + { + Real magsq = ci.real() * ci.real() + ci.imag() * ci.imag(); + magsq /= (1<<30); + m_movingAverage.feed(magsq); + m_magsq = m_movingAverage.average(); + m_magsqSum += magsq; + + if (magsq > m_magsqPeak) + { + m_magsqPeak = magsq; + } + + m_magsqCount++; + + if (m_magsq >= m_squelchLevel) + { + if (m_squelchCount <= m_settings.m_audioSampleRate / 10) + { + if (m_squelchCount == m_settings.m_audioSampleRate / 20) { + m_volumeAGC.fill(1.0); + } + + m_squelchCount++; + } + } + else + { + if (m_squelchCount > 1) + { + m_squelchCount -= 2; + } + } + + qint16 sample; + + if ((m_squelchCount >= m_settings.m_audioSampleRate / 20) && !m_settings.m_audioMute) + { + Real demod = sqrt(magsq); + m_volumeAGC.feed(demod); + demod = (demod - m_volumeAGC.getValue()) / m_volumeAGC.getValue(); + + if (m_settings.m_bandpassEnable) + { + demod = m_bandpass.filter(demod); + demod /= 301.0f; + } + + Real attack = (m_squelchCount - 0.05f * m_settings.m_audioSampleRate) / (0.05f * m_settings.m_audioSampleRate); + sample = demod * attack * 2048 * m_settings.m_volume; + if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(demod * attack * 32768); + + m_squelchOpen = true; + } + else + { + sample = 0; + if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(0); + m_squelchOpen = false; + } + + m_audioBuffer[m_audioBufferFill].l = sample; + m_audioBuffer[m_audioBufferFill].r = sample; + ++m_audioBufferFill; + + if (m_audioBufferFill >= m_audioBuffer.size()) + { + uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10); + + if (res != m_audioBufferFill) + { + qDebug("AMDemod::feed: %u/%u audio samples written", res, m_audioBufferFill); + } + + m_audioBufferFill = 0; + } + } + +}; + +#endif // INCLUDE_AMDEMOD_H diff --git a/plugins/channelrx/demodam/amdemodgui.cpp b/plugins/channelrx/demodam/amdemodgui.cpp index a4a836353..87fd18a19 100644 --- a/plugins/channelrx/demodam/amdemodgui.cpp +++ b/plugins/channelrx/demodam/amdemodgui.cpp @@ -34,8 +34,6 @@ #include "amdemod.h" -const QString AMDemodGUI::m_channelID = "de.maintech.sdrangelove.channel.am"; - AMDemodGUI* AMDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { AMDemodGUI* gui = new AMDemodGUI(pluginAPI, deviceUISet); @@ -206,7 +204,7 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, QWidget* connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(AMDemod::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/demodam/amdemodgui.h b/plugins/channelrx/demodam/amdemodgui.h index 32833328b..52a0211e0 100644 --- a/plugins/channelrx/demodam/amdemodgui.h +++ b/plugins/channelrx/demodam/amdemodgui.h @@ -37,8 +37,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void channelMarkerChanged(); void on_deltaFrequency_changed(qint64 value); diff --git a/plugins/channelrx/demodam/amdemodplugin.cpp b/plugins/channelrx/demodam/amdemodplugin.cpp index c93b20857..b551ab1c1 100644 --- a/plugins/channelrx/demodam/amdemodplugin.cpp +++ b/plugins/channelrx/demodam/amdemodplugin.cpp @@ -31,12 +31,12 @@ void AMDemodPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register AM demodulator - m_pluginAPI->registerRxChannel(AMDemodGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(AMDemod::m_channelID, this); } PluginInstanceGUI* AMDemodPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == AMDemodGUI::m_channelID) + if(channelName == AMDemod::m_channelID) { AMDemodGUI* gui = AMDemodGUI::create(m_pluginAPI, deviceUISet); return gui; @@ -47,7 +47,7 @@ PluginInstanceGUI* AMDemodPlugin::createRxChannelGUI(const QString& channelName, BasebandSampleSink* AMDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { - if(channelName == AMDemodGUI::m_channelID) + if(channelName == AMDemod::m_channelID) { AMDemod* sink = new AMDemod(deviceAPI); return sink; diff --git a/plugins/channelrx/demodatv/atvdemod.cpp b/plugins/channelrx/demodatv/atvdemod.cpp index f9209bf1a..47543dc10 100644 --- a/plugins/channelrx/demodatv/atvdemod.cpp +++ b/plugins/channelrx/demodatv/atvdemod.cpp @@ -35,6 +35,7 @@ MESSAGE_CLASS_DEFINITION(ATVDemod::MsgReportEffectiveSampleRate, Message) MESSAGE_CLASS_DEFINITION(ATVDemod::MsgConfigureChannelizer, Message) MESSAGE_CLASS_DEFINITION(ATVDemod::MsgReportChannelSampleRateChanged, Message) +const QString ATVDemod::m_channelID = "sdrangel.channel.demodatv"; const int ATVDemod::m_ssbFftLen = 1024; ATVDemod::ATVDemod(DeviceSourceAPI *deviceAPI) : diff --git a/plugins/channelrx/demodatv/atvdemod.h b/plugins/channelrx/demodatv/atvdemod.h index 7013d3e23..c1fd93ddb 100644 --- a/plugins/channelrx/demodatv/atvdemod.h +++ b/plugins/channelrx/demodatv/atvdemod.h @@ -227,6 +227,8 @@ public: double getMagSq() const { return m_objMagSqAverage.average(); } //!< Beware this is scaled to 2^30 bool getBFOLocked(); + static const QString m_channelID; + private slots: void channelSampleRateChanged(); diff --git a/plugins/channelrx/demodatv/atvdemodgui.cpp b/plugins/channelrx/demodatv/atvdemodgui.cpp index 83cc9b83c..c671027a3 100644 --- a/plugins/channelrx/demodatv/atvdemodgui.cpp +++ b/plugins/channelrx/demodatv/atvdemodgui.cpp @@ -36,8 +36,6 @@ #include "atvdemod.h" -const QString ATVDemodGUI::m_strChannelID = "sdrangel.channel.demodatv"; - ATVDemodGUI* ATVDemodGUI::create(PluginAPI* objPluginAPI, DeviceUISet *deviceUISet) { @@ -312,7 +310,7 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceUISet *deviceUISet, connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); - m_deviceUISet->registerRxChannelInstance(m_strChannelID, this); + m_deviceUISet->registerRxChannelInstance(ATVDemod::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/demodatv/atvdemodgui.h b/plugins/channelrx/demodatv/atvdemodgui.h index 0fdbdeb7a..abacc0a8d 100644 --- a/plugins/channelrx/demodatv/atvdemodgui.h +++ b/plugins/channelrx/demodatv/atvdemodgui.h @@ -54,8 +54,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& objMessage); - static const QString m_strChannelID; - private slots: void viewChanged(); void handleSourceMessages(); diff --git a/plugins/channelrx/demodatv/atvdemodplugin.cpp b/plugins/channelrx/demodatv/atvdemodplugin.cpp index 2cb0de19c..4dfa93be3 100644 --- a/plugins/channelrx/demodatv/atvdemodplugin.cpp +++ b/plugins/channelrx/demodatv/atvdemodplugin.cpp @@ -21,6 +21,7 @@ #include "plugin/pluginapi.h" #include "atvdemodgui.h" +#include "atvdemod.h" #include "atvdemodplugin.h" const PluginDescriptor ATVDemodPlugin::m_ptrPluginDescriptor = @@ -50,18 +51,30 @@ void ATVDemodPlugin::initPlugin(PluginAPI* ptrPluginAPI) m_ptrPluginAPI = ptrPluginAPI; // register ATV demodulator - m_ptrPluginAPI->registerRxChannel(ATVDemodGUI::m_strChannelID, this); + m_ptrPluginAPI->registerRxChannel(ATVDemod::m_channelID, this); } PluginInstanceGUI* ATVDemodPlugin::createRxChannelGUI(const QString& strChannelName, DeviceUISet *deviceUISet) { - if(strChannelName == ATVDemodGUI::m_strChannelID) + if(strChannelName == ATVDemod::m_channelID) { ATVDemodGUI* ptrGui = ATVDemodGUI::create(m_ptrPluginAPI, deviceUISet); return ptrGui; } else { - return NULL; + return 0; } } + +BasebandSampleSink* ATVDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == ATVDemod::m_channelID) + { + ATVDemod* sink = new ATVDemod(deviceAPI); + return sink; + } else { + return 0; + } +} + diff --git a/plugins/channelrx/demodatv/atvdemodplugin.h b/plugins/channelrx/demodatv/atvdemodplugin.h index e8f61e681..c8dde4005 100644 --- a/plugins/channelrx/demodatv/atvdemodplugin.h +++ b/plugins/channelrx/demodatv/atvdemodplugin.h @@ -22,6 +22,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class ATVDemodPlugin : public QObject, PluginInterface { @@ -36,6 +37,7 @@ public: void initPlugin(PluginAPI* ptrPluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& strChannelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_ptrPluginDescriptor; diff --git a/plugins/channelrx/demodbfm/bfmdemod.cpp b/plugins/channelrx/demodbfm/bfmdemod.cpp index bda23fc3d..8954c65c0 100644 --- a/plugins/channelrx/demodbfm/bfmdemod.cpp +++ b/plugins/channelrx/demodbfm/bfmdemod.cpp @@ -34,6 +34,7 @@ MESSAGE_CLASS_DEFINITION(BFMDemod::MsgConfigureChannelizer, Message) MESSAGE_CLASS_DEFINITION(BFMDemod::MsgReportChannelSampleRateChanged, Message) MESSAGE_CLASS_DEFINITION(BFMDemod::MsgConfigureBFMDemod, Message) +const QString BFMDemod::m_channelID = "sdrangel.channel.bfm"; const Real BFMDemod::default_deemphasis = 50.0; // 50 us const int BFMDemod::m_udpBlockSize = 512; diff --git a/plugins/channelrx/demodbfm/bfmdemod.h b/plugins/channelrx/demodbfm/bfmdemod.h index 3c403bb19..1d5ddf13e 100644 --- a/plugins/channelrx/demodbfm/bfmdemod.h +++ b/plugins/channelrx/demodbfm/bfmdemod.h @@ -1,219 +1,221 @@ -/////////////////////////////////////////////////////////////////////////////////// -// 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_BFMDEMOD_H -#define INCLUDE_BFMDEMOD_H - -#include -#include -#include -#include "dsp/nco.h" -#include "dsp/interpolator.h" -#include "dsp/lowpass.h" -#include "dsp/movingaverage.h" -#include "dsp/fftfilt.h" -#include "dsp/phaselock.h" -#include "dsp/filterrc.h" -#include "dsp/phasediscri.h" -#include "audio/audiofifo.h" -#include "util/message.h" -#include "util/udpsink.h" - -#include "rdsparser.h" -#include "rdsdecoder.h" -#include "rdsdemod.h" -#include "bfmdemodsettings.h" - -class DeviceSourceAPI; -class ThreadedBasebandSampleSink; -class DownChannelizer; - -class BFMDemod : public BasebandSampleSink { -public: - class MsgConfigureBFMDemod : public Message { - MESSAGE_CLASS_DECLARATION - - public: - const BFMDemodSettings& getSettings() const { return m_settings; } - bool getForce() const { return m_force; } - - static MsgConfigureBFMDemod* create(const BFMDemodSettings& settings, bool force) - { - return new MsgConfigureBFMDemod(settings, force); - } - - private: - BFMDemodSettings m_settings; - bool m_force; - - MsgConfigureBFMDemod(const BFMDemodSettings& settings, bool force) : - Message(), - m_settings(settings), - m_force(force) - { } - }; - - class MsgConfigureChannelizer : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getSampleRate() const { return m_sampleRate; } - int getCenterFrequency() const { return m_centerFrequency; } - - static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) - { - return new MsgConfigureChannelizer(sampleRate, centerFrequency); - } - - private: - int m_sampleRate; - int m_centerFrequency; - - MsgConfigureChannelizer(int sampleRate, int centerFrequency) : - Message(), - m_sampleRate(sampleRate), - m_centerFrequency(centerFrequency) - { } - }; - - class MsgReportChannelSampleRateChanged : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getSampleRate() const { return m_sampleRate; } - - static MsgReportChannelSampleRateChanged* create(int sampleRate) - { - return new MsgReportChannelSampleRateChanged(sampleRate); - } - - private: - int m_sampleRate; - - MsgReportChannelSampleRateChanged(int sampleRate) : - Message(), - m_sampleRate(sampleRate) - { } - }; - - BFMDemod(DeviceSourceAPI *deviceAPI); - virtual ~BFMDemod(); - void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; } - - int getSampleRate() const { return m_settings.m_inputSampleRate; } - virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); - virtual void start(); - virtual void stop(); - virtual bool handleMessage(const Message& cmd); - - double getMagSq() const { return m_magsq; } - - bool getPilotLock() const { return m_pilotPLL.locked(); } - Real getPilotLevel() const { return m_pilotPLL.get_pilot_level(); } - - Real getDecoderQua() const { return m_rdsDecoder.m_qua; } - bool getDecoderSynced() const { return m_rdsDecoder.synced(); } - Real getDemodAcc() const { return m_rdsDemod.m_report.acc; } - Real getDemodQua() const { return m_rdsDemod.m_report.qua; } - Real getDemodFclk() const { return m_rdsDemod.m_report.fclk; } - - void getMagSqLevels(double& avg, double& peak, int& nbSamples) - { - avg = m_magsqCount == 0 ? 1e-10 : m_magsqSum / m_magsqCount; - m_magsq = avg; - peak = m_magsqPeak == 0.0 ? 1e-10 : m_magsqPeak; - nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; - m_magsqSum = 0.0f; - m_magsqPeak = 0.0f; - m_magsqCount = 0; - } - - RDSParser& getRDSParser() { return m_rdsParser; } - -private slots: - void channelSampleRateChanged(); - -private: - enum RateState { - RSInitialFill, - RSRunning - }; - - DeviceSourceAPI *m_deviceAPI; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; - - BFMDemodSettings m_settings; - - NCO m_nco; - Interpolator m_interpolator; //!< Interpolator between fixed demod bandwidth and audio bandwidth (rational) - Real m_interpolatorDistance; - Real m_interpolatorDistanceRemain; - - Interpolator m_interpolatorStereo; //!< Twin Interpolator for stereo subcarrier - Real m_interpolatorStereoDistance; - Real m_interpolatorStereoDistanceRemain; - - Interpolator m_interpolatorRDS; //!< Twin Interpolator for stereo subcarrier - Real m_interpolatorRDSDistance; - Real m_interpolatorRDSDistanceRemain; - - Lowpass m_lowpass; - fftfilt* m_rfFilter; - static const int filtFftLen = 1024; - - Real m_squelchLevel; - int m_squelchState; - - Real m_m1Arg; //!> x^-1 real sample - - double m_magsq; - double m_magsqSum; - double m_magsqPeak; - int m_magsqCount; - - AudioVector m_audioBuffer; - uint m_audioBufferFill; - - BasebandSampleSink* m_sampleSink; - AudioFifo m_audioFifo; - SampleVector m_sampleBuffer; - QMutex m_settingsMutex; - - RDSPhaseLock m_pilotPLL; - Real m_pilotPLLSamples[4]; - - RDSDemod m_rdsDemod; - RDSDecoder m_rdsDecoder; - RDSParser m_rdsParser; - - LowPassFilterRC m_deemphasisFilterX; - LowPassFilterRC m_deemphasisFilterY; - static const Real default_deemphasis; - - Real m_fmExcursion; - static const int default_excursion = 750000; // +/- 75 kHz - - PhaseDiscriminators m_phaseDiscri; - UDPSink *m_udpBufferAudio; - - static const int m_udpBlockSize; - - void applySettings(const BFMDemodSettings& settings, bool force = false); -}; - -#endif // INCLUDE_BFMDEMOD_H +/////////////////////////////////////////////////////////////////////////////////// +// 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_BFMDEMOD_H +#define INCLUDE_BFMDEMOD_H + +#include +#include +#include +#include "dsp/nco.h" +#include "dsp/interpolator.h" +#include "dsp/lowpass.h" +#include "dsp/movingaverage.h" +#include "dsp/fftfilt.h" +#include "dsp/phaselock.h" +#include "dsp/filterrc.h" +#include "dsp/phasediscri.h" +#include "audio/audiofifo.h" +#include "util/message.h" +#include "util/udpsink.h" + +#include "rdsparser.h" +#include "rdsdecoder.h" +#include "rdsdemod.h" +#include "bfmdemodsettings.h" + +class DeviceSourceAPI; +class ThreadedBasebandSampleSink; +class DownChannelizer; + +class BFMDemod : public BasebandSampleSink { +public: + class MsgConfigureBFMDemod : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const BFMDemodSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureBFMDemod* create(const BFMDemodSettings& settings, bool force) + { + return new MsgConfigureBFMDemod(settings, force); + } + + private: + BFMDemodSettings m_settings; + bool m_force; + + MsgConfigureBFMDemod(const BFMDemodSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgConfigureChannelizer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + int getCenterFrequency() const { return m_centerFrequency; } + + static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) + { + return new MsgConfigureChannelizer(sampleRate, centerFrequency); + } + + private: + int m_sampleRate; + int m_centerFrequency; + + MsgConfigureChannelizer(int sampleRate, int centerFrequency) : + Message(), + m_sampleRate(sampleRate), + m_centerFrequency(centerFrequency) + { } + }; + + class MsgReportChannelSampleRateChanged : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + + static MsgReportChannelSampleRateChanged* create(int sampleRate) + { + return new MsgReportChannelSampleRateChanged(sampleRate); + } + + private: + int m_sampleRate; + + MsgReportChannelSampleRateChanged(int sampleRate) : + Message(), + m_sampleRate(sampleRate) + { } + }; + + BFMDemod(DeviceSourceAPI *deviceAPI); + virtual ~BFMDemod(); + void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; } + + int getSampleRate() const { return m_settings.m_inputSampleRate; } + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); + virtual void start(); + virtual void stop(); + virtual bool handleMessage(const Message& cmd); + + double getMagSq() const { return m_magsq; } + + bool getPilotLock() const { return m_pilotPLL.locked(); } + Real getPilotLevel() const { return m_pilotPLL.get_pilot_level(); } + + Real getDecoderQua() const { return m_rdsDecoder.m_qua; } + bool getDecoderSynced() const { return m_rdsDecoder.synced(); } + Real getDemodAcc() const { return m_rdsDemod.m_report.acc; } + Real getDemodQua() const { return m_rdsDemod.m_report.qua; } + Real getDemodFclk() const { return m_rdsDemod.m_report.fclk; } + + void getMagSqLevels(double& avg, double& peak, int& nbSamples) + { + avg = m_magsqCount == 0 ? 1e-10 : m_magsqSum / m_magsqCount; + m_magsq = avg; + peak = m_magsqPeak == 0.0 ? 1e-10 : m_magsqPeak; + nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; + m_magsqSum = 0.0f; + m_magsqPeak = 0.0f; + m_magsqCount = 0; + } + + RDSParser& getRDSParser() { return m_rdsParser; } + + static const QString m_channelID; + +private slots: + void channelSampleRateChanged(); + +private: + enum RateState { + RSInitialFill, + RSRunning + }; + + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; + + BFMDemodSettings m_settings; + + NCO m_nco; + Interpolator m_interpolator; //!< Interpolator between fixed demod bandwidth and audio bandwidth (rational) + Real m_interpolatorDistance; + Real m_interpolatorDistanceRemain; + + Interpolator m_interpolatorStereo; //!< Twin Interpolator for stereo subcarrier + Real m_interpolatorStereoDistance; + Real m_interpolatorStereoDistanceRemain; + + Interpolator m_interpolatorRDS; //!< Twin Interpolator for stereo subcarrier + Real m_interpolatorRDSDistance; + Real m_interpolatorRDSDistanceRemain; + + Lowpass m_lowpass; + fftfilt* m_rfFilter; + static const int filtFftLen = 1024; + + Real m_squelchLevel; + int m_squelchState; + + Real m_m1Arg; //!> x^-1 real sample + + double m_magsq; + double m_magsqSum; + double m_magsqPeak; + int m_magsqCount; + + AudioVector m_audioBuffer; + uint m_audioBufferFill; + + BasebandSampleSink* m_sampleSink; + AudioFifo m_audioFifo; + SampleVector m_sampleBuffer; + QMutex m_settingsMutex; + + RDSPhaseLock m_pilotPLL; + Real m_pilotPLLSamples[4]; + + RDSDemod m_rdsDemod; + RDSDecoder m_rdsDecoder; + RDSParser m_rdsParser; + + LowPassFilterRC m_deemphasisFilterX; + LowPassFilterRC m_deemphasisFilterY; + static const Real default_deemphasis; + + Real m_fmExcursion; + static const int default_excursion = 750000; // +/- 75 kHz + + PhaseDiscriminators m_phaseDiscri; + UDPSink *m_udpBufferAudio; + + static const int m_udpBlockSize; + + void applySettings(const BFMDemodSettings& settings, bool force = false); +}; + +#endif // INCLUDE_BFMDEMOD_H diff --git a/plugins/channelrx/demodbfm/bfmdemodgui.cpp b/plugins/channelrx/demodbfm/bfmdemodgui.cpp index 0476f702f..4a2b0b84a 100644 --- a/plugins/channelrx/demodbfm/bfmdemodgui.cpp +++ b/plugins/channelrx/demodbfm/bfmdemodgui.cpp @@ -43,8 +43,6 @@ #include "rdstmc.h" #include "ui_bfmdemodgui.h" -const QString BFMDemodGUI::m_channelID = "sdrangel.channel.bfm"; - BFMDemodGUI* BFMDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUIset) { BFMDemodGUI* gui = new BFMDemodGUI(pluginAPI, deviceUIset); @@ -364,7 +362,7 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, QWidget connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(BFMDemod::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/demodbfm/bfmdemodgui.h b/plugins/channelrx/demodbfm/bfmdemodgui.h index 5d83edd10..9b6307436 100644 --- a/plugins/channelrx/demodbfm/bfmdemodgui.h +++ b/plugins/channelrx/demodbfm/bfmdemodgui.h @@ -56,8 +56,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void on_deltaFrequency_changed(qint64 value); void on_rfBW_valueChanged(int value); diff --git a/plugins/channelrx/demodbfm/bfmplugin.cpp b/plugins/channelrx/demodbfm/bfmplugin.cpp index 923f7a20f..fa2c9ffa4 100644 --- a/plugins/channelrx/demodbfm/bfmplugin.cpp +++ b/plugins/channelrx/demodbfm/bfmplugin.cpp @@ -21,6 +21,7 @@ #include "plugin/pluginapi.h" #include "bfmdemodgui.h" +#include "bfmdemod.h" const PluginDescriptor BFMPlugin::m_pluginDescriptor = { QString("Broadcast FM Demodulator"), @@ -47,12 +48,12 @@ void BFMPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register BFM demodulator - m_pluginAPI->registerRxChannel(BFMDemodGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(BFMDemod::m_channelID, this); } PluginInstanceGUI* BFMPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == BFMDemodGUI::m_channelID) + if(channelName == BFMDemod::m_channelID) { BFMDemodGUI* gui = BFMDemodGUI::create(m_pluginAPI, deviceUISet); return gui; @@ -60,3 +61,15 @@ PluginInstanceGUI* BFMPlugin::createRxChannelGUI(const QString& channelName, Dev return 0; } } + + +BasebandSampleSink* BFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == BFMDemod::m_channelID) + { + BFMDemod* sink = new BFMDemod(deviceAPI); + return sink; + } else { + return 0; + } +} diff --git a/plugins/channelrx/demodbfm/bfmplugin.h b/plugins/channelrx/demodbfm/bfmplugin.h index 8377ac745..c03991768 100644 --- a/plugins/channelrx/demodbfm/bfmplugin.h +++ b/plugins/channelrx/demodbfm/bfmplugin.h @@ -35,6 +35,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demoddsd/dsddemod.cpp b/plugins/channelrx/demoddsd/dsddemod.cpp index 9230ac579..d18120847 100644 --- a/plugins/channelrx/demoddsd/dsddemod.cpp +++ b/plugins/channelrx/demoddsd/dsddemod.cpp @@ -35,6 +35,7 @@ MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureChannelizer, Message) MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureDSDDemod, Message) MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureMyPosition, Message) +const QString DSDDemod::m_channelID = "sdrangel.channel.dsddemod"; const int DSDDemod::m_udpBlockSize = 512; DSDDemod::DSDDemod(DeviceSourceAPI *deviceAPI) : diff --git a/plugins/channelrx/demoddsd/dsddemod.h b/plugins/channelrx/demoddsd/dsddemod.h index 501c58ccc..1b4e0e896 100644 --- a/plugins/channelrx/demoddsd/dsddemod.h +++ b/plugins/channelrx/demoddsd/dsddemod.h @@ -1,194 +1,195 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 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_DSDDEMOD_H -#define INCLUDE_DSDDEMOD_H - -#include -#include -#include -#include -#include "dsp/nco.h" -#include "dsp/interpolator.h" -#include "dsp/lowpass.h" -#include "dsp/bandpass.h" -#include "dsp/afsquelch.h" -#include "dsp/movingaverage.h" -#include "dsp/afsquelch.h" -#include "audio/audiofifo.h" -#include "util/message.h" -#include "util/udpsink.h" - -#include "dsddemodsettings.h" -#include "dsddecoder.h" - -class DeviceSourceAPI; -class ThreadedBasebandSampleSink; -class DownChannelizer; - -class DSDDemod : public BasebandSampleSink { -public: - class MsgConfigureDSDDemod : public Message { - MESSAGE_CLASS_DECLARATION - - public: - const DSDDemodSettings& getSettings() const { return m_settings; } - bool getForce() const { return m_force; } - - static MsgConfigureDSDDemod* create(const DSDDemodSettings& settings, bool force) - { - return new MsgConfigureDSDDemod(settings, force); - } - - private: - DSDDemodSettings m_settings; - bool m_force; - - MsgConfigureDSDDemod(const DSDDemodSettings& settings, bool force) : - Message(), - m_settings(settings), - m_force(force) - { } - }; - - class MsgConfigureChannelizer : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getSampleRate() const { return m_sampleRate; } - int getCenterFrequency() const { return m_centerFrequency; } - - static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) - { - return new MsgConfigureChannelizer(sampleRate, centerFrequency); - } - - private: - int m_sampleRate; - int m_centerFrequency; - - MsgConfigureChannelizer(int sampleRate, int centerFrequency) : - Message(), - m_sampleRate(sampleRate), - m_centerFrequency(centerFrequency) - { } - }; - - DSDDemod(DeviceSourceAPI *deviceAPI); - ~DSDDemod(); - void setScopeSink(BasebandSampleSink* sampleSink) { m_scope = sampleSink; } - - void configureMyPosition(MessageQueue* messageQueue, float myLatitude, float myLongitude); - - virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); - virtual void start(); - virtual void stop(); - virtual bool handleMessage(const Message& cmd); - - double getMagSq() { return m_magsq; } - bool getSquelchOpen() const { return m_squelchOpen; } - - const DSDDecoder& getDecoder() const { return m_dsdDecoder; } - - void getMagSqLevels(double& avg, double& peak, int& nbSamples) - { - avg = m_magsqCount == 0 ? 1e-10 : m_magsqSum / m_magsqCount; - m_magsq = avg; - peak = m_magsqPeak == 0.0 ? 1e-10 : m_magsqPeak; - nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; - m_magsqSum = 0.0f; - m_magsqPeak = 0.0f; - m_magsqCount = 0; - } - - -private: - class MsgConfigureMyPosition : public Message { - MESSAGE_CLASS_DECLARATION - - public: - float getMyLatitude() const { return m_myLatitude; } - float getMyLongitude() const { return m_myLongitude; } - - static MsgConfigureMyPosition* create(float myLatitude, float myLongitude) - { - return new MsgConfigureMyPosition(myLatitude, myLongitude); - } - - private: - float m_myLatitude; - float m_myLongitude; - - MsgConfigureMyPosition(float myLatitude, float myLongitude) : - m_myLatitude(myLatitude), - m_myLongitude(myLongitude) - {} - }; - - enum RateState { - RSInitialFill, - RSRunning - }; - - DSDDemodSettings m_settings; - - DeviceSourceAPI *m_deviceAPI; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; - - NCO m_nco; - Interpolator m_interpolator; - Real m_interpolatorDistance; - Real m_interpolatorDistanceRemain; - int m_sampleCount; - int m_squelchCount; - int m_squelchGate; - - double m_squelchLevel; - bool m_squelchOpen; - - MovingAverage m_movingAverage; - double m_magsq; - double m_magsqSum; - double m_magsqPeak; - int m_magsqCount; - - Real m_fmExcursion; - - SampleVector m_scopeSampleBuffer; - AudioVector m_audioBuffer; - uint m_audioBufferFill; - qint16 *m_sampleBuffer; //!< samples ring buffer - int m_sampleBufferIndex; - - AudioFifo m_audioFifo1; - AudioFifo m_audioFifo2; - BasebandSampleSink* m_scope; - bool m_scopeEnabled; - - DSDDecoder m_dsdDecoder; - QMutex m_settingsMutex; - - PhaseDiscriminators m_phaseDiscri; - UDPSink *m_udpBufferAudio; - - static const int m_udpBlockSize; - - void applySettings(DSDDemodSettings& settings, bool force = false); -}; - -#endif // INCLUDE_DSDDEMOD_H +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 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_DSDDEMOD_H +#define INCLUDE_DSDDEMOD_H + +#include +#include +#include +#include +#include "dsp/nco.h" +#include "dsp/interpolator.h" +#include "dsp/lowpass.h" +#include "dsp/bandpass.h" +#include "dsp/afsquelch.h" +#include "dsp/movingaverage.h" +#include "dsp/afsquelch.h" +#include "audio/audiofifo.h" +#include "util/message.h" +#include "util/udpsink.h" + +#include "dsddemodsettings.h" +#include "dsddecoder.h" + +class DeviceSourceAPI; +class ThreadedBasebandSampleSink; +class DownChannelizer; + +class DSDDemod : public BasebandSampleSink { +public: + class MsgConfigureDSDDemod : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const DSDDemodSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureDSDDemod* create(const DSDDemodSettings& settings, bool force) + { + return new MsgConfigureDSDDemod(settings, force); + } + + private: + DSDDemodSettings m_settings; + bool m_force; + + MsgConfigureDSDDemod(const DSDDemodSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgConfigureChannelizer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + int getCenterFrequency() const { return m_centerFrequency; } + + static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) + { + return new MsgConfigureChannelizer(sampleRate, centerFrequency); + } + + private: + int m_sampleRate; + int m_centerFrequency; + + MsgConfigureChannelizer(int sampleRate, int centerFrequency) : + Message(), + m_sampleRate(sampleRate), + m_centerFrequency(centerFrequency) + { } + }; + + DSDDemod(DeviceSourceAPI *deviceAPI); + ~DSDDemod(); + void setScopeSink(BasebandSampleSink* sampleSink) { m_scope = sampleSink; } + + void configureMyPosition(MessageQueue* messageQueue, float myLatitude, float myLongitude); + + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); + virtual void start(); + virtual void stop(); + virtual bool handleMessage(const Message& cmd); + + double getMagSq() { return m_magsq; } + bool getSquelchOpen() const { return m_squelchOpen; } + + const DSDDecoder& getDecoder() const { return m_dsdDecoder; } + + void getMagSqLevels(double& avg, double& peak, int& nbSamples) + { + avg = m_magsqCount == 0 ? 1e-10 : m_magsqSum / m_magsqCount; + m_magsq = avg; + peak = m_magsqPeak == 0.0 ? 1e-10 : m_magsqPeak; + nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; + m_magsqSum = 0.0f; + m_magsqPeak = 0.0f; + m_magsqCount = 0; + } + + static const QString m_channelID; + +private: + class MsgConfigureMyPosition : public Message { + MESSAGE_CLASS_DECLARATION + + public: + float getMyLatitude() const { return m_myLatitude; } + float getMyLongitude() const { return m_myLongitude; } + + static MsgConfigureMyPosition* create(float myLatitude, float myLongitude) + { + return new MsgConfigureMyPosition(myLatitude, myLongitude); + } + + private: + float m_myLatitude; + float m_myLongitude; + + MsgConfigureMyPosition(float myLatitude, float myLongitude) : + m_myLatitude(myLatitude), + m_myLongitude(myLongitude) + {} + }; + + enum RateState { + RSInitialFill, + RSRunning + }; + + DSDDemodSettings m_settings; + + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; + + NCO m_nco; + Interpolator m_interpolator; + Real m_interpolatorDistance; + Real m_interpolatorDistanceRemain; + int m_sampleCount; + int m_squelchCount; + int m_squelchGate; + + double m_squelchLevel; + bool m_squelchOpen; + + MovingAverage m_movingAverage; + double m_magsq; + double m_magsqSum; + double m_magsqPeak; + int m_magsqCount; + + Real m_fmExcursion; + + SampleVector m_scopeSampleBuffer; + AudioVector m_audioBuffer; + uint m_audioBufferFill; + qint16 *m_sampleBuffer; //!< samples ring buffer + int m_sampleBufferIndex; + + AudioFifo m_audioFifo1; + AudioFifo m_audioFifo2; + BasebandSampleSink* m_scope; + bool m_scopeEnabled; + + DSDDecoder m_dsdDecoder; + QMutex m_settingsMutex; + + PhaseDiscriminators m_phaseDiscri; + UDPSink *m_udpBufferAudio; + + static const int m_udpBlockSize; + + void applySettings(DSDDemodSettings& settings, bool force = false); +}; + +#endif // INCLUDE_DSDDEMOD_H diff --git a/plugins/channelrx/demoddsd/dsddemodgui.cpp b/plugins/channelrx/demoddsd/dsddemodgui.cpp index 16aa89359..88eb2e04a 100644 --- a/plugins/channelrx/demoddsd/dsddemodgui.cpp +++ b/plugins/channelrx/demoddsd/dsddemodgui.cpp @@ -38,8 +38,6 @@ #include "dsddemodbaudrates.h" #include "dsddemod.h" -const QString DSDDemodGUI::m_channelID = "sdrangel.channel.dsddemod"; - DSDDemodGUI* DSDDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { DSDDemodGUI* gui = new DSDDemodGUI(pluginAPI, deviceUISet); @@ -281,7 +279,7 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, QWidget connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(DSDDemod::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/demoddsd/dsddemodgui.h b/plugins/channelrx/demoddsd/dsddemodgui.h index 46a9a7362..1edad84b4 100644 --- a/plugins/channelrx/demoddsd/dsddemodgui.h +++ b/plugins/channelrx/demoddsd/dsddemodgui.h @@ -57,8 +57,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void formatStatusText(); void channelMarkerChanged(); diff --git a/plugins/channelrx/demoddsd/dsddemodplugin.cpp b/plugins/channelrx/demoddsd/dsddemodplugin.cpp index 6fdd2ae7f..df46e57bd 100644 --- a/plugins/channelrx/demoddsd/dsddemodplugin.cpp +++ b/plugins/channelrx/demoddsd/dsddemodplugin.cpp @@ -21,6 +21,7 @@ #include #include "plugin/pluginapi.h" #include "dsddemodgui.h" +#include "dsddemod.h" const PluginDescriptor DSDDemodPlugin::m_pluginDescriptor = { QString("DSD Demodulator"), @@ -47,16 +48,27 @@ void DSDDemodPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register DSD demodulator - m_pluginAPI->registerRxChannel(DSDDemodGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(DSDDemod::m_channelID, this); } PluginInstanceGUI* DSDDemodPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == DSDDemodGUI::m_channelID) + if(channelName == DSDDemod::m_channelID) { DSDDemodGUI* gui = DSDDemodGUI::create(m_pluginAPI, deviceUISet); return gui; } else { - return NULL; + return 0; } } + +BasebandSampleSink* DSDDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == DSDDemod::m_channelID) + { + DSDDemod* sink = new DSDDemod(deviceAPI); + return sink; + } else { + return 0; + } +} diff --git a/plugins/channelrx/demoddsd/dsddemodplugin.h b/plugins/channelrx/demoddsd/dsddemodplugin.h index 5342f8b21..a996fb1e3 100644 --- a/plugins/channelrx/demoddsd/dsddemodplugin.h +++ b/plugins/channelrx/demoddsd/dsddemodplugin.h @@ -22,6 +22,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class DSDDemodPlugin : public QObject, PluginInterface { Q_OBJECT @@ -35,6 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodlora/lorademod.cpp b/plugins/channelrx/demodlora/lorademod.cpp index 637867163..a731d03e2 100644 --- a/plugins/channelrx/demodlora/lorademod.cpp +++ b/plugins/channelrx/demodlora/lorademod.cpp @@ -31,6 +31,8 @@ MESSAGE_CLASS_DEFINITION(LoRaDemod::MsgConfigureLoRaDemod, Message) MESSAGE_CLASS_DEFINITION(LoRaDemod::MsgConfigureChannelizer, Message) +const QString LoRaDemod::m_channelID = "de.maintech.sdrangelove.channel.lora"; + LoRaDemod::LoRaDemod(DeviceSourceAPI* deviceAPI) : m_deviceAPI(deviceAPI), m_sampleSink(0), diff --git a/plugins/channelrx/demodlora/lorademod.h b/plugins/channelrx/demodlora/lorademod.h index 032016e25..1bb53d7f2 100644 --- a/plugins/channelrx/demodlora/lorademod.h +++ b/plugins/channelrx/demodlora/lorademod.h @@ -96,6 +96,8 @@ public: virtual void stop(); virtual bool handleMessage(const Message& cmd); + static const QString m_channelID; + private: int detect(Complex sample, Complex angle); void dumpRaw(void); diff --git a/plugins/channelrx/demodlora/lorademodgui.cpp b/plugins/channelrx/demodlora/lorademodgui.cpp index 9920453fd..56f897ede 100644 --- a/plugins/channelrx/demodlora/lorademodgui.cpp +++ b/plugins/channelrx/demodlora/lorademodgui.cpp @@ -16,8 +16,6 @@ #include "lorademod.h" #include "lorademodgui.h" -const QString LoRaDemodGUI::m_channelID = "de.maintech.sdrangelove.channel.lora"; - LoRaDemodGUI* LoRaDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { LoRaDemodGUI* gui = new LoRaDemodGUI(pluginAPI, deviceUISet); @@ -153,7 +151,7 @@ LoRaDemodGUI::LoRaDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, QWidg connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(LoRaDemod::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/demodlora/lorademodgui.h b/plugins/channelrx/demodlora/lorademodgui.h index 343bbcd02..cb0458fb8 100644 --- a/plugins/channelrx/demodlora/lorademodgui.h +++ b/plugins/channelrx/demodlora/lorademodgui.h @@ -35,8 +35,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void viewChanged(); void on_BW_valueChanged(int value); diff --git a/plugins/channelrx/demodlora/loraplugin.cpp b/plugins/channelrx/demodlora/loraplugin.cpp index f777ed66c..f357de6b3 100644 --- a/plugins/channelrx/demodlora/loraplugin.cpp +++ b/plugins/channelrx/demodlora/loraplugin.cpp @@ -3,6 +3,7 @@ #include "loraplugin.h" #include "lorademodgui.h" +#include "lorademod.h" const PluginDescriptor LoRaPlugin::m_pluginDescriptor = { QString("LoRa Demodulator"), @@ -29,16 +30,27 @@ void LoRaPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register demodulator - m_pluginAPI->registerRxChannel(LoRaDemodGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(LoRaDemod::m_channelID, this); } PluginInstanceGUI* LoRaPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == LoRaDemodGUI::m_channelID) + if(channelName == LoRaDemod::m_channelID) { LoRaDemodGUI* gui = LoRaDemodGUI::create(m_pluginAPI, deviceUISet); return gui; } else { - return NULL; + return 0; } } + +BasebandSampleSink* LoRaPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == LoRaDemod::m_channelID) + { + LoRaDemod* sink = new LoRaDemod(deviceAPI); + return sink; + } else { + return 0; + } +} diff --git a/plugins/channelrx/demodlora/loraplugin.h b/plugins/channelrx/demodlora/loraplugin.h index 2745db53d..1a2ead455 100644 --- a/plugins/channelrx/demodlora/loraplugin.h +++ b/plugins/channelrx/demodlora/loraplugin.h @@ -5,6 +5,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class LoRaPlugin : public QObject, PluginInterface { Q_OBJECT @@ -18,6 +19,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodnfm/nfmdemod.cpp b/plugins/channelrx/demodnfm/nfmdemod.cpp index a1d1fdbb9..8fd641a97 100644 --- a/plugins/channelrx/demodnfm/nfmdemod.cpp +++ b/plugins/channelrx/demodnfm/nfmdemod.cpp @@ -35,6 +35,8 @@ MESSAGE_CLASS_DEFINITION(NFMDemod::MsgConfigureNFMDemod, Message) MESSAGE_CLASS_DEFINITION(NFMDemod::MsgConfigureChannelizer, Message) MESSAGE_CLASS_DEFINITION(NFMDemod::MsgReportCTCSSFreq, Message) +const QString NFMDemod::m_channelID = "de.maintech.sdrangelove.channel.nfm"; + static const double afSqTones[2] = {1000.0, 6000.0}; // {1200.0, 8000.0}; const int NFMDemod::m_udpBlockSize = 512; diff --git a/plugins/channelrx/demodnfm/nfmdemod.h b/plugins/channelrx/demodnfm/nfmdemod.h index decaeada0..c0d403c0f 100644 --- a/plugins/channelrx/demodnfm/nfmdemod.h +++ b/plugins/channelrx/demodnfm/nfmdemod.h @@ -138,6 +138,8 @@ public: m_magsqCount = 0; } + static const QString m_channelID; + private: enum RateState { RSInitialFill, diff --git a/plugins/channelrx/demodnfm/nfmdemodgui.cpp b/plugins/channelrx/demodnfm/nfmdemodgui.cpp index edb2e2fc0..2767a2178 100644 --- a/plugins/channelrx/demodnfm/nfmdemodgui.cpp +++ b/plugins/channelrx/demodnfm/nfmdemodgui.cpp @@ -16,8 +16,6 @@ #include "mainwindow.h" #include "nfmdemod.h" -const QString NFMDemodGUI::m_channelID = "de.maintech.sdrangelove.channel.nfm"; - NFMDemodGUI* NFMDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { NFMDemodGUI* gui = new NFMDemodGUI(pluginAPI, deviceUISet); @@ -277,7 +275,7 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, QWidget connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(NFMDemod::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/demodnfm/nfmdemodgui.h b/plugins/channelrx/demodnfm/nfmdemodgui.h index 317ce2f4f..3d5c2b6ad 100644 --- a/plugins/channelrx/demodnfm/nfmdemodgui.h +++ b/plugins/channelrx/demodnfm/nfmdemodgui.h @@ -38,8 +38,6 @@ public: virtual bool handleMessage(const Message& message); void setCtcssFreq(Real ctcssFreq); - static const QString m_channelID; - private slots: void channelMarkerChanged(); void on_deltaFrequency_changed(qint64 value); diff --git a/plugins/channelrx/demodnfm/nfmplugin.cpp b/plugins/channelrx/demodnfm/nfmplugin.cpp index 3536a243e..173362284 100644 --- a/plugins/channelrx/demodnfm/nfmplugin.cpp +++ b/plugins/channelrx/demodnfm/nfmplugin.cpp @@ -3,6 +3,7 @@ #include "nfmplugin.h" #include "nfmdemodgui.h" +#include "nfmdemod.h" const PluginDescriptor NFMPlugin::m_pluginDescriptor = { QString("NFM Demodulator"), @@ -29,15 +30,26 @@ void NFMPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register NFM demodulator - m_pluginAPI->registerRxChannel(NFMDemodGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(NFMDemod::m_channelID, this); } PluginInstanceGUI* NFMPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == NFMDemodGUI::m_channelID) { + if(channelName == NFMDemod::m_channelID) { NFMDemodGUI* gui = NFMDemodGUI::create(m_pluginAPI, deviceUISet); return gui; } else { - return NULL; + return 0; } } + +BasebandSampleSink* NFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == NFMDemod::m_channelID) + { + NFMDemod* sink = new NFMDemod(deviceAPI); + return sink; + } else { + return 0; + } +} diff --git a/plugins/channelrx/demodnfm/nfmplugin.h b/plugins/channelrx/demodnfm/nfmplugin.h index d43e9c122..2e28e63f5 100644 --- a/plugins/channelrx/demodnfm/nfmplugin.h +++ b/plugins/channelrx/demodnfm/nfmplugin.h @@ -5,6 +5,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class NFMPlugin : public QObject, PluginInterface { Q_OBJECT @@ -18,6 +19,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodssb/ssbdemod.cpp b/plugins/channelrx/demodssb/ssbdemod.cpp index a6efae9e4..2932fc348 100644 --- a/plugins/channelrx/demodssb/ssbdemod.cpp +++ b/plugins/channelrx/demodssb/ssbdemod.cpp @@ -34,6 +34,8 @@ MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemod, Message) MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemodPrivate, Message) MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureChannelizer, Message) +const QString SSBDemod::m_channelID = "de.maintech.sdrangelove.channel.ssb"; + SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) : m_deviceAPI(deviceAPI), m_audioBinaual(false), diff --git a/plugins/channelrx/demodssb/ssbdemod.h b/plugins/channelrx/demodssb/ssbdemod.h index f5b148f3d..4357c45f4 100644 --- a/plugins/channelrx/demodssb/ssbdemod.h +++ b/plugins/channelrx/demodssb/ssbdemod.h @@ -1,270 +1,272 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // -// written by Christian Daniel // -// // -// 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_SSBDEMOD_H -#define INCLUDE_SSBDEMOD_H - -#include -#include - -#include -#include "dsp/ncof.h" -#include "dsp/interpolator.h" -#include "dsp/fftfilt.h" -#include "dsp/agc.h" -#include "audio/audiofifo.h" -#include "util/message.h" - -#include "ssbdemodsettings.h" - -#define ssbFftLen 1024 -#define agcTarget 3276.8 // -10 dB amplitude => -20 dB power: center of normal signal - -class DeviceSourceAPI; -class ThreadedBasebandSampleSink; -class DownChannelizer; - -class SSBDemod : public BasebandSampleSink { -public: - class MsgConfigureSSBDemod : public Message { - MESSAGE_CLASS_DECLARATION - - public: - const SSBDemodSettings& getSettings() const { return m_settings; } - bool getForce() const { return m_force; } - - static MsgConfigureSSBDemod* create(const SSBDemodSettings& settings, bool force) - { - return new MsgConfigureSSBDemod(settings, force); - } - - private: - SSBDemodSettings m_settings; - bool m_force; - - MsgConfigureSSBDemod(const SSBDemodSettings& settings, bool force) : - Message(), - m_settings(settings), - m_force(force) - { } - }; - - class MsgConfigureChannelizer : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getSampleRate() const { return m_sampleRate; } - int getCenterFrequency() const { return m_centerFrequency; } - - static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) - { - return new MsgConfigureChannelizer(sampleRate, centerFrequency); - } - - private: - int m_sampleRate; - int m_centerFrequency; - - MsgConfigureChannelizer(int sampleRate, int centerFrequency) : - Message(), - m_sampleRate(sampleRate), - m_centerFrequency(centerFrequency) - { } - }; - - SSBDemod(DeviceSourceAPI *deviceAPI); - virtual ~SSBDemod(); - void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; } - - void configure(MessageQueue* messageQueue, - Real Bandwidth, - Real LowCutoff, - Real volume, - int spanLog2, - bool audioBinaural, - bool audioFlipChannels, - bool dsb, - bool audioMute, - bool agc, - bool agcClamping, - int agcTimeLog2, - int agcPowerThreshold, - int agcThresholdGate); - - virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); - virtual void start(); - virtual void stop(); - virtual bool handleMessage(const Message& cmd); - - double getMagSq() const { return m_magsq; } - bool getAudioActive() const { return m_audioActive; } - - void getMagSqLevels(double& avg, double& peak, int& nbSamples) - { - avg = m_magsqCount == 0 ? 1e-10 : m_magsqSum / m_magsqCount; - m_magsq = avg; - peak = m_magsqPeak == 0.0 ? 1e-10 : m_magsqPeak; - nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; - m_magsqSum = 0.0f; - m_magsqPeak = 0.0f; - m_magsqCount = 0; - } - -private: - class MsgConfigureSSBDemodPrivate : public Message { - MESSAGE_CLASS_DECLARATION - - public: - Real getBandwidth() const { return m_Bandwidth; } - Real getLoCutoff() const { return m_LowCutoff; } - Real getVolume() const { return m_volume; } - int getSpanLog2() const { return m_spanLog2; } - bool getAudioBinaural() const { return m_audioBinaural; } - bool getAudioFlipChannels() const { return m_audioFlipChannels; } - bool getDSB() const { return m_dsb; } - bool getAudioMute() const { return m_audioMute; } - bool getAGC() const { return m_agc; } - bool getAGCClamping() const { return m_agcClamping; } - int getAGCTimeLog2() const { return m_agcTimeLog2; } - int getAGCPowerThershold() const { return m_agcPowerThreshold; } - int getAGCThersholdGate() const { return m_agcThresholdGate; } - - static MsgConfigureSSBDemodPrivate* create(Real Bandwidth, - Real LowCutoff, - Real volume, - int spanLog2, - bool audioBinaural, - bool audioFlipChannels, - bool dsb, - bool audioMute, - bool agc, - bool agcClamping, - int agcTimeLog2, - int agcPowerThreshold, - int agcThresholdGate) - { - return new MsgConfigureSSBDemodPrivate( - Bandwidth, - LowCutoff, - volume, - spanLog2, - audioBinaural, - audioFlipChannels, - dsb, - audioMute, - agc, - agcClamping, - agcTimeLog2, - agcPowerThreshold, - agcThresholdGate); - } - - private: - Real m_Bandwidth; - Real m_LowCutoff; - Real m_volume; - int m_spanLog2; - bool m_audioBinaural; - bool m_audioFlipChannels; - bool m_dsb; - bool m_audioMute; - bool m_agc; - bool m_agcClamping; - int m_agcTimeLog2; - int m_agcPowerThreshold; - int m_agcThresholdGate; - - MsgConfigureSSBDemodPrivate(Real Bandwidth, - Real LowCutoff, - Real volume, - int spanLog2, - bool audioBinaural, - bool audioFlipChannels, - bool dsb, - bool audioMute, - bool agc, - bool agcClamping, - int agcTimeLog2, - int agcPowerThreshold, - int agcThresholdGate) : - Message(), - m_Bandwidth(Bandwidth), - m_LowCutoff(LowCutoff), - m_volume(volume), - m_spanLog2(spanLog2), - m_audioBinaural(audioBinaural), - m_audioFlipChannels(audioFlipChannels), - m_dsb(dsb), - m_audioMute(audioMute), - m_agc(agc), - m_agcClamping(agcClamping), - m_agcTimeLog2(agcTimeLog2), - m_agcPowerThreshold(agcPowerThreshold), - m_agcThresholdGate(agcThresholdGate) - { } - }; - - DeviceSourceAPI *m_deviceAPI; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; - SSBDemodSettings m_settings; - - Real m_Bandwidth; - Real m_LowCutoff; - Real m_volume; - int m_spanLog2; - fftfilt::cmplx m_sum; - int m_undersampleCount; - int m_sampleRate; - int m_frequency; - bool m_audioBinaual; - bool m_audioFlipChannels; - bool m_usb; - bool m_dsb; - bool m_audioMute; - double m_magsq; - double m_magsqSum; - double m_magsqPeak; - int m_magsqCount; - MagAGC m_agc; - bool m_agcActive; - bool m_agcClamping; - int m_agcNbSamples; //!< number of audio (48 kHz) samples for AGC averaging - double m_agcPowerThreshold; //!< AGC power threshold (linear) - int m_agcThresholdGate; //!< Gate length in number of samples befor threshold triggers - bool m_audioActive; //!< True if an audio signal is produced (no AGC or AGC and above threshold) - - NCOF m_nco; - Interpolator m_interpolator; - Real m_sampleDistanceRemain; - fftfilt* SSBFilter; - fftfilt* DSBFilter; - - BasebandSampleSink* m_sampleSink; - SampleVector m_sampleBuffer; - - AudioVector m_audioBuffer; - uint m_audioBufferFill; - AudioFifo m_audioFifo; - quint32 m_audioSampleRate; - - QMutex m_settingsMutex; - - void applySettings(const SSBDemodSettings& settings, bool force = false); -}; - -#endif // INCLUDE_SSBDEMOD_H +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // +// written by Christian Daniel // +// // +// 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_SSBDEMOD_H +#define INCLUDE_SSBDEMOD_H + +#include +#include + +#include +#include "dsp/ncof.h" +#include "dsp/interpolator.h" +#include "dsp/fftfilt.h" +#include "dsp/agc.h" +#include "audio/audiofifo.h" +#include "util/message.h" + +#include "ssbdemodsettings.h" + +#define ssbFftLen 1024 +#define agcTarget 3276.8 // -10 dB amplitude => -20 dB power: center of normal signal + +class DeviceSourceAPI; +class ThreadedBasebandSampleSink; +class DownChannelizer; + +class SSBDemod : public BasebandSampleSink { +public: + class MsgConfigureSSBDemod : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const SSBDemodSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureSSBDemod* create(const SSBDemodSettings& settings, bool force) + { + return new MsgConfigureSSBDemod(settings, force); + } + + private: + SSBDemodSettings m_settings; + bool m_force; + + MsgConfigureSSBDemod(const SSBDemodSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgConfigureChannelizer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + int getCenterFrequency() const { return m_centerFrequency; } + + static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) + { + return new MsgConfigureChannelizer(sampleRate, centerFrequency); + } + + private: + int m_sampleRate; + int m_centerFrequency; + + MsgConfigureChannelizer(int sampleRate, int centerFrequency) : + Message(), + m_sampleRate(sampleRate), + m_centerFrequency(centerFrequency) + { } + }; + + SSBDemod(DeviceSourceAPI *deviceAPI); + virtual ~SSBDemod(); + void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; } + + void configure(MessageQueue* messageQueue, + Real Bandwidth, + Real LowCutoff, + Real volume, + int spanLog2, + bool audioBinaural, + bool audioFlipChannels, + bool dsb, + bool audioMute, + bool agc, + bool agcClamping, + int agcTimeLog2, + int agcPowerThreshold, + int agcThresholdGate); + + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); + virtual void start(); + virtual void stop(); + virtual bool handleMessage(const Message& cmd); + + double getMagSq() const { return m_magsq; } + bool getAudioActive() const { return m_audioActive; } + + void getMagSqLevels(double& avg, double& peak, int& nbSamples) + { + avg = m_magsqCount == 0 ? 1e-10 : m_magsqSum / m_magsqCount; + m_magsq = avg; + peak = m_magsqPeak == 0.0 ? 1e-10 : m_magsqPeak; + nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; + m_magsqSum = 0.0f; + m_magsqPeak = 0.0f; + m_magsqCount = 0; + } + + static const QString m_channelID; + +private: + class MsgConfigureSSBDemodPrivate : public Message { + MESSAGE_CLASS_DECLARATION + + public: + Real getBandwidth() const { return m_Bandwidth; } + Real getLoCutoff() const { return m_LowCutoff; } + Real getVolume() const { return m_volume; } + int getSpanLog2() const { return m_spanLog2; } + bool getAudioBinaural() const { return m_audioBinaural; } + bool getAudioFlipChannels() const { return m_audioFlipChannels; } + bool getDSB() const { return m_dsb; } + bool getAudioMute() const { return m_audioMute; } + bool getAGC() const { return m_agc; } + bool getAGCClamping() const { return m_agcClamping; } + int getAGCTimeLog2() const { return m_agcTimeLog2; } + int getAGCPowerThershold() const { return m_agcPowerThreshold; } + int getAGCThersholdGate() const { return m_agcThresholdGate; } + + static MsgConfigureSSBDemodPrivate* create(Real Bandwidth, + Real LowCutoff, + Real volume, + int spanLog2, + bool audioBinaural, + bool audioFlipChannels, + bool dsb, + bool audioMute, + bool agc, + bool agcClamping, + int agcTimeLog2, + int agcPowerThreshold, + int agcThresholdGate) + { + return new MsgConfigureSSBDemodPrivate( + Bandwidth, + LowCutoff, + volume, + spanLog2, + audioBinaural, + audioFlipChannels, + dsb, + audioMute, + agc, + agcClamping, + agcTimeLog2, + agcPowerThreshold, + agcThresholdGate); + } + + private: + Real m_Bandwidth; + Real m_LowCutoff; + Real m_volume; + int m_spanLog2; + bool m_audioBinaural; + bool m_audioFlipChannels; + bool m_dsb; + bool m_audioMute; + bool m_agc; + bool m_agcClamping; + int m_agcTimeLog2; + int m_agcPowerThreshold; + int m_agcThresholdGate; + + MsgConfigureSSBDemodPrivate(Real Bandwidth, + Real LowCutoff, + Real volume, + int spanLog2, + bool audioBinaural, + bool audioFlipChannels, + bool dsb, + bool audioMute, + bool agc, + bool agcClamping, + int agcTimeLog2, + int agcPowerThreshold, + int agcThresholdGate) : + Message(), + m_Bandwidth(Bandwidth), + m_LowCutoff(LowCutoff), + m_volume(volume), + m_spanLog2(spanLog2), + m_audioBinaural(audioBinaural), + m_audioFlipChannels(audioFlipChannels), + m_dsb(dsb), + m_audioMute(audioMute), + m_agc(agc), + m_agcClamping(agcClamping), + m_agcTimeLog2(agcTimeLog2), + m_agcPowerThreshold(agcPowerThreshold), + m_agcThresholdGate(agcThresholdGate) + { } + }; + + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; + SSBDemodSettings m_settings; + + Real m_Bandwidth; + Real m_LowCutoff; + Real m_volume; + int m_spanLog2; + fftfilt::cmplx m_sum; + int m_undersampleCount; + int m_sampleRate; + int m_frequency; + bool m_audioBinaual; + bool m_audioFlipChannels; + bool m_usb; + bool m_dsb; + bool m_audioMute; + double m_magsq; + double m_magsqSum; + double m_magsqPeak; + int m_magsqCount; + MagAGC m_agc; + bool m_agcActive; + bool m_agcClamping; + int m_agcNbSamples; //!< number of audio (48 kHz) samples for AGC averaging + double m_agcPowerThreshold; //!< AGC power threshold (linear) + int m_agcThresholdGate; //!< Gate length in number of samples befor threshold triggers + bool m_audioActive; //!< True if an audio signal is produced (no AGC or AGC and above threshold) + + NCOF m_nco; + Interpolator m_interpolator; + Real m_sampleDistanceRemain; + fftfilt* SSBFilter; + fftfilt* DSBFilter; + + BasebandSampleSink* m_sampleSink; + SampleVector m_sampleBuffer; + + AudioVector m_audioBuffer; + uint m_audioBufferFill; + AudioFifo m_audioFifo; + quint32 m_audioSampleRate; + + QMutex m_settingsMutex; + + void applySettings(const SSBDemodSettings& settings, bool force = false); +}; + +#endif // INCLUDE_SSBDEMOD_H diff --git a/plugins/channelrx/demodssb/ssbdemodgui.cpp b/plugins/channelrx/demodssb/ssbdemodgui.cpp index 95cb97b0b..e273c6702 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.cpp +++ b/plugins/channelrx/demodssb/ssbdemodgui.cpp @@ -17,8 +17,6 @@ #include "mainwindow.h" #include "ssbdemod.h" -const QString SSBDemodGUI::m_channelID = "de.maintech.sdrangelove.channel.ssb"; - SSBDemodGUI* SSBDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { SSBDemodGUI* gui = new SSBDemodGUI(pluginAPI, deviceUISet); @@ -253,7 +251,7 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, QWidget connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(SSBDemod::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/demodssb/ssbdemodgui.h b/plugins/channelrx/demodssb/ssbdemodgui.h index a812f9eb7..9bed86064 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.h +++ b/plugins/channelrx/demodssb/ssbdemodgui.h @@ -37,8 +37,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void viewChanged(); void on_deltaFrequency_changed(qint64 value); diff --git a/plugins/channelrx/demodssb/ssbplugin.cpp b/plugins/channelrx/demodssb/ssbplugin.cpp index f0ce112ed..c29465200 100644 --- a/plugins/channelrx/demodssb/ssbplugin.cpp +++ b/plugins/channelrx/demodssb/ssbplugin.cpp @@ -4,6 +4,7 @@ #include #include "plugin/pluginapi.h" #include "ssbdemodgui.h" +#include "ssbdemod.h" const PluginDescriptor SSBPlugin::m_pluginDescriptor = { QString("SSB Demodulator"), @@ -30,16 +31,27 @@ void SSBPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register demodulator - m_pluginAPI->registerRxChannel(SSBDemodGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(SSBDemod::m_channelID, this); } PluginInstanceGUI* SSBPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == SSBDemodGUI::m_channelID) + if(channelName == SSBDemod::m_channelID) { SSBDemodGUI* gui = SSBDemodGUI::create(m_pluginAPI, deviceUISet); return gui; } else { - return NULL; + return 0; } } + +BasebandSampleSink* SSBPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == SSBDemod::m_channelID) + { + SSBDemod* sink = new SSBDemod(deviceAPI); + return sink; + } else { + return 0; + } +} diff --git a/plugins/channelrx/demodssb/ssbplugin.h b/plugins/channelrx/demodssb/ssbplugin.h index b9c52b929..ba71a0381 100644 --- a/plugins/channelrx/demodssb/ssbplugin.h +++ b/plugins/channelrx/demodssb/ssbplugin.h @@ -5,6 +5,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class SSBPlugin : public QObject, PluginInterface { Q_OBJECT @@ -18,6 +19,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodwfm/wfmdemod.cpp b/plugins/channelrx/demodwfm/wfmdemod.cpp index 4c5a672ef..4673e7242 100644 --- a/plugins/channelrx/demodwfm/wfmdemod.cpp +++ b/plugins/channelrx/demodwfm/wfmdemod.cpp @@ -33,6 +33,8 @@ MESSAGE_CLASS_DEFINITION(WFMDemod::MsgConfigureWFMDemod, Message) MESSAGE_CLASS_DEFINITION(WFMDemod::MsgConfigureChannelizer, Message) +const QString WFMDemod::m_channelID = "de.maintech.sdrangelove.channel.wfm"; + WFMDemod::WFMDemod(DeviceSourceAPI* deviceAPI) : m_deviceAPI(deviceAPI), m_squelchOpen(false), diff --git a/plugins/channelrx/demodwfm/wfmdemod.h b/plugins/channelrx/demodwfm/wfmdemod.h index 39740bd07..cb98dbcd2 100644 --- a/plugins/channelrx/demodwfm/wfmdemod.h +++ b/plugins/channelrx/demodwfm/wfmdemod.h @@ -109,6 +109,8 @@ public: m_magsqCount = 0; } + static const QString m_channelID; + private: enum RateState { RSInitialFill, diff --git a/plugins/channelrx/demodwfm/wfmdemodgui.cpp b/plugins/channelrx/demodwfm/wfmdemodgui.cpp index 11e57216c..0b7cde1bb 100644 --- a/plugins/channelrx/demodwfm/wfmdemodgui.cpp +++ b/plugins/channelrx/demodwfm/wfmdemodgui.cpp @@ -18,8 +18,6 @@ #include "wfmdemod.h" -const QString WFMDemodGUI::m_channelID = "de.maintech.sdrangelove.channel.wfm"; - WFMDemodGUI* WFMDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { WFMDemodGUI* gui = new WFMDemodGUI(pluginAPI, deviceUISet); @@ -187,7 +185,7 @@ WFMDemodGUI::WFMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, QWidget connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(WFMDemod::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/demodwfm/wfmdemodgui.h b/plugins/channelrx/demodwfm/wfmdemodgui.h index ac6379066..9fe62a0be 100644 --- a/plugins/channelrx/demodwfm/wfmdemodgui.h +++ b/plugins/channelrx/demodwfm/wfmdemodgui.h @@ -36,8 +36,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void channelMarkerChanged(); void on_deltaFrequency_changed(qint64 value); diff --git a/plugins/channelrx/demodwfm/wfmplugin.cpp b/plugins/channelrx/demodwfm/wfmplugin.cpp index 3d56a2891..0a7432f80 100644 --- a/plugins/channelrx/demodwfm/wfmplugin.cpp +++ b/plugins/channelrx/demodwfm/wfmplugin.cpp @@ -4,6 +4,7 @@ #include "plugin/pluginapi.h" #include "wfmdemodgui.h" +#include "wfmdemod.h" const PluginDescriptor WFMPlugin::m_pluginDescriptor = { QString("WFM Demodulator"), @@ -30,16 +31,27 @@ void WFMPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register WFM demodulator - m_pluginAPI->registerRxChannel(WFMDemodGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(WFMDemod::m_channelID, this); } PluginInstanceGUI* WFMPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == WFMDemodGUI::m_channelID) + if(channelName == WFMDemod::m_channelID) { WFMDemodGUI* gui = WFMDemodGUI::create(m_pluginAPI, deviceUISet); return gui; } else { - return NULL; + return 0; } } + +BasebandSampleSink* WFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == WFMDemod::m_channelID) + { + WFMDemod* sink = new WFMDemod(deviceAPI); + return sink; + } else { + return 0; + } +} diff --git a/plugins/channelrx/demodwfm/wfmplugin.h b/plugins/channelrx/demodwfm/wfmplugin.h index 077cb78fb..30caa534c 100644 --- a/plugins/channelrx/demodwfm/wfmplugin.h +++ b/plugins/channelrx/demodwfm/wfmplugin.h @@ -5,6 +5,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class WFMPlugin : public QObject, PluginInterface { Q_OBJECT @@ -18,6 +19,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/tcpsrc/tcpsrc.cpp b/plugins/channelrx/tcpsrc/tcpsrc.cpp index 0f749965b..739d5260d 100644 --- a/plugins/channelrx/tcpsrc/tcpsrc.cpp +++ b/plugins/channelrx/tcpsrc/tcpsrc.cpp @@ -30,6 +30,8 @@ MESSAGE_CLASS_DEFINITION(TCPSrc::MsgConfigureChannelizer, Message) MESSAGE_CLASS_DEFINITION(TCPSrc::MsgTCPSrcConnection, Message) MESSAGE_CLASS_DEFINITION(TCPSrc::MsgTCPSrcSpectrum, Message) +const QString TCPSrc::m_channelID = "sdrangel.channel.tcpsrc"; + TCPSrc::TCPSrc(DeviceSourceAPI* deviceAPI) : m_deviceAPI(deviceAPI), m_settingsMutex(QMutex::Recursive) diff --git a/plugins/channelrx/tcpsrc/tcpsrc.h b/plugins/channelrx/tcpsrc/tcpsrc.h index ac58155f0..36931185b 100644 --- a/plugins/channelrx/tcpsrc/tcpsrc.h +++ b/plugins/channelrx/tcpsrc/tcpsrc.h @@ -113,6 +113,8 @@ public: virtual void stop(); virtual bool handleMessage(const Message& cmd); + static const QString m_channelID; + protected: class MsgTCPSrcSpectrum : public Message { MESSAGE_CLASS_DECLARATION diff --git a/plugins/channelrx/tcpsrc/tcpsrcgui.cpp b/plugins/channelrx/tcpsrc/tcpsrcgui.cpp index 8965e911f..6c53c09bc 100644 --- a/plugins/channelrx/tcpsrc/tcpsrcgui.cpp +++ b/plugins/channelrx/tcpsrc/tcpsrcgui.cpp @@ -12,8 +12,6 @@ #include "mainwindow.h" #include "tcpsrc.h" -const QString TCPSrcGUI::m_channelID = "sdrangel.channel.tcpsrc"; - TCPSrcGUI* TCPSrcGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { TCPSrcGUI* gui = new TCPSrcGUI(pluginAPI, deviceUISet); @@ -165,7 +163,7 @@ TCPSrcGUI::TCPSrcGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, QWidget* pa connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(TCPSrc::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/tcpsrc/tcpsrcgui.h b/plugins/channelrx/tcpsrc/tcpsrcgui.h index a4697732d..6c34d96a8 100644 --- a/plugins/channelrx/tcpsrc/tcpsrcgui.h +++ b/plugins/channelrx/tcpsrc/tcpsrcgui.h @@ -39,8 +39,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void channelMarkerChanged(); void on_deltaFrequency_changed(qint64 value); diff --git a/plugins/channelrx/tcpsrc/tcpsrcplugin.cpp b/plugins/channelrx/tcpsrc/tcpsrcplugin.cpp index c6baaedb3..0edf913f6 100644 --- a/plugins/channelrx/tcpsrc/tcpsrcplugin.cpp +++ b/plugins/channelrx/tcpsrc/tcpsrcplugin.cpp @@ -4,6 +4,7 @@ #include "plugin/pluginapi.h" #include "tcpsrcgui.h" +#include "tcpsrc.h" const PluginDescriptor TCPSrcPlugin::m_pluginDescriptor = { QString("TCP Channel Source"), @@ -30,18 +31,29 @@ void TCPSrcPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register TCP Channel Source - m_pluginAPI->registerRxChannel(TCPSrcGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(TCPSrc::m_channelID, this); } PluginInstanceGUI* TCPSrcPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == TCPSrcGUI::m_channelID) + if(channelName == TCPSrc::m_channelID) { TCPSrcGUI* gui = TCPSrcGUI::create(m_pluginAPI, deviceUISet); // deviceAPI->registerChannelInstance("sdrangel.channel.tcpsrc", gui); // m_pluginAPI->addChannelRollup(gui); return gui; } else { - return NULL; + return 0; } } + +BasebandSampleSink* TCPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == TCPSrc::m_channelID) + { + TCPSrc* sink = new TCPSrc(deviceAPI); + return sink; + } else { + return 0; + } +} diff --git a/plugins/channelrx/tcpsrc/tcpsrcplugin.h b/plugins/channelrx/tcpsrc/tcpsrcplugin.h index dcd15ea22..162285f21 100644 --- a/plugins/channelrx/tcpsrc/tcpsrcplugin.h +++ b/plugins/channelrx/tcpsrc/tcpsrcplugin.h @@ -5,6 +5,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class TCPSrcPlugin : public QObject, PluginInterface { Q_OBJECT @@ -18,6 +19,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/udpsrc/udpsrc.cpp b/plugins/channelrx/udpsrc/udpsrc.cpp index b601c098e..c5d2d41c1 100644 --- a/plugins/channelrx/udpsrc/udpsrc.cpp +++ b/plugins/channelrx/udpsrc/udpsrc.cpp @@ -33,6 +33,8 @@ MESSAGE_CLASS_DEFINITION(UDPSrc::MsgConfigureUDPSrc, Message) MESSAGE_CLASS_DEFINITION(UDPSrc::MsgConfigureChannelizer, Message) MESSAGE_CLASS_DEFINITION(UDPSrc::MsgUDPSrcSpectrum, Message) +const QString UDPSrc::m_channelID = "sdrangel.channel.udpsrc"; + UDPSrc::UDPSrc(DeviceSourceAPI *deviceAPI) : m_deviceAPI(deviceAPI), m_outMovingAverage(480, 1e-10), diff --git a/plugins/channelrx/udpsrc/udpsrc.h b/plugins/channelrx/udpsrc/udpsrc.h index 441c22a75..391c378c9 100644 --- a/plugins/channelrx/udpsrc/udpsrc.h +++ b/plugins/channelrx/udpsrc/udpsrc.h @@ -104,6 +104,7 @@ public: virtual void stop(); virtual bool handleMessage(const Message& cmd); + static const QString m_channelID; static const int udpBlockSize = 512; // UDP block size in number of bytes public slots: diff --git a/plugins/channelrx/udpsrc/udpsrcgui.cpp b/plugins/channelrx/udpsrc/udpsrcgui.cpp index 9141cdd82..f8a45f0dc 100644 --- a/plugins/channelrx/udpsrc/udpsrcgui.cpp +++ b/plugins/channelrx/udpsrc/udpsrcgui.cpp @@ -30,8 +30,6 @@ #include "udpsrc.h" -const QString UDPSrcGUI::m_channelID = "sdrangel.channel.udpsrc"; - UDPSrcGUI* UDPSrcGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet) { UDPSrcGUI* gui = new UDPSrcGUI(pluginAPI, deviceUISet); @@ -185,7 +183,7 @@ UDPSrcGUI::UDPSrcGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, QWidget* pa connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); - m_deviceUISet->registerRxChannelInstance(m_channelID, this); + m_deviceUISet->registerRxChannelInstance(UDPSrc::m_channelID, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); diff --git a/plugins/channelrx/udpsrc/udpsrcgui.h b/plugins/channelrx/udpsrc/udpsrcgui.h index 63ad4e994..d5c7edd29 100644 --- a/plugins/channelrx/udpsrc/udpsrcgui.h +++ b/plugins/channelrx/udpsrc/udpsrcgui.h @@ -55,8 +55,6 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); - static const QString m_channelID; - private slots: void channelMarkerChanged(); void on_deltaFrequency_changed(qint64 value); diff --git a/plugins/channelrx/udpsrc/udpsrcplugin.cpp b/plugins/channelrx/udpsrc/udpsrcplugin.cpp index b7043a4ea..ecd456ec3 100644 --- a/plugins/channelrx/udpsrc/udpsrcplugin.cpp +++ b/plugins/channelrx/udpsrc/udpsrcplugin.cpp @@ -21,6 +21,7 @@ #include "plugin/pluginapi.h" #include "udpsrcgui.h" +#include "udpsrc.h" const PluginDescriptor UDPSrcPlugin::m_pluginDescriptor = { QString("UDP Channel Source"), @@ -47,12 +48,12 @@ void UDPSrcPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI = pluginAPI; // register TCP Channel Source - m_pluginAPI->registerRxChannel(UDPSrcGUI::m_channelID, this); + m_pluginAPI->registerRxChannel(UDPSrc::m_channelID, this); } PluginInstanceGUI* UDPSrcPlugin::createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet) { - if(channelName == UDPSrcGUI::m_channelID) + if(channelName == UDPSrc::m_channelID) { UDPSrcGUI* gui = UDPSrcGUI::create(m_pluginAPI, deviceUISet); // deviceAPI->registerChannelInstance("sdrangel.channel.udpsrc", gui); @@ -62,3 +63,14 @@ PluginInstanceGUI* UDPSrcPlugin::createRxChannelGUI(const QString& channelName, return 0; } } + +BasebandSampleSink* UDPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +{ + if(channelName == UDPSrc::m_channelID) + { + UDPSrc* sink = new UDPSrc(deviceAPI); + return sink; + } else { + return 0; + } +} diff --git a/plugins/channelrx/udpsrc/udpsrcplugin.h b/plugins/channelrx/udpsrc/udpsrcplugin.h index 2b75fab30..e96bc082d 100644 --- a/plugins/channelrx/udpsrc/udpsrcplugin.h +++ b/plugins/channelrx/udpsrc/udpsrcplugin.h @@ -22,6 +22,7 @@ #include "plugin/plugininterface.h" class DeviceUISet; +class BasebandSampleSink; class UDPSrcPlugin : public QObject, PluginInterface { Q_OBJECT @@ -35,6 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); PluginInstanceGUI* createRxChannelGUI(const QString& channelName, DeviceUISet *deviceUISet); + BasebandSampleSink* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor;