diff --git a/CMakeLists.txt b/CMakeLists.txt index e5675f6e1..e24226041 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -264,6 +264,8 @@ set(sdrbase_SOURCES sdrbase/gui/samplingdevicecontrol.cpp sdrbase/gui/scale.cpp sdrbase/gui/scaleengine.cpp + sdrbase/gui/transverterbutton.cpp + sdrbase/gui/transverterdialog.cpp sdrbase/gui/valuedial.cpp sdrbase/gui/valuedialz.cpp @@ -386,6 +388,8 @@ set(sdrbase_HEADERS sdrbase/gui/samplingdevicecontrol.h sdrbase/gui/scale.h sdrbase/gui/scaleengine.h + sdrbase/gui/transverterbutton.h + sdrbase/gui/transverterdialog.h sdrbase/gui/valuedial.h sdrbase/gui/valuedialz.h @@ -393,7 +397,7 @@ set(sdrbase_HEADERS sdrbase/dsp/devicesamplesink.h sdrbase/plugin/pluginapi.h - sdrbase/plugin/plugininstanceui.h + sdrbase/plugin/plugininstancegui.h sdrbase/plugin/plugininterface.h sdrbase/plugin/pluginmanager.h @@ -439,6 +443,7 @@ set(sdrbase_FORMS sdrbase/gui/audiodialog.ui sdrbase/gui/samplingdevicecontrol.ui sdrbase/gui/myposdialog.ui + sdrbase/gui/transverterdialog.ui ) set(sdrbase_RESOURCES diff --git a/app/app.pro b/app/app.pro index 3f1f6e185..bdd7bf26e 100644 --- a/app/app.pro +++ b/app/app.pro @@ -6,6 +6,7 @@ QT += core gui multimedia opengl greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +QMAKE_CXXFLAGS += -std=c++11 TEMPLATE = app TARGET = sdrangel diff --git a/debian/changelog b/debian/changelog index a9cc4675b..1d9b44c88 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +sdrangel (3.7.3-1) unstable; urgency=medium + + * For Airspy, Funcube Pro and Pro+, PlutoSDR Rx and Tx, RTLSDR: + * Button and dialog to set frequency translation for transverter operation + * GUI and demod separation step 1 partial + + -- Edouard Griffiths, F4EXB Wed, 04 Oct 2017 23:14:18 +0200 + sdrangel (3.7.2-1) unstable; urgency=medium * PlutoSDR: Remove from device enumeration if device is not accessible diff --git a/debian/control b/debian/control index 8aa57f309..5ae42f3a4 100644 --- a/debian/control +++ b/debian/control @@ -10,7 +10,7 @@ Homepage: https://github.com/f4exb/sdrangel Package: sdrangel Architecture: any -Depends: libc6, libasound2, libfftw3-single3, libgcc1, libgl1-mesa-glx, libnanomsg0, libqt5core5a, libqt5gui5, libqt5multimedia5, libqt5network5, libqt5opengl5, libqt5widgets5, libqt5multimedia5-plugins, libstdc++6, libusb-1.0-0, libopencv-dev, libsqlite3-dev, pulseaudio, libxml2, ${shlibs:Depends}, ${misc:Depends} +Depends: libc6, libasound2, libfftw3-single3, libgcc1, libgl1-mesa-glx, libnanomsg0|libnanomsg4, libqt5core5a, libqt5gui5, libqt5multimedia5, libqt5network5, libqt5opengl5, libqt5widgets5, libqt5multimedia5-plugins, libstdc++6, libusb-1.0-0, libopencv-dev, libsqlite3-dev, pulseaudio, libxml2, ${shlibs:Depends}, ${misc:Depends} Description: SDR/Analyzer/Generator front-end for various hardware SDR/Analyzer/Generator front-end for Airspy, BladeRF, HackRF, RTL-SDR, FunCube, LimeSDR, PlutoSDR. Also File source and sink for I/Q samples, network I/Q sources with SDRDaemon. diff --git a/devices/limesdr/devicelimesdr.cpp b/devices/limesdr/devicelimesdr.cpp index 6902b2b2e..88e0e69d4 100644 --- a/devices/limesdr/devicelimesdr.cpp +++ b/devices/limesdr/devicelimesdr.cpp @@ -56,20 +56,41 @@ bool DeviceLimeSDR::setNCOFrequency(lms_device_t *device, bool dir_tx, std::size return false; } + if (dir_tx) + { + if (LMS_WriteParam(device,LMS7param(CMIX_BYP_TXTSP),0) < 0) { + fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot enable Tx NCO\n"); + return false; + } + } + else + { + if (LMS_WriteParam(device,LMS7param(CMIX_BYP_RXTSP),0) < 0) { + fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot enable Rx NCO\n"); + return false; + } + } + return true; } else { - if (LMS_SetNCOIndex(device, dir_tx, chan, LMS_NCO_VAL_COUNT, true) < 0) + if (dir_tx) { - fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot disable NCO\n"); - return false; + if (LMS_WriteParam(device,LMS7param(CMIX_BYP_TXTSP),1) < 0) { + fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot disable Tx NCO\n"); + return false; + } } else { - fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: NCO disabled\n"); - return true; + if (LMS_WriteParam(device,LMS7param(CMIX_BYP_RXTSP),1) < 0) { + fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot disable Rx NCO\n"); + return false; + } } + + return true; } } diff --git a/doc/img/PlutoSDRInput_plugin.png b/doc/img/PlutoSDRInput_plugin.png index bd147c3b9..72de0453a 100644 Binary files a/doc/img/PlutoSDRInput_plugin.png and b/doc/img/PlutoSDRInput_plugin.png differ diff --git a/doc/img/PlutoSDROutput_plugin.png b/doc/img/PlutoSDROutput_plugin.png index 9bfebf06c..d728b849f 100644 Binary files a/doc/img/PlutoSDROutput_plugin.png and b/doc/img/PlutoSDROutput_plugin.png differ diff --git a/doc/img/RTLSDR_plugin.png b/doc/img/RTLSDR_plugin.png index 1a99604de..6a9d91065 100644 Binary files a/doc/img/RTLSDR_plugin.png and b/doc/img/RTLSDR_plugin.png differ diff --git a/doc/img/RTLSDR_plugin_xvrt.png b/doc/img/RTLSDR_plugin_xvrt.png new file mode 100644 index 000000000..caba79912 Binary files /dev/null and b/doc/img/RTLSDR_plugin_xvrt.png differ diff --git a/fcdpp.rules b/fcd.rules similarity index 56% rename from fcdpp.rules rename to fcd.rules index ccadc1461..3dace445c 100644 --- a/fcdpp.rules +++ b/fcd.rules @@ -1,5 +1,6 @@ # Udev rules for the Funcube Dongle Pro+ (0xfb31) # HIDAPI/libusb: -SUBSYSTEMS=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fb31", GROUP:="audio", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fb56", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fb31", MODE:="0666" diff --git a/fcdlib/fcdtraits.cpp b/fcdlib/fcdtraits.cpp index a119628fa..980f9400d 100644 --- a/fcdlib/fcdtraits.cpp +++ b/fcdlib/fcdtraits.cpp @@ -22,5 +22,11 @@ const char *fcd_traits::displayedName = "FunCube Dongle Pro+"; const char *fcd_traits::pluginDisplayedName = "FunCube Pro Input"; const char *fcd_traits::pluginDisplayedName = "FunCube Pro+ Input"; -const char *fcd_traits::pluginVersion = "3.5.0"; -const char *fcd_traits::pluginVersion = "3.5.0"; +const char *fcd_traits::pluginVersion = "3.7.3"; +const char *fcd_traits::pluginVersion = "3.7.3"; + +const int64_t fcd_traits::loLowLimitFreq = 64000000L; +const int64_t fcd_traits::loLowLimitFreq = 150000L; + +const int64_t fcd_traits::loHighLimitFreq = 1700000000L; +const int64_t fcd_traits::loHighLimitFreq = 2000000000L; diff --git a/fcdlib/fcdtraits.h b/fcdlib/fcdtraits.h index 8d6cc9db0..a649edc39 100644 --- a/fcdlib/fcdtraits.h +++ b/fcdlib/fcdtraits.h @@ -30,6 +30,8 @@ struct fcd_traits static const char *displayedName; static const char *pluginDisplayedName; static const char *pluginVersion; + static const int64_t loLowLimitFreq; + static const int64_t loHighLimitFreq; }; template<> @@ -46,6 +48,8 @@ struct fcd_traits static const char *displayedName; static const char *pluginDisplayedName; static const char *pluginVersion; + static const int64_t loLowLimitFreq; + static const int64_t loHighLimitFreq; }; template<> @@ -62,6 +66,8 @@ struct fcd_traits static const char *displayedName; static const char *pluginDisplayedName; static const char *pluginVersion; + static const int64_t loLowLimitFreq; + static const int64_t loHighLimitFreq; }; template const char *fcd_traits::alsaDeviceName = ""; diff --git a/plugins/channelrx/chanalyzer/chanalyzer.cpp b/plugins/channelrx/chanalyzer/chanalyzer.cpp index 641f75037..d7c42629f 100644 --- a/plugins/channelrx/chanalyzer/chanalyzer.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzer.cpp @@ -14,19 +14,25 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "../../channelrx/chanalyzer/chanalyzer.h" +#include "chanalyzer.h" -#include #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(BasebandSampleSink* sampleSink) : - m_sampleSink(sampleSink), +ChannelAnalyzer::ChannelAnalyzer(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_sampleSink(0), m_settingsMutex(QMutex::Recursive) { m_Bandwidth = 5000; @@ -42,12 +48,20 @@ ChannelAnalyzer::ChannelAnalyzer(BasebandSampleSink* sampleSink) : 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, @@ -130,6 +144,12 @@ void ChannelAnalyzer::stop() { } +void ChannelAnalyzer::channelSampleRateChanged() +{ + MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create(); + getMessageQueueToGUI()->push(msg); +} + bool ChannelAnalyzer::handleMessage(const Message& cmd) { float band, lowCutoff; @@ -148,6 +168,16 @@ bool ChannelAnalyzer::handleMessage(const Message& cmd) 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; diff --git a/plugins/channelrx/chanalyzer/chanalyzer.h b/plugins/channelrx/chanalyzer/chanalyzer.h index adc2c1361..7dd26732f 100644 --- a/plugins/channelrx/chanalyzer/chanalyzer.h +++ b/plugins/channelrx/chanalyzer/chanalyzer.h @@ -27,10 +27,87 @@ #define ssbFftLen 1024 +class DeviceSourceAPI; +class ThreadedBasebandSampleSink; +class DownChannelizer; + class ChannelAnalyzer : public BasebandSampleSink { public: - ChannelAnalyzer(BasebandSampleSink* m_sampleSink); + 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, @@ -46,41 +123,13 @@ public: virtual void stop(); virtual bool handleMessage(const Message& cmd); +private slots: + void channelSampleRateChanged(); + private: - 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) - { } - }; + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; Real m_Bandwidth; Real m_LowCutoff; diff --git a/plugins/channelrx/chanalyzer/chanalyzergui.cpp b/plugins/channelrx/chanalyzer/chanalyzergui.cpp index 0cc9b561d..147edac22 100644 --- a/plugins/channelrx/chanalyzer/chanalyzergui.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzergui.cpp @@ -154,11 +154,32 @@ bool ChannelAnalyzerGUI::deserialize(const QByteArray& data) } } -bool ChannelAnalyzerGUI::handleMessage(const Message& message __attribute__((unused))) +bool ChannelAnalyzerGUI::handleMessage(const Message& message) { + if (ChannelAnalyzer::MsgReportChannelSampleRateChanged::match(message)) + { + setNewRate(m_spanLog2); + return true; + } + return false; } +void ChannelAnalyzerGUI::handleInputMessages() +{ + Message* message; + + while ((message = getInputMessageQueue()->pop()) != 0) + { + qDebug("ChannelAnalyzerGUI::handleInputMessages: message: %s", message->getIdentifier()); + + if (handleMessage(*message)) + { + delete message; + } + } +} + void ChannelAnalyzerGUI::viewChanged() { applySettings(); @@ -171,11 +192,6 @@ void ChannelAnalyzerGUI::tick() ui->channelPower->setText(QString::number(m_channelPowerDbAvg.average(), 'f', 1)); } -void ChannelAnalyzerGUI::channelSampleRateChanged() -{ - setNewRate(m_spanLog2); -} - void ChannelAnalyzerGUI::on_deltaMinus_toggled(bool minus) { int deltaFrequency = m_channelMarker.getCenterFrequency(); @@ -326,11 +342,9 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceSourceAPI *de m_spectrumVis = new SpectrumVis(ui->glSpectrum); m_scopeVis = new ScopeVis(ui->glScope); m_spectrumScopeComboVis = new SpectrumScopeComboVis(m_spectrumVis, m_scopeVis); - m_channelAnalyzer = new ChannelAnalyzer(m_spectrumScopeComboVis); - m_channelizer = new DownChannelizer(m_channelAnalyzer); - m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); - connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged())); - m_deviceAPI->addThreadedSink(m_threadedChannelizer); + m_channelAnalyzer = new ChannelAnalyzer(m_deviceAPI); + m_channelAnalyzer->setSampleSink(m_spectrumScopeComboVis); + m_channelAnalyzer->setMessageQueueToGUI(getInputMessageQueue()); ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold)); ui->deltaFrequency->setValueRange(7, 0U, 9999999U); @@ -361,6 +375,8 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceSourceAPI *de ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum); ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + applySettings(); setNewRate(m_spanLog2); } @@ -368,9 +384,6 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceSourceAPI *de ChannelAnalyzerGUI::~ChannelAnalyzerGUI() { m_deviceAPI->removeChannelInstance(this); - m_deviceAPI->removeThreadedSink(m_threadedChannelizer); - delete m_threadedChannelizer; - delete m_channelizer; delete m_channelAnalyzer; delete m_spectrumVis; delete m_scopeVis; @@ -457,9 +470,8 @@ void ChannelAnalyzerGUI::applySettings() ui->deltaFrequency->setValue(abs(m_channelMarker.getCenterFrequency())); ui->deltaMinus->setChecked(m_channelMarker.getCenterFrequency() < 0); - m_channelizer->configure(m_channelizer->getInputMessageQueue(), - m_channelizer->getInputSampleRate(), - m_channelMarker.getCenterFrequency()); + ChannelAnalyzer::MsgConfigureChannelizer *msg = ChannelAnalyzer::MsgConfigureChannelizer::create(m_channelMarker.getCenterFrequency()); + m_channelAnalyzer->getInputMessageQueue()->push(msg); m_channelAnalyzer->configure(m_channelAnalyzer->getInputMessageQueue(), ui->BW->value() * 100.0, diff --git a/plugins/channelrx/chanalyzer/chanalyzergui.h b/plugins/channelrx/chanalyzer/chanalyzergui.h index 24b352dba..c13238f40 100644 --- a/plugins/channelrx/chanalyzer/chanalyzergui.h +++ b/plugins/channelrx/chanalyzer/chanalyzergui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_CHANNELANALYZERGUI_H #define INCLUDE_CHANNELANALYZERGUI_H +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" class PluginAPI; @@ -37,7 +37,7 @@ namespace Ui { class ChannelAnalyzerGUI; } -class ChannelAnalyzerGUI : public RollupWidget, public PluginInstanceUI { +class ChannelAnalyzerGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -59,7 +59,6 @@ public: private slots: void viewChanged(); - void channelSampleRateChanged(); void on_deltaFrequency_changed(quint64 value); void on_deltaMinus_toggled(bool minus); void on_BW_valueChanged(int value); @@ -68,6 +67,7 @@ private slots: void on_ssb_toggled(bool checked); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDoubleClicked(); + void handleInputMessages(); void tick(); private: @@ -81,8 +81,8 @@ private: int m_spanLog2; MovingAverage m_channelPowerDbAvg; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; +// ThreadedBasebandSampleSink* m_threadedChannelizer; +// DownChannelizer* m_channelizer; ChannelAnalyzer* m_channelAnalyzer; SpectrumScopeComboVis* m_spectrumScopeComboVis; SpectrumVis* m_spectrumVis; diff --git a/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp b/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp index da6b09167..428ccd78c 100644 --- a/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp @@ -33,7 +33,7 @@ void ChannelAnalyzerPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(ChannelAnalyzerGUI::m_channelID, this); } -PluginInstanceUI* ChannelAnalyzerPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* ChannelAnalyzerPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == ChannelAnalyzerGUI::m_channelID) { diff --git a/plugins/channelrx/chanalyzer/chanalyzerplugin.h b/plugins/channelrx/chanalyzer/chanalyzerplugin.h index 02ad6ddaa..aa42c8edb 100644 --- a/plugins/channelrx/chanalyzer/chanalyzerplugin.h +++ b/plugins/channelrx/chanalyzer/chanalyzerplugin.h @@ -17,7 +17,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* 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 f27ea6407..ddfa63fc3 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerng.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzerng.cpp @@ -16,17 +16,23 @@ #include "chanalyzerng.h" -#include #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(BasebandSampleSink* sampleSink) : - m_sampleSink(sampleSink), +ChannelAnalyzerNG::ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_sampleSink(0), m_settingsMutex(QMutex::Recursive) { m_undersampleCount = 0; @@ -38,6 +44,12 @@ ChannelAnalyzerNG::ChannelAnalyzerNG(BasebandSampleSink* sampleSink) : 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); } @@ -45,6 +57,9 @@ 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, @@ -54,7 +69,7 @@ void ChannelAnalyzerNG::configure(MessageQueue* messageQueue, int spanLog2, bool ssb) { - Message* cmd = MsgConfigureChannelAnalyzer::create(channelSampleRate, Bandwidth, LowCutoff, spanLog2, ssb); + Message* cmd = MsgConfigureChannelAnalyzer::create(channelSampleRate, Bandwidth, LowCutoff, spanLog2, ssb); messageQueue->push(cmd); } @@ -102,6 +117,12 @@ void ChannelAnalyzerNG::stop() { } +void ChannelAnalyzerNG::channelizerInputSampleRateChanged() +{ + MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create(); + getMessageQueueToGUI()->push(msg); +} + bool ChannelAnalyzerNG::handleMessage(const Message& cmd) { qDebug() << "ChannelAnalyzerNG::handleMessage: " << cmd.getIdentifier(); @@ -120,11 +141,19 @@ bool ChannelAnalyzerNG::handleMessage(const Message& cmd) 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_channelSampleRate = cfg.getChannelSampleRate(); m_config.m_Bandwidth = cfg.getBandwidth(); m_config.m_LowCutoff = cfg.getLoCutoff(); m_config.m_spanLog2 = cfg.getSpanLog2(); @@ -153,6 +182,8 @@ bool ChannelAnalyzerNG::handleMessage(const Message& cmd) } } + + void ChannelAnalyzerNG::apply(bool force) { if ((m_running.m_frequency != m_config.m_frequency) || diff --git a/plugins/channelrx/chanalyzerng/chanalyzerng.h b/plugins/channelrx/chanalyzerng/chanalyzerng.h index 671e12c92..bee680725 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerng.h +++ b/plugins/channelrx/chanalyzerng/chanalyzerng.h @@ -29,10 +29,102 @@ #define ssbFftLen 1024 +class DeviceSourceAPI; +class ThreadedBasebandSampleSink; +class DownChannelizer; + class ChannelAnalyzerNG : public BasebandSampleSink { public: - ChannelAnalyzerNG(BasebandSampleSink* m_sampleSink); + 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, @@ -41,6 +133,7 @@ public: 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; } @@ -50,48 +143,10 @@ public: virtual void stop(); virtual bool handleMessage(const Message& cmd); +private slots: + void channelizerInputSampleRateChanged(); + private: - 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) - { } - }; struct Config { @@ -117,6 +172,10 @@ private: 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; diff --git a/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp b/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp index 7940da613..cd05da0a3 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp @@ -159,7 +159,29 @@ bool ChannelAnalyzerNGGUI::deserialize(const QByteArray& data) bool ChannelAnalyzerNGGUI::handleMessage(const Message& message __attribute__((unused))) { - return false; + if (ChannelAnalyzerNG::MsgReportChannelSampleRateChanged::match(message)) + { + setNewFinalRate(m_spanLog2); + applySettings(); + return true; + } + + return false; +} + +void ChannelAnalyzerNGGUI::handleInputMessages() +{ + Message* message; + + while ((message = getInputMessageQueue()->pop()) != 0) + { + qDebug("ChannelAnalyzerGUI::handleInputMessages: message: %s", message->getIdentifier()); + + if (handleMessage(*message)) + { + delete message; + } + } } void ChannelAnalyzerNGGUI::viewChanged() @@ -174,12 +196,12 @@ void ChannelAnalyzerNGGUI::tick() ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.average(), 0, 'f', 1)); } -void ChannelAnalyzerNGGUI::channelizerInputSampleRateChanged() -{ - //ui->channelSampleRate->setValueRange(7, 2000U, m_channelAnalyzer->getInputSampleRate()); - setNewFinalRate(m_spanLog2); - applySettings(); -} +//void ChannelAnalyzerNGGUI::channelizerInputSampleRateChanged() +//{ +// //ui->channelSampleRate->setValueRange(7, 2000U, m_channelAnalyzer->getInputSampleRate()); +// setNewFinalRate(m_spanLog2); +// applySettings(); +//} void ChannelAnalyzerNGGUI::on_channelSampleRate_changed(quint64 value) { @@ -204,7 +226,7 @@ int ChannelAnalyzerNGGUI::getRequestedChannelSampleRate() if (ui->useRationalDownsampler->isChecked()) { return ui->channelSampleRate->getValueNew(); } else { - return m_channelizer->getInputSampleRate(); + return m_channelAnalyzer->getChannelizer()->getInputSampleRate(); } } @@ -348,11 +370,13 @@ ChannelAnalyzerNGGUI::ChannelAnalyzerNGGUI(PluginAPI* pluginAPI, DeviceSourceAPI m_spectrumVis = new SpectrumVis(ui->glSpectrum); m_scopeVis = new ScopeVisNG(ui->glScope); m_spectrumScopeComboVis = new SpectrumScopeNGComboVis(m_spectrumVis, m_scopeVis); - m_channelAnalyzer = new ChannelAnalyzerNG(m_spectrumScopeComboVis); - m_channelizer = new DownChannelizer(m_channelAnalyzer); - m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); - connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelizerInputSampleRateChanged())); - m_deviceAPI->addThreadedSink(m_threadedChannelizer); + m_channelAnalyzer = new ChannelAnalyzerNG(m_deviceAPI); + m_channelAnalyzer->setSampleSink(m_spectrumScopeComboVis); + m_channelAnalyzer->setMessageQueueToGUI(getInputMessageQueue()); +// m_channelizer = new DownChannelizer(m_channelAnalyzer); +// m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); +// connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelizerInputSampleRateChanged())); +// m_deviceAPI->addThreadedSink(m_threadedChannelizer); ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03))); ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); @@ -389,6 +413,8 @@ ChannelAnalyzerNGGUI::ChannelAnalyzerNGGUI(PluginAPI* pluginAPI, DeviceSourceAPI ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum); ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + applySettings(); setNewFinalRate(m_spanLog2); } @@ -396,9 +422,9 @@ ChannelAnalyzerNGGUI::ChannelAnalyzerNGGUI(PluginAPI* pluginAPI, DeviceSourceAPI ChannelAnalyzerNGGUI::~ChannelAnalyzerNGGUI() { m_deviceAPI->removeChannelInstance(this); - m_deviceAPI->removeThreadedSink(m_threadedChannelizer); - delete m_threadedChannelizer; - delete m_channelizer; +// m_deviceAPI->removeThreadedSink(m_threadedChannelizer); +// delete m_threadedChannelizer; +// delete m_channelizer; delete m_channelAnalyzer; delete m_spectrumVis; delete m_scopeVis; @@ -514,14 +540,25 @@ void ChannelAnalyzerNGGUI::applySettings() setTitleColor(m_channelMarker.getColor()); ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); - m_channelizer->configure(m_channelizer->getInputMessageQueue(), - //m_channelizer->getInputSampleRate(), - getRequestedChannelSampleRate(), - m_channelMarker.getCenterFrequency()); + int sampleRate = getRequestedChannelSampleRate(); + + ChannelAnalyzerNG::MsgConfigureChannelizer *msgChannelizer = ChannelAnalyzerNG::MsgConfigureChannelizer::create(sampleRate, m_channelMarker.getCenterFrequency()); + m_channelAnalyzer->getInputMessageQueue()->push(msgChannelizer); + + ChannelAnalyzerNG::MsgConfigureChannelizer *msg = + ChannelAnalyzerNG::MsgConfigureChannelizer::create( + sampleRate, + m_channelMarker.getCenterFrequency()); + m_channelAnalyzer->getInputMessageQueue()->push(msg); + +// m_channelizer->configure(m_channelizer->getInputMessageQueue(), +// //m_channelizer->getInputSampleRate(), +// getRequestedChannelSampleRate(), +// m_channelMarker.getCenterFrequency()); m_channelAnalyzer->configure(m_channelAnalyzer->getInputMessageQueue(), //m_channelizer->getInputSampleRate(), // TODO: specify required channel sample rate - getRequestedChannelSampleRate(), // TODO: specify required channel sample rate + sampleRate, // TODO: specify required channel sample rate ui->BW->value() * 100.0, ui->lowCut->value() * 100.0, m_spanLog2, diff --git a/plugins/channelrx/chanalyzerng/chanalyzernggui.h b/plugins/channelrx/chanalyzerng/chanalyzernggui.h index d9797c0d1..7ef686b66 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzernggui.h +++ b/plugins/channelrx/chanalyzerng/chanalyzernggui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_CHANNELANALYZERNGGUI_H #define INCLUDE_CHANNELANALYZERNGGUI_H +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" class PluginAPI; @@ -37,7 +37,7 @@ namespace Ui { class ChannelAnalyzerNGGUI; } -class ChannelAnalyzerNGGUI : public RollupWidget, public PluginInstanceUI { +class ChannelAnalyzerNGGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -59,7 +59,7 @@ public: private slots: void viewChanged(); - void channelizerInputSampleRateChanged(); +// void channelizerInputSampleRateChanged(); void on_deltaFrequency_changed(qint64 value); void on_channelSampleRate_changed(quint64 value); void on_useRationalDownsampler_toggled(bool checked); @@ -69,6 +69,7 @@ private slots: void on_ssb_toggled(bool checked); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDoubleClicked(); + void handleInputMessages(); void tick(); private: @@ -82,8 +83,8 @@ private: int m_spanLog2; MovingAverage m_channelPowerDbAvg; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; +// ThreadedBasebandSampleSink* m_threadedChannelizer; +// DownChannelizer* m_channelizer; ChannelAnalyzerNG* m_channelAnalyzer; SpectrumScopeNGComboVis* m_spectrumScopeComboVis; SpectrumVis* m_spectrumVis; diff --git a/plugins/channelrx/chanalyzerng/chanalyzerngplugin.cpp b/plugins/channelrx/chanalyzerng/chanalyzerngplugin.cpp index d6ad4176c..1ddff0440 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerngplugin.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzerngplugin.cpp @@ -48,7 +48,7 @@ void ChannelAnalyzerNGPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(ChannelAnalyzerNGGUI::m_channelID, this); } -PluginInstanceUI* ChannelAnalyzerNGPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* ChannelAnalyzerNGPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == ChannelAnalyzerNGGUI::m_channelID) { diff --git a/plugins/channelrx/chanalyzerng/chanalyzerngplugin.h b/plugins/channelrx/chanalyzerng/chanalyzerngplugin.h index c3536677e..2f4597254 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerngplugin.h +++ b/plugins/channelrx/chanalyzerng/chanalyzerngplugin.h @@ -34,7 +34,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodam/CMakeLists.txt b/plugins/channelrx/demodam/CMakeLists.txt index 0c6721c3b..cbbd3ae9c 100644 --- a/plugins/channelrx/demodam/CMakeLists.txt +++ b/plugins/channelrx/demodam/CMakeLists.txt @@ -3,12 +3,14 @@ project(am) set(am_SOURCES amdemod.cpp amdemodgui.cpp + amdemodsettings.cpp amdemodplugin.cpp ) set(am_HEADERS amdemod.h amdemodgui.h + amdemodsettings.h amdemodplugin.h ) diff --git a/plugins/channelrx/demodam/amdemod.cpp b/plugins/channelrx/demodam/amdemod.cpp index f4c1f7e60..b1d93b286 100644 --- a/plugins/channelrx/demodam/amdemod.cpp +++ b/plugins/channelrx/demodam/amdemod.cpp @@ -26,12 +26,16 @@ #include "audio/audiooutput.h" #include "dsp/dspengine.h" #include "dsp/pidcontroller.h" +#include "dsp/threadedbasebandsamplesink.h" +#include "device/devicesourceapi.h" MESSAGE_CLASS_DEFINITION(AMDemod::MsgConfigureAMDemod, Message) +MESSAGE_CLASS_DEFINITION(AMDemod::MsgConfigureChannelizer, Message) const int AMDemod::m_udpBlockSize = 512; -AMDemod::AMDemod() : +AMDemod::AMDemod(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), m_squelchOpen(false), m_magsqSum(0.0f), m_magsqPeak(0.0f), @@ -43,14 +47,9 @@ AMDemod::AMDemod() : { setObjectName("AMDemod"); - m_config.m_inputSampleRate = 96000; - m_config.m_inputFrequencyOffset = 0; - m_config.m_rfBandwidth = 5000; - m_config.m_squelch = -40.0; - m_config.m_volume = 2.0; - m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); - - apply(); + m_channelizer = new DownChannelizer(this); + m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); + m_deviceAPI->addThreadedSink(m_threadedChannelizer); m_audioBuffer.resize(1<<14); m_audioBufferFill = 0; @@ -60,7 +59,9 @@ AMDemod::AMDemod() : m_magsq = 0.0; DSPEngine::instance()->addAudioSink(&m_audioFifo); - m_udpBufferAudio = new UDPSink(this, m_udpBlockSize, m_config.m_udpPort); + m_udpBufferAudio = new UDPSink(this, m_udpBlockSize, m_settings.m_udpPort); + + applySettings(m_settings, true); } AMDemod::~AMDemod() @@ -69,29 +70,6 @@ AMDemod::~AMDemod() delete m_udpBufferAudio; } -void AMDemod::configure(MessageQueue* messageQueue, - Real rfBandwidth, - Real volume, - Real squelch, - bool audioMute, - bool bandpassEnable, - bool copyAudioToUDP, - const QString& udpAddress, - quint16 udpPort, - bool force) -{ - Message* cmd = MsgConfigureAMDemod::create(rfBandwidth, - volume, - squelch, - audioMute, - bandpassEnable, - copyAudioToUDP, - udpAddress, - udpPort, - force); - messageQueue->push(cmd); -} - void AMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) { Complex ci; @@ -142,8 +120,8 @@ void AMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector void AMDemod::start() { - qDebug() << "AMDemod::start: m_inputSampleRate: " << m_config.m_inputSampleRate - << " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; + qDebug() << "AMDemod::start: m_inputSampleRate: " << m_settings.m_inputSampleRate + << " m_inputFrequencyOffset: " << m_settings.m_inputFrequencyOffset; m_squelchCount = 0; m_audioFifo.clear(); @@ -161,41 +139,51 @@ bool AMDemod::handleMessage(const Message& cmd) { DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; - m_config.m_inputSampleRate = notif.getSampleRate(); - m_config.m_inputFrequencyOffset = notif.getFrequencyOffset(); + AMDemodSettings settings = m_settings; - apply(); + settings.m_inputSampleRate = notif.getSampleRate(); + settings.m_inputFrequencyOffset = notif.getFrequencyOffset(); - qDebug() << "AMDemod::handleMessage: MsgChannelizerNotification:" - << " m_inputSampleRate: " << m_config.m_inputSampleRate - << " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; + applySettings(settings); + + qDebug() << "AMDemod::handleMessage: MsgChannelizerNotification:" + << " m_inputSampleRate: " << settings.m_inputSampleRate + << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset; 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 (MsgConfigureAMDemod::match(cmd)) { - MsgConfigureAMDemod& cfg = (MsgConfigureAMDemod&) cmd; + MsgConfigureAMDemod& cfg = (MsgConfigureAMDemod&) cmd; - m_config.m_rfBandwidth = cfg.getRFBandwidth(); - m_config.m_volume = cfg.getVolume(); - m_config.m_squelch = cfg.getSquelch(); - m_config.m_audioMute = cfg.getAudioMute(); - m_config.m_bandpassEnable = cfg.getBandpassEnable(); - m_config.m_copyAudioToUDP = cfg.getCopyAudioToUDP(); - m_config.m_udpAddress = cfg.getUDPAddress(); - m_config.m_udpPort = cfg.getUDPPort(); + AMDemodSettings settings = cfg.getSettings(); - apply(cfg.getForce()); + // These settings are set with DownChannelizer::MsgChannelizerNotification + settings.m_inputSampleRate = m_settings.m_inputSampleRate; + settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset; - qDebug() << "AMDemod::handleMessage: MsgConfigureAMDemod:" - << " m_rfBandwidth: " << m_config.m_rfBandwidth - << " m_volume: " << m_config.m_volume - << " m_squelch: " << m_config.m_squelch - << " m_audioMute: " << m_config.m_audioMute - << " m_bandpassEnable: " << m_config.m_bandpassEnable - << " m_copyAudioToUDP: " << m_config.m_copyAudioToUDP - << " m_udpAddress: " << m_config.m_udpAddress - << " m_udpPort: " << m_config.m_udpPort; + applySettings(settings, cfg.getForce()); + + qDebug() << "AMDemod::handleMessage: MsgConfigureAMDemod:" + << " m_rfBandwidth: " << settings.m_rfBandwidth + << " m_volume: " << settings.m_volume + << " m_squelch: " << settings.m_squelch + << " m_audioMute: " << settings.m_audioMute + << " m_bandpassEnable: " << settings.m_bandpassEnable + << " m_copyAudioToUDP: " << settings.m_copyAudioToUDP + << " m_udpAddress: " << settings.m_udpAddress + << " m_udpPort: " << settings.m_udpPort + << " force: " << cfg.getForce(); return true; } @@ -205,40 +193,38 @@ bool AMDemod::handleMessage(const Message& cmd) } } -void AMDemod::apply(bool force) +void AMDemod::applySettings(const AMDemodSettings& settings, bool force) { - - if ((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || - (m_config.m_inputSampleRate != m_running.m_inputSampleRate) || force) - { - m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate); - } - - if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) || - (m_config.m_rfBandwidth != m_running.m_rfBandwidth) || - (m_config.m_audioSampleRate != m_running.m_audioSampleRate) || - (m_config.m_bandpassEnable != m_running.m_bandpassEnable) || force) - { - m_settingsMutex.lock(); - m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.2f); - m_interpolatorDistanceRemain = 0; - m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate; - m_bandpass.create(301, m_config.m_audioSampleRate, 300.0, m_config.m_rfBandwidth / 2.0f); - m_settingsMutex.unlock(); - } - - if ((m_config.m_squelch != m_running.m_squelch) || force) - { - m_squelchLevel = pow(10.0, m_config.m_squelch / 20.0); - m_squelchLevel *= m_squelchLevel; - } - - if ((m_config.m_udpAddress != m_running.m_udpAddress) - || (m_config.m_udpPort != m_running.m_udpPort) || force) + if ((m_settings.m_inputFrequencyOffset != settings.m_inputFrequencyOffset) || + (m_settings.m_inputSampleRate != settings.m_inputSampleRate) || force) { - m_udpBufferAudio->setAddress(m_config.m_udpAddress); - m_udpBufferAudio->setPort(m_config.m_udpPort); + m_nco.setFreq(-settings.m_inputFrequencyOffset, settings.m_inputSampleRate); } - m_running = m_config; + if((m_settings.m_inputSampleRate != settings.m_inputSampleRate) || + (m_settings.m_rfBandwidth != settings.m_rfBandwidth) || + (m_settings.m_audioSampleRate != settings.m_audioSampleRate) || + (m_settings.m_bandpassEnable != settings.m_bandpassEnable) || force) + { + m_settingsMutex.lock(); + m_interpolator.create(16, settings.m_inputSampleRate, settings.m_rfBandwidth / 2.2f); + m_interpolatorDistanceRemain = 0; + m_interpolatorDistance = (Real) settings.m_inputSampleRate / (Real) settings.m_audioSampleRate; + m_bandpass.create(301, settings.m_audioSampleRate, 300.0, settings.m_rfBandwidth / 2.0f); + m_settingsMutex.unlock(); + } + + if ((m_settings.m_squelch != settings.m_squelch) || force) + { + m_squelchLevel = pow(10.0, settings.m_squelch / 10.0); + } + + if ((m_settings.m_udpAddress != settings.m_udpAddress) + || (m_settings.m_udpPort != settings.m_udpPort) || force) + { + m_udpBufferAudio->setAddress(const_cast(settings.m_udpAddress)); + m_udpBufferAudio->setPort(settings.m_udpPort); + } + + m_settings = settings; } diff --git a/plugins/channelrx/demodam/amdemod.h b/plugins/channelrx/demodam/amdemod.h index 2bf2ad7ca..8c48c2914 100644 --- a/plugins/channelrx/demodam/amdemod.h +++ b/plugins/channelrx/demodam/amdemod.h @@ -27,23 +27,63 @@ #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: - AMDemod(); - ~AMDemod(); + class MsgConfigureAMDemod : public Message { + MESSAGE_CLASS_DECLARATION - void configure(MessageQueue* messageQueue, - Real rfBandwidth, - Real volume, - Real squelch, - bool audioMute, - bool bandpassEnable, - bool copyAudioToUDP, - const QString& udpAddress, - quint16 udpPort, - bool force); + 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(); @@ -64,109 +104,16 @@ public: } private: - class MsgConfigureAMDemod : public Message { - MESSAGE_CLASS_DECLARATION - - public: - Real getRFBandwidth() const { return m_rfBandwidth; } - Real getVolume() const { return m_volume; } - Real getSquelch() const { return m_squelch; } - bool getAudioMute() const { return m_audioMute; } - bool getBandpassEnable() const { return m_bandpassEnable; } - bool getCopyAudioToUDP() const { return m_copyAudioToUDP; } - const QString& getUDPAddress() const { return m_udpAddress; } - quint16 getUDPPort() const { return m_udpPort; } - bool getForce() const { return m_force; } - - static MsgConfigureAMDemod* create(Real rfBandwidth, - Real volume, - Real squelch, - bool audioMute, - bool bandpassEnable, - bool copyAudioToUDP, - const QString& udpAddress, - quint16 udpPort, - bool force) - { - return new MsgConfigureAMDemod(rfBandwidth, - volume, - squelch, - audioMute, - bandpassEnable, - copyAudioToUDP, - udpAddress, - udpPort, - force); - } - - private: - Real m_rfBandwidth; - Real m_volume; - Real m_squelch; - bool m_audioMute; - bool m_bandpassEnable; - bool m_copyAudioToUDP; - QString m_udpAddress; - quint16 m_udpPort; - bool m_force; - - MsgConfigureAMDemod(Real rfBandwidth, - Real volume, - Real squelch, - bool audioMute, - bool bandpassEnable, - bool copyAudioToUDP, - const QString& udpAddress, - quint16 udpPort, - bool force) : - Message(), - m_rfBandwidth(rfBandwidth), - m_volume(volume), - m_squelch(squelch), - m_audioMute(audioMute), - m_bandpassEnable(bandpassEnable), - m_copyAudioToUDP(copyAudioToUDP), - m_udpAddress(udpAddress), - m_udpPort(udpPort), - m_force(force) - { } - }; - enum RateState { RSInitialFill, RSRunning }; - struct Config { - int m_inputSampleRate; - qint64 m_inputFrequencyOffset; - Real m_rfBandwidth; - Real m_squelch; - Real m_volume; - quint32 m_audioSampleRate; - bool m_audioMute; - bool m_bandpassEnable; - bool m_copyAudioToUDP; - QString m_udpAddress; - quint16 m_udpPort; + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; - Config() : - m_inputSampleRate(-1), - m_inputFrequencyOffset(0), - m_rfBandwidth(-1), - m_squelch(0), - m_volume(0), - m_audioSampleRate(0), - m_audioMute(false), - m_bandpassEnable(false), - m_copyAudioToUDP(false), - m_udpAddress("127.0.0.1"), - m_udpPort(9999) - { } - }; - - Config m_config; - Config m_running; + AMDemodSettings m_settings; NCO m_nco; Interpolator m_interpolator; @@ -194,7 +141,8 @@ private: QMutex m_settingsMutex; - void apply(bool force = false); +// void apply(bool force = false); + void applySettings(const AMDemodSettings& settings, bool force = false); void processOneSample(Complex &ci) { @@ -213,9 +161,9 @@ private: if (m_magsq >= m_squelchLevel) { - if (m_squelchCount <= m_running.m_audioSampleRate / 10) + if (m_squelchCount <= m_settings.m_audioSampleRate / 10) { - if (m_squelchCount == m_running.m_audioSampleRate / 20) { + if (m_squelchCount == m_settings.m_audioSampleRate / 20) { m_volumeAGC.fill(1.0); } @@ -232,28 +180,28 @@ private: qint16 sample; - if ((m_squelchCount >= m_running.m_audioSampleRate / 20) && !m_running.m_audioMute) + 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_running.m_bandpassEnable) + if (m_settings.m_bandpassEnable) { demod = m_bandpass.filter(demod); demod /= 301.0f; } - Real attack = (m_squelchCount - 0.05f * m_running.m_audioSampleRate) / (0.05f * m_running.m_audioSampleRate); - sample = demod * attack * 2048 * m_running.m_volume; - if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(demod * attack * 32768); + 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_running.m_copyAudioToUDP) m_udpBufferAudio->write(0); + if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(0); m_squelchOpen = false; } @@ -273,6 +221,7 @@ private: m_audioBufferFill = 0; } } + }; #endif // INCLUDE_AMDEMOD_H diff --git a/plugins/channelrx/demodam/amdemodgui.cpp b/plugins/channelrx/demodam/amdemodgui.cpp index f8a238cf4..649d5c306 100644 --- a/plugins/channelrx/demodam/amdemodgui.cpp +++ b/plugins/channelrx/demodam/amdemodgui.cpp @@ -68,83 +68,27 @@ void AMDemodGUI::setCenterFrequency(qint64 centerFrequency) void AMDemodGUI::resetToDefaults() { - blockApplySettings(true); - - ui->rfBW->setValue(50); - ui->volume->setValue(20); - ui->squelch->setValue(-40); - ui->deltaFrequency->setValue(0); - - blockApplySettings(false); - applySettings(); + m_settings.resetToDefaults(); + displaySettings(); + applySettings(true); } QByteArray AMDemodGUI::serialize() const { - SimpleSerializer s(1); - s.writeS32(1, m_channelMarker.getCenterFrequency()); - s.writeS32(2, ui->rfBW->value()); - s.writeS32(4, ui->volume->value()); - s.writeS32(5, ui->squelch->value()); - s.writeBlob(6, m_channelMarker.serialize()); - s.writeU32(7, m_channelMarker.getColor().rgb()); - s.writeBool(8, ui->bandpassEnable->isChecked()); - return s.final(); + return m_settings.serialize(); } bool AMDemodGUI::deserialize(const QByteArray& data) { - SimpleDeserializer d(data); - - if(!d.isValid()) - { - resetToDefaults(); - return false; - } - - if(d.getVersion() == 1) - { - QByteArray bytetmp; - quint32 u32tmp; - qint32 tmp; - bool boolTmp; - QString strtmp; - - blockApplySettings(true); - m_channelMarker.blockSignals(true); - - d.readBlob(6, &bytetmp); - m_channelMarker.deserialize(bytetmp); - d.readS32(1, &tmp, 0); - m_channelMarker.setCenterFrequency(tmp); - d.readS32(2, &tmp, 4); - ui->rfBW->setValue(tmp); - d.readS32(3, &tmp, 3); - //ui->afBW->setValue(tmp); - d.readS32(4, &tmp, 20); - ui->volume->setValue(tmp); - d.readS32(5, &tmp, -40); - ui->squelch->setValue(tmp); - if(d.readU32(7, &u32tmp)) { - m_channelMarker.setColor(u32tmp); - } - d.readBool(8, &boolTmp, false); - ui->bandpassEnable->setChecked(boolTmp); - - this->setWindowTitle(m_channelMarker.getTitle()); - displayUDPAddress(); - - blockApplySettings(false); - m_channelMarker.blockSignals(false); - - applySettings(true); - return true; - } - else - { - resetToDefaults(); - return false; - } + if(m_settings.deserialize(data)) { + updateChannelMarker(); + displaySettings(); + applySettings(true); + return true; + } else { + resetToDefaults(); + return false; + } } bool AMDemodGUI::handleMessage(const Message& message __attribute__((unused))) @@ -155,17 +99,25 @@ bool AMDemodGUI::handleMessage(const Message& message __attribute__((unused))) void AMDemodGUI::channelMarkerChanged() { this->setWindowTitle(m_channelMarker.getTitle()); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); + m_settings.m_udpAddress = m_channelMarker.getUDPAddress(), + m_settings.m_udpPort = m_channelMarker.getUDPSendPort(), + m_settings.m_rgbColor = m_channelMarker.getColor().rgb(); displayUDPAddress(); + //m_settings.m_channelMarkerBytes = m_channelMarker.serialize(); applySettings(); } void AMDemodGUI::on_deltaFrequency_changed(qint64 value) { m_channelMarker.setCenterFrequency(value); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); + applySettings(); } -void AMDemodGUI::on_bandpassEnable_toggled(bool checked __attribute__((unused))) +void AMDemodGUI::on_bandpassEnable_toggled(bool checked) { + m_settings.m_bandpassEnable = checked; applySettings(); } @@ -173,28 +125,33 @@ void AMDemodGUI::on_rfBW_valueChanged(int value) { ui->rfBWText->setText(QString("%1 kHz").arg(value / 10.0, 0, 'f', 1)); m_channelMarker.setBandwidth(value * 100); + m_settings.m_rfBandwidth = value * 100; applySettings(); } void AMDemodGUI::on_volume_valueChanged(int value) { ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_volume = value / 10.0; applySettings(); } void AMDemodGUI::on_squelch_valueChanged(int value) { ui->squelchText->setText(QString("%1 dB").arg(value)); + m_settings.m_squelch = value; applySettings(); } -void AMDemodGUI::on_audioMute_toggled(bool checked __attribute__((unused))) +void AMDemodGUI::on_audioMute_toggled(bool checked) { + m_settings.m_audioMute = checked; applySettings(); } -void AMDemodGUI::on_copyAudioToUDP_toggled(bool checked __attribute__((unused))) +void AMDemodGUI::on_copyAudioToUDP_toggled(bool checked) { + m_settings.m_copyAudioToUDP = checked; applySettings(); } @@ -228,11 +185,7 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); - m_amDemod = new AMDemod(); - m_channelizer = new DownChannelizer(m_amDemod); - m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); - //m_pluginAPI->addThreadedSink(m_threadedChannelizer); - m_deviceAPI->addThreadedSink(m_threadedChannelizer); + m_amDemod = new AMDemod(m_deviceAPI); connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms @@ -241,7 +194,6 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999); ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue); - //m_channelMarker = new ChannelMarker(this); m_channelMarker.setColor(Qt::yellow); m_channelMarker.setBandwidth(5000); m_channelMarker.setCenterFrequency(0); @@ -250,6 +202,7 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget m_channelMarker.setUDPSendPort(9999); m_channelMarker.setVisible(true); setTitleColor(m_channelMarker.getColor()); + m_settings.setChannelMarker(&m_channelMarker); connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); @@ -257,17 +210,14 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget m_deviceAPI->addChannelMarker(&m_channelMarker); m_deviceAPI->addRollupWidget(this); + displaySettings(); applySettings(true); } AMDemodGUI::~AMDemodGUI() { m_deviceAPI->removeChannelInstance(this); - m_deviceAPI->removeThreadedSink(m_threadedChannelizer); - delete m_threadedChannelizer; - delete m_channelizer; delete m_amDemod; - //delete m_channelMarker; delete ui; } @@ -282,30 +232,62 @@ void AMDemodGUI::applySettings(bool force) { setTitleColor(m_channelMarker.getColor()); - m_channelizer->configure(m_channelizer->getInputMessageQueue(), - 48000, - m_channelMarker.getCenterFrequency()); + AMDemod::MsgConfigureChannelizer* channelConfigMsg = AMDemod::MsgConfigureChannelizer::create( + 48000, m_channelMarker.getCenterFrequency()); + m_amDemod->getInputMessageQueue()->push(channelConfigMsg); ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); - m_amDemod->configure(m_amDemod->getInputMessageQueue(), - ui->rfBW->value() * 100.0, - ui->volume->value() / 10.0, - ui->squelch->value(), - ui->audioMute->isChecked(), - ui->bandpassEnable->isChecked(), - ui->copyAudioToUDP->isChecked(), - m_channelMarker.getUDPAddress(), - m_channelMarker.getUDPSendPort(), - force); + AMDemod::MsgConfigureAMDemod* message = AMDemod::MsgConfigureAMDemod::create( m_settings, force); + m_amDemod->getInputMessageQueue()->push(message); } } +void AMDemodGUI::displaySettings() +{ + blockApplySettings(true); + + int displayValue = m_settings.m_rfBandwidth/100.0; + ui->rfBW->setValue(displayValue); + ui->rfBWText->setText(QString("%1 kHz").arg(displayValue / 10.0, 0, 'f', 1)); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); + + ui->volume->setValue(m_settings.m_volume * 10.0); + ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1)); + + ui->squelch->setValue(m_settings.m_squelch); + ui->squelchText->setText(QString("%1 dB").arg(m_settings.m_squelch)); + + ui->audioMute->setChecked(m_settings.m_audioMute); + ui->bandpassEnable->setChecked(m_settings.m_bandpassEnable); + ui->copyAudioToUDP->setChecked(m_settings.m_copyAudioToUDP); + + m_channelMarker.blockSignals(true); + m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); + m_channelMarker.setUDPAddress(m_settings.m_udpAddress); + m_channelMarker.setUDPSendPort(m_settings.m_udpPort); + m_channelMarker.setColor(m_settings.m_rgbColor); + setTitleColor(m_settings.m_rgbColor); + m_channelMarker.blockSignals(false); + + blockApplySettings(false); +} + void AMDemodGUI::displayUDPAddress() { ui->copyAudioToUDP->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort())); } +void AMDemodGUI::updateChannelMarker() +{ + m_channelMarker.blockSignals(true); + + //m_channelMarker.deserialize(m_settings.m_channelMarkerBytes); + this->setWindowTitle(m_channelMarker.getTitle()); + + m_channelMarker.blockSignals(false); +} + void AMDemodGUI::leaveEvent(QEvent*) { blockApplySettings(true); diff --git a/plugins/channelrx/demodam/amdemodgui.h b/plugins/channelrx/demodam/amdemodgui.h index 1133d8bf4..fdc82a477 100644 --- a/plugins/channelrx/demodam/amdemodgui.h +++ b/plugins/channelrx/demodam/amdemodgui.h @@ -1,11 +1,12 @@ #ifndef INCLUDE_AMDEMODGUI_H #define INCLUDE_AMDEMODGUI_H +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" +#include "amdemodsettings.h" class PluginAPI; class DeviceSourceAPI; @@ -18,7 +19,7 @@ namespace Ui { class AMDemodGUI; } -class AMDemodGUI : public RollupWidget, public PluginInstanceUI { +class AMDemodGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -56,10 +57,11 @@ private: PluginAPI* m_pluginAPI; DeviceSourceAPI* m_deviceAPI; ChannelMarker m_channelMarker; + AMDemodSettings m_settings; bool m_doApplySettings; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; +// ThreadedBasebandSampleSink* m_threadedChannelizer; +// DownChannelizer* m_channelizer; AMDemod* m_amDemod; bool m_squelchOpen; uint32_t m_tickCount; @@ -70,7 +72,9 @@ private: void blockApplySettings(bool block); void applySettings(bool force = false); + void displaySettings(); void displayUDPAddress(); + void updateChannelMarker(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/channelrx/demodam/amdemodplugin.cpp b/plugins/channelrx/demodam/amdemodplugin.cpp index 1384d25d1..4cb488aff 100644 --- a/plugins/channelrx/demodam/amdemodplugin.cpp +++ b/plugins/channelrx/demodam/amdemodplugin.cpp @@ -7,7 +7,7 @@ const PluginDescriptor AMDemodPlugin::m_pluginDescriptor = { QString("AM Demodulator"), - QString("3.6.1"), + QString("3.7.3"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -33,7 +33,7 @@ void AMDemodPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(AMDemodGUI::m_channelID, this); } -PluginInstanceUI* AMDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* AMDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == AMDemodGUI::m_channelID) { diff --git a/plugins/channelrx/demodam/amdemodplugin.h b/plugins/channelrx/demodam/amdemodplugin.h index adc15d026..903c6d7c4 100644 --- a/plugins/channelrx/demodam/amdemodplugin.h +++ b/plugins/channelrx/demodam/amdemodplugin.h @@ -33,7 +33,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodam/amdemodsettings.cpp b/plugins/channelrx/demodam/amdemodsettings.cpp new file mode 100644 index 000000000..e9a14c14f --- /dev/null +++ b/plugins/channelrx/demodam/amdemodsettings.cpp @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "dsp/dspengine.h" +#include "util/simpleserializer.h" +#include "settings/serializable.h" +#include "amdemodsettings.h" + +AMDemodSettings::AMDemodSettings() : + m_channelMarker(0) +{ + resetToDefaults(); +} + +void AMDemodSettings::resetToDefaults() +{ + m_inputSampleRate = 96000; + m_inputFrequencyOffset = 0; + m_rfBandwidth = 5000; + m_squelch = -40.0; + m_volume = 2.0; + m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); + m_audioMute = false; + m_bandpassEnable = false; + m_copyAudioToUDP = false; + m_udpAddress = "127.0.0.1"; + m_udpPort = 9999; +} + +QByteArray AMDemodSettings::serialize() const +{ + SimpleSerializer s(1); + s.writeS32(1, m_inputFrequencyOffset); + s.writeS32(2, m_rfBandwidth/100); + s.writeS32(4, m_volume*10); + s.writeS32(5, m_squelch); + + if (m_channelMarker) { + s.writeBlob(6, m_channelMarker->serialize()); + } + + s.writeU32(7, m_rgbColor); + s.writeBool(8, m_bandpassEnable); + return s.final(); +} + +bool AMDemodSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) + { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) + { + QByteArray bytetmp; + qint32 tmp; + QString strtmp; + + d.readS32(1, &m_inputFrequencyOffset, 0); + d.readS32(2, &tmp, 4); + m_rfBandwidth = 100 * tmp; + d.readS32(4, &tmp, 20); + m_volume = tmp * 0.1; + d.readS32(5, &tmp, -40); + m_squelch = tmp; + d.readBlob(6, &bytetmp); + + if (m_channelMarker) { + m_channelMarker->deserialize(bytetmp); + } + + d.readU32(7, &m_rgbColor); + d.readBool(8, &m_bandpassEnable, false); + return true; + } + else + { + resetToDefaults(); + return false; + } +} + + diff --git a/plugins/channelrx/demodam/amdemodsettings.h b/plugins/channelrx/demodam/amdemodsettings.h new file mode 100644 index 000000000..b07bc0c74 --- /dev/null +++ b/plugins/channelrx/demodam/amdemodsettings.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 PLUGINS_CHANNELRX_DEMODAM_AMDEMODSETTINGS_H_ +#define PLUGINS_CHANNELRX_DEMODAM_AMDEMODSETTINGS_H_ + +#include + +class Serializable; + +struct AMDemodSettings +{ + int m_inputSampleRate; + qint32 m_inputFrequencyOffset; + Real m_rfBandwidth; + Real m_squelch; + Real m_volume; + quint32 m_audioSampleRate; + bool m_audioMute; + bool m_bandpassEnable; + bool m_copyAudioToUDP; + QString m_udpAddress; + quint16 m_udpPort; + quint32 m_rgbColor; + Serializable *m_channelMarker; + + AMDemodSettings(); + void resetToDefaults(); + void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + + + +#endif /* PLUGINS_CHANNELRX_DEMODAM_AMDEMODSETTINGS_H_ */ diff --git a/plugins/channelrx/demodam/demodam.pro b/plugins/channelrx/demodam/demodam.pro index 2fb2826ad..ed42eeec6 100644 --- a/plugins/channelrx/demodam/demodam.pro +++ b/plugins/channelrx/demodam/demodam.pro @@ -25,11 +25,13 @@ CONFIG(Debug):build_subdir = debug SOURCES += amdemod.cpp\ amdemodgui.cpp\ - amdemodplugin.cpp + amdemodplugin.cpp\ + amdemodsettings.cpp HEADERS += amdemod.h\ amdemodgui.h\ - amdemodplugin.h + amdemodplugin.h\ + amdemodsettings.h FORMS += amdemodgui.ui diff --git a/plugins/channelrx/demodatv/atvdemod.cpp b/plugins/channelrx/demodatv/atvdemod.cpp index 7d41a828c..93e8192cb 100644 --- a/plugins/channelrx/demodatv/atvdemod.cpp +++ b/plugins/channelrx/demodatv/atvdemod.cpp @@ -31,9 +31,9 @@ MESSAGE_CLASS_DEFINITION(ATVDemod::MsgReportEffectiveSampleRate, Message) const int ATVDemod::m_ssbFftLen = 1024; -ATVDemod::ATVDemod(BasebandSampleSink* objScopeSink) : - m_objScopeSink(objScopeSink), - m_objRegisteredATVScreen(NULL), +ATVDemod::ATVDemod(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_registeredATVScreen(NULL), m_intNumberSamplePerTop(0), m_intImageIndex(0), m_intSynchroPoints(0), @@ -70,7 +70,7 @@ ATVDemod::ATVDemod(BasebandSampleSink* objScopeSink) : m_objMagSqAverage.resize(32, 1.0); - m_DSBFilter = new fftfilt((2.0f * m_objRFConfig.m_fltRFBandwidth) / 1000000, 2 * m_ssbFftLen); // arbitrary 1 MS/s sample rate + m_DSBFilter = new fftfilt((2.0f * m_rfConfig.m_fltRFBandwidth) / 1000000, 2 * m_ssbFftLen); // arbitrary 1 MS/s sample rate m_DSBFilterBuffer = new Complex[m_ssbFftLen]; memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen)); @@ -88,7 +88,7 @@ ATVDemod::~ATVDemod() void ATVDemod::setATVScreen(ATVScreen *objScreen) { - m_objRegisteredATVScreen = objScreen; + m_registeredATVScreen = objScreen; } void ATVDemod::configure( @@ -188,12 +188,12 @@ void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto #endif Complex c(fltI, fltQ); - if (m_objRFRunning.m_intFrequencyOffset != 0) + if (m_rfRunning.m_intFrequencyOffset != 0) { c *= m_nco.nextIQ(); } - if (m_objRFRunning.m_blndecimatorEnable) + if (m_rfRunning.m_blndecimatorEnable) { if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) { @@ -207,10 +207,10 @@ void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto } } - if ((m_objRunning.m_intVideoTabIndex == 1) && (m_objScopeSink != 0)) // do only if scope tab is selected and scope is available + if ((m_running.m_intVideoTabIndex == 1) && (m_scopeSink != 0)) // do only if scope tab is selected and scope is available { - m_objScopeSink->feed(m_objScopeSampleBuffer.begin(), m_objScopeSampleBuffer.end(), false); // m_ssb = positive only - m_objScopeSampleBuffer.clear(); + m_scopeSink->feed(m_scopeSampleBuffer.begin(), m_scopeSampleBuffer.end(), false); // m_ssb = positive only + m_scopeSampleBuffer.clear(); } if (ptrBufferToRelease != 0) @@ -223,7 +223,7 @@ void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto void ATVDemod::demod(Complex& c) { - float fltDivSynchroBlack = 1.0f - m_objRunning.m_fltVoltLevelSynchroBlack; + float fltDivSynchroBlack = 1.0f - m_running.m_fltVoltLevelSynchroBlack; float fltNormI; float fltNormQ; float fltNorm; @@ -232,12 +232,12 @@ void ATVDemod::demod(Complex& c) //********** FFT filtering ********** - if (m_objRFRunning.m_blnFFTFiltering) + if (m_rfRunning.m_blnFFTFiltering) { int n_out; fftfilt::cmplx *filtered; - n_out = m_DSBFilter->runAsym(c, &filtered, m_objRFRunning.m_enmModulation != ATV_LSB); // all usb except explicitely lsb + n_out = m_DSBFilter->runAsym(c, &filtered, m_rfRunning.m_enmModulation != ATV_LSB); // all usb except explicitely lsb if (n_out > 0) { @@ -250,11 +250,11 @@ void ATVDemod::demod(Complex& c) //********** demodulation ********** - const float& fltI = m_objRFRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].real() : c.real(); - const float& fltQ = m_objRFRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].imag() : c.imag(); + const float& fltI = m_rfRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].real() : c.real(); + const float& fltQ = m_rfRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].imag() : c.imag(); double magSq; - if ((m_objRFRunning.m_enmModulation == ATV_FM1) || (m_objRFRunning.m_enmModulation == ATV_FM2)) + if ((m_rfRunning.m_enmModulation == ATV_FM1) || (m_rfRunning.m_enmModulation == ATV_FM2)) { //Amplitude FM magSq = fltI*fltI + fltQ*fltQ; @@ -266,7 +266,7 @@ void ATVDemod::demod(Complex& c) //-2 > 2 : 0 -> 1 volt //0->0.3 synchro 0.3->1 image - if (m_objRFRunning.m_enmModulation == ATV_FM1) + if (m_rfRunning.m_enmModulation == ATV_FM1) { //YDiff Cd fltVal = m_fltBufferI[0]*(fltNormQ - m_fltBufferQ[1]); @@ -304,12 +304,12 @@ void ATVDemod::demod(Complex& c) m_fltBufferI[0]=fltNormI; m_fltBufferQ[0]=fltNormQ; - if (m_objRFRunning.m_fmDeviation != 1.0f) + if (m_rfRunning.m_fmDeviation != 1.0f) { - fltVal = ((fltVal - 0.5f) / m_objRFRunning.m_fmDeviation) + 0.5f; + fltVal = ((fltVal - 0.5f) / m_rfRunning.m_fmDeviation) + 0.5f; } } - else if (m_objRFRunning.m_enmModulation == ATV_AM) + else if (m_rfRunning.m_enmModulation == ATV_AM) { //Amplitude AM magSq = fltI*fltI + fltQ*fltQ; @@ -334,7 +334,7 @@ void ATVDemod::demod(Complex& c) fltVal -= m_fltAmpMin; fltVal /=m_fltAmpDelta; } - else if ((m_objRFRunning.m_enmModulation == ATV_USB) || (m_objRFRunning.m_enmModulation == ATV_LSB)) + else if ((m_rfRunning.m_enmModulation == ATV_USB) || (m_rfRunning.m_enmModulation == ATV_LSB)) { magSq = fltI*fltI + fltQ*fltQ; m_objMagSqAverage.feed(magSq); @@ -349,7 +349,7 @@ void ATVDemod::demod(Complex& c) float mixI = fltI * bfoValues[0] - fltQ * bfoValues[1]; float mixQ = fltI * bfoValues[1] + fltQ * bfoValues[0]; - if (m_objRFRunning.m_enmModulation == ATV_USB) { + if (m_rfRunning.m_enmModulation == ATV_USB) { fltVal = (mixI + mixQ); } else { fltVal = (mixI - mixQ); @@ -371,7 +371,7 @@ void ATVDemod::demod(Complex& c) fltVal -= m_fltAmpMin; fltVal /=m_fltAmpDelta; } - else if (m_objRFRunning.m_enmModulation == ATV_FM3) + else if (m_rfRunning.m_enmModulation == ATV_FM3) { float rawDeviation; fltVal = m_objPhaseDiscri.phaseDiscriminatorDelta(c, magSq, rawDeviation) + 0.5f; @@ -387,18 +387,18 @@ void ATVDemod::demod(Complex& c) fltVal = 0.0f; } - fltVal = m_objRunning.m_blnInvertVideo ? 1.0f - fltVal : fltVal; + fltVal = m_running.m_blnInvertVideo ? 1.0f - fltVal : fltVal; fltVal = (fltVal < -1.0f) ? -1.0f : (fltVal > 1.0f) ? 1.0f : fltVal; - if ((m_objRunning.m_intVideoTabIndex == 1) && (m_objScopeSink != 0)) { // feed scope buffer only if scope is present and visible - m_objScopeSampleBuffer.push_back(Sample(fltVal*32767.0f, 0.0f)); + if ((m_running.m_intVideoTabIndex == 1) && (m_scopeSink != 0)) { // feed scope buffer only if scope is present and visible + m_scopeSampleBuffer.push_back(Sample(fltVal*32767.0f, 0.0f)); } m_fltAmpLineAverage += fltVal; //********** gray level ********** //-0.3 -> 0.7 - intVal = (int) 255.0*(fltVal - m_objRunning.m_fltVoltLevelSynchroBlack) / fltDivSynchroBlack; + intVal = (int) 255.0*(fltVal - m_running.m_fltVoltLevelSynchroBlack) / fltDivSynchroBlack; //0 -> 255 if(intVal<0) @@ -412,7 +412,7 @@ void ATVDemod::demod(Complex& c) //********** process video sample ********** - if (m_objRunning.m_enmATVStandard == ATVStdHSkip) + if (m_running.m_enmATVStandard == ATVStdHSkip) { processHSkip(fltVal, intVal); } @@ -438,12 +438,12 @@ bool ATVDemod::handleMessage(const Message& cmd) if (DownChannelizer::MsgChannelizerNotification::match(cmd)) { DownChannelizer::MsgChannelizerNotification& objNotif = (DownChannelizer::MsgChannelizerNotification&) cmd; - m_objConfig.m_intSampleRate = objNotif.getSampleRate(); - m_objRFConfig.m_intFrequencyOffset = objNotif.getFrequencyOffset(); + m_config.m_intSampleRate = objNotif.getSampleRate(); + m_rfConfig.m_intFrequencyOffset = objNotif.getFrequencyOffset(); qDebug() << "ATVDemod::handleMessage: MsgChannelizerNotification:" - << " m_intSampleRate: " << m_objConfig.m_intSampleRate - << " m_intFrequencyOffset: " << m_objRFConfig.m_intFrequencyOffset; + << " m_intSampleRate: " << m_config.m_intSampleRate + << " m_intFrequencyOffset: " << m_rfConfig.m_intFrequencyOffset; applySettings(); @@ -453,17 +453,17 @@ bool ATVDemod::handleMessage(const Message& cmd) { MsgConfigureATVDemod& objCfg = (MsgConfigureATVDemod&) cmd; - m_objConfig = objCfg.m_objMsgConfig; + m_config = objCfg.m_objMsgConfig; qDebug() << "ATVDemod::handleMessage: MsgConfigureATVDemod:" - << " m_fltVoltLevelSynchroBlack:" << m_objConfig.m_fltVoltLevelSynchroBlack - << " m_fltVoltLevelSynchroTop:" << m_objConfig.m_fltVoltLevelSynchroTop - << " m_fltFramePerS:" << m_objConfig.m_fltFramePerS - << " m_fltLineDurationUs:" << m_objConfig.m_fltLineDuration - << " m_fltRatioOfRowsToDisplay:" << m_objConfig.m_fltRatioOfRowsToDisplay - << " m_fltTopDurationUs:" << m_objConfig.m_fltTopDuration - << " m_blnHSync:" << m_objConfig.m_blnHSync - << " m_blnVSync:" << m_objConfig.m_blnVSync; + << " m_fltVoltLevelSynchroBlack:" << m_config.m_fltVoltLevelSynchroBlack + << " m_fltVoltLevelSynchroTop:" << m_config.m_fltVoltLevelSynchroTop + << " m_fltFramePerS:" << m_config.m_fltFramePerS + << " m_fltLineDurationUs:" << m_config.m_fltLineDuration + << " m_fltRatioOfRowsToDisplay:" << m_config.m_fltRatioOfRowsToDisplay + << " m_fltTopDurationUs:" << m_config.m_fltTopDuration + << " m_blnHSync:" << m_config.m_blnHSync + << " m_blnVSync:" << m_config.m_blnVSync; applySettings(); @@ -473,16 +473,16 @@ bool ATVDemod::handleMessage(const Message& cmd) { MsgConfigureRFATVDemod& objCfg = (MsgConfigureRFATVDemod&) cmd; - m_objRFConfig = objCfg.m_objMsgConfig; + m_rfConfig = objCfg.m_objMsgConfig; qDebug() << "ATVDemod::handleMessage: MsgConfigureRFATVDemod:" - << " m_enmModulation:" << m_objRFConfig.m_enmModulation - << " m_fltRFBandwidth:" << m_objRFConfig.m_fltRFBandwidth - << " m_fltRFOppBandwidth:" << m_objRFConfig.m_fltRFOppBandwidth - << " m_blnFFTFiltering:" << m_objRFConfig.m_blnFFTFiltering - << " m_blnDecimatorEnable:" << m_objRFConfig.m_blndecimatorEnable - << " m_fltBFOFrequency:" << m_objRFConfig.m_fltBFOFrequency - << " m_fmDeviation:" << m_objRFConfig.m_fmDeviation; + << " m_enmModulation:" << m_rfConfig.m_enmModulation + << " m_fltRFBandwidth:" << m_rfConfig.m_fltRFBandwidth + << " m_fltRFOppBandwidth:" << m_rfConfig.m_fltRFOppBandwidth + << " m_blnFFTFiltering:" << m_rfConfig.m_blnFFTFiltering + << " m_blnDecimatorEnable:" << m_rfConfig.m_blndecimatorEnable + << " m_fltBFOFrequency:" << m_rfConfig.m_fltBFOFrequency + << " m_fmDeviation:" << m_rfConfig.m_fmDeviation; applySettings(); @@ -490,9 +490,9 @@ bool ATVDemod::handleMessage(const Message& cmd) } else { - if (m_objScopeSink != 0) + if (m_scopeSink != 0) { - return m_objScopeSink->handleMessage(cmd); + return m_scopeSink->handleMessage(cmd); } else { @@ -504,30 +504,30 @@ bool ATVDemod::handleMessage(const Message& cmd) void ATVDemod::applySettings() { - if (m_objConfig.m_intSampleRate == 0) + if (m_config.m_intSampleRate == 0) { return; } bool forwardSampleRateChange = false; - if((m_objRFConfig.m_intFrequencyOffset != m_objRFRunning.m_intFrequencyOffset) - || (m_objRFConfig.m_enmModulation != m_objRFRunning.m_enmModulation) - || (m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate)) + if((m_rfConfig.m_intFrequencyOffset != m_rfRunning.m_intFrequencyOffset) + || (m_rfConfig.m_enmModulation != m_rfRunning.m_enmModulation) + || (m_config.m_intSampleRate != m_running.m_intSampleRate)) { - m_nco.setFreq(-m_objRFConfig.m_intFrequencyOffset, m_objConfig.m_intSampleRate); + m_nco.setFreq(-m_rfConfig.m_intFrequencyOffset, m_config.m_intSampleRate); } - if ((m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate) - || (m_objRFConfig.m_fltRFBandwidth != m_objRFRunning.m_fltRFBandwidth) - || (m_objConfig.m_fltFramePerS != m_objRunning.m_fltFramePerS) - || (m_objConfig.m_intNumberOfLines != m_objRunning.m_intNumberOfLines)) + if ((m_config.m_intSampleRate != m_running.m_intSampleRate) + || (m_rfConfig.m_fltRFBandwidth != m_rfRunning.m_fltRFBandwidth) + || (m_config.m_fltFramePerS != m_running.m_fltFramePerS) + || (m_config.m_intNumberOfLines != m_running.m_intNumberOfLines)) { m_objSettingsMutex.lock(); - int linesPerSecond = m_objConfig.m_intNumberOfLines * m_objConfig.m_fltFramePerS; + int linesPerSecond = m_config.m_intNumberOfLines * m_config.m_fltFramePerS; - int maxPoints = m_objConfig.m_intSampleRate / linesPerSecond; + int maxPoints = m_config.m_intSampleRate / linesPerSecond; int i = maxPoints; for (; i > 0; i--) @@ -537,53 +537,53 @@ void ATVDemod::applySettings() } int nbPointsPerRateUnit = i == 0 ? maxPoints : i; - m_objConfigPrivate.m_intTVSampleRate = nbPointsPerRateUnit * linesPerSecond; + m_configPrivate.m_intTVSampleRate = nbPointsPerRateUnit * linesPerSecond; - if (m_objConfigPrivate.m_intTVSampleRate > 0) + if (m_configPrivate.m_intTVSampleRate > 0) { - m_interpolatorDistance = (Real) m_objConfigPrivate.m_intTVSampleRate / (Real) m_objConfig.m_intSampleRate; + m_interpolatorDistance = (Real) m_configPrivate.m_intTVSampleRate / (Real) m_config.m_intSampleRate; } else { - m_objConfigPrivate.m_intTVSampleRate = m_objConfig.m_intSampleRate; + m_configPrivate.m_intTVSampleRate = m_config.m_intSampleRate; m_interpolatorDistance = 1.0f; } m_interpolatorDistanceRemain = 0; m_interpolator.create(24, - m_objConfigPrivate.m_intTVSampleRate, - m_objRFConfig.m_fltRFBandwidth / getRFBandwidthDivisor(m_objRFConfig.m_enmModulation), + m_configPrivate.m_intTVSampleRate, + m_rfConfig.m_fltRFBandwidth / getRFBandwidthDivisor(m_rfConfig.m_enmModulation), 3.0); m_objSettingsMutex.unlock(); } - if((m_objConfig.m_fltFramePerS != m_objRunning.m_fltFramePerS) - || (m_objConfig.m_fltLineDuration != m_objRunning.m_fltLineDuration) - || (m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate) - || (m_objConfig.m_fltTopDuration != m_objRunning.m_fltTopDuration) - || (m_objConfig.m_fltRatioOfRowsToDisplay != m_objRunning.m_fltRatioOfRowsToDisplay) - || (m_objConfig.m_enmATVStandard != m_objRunning.m_enmATVStandard) - || (m_objConfig.m_intNumberOfLines != m_objRunning.m_intNumberOfLines)) + if((m_config.m_fltFramePerS != m_running.m_fltFramePerS) + || (m_config.m_fltLineDuration != m_running.m_fltLineDuration) + || (m_config.m_intSampleRate != m_running.m_intSampleRate) + || (m_config.m_fltTopDuration != m_running.m_fltTopDuration) + || (m_config.m_fltRatioOfRowsToDisplay != m_running.m_fltRatioOfRowsToDisplay) + || (m_config.m_enmATVStandard != m_running.m_enmATVStandard) + || (m_config.m_intNumberOfLines != m_running.m_intNumberOfLines)) { m_objSettingsMutex.lock(); - m_intNumberOfLines = m_objConfig.m_intNumberOfLines; + m_intNumberOfLines = m_config.m_intNumberOfLines; applyStandard(); - m_objConfigPrivate.m_intNumberSamplePerLine = (int) (m_objConfig.m_fltLineDuration * m_objConfig.m_intSampleRate); - m_intNumberSamplePerTop = (int) (m_objConfig.m_fltTopDuration * m_objConfig.m_intSampleRate); + m_configPrivate.m_intNumberSamplePerLine = (int) (m_config.m_fltLineDuration * m_config.m_intSampleRate); + m_intNumberSamplePerTop = (int) (m_config.m_fltTopDuration * m_config.m_intSampleRate); - m_objRegisteredATVScreen->setRenderImmediate(!(m_objConfig.m_fltFramePerS > 25.0f)); - m_objRegisteredATVScreen->resizeATVScreen( - m_objConfigPrivate.m_intNumberSamplePerLine - m_intNumberSamplePerLineSignals, + m_registeredATVScreen->setRenderImmediate(!(m_config.m_fltFramePerS > 25.0f)); + m_registeredATVScreen->resizeATVScreen( + m_configPrivate.m_intNumberSamplePerLine - m_intNumberSamplePerLineSignals, m_intNumberOfLines - m_intNumberOfBlackLines); qDebug() << "ATVDemod::applySettings:" - << " m_fltLineDuration: " << m_objConfig.m_fltLineDuration - << " m_fltFramePerS: " << m_objConfig.m_fltFramePerS + << " m_fltLineDuration: " << m_config.m_fltLineDuration + << " m_fltFramePerS: " << m_config.m_fltFramePerS << " m_intNumberOfLines: " << m_intNumberOfLines - << " m_intNumberSamplePerLine: " << m_objConfigPrivate.m_intNumberSamplePerLine + << " m_intNumberSamplePerLine: " << m_configPrivate.m_intNumberSamplePerLine << " m_intNumberOfBlackLines: " << m_intNumberOfBlackLines; m_intImageIndex = 0; @@ -593,56 +593,56 @@ void ATVDemod::applySettings() m_objSettingsMutex.unlock(); } - if ((m_objConfigPrivate.m_intTVSampleRate != m_objRunningPrivate.m_intTVSampleRate) - || (m_objConfigPrivate.m_intNumberSamplePerLine != m_objRunningPrivate.m_intNumberSamplePerLine) - || (m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate) - || (m_objRFConfig.m_blndecimatorEnable != m_objRFRunning.m_blndecimatorEnable)) + if ((m_configPrivate.m_intTVSampleRate != m_runningPrivate.m_intTVSampleRate) + || (m_configPrivate.m_intNumberSamplePerLine != m_runningPrivate.m_intNumberSamplePerLine) + || (m_config.m_intSampleRate != m_running.m_intSampleRate) + || (m_rfConfig.m_blndecimatorEnable != m_rfRunning.m_blndecimatorEnable)) { forwardSampleRateChange = true; } - if ((m_objConfigPrivate.m_intTVSampleRate != m_objRunningPrivate.m_intTVSampleRate) - || (m_objRFConfig.m_fltRFBandwidth != m_objRFRunning.m_fltRFBandwidth) - || (m_objRFConfig.m_fltRFOppBandwidth != m_objRFRunning.m_fltRFOppBandwidth)) + if ((m_configPrivate.m_intTVSampleRate != m_runningPrivate.m_intTVSampleRate) + || (m_rfConfig.m_fltRFBandwidth != m_rfRunning.m_fltRFBandwidth) + || (m_rfConfig.m_fltRFOppBandwidth != m_rfRunning.m_fltRFOppBandwidth)) { m_objSettingsMutex.lock(); - m_DSBFilter->create_asym_filter(m_objRFConfig.m_fltRFOppBandwidth / m_objConfigPrivate.m_intTVSampleRate, - m_objRFConfig.m_fltRFBandwidth / m_objConfigPrivate.m_intTVSampleRate); + m_DSBFilter->create_asym_filter(m_rfConfig.m_fltRFOppBandwidth / m_configPrivate.m_intTVSampleRate, + m_rfConfig.m_fltRFBandwidth / m_configPrivate.m_intTVSampleRate); memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen)); m_DSBFilterBufferIndex = 0; m_objSettingsMutex.unlock(); } - if ((m_objConfigPrivate.m_intTVSampleRate != m_objRunningPrivate.m_intTVSampleRate) - || (m_objRFConfig.m_fltBFOFrequency != m_objRFRunning.m_fltBFOFrequency)) + if ((m_configPrivate.m_intTVSampleRate != m_runningPrivate.m_intTVSampleRate) + || (m_rfConfig.m_fltBFOFrequency != m_rfRunning.m_fltBFOFrequency)) { - m_bfoPLL.configure(m_objRFConfig.m_fltBFOFrequency / m_objConfigPrivate.m_intTVSampleRate, - 100.0 / m_objConfigPrivate.m_intTVSampleRate, + m_bfoPLL.configure(m_rfConfig.m_fltBFOFrequency / m_configPrivate.m_intTVSampleRate, + 100.0 / m_configPrivate.m_intTVSampleRate, 0.01); - m_bfoFilter.setFrequencies(m_objRFConfig.m_fltBFOFrequency, m_objConfigPrivate.m_intTVSampleRate); + m_bfoFilter.setFrequencies(m_rfConfig.m_fltBFOFrequency, m_configPrivate.m_intTVSampleRate); } - if (m_objRFConfig.m_fmDeviation != m_objRFRunning.m_fmDeviation) + if (m_rfConfig.m_fmDeviation != m_rfRunning.m_fmDeviation) { - m_objPhaseDiscri.setFMScaling(1.0f / m_objRFConfig.m_fmDeviation); + m_objPhaseDiscri.setFMScaling(1.0f / m_rfConfig.m_fmDeviation); } - m_objRunning = m_objConfig; - m_objRFRunning = m_objRFConfig; - m_objRunningPrivate = m_objConfigPrivate; + m_running = m_config; + m_rfRunning = m_rfConfig; + m_runningPrivate = m_configPrivate; if (forwardSampleRateChange) { - int sampleRate = m_objRFRunning.m_blndecimatorEnable ? m_objRunningPrivate.m_intTVSampleRate : m_objRunning.m_intSampleRate; + int sampleRate = m_rfRunning.m_blndecimatorEnable ? m_runningPrivate.m_intTVSampleRate : m_running.m_intSampleRate; MsgReportEffectiveSampleRate *report; - report = MsgReportEffectiveSampleRate::create(sampleRate, m_objRunningPrivate.m_intNumberSamplePerLine); - getOutputMessageQueue()->push(report); + report = MsgReportEffectiveSampleRate::create(sampleRate, m_runningPrivate.m_intNumberSamplePerLine); + getMessageQueueToGUI()->push(report); } } void ATVDemod::applyStandard() { - switch(m_objConfig.m_enmATVStandard) + switch(m_config.m_enmATVStandard) { case ATVStdHSkip: // what is left in a line for the image @@ -689,23 +689,23 @@ void ATVDemod::applyStandard() } // for now all standards apply this - m_intNumberSamplePerLineSignals = (int) ((12.0f/64.0f)*m_objConfig.m_fltLineDuration * m_objConfig.m_intSampleRate); // 12.0 = 7.3 + 4.7 - m_intNumberSaplesPerHSync = (int) ((9.6f/64.0f)*m_objConfig.m_fltLineDuration * m_objConfig.m_intSampleRate); // 9.4 = 4.7 + 4.7 + m_intNumberSamplePerLineSignals = (int) ((12.0f/64.0f)*m_config.m_fltLineDuration * m_config.m_intSampleRate); // 12.0 = 7.3 + 4.7 + m_intNumberSaplesPerHSync = (int) ((9.6f/64.0f)*m_config.m_fltLineDuration * m_config.m_intSampleRate); // 9.4 = 4.7 + 4.7 } int ATVDemod::getSampleRate() { - return m_objRunning.m_intSampleRate; + return m_running.m_intSampleRate; } int ATVDemod::getEffectiveSampleRate() { - return m_objRFRunning.m_blndecimatorEnable ? m_objRunningPrivate.m_intTVSampleRate : m_objRunning.m_intSampleRate; + return m_rfRunning.m_blndecimatorEnable ? m_runningPrivate.m_intTVSampleRate : m_running.m_intSampleRate; } bool ATVDemod::getBFOLocked() { - if ((m_objRFRunning.m_enmModulation == ATV_USB) || (m_objRFRunning.m_enmModulation == ATV_LSB)) + if ((m_rfRunning.m_enmModulation == ATV_USB) || (m_rfRunning.m_enmModulation == ATV_LSB)) { return m_bfoPLL.locked(); } diff --git a/plugins/channelrx/demodatv/atvdemod.h b/plugins/channelrx/demodatv/atvdemod.h index 60b19f015..a561d834e 100644 --- a/plugins/channelrx/demodatv/atvdemod.h +++ b/plugins/channelrx/demodatv/atvdemod.h @@ -38,6 +38,7 @@ #include "util/message.h" #include "atvscreen.h" +class DeviceSourceAPI; class ATVDemod : public BasebandSampleSink { @@ -146,8 +147,9 @@ public: { } }; - ATVDemod(BasebandSampleSink* objScopeSink); + ATVDemod(DeviceSourceAPI *deviceAPI); ~ATVDemod(); + void setScopeSink(BasebandSampleSink* scopeSink) { m_scopeSink = scopeSink; } void configure(MessageQueue* objMessageQueue, float fltLineDurationUs, @@ -339,13 +341,15 @@ private: bool m_start; }; + DeviceSourceAPI* m_deviceAPI; + //*************** SCOPE *************** - BasebandSampleSink* m_objScopeSink; - SampleVector m_objScopeSampleBuffer; + BasebandSampleSink* m_scopeSink; + SampleVector m_scopeSampleBuffer; //*************** ATV PARAMETERS *************** - ATVScreen * m_objRegisteredATVScreen; + ATVScreen * m_registeredATVScreen; //int m_intNumberSamplePerLine; int m_intNumberSamplePerTop; @@ -411,14 +415,14 @@ private: //QElapsedTimer m_objTimer; - ATVConfig m_objRunning; - ATVConfig m_objConfig; + ATVConfig m_running; + ATVConfig m_config; - ATVRFConfig m_objRFRunning; - ATVRFConfig m_objRFConfig; + ATVRFConfig m_rfRunning; + ATVRFConfig m_rfConfig; - ATVConfigPrivate m_objRunningPrivate; - ATVConfigPrivate m_objConfigPrivate; + ATVConfigPrivate m_runningPrivate; + ATVConfigPrivate m_configPrivate; QMutex m_objSettingsMutex; @@ -429,17 +433,17 @@ private: inline void processHSkip(float& fltVal, int& intVal) { - m_objRegisteredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop, intVal, intVal, intVal); + m_registeredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop, intVal, intVal, intVal); // Horizontal Synchro detection // Floor Detection 0 - if (fltVal < m_objRunning.m_fltVoltLevelSynchroTop) + if (fltVal < m_running.m_fltVoltLevelSynchroTop) { m_intSynchroPoints++; } // Black detection 0.3 - else if (fltVal > m_objRunning.m_fltVoltLevelSynchroBlack) + else if (fltVal > m_running.m_fltVoltLevelSynchroBlack) { m_intSynchroPoints = 0; } @@ -450,11 +454,11 @@ private: if (m_blnSynchroDetected) { - if (m_intSampleIndex >= (3 * m_objRunningPrivate.m_intNumberSamplePerLine)/2) // first after skip + if (m_intSampleIndex >= (3 * m_runningPrivate.m_intNumberSamplePerLine)/2) // first after skip { //qDebug("VSync: %d %d %d", m_intColIndex, m_intSampleIndex, m_intLineIndex); m_intAvgColIndex = m_intColIndex; - m_objRegisteredATVScreen->renderImage(0); + m_registeredATVScreen->renderImage(0); m_intImageIndex++; m_intLineIndex = 0; @@ -468,25 +472,25 @@ private: m_intSampleIndex++; } - if (m_intColIndex < m_objRunningPrivate.m_intNumberSamplePerLine + m_intNumberSamplePerTop - 1) + if (m_intColIndex < m_runningPrivate.m_intNumberSamplePerLine + m_intNumberSamplePerTop - 1) { m_intColIndex++; } else { - if (m_objRunning.m_blnHSync && (m_intLineIndex == 0)) + if (m_running.m_blnHSync && (m_intLineIndex == 0)) { //qDebug("HCorr: %d", m_intAvgColIndex); - m_intColIndex = m_intNumberSamplePerTop + (m_objRunningPrivate.m_intNumberSamplePerLine - m_intAvgColIndex)/2; // amortizing factor 1/2 + m_intColIndex = m_intNumberSamplePerTop + (m_runningPrivate.m_intNumberSamplePerLine - m_intAvgColIndex)/2; // amortizing factor 1/2 } else { m_intColIndex = m_intNumberSamplePerTop; } - if ((m_objRFRunning.m_enmModulation == ATV_AM) - || (m_objRFRunning.m_enmModulation == ATV_USB) - || (m_objRFRunning.m_enmModulation == ATV_LSB)) + if ((m_rfRunning.m_enmModulation == ATV_AM) + || (m_rfRunning.m_enmModulation == ATV_USB) + || (m_rfRunning.m_enmModulation == ATV_LSB)) { m_fltAmpMin = m_fltEffMin; m_fltAmpMax = m_fltEffMax; @@ -502,7 +506,7 @@ private: m_fltEffMax = -2000000.0f; } - m_objRegisteredATVScreen->selectRow(m_intRowIndex); + m_registeredATVScreen->selectRow(m_intRowIndex); m_intLineIndex++; m_intRowIndex++; } @@ -510,18 +514,18 @@ private: inline void processClassic(float& fltVal, int& intVal) { - int intSynchroTimeSamples= (3 * m_objRunningPrivate.m_intNumberSamplePerLine)/4; - float fltSynchroTrameLevel = 0.5f*((float)intSynchroTimeSamples) * m_objRunning.m_fltVoltLevelSynchroBlack; + int intSynchroTimeSamples= (3 * m_runningPrivate.m_intNumberSamplePerLine)/4; + float fltSynchroTrameLevel = 0.5f*((float)intSynchroTimeSamples) * m_running.m_fltVoltLevelSynchroBlack; // Horizontal Synchro detection // Floor Detection 0 - if (fltVal < m_objRunning.m_fltVoltLevelSynchroTop) + if (fltVal < m_running.m_fltVoltLevelSynchroTop) { m_intSynchroPoints++; } // Black detection 0.3 - else if (fltVal > m_objRunning.m_fltVoltLevelSynchroBlack) + else if (fltVal > m_running.m_fltVoltLevelSynchroBlack) { m_intSynchroPoints = 0; } @@ -534,7 +538,7 @@ private: if (m_blnSynchroDetected) { - m_intAvgColIndex = m_intSampleIndex - m_intColIndex - (m_intColIndex < m_objRunningPrivate.m_intNumberSamplePerLine/2 ? 150 : 0); + m_intAvgColIndex = m_intSampleIndex - m_intColIndex - (m_intColIndex < m_runningPrivate.m_intNumberSamplePerLine/2 ? 150 : 0); //qDebug("HSync: %d %d %d", m_intSampleIndex, m_intColIndex, m_intAvgColIndex); m_intSampleIndex = 0; } @@ -543,14 +547,14 @@ private: m_intSampleIndex++; } - if (!m_objRunning.m_blnHSync && (m_intColIndex >= m_objRunningPrivate.m_intNumberSamplePerLine)) // H Sync not active + if (!m_running.m_blnHSync && (m_intColIndex >= m_runningPrivate.m_intNumberSamplePerLine)) // H Sync not active { m_intColIndex = 0; blnNewLine = true; } - else if (m_intColIndex >= m_objRunningPrivate.m_intNumberSamplePerLine + m_intNumberSamplePerTop) // No valid H sync + else if (m_intColIndex >= m_runningPrivate.m_intNumberSamplePerLine + m_intNumberSamplePerTop) // No valid H sync { - if (m_objRunning.m_blnHSync && (m_intLineIndex == 0)) + if (m_running.m_blnHSync && (m_intLineIndex == 0)) { //qDebug("HSync: %d %d", m_intColIndex, m_intAvgColIndex); m_intColIndex = m_intNumberSamplePerTop + m_intAvgColIndex/4; // amortizing 1/4 @@ -565,9 +569,9 @@ private: if (blnNewLine) { - if ((m_objRFRunning.m_enmModulation == ATV_AM) - || (m_objRFRunning.m_enmModulation == ATV_USB) - || (m_objRFRunning.m_enmModulation == ATV_LSB)) + if ((m_rfRunning.m_enmModulation == ATV_AM) + || (m_rfRunning.m_enmModulation == ATV_USB) + || (m_rfRunning.m_enmModulation == ATV_LSB)) { m_fltAmpMin = m_fltEffMin; m_fltAmpMax = m_fltEffMax; @@ -590,7 +594,7 @@ private: if (m_intRowIndex < m_intNumberOfLines) { - m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines); + m_registeredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines); } m_intLineIndex++; @@ -599,12 +603,12 @@ private: // Filling pixels // +4 is to compensate shift due to hsync amortizing factor of 1/4 - m_objRegisteredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop + 4, intVal, intVal, intVal); + m_registeredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop + 4, intVal, intVal, intVal); m_intColIndex++; // Vertical sync and image rendering - if ((m_objRunning.m_blnVSync) && (m_intLineIndex < m_intNumberOfLines)) // VSync activated and lines in range + if ((m_running.m_blnVSync) && (m_intLineIndex < m_intNumberOfLines)) // VSync activated and lines in range { if (m_intColIndex >= intSynchroTimeSamples) { @@ -618,7 +622,7 @@ private: if ((m_intLineIndex % 2 == 0) || !m_interleaved) // even => odd image { - m_objRegisteredATVScreen->renderImage(0); + m_registeredATVScreen->renderImage(0); m_intRowIndex = 1; } else @@ -626,7 +630,7 @@ private: m_intRowIndex = 0; } - m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines); + m_registeredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines); m_intLineIndex = 0; m_intImageIndex++; } @@ -643,9 +647,9 @@ private: { if (m_intImageIndex % 2 == 1) // odd image { - m_objRegisteredATVScreen->renderImage(0); + m_registeredATVScreen->renderImage(0); - if (m_objRFRunning.m_enmModulation == ATV_AM) + if (m_rfRunning.m_enmModulation == ATV_AM) { m_fltAmpMin = m_fltEffMin; m_fltAmpMax = m_fltEffMax; @@ -668,7 +672,7 @@ private: m_intRowIndex = 0; } - m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines); + m_registeredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines); m_intLineIndex = 0; m_intImageIndex++; } diff --git a/plugins/channelrx/demodatv/atvdemodgui.cpp b/plugins/channelrx/demodatv/atvdemodgui.cpp index 15c4976d1..7683dbc22 100644 --- a/plugins/channelrx/demodatv/atvdemodgui.cpp +++ b/plugins/channelrx/demodatv/atvdemodgui.cpp @@ -61,12 +61,12 @@ QString ATVDemodGUI::getName() const qint64 ATVDemodGUI::getCenterFrequency() const { - return m_objChannelMarker.getCenterFrequency(); + return m_channelMarker.getCenterFrequency(); } void ATVDemodGUI::setCenterFrequency(qint64 intCenterFrequency) { - m_objChannelMarker.setCenterFrequency(intCenterFrequency); + m_channelMarker.setCenterFrequency(intCenterFrequency); applySettings(); } @@ -105,8 +105,8 @@ QByteArray ATVDemodGUI::serialize() const { SimpleSerializer s(1); - s.writeS32(1, m_objChannelMarker.getCenterFrequency()); - s.writeU32(2, m_objChannelMarker.getColor().rgb()); + s.writeS32(1, m_channelMarker.getCenterFrequency()); + s.writeU32(2, m_channelMarker.getColor().rgb()); s.writeS32(3, ui->synchLevel->value()); s.writeS32(4, ui->blackLevel->value()); s.writeS32(5, ui->lineTime->value()); @@ -144,10 +144,10 @@ bool ATVDemodGUI::deserialize(const QByteArray& arrData) bool booltmp; blockApplySettings(true); - m_objChannelMarker.blockSignals(true); + m_channelMarker.blockSignals(true); d.readS32(1, &tmp, 0); - m_objChannelMarker.setCenterFrequency(tmp); + m_channelMarker.setCenterFrequency(tmp); // if (d.readU32(2, &u32tmp)) { // m_objChannelMarker.setColor(u32tmp); @@ -189,7 +189,7 @@ bool ATVDemodGUI::deserialize(const QByteArray& arrData) ui->standard->setCurrentIndex(tmp); blockApplySettings(false); - m_objChannelMarker.blockSignals(false); + m_channelMarker.blockSignals(false); lineTimeUpdate(); topTimeUpdate(); @@ -211,7 +211,7 @@ bool ATVDemodGUI::handleMessage(const Message& objMessage) int nbPointsPerLine = ((ATVDemod::MsgReportEffectiveSampleRate&)objMessage).getNbPointsPerLine(); ui->channelSampleRateText->setText(tr("%1k").arg(sampleRate/1000.0f, 0, 'f', 2)); ui->nbPointsPerLineText->setText(tr("%1p").arg(nbPointsPerLine)); - m_objScopeVis->setSampleRate(sampleRate); + m_scopeVis->setSampleRate(sampleRate); setRFFiltersSlidersRange(sampleRate); lineTimeUpdate(); topTimeUpdate(); @@ -242,7 +242,7 @@ void ATVDemodGUI::handleSourceMessages() { Message* message; - while ((message = m_objATVDemod->getOutputMessageQueue()->pop()) != 0) + while ((message = getInputMessageQueue()->pop()) != 0) { if (handleMessage(*message)) { @@ -261,7 +261,7 @@ void ATVDemodGUI::onMenuDoubleClicked() { m_blnBasicSettingsShown = true; BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget( - &m_objChannelMarker, this); + &m_channelMarker, this); bcsw->show(); } } @@ -270,9 +270,9 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI, QWidget* objParent) : RollupWidget(objParent), ui(new Ui::ATVDemodGUI), - m_objPluginAPI(objPluginAPI), - m_objDeviceAPI(objDeviceAPI), - m_objChannelMarker(this), + m_pluginAPI(objPluginAPI), + m_deviceAPI(objDeviceAPI), + m_channelMarker(this), m_blnBasicSettingsShown(false), m_blnDoApplySettings(true), m_objMagSqAverage(40, 0), @@ -283,42 +283,44 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI, connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked())); - m_objScopeVis = new ScopeVisNG(ui->glScope); - m_objATVDemod = new ATVDemod(m_objScopeVis); - m_objATVDemod->setATVScreen(ui->screenTV); + m_scopeVis = new ScopeVisNG(ui->glScope); + m_atvDemod = new ATVDemod(m_deviceAPI); + m_atvDemod->setScopeSink(m_scopeVis); + m_atvDemod->setMessageQueueToGUI(getInputMessageQueue()); + m_atvDemod->setATVScreen(ui->screenTV); - m_objChannelizer = new DownChannelizer(m_objATVDemod); - m_objThreadedChannelizer = new ThreadedBasebandSampleSink(m_objChannelizer, this); - m_objDeviceAPI->addThreadedSink(m_objThreadedChannelizer); + m_channelizer = new DownChannelizer(m_atvDemod); + m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); + m_deviceAPI->addThreadedSink(m_threadedChannelizer); - ui->glScope->connectTimer(m_objPluginAPI->getMainWindow()->getMasterTimer()); - connect(&m_objPluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms + ui->glScope->connectTimer(m_pluginAPI->getMainWindow()->getMasterTimer()); + connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03))); ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999); - connect(m_objChannelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged())); + connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged())); //m_objPluginAPI->addThreadedSink(m_objThreadedChannelizer); - m_objChannelMarker.setColor(Qt::white); - m_objChannelMarker.setMovable(false); - m_objChannelMarker.setBandwidth(6000000); - m_objChannelMarker.setCenterFrequency(0); - m_objChannelMarker.setVisible(true); - setTitleColor(m_objChannelMarker.getColor()); + m_channelMarker.setColor(Qt::white); + m_channelMarker.setMovable(false); + m_channelMarker.setBandwidth(6000000); + m_channelMarker.setCenterFrequency(0); + m_channelMarker.setVisible(true); + setTitleColor(m_channelMarker.getColor()); - connect(&m_objChannelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); + connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); - m_objDeviceAPI->registerChannelInstance(m_strChannelID, this); - m_objDeviceAPI->addChannelMarker(&m_objChannelMarker); - m_objDeviceAPI->addRollupWidget(this); + m_deviceAPI->registerChannelInstance(m_strChannelID, this); + m_deviceAPI->addChannelMarker(&m_channelMarker); + m_deviceAPI->addRollupWidget(this); //ui->screenTV->connectTimer(m_objPluginAPI->getMainWindow()->getMasterTimer()); m_objMagSqAverage.resize(4, 1.0); - ui->scopeGUI->setBuddies(m_objScopeVis->getInputMessageQueue(), m_objScopeVis, ui->glScope); + ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope); resetToDefaults(); // does applySettings() @@ -337,7 +339,7 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI, ui->scopeGUI->changeTrigger(0, triggerData); ui->scopeGUI->focusOnTrigger(0); // re-focus to take changes into account in the GUI - connect(m_objATVDemod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); QChar delta = QChar(0x94, 0x03); ui->fmDeviationLabel->setText(delta); @@ -345,12 +347,12 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI, ATVDemodGUI::~ATVDemodGUI() { - m_objDeviceAPI->removeChannelInstance(this); - m_objDeviceAPI->removeThreadedSink(m_objThreadedChannelizer); - delete m_objThreadedChannelizer; - delete m_objChannelizer; - delete m_objATVDemod; - delete m_objScopeVis; + m_deviceAPI->removeChannelInstance(this); + m_deviceAPI->removeThreadedSink(m_threadedChannelizer); + delete m_threadedChannelizer; + delete m_channelizer; + delete m_atvDemod; + delete m_scopeVis; delete ui; } @@ -363,13 +365,13 @@ void ATVDemodGUI::applySettings() { if (m_blnDoApplySettings) { - ui->deltaFrequency->setValue(m_objChannelMarker.getCenterFrequency()); + ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); - m_objChannelizer->configure(m_objChannelizer->getInputMessageQueue(), - m_objChannelizer->getInputSampleRate(), // always use maximum available bandwidth - m_objChannelMarker.getCenterFrequency()); + m_channelizer->configure(m_channelizer->getInputMessageQueue(), + m_channelizer->getInputSampleRate(), // always use maximum available bandwidth + m_channelMarker.getCenterFrequency()); - m_objATVDemod->configure(m_objATVDemod->getInputMessageQueue(), + m_atvDemod->configure(m_atvDemod->getInputMessageQueue(), getNominalLineTime(ui->nbLines->currentIndex(), ui->fps->currentIndex()) + ui->lineTime->value() * m_fltLineTimeMultiplier, getNominalLineTime(ui->nbLines->currentIndex(), ui->fps->currentIndex()) * (4.7f / 64.0f) + ui->topTime->value() * m_fltTopTimeMultiplier, getFps(ui->fps->currentIndex()), @@ -384,8 +386,8 @@ void ATVDemodGUI::applySettings() ui->screenTabWidget->currentIndex()); qDebug() << "ATVDemodGUI::applySettings:" - << " m_objChannelizer.inputSampleRate: " << m_objChannelizer->getInputSampleRate() - << " m_objATVDemod.sampleRate: " << m_objATVDemod->getSampleRate(); + << " m_objChannelizer.inputSampleRate: " << m_channelizer->getInputSampleRate() + << " m_objATVDemod.sampleRate: " << m_atvDemod->getSampleRate(); } } @@ -393,7 +395,7 @@ void ATVDemodGUI::applyRFSettings() { if (m_blnDoApplySettings) { - m_objATVDemod->configureRF(m_objATVDemod->getInputMessageQueue(), + m_atvDemod->configureRF(m_atvDemod->getInputMessageQueue(), (ATVDemod::ATVModulation) ui->modulation->currentIndex(), ui->rfBW->value() * m_rfSliderDivisor * 1.0f, ui->rfOppBW->value() * m_rfSliderDivisor * 1.0f, @@ -410,26 +412,26 @@ void ATVDemodGUI::setChannelMarkerBandwidth() if (ui->rfFiltering->isChecked()) // FFT filter { - m_objChannelMarker.setBandwidth(ui->rfBW->value()*m_rfSliderDivisor); - m_objChannelMarker.setOppositeBandwidth(ui->rfOppBW->value()*m_rfSliderDivisor); + m_channelMarker.setBandwidth(ui->rfBW->value()*m_rfSliderDivisor); + m_channelMarker.setOppositeBandwidth(ui->rfOppBW->value()*m_rfSliderDivisor); if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_LSB) { - m_objChannelMarker.setSidebands(ChannelMarker::vlsb); + m_channelMarker.setSidebands(ChannelMarker::vlsb); } else if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_USB) { - m_objChannelMarker.setSidebands(ChannelMarker::vusb); + m_channelMarker.setSidebands(ChannelMarker::vusb); } else { - m_objChannelMarker.setSidebands(ChannelMarker::vusb); + m_channelMarker.setSidebands(ChannelMarker::vusb); } } else { if (ui->decimatorEnable->isChecked()) { - m_objChannelMarker.setBandwidth(ui->rfBW->value()*m_rfSliderDivisor); + m_channelMarker.setBandwidth(ui->rfBW->value()*m_rfSliderDivisor); } else { - m_objChannelMarker.setBandwidth(m_objChannelizer->getInputSampleRate()); + m_channelMarker.setBandwidth(m_channelizer->getInputSampleRate()); } - m_objChannelMarker.setSidebands(ChannelMarker::dsb); + m_channelMarker.setSidebands(ChannelMarker::dsb); } m_blnDoApplySettings = true; @@ -463,14 +465,14 @@ void ATVDemodGUI::setRFFiltersSlidersRange(int sampleRate) void ATVDemodGUI::leaveEvent(QEvent*) { blockApplySettings(true); - m_objChannelMarker.setHighlighted(false); + m_channelMarker.setHighlighted(false); blockApplySettings(false); } void ATVDemodGUI::enterEvent(QEvent*) { blockApplySettings(true); - m_objChannelMarker.setHighlighted(true); + m_channelMarker.setHighlighted(true); blockApplySettings(false); } @@ -482,13 +484,13 @@ void ATVDemodGUI::tick() } else { - if (m_objATVDemod) + if (m_atvDemod) { - m_objMagSqAverage.feed(m_objATVDemod->getMagSq()); + m_objMagSqAverage.feed(m_atvDemod->getMagSq()); double magSqDB = CalcDb::dbPower(m_objMagSqAverage.average() / (1<<30)); ui->channePowerText->setText(tr("%1 dB").arg(magSqDB, 0, 'f', 1)); - if (m_objATVDemod->getBFOLocked()) { + if (m_atvDemod->getBFOLocked()) { ui->bfoLockedLabel->setStyleSheet("QLabel { background-color : green; }"); } else { ui->bfoLockedLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }"); @@ -573,7 +575,7 @@ void ATVDemodGUI::on_reset_clicked(bool checked __attribute__((unused))) void ATVDemodGUI::on_modulation_currentIndexChanged(int index __attribute__((unused))) { - setRFFiltersSlidersRange(m_objATVDemod->getEffectiveSampleRate()); + setRFFiltersSlidersRange(m_atvDemod->getEffectiveSampleRate()); setChannelMarkerBandwidth(); applyRFSettings(); } @@ -594,7 +596,7 @@ void ATVDemodGUI::on_rfOppBW_valueChanged(int value) void ATVDemodGUI::on_rfFiltering_toggled(bool checked __attribute__((unused))) { - setRFFiltersSlidersRange(m_objATVDemod->getEffectiveSampleRate()); + setRFFiltersSlidersRange(m_atvDemod->getEffectiveSampleRate()); setChannelMarkerBandwidth(); applyRFSettings(); } @@ -607,7 +609,7 @@ void ATVDemodGUI::on_decimatorEnable_toggled(bool checked __attribute__((unused) void ATVDemodGUI::on_deltaFrequency_changed(qint64 value) { - m_objChannelMarker.setCenterFrequency(value); + m_channelMarker.setCenterFrequency(value); } void ATVDemodGUI::on_bfo_valueChanged(int value) @@ -632,10 +634,10 @@ void ATVDemodGUI::lineTimeUpdate() float nominalLineTime = getNominalLineTime(ui->nbLines->currentIndex(), ui->fps->currentIndex()); int lineTimeScaleFactor = (int) std::log10(nominalLineTime); - if (m_objATVDemod->getEffectiveSampleRate() == 0) { + if (m_atvDemod->getEffectiveSampleRate() == 0) { m_fltLineTimeMultiplier = std::pow(10.0, lineTimeScaleFactor-3); } else { - m_fltLineTimeMultiplier = 1.0f / m_objATVDemod->getEffectiveSampleRate(); + m_fltLineTimeMultiplier = 1.0f / m_atvDemod->getEffectiveSampleRate(); } float lineTime = nominalLineTime + m_fltLineTimeMultiplier * ui->lineTime->value(); @@ -657,10 +659,10 @@ void ATVDemodGUI::topTimeUpdate() float nominalTopTime = getNominalLineTime(ui->nbLines->currentIndex(), ui->fps->currentIndex()) * (4.7f / 64.0f); int topTimeScaleFactor = (int) std::log10(nominalTopTime); - if (m_objATVDemod->getEffectiveSampleRate() == 0) { + if (m_atvDemod->getEffectiveSampleRate() == 0) { m_fltTopTimeMultiplier = std::pow(10.0, topTimeScaleFactor-3); } else { - m_fltTopTimeMultiplier = 1.0f / m_objATVDemod->getEffectiveSampleRate(); + m_fltTopTimeMultiplier = 1.0f / m_atvDemod->getEffectiveSampleRate(); } float topTime = nominalTopTime + m_fltTopTimeMultiplier * ui->topTime->value(); diff --git a/plugins/channelrx/demodatv/atvdemodgui.h b/plugins/channelrx/demodatv/atvdemodgui.h index 720a5f19f..917076294 100644 --- a/plugins/channelrx/demodatv/atvdemodgui.h +++ b/plugins/channelrx/demodatv/atvdemodgui.h @@ -18,10 +18,10 @@ #ifndef INCLUDE_ATVDEMODGUI_H #define INCLUDE_ATVDEMODGUI_H +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" class PluginAPI; @@ -37,7 +37,7 @@ namespace Ui class ATVDemodGUI; } -class ATVDemodGUI : public RollupWidget, public PluginInstanceUI +class ATVDemodGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT @@ -89,12 +89,12 @@ private slots: private: Ui::ATVDemodGUI* ui; - PluginAPI* m_objPluginAPI; - DeviceSourceAPI* m_objDeviceAPI; - ChannelMarker m_objChannelMarker; - ThreadedBasebandSampleSink* m_objThreadedChannelizer; - DownChannelizer* m_objChannelizer; - ATVDemod* m_objATVDemod; + PluginAPI* m_pluginAPI; + DeviceSourceAPI* m_deviceAPI; + ChannelMarker m_channelMarker; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; + ATVDemod* m_atvDemod; bool m_blnBasicSettingsShown; bool m_blnDoApplySettings; @@ -102,7 +102,7 @@ private: MovingAverage m_objMagSqAverage; int m_intTickCount; - ScopeVisNG* m_objScopeVis; + ScopeVisNG* m_scopeVis; float m_fltLineTimeMultiplier; float m_fltTopTimeMultiplier; diff --git a/plugins/channelrx/demodatv/atvdemodplugin.cpp b/plugins/channelrx/demodatv/atvdemodplugin.cpp index 8aecf1499..745f13921 100644 --- a/plugins/channelrx/demodatv/atvdemodplugin.cpp +++ b/plugins/channelrx/demodatv/atvdemodplugin.cpp @@ -26,7 +26,7 @@ const PluginDescriptor ATVDemodPlugin::m_ptrPluginDescriptor = { QString("ATV Demodulator"), - QString("3.5.0"), + QString("3.7.3"), QString("(c) F4HKW for F4EXB / SDRAngel"), QString("https://github.com/f4exb/sdrangel"), true, @@ -53,7 +53,7 @@ void ATVDemodPlugin::initPlugin(PluginAPI* ptrPluginAPI) m_ptrPluginAPI->registerRxChannel(ATVDemodGUI::m_strChannelID, this); } -PluginInstanceUI* ATVDemodPlugin::createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI) +PluginInstanceGUI* ATVDemodPlugin::createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI) { if(strChannelName == ATVDemodGUI::m_strChannelID) { diff --git a/plugins/channelrx/demodatv/atvdemodplugin.h b/plugins/channelrx/demodatv/atvdemodplugin.h index e26d77610..93f0e11d5 100644 --- a/plugins/channelrx/demodatv/atvdemodplugin.h +++ b/plugins/channelrx/demodatv/atvdemodplugin.h @@ -35,7 +35,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* ptrPluginAPI); - PluginInstanceUI* createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI); + PluginInstanceGUI* createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI); private: static const PluginDescriptor m_ptrPluginDescriptor; diff --git a/plugins/channelrx/demodbfm/CMakeLists.txt b/plugins/channelrx/demodbfm/CMakeLists.txt index 82de4604d..17f901d0f 100644 --- a/plugins/channelrx/demodbfm/CMakeLists.txt +++ b/plugins/channelrx/demodbfm/CMakeLists.txt @@ -3,6 +3,7 @@ project(bfm) set(bfm_SOURCES bfmdemod.cpp bfmdemodgui.cpp + bfmdemodsettings.cpp bfmplugin.cpp rdsdemod.cpp rdsdecoder.cpp @@ -13,6 +14,7 @@ set(bfm_SOURCES set(bfm_HEADERS bfmdemod.h bfmdemodgui.h + bfmdemodsettings.h bfmplugin.h rdsdemod.h rdsdecoder.h diff --git a/plugins/channelrx/demodbfm/bfmdemod.cpp b/plugins/channelrx/demodbfm/bfmdemod.cpp index f6dd35444..0e9115879 100644 --- a/plugins/channelrx/demodbfm/bfmdemod.cpp +++ b/plugins/channelrx/demodbfm/bfmdemod.cpp @@ -15,63 +15,77 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "../../channelrx/demodbfm/bfmdemod.h" - #include #include #include #include + #include "audio/audiooutput.h" #include "dsp/dspengine.h" #include "dsp/pidcontroller.h" -#include "bfmdemod.h" - #include +#include "dsp/threadedbasebandsamplesink.h" +#include "device/devicesourceapi.h" #include "rdsparser.h" +#include "bfmdemod.h" +MESSAGE_CLASS_DEFINITION(BFMDemod::MsgConfigureChannelizer, Message) +MESSAGE_CLASS_DEFINITION(BFMDemod::MsgReportChannelSampleRateChanged, Message) MESSAGE_CLASS_DEFINITION(BFMDemod::MsgConfigureBFMDemod, Message) const Real BFMDemod::default_deemphasis = 50.0; // 50 us const int BFMDemod::m_udpBlockSize = 512; -BFMDemod::BFMDemod(BasebandSampleSink* sampleSink, RDSParser *rdsParser) : - m_sampleSink(sampleSink), +BFMDemod::BFMDemod(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), m_audioFifo(250000), m_settingsMutex(QMutex::Recursive), m_pilotPLL(19000/384000, 50/384000, 0.01), - m_rdsParser(rdsParser), m_deemphasisFilterX(default_deemphasis * 48000 * 1.0e-6), m_deemphasisFilterY(default_deemphasis * 48000 * 1.0e-6), m_fmExcursion(default_excursion) { setObjectName("BFMDemod"); - m_config.m_inputSampleRate = 384000; - m_config.m_inputFrequencyOffset = 0; - m_config.m_rfBandwidth = 180000; - m_config.m_afBandwidth = 15000; - m_config.m_squelch = -60.0; - m_config.m_volume = 2.0; - m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); // normally 48 kHz - m_deemphasisFilterX.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6); - m_deemphasisFilterY.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6); - m_rfFilter = new fftfilt(-50000.0 / 384000.0, 50000.0 / 384000.0, filtFftLen); - m_phaseDiscri.setFMScaling(384000/m_fmExcursion); - - apply(); - - m_audioBuffer.resize(16384); - m_audioBufferFill = 0; - -// m_movingAverage.resize(16, 0); - m_magsq = 0.0f; + m_magsq = 0.0f; m_magsqSum = 0.0f; m_magsqPeak = 0.0f; m_magsqCount = 0; + m_squelchLevel = 0; + m_squelchState = 0; + + m_interpolatorDistance = 0.0f; + m_interpolatorDistanceRemain = 0.0f; + + m_interpolatorRDSDistance = 0.0f; + m_interpolatorRDSDistanceRemain = 0.0f; + + m_interpolatorStereoDistance = 0.0f; + m_interpolatorStereoDistanceRemain = 0.0f; + + m_sampleSink = 0; + m_m1Arg = 0; + + m_rfFilter = new fftfilt(-50000.0 / 384000.0, 50000.0 / 384000.0, filtFftLen); + + 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); + + m_deemphasisFilterX.configure(default_deemphasis * m_settings.m_audioSampleRate * 1.0e-6); + m_deemphasisFilterY.configure(default_deemphasis * m_settings.m_audioSampleRate * 1.0e-6); + m_phaseDiscri.setFMScaling(384000/m_fmExcursion); + + m_audioBuffer.resize(16384); + m_audioBufferFill = 0; + DSPEngine::instance()->addAudioSink(&m_audioFifo); - m_udpBufferAudio = new UDPSink(this, m_udpBlockSize, m_config.m_udpPort); + m_udpBufferAudio = new UDPSink(this, m_udpBlockSize, m_settings.m_udpPort); + + applySettings(m_settings, true); } BFMDemod::~BFMDemod() @@ -83,35 +97,10 @@ BFMDemod::~BFMDemod() DSPEngine::instance()->removeAudioSink(&m_audioFifo); delete m_udpBufferAudio; -} -void BFMDemod::configure(MessageQueue* messageQueue, - Real rfBandwidth, - Real afBandwidth, - Real volume, - Real squelch, - bool audioStereo, - bool lsbStereo, - bool showPilot, - bool rdsActive, - bool copyAudioToUDP, - const QString& udpAddress, - quint16 udpPort, - bool force) -{ - Message* cmd = MsgConfigureBFMDemod::create(rfBandwidth, - afBandwidth, - volume, - squelch, - audioStereo, - lsbStereo, - showPilot, - rdsActive, - copyAudioToUDP, - udpAddress, - udpPort, - force); - messageQueue->push(cmd); + m_deviceAPI->removeThreadedSink(m_threadedChannelizer); + delete m_threadedChannelizer; + delete m_channelizer; } void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) @@ -149,7 +138,7 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto // m_movingAverage.feed(msq); if(m_magsq >= m_squelchLevel) { - m_squelchState = m_running.m_rfBandwidth / 20; // decay rate + m_squelchState = m_settings.m_rfBandwidth / 20; // decay rate } if(m_squelchState > 0) @@ -164,12 +153,12 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto demod = 0; } - if (!m_running.m_showPilot) + if (!m_settings.m_showPilot) { m_sampleBuffer.push_back(Sample(demod * (1<<15), 0.0)); } - if (m_running.m_rdsActive) + if (m_settings.m_rdsActive) { //Complex r(demod * 2.0 * std::cos(3.0 * m_pilotPLLSamples[3]), 0.0); Complex r(demod * 2.0 * std::cos(3.0 * m_pilotPLLSamples[3]), 0.0); @@ -182,10 +171,7 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto { if (m_rdsDecoder.frameSync(bit)) { - if (m_rdsParser) - { - m_rdsParser->parseGroup(m_rdsDecoder.getGroup()); - } + m_rdsParser.parseGroup(m_rdsDecoder.getGroup()); } } @@ -197,16 +183,16 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto // Process stereo if stereo mode is selected - if (m_running.m_audioStereo) + if (m_settings.m_audioStereo) { m_pilotPLL.process(demod, m_pilotPLLSamples); - if (m_running.m_showPilot) + if (m_settings.m_showPilot) { m_sampleBuffer.push_back(Sample(m_pilotPLLSamples[1] * (1<<15), 0.0)); // debug 38 kHz pilot } - if (m_running.m_lsbStereo) + if (m_settings.m_lsbStereo) { // 1.17 * 0.7 = 0.819 Complex s(demod * m_pilotPLLSamples[1], demod * m_pilotPLLSamples[2]); @@ -233,32 +219,32 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto if (m_interpolator.decimate(&m_interpolatorDistanceRemain, e, &ci)) { - if (m_running.m_audioStereo) + if (m_settings.m_audioStereo) { Real deemph_l, deemph_r; // Pre-emphasis is applied on each channel before multiplexing m_deemphasisFilterX.process(ci.real() + sampleStereo, deemph_l); m_deemphasisFilterY.process(ci.real() - sampleStereo, deemph_r); - if (m_running.m_lsbStereo) + if (m_settings.m_lsbStereo) { - m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_running.m_volume); - m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_running.m_volume); - if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]); + m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_settings.m_volume); + m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_settings.m_volume); + if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]); } else { - m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_running.m_volume); - m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_running.m_volume); - if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]); + m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_settings.m_volume); + m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_settings.m_volume); + if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]); } } else { Real deemph; m_deemphasisFilterX.process(ci.real(), deemph); - quint16 sample = (qint16)(deemph * (1<<12) * m_running.m_volume); + quint16 sample = (qint16)(deemph * (1<<12) * m_settings.m_volume); m_audioBuffer[m_audioBufferFill].l = sample; m_audioBuffer[m_audioBufferFill].r = sample; - if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]); + if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]); } ++m_audioBufferFill; @@ -313,54 +299,58 @@ void BFMDemod::stop() { } +void BFMDemod::channelSampleRateChanged() +{ + MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create(getSampleRate()); + getMessageQueueToGUI()->push(msg); +} + bool BFMDemod::handleMessage(const Message& cmd) { if (DownChannelizer::MsgChannelizerNotification::match(cmd)) { DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; - m_config.m_inputSampleRate = notif.getSampleRate(); - m_config.m_inputFrequencyOffset = notif.getFrequencyOffset(); + BFMDemodSettings settings = m_settings; - apply(); + settings.m_inputSampleRate = notif.getSampleRate(); + settings.m_inputFrequencyOffset = notif.getFrequencyOffset(); - qDebug() << "BFMDemod::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << m_config.m_inputSampleRate - << " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; + applySettings(settings); + + qDebug() << "BFMDemod::handleMessage: MsgChannelizerNotification:" + << " m_inputSampleRate: " << settings.m_inputSampleRate + << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset; return true; } - else if (MsgConfigureBFMDemod::match(cmd)) - { - MsgConfigureBFMDemod& cfg = (MsgConfigureBFMDemod&) cmd; + else if (MsgConfigureBFMDemod::match(cmd)) + { + MsgConfigureBFMDemod& cfg = (MsgConfigureBFMDemod&) cmd; - m_config.m_rfBandwidth = cfg.getRFBandwidth(); - m_config.m_afBandwidth = cfg.getAFBandwidth(); - m_config.m_volume = cfg.getVolume(); - m_config.m_squelch = cfg.getSquelch(); - m_config.m_audioStereo = cfg.getAudioStereo(); - m_config.m_lsbStereo = cfg.getLsbStereo(); - m_config.m_showPilot = cfg.getShowPilot(); - m_config.m_rdsActive = cfg.getRDSActive(); - m_config.m_copyAudioToUDP= cfg.getCopyAudioToUDP(); - m_config.m_udpAddress = cfg.getUDPAddress(); - m_config.m_udpPort = cfg.getUDPPort(); + BFMDemodSettings settings = cfg.getSettings(); - apply(cfg.getForce()); + // These settings are set with DownChannelizer::MsgChannelizerNotification + settings.m_inputSampleRate = m_settings.m_inputSampleRate; + settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset; - qDebug() << "BFMDemod::handleMessage: MsgConfigureBFMDemod: m_rfBandwidth: " << m_config.m_rfBandwidth - << " m_afBandwidth: " << m_config.m_afBandwidth - << " m_volume: " << m_config.m_volume - << " m_squelch: " << m_config.m_squelch - << " m_audioStereo: " << m_config.m_audioStereo - << " m_lsbStereo: " << m_config.m_lsbStereo - << " m_showPilot: " << m_config.m_showPilot - << " m_rdsActive: " << m_config.m_rdsActive - << " m_copyAudioToUDP: " << m_config.m_copyAudioToUDP - << " m_udpAddress: " << m_config.m_udpAddress - << " m_udpPort: " << m_config.m_udpPort; + applySettings(settings, cfg.getForce()); - return true; - } + qDebug() << "BFMDemod::handleMessage: MsgConfigureBFMDemod:" + << " m_rfBandwidth: " << settings.m_rfBandwidth + << " m_volume: " << settings.m_volume + << " m_squelch: " << settings.m_squelch + << " m_audioStereo: " << settings.m_audioStereo + << " m_lsbStereo: " << settings.m_lsbStereo + << " m_showPilot: " << settings.m_showPilot + << " m_rdsActive: " << settings.m_rdsActive + << " m_copyAudioToUDP: " << settings.m_copyAudioToUDP + << " m_udpAddress: " << settings.m_udpAddress + << " m_udpPort: " << settings.m_udpPort + << " force: " << cfg.getForce(); + + return true; + } else { qDebug() << "BFMDemod::handleMessage: none"; @@ -376,87 +366,87 @@ bool BFMDemod::handleMessage(const Message& cmd) } } -void BFMDemod::apply(bool force) +void BFMDemod::applySettings(const BFMDemodSettings& settings, bool force) { - if ((m_config.m_inputSampleRate != m_running.m_inputSampleRate) - || (m_config.m_audioStereo && (m_config.m_audioStereo != m_running.m_audioStereo)) || force) - { - m_pilotPLL.configure(19000.0/m_config.m_inputSampleRate, 50.0/m_config.m_inputSampleRate, 0.01); - } - - if((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || - (m_config.m_inputSampleRate != m_running.m_inputSampleRate) || force) - { - qDebug() << "BFMDemod::handleMessage: m_nco.setFreq"; - m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate); - } - - if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) || - (m_config.m_afBandwidth != m_running.m_afBandwidth) || force) - { - m_settingsMutex.lock(); - qDebug() << "BFMDemod::handleMessage: m_interpolator.create"; - - m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_afBandwidth); - m_interpolatorDistanceRemain = (Real) m_config.m_inputSampleRate / m_config.m_audioSampleRate; - m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate; - - m_interpolatorStereo.create(16, m_config.m_inputSampleRate, m_config.m_afBandwidth); - m_interpolatorStereoDistanceRemain = (Real) m_config.m_inputSampleRate / m_config.m_audioSampleRate; - m_interpolatorStereoDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate; - - m_interpolatorRDS.create(4, m_config.m_inputSampleRate, 600.0); - m_interpolatorRDSDistanceRemain = (Real) m_config.m_inputSampleRate / 250000.0; - m_interpolatorRDSDistance = (Real) m_config.m_inputSampleRate / 250000.0; - - m_settingsMutex.unlock(); - } - - if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) || - (m_config.m_rfBandwidth != m_running.m_rfBandwidth) || - (m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || force) - { - m_settingsMutex.lock(); - Real lowCut = -(m_config.m_rfBandwidth / 2.0) / m_config.m_inputSampleRate; - Real hiCut = (m_config.m_rfBandwidth / 2.0) / m_config.m_inputSampleRate; - m_rfFilter->create_filter(lowCut, hiCut); - m_phaseDiscri.setFMScaling(m_config.m_inputSampleRate / m_fmExcursion); - m_settingsMutex.unlock(); - - qDebug() << "BFMDemod::handleMessage: m_rfFilter->create_filter: sampleRate: " - << m_config.m_inputSampleRate - << " lowCut: " << lowCut * m_config.m_inputSampleRate - << " hiCut: " << hiCut * m_config.m_inputSampleRate; - } - - if ((m_config.m_afBandwidth != m_running.m_afBandwidth) || - (m_config.m_audioSampleRate != m_running.m_audioSampleRate) || force) - { - m_settingsMutex.lock(); - qDebug() << "BFMDemod::handleMessage: m_lowpass.create"; - m_lowpass.create(21, m_config.m_audioSampleRate, m_config.m_afBandwidth); - m_settingsMutex.unlock(); - } - - if ((m_config.m_squelch != m_running.m_squelch) || force) - { - qDebug() << "BFMDemod::handleMessage: set m_squelchLevel"; - m_squelchLevel = std::pow(10.0, m_config.m_squelch / 20.0); - m_squelchLevel *= m_squelchLevel; - } - - if ((m_config.m_audioSampleRate != m_running.m_audioSampleRate) || force) - { - m_deemphasisFilterX.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6); - m_deemphasisFilterY.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6); - } - - if ((m_config.m_udpAddress != m_running.m_udpAddress) - || (m_config.m_udpPort != m_running.m_udpPort) || force) + if ((settings.m_inputSampleRate != m_settings.m_inputSampleRate) + || (settings.m_audioStereo && (settings.m_audioStereo != m_settings.m_audioStereo)) || force) { - m_udpBufferAudio->setAddress(m_config.m_udpAddress); - m_udpBufferAudio->setPort(m_config.m_udpPort); + m_pilotPLL.configure(19000.0/settings.m_inputSampleRate, 50.0/settings.m_inputSampleRate, 0.01); } - m_running = m_config; + if((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || + (settings.m_inputSampleRate != m_settings.m_inputSampleRate) || force) + { + qDebug() << "BFMDemod::handleMessage: m_nco.setFreq"; + m_nco.setFreq(-settings.m_inputFrequencyOffset, settings.m_inputSampleRate); + } + + if((settings.m_inputSampleRate != m_settings.m_inputSampleRate) || + (settings.m_afBandwidth != m_settings.m_afBandwidth) || force) + { + m_settingsMutex.lock(); + qDebug() << "BFMDemod::handleMessage: m_interpolator.create"; + + m_interpolator.create(16, settings.m_inputSampleRate, settings.m_afBandwidth); + m_interpolatorDistanceRemain = (Real) settings.m_inputSampleRate / settings.m_audioSampleRate; + m_interpolatorDistance = (Real) settings.m_inputSampleRate / (Real) settings.m_audioSampleRate; + + m_interpolatorStereo.create(16, settings.m_inputSampleRate, settings.m_afBandwidth); + m_interpolatorStereoDistanceRemain = (Real) settings.m_inputSampleRate / settings.m_audioSampleRate; + m_interpolatorStereoDistance = (Real) settings.m_inputSampleRate / (Real) settings.m_audioSampleRate; + + m_interpolatorRDS.create(4, settings.m_inputSampleRate, 600.0); + m_interpolatorRDSDistanceRemain = (Real) settings.m_inputSampleRate / 250000.0; + m_interpolatorRDSDistance = (Real) settings.m_inputSampleRate / 250000.0; + + m_settingsMutex.unlock(); + } + + if((settings.m_inputSampleRate != m_settings.m_inputSampleRate) || + (settings.m_rfBandwidth != m_settings.m_rfBandwidth) || + (settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) + { + m_settingsMutex.lock(); + Real lowCut = -(settings.m_rfBandwidth / 2.0) / settings.m_inputSampleRate; + Real hiCut = (settings.m_rfBandwidth / 2.0) / settings.m_inputSampleRate; + m_rfFilter->create_filter(lowCut, hiCut); + m_phaseDiscri.setFMScaling(settings.m_inputSampleRate / m_fmExcursion); + m_settingsMutex.unlock(); + + qDebug() << "BFMDemod::handleMessage: m_rfFilter->create_filter: sampleRate: " + << settings.m_inputSampleRate + << " lowCut: " << lowCut * settings.m_inputSampleRate + << " hiCut: " << hiCut * settings.m_inputSampleRate; + } + + if ((settings.m_afBandwidth != m_settings.m_afBandwidth) || + (settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force) + { + m_settingsMutex.lock(); + qDebug() << "BFMDemod::handleMessage: m_lowpass.create"; + m_lowpass.create(21, settings.m_audioSampleRate, settings.m_afBandwidth); + m_settingsMutex.unlock(); + } + + if ((settings.m_squelch != m_settings.m_squelch) || force) + { + qDebug() << "BFMDemod::handleMessage: set m_squelchLevel"; + m_squelchLevel = std::pow(10.0, settings.m_squelch / 20.0); + m_squelchLevel *= m_squelchLevel; + } + + if ((settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force) + { + m_deemphasisFilterX.configure(default_deemphasis * settings.m_audioSampleRate * 1.0e-6); + m_deemphasisFilterY.configure(default_deemphasis * settings.m_audioSampleRate * 1.0e-6); + } + + if ((settings.m_udpAddress != m_settings.m_udpAddress) + || (settings.m_udpPort != m_settings.m_udpPort) || force) + { + m_udpBufferAudio->setAddress(const_cast(settings.m_udpAddress)); + m_udpBufferAudio->setPort(settings.m_udpPort); + } + + m_settings = settings; } diff --git a/plugins/channelrx/demodbfm/bfmdemod.h b/plugins/channelrx/demodbfm/bfmdemod.h index 5c6dc813c..3c403bb19 100644 --- a/plugins/channelrx/demodbfm/bfmdemod.h +++ b/plugins/channelrx/demodbfm/bfmdemod.h @@ -33,31 +33,88 @@ #include "util/message.h" #include "util/udpsink.h" +#include "rdsparser.h" #include "rdsdecoder.h" #include "rdsdemod.h" +#include "bfmdemodsettings.h" -class RDSParser; +class DeviceSourceAPI; +class ThreadedBasebandSampleSink; +class DownChannelizer; class BFMDemod : public BasebandSampleSink { public: - BFMDemod(BasebandSampleSink* sampleSink, RDSParser* rdsParser); + 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; } - void configure(MessageQueue* messageQueue, - Real rfBandwidth, - Real afBandwidth, - Real volume, - Real squelch, - bool audioStereo, - bool lsbStereo, - bool showPilot, - bool rdsActive, - bool copyAudioUDP, - const QString& m_udpAddress, - quint16 udpPort, - bool force = false); - - int getSampleRate() const { return m_config.m_inputSampleRate; } + 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(); @@ -85,134 +142,22 @@ public: m_magsqCount = 0; } + RDSParser& getRDSParser() { return m_rdsParser; } + +private slots: + void channelSampleRateChanged(); + private: - class MsgConfigureBFMDemod : public Message { - MESSAGE_CLASS_DECLARATION - - public: - Real getRFBandwidth() const { return m_rfBandwidth; } - Real getAFBandwidth() const { return m_afBandwidth; } - Real getVolume() const { return m_volume; } - Real getSquelch() const { return m_squelch; } - bool getAudioStereo() const { return m_audioStereo; } - bool getLsbStereo() const { return m_lsbStereo; } - bool getShowPilot() const { return m_showPilot; } - bool getRDSActive() const { return m_rdsActive; } - bool getCopyAudioToUDP() const { return m_copyAudioToUDP; } - const QString& getUDPAddress() const { return m_udpAddress; } - quint16 getUDPPort() const { return m_udpPort; } - bool getForce() const { return m_force; } - - static MsgConfigureBFMDemod* create(Real rfBandwidth, - Real afBandwidth, - Real volume, - Real squelch, - bool audioStereo, - bool lsbStereo, - bool showPilot, - bool rdsActive, - bool copyAudioToUDP, - const QString& udpAddress, - quint16 udpPort, - bool force) - { - return new MsgConfigureBFMDemod(rfBandwidth, - afBandwidth, - volume, - squelch, - audioStereo, - lsbStereo, - showPilot, - rdsActive, - copyAudioToUDP, - udpAddress, - udpPort, - force); - } - - private: - Real m_rfBandwidth; - Real m_afBandwidth; - Real m_volume; - Real m_squelch; - bool m_audioStereo; - bool m_lsbStereo; - bool m_showPilot; - bool m_rdsActive; - bool m_copyAudioToUDP; - QString m_udpAddress; - quint16 m_udpPort; - bool m_force; - - MsgConfigureBFMDemod(Real rfBandwidth, - Real afBandwidth, - Real volume, - Real squelch, - bool audioStereo, - bool lsbStereo, - bool showPilot, - bool rdsActive, - bool copyAudioToUDP, - const QString& udpAddress, - quint16 udpPort, - bool force) : - Message(), - m_rfBandwidth(rfBandwidth), - m_afBandwidth(afBandwidth), - m_volume(volume), - m_squelch(squelch), - m_audioStereo(audioStereo), - m_lsbStereo(lsbStereo), - m_showPilot(showPilot), - m_rdsActive(rdsActive), - m_copyAudioToUDP(copyAudioToUDP), - m_udpAddress(udpAddress), - m_udpPort(udpPort), - m_force(force) - { } - }; - enum RateState { RSInitialFill, RSRunning }; - struct Config { - int m_inputSampleRate; - qint64 m_inputFrequencyOffset; - Real m_rfBandwidth; - Real m_afBandwidth; - Real m_squelch; - Real m_volume; - quint32 m_audioSampleRate; - bool m_audioStereo; - bool m_lsbStereo; - bool m_showPilot; - bool m_rdsActive; - bool m_copyAudioToUDP; - QString m_udpAddress; - quint16 m_udpPort; + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; - Config() : - m_inputSampleRate(-1), - m_inputFrequencyOffset(0), - m_rfBandwidth(-1), - m_afBandwidth(-1), - m_squelch(0), - m_volume(0), - m_audioSampleRate(0), - m_audioStereo(false), - m_lsbStereo(false), - m_showPilot(false), - m_rdsActive(false), - m_copyAudioToUDP(false), - m_udpAddress("127.0.0.1"), - m_udpPort(9999) - { } - }; - - Config m_config; - Config m_running; + BFMDemodSettings m_settings; NCO m_nco; Interpolator m_interpolator; //!< Interpolator between fixed demod bandwidth and audio bandwidth (rational) @@ -254,7 +199,7 @@ private: RDSDemod m_rdsDemod; RDSDecoder m_rdsDecoder; - RDSParser *m_rdsParser; + RDSParser m_rdsParser; LowPassFilterRC m_deemphasisFilterX; LowPassFilterRC m_deemphasisFilterY; @@ -268,7 +213,7 @@ private: static const int m_udpBlockSize; - void apply(bool force = false); + 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 82170bb6c..02c86f2ff 100644 --- a/plugins/channelrx/demodbfm/bfmdemodgui.cpp +++ b/plugins/channelrx/demodbfm/bfmdemodgui.cpp @@ -37,26 +37,13 @@ #include "gui/basicchannelsettingsdialog.h" #include "mainwindow.h" +#include "bfmdemodsettings.h" #include "bfmdemod.h" #include "rdstmc.h" #include "ui_bfmdemodgui.h" const QString BFMDemodGUI::m_channelID = "sdrangel.channel.bfm"; -const int BFMDemodGUI::m_rfBW[] = { - 80000, 100000, 120000, 140000, 160000, 180000, 200000, 220000, 250000 -}; - -//int requiredBW(int rfBW) -//{ -// if (rfBW <= 48000) -// return 48000; -// else if (rfBW < 100000) -// return 96000; -// else -// return 384000; -//} - BFMDemodGUI* BFMDemodGUI::create(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI) { BFMDemodGUI* gui = new BFMDemodGUI(pluginAPI, deviceAPI); @@ -91,119 +78,65 @@ void BFMDemodGUI::setCenterFrequency(qint64 centerFrequency) void BFMDemodGUI::resetToDefaults() { - blockApplySettings(true); + m_settings.resetToDefaults(); + displaySettings(); - ui->rfBW->setValue(4); - ui->afBW->setValue(3); - ui->volume->setValue(20); - ui->squelch->setValue(-40); - ui->deltaFrequency->setValue(0); - ui->copyAudioToUDP->setChecked(false); - m_channelMarker.setTitle("Broadcast FM Demod"); - m_channelMarker.setColor(QColor(80, 120, 228)); - m_channelMarker.setBandwidth(12500); - m_channelMarker.setCenterFrequency(0); - m_channelMarker.setUDPAddress("127.0.0.1"); - m_channelMarker.setUDPSendPort(9999); - setTitleColor(m_channelMarker.getColor()); + blockApplySettings(true); ui->g00AltFrequenciesBox->setEnabled(false); ui->g14MappedFrequencies->setEnabled(false); ui->g14AltFrequencies->setEnabled(false); - blockApplySettings(false); + applySettings(); } QByteArray BFMDemodGUI::serialize() const { - SimpleSerializer s(1); - s.writeS32(1, m_channelMarker.getCenterFrequency()); - s.writeS32(2, ui->rfBW->value()); - s.writeS32(3, ui->afBW->value()); - s.writeS32(4, ui->volume->value()); - s.writeS32(5, ui->squelch->value()); - s.writeU32(7, m_channelMarker.getColor().rgb()); - s.writeBlob(8, ui->spectrumGUI->serialize()); - s.writeBool(9, ui->audioStereo->isChecked()); - s.writeBool(10, ui->lsbStereo->isChecked()); - s.writeBlob(11, m_channelMarker.serialize()); - return s.final(); + return m_settings.serialize(); } bool BFMDemodGUI::deserialize(const QByteArray& data) { - SimpleDeserializer d(data); - - if (!d.isValid()) - { - resetToDefaults(); - return false; - } - - if (d.getVersion() == 1) - { - QByteArray bytetmp; - qint32 tmp; - quint32 u32tmp; - bool booltmp; - QString strtmp; - - blockApplySettings(true); - m_channelMarker.blockSignals(true); - - d.readBlob(11, &bytetmp); - m_channelMarker.deserialize(bytetmp); - - d.readS32(1, &tmp, 0); - m_channelMarker.setCenterFrequency(tmp); - - d.readS32(2, &tmp, 4); - ui->rfBW->setValue(tmp); - ui->rfBWText->setText(QString("%1 kHz").arg(m_rfBW[tmp] / 1000.0)); - m_channelMarker.setBandwidth(m_rfBW[tmp]); - - d.readS32(3, &tmp, 3); - ui->afBW->setValue(tmp); - - d.readS32(4, &tmp, 20); - ui->volume->setValue(tmp); - - d.readS32(5, &tmp, -40); - ui->squelch->setValue(tmp); - - if(d.readU32(7, &u32tmp)) - { - m_channelMarker.setColor(u32tmp); - } - - d.readBlob(8, &bytetmp); - ui->spectrumGUI->deserialize(bytetmp); - - d.readBool(9, &booltmp, false); - ui->audioStereo->setChecked(booltmp); - - d.readBool(10, &booltmp, false); - ui->lsbStereo->setChecked(booltmp); - - this->setWindowTitle(m_channelMarker.getTitle()); - displayUDPAddress(); - - blockApplySettings(false); - m_channelMarker.blockSignals(false); - - applySettings(true); - return true; - } - else - { - resetToDefaults(); - return false; - } + if(m_settings.deserialize(data)) { + updateChannelMarker(); + displaySettings(); + applySettings(true); + return true; + } else { + resetToDefaults(); + return false; + } } -bool BFMDemodGUI::handleMessage(const Message& message __attribute__((unused))) +bool BFMDemodGUI::handleMessage(const Message& message) { - return false; + if (BFMDemod::MsgReportChannelSampleRateChanged::match(message)) + { + BFMDemod::MsgReportChannelSampleRateChanged& report = (BFMDemod::MsgReportChannelSampleRateChanged&) message; + m_rate = report.getSampleRate(); + ui->glSpectrum->setCenterFrequency(m_rate / 4); + ui->glSpectrum->setSampleRate(m_rate / 2); + return true; + } + else + { + return false; + } +} + +void BFMDemodGUI::handleInputMessages() +{ + Message* message; + + while ((message = getInputMessageQueue()->pop()) != 0) + { + qDebug("BFMDemodGUI::handleInputMessages: message: %s", message->getIdentifier()); + + if (handleMessage(*message)) + { + delete message; + } + } } void BFMDemodGUI::channelMarkerChanged() @@ -216,30 +149,36 @@ void BFMDemodGUI::channelMarkerChanged() void BFMDemodGUI::on_deltaFrequency_changed(qint64 value) { m_channelMarker.setCenterFrequency(value); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); + applySettings(); } void BFMDemodGUI::on_rfBW_valueChanged(int value) { - ui->rfBWText->setText(QString("%1 kHz").arg(m_rfBW[value] / 1000.0)); - m_channelMarker.setBandwidth(m_rfBW[value]); + ui->rfBWText->setText(QString("%1 kHz").arg(BFMDemodSettings::getRFBW(value) / 1000.0)); + m_channelMarker.setBandwidth(BFMDemodSettings::getRFBW(value)); + m_settings.m_rfBandwidth = BFMDemodSettings::getRFBW(value); applySettings(); } void BFMDemodGUI::on_afBW_valueChanged(int value) { ui->afBWText->setText(QString("%1 kHz").arg(value)); + m_settings.m_afBandwidth = value * 1000.0; applySettings(); } void BFMDemodGUI::on_volume_valueChanged(int value) { ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_volume = value / 10.0; applySettings(); } void BFMDemodGUI::on_squelch_valueChanged(int value) { ui->squelchText->setText(QString("%1 dB").arg(value)); + m_settings.m_squelch = value; applySettings(); } @@ -250,26 +189,31 @@ void BFMDemodGUI::on_audioStereo_toggled(bool stereo) ui->audioStereo->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); } + m_settings.m_audioStereo = stereo; applySettings(); } -void BFMDemodGUI::on_lsbStereo_toggled(bool lsb __attribute__((unused))) +void BFMDemodGUI::on_lsbStereo_toggled(bool lsb) { + m_settings.m_lsbStereo = lsb; applySettings(); } -void BFMDemodGUI::on_copyAudioToUDP_toggled(bool copy __attribute__((unused))) +void BFMDemodGUI::on_copyAudioToUDP_toggled(bool copy) { + m_settings.m_copyAudioToUDP = copy; applySettings(); } void BFMDemodGUI::on_showPilot_clicked() { + m_settings.m_showPilot = ui->showPilot->isChecked(); applySettings(); } void BFMDemodGUI::on_rds_clicked() { + m_settings.m_rdsActive = ui->rds->isChecked(); applySettings(); } @@ -277,7 +221,7 @@ void BFMDemodGUI::on_clearData_clicked(bool checked __attribute__((unused))) { if (ui->rds->isChecked()) { - m_rdsParser.clearAllFields(); + m_bfmDemod->getRDSParser().clearAllFields(); ui->g14ProgServiceNames->clear(); ui->g14MappedFrequencies->clear(); @@ -298,9 +242,9 @@ void BFMDemodGUI::on_g14ProgServiceNames_currentIndexChanged(int _index) if (index < m_g14ComboIndex.size()) { unsigned int piKey = m_g14ComboIndex[index]; - RDSParser::freqs_map_t::const_iterator mIt = m_rdsParser.m_g14_mapped_freqs.find(piKey); + RDSParser::freqs_map_t::const_iterator mIt = m_bfmDemod->getRDSParser().m_g14_mapped_freqs.find(piKey); - if (mIt != m_rdsParser.m_g14_mapped_freqs.end()) + if (mIt != m_bfmDemod->getRDSParser().m_g14_mapped_freqs.end()) { ui->g14MappedFrequencies->clear(); RDSParser::freqs_set_t::iterator sIt = (mIt->second).begin(); @@ -316,9 +260,9 @@ void BFMDemodGUI::on_g14ProgServiceNames_currentIndexChanged(int _index) ui->g14MappedFrequencies->setEnabled(ui->g14MappedFrequencies->count() > 0); } - mIt = m_rdsParser.m_g14_alt_freqs.find(piKey); + mIt = m_bfmDemod->getRDSParser().m_g14_alt_freqs.find(piKey); - if (mIt != m_rdsParser.m_g14_alt_freqs.end()) + if (mIt != m_bfmDemod->getRDSParser().m_g14_alt_freqs.end()) { ui->g14AltFrequencies->clear(); RDSParser::freqs_set_t::iterator sIt = (mIt->second).begin(); @@ -354,7 +298,6 @@ void BFMDemodGUI::on_g14AltFrequencies_activated(int index __attribute__((unused changeFrequency(f); } - void BFMDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) { } @@ -385,13 +328,12 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg setAttribute(Qt::WA_DeleteOnClose, true); connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); m_spectrumVis = new SpectrumVis(ui->glSpectrum); - m_bfmDemod = new BFMDemod(m_spectrumVis, &m_rdsParser); - m_channelizer = new DownChannelizer(m_bfmDemod); - m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); - connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged())); - m_deviceAPI->addThreadedSink(m_threadedChannelizer); + m_bfmDemod = new BFMDemod(m_deviceAPI); + m_bfmDemod->setMessageQueueToGUI(getInputMessageQueue()); + m_bfmDemod->setSampleSink(m_spectrumVis); ui->glSpectrum->setCenterFrequency(m_rate / 4); ui->glSpectrum->setSampleRate(m_rate / 2); @@ -401,16 +343,18 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, FFTWindow::BlackmanHarris); connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); - //m_channelMarker = new ChannelMarker(this); m_channelMarker.setTitle("Broadcast FM Demod"); - m_channelMarker.setColor(QColor(80, 120, 228)); m_channelMarker.setBandwidth(12500); m_channelMarker.setCenterFrequency(0); m_channelMarker.setUDPAddress("127.0.0.1"); m_channelMarker.setUDPSendPort(9999); m_channelMarker.setVisible(true); + m_channelMarker.setColor(m_settings.m_rgbColor); setTitleColor(m_channelMarker.getColor()); + m_settings.setChannelMarker(&m_channelMarker); + m_settings.setSpectrumGUI(ui->spectrumGUI); + connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); m_deviceAPI->registerChannelInstance(m_channelID, this); @@ -425,6 +369,7 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg rdsUpdateFixedFields(); rdsUpdate(true); + displaySettings(); displayUDPAddress(); applySettings(true); } @@ -432,11 +377,7 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg BFMDemodGUI::~BFMDemodGUI() { m_deviceAPI->removeChannelInstance(this); - m_deviceAPI->removeThreadedSink(m_threadedChannelizer); - delete m_threadedChannelizer; - delete m_channelizer; delete m_bfmDemod; - //delete m_channelMarker; delete ui; } @@ -445,6 +386,13 @@ void BFMDemodGUI::displayUDPAddress() ui->copyAudioToUDP->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort())); } +void BFMDemodGUI::updateChannelMarker() +{ + m_channelMarker.blockSignals(true); + this->setWindowTitle(m_channelMarker.getTitle()); + m_channelMarker.blockSignals(false); +} + void BFMDemodGUI::blockApplySettings(bool block) { m_doApplySettings = !block; @@ -456,28 +404,54 @@ void BFMDemodGUI::applySettings(bool force) { setTitleColor(m_channelMarker.getColor()); - m_channelizer->configure(m_channelizer->getInputMessageQueue(), - requiredBW(m_rfBW[ui->rfBW->value()]), // TODO: this is where requested sample rate is specified - m_channelMarker.getCenterFrequency()); + BFMDemod::MsgConfigureChannelizer *msgChan = BFMDemod::MsgConfigureChannelizer::create( + requiredBW(BFMDemodSettings::getRFBW(ui->rfBW->value())), + m_channelMarker.getCenterFrequency()); + m_bfmDemod->getInputMessageQueue()->push(msgChan); ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); - m_bfmDemod->configure(m_bfmDemod->getInputMessageQueue(), - m_rfBW[ui->rfBW->value()], - ui->afBW->value() * 1000.0, - ui->volume->value() / 10.0, - ui->squelch->value(), - ui->audioStereo->isChecked(), - ui->lsbStereo->isChecked(), - ui->showPilot->isChecked(), - ui->rds->isChecked(), - ui->copyAudioToUDP->isChecked(), - m_channelMarker.getUDPAddress(), - m_channelMarker.getUDPSendPort(), - force); + BFMDemod::MsgConfigureBFMDemod* msgConfig = BFMDemod::MsgConfigureBFMDemod::create( m_settings, force); + m_bfmDemod->getInputMessageQueue()->push(msgConfig); } } +void BFMDemodGUI::displaySettings() +{ + blockApplySettings(true); + + ui->deltaFrequency->setValue(m_settings.m_inputFrequencyOffset); + + ui->rfBW->setValue(BFMDemodSettings::getRFBWIndex(m_settings.m_rfBandwidth)); + ui->rfBWText->setText(QString("%1 kHz").arg(m_settings.m_rfBandwidth / 1000.0)); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); + + ui->afBW->setValue(m_settings.m_afBandwidth/1000.0); + ui->afBWText->setText(QString("%1 kHz").arg(m_settings.m_afBandwidth/1000.0)); + + ui->volume->setValue(m_settings.m_volume * 10.0); + ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1)); + + ui->squelch->setValue(m_settings.m_squelch); + ui->squelchText->setText(QString("%1 dB").arg(m_settings.m_squelch)); + + ui->audioStereo->setChecked(m_settings.m_audioStereo); + ui->lsbStereo->setChecked(m_settings.m_lsbStereo); + ui->showPilot->setChecked(m_settings.m_showPilot); + ui->rds->setChecked(m_settings.m_rdsActive); + ui->copyAudioToUDP->setChecked(m_settings.m_copyAudioToUDP); + + m_channelMarker.blockSignals(true); + m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); + m_channelMarker.setUDPAddress(m_settings.m_udpAddress); + m_channelMarker.setUDPSendPort(m_settings.m_udpPort); + m_channelMarker.setColor(m_settings.m_rgbColor); + setTitleColor(m_settings.m_rgbColor); + m_channelMarker.blockSignals(false); + + blockApplySettings(false); +} + void BFMDemodGUI::leaveEvent(QEvent*) { blockApplySettings(true); @@ -541,38 +515,31 @@ void BFMDemodGUI::tick() //qDebug() << "Pilot lock: " << m_bfmDemod->getPilotLock() << ":" << m_bfmDemod->getPilotLevel(); TODO: update a GUI item with status } -void BFMDemodGUI::channelSampleRateChanged() -{ - m_rate = m_bfmDemod->getSampleRate(); - ui->glSpectrum->setCenterFrequency(m_rate / 4); - ui->glSpectrum->setSampleRate(m_rate / 2); -} - void BFMDemodGUI::rdsUpdateFixedFields() { - ui->g00Label->setText(m_rdsParser.rds_group_acronym_tags[0].c_str()); - ui->g01Label->setText(m_rdsParser.rds_group_acronym_tags[1].c_str()); - ui->g02Label->setText(m_rdsParser.rds_group_acronym_tags[2].c_str()); - ui->g03Label->setText(m_rdsParser.rds_group_acronym_tags[3].c_str()); - ui->g04Label->setText(m_rdsParser.rds_group_acronym_tags[4].c_str()); - //ui->g05Label->setText(m_rdsParser.rds_group_acronym_tags[5].c_str()); - //ui->g06Label->setText(m_rdsParser.rds_group_acronym_tags[6].c_str()); - //ui->g07Label->setText(m_rdsParser.rds_group_acronym_tags[7].c_str()); - ui->g08Label->setText(m_rdsParser.rds_group_acronym_tags[8].c_str()); - ui->g09Label->setText(m_rdsParser.rds_group_acronym_tags[9].c_str()); - ui->g14Label->setText(m_rdsParser.rds_group_acronym_tags[14].c_str()); + ui->g00Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[0].c_str()); + ui->g01Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[1].c_str()); + ui->g02Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[2].c_str()); + ui->g03Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[3].c_str()); + ui->g04Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[4].c_str()); + //ui->g05Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[5].c_str()); + //ui->g06Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[6].c_str()); + //ui->g07Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[7].c_str()); + ui->g08Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[8].c_str()); + ui->g09Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[9].c_str()); + ui->g14Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[14].c_str()); - ui->g00CountLabel->setText(m_rdsParser.rds_group_acronym_tags[0].c_str()); - ui->g01CountLabel->setText(m_rdsParser.rds_group_acronym_tags[1].c_str()); - ui->g02CountLabel->setText(m_rdsParser.rds_group_acronym_tags[2].c_str()); - ui->g03CountLabel->setText(m_rdsParser.rds_group_acronym_tags[3].c_str()); - ui->g04CountLabel->setText(m_rdsParser.rds_group_acronym_tags[4].c_str()); - ui->g05CountLabel->setText(m_rdsParser.rds_group_acronym_tags[5].c_str()); - ui->g06CountLabel->setText(m_rdsParser.rds_group_acronym_tags[6].c_str()); - ui->g07CountLabel->setText(m_rdsParser.rds_group_acronym_tags[7].c_str()); - ui->g08CountLabel->setText(m_rdsParser.rds_group_acronym_tags[8].c_str()); - ui->g09CountLabel->setText(m_rdsParser.rds_group_acronym_tags[9].c_str()); - ui->g14CountLabel->setText(m_rdsParser.rds_group_acronym_tags[14].c_str()); + ui->g00CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[0].c_str()); + ui->g01CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[1].c_str()); + ui->g02CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[2].c_str()); + ui->g03CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[3].c_str()); + ui->g04CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[4].c_str()); + ui->g05CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[5].c_str()); + ui->g06CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[6].c_str()); + ui->g07CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[7].c_str()); + ui->g08CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[8].c_str()); + ui->g09CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[9].c_str()); + ui->g14CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[14].c_str()); } void BFMDemodGUI::rdsUpdate(bool force) @@ -591,21 +558,21 @@ void BFMDemodGUI::rdsUpdate(bool force) } // PI group - if (m_rdsParser.m_pi_updated || force) + if (m_bfmDemod->getRDSParser().m_pi_updated || force) { ui->piLabel->setStyleSheet("QLabel { background-color : green; }"); - ui->piCountText->setNum((int) m_rdsParser.m_pi_count); - QString pistring(str(boost::format("%04X") % m_rdsParser.m_pi_program_identification).c_str()); + ui->piCountText->setNum((int) m_bfmDemod->getRDSParser().m_pi_count); + QString pistring(str(boost::format("%04X") % m_bfmDemod->getRDSParser().m_pi_program_identification).c_str()); ui->piText->setText(pistring); - if (m_rdsParser.m_pi_traffic_program) { + if (m_bfmDemod->getRDSParser().m_pi_traffic_program) { ui->piTPIndicator->setStyleSheet("QLabel { background-color : green; }"); } else { ui->piTPIndicator->setStyleSheet("QLabel { background:rgb(79,79,79); }"); } - ui->piType->setText(QString(m_rdsParser.pty_table[m_rdsParser.m_pi_program_type].c_str())); - ui->piCoverage->setText(QString(m_rdsParser.coverage_area_codes[m_rdsParser.m_pi_area_coverage_index].c_str())); + ui->piType->setText(QString(m_bfmDemod->getRDSParser().pty_table[m_bfmDemod->getRDSParser().m_pi_program_type].c_str())); + ui->piCoverage->setText(QString(m_bfmDemod->getRDSParser().coverage_area_codes[m_bfmDemod->getRDSParser().m_pi_area_coverage_index].c_str())); } else { @@ -613,29 +580,29 @@ void BFMDemodGUI::rdsUpdate(bool force) } // G0 group - if (m_rdsParser.m_g0_updated || force) + if (m_bfmDemod->getRDSParser().m_g0_updated || force) { ui->g00Label->setStyleSheet("QLabel { background-color : green; }"); - ui->g00CountText->setNum((int) m_rdsParser.m_g0_count); + ui->g00CountText->setNum((int) m_bfmDemod->getRDSParser().m_g0_count); - if (m_rdsParser.m_g0_psn_bitmap == 0b1111) { - ui->g00ProgServiceName->setText(QString(m_rdsParser.m_g0_program_service_name)); + if (m_bfmDemod->getRDSParser().m_g0_psn_bitmap == 0b1111) { + ui->g00ProgServiceName->setText(QString(m_bfmDemod->getRDSParser().m_g0_program_service_name)); } - if (m_rdsParser.m_g0_traffic_announcement) { + if (m_bfmDemod->getRDSParser().m_g0_traffic_announcement) { ui->g00TrafficAnnouncement->setStyleSheet("QLabel { background-color : green; }"); } else { ui->g00TrafficAnnouncement->setStyleSheet("QLabel { background:rgb(79,79,79); }"); } - ui->g00MusicSpeech->setText(QString((m_rdsParser.m_g0_music_speech ? "Music" : "Speech"))); - ui->g00MonoStereo->setText(QString((m_rdsParser.m_g0_mono_stereo ? "Mono" : "Stereo"))); + ui->g00MusicSpeech->setText(QString((m_bfmDemod->getRDSParser().m_g0_music_speech ? "Music" : "Speech"))); + ui->g00MonoStereo->setText(QString((m_bfmDemod->getRDSParser().m_g0_mono_stereo ? "Mono" : "Stereo"))); - if (m_rdsParser.m_g0_af_updated) + if (m_bfmDemod->getRDSParser().m_g0_af_updated) { ui->g00AltFrequenciesBox->clear(); - for (std::set::iterator it = m_rdsParser.m_g0_alt_freq.begin(); it != m_rdsParser.m_g0_alt_freq.end(); ++it) + for (std::set::iterator it = m_bfmDemod->getRDSParser().m_g0_alt_freq.begin(); it != m_bfmDemod->getRDSParser().m_g0_alt_freq.end(); ++it) { if (*it > 76.0) { @@ -654,20 +621,20 @@ void BFMDemodGUI::rdsUpdate(bool force) } // G1 group - if (m_rdsParser.m_g1_updated || force) + if (m_bfmDemod->getRDSParser().m_g1_updated || force) { ui->g01Label->setStyleSheet("QLabel { background-color : green; }"); - ui->g01CountText->setNum((int) m_rdsParser.m_g1_count); + ui->g01CountText->setNum((int) m_bfmDemod->getRDSParser().m_g1_count); - if ((m_rdsParser.m_g1_country_page_index >= 0) && (m_rdsParser.m_g1_country_index >= 0)) { - ui->g01CountryCode->setText(QString((m_rdsParser.pi_country_codes[m_rdsParser.m_g1_country_page_index][m_rdsParser.m_g1_country_index]).c_str())); + if ((m_bfmDemod->getRDSParser().m_g1_country_page_index >= 0) && (m_bfmDemod->getRDSParser().m_g1_country_index >= 0)) { + ui->g01CountryCode->setText(QString((m_bfmDemod->getRDSParser().pi_country_codes[m_bfmDemod->getRDSParser().m_g1_country_page_index][m_bfmDemod->getRDSParser().m_g1_country_index]).c_str())); } - if (m_rdsParser.m_g1_language_index >= 0) { - ui->g01Language->setText(QString(m_rdsParser.language_codes[m_rdsParser.m_g1_language_index].c_str())); + if (m_bfmDemod->getRDSParser().m_g1_language_index >= 0) { + ui->g01Language->setText(QString(m_bfmDemod->getRDSParser().language_codes[m_bfmDemod->getRDSParser().m_g1_language_index].c_str())); } - ui->g01DHM->setText(QString(str(boost::format("%id:%i:%i") % m_rdsParser.m_g1_pin_day % m_rdsParser.m_g1_pin_hour % m_rdsParser.m_g1_pin_minute).c_str())); + ui->g01DHM->setText(QString(str(boost::format("%id:%i:%i") % m_bfmDemod->getRDSParser().m_g1_pin_day % m_bfmDemod->getRDSParser().m_g1_pin_hour % m_bfmDemod->getRDSParser().m_g1_pin_minute).c_str())); } else { @@ -675,11 +642,11 @@ void BFMDemodGUI::rdsUpdate(bool force) } // G2 group - if (m_rdsParser.m_g2_updated || force) + if (m_bfmDemod->getRDSParser().m_g2_updated || force) { ui->g02Label->setStyleSheet("QLabel { background-color : green; }"); - ui->g02CountText->setNum((int) m_rdsParser.m_g2_count); - ui->go2Text->setText(QString(m_rdsParser.m_g2_radiotext)); + ui->g02CountText->setNum((int) m_bfmDemod->getRDSParser().m_g2_count); + ui->go2Text->setText(QString(m_bfmDemod->getRDSParser().m_g2_radiotext)); } else { @@ -687,11 +654,11 @@ void BFMDemodGUI::rdsUpdate(bool force) } // G3 group - if (m_rdsParser.m_g3_updated || force) + if (m_bfmDemod->getRDSParser().m_g3_updated || force) { ui->g03Label->setStyleSheet("QLabel { background-color : green; }"); - ui->g03CountText->setNum((int) m_rdsParser.m_g3_count); - std::string g3str = str(boost::format("%02X%c %04X %04X") % m_rdsParser.m_g3_appGroup % (m_rdsParser.m_g3_groupB ? 'B' : 'A') % m_rdsParser.m_g3_message % m_rdsParser.m_g3_aid); + ui->g03CountText->setNum((int) m_bfmDemod->getRDSParser().m_g3_count); + std::string g3str = str(boost::format("%02X%c %04X %04X") % m_bfmDemod->getRDSParser().m_g3_appGroup % (m_bfmDemod->getRDSParser().m_g3_groupB ? 'B' : 'A') % m_bfmDemod->getRDSParser().m_g3_message % m_bfmDemod->getRDSParser().m_g3_aid); ui->g03Data->setText(QString(g3str.c_str())); } else @@ -700,12 +667,12 @@ void BFMDemodGUI::rdsUpdate(bool force) } // G4 group - if (m_rdsParser.m_g4_updated || force) + if (m_bfmDemod->getRDSParser().m_g4_updated || force) { ui->g04Label->setStyleSheet("QLabel { background-color : green; }"); - ui->g04CountText->setNum((int) m_rdsParser.m_g4_count); + ui->g04CountText->setNum((int) m_bfmDemod->getRDSParser().m_g4_count); std::string time = str(boost::format("%02i.%02i.%4i, %02i:%02i (%+.1fh)")\ - % m_rdsParser.m_g4_day % m_rdsParser.m_g4_month % (1900 + m_rdsParser.m_g4_year) % m_rdsParser.m_g4_hours % m_rdsParser.m_g4_minutes % m_rdsParser.m_g4_local_time_offset); + % m_bfmDemod->getRDSParser().m_g4_day % m_bfmDemod->getRDSParser().m_g4_month % (1900 + m_bfmDemod->getRDSParser().m_g4_year) % m_bfmDemod->getRDSParser().m_g4_hours % m_bfmDemod->getRDSParser().m_g4_minutes % m_bfmDemod->getRDSParser().m_g4_local_time_offset); ui->g04Time->setText(QString(time.c_str())); } else @@ -714,42 +681,42 @@ void BFMDemodGUI::rdsUpdate(bool force) } // G5 group - if (m_rdsParser.m_g5_updated || force) + if (m_bfmDemod->getRDSParser().m_g5_updated || force) { - ui->g05CountText->setNum((int) m_rdsParser.m_g5_count); + ui->g05CountText->setNum((int) m_bfmDemod->getRDSParser().m_g5_count); } // G6 group - if (m_rdsParser.m_g6_updated || force) + if (m_bfmDemod->getRDSParser().m_g6_updated || force) { - ui->g06CountText->setNum((int) m_rdsParser.m_g6_count); + ui->g06CountText->setNum((int) m_bfmDemod->getRDSParser().m_g6_count); } // G7 group - if (m_rdsParser.m_g7_updated || force) + if (m_bfmDemod->getRDSParser().m_g7_updated || force) { - ui->g07CountText->setNum((int) m_rdsParser.m_g7_count); + ui->g07CountText->setNum((int) m_bfmDemod->getRDSParser().m_g7_count); } // G8 group - if (m_rdsParser.m_g8_updated || force) + if (m_bfmDemod->getRDSParser().m_g8_updated || force) { ui->g08Label->setStyleSheet("QLabel { background-color : green; }"); - ui->g08CountText->setNum((int) m_rdsParser.m_g8_count); + ui->g08CountText->setNum((int) m_bfmDemod->getRDSParser().m_g8_count); std::ostringstream os; - os << (m_rdsParser.m_g8_sign ? "-" : "+") << m_rdsParser.m_g8_extent + 1; + os << (m_bfmDemod->getRDSParser().m_g8_sign ? "-" : "+") << m_bfmDemod->getRDSParser().m_g8_extent + 1; ui->g08Extent->setText(QString(os.str().c_str())); - int event_line = RDSTMC::get_tmc_event_code_index(m_rdsParser.m_g8_event, 1); + int event_line = RDSTMC::get_tmc_event_code_index(m_bfmDemod->getRDSParser().m_g8_event, 1); ui->g08TMCEvent->setText(QString(RDSTMC::get_tmc_events(event_line, 1).c_str())); - QString pistring(str(boost::format("%04X") % m_rdsParser.m_g8_location).c_str()); + QString pistring(str(boost::format("%04X") % m_bfmDemod->getRDSParser().m_g8_location).c_str()); ui->g08Location->setText(pistring); - if (m_rdsParser.m_g8_label_index >= 0) { - ui->g08Description->setText(QString(m_rdsParser.label_descriptions[m_rdsParser.m_g8_label_index].c_str())); + if (m_bfmDemod->getRDSParser().m_g8_label_index >= 0) { + ui->g08Description->setText(QString(m_bfmDemod->getRDSParser().label_descriptions[m_bfmDemod->getRDSParser().m_g8_label_index].c_str())); } - ui->g08Content->setNum(m_rdsParser.m_g8_content); + ui->g08Content->setNum(m_bfmDemod->getRDSParser().m_g8_content); } else { @@ -757,11 +724,11 @@ void BFMDemodGUI::rdsUpdate(bool force) } // G9 group - if (m_rdsParser.m_g9_updated || force) + if (m_bfmDemod->getRDSParser().m_g9_updated || force) { ui->g09Label->setStyleSheet("QLabel { background-color : green; }"); - ui->g09CountText->setNum((int) m_rdsParser.m_g9_count); - std::string g9str = str(boost::format("%02X %04X %04X %02X %04X") % m_rdsParser.m_g9_varA % m_rdsParser.m_g9_cA % m_rdsParser.m_g9_dA % m_rdsParser.m_g9_varB % m_rdsParser.m_g9_dB); + ui->g09CountText->setNum((int) m_bfmDemod->getRDSParser().m_g9_count); + std::string g9str = str(boost::format("%02X %04X %04X %02X %04X") % m_bfmDemod->getRDSParser().m_g9_varA % m_bfmDemod->getRDSParser().m_g9_cA % m_bfmDemod->getRDSParser().m_g9_dA % m_bfmDemod->getRDSParser().m_g9_varB % m_bfmDemod->getRDSParser().m_g9_dB); ui->g09Data->setText(QString(g9str.c_str())); } else @@ -770,18 +737,18 @@ void BFMDemodGUI::rdsUpdate(bool force) } // G14 group - if (m_rdsParser.m_g14_updated || force) + if (m_bfmDemod->getRDSParser().m_g14_updated || force) { - ui->g14CountText->setNum((int) m_rdsParser.m_g14_count); + ui->g14CountText->setNum((int) m_bfmDemod->getRDSParser().m_g14_count); - if (m_rdsParser.m_g14_data_available) + if (m_bfmDemod->getRDSParser().m_g14_data_available) { ui->g14Label->setStyleSheet("QLabel { background-color : green; }"); m_g14ComboIndex.clear(); ui->g14ProgServiceNames->clear(); - RDSParser::psns_map_t::iterator it = m_rdsParser.m_g14_program_service_names.begin(); - const RDSParser::psns_map_t::iterator itEnd = m_rdsParser.m_g14_program_service_names.end(); + RDSParser::psns_map_t::iterator it = m_bfmDemod->getRDSParser().m_g14_program_service_names.begin(); + const RDSParser::psns_map_t::iterator itEnd = m_bfmDemod->getRDSParser().m_g14_program_service_names.end(); int i = 0; for (; it != itEnd; ++it, i++) @@ -797,12 +764,11 @@ void BFMDemodGUI::rdsUpdate(bool force) } } - m_rdsParser.clearUpdateFlags(); + m_bfmDemod->getRDSParser().clearUpdateFlags(); } void BFMDemodGUI::changeFrequency(qint64 f) { qint64 df = m_channelMarker.getCenterFrequency(); qDebug() << "BFMDemodGUI::changeFrequency: " << f - df; - // TODO: in the future it should be able to set the center frequency of the sample source this channel plugin is linked to } diff --git a/plugins/channelrx/demodbfm/bfmdemodgui.h b/plugins/channelrx/demodbfm/bfmdemodgui.h index cf3c2d875..efcdc4f94 100644 --- a/plugins/channelrx/demodbfm/bfmdemodgui.h +++ b/plugins/channelrx/demodbfm/bfmdemodgui.h @@ -18,16 +18,16 @@ #ifndef INCLUDE_BFMDEMODGUI_H #define INCLUDE_BFMDEMODGUI_H +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" - -#include "rdsparser.h" +#include "bfmdemodsettings.h" class PluginAPI; class DeviceSourceAPI; +class RDSParser; class ThreadedBasebandSampleSink; class DownChannelizer; @@ -38,7 +38,7 @@ namespace Ui { class BFMDemodGUI; } -class BFMDemodGUI : public RollupWidget, public PluginInstanceUI { +class BFMDemodGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -60,7 +60,6 @@ public: private slots: void channelMarkerChanged(); - void channelSampleRateChanged(); void on_deltaFrequency_changed(qint64 value); void on_rfBW_valueChanged(int value); void on_afBW_valueChanged(int value); @@ -78,6 +77,7 @@ private slots: void on_g14AltFrequencies_activated(int index); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); + void handleInputMessages(); void tick(); private: @@ -85,13 +85,11 @@ private: PluginAPI* m_pluginAPI; DeviceSourceAPI* m_deviceAPI; ChannelMarker m_channelMarker; + BFMDemodSettings m_settings; bool m_doApplySettings; int m_rdsTimerCount; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; SpectrumVis* m_spectrumVis; - RDSParser m_rdsParser; BFMDemod* m_bfmDemod; MovingAverage m_channelPowerDbAvg; @@ -99,14 +97,14 @@ private: std::vector m_g14ComboIndex; MessageQueue m_inputMessageQueue; - static const int m_rfBW[]; - explicit BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget* parent = NULL); virtual ~BFMDemodGUI(); void blockApplySettings(bool block); void applySettings(bool force = false); + void displaySettings(); void displayUDPAddress(); + void updateChannelMarker(); void rdsUpdate(bool force); void rdsUpdateFixedFields(); diff --git a/plugins/channelrx/demodbfm/bfmdemodsettings.cpp b/plugins/channelrx/demodbfm/bfmdemodsettings.cpp new file mode 100644 index 000000000..6efa0385c --- /dev/null +++ b/plugins/channelrx/demodbfm/bfmdemodsettings.cpp @@ -0,0 +1,154 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 + +#include "dsp/dspengine.h" +#include "util/simpleserializer.h" +#include "settings/serializable.h" + +#include "bfmdemodsettings.h" + +const int BFMDemodSettings::m_nbRFBW = 9; +const int BFMDemodSettings::m_rfBW[] = { + 80000, 100000, 120000, 140000, 160000, 180000, 200000, 220000, 250000 +}; + +BFMDemodSettings::BFMDemodSettings() : + m_channelMarker(0), + m_spectrumGUI(0) +{ + resetToDefaults(); +} + +void BFMDemodSettings::resetToDefaults() +{ + m_inputSampleRate = 384000; + m_inputFrequencyOffset = 0; + m_rfBandwidth = getRFBW(5); + m_afBandwidth = 15000; + m_volume = 2.0; + m_squelch = -60.0; + m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); + m_audioStereo = false; + m_lsbStereo = false; + m_showPilot = false; + m_rdsActive = false; + m_copyAudioToUDP = false; + m_udpAddress = "127.0.0.1"; + m_udpPort = 9999; + m_rgbColor = QColor(80, 120, 228).rgb(); +} + +QByteArray BFMDemodSettings::serialize() const +{ + SimpleSerializer s(1); + s.writeS32(1, m_inputFrequencyOffset); + s.writeS32(2, getRFBWIndex(m_rfBandwidth)); + s.writeS32(3, m_afBandwidth/1000.0); + s.writeS32(4, m_volume*10.0); + s.writeS32(5, m_squelch); + s.writeU32(7, m_rgbColor); + + if (m_spectrumGUI) { + s.writeBlob(8, m_spectrumGUI->serialize()); + } + + s.writeBool(9, m_audioStereo); + s.writeBool(10, m_lsbStereo); + + if (m_channelMarker) { + s.writeBlob(11, m_channelMarker->serialize()); + } + + return s.final(); +} + +bool BFMDemodSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) + { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) + { + QByteArray bytetmp; + qint32 tmp; + QString strtmp; + + d.readS32(1, &tmp, 0); + m_inputFrequencyOffset = tmp; + d.readS32(2, &tmp, 4); + m_rfBandwidth = getRFBW(tmp); + d.readS32(3, &tmp, 3); + m_afBandwidth = tmp * 1000.0; + d.readS32(4, &tmp, 20); + m_volume = tmp * 0.1; + d.readS32(5, &tmp, -60); + m_squelch = tmp; + d.readU32(7, &m_rgbColor); + + d.readBlob(8, &bytetmp); + + if (m_spectrumGUI) { + m_spectrumGUI->deserialize(bytetmp); + } + + d.readBool(9, &m_audioStereo, false); + d.readBool(10, &m_lsbStereo, false); + + d.readBlob(11, &bytetmp); + + if (m_channelMarker) { + m_channelMarker->deserialize(bytetmp); + } + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +int BFMDemodSettings::getRFBW(int index) +{ + if (index < 0) { + return m_rfBW[0]; + } else if (index < m_nbRFBW) { + return m_rfBW[index]; + } else { + return m_rfBW[m_nbRFBW-1]; + } +} + +int BFMDemodSettings::getRFBWIndex(int rfbw) +{ + for (int i = 0; i < m_nbRFBW; i++) + { + if (rfbw <= m_rfBW[i]) + { + return i; + } + } + + return m_nbRFBW-1; +} diff --git a/plugins/channelrx/demodbfm/bfmdemodsettings.h b/plugins/channelrx/demodbfm/bfmdemodsettings.h new file mode 100644 index 000000000..3f8f69ec2 --- /dev/null +++ b/plugins/channelrx/demodbfm/bfmdemodsettings.h @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 PLUGINS_CHANNELRX_DEMODBFM_BFMDEMODSETTINGS_H_ +#define PLUGINS_CHANNELRX_DEMODBFM_BFMDEMODSETTINGS_H_ + +class Serializable; + +struct BFMDemodSettings +{ + int m_inputSampleRate; + qint64 m_inputFrequencyOffset; + Real m_rfBandwidth; + Real m_afBandwidth; + Real m_volume; + Real m_squelch; + quint32 m_audioSampleRate; + bool m_audioStereo; + bool m_lsbStereo; + bool m_showPilot; + bool m_rdsActive; + bool m_copyAudioToUDP; + QString m_udpAddress; + quint16 m_udpPort; + quint32 m_rgbColor; + + Serializable *m_channelMarker; + Serializable *m_spectrumGUI; + + static const int m_nbRFBW; + static const int m_rfBW[]; + + BFMDemodSettings(); + void resetToDefaults(); + void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } + void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; } + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + + static int getRFBW(int index); + static int getRFBWIndex(int rfbw); +}; + + +#endif /* PLUGINS_CHANNELRX_DEMODBFM_BFMDEMODSETTINGS_H_ */ diff --git a/plugins/channelrx/demodbfm/bfmplugin.cpp b/plugins/channelrx/demodbfm/bfmplugin.cpp index 6eb20bfd3..9aee0f780 100644 --- a/plugins/channelrx/demodbfm/bfmplugin.cpp +++ b/plugins/channelrx/demodbfm/bfmplugin.cpp @@ -24,7 +24,7 @@ const PluginDescriptor BFMPlugin::m_pluginDescriptor = { QString("Broadcast FM Demodulator"), - QString("3.6.1"), + QString("3.7.3"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -50,7 +50,7 @@ void BFMPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(BFMDemodGUI::m_channelID, this); } -PluginInstanceUI* BFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* BFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == BFMDemodGUI::m_channelID) { diff --git a/plugins/channelrx/demodbfm/bfmplugin.h b/plugins/channelrx/demodbfm/bfmplugin.h index 0b5fdb8e7..6879eb197 100644 --- a/plugins/channelrx/demodbfm/bfmplugin.h +++ b/plugins/channelrx/demodbfm/bfmplugin.h @@ -34,7 +34,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodbfm/demodbfm.pro b/plugins/channelrx/demodbfm/demodbfm.pro index cd6f5b130..908d69982 100644 --- a/plugins/channelrx/demodbfm/demodbfm.pro +++ b/plugins/channelrx/demodbfm/demodbfm.pro @@ -30,6 +30,7 @@ CONFIG(Debug):build_subdir = debug SOURCES += bfmdemod.cpp\ bfmdemodgui.cpp\ + bfmdemodsettings.cpp\ bfmplugin.cpp\ rdsdemod.cpp\ rdsdecoder.cpp\ @@ -38,6 +39,7 @@ SOURCES += bfmdemod.cpp\ HEADERS += bfmdemod.h\ bfmdemodgui.h\ + bfmdemodsettings.h\ bfmplugin.h\ rdsdemod.h\ rdsdecoder.h\ diff --git a/plugins/channelrx/demodbfm/rdsdemod.cpp b/plugins/channelrx/demodbfm/rdsdemod.cpp index 97c1a21bb..32292f32b 100644 --- a/plugins/channelrx/demodbfm/rdsdemod.cpp +++ b/plugins/channelrx/demodbfm/rdsdemod.cpp @@ -22,6 +22,10 @@ #include #include +#undef M_PI +#define M_PI 3.14159265358979323846 +#undef M_PI_2 +#define M_PI_2 1.57079632679489661923 const Real RDSDemod::m_pllBeta = 50; const Real RDSDemod::m_fsc = 1187.5; @@ -77,7 +81,7 @@ bool RDSDemod::process(Real demod, bool& bit) m_parms.clock_offset = 0; }*/ - m_parms.subcarr_phi += (2 * M_PI * m_fsc) / (Real) m_srate; + m_parms.subcarr_phi += (2 * M_PI * m_fsc) / (Real) m_srate; m_parms.clock_phi = m_parms.subcarr_phi + m_parms.clock_offset; // Clock phase recovery diff --git a/plugins/channelrx/demoddsd/CMakeLists.txt b/plugins/channelrx/demoddsd/CMakeLists.txt index 04823c5a4..02a1b533a 100644 --- a/plugins/channelrx/demoddsd/CMakeLists.txt +++ b/plugins/channelrx/demoddsd/CMakeLists.txt @@ -4,6 +4,8 @@ set(dsddemod_SOURCES dsddemod.cpp dsddemodgui.cpp dsddemodplugin.cpp + dsddemodbaudrates.cpp + dsddemodsettings.cpp dsddecoder.cpp ) @@ -11,6 +13,8 @@ set(dsddemod_HEADERS dsddemod.h dsddemodgui.h dsddemodplugin.h + dsddemodbaudrates.h + dsddemodsettings.h dsddecoder.h ) diff --git a/plugins/channelrx/demoddsd/demoddsd.pro b/plugins/channelrx/demoddsd/demoddsd.pro index 3255ff461..1779fcd1c 100644 --- a/plugins/channelrx/demoddsd/demoddsd.pro +++ b/plugins/channelrx/demoddsd/demoddsd.pro @@ -40,12 +40,16 @@ CONFIG(Debug):build_subdir = debug SOURCES = dsddecoder.cpp\ dsddemod.cpp\ dsddemodgui.cpp\ -dsddemodplugin.cpp +dsddemodplugin.cpp\ +dsddemodbaudrates.cpp\ +dsddemodsettings.cpp HEADERS = dsddecoder.h\ dsddemod.h\ dsddemodgui.h\ -dsddemodplugin.h +dsddemodplugin.h\ +dsddemodbaudrates.h\ +dsddemodsettings.h FORMS = dsddemodgui.ui diff --git a/plugins/channelrx/demoddsd/dsddemod.cpp b/plugins/channelrx/demoddsd/dsddemod.cpp index d1bf7df5c..6a69c6fe2 100644 --- a/plugins/channelrx/demoddsd/dsddemod.cpp +++ b/plugins/channelrx/demoddsd/dsddemod.cpp @@ -15,51 +15,48 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "../../channelrx/demoddsd/dsddemod.h" #include #include #include #include + #include #include "audio/audiooutput.h" #include "dsp/pidcontroller.h" #include "dsp/dspengine.h" -#include "dsddemodgui.h" +#include "dsp/threadedbasebandsamplesink.h" +#include +#include +#include "dsddemod.h" + +MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureChannelizer, Message) MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureDSDDemod, Message) MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureMyPosition, Message) const int DSDDemod::m_udpBlockSize = 512; -DSDDemod::DSDDemod(BasebandSampleSink* sampleSink) : - m_sampleCount(0), - m_squelchCount(0), - m_squelchOpen(false), +DSDDemod::DSDDemod(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_interpolatorDistance(0.0f), + m_interpolatorDistanceRemain(0.0f), + m_sampleCount(0), + m_squelchCount(0), + m_squelchGate(0), + m_squelchLevel(1e-4), + m_squelchOpen(false), m_movingAverage(40, 0), m_fmExcursion(24), - m_audioFifo1(48000), + m_audioFifo1(48000), m_audioFifo2(48000), - m_scope(sampleSink), + m_scope(0), m_scopeEnabled(true), m_dsdDecoder(), m_settingsMutex(QMutex::Recursive) { setObjectName("DSDDemod"); - m_config.m_inputSampleRate = 96000; - m_config.m_inputFrequencyOffset = 0; - m_config.m_rfBandwidth = 100; - m_config.m_demodGain = 100; - m_config.m_fmDeviation = 100; - m_config.m_squelchGate = 5; // 10s of ms at 48000 Hz sample rate. Corresponds to 2400 for AGC attack - m_config.m_squelch = -30.0; - m_config.m_volume = 1.0; - m_config.m_baudRate = 4800; - m_config.m_audioMute = false; - m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); - m_config.m_enableCosineFiltering = false; - m_audioBuffer.resize(1<<14); m_audioBufferFill = 0; @@ -75,11 +72,15 @@ DSDDemod::DSDDemod(BasebandSampleSink* sampleSink) : DSPEngine::instance()->addAudioSink(&m_audioFifo1); DSPEngine::instance()->addAudioSink(&m_audioFifo2); - m_udpBufferAudio = new UDPSink(this, m_udpBlockSize, m_config.m_udpPort); + m_udpBufferAudio = new UDPSink(this, m_udpBlockSize, m_settings.m_udpPort); m_audioFifo1.setUDPSink(m_udpBufferAudio); m_audioFifo2.setUDPSink(m_udpBufferAudio); - apply(true); + m_channelizer = new DownChannelizer(this); + m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); + m_deviceAPI->addThreadedSink(m_threadedChannelizer); + + applySettings(m_settings, true); } DSDDemod::~DSDDemod() @@ -88,47 +89,10 @@ DSDDemod::~DSDDemod() DSPEngine::instance()->removeAudioSink(&m_audioFifo1); DSPEngine::instance()->removeAudioSink(&m_audioFifo2); delete m_udpBufferAudio; -} -void DSDDemod::configure(MessageQueue* messageQueue, - int rfBandwidth, - int demodGain, - int fmDeviation, - int volume, - int baudRate, - int squelchGate, - Real squelch, - bool audioMute, - bool enableCosineFiltering, - bool syncOrConstellation, - bool slot1On, - bool slot2On, - bool tdmaStereo, - bool pllLock, - bool udpCopyAudio, - const QString& udpAddress, - quint16 udpPort, - bool force) -{ - Message* cmd = MsgConfigureDSDDemod::create(rfBandwidth, - demodGain, - fmDeviation, - volume, - baudRate, - squelchGate, - squelch, - audioMute, - enableCosineFiltering, - syncOrConstellation, - slot1On, - slot2On, - tdmaStereo, - pllLock, - udpCopyAudio, - udpAddress, - udpPort, - force); - messageQueue->push(cmd); + m_deviceAPI->removeThreadedSink(m_threadedChannelizer); + delete m_threadedChannelizer; + delete m_channelizer; } void DSDDemod::configureMyPosition(MessageQueue* messageQueue, float myLatitude, float myLongitude) @@ -168,7 +132,7 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto m_magsqCount++; - Real demod = 32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * ((float) m_running.m_demodGain / 100.0f); + Real demod = 32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_demodGain; m_sampleCount++; // AF processing @@ -205,7 +169,7 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto m_dsdDecoder.pushSample(sample); - if (m_running.m_enableCosineFiltering) { // show actual input to FSK demod + if (m_settings.m_enableCosineFiltering) { // show actual input to FSK demod sample = m_dsdDecoder.getFilteredSample(); } @@ -223,7 +187,7 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto delayedSample = m_sampleBuffer[m_sampleBufferIndex - samplesPerSymbol]; } - if (m_running.m_syncOrConstellation) + if (m_settings.m_syncOrConstellation) { Sample s(sample, m_dsdDecoder.getSymbolSyncSample()); m_scopeSampleBuffer.push_back(s); @@ -236,30 +200,30 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto if (DSPEngine::instance()->hasDVSerialSupport()) { - if ((m_running.m_slot1On) && m_dsdDecoder.mbeDVReady1()) + if ((m_settings.m_slot1On) && m_dsdDecoder.mbeDVReady1()) { - if (!m_running.m_audioMute) + if (!m_settings.m_audioMute) { DSPEngine::instance()->pushMbeFrame( m_dsdDecoder.getMbeDVFrame1(), m_dsdDecoder.getMbeRateIndex(), - m_running.m_volume, - m_running.m_tdmaStereo ? 1 : 3, // left or both channels + m_settings.m_volume, + m_settings.m_tdmaStereo ? 1 : 3, // left or both channels &m_audioFifo1); } m_dsdDecoder.resetMbeDV1(); } - if ((m_running.m_slot2On) && m_dsdDecoder.mbeDVReady2()) + if ((m_settings.m_slot2On) && m_dsdDecoder.mbeDVReady2()) { - if (!m_running.m_audioMute) + if (!m_settings.m_audioMute) { DSPEngine::instance()->pushMbeFrame( m_dsdDecoder.getMbeDVFrame2(), m_dsdDecoder.getMbeRateIndex(), - m_running.m_volume, - m_running.m_tdmaStereo ? 2 : 3, // right or both channels + m_settings.m_volume, + m_settings.m_tdmaStereo ? 2 : 3, // right or both channels &m_audioFifo2); } @@ -269,9 +233,9 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto // if (DSPEngine::instance()->hasDVSerialSupport() && m_dsdDecoder.mbeDVReady1()) // { -// if (!m_running.m_audioMute) +// if (!m_settings.m_audioMute) // { -// DSPEngine::instance()->pushMbeFrame(m_dsdDecoder.getMbeDVFrame1(), m_dsdDecoder.getMbeRateIndex(), m_running.m_volume, &m_audioFifo1); +// DSPEngine::instance()->pushMbeFrame(m_dsdDecoder.getMbeDVFrame1(), m_dsdDecoder.getMbeRateIndex(), m_settings.m_volume, &m_audioFifo1); // } // // m_dsdDecoder.resetMbeDV1(); @@ -283,14 +247,14 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto if (!DSPEngine::instance()->hasDVSerialSupport()) { - if (m_running.m_slot1On) + if (m_settings.m_slot1On) { int nbAudioSamples; short *dsdAudio = m_dsdDecoder.getAudio1(nbAudioSamples); if (nbAudioSamples > 0) { - if (!m_running.m_audioMute) { + if (!m_settings.m_audioMute) { m_audioFifo1.write((const quint8*) dsdAudio, nbAudioSamples, 10); } @@ -298,14 +262,14 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto } } - if (m_running.m_slot2On) + if (m_settings.m_slot2On) { int nbAudioSamples; short *dsdAudio = m_dsdDecoder.getAudio2(nbAudioSamples); if (nbAudioSamples > 0) { - if (!m_running.m_audioMute) { + if (!m_settings.m_audioMute) { m_audioFifo2.write((const quint8*) dsdAudio, nbAudioSamples, 10); } @@ -318,7 +282,7 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto // // if (nbAudioSamples > 0) // { -// if (!m_running.m_audioMute) { +// if (!m_settings.m_audioMute) { // uint res = m_audioFifo1.write((const quint8*) dsdAudio, nbAudioSamples, 10); // } // @@ -354,60 +318,60 @@ bool DSDDemod::handleMessage(const Message& cmd) { DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; - m_config.m_inputSampleRate = notif.getSampleRate(); - m_config.m_inputFrequencyOffset = notif.getFrequencyOffset(); + DSDDemodSettings settings = m_settings; + settings.m_inputSampleRate = notif.getSampleRate(); + settings.m_inputFrequencyOffset = notif.getFrequencyOffset(); - apply(); + applySettings(settings); - qDebug() << "DSDDemod::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << m_config.m_inputSampleRate - << " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; + qDebug() << "DSDDemod::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << settings.m_inputSampleRate + << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset; return true; } - else if (MsgConfigureDSDDemod::match(cmd)) - { - MsgConfigureDSDDemod& cfg = (MsgConfigureDSDDemod&) cmd; + else if (MsgConfigureChannelizer::match(cmd)) + { + MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; - m_config.m_rfBandwidth = cfg.getRFBandwidth(); - m_config.m_demodGain = cfg.getDemodGain(); - m_config.m_fmDeviation = cfg.getFMDeviation(); - m_config.m_volume = cfg.getVolume(); - m_config.m_baudRate = cfg.getBaudRate(); - m_config.m_squelchGate = cfg.getSquelchGate(); - m_config.m_squelch = cfg.getSquelch(); - m_config.m_audioMute = cfg.getAudioMute(); - m_config.m_enableCosineFiltering = cfg.getEnableCosineFiltering(); - m_config.m_syncOrConstellation = cfg.getSyncOrConstellation(); - m_config.m_slot1On = cfg.getSlot1On(); - m_config.m_slot2On = cfg.getSlot2On(); - m_config.m_tdmaStereo = cfg.getTDMAStereo(); - m_config.m_pllLock = cfg.getPLLLock(); - m_config.m_udpCopyAudio = cfg.getUDPCopyAudio(); - m_config.m_udpAddress = cfg.getUDPAddress(); - m_config.m_udpPort = cfg.getUDPPort(); + m_channelizer->configure(m_channelizer->getInputMessageQueue(), + cfg.getSampleRate(), + cfg.getCenterFrequency()); - apply(); + return true; + } + else if (MsgConfigureDSDDemod::match(cmd)) + { + MsgConfigureDSDDemod& cfg = (MsgConfigureDSDDemod&) cmd; - qDebug() << "DSDDemod::handleMessage: MsgConfigureDSDDemod: m_rfBandwidth: " << m_config.m_rfBandwidth * 100 - << " m_demodGain: " << m_config.m_demodGain / 100.0 - << " m_fmDeviation: " << m_config.m_fmDeviation * 100 - << " m_volume: " << m_config.m_volume / 10.0 - << " m_baudRate: " << m_config.m_baudRate - << " m_squelchGate" << m_config.m_squelchGate - << " m_squelch: " << m_config.m_squelch - << " m_audioMute: " << m_config.m_audioMute - << " m_enableCosineFiltering: " << m_config.m_enableCosineFiltering - << " m_syncOrConstellation: " << m_config.m_syncOrConstellation - << " m_slot1On: " << m_config.m_slot1On - << " m_slot2On: " << m_config.m_slot2On - << " m_tdmaStereo: " << m_config.m_tdmaStereo - << " m_pllLock: " << m_config.m_pllLock - << " m_udpCopyAudio: " << m_config.m_udpCopyAudio - << " m_udpAddress: " << m_config.m_udpAddress - << " m_udpPort: " << m_config.m_udpPort; + DSDDemodSettings settings = cfg.getSettings(); - return true; - } + // These settings are set with DownChannelizer::MsgChannelizerNotification + settings.m_inputSampleRate = m_settings.m_inputSampleRate; + settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset; + + applySettings(settings, cfg.getForce()); + + qDebug() << "DSDDemod::handleMessage: MsgConfigureDSDDemod: m_rfBandwidth: " << m_settings.m_rfBandwidth + << " m_fmDeviation: " << m_settings.m_fmDeviation + << " m_demodGain: " << m_settings.m_demodGain + << " m_volume: " << m_settings.m_volume + << " m_baudRate: " << m_settings.m_baudRate + << " m_squelchGate" << m_settings.m_squelchGate + << " m_squelch: " << m_settings.m_squelch + << " m_audioMute: " << m_settings.m_audioMute + << " m_enableCosineFiltering: " << m_settings.m_enableCosineFiltering + << " m_syncOrConstellation: " << m_settings.m_syncOrConstellation + << " m_slot1On: " << m_settings.m_slot1On + << " m_slot2On: " << m_settings.m_slot2On + << " m_tdmaStereo: " << m_settings.m_tdmaStereo + << " m_pllLock: " << m_settings.m_pllLock + << " m_udpCopyAudio: " << m_settings.m_udpCopyAudio + << " m_udpAddress: " << m_settings.m_udpAddress + << " m_udpPort: " << m_settings.m_udpPort + << " force: " << cfg.getForce(); + + return true; + } else if (MsgConfigureMyPosition::match(cmd)) { MsgConfigureMyPosition& cfg = (MsgConfigureMyPosition&) cmd; @@ -420,82 +384,81 @@ bool DSDDemod::handleMessage(const Message& cmd) } } -void DSDDemod::apply(bool force) +void DSDDemod::applySettings(DSDDemodSettings& settings, bool force) { - if ((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || - (m_config.m_inputSampleRate != m_running.m_inputSampleRate) || force) - { - m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate); - } - - if ((m_config.m_inputSampleRate != m_running.m_inputSampleRate) || - (m_config.m_rfBandwidth != m_running.m_rfBandwidth) || force) - { - m_settingsMutex.lock(); - m_interpolator.create(16, m_config.m_inputSampleRate, (m_config.m_rfBandwidth * 100) / 2.2); - m_interpolatorDistanceRemain = 0; - m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate; - m_phaseDiscri.setFMScaling((float) m_config.m_rfBandwidth / (float) m_config.m_fmDeviation); - m_settingsMutex.unlock(); - } - - if ((m_config.m_fmDeviation != m_running.m_fmDeviation) || force) - { - m_phaseDiscri.setFMScaling((float) m_config.m_rfBandwidth / (float) m_config.m_fmDeviation); - } - - if ((m_config.m_squelchGate != m_running.m_squelchGate) || force) - { - m_squelchGate = 480 * m_config.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate - m_squelchCount = 0; // reset squelch open counter - } - - if ((m_config.m_squelch != m_running.m_squelch) || force) - { - // input is a value in tenths of dB - m_squelchLevel = std::pow(10.0, m_config.m_squelch / 100.0); - //m_squelchLevel *= m_squelchLevel; - } - - if ((m_config.m_volume != m_running.m_volume) || force) + if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || + (settings.m_inputSampleRate != m_settings.m_inputSampleRate) || force) { - m_dsdDecoder.setAudioGain(m_config.m_volume / 10.0f); + m_nco.setFreq(-settings.m_inputFrequencyOffset, settings.m_inputSampleRate); } - if ((m_config.m_baudRate != m_running.m_baudRate) || force) + if ((settings.m_inputSampleRate != m_settings.m_inputSampleRate) || + (settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) { - m_dsdDecoder.setBaudRate(m_config.m_baudRate); + m_settingsMutex.lock(); + m_interpolator.create(16, settings.m_inputSampleRate, (settings.m_rfBandwidth) / 2.2); + m_interpolatorDistanceRemain = 0; + m_interpolatorDistance = (Real) settings.m_inputSampleRate / (Real) settings.m_audioSampleRate; + m_phaseDiscri.setFMScaling((float) settings.m_rfBandwidth / (float) settings.m_fmDeviation); + m_settingsMutex.unlock(); } - if ((m_config.m_enableCosineFiltering != m_running.m_enableCosineFiltering) || force) + if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) { - m_dsdDecoder.enableCosineFiltering(m_config.m_enableCosineFiltering); + m_phaseDiscri.setFMScaling((float) settings.m_rfBandwidth / (float) settings.m_fmDeviation); } - if ((m_config.m_tdmaStereo != m_running.m_tdmaStereo) || force) + if ((settings.m_squelchGate != m_settings.m_squelchGate) || force) { - m_dsdDecoder.setTDMAStereo(m_config.m_tdmaStereo); + m_squelchGate = 480 * settings.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate + m_squelchCount = 0; // reset squelch open counter } - if ((m_config.m_pllLock != m_running.m_pllLock) || force) + if ((settings.m_squelch != m_settings.m_squelch) || force) { - m_dsdDecoder.setSymbolPLLLock(m_config.m_pllLock); + // input is a value in dB + m_squelchLevel = std::pow(10.0, settings.m_squelch / 10.0); } - if ((m_config.m_udpAddress != m_running.m_udpAddress) - || (m_config.m_udpPort != m_running.m_udpPort) || force) + if ((settings.m_volume != m_settings.m_volume) || force) { - m_udpBufferAudio->setAddress(m_config.m_udpAddress); - m_udpBufferAudio->setPort(m_config.m_udpPort); + m_dsdDecoder.setAudioGain(settings.m_volume); } - if ((m_config.m_udpCopyAudio != m_running.m_udpCopyAudio) - || (m_config.m_slot1On != m_running.m_slot1On) - || (m_config.m_slot2On != m_running.m_slot2On) || force) + if ((settings.m_baudRate != m_settings.m_baudRate) || force) { - m_audioFifo1.setCopyToUDP(m_config.m_slot1On && m_config.m_udpCopyAudio); - m_audioFifo2.setCopyToUDP(m_config.m_slot2On && !m_config.m_slot1On && m_config.m_udpCopyAudio); + m_dsdDecoder.setBaudRate(settings.m_baudRate); } - m_running = m_config; + if ((settings.m_enableCosineFiltering != m_settings.m_enableCosineFiltering) || force) + { + m_dsdDecoder.enableCosineFiltering(settings.m_enableCosineFiltering); + } + + if ((settings.m_tdmaStereo != m_settings.m_tdmaStereo) || force) + { + m_dsdDecoder.setTDMAStereo(settings.m_tdmaStereo); + } + + if ((settings.m_pllLock != m_settings.m_pllLock) || force) + { + m_dsdDecoder.setSymbolPLLLock(settings.m_pllLock); + } + + if ((settings.m_udpAddress != m_settings.m_udpAddress) + || (settings.m_udpPort != m_settings.m_udpPort) || force) + { + m_udpBufferAudio->setAddress(settings.m_udpAddress); + m_udpBufferAudio->setPort(settings.m_udpPort); + } + + if ((settings.m_udpCopyAudio != m_settings.m_udpCopyAudio) + || (settings.m_slot1On != m_settings.m_slot1On) + || (settings.m_slot2On != m_settings.m_slot2On) || force) + { + m_audioFifo1.setCopyToUDP(settings.m_slot1On && settings.m_udpCopyAudio); + m_audioFifo2.setCopyToUDP(settings.m_slot2On && !settings.m_slot1On && settings.m_udpCopyAudio); + } + + m_settings = settings; } diff --git a/plugins/channelrx/demoddsd/dsddemod.h b/plugins/channelrx/demoddsd/dsddemod.h index 3b17ad66b..501c58ccc 100644 --- a/plugins/channelrx/demoddsd/dsddemod.h +++ b/plugins/channelrx/demoddsd/dsddemod.h @@ -33,34 +33,64 @@ #include "util/message.h" #include "util/udpsink.h" +#include "dsddemodsettings.h" #include "dsddecoder.h" -class DSDDemodGUI; +class DeviceSourceAPI; +class ThreadedBasebandSampleSink; +class DownChannelizer; class DSDDemod : public BasebandSampleSink { public: - DSDDemod(BasebandSampleSink* sampleSink); - ~DSDDemod(); + class MsgConfigureDSDDemod : public Message { + MESSAGE_CLASS_DECLARATION - void configure(MessageQueue* messageQueue, - int rfBandwidth, - int demodGain, - int volume, - int baudRate, - int fmDeviation, - int squelchGate, - Real squelch, - bool audioMute, - bool enableCosineFiltering, - bool syncOrConstellation, - bool slot1On, - bool slot2On, - bool tdmaStereo, - bool pllLock, - bool udpCopyAudio, - const QString& udpAddress, - quint16 udpPort, - bool force); + 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); @@ -69,10 +99,6 @@ public: virtual void stop(); virtual bool handleMessage(const Message& cmd); - void registerGUI(DSDDemodGUI *dsdDemodGUI) { - m_dsdDemodGUI = dsdDemodGUI; - } - double getMagSq() { return m_magsq; } bool getSquelchOpen() const { return m_squelchOpen; } @@ -113,180 +139,16 @@ private: {} }; - class MsgConfigureDSDDemod : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getRFBandwidth() const { return m_rfBandwidth; } - int getDemodGain() const { return m_demodGain; } - int getFMDeviation() const { return m_fmDeviation; } - int getVolume() const { return m_volume; } - int getBaudRate() const { return m_baudRate; } - int getSquelchGate() const { return m_squelchGate; } - Real getSquelch() const { return m_squelch; } - bool getAudioMute() const { return m_audioMute; } - bool getEnableCosineFiltering() const { return m_enableCosineFiltering; } - bool getSyncOrConstellation() const { return m_syncOrConstellation; } - bool getSlot1On() const { return m_slot1On; } - bool getSlot2On() const { return m_slot2On; } - bool getTDMAStereo() const { return m_tdmaStereo; } - bool getPLLLock() const { return m_pllLock; } - bool getUDPCopyAudio() const { return m_udpCopyAudio; } - const QString& getUDPAddress() const { return m_udpAddress; } - quint16 getUDPPort() const { return m_udpPort; } - - static MsgConfigureDSDDemod* create(int rfBandwidth, - int demodGain, - int fmDeviation, - int volume, - int baudRate, - int squelchGate, - Real squelch, - bool audioMute, - bool enableCosineFiltering, - bool syncOrConstellation, - bool slot1On, - bool slot2On, - bool tdmaStereo, - bool pllLock, - bool udpCopyAudio, - const QString& udpAddress, - quint16 udpPort, - bool force) - { - return new MsgConfigureDSDDemod(rfBandwidth, - demodGain, - fmDeviation, - volume, - baudRate, - squelchGate, - squelch, - audioMute, - enableCosineFiltering, - syncOrConstellation, - slot1On, - slot2On, - tdmaStereo, - pllLock, - udpCopyAudio, - udpAddress, - udpPort, - force); - } - - private: - Real m_rfBandwidth; - Real m_demodGain; - int m_fmDeviation; - int m_volume; - int m_baudRate; - int m_squelchGate; - Real m_squelch; - bool m_audioMute; - bool m_enableCosineFiltering; - bool m_syncOrConstellation; - bool m_slot1On; - bool m_slot2On; - bool m_tdmaStereo; - bool m_pllLock; - bool m_udpCopyAudio; - QString m_udpAddress; - quint16 m_udpPort; - bool m_force; - - MsgConfigureDSDDemod(int rfBandwidth, - int demodGain, - int fmDeviation, - int volume, - int baudRate, - int squelchGate, - Real squelch, - bool audioMute, - bool enableCosineFiltering, - bool syncOrConstellation, - bool slot1On, - bool slot2On, - bool tdmaStereo, - bool pllLock, - bool udpCopyAudio, - const QString& udpAddress, - quint16 udpPort, - bool force) : - Message(), - m_rfBandwidth(rfBandwidth), - m_demodGain(demodGain), - m_fmDeviation(fmDeviation), - m_volume(volume), - m_baudRate(baudRate), - m_squelchGate(squelchGate), - m_squelch(squelch), - m_audioMute(audioMute), - m_enableCosineFiltering(enableCosineFiltering), - m_syncOrConstellation(syncOrConstellation), - m_slot1On(slot1On), - m_slot2On(slot2On), - m_tdmaStereo(tdmaStereo), - m_pllLock(pllLock), - m_udpCopyAudio(udpCopyAudio), - m_udpAddress(udpAddress), - m_udpPort(udpPort), - m_force(force) - { } - }; - enum RateState { RSInitialFill, RSRunning }; - struct Config { - int m_inputSampleRate; - qint64 m_inputFrequencyOffset; - int m_rfBandwidth; - int m_demodGain; - int m_volume; - int m_baudRate; - int m_fmDeviation; - int m_squelchGate; - Real m_squelch; - bool m_audioMute; - quint32 m_audioSampleRate; - bool m_enableCosineFiltering; - bool m_syncOrConstellation; - bool m_slot1On; - bool m_slot2On; - bool m_tdmaStereo; - bool m_pllLock; - bool m_udpCopyAudio; - QString m_udpAddress; - quint16 m_udpPort; + DSDDemodSettings m_settings; - Config() : - m_inputSampleRate(-1), - m_inputFrequencyOffset(0), - m_rfBandwidth(-1), - m_demodGain(-1), - m_volume(-1), - m_baudRate(4800), - m_fmDeviation(1), - m_squelchGate(1), - m_squelch(0), - m_audioMute(false), - m_audioSampleRate(0), - m_enableCosineFiltering(false), - m_syncOrConstellation(false), - m_slot1On(false), - m_slot2On(false), - m_tdmaStereo(false), - m_pllLock(true), - m_udpCopyAudio(false), - m_udpAddress("127.0.0.1"), - m_udpPort(9999) - { } - }; - - Config m_config; - Config m_running; + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; NCO m_nco; Interpolator m_interpolator; @@ -299,7 +161,6 @@ private: double m_squelchLevel; bool m_squelchOpen; - Real m_lastArgument; MovingAverage m_movingAverage; double m_magsq; double m_magsqSum; @@ -320,7 +181,6 @@ private: bool m_scopeEnabled; DSDDecoder m_dsdDecoder; - DSDDemodGUI *m_dsdDemodGUI; QMutex m_settingsMutex; PhaseDiscriminators m_phaseDiscri; @@ -328,7 +188,7 @@ private: static const int m_udpBlockSize; - void apply(bool force = false); + void applySettings(DSDDemodSettings& settings, bool force = false); }; #endif // INCLUDE_DSDDEMOD_H diff --git a/plugins/channelrx/demoddsd/dsddemodbaudrates.cpp b/plugins/channelrx/demoddsd/dsddemodbaudrates.cpp new file mode 100644 index 000000000..5dc099b61 --- /dev/null +++ b/plugins/channelrx/demoddsd/dsddemodbaudrates.cpp @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "dsddemodbaudrates.h" + +unsigned int DSDDemodBaudRates::m_rates[] = {2400, 4800}; +unsigned int DSDDemodBaudRates::m_nb_rates = 2; +unsigned int DSDDemodBaudRates::m_defaultRateIndex = 1; // 4800 bauds + +unsigned int DSDDemodBaudRates::getRate(unsigned int rate_index) +{ + if (rate_index < m_nb_rates) + { + return m_rates[rate_index]; + } + else + { + return m_rates[m_defaultRateIndex]; + } +} + +unsigned int DSDDemodBaudRates::getRateIndex(unsigned int rate) +{ + for (unsigned int i=0; i < m_nb_rates; i++) + { + if (rate == m_rates[i]) + { + return i; + } + } + + return m_defaultRateIndex; +} + + + diff --git a/plugins/channelrx/demoddsd/dsddemodbaudrates.h b/plugins/channelrx/demoddsd/dsddemodbaudrates.h new file mode 100644 index 000000000..2dbd18a8f --- /dev/null +++ b/plugins/channelrx/demoddsd/dsddemodbaudrates.h @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODBAUDRATES_H_ +#define PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODBAUDRATES_H_ + +class DSDDemodBaudRates +{ +public: + static unsigned int getRate(unsigned int rate_index); + static unsigned int getRateIndex(unsigned int rate); + static unsigned int getDefaultRate() { return m_rates[m_defaultRateIndex]; } + static unsigned int getDefaultRateIndex() { return m_defaultRateIndex; } + static unsigned int getNbRates() { return m_nb_rates; } +private: + static unsigned int m_nb_rates; + static unsigned int m_rates[2]; + static unsigned int m_defaultRateIndex; +}; + +#endif /* PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODBAUDRATES_H_ */ diff --git a/plugins/channelrx/demoddsd/dsddemodgui.cpp b/plugins/channelrx/demoddsd/dsddemodgui.cpp index 2015c6ce1..dd42a01e2 100644 --- a/plugins/channelrx/demoddsd/dsddemodgui.cpp +++ b/plugins/channelrx/demoddsd/dsddemodgui.cpp @@ -34,14 +34,11 @@ #include "dsp/dspengine.h" #include "mainwindow.h" +#include "dsddemodbaudrates.h" #include "dsddemod.h" const QString DSDDemodGUI::m_channelID = "sdrangel.channel.dsddemod"; -unsigned int DSDDemodBaudRates::m_rates[] = {2400, 4800}; -unsigned int DSDDemodBaudRates::m_nb_rates = 2; -unsigned int DSDDemodBaudRates::m_defaultRateIndex = 1; // 4800 bauds - DSDDemodGUI* DSDDemodGUI::create(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI) { DSDDemodGUI* gui = new DSDDemodGUI(pluginAPI, deviceAPI); @@ -76,112 +73,31 @@ void DSDDemodGUI::setCenterFrequency(qint64 centerFrequency) void DSDDemodGUI::resetToDefaults() { + m_settings.resetToDefaults(); blockApplySettings(true); - - ui->rfBW->setValue(100); // x100 Hz - ui->demodGain->setValue(100); // 100ths - ui->fmDeviation->setValue(50); // x100 Hz - ui->volume->setValue(20); // /10.0 - ui->baudRate->setCurrentIndex(DSDDemodBaudRates::getDefaultRateIndex()); - ui->squelchGate->setValue(5); - ui->squelch->setValue(-40); - ui->deltaFrequency->setValue(0); - ui->symbolPLLLock->setChecked(true); - + displaySettings(); blockApplySettings(false); applySettings(); } QByteArray DSDDemodGUI::serialize() const { - SimpleSerializer s(1); - s.writeS32(1, m_channelMarker.getCenterFrequency()); - s.writeS32(2, ui->rfBW->value()); - s.writeS32(3, ui->demodGain->value()); - s.writeS32(4, ui->fmDeviation->value()); - s.writeS32(5, ui->squelch->value()); - s.writeU32(7, m_channelMarker.getColor().rgb()); - s.writeS32(8, ui->squelchGate->value()); - s.writeS32(9, ui->volume->value()); - s.writeBlob(10, ui->scopeGUI->serialize()); - s.writeS32(11, ui->baudRate->currentIndex()); - s.writeBool(12, m_enableCosineFiltering); - s.writeBool(13, m_syncOrConstellation); - s.writeBool(14, m_slot1On); - s.writeBool(15, m_slot2On); - s.writeBool(16, m_tdmaStereo); - s.writeBlob(17, m_channelMarker.serialize()); - return s.final(); + return m_settings.serialize(); } bool DSDDemodGUI::deserialize(const QByteArray& data) { - SimpleDeserializer d(data); - - if (!d.isValid()) - { - resetToDefaults(); - return false; - } - - if (d.getVersion() == 1) - { - QByteArray bytetmp; - QString strtmp; - quint32 u32tmp; - qint32 tmp; - - blockApplySettings(true); - m_channelMarker.blockSignals(true); - - d.readBlob(17, &bytetmp); - m_channelMarker.deserialize(bytetmp); - - d.readS32(1, &tmp, 0); - m_channelMarker.setCenterFrequency(tmp); - d.readS32(2, &tmp, 4); - ui->rfBW->setValue(tmp); - d.readS32(3, &tmp, 3); - ui->demodGain->setValue(tmp); - d.readS32(4, &tmp, 20); - ui->fmDeviation->setValue(tmp); - d.readS32(5, &tmp, -40); - ui->squelch->setValue(tmp); - - if(d.readU32(7, &u32tmp)) - { - m_channelMarker.setColor(u32tmp); - } - - d.readS32(8, &tmp, 5); - ui->squelchGate->setValue(tmp); - d.readS32(9, &tmp, 20); - ui->volume->setValue(tmp); - d.readBlob(10, &bytetmp); - ui->scopeGUI->deserialize(bytetmp); - d.readS32(11, &tmp, 20); - ui->baudRate->setCurrentIndex(tmp); - d.readBool(12, &m_enableCosineFiltering, false); - d.readBool(13, &m_syncOrConstellation, false); - d.readBool(14, &m_slot1On, false); - d.readBool(15, &m_slot2On, false); - d.readBool(16, &m_tdmaStereo, false); - - this->setWindowTitle(m_channelMarker.getTitle()); - displayUDPAddress(); - - blockApplySettings(false); - m_channelMarker.blockSignals(false); - - updateMyPosition(); // we do it also here to be able to refresh with latest settings - applySettings(true); - return true; - } - else - { - resetToDefaults(); - return false; - } + if (m_settings.deserialize(data)) + { + displaySettings(); + applySettings(true); + return true; + } + else + { + resetToDefaults(); + return false; + } } bool DSDDemodGUI::handleMessage(const Message& message __attribute__((unused))) @@ -192,79 +108,92 @@ bool DSDDemodGUI::handleMessage(const Message& message __attribute__((unused))) void DSDDemodGUI::on_deltaFrequency_changed(qint64 value) { m_channelMarker.setCenterFrequency(value); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); + applySettings(); } void DSDDemodGUI::on_rfBW_valueChanged(int value) { - qDebug() << "DSDDemodGUI::on_rfBW_valueChanged" << value * 100; m_channelMarker.setBandwidth(value * 100); + m_settings.m_rfBandwidth = value * 100.0; + ui->rfBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); applySettings(); } -void DSDDemodGUI::on_demodGain_valueChanged(int value __attribute__((unused))) +void DSDDemodGUI::on_demodGain_valueChanged(int value) { + m_settings.m_demodGain = value / 100.0; + ui->demodGainText->setText(QString("%1").arg(value / 100.0, 0, 'f', 2)); applySettings(); } -void DSDDemodGUI::on_fmDeviation_valueChanged(int value __attribute__((unused))) +void DSDDemodGUI::on_fmDeviation_valueChanged(int value) { + m_settings.m_fmDeviation = value * 100.0; + ui->fmDeviationText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); applySettings(); } -void DSDDemodGUI::on_volume_valueChanged(int value __attribute__((unused))) +void DSDDemodGUI::on_volume_valueChanged(int value) { + m_settings.m_volume= value / 10.0; + ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1)); applySettings(); } -void DSDDemodGUI::on_baudRate_currentIndexChanged(int index __attribute__((unused))) +void DSDDemodGUI::on_baudRate_currentIndexChanged(int index) { + m_settings.m_baudRate = DSDDemodBaudRates::getRate(index); applySettings(); } void DSDDemodGUI::on_enableCosineFiltering_toggled(bool enable) { - m_enableCosineFiltering = enable; + m_settings.m_enableCosineFiltering = enable; applySettings(); } void DSDDemodGUI::on_syncOrConstellation_toggled(bool checked) { - m_syncOrConstellation = checked; + m_settings.m_syncOrConstellation = checked; applySettings(); } void DSDDemodGUI::on_slot1On_toggled(bool checked) { - m_slot1On = checked; + m_settings.m_slot1On = checked; applySettings(); } void DSDDemodGUI::on_slot2On_toggled(bool checked) { - m_slot2On = checked; + m_settings.m_slot2On = checked; applySettings(); } void DSDDemodGUI::on_tdmaStereoSplit_toggled(bool checked) { - m_tdmaStereo = checked; + m_settings.m_tdmaStereo = checked; applySettings(); } -void DSDDemodGUI::on_squelchGate_valueChanged(int value __attribute__((unused))) +void DSDDemodGUI::on_squelchGate_valueChanged(int value) { + m_settings.m_squelchGate = value; + ui->squelchGateText->setText(QString("%1").arg(value * 10.0, 0, 'f', 0)); applySettings(); } void DSDDemodGUI::on_squelch_valueChanged(int value) { ui->squelchText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_squelch = value / 10.0; applySettings(); } void DSDDemodGUI::on_audioMute_toggled(bool checked) { - m_audioMute = checked; + m_settings.m_audioMute = checked; applySettings(); } @@ -275,11 +204,13 @@ void DSDDemodGUI::on_symbolPLLLock_toggled(bool checked) } else { ui->symbolPLLLock->setStyleSheet("QToolButton { background:rgb(53,53,53); }"); } + m_settings.m_pllLock = checked; applySettings(); } -void DSDDemodGUI::on_udpOutput_toggled(bool checked __attribute__((unused))) +void DSDDemodGUI::on_udpOutput_toggled(bool checked) { + m_settings.m_udpCopyAudio = checked; applySettings(); } @@ -322,8 +253,9 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); m_scopeVis = new ScopeVis(ui->glScope); - m_dsdDemod = new DSDDemod(m_scopeVis); - m_dsdDemod->registerGUI(this); + m_dsdDemod = new DSDDemod(m_deviceAPI); + m_dsdDemod->setScopeSink(m_scopeVis); + m_dsdDemod->setMessageQueueToGUI(getInputMessageQueue()); ui->glScope->setSampleRate(48000); m_scopeVis->setSampleRate(48000); @@ -339,11 +271,7 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999); ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue); - m_channelizer = new DownChannelizer(m_dsdDemod); - m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); - m_deviceAPI->addThreadedSink(m_threadedChannelizer); - //m_channelMarker = new ChannelMarker(this); m_channelMarker.setTitle(windowTitle()); m_channelMarker.setColor(Qt::cyan); m_channelMarker.setBandwidth(10000); @@ -358,7 +286,11 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope); + m_settings.setChannelMarker(&m_channelMarker); + m_settings.setScopeGUI(ui->scopeGUI); + updateMyPosition(); + displaySettings(); displayUDPAddress(); applySettings(true); } @@ -366,11 +298,7 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg DSDDemodGUI::~DSDDemodGUI() { m_deviceAPI->removeChannelInstance(this); - m_deviceAPI->removeThreadedSink(m_threadedChannelizer); - delete m_threadedChannelizer; - delete m_channelizer; delete m_dsdDemod; - //delete m_channelMarker; delete ui; } @@ -392,49 +320,65 @@ void DSDDemodGUI::displayUDPAddress() ui->udpOutput->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort())); } +void DSDDemodGUI::displaySettings() +{ + blockApplySettings(true); + + m_channelMarker.blockSignals(true); + m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); + m_channelMarker.setUDPAddress(m_settings.m_udpAddress); + m_channelMarker.setUDPSendPort(m_settings.m_udpPort); + m_channelMarker.setColor(m_settings.m_rgbColor); + this->setWindowTitle(m_channelMarker.getTitle()); + setTitleColor(m_settings.m_rgbColor); + m_channelMarker.blockSignals(false); + + ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); + + ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0); + ui->rfBWText->setText(QString("%1k").arg(ui->rfBW->value() / 10.0, 0, 'f', 1)); + + ui->fmDeviation->setValue(m_settings.m_fmDeviation / 100.0); + ui->fmDeviationText->setText(QString("%1k").arg(ui->fmDeviation->value() / 10.0, 0, 'f', 1)); + + ui->squelch->setValue(m_settings.m_squelch * 10.0); + ui->squelchText->setText(QString("%1").arg(ui->squelch->value() / 10.0, 0, 'f', 1)); + + ui->squelchGate->setValue(m_settings.m_squelchGate); + ui->squelchGateText->setText(QString("%1").arg(ui->squelchGate->value() * 10.0, 0, 'f', 0)); + + ui->demodGain->setValue(m_settings.m_demodGain * 100.0); + ui->demodGainText->setText(QString("%1").arg(ui->demodGain->value() / 100.0, 0, 'f', 2)); + + ui->volume->setValue(m_settings.m_volume * 10.0); + ui->volumeText->setText(QString("%1").arg(ui->volume->value() / 10.0, 0, 'f', 1)); + + ui->enableCosineFiltering->setChecked(m_settings.m_enableCosineFiltering); + ui->syncOrConstellation->setChecked(m_settings.m_syncOrConstellation); + ui->slot1On->setChecked(m_settings.m_slot1On); + ui->slot2On->setChecked(m_settings.m_slot2On); + ui->tdmaStereoSplit->setChecked(m_settings.m_tdmaStereo); + ui->audioMute->setChecked(m_settings.m_audioMute); + ui->udpOutput->setChecked(m_settings.m_udpCopyAudio); + ui->symbolPLLLock->setChecked(m_settings.m_pllLock); + + ui->baudRate->setCurrentIndex(DSDDemodBaudRates::getRateIndex(m_settings.m_baudRate)); + + blockApplySettings(false); +} + void DSDDemodGUI::applySettings(bool force) { if (m_doApplySettings) { qDebug() << "DSDDemodGUI::applySettings"; - setTitleColor(m_channelMarker.getColor()); + DSDDemod::MsgConfigureChannelizer* channelConfigMsg = DSDDemod::MsgConfigureChannelizer::create( + 48000, m_channelMarker.getCenterFrequency()); + m_dsdDemod->getInputMessageQueue()->push(channelConfigMsg); - m_channelizer->configure(m_channelizer->getInputMessageQueue(), - 48000, - m_channelMarker.getCenterFrequency()); - - ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); - ui->rfBWText->setText(QString("%1k").arg(ui->rfBW->value() / 10.0, 0, 'f', 1)); - ui->demodGainText->setText(QString("%1").arg(ui->demodGain->value() / 100.0, 0, 'f', 2)); - ui->fmDeviationText->setText(QString("%1k").arg(ui->fmDeviation->value() / 10.0, 0, 'f', 1)); - ui->squelchGateText->setText(QString("%1").arg(ui->squelchGate->value() * 10.0, 0, 'f', 0)); - ui->volumeText->setText(QString("%1").arg(ui->volume->value() / 10.0, 0, 'f', 1)); - ui->enableCosineFiltering->setChecked(m_enableCosineFiltering); - ui->syncOrConstellation->setChecked(m_syncOrConstellation); - ui->slot1On->setChecked(m_slot1On); - ui->slot2On->setChecked(m_slot2On); - ui->tdmaStereoSplit->setChecked(m_tdmaStereo); - - m_dsdDemod->configure(m_dsdDemod->getInputMessageQueue(), - ui->rfBW->value(), - ui->demodGain->value(), - ui->fmDeviation->value(), - ui->volume->value(), - DSDDemodBaudRates::getRate(ui->baudRate->currentIndex()), - ui->squelchGate->value(), // in 10ths of ms - ui->squelch->value(), - ui->audioMute->isChecked(), - m_enableCosineFiltering, - m_syncOrConstellation, - m_slot1On, - m_slot2On, - m_tdmaStereo, - ui->symbolPLLLock->isChecked(), - ui->udpOutput->isChecked(), - m_channelMarker.getUDPAddress(), - m_channelMarker.getUDPSendPort(), - force); + DSDDemod::MsgConfigureDSDDemod* message = DSDDemod::MsgConfigureDSDDemod::create( m_settings, force); + m_dsdDemod->getInputMessageQueue()->push(message); } } @@ -683,28 +627,3 @@ void DSDDemodGUI::tick() m_tickCount++; } - -unsigned int DSDDemodBaudRates::getRate(unsigned int rate_index) -{ - if (rate_index < m_nb_rates) - { - return m_rates[rate_index]; - } - else - { - return m_rates[m_defaultRateIndex]; - } -} - -unsigned int DSDDemodBaudRates::getRateIndex(unsigned int rate) -{ - for (unsigned int i=0; i < m_nb_rates; i++) - { - if (rate == m_rates[i]) - { - return i; - } - } - - return m_defaultRateIndex; -} diff --git a/plugins/channelrx/demoddsd/dsddemodgui.h b/plugins/channelrx/demoddsd/dsddemodgui.h index 390a835ed..add6e5b83 100644 --- a/plugins/channelrx/demoddsd/dsddemodgui.h +++ b/plugins/channelrx/demoddsd/dsddemodgui.h @@ -18,20 +18,20 @@ #ifndef INCLUDE_DSDDEMODGUI_H #define INCLUDE_DSDDEMODGUI_H +#include #include #include "gui/rollupwidget.h" #include "dsp/dsptypes.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" +#include "dsddemodsettings.h" + class PluginAPI; class DeviceSourceAPI; -class ThreadedBasebandSampleSink; -class DownChannelizer; class ScopeVis; class DSDDemod; @@ -39,7 +39,7 @@ namespace Ui { class DSDDemodGUI; } -class DSDDemodGUI : public RollupWidget, public PluginInstanceUI { +class DSDDemodGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -96,12 +96,11 @@ private: PluginAPI* m_pluginAPI; DeviceSourceAPI* m_deviceAPI; ChannelMarker m_channelMarker; + DSDDemodSettings m_settings; bool m_doApplySettings; char m_formatStatusText[82+1]; //!< Fixed signal format dependent status text SignalFormat m_signalFormat; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; ScopeVis* m_scopeVis; DSDDemod* m_dsdDemod; @@ -124,6 +123,7 @@ private: void blockApplySettings(bool block); void applySettings(bool force = false); + void displaySettings(); void updateMyPosition(); void displayUDPAddress(); @@ -131,18 +131,4 @@ private: void enterEvent(QEvent*); }; -class DSDDemodBaudRates -{ -public: - static unsigned int getRate(unsigned int rate_index); - static unsigned int getRateIndex(unsigned int rate); - static unsigned int getDefaultRate() { return m_rates[m_defaultRateIndex]; } - static unsigned int getDefaultRateIndex() { return m_defaultRateIndex; } - static unsigned int getNbRates(); -private: - static unsigned int m_nb_rates; - static unsigned int m_rates[2]; - static unsigned int m_defaultRateIndex; -}; - #endif // INCLUDE_DSDDEMODGUI_H diff --git a/plugins/channelrx/demoddsd/dsddemodplugin.cpp b/plugins/channelrx/demoddsd/dsddemodplugin.cpp index a3d1c9c4b..2c1de0032 100644 --- a/plugins/channelrx/demoddsd/dsddemodplugin.cpp +++ b/plugins/channelrx/demoddsd/dsddemodplugin.cpp @@ -24,7 +24,7 @@ const PluginDescriptor DSDDemodPlugin::m_pluginDescriptor = { QString("DSD Demodulator"), - QString("3.6.1"), + QString("3.7.3"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -50,7 +50,7 @@ void DSDDemodPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(DSDDemodGUI::m_channelID, this); } -PluginInstanceUI* DSDDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* DSDDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == DSDDemodGUI::m_channelID) { diff --git a/plugins/channelrx/demoddsd/dsddemodplugin.h b/plugins/channelrx/demoddsd/dsddemodplugin.h index 835a85508..ee80b5033 100644 --- a/plugins/channelrx/demoddsd/dsddemodplugin.h +++ b/plugins/channelrx/demoddsd/dsddemodplugin.h @@ -34,7 +34,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demoddsd/dsddemodsettings.cpp b/plugins/channelrx/demoddsd/dsddemodsettings.cpp new file mode 100644 index 000000000..6d409c2b3 --- /dev/null +++ b/plugins/channelrx/demoddsd/dsddemodsettings.cpp @@ -0,0 +1,144 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB. // +// // +// This program is free som_udpCopyAudioftware; 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 + +#include "dsp/dspengine.h" +#include "util/simpleserializer.h" +#include "settings/serializable.h" +#include "dsddemodsettings.h" + +DSDDemodSettings::DSDDemodSettings() : + m_channelMarker(0), + m_scopeGUI(0) +{ + resetToDefaults(); +} + +void DSDDemodSettings::resetToDefaults() +{ + m_inputSampleRate = 96000; + m_inputFrequencyOffset = 0; + m_rfBandwidth = 12500.0; + m_fmDeviation = 5000.0; + m_demodGain = 1.25; + m_volume = 2.0; + m_baudRate = 4800; + m_squelchGate = 5; // 10s of ms at 48000 Hz sample rate. Corresponds to 2400 for AGC attack + m_squelch = -40.0; + m_audioMute = false; + m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); + m_enableCosineFiltering = false; + m_syncOrConstellation = false; + m_slot1On = true; + m_slot2On = false; + m_tdmaStereo = false; + m_pllLock = true; + m_udpCopyAudio = false; + m_udpAddress = "127.0.0.1"; + m_udpPort = 9999; + m_rgbColor = QColor(0, 255, 255).rgb(); +} + +QByteArray DSDDemodSettings::serialize() const +{ + SimpleSerializer s(1); + s.writeS32(1, m_inputFrequencyOffset); + s.writeS32(2, m_rfBandwidth/100.0); + s.writeS32(3, m_demodGain*100.0); + s.writeS32(4, m_fmDeviation/100.0); + s.writeS32(5, m_squelch*10.0); + s.writeS32(6, m_inputSampleRate); + s.writeU32(7, m_rgbColor); + s.writeS32(8, m_squelchGate); + s.writeS32(9, m_volume*10.0); + + if (m_scopeGUI) { + s.writeBlob(10, m_scopeGUI->serialize()); + } + + s.writeS32(11, m_baudRate); + s.writeBool(12, m_enableCosineFiltering); + s.writeBool(13, m_syncOrConstellation); + s.writeBool(14, m_slot1On); + s.writeBool(15, m_slot2On); + s.writeBool(16, m_tdmaStereo); + + if (m_channelMarker) { + s.writeBlob(17, m_channelMarker->serialize()); + } + + return s.final(); +} + +bool DSDDemodSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 1) + { + QByteArray bytetmp; + QString strtmp; + qint32 tmp; + + if (m_channelMarker) { + d.readBlob(17, &bytetmp); + m_channelMarker->deserialize(bytetmp); + } + + d.readS32(1, &tmp, 0); + m_inputFrequencyOffset = tmp; + d.readS32(2, &tmp, 125); + m_rfBandwidth = tmp * 100.0; + d.readS32(3, &tmp, 125); + m_demodGain = tmp / 100.0; + d.readS32(4, &tmp, 50); + m_fmDeviation = tmp * 100.0; + d.readS32(5, &tmp, -400); + m_squelch = tmp / 10.0; + d.readS32(6, &m_inputSampleRate, 96000); + d.readU32(7, &m_rgbColor); + d.readS32(8, &m_squelchGate, 5); + d.readS32(9, &tmp, 20); + m_volume = tmp / 10.0; + + if (m_scopeGUI) { + d.readBlob(10, &bytetmp); + m_scopeGUI->deserialize(bytetmp); + } + + d.readS32(11, &m_baudRate, 4800); + d.readBool(12, &m_enableCosineFiltering, false); + d.readBool(13, &m_syncOrConstellation, false); + d.readBool(14, &m_slot1On, false); + d.readBool(15, &m_slot2On, false); + d.readBool(16, &m_tdmaStereo, false); + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + diff --git a/plugins/channelrx/demoddsd/dsddemodsettings.h b/plugins/channelrx/demoddsd/dsddemodsettings.h new file mode 100644 index 000000000..d8729a222 --- /dev/null +++ b/plugins/channelrx/demoddsd/dsddemodsettings.h @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODSETTINGS_H_ +#define PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODSETTINGS_H_ + +#include + +class Serializable; + +struct DSDDemodSettings +{ + int m_inputSampleRate; + qint64 m_inputFrequencyOffset; + Real m_rfBandwidth; + Real m_fmDeviation; + Real m_demodGain; + Real m_volume; + int m_baudRate; + int m_squelchGate; + Real m_squelch; + bool m_audioMute; + quint32 m_audioSampleRate; + bool m_enableCosineFiltering; + bool m_syncOrConstellation; + bool m_slot1On; + bool m_slot2On; + bool m_tdmaStereo; + bool m_pllLock; + bool m_udpCopyAudio; + QString m_udpAddress; + quint16 m_udpPort; + quint32 m_rgbColor; + + Serializable *m_channelMarker; + Serializable *m_scopeGUI; + + DSDDemodSettings(); + void resetToDefaults(); + void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } + void setScopeGUI(Serializable *scopeGUI) { m_scopeGUI = scopeGUI; } + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + + +#endif /* PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODSETTINGS_H_ */ diff --git a/plugins/channelrx/demodlora/lorademodgui.h b/plugins/channelrx/demodlora/lorademodgui.h index 43884380c..a48c4e221 100644 --- a/plugins/channelrx/demodlora/lorademodgui.h +++ b/plugins/channelrx/demodlora/lorademodgui.h @@ -1,9 +1,9 @@ #ifndef INCLUDE_LoRaDEMODGUI_H #define INCLUDE_LoRaDEMODGUI_H +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #define BANDWIDTHSTRING {7813,15625,20833,31250,62500} @@ -19,7 +19,7 @@ namespace Ui { class LoRaDemodGUI; } -class LoRaDemodGUI : public RollupWidget, public PluginInstanceUI { +class LoRaDemodGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channelrx/demodlora/loraplugin.cpp b/plugins/channelrx/demodlora/loraplugin.cpp index 2f93c2ffb..0d877a716 100644 --- a/plugins/channelrx/demodlora/loraplugin.cpp +++ b/plugins/channelrx/demodlora/loraplugin.cpp @@ -33,7 +33,7 @@ void LoRaPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(LoRaDemodGUI::m_channelID, this); } -PluginInstanceUI* LoRaPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* LoRaPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == LoRaDemodGUI::m_channelID) { diff --git a/plugins/channelrx/demodlora/loraplugin.h b/plugins/channelrx/demodlora/loraplugin.h index 5fa25822d..412419c10 100644 --- a/plugins/channelrx/demodlora/loraplugin.h +++ b/plugins/channelrx/demodlora/loraplugin.h @@ -17,7 +17,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodnfm/nfmdemodgui.h b/plugins/channelrx/demodnfm/nfmdemodgui.h index e986b143b..7b8cbd5f5 100644 --- a/plugins/channelrx/demodnfm/nfmdemodgui.h +++ b/plugins/channelrx/demodnfm/nfmdemodgui.h @@ -1,11 +1,11 @@ #ifndef INCLUDE_NFMDEMODGUI_H #define INCLUDE_NFMDEMODGUI_H +#include #include "gui/rollupwidget.h" #include "dsp/dsptypes.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" class PluginAPI; @@ -19,7 +19,7 @@ namespace Ui { class NFMDemodGUI; } -class NFMDemodGUI : public RollupWidget, public PluginInstanceUI { +class NFMDemodGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channelrx/demodnfm/nfmplugin.cpp b/plugins/channelrx/demodnfm/nfmplugin.cpp index f0f218f1b..c66b64a14 100644 --- a/plugins/channelrx/demodnfm/nfmplugin.cpp +++ b/plugins/channelrx/demodnfm/nfmplugin.cpp @@ -33,7 +33,7 @@ void NFMPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(NFMDemodGUI::m_channelID, this); } -PluginInstanceUI* NFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* NFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == NFMDemodGUI::m_channelID) { NFMDemodGUI* gui = NFMDemodGUI::create(m_pluginAPI, deviceAPI); diff --git a/plugins/channelrx/demodnfm/nfmplugin.h b/plugins/channelrx/demodnfm/nfmplugin.h index ff2e822ce..10eb6b131 100644 --- a/plugins/channelrx/demodnfm/nfmplugin.h +++ b/plugins/channelrx/demodnfm/nfmplugin.h @@ -17,7 +17,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodssb/CMakeLists.txt b/plugins/channelrx/demodssb/CMakeLists.txt index f1b1449f1..53cf45296 100644 --- a/plugins/channelrx/demodssb/CMakeLists.txt +++ b/plugins/channelrx/demodssb/CMakeLists.txt @@ -3,12 +3,14 @@ project(ssb) set(ssb_SOURCES ssbdemod.cpp ssbdemodgui.cpp + ssbdemodsettings.cpp ssbplugin.cpp ) set(ssb_HEADERS ssbdemod.h ssbdemodgui.h + ssbdemodsettings.h ssbplugin.h ) diff --git a/plugins/channelrx/demodssb/demodssb.pro b/plugins/channelrx/demodssb/demodssb.pro index d65971658..6b347d66f 100644 --- a/plugins/channelrx/demodssb/demodssb.pro +++ b/plugins/channelrx/demodssb/demodssb.pro @@ -25,10 +25,12 @@ CONFIG(Debug):build_subdir = debug SOURCES += ssbdemod.cpp\ ssbdemodgui.cpp\ + ssbdemodsettings.cpp\ ssbplugin.cpp HEADERS += ssbdemod.h\ ssbdemodgui.h\ + ssbdemodsettings.h\ ssbplugin.h FORMS += ssbdemodgui.ui diff --git a/plugins/channelrx/demodssb/ssbdemod.cpp b/plugins/channelrx/demodssb/ssbdemod.cpp index 387b7bdb4..2a01da180 100644 --- a/plugins/channelrx/demodssb/ssbdemod.cpp +++ b/plugins/channelrx/demodssb/ssbdemod.cpp @@ -16,19 +16,26 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "ssbdemod.h" -#include #include #include #include + #include "audio/audiooutput.h" #include "dsp/dspengine.h" +#include +#include "dsp/threadedbasebandsamplesink.h" +#include "device/devicesourceapi.h" #include "util/db.h" -MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemod, Message) +#include "ssbdemod.h" -SSBDemod::SSBDemod(BasebandSampleSink* sampleSink) : +MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemod, Message) +MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemodPrivate, Message) +MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureChannelizer, Message) + +SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), m_audioBinaual(false), m_audioFlipChannels(false), m_dsb(false), @@ -40,7 +47,7 @@ SSBDemod::SSBDemod(BasebandSampleSink* sampleSink) : m_agcPowerThreshold(1e-2), m_agcThresholdGate(0), m_audioActive(false), - m_sampleSink(sampleSink), + m_sampleSink(0), m_audioFifo(24000), m_settingsMutex(QMutex::Recursive) { @@ -75,7 +82,13 @@ SSBDemod::SSBDemod(BasebandSampleSink* sampleSink) : SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, ssbFftLen); DSBFilter = new fftfilt((2.0f * m_Bandwidth) / m_audioSampleRate, 2 * ssbFftLen); + m_channelizer = new DownChannelizer(this); + m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); + m_deviceAPI->addThreadedSink(m_threadedChannelizer); + DSPEngine::instance()->addAudioSink(&m_audioFifo); + + applySettings(m_settings, true); } SSBDemod::~SSBDemod() @@ -84,6 +97,10 @@ SSBDemod::~SSBDemod() if (DSBFilter) delete DSBFilter; DSPEngine::instance()->removeAudioSink(&m_audioFifo); + + m_deviceAPI->removeThreadedSink(m_threadedChannelizer); + delete m_threadedChannelizer; + delete m_channelizer; } void SSBDemod::configure(MessageQueue* messageQueue, @@ -101,7 +118,7 @@ void SSBDemod::configure(MessageQueue* messageQueue, int agcPowerThreshold, int agcThresholdGate) { - Message* cmd = MsgConfigureSSBDemod::create( + Message* cmd = MsgConfigureSSBDemodPrivate::create( Bandwidth, LowCutoff, volume, @@ -262,10 +279,6 @@ void SSBDemod::stop() bool SSBDemod::handleMessage(const Message& cmd) { - float band, lowCutoff; - - qDebug() << "SSBDemod::handleMessage"; - if (DownChannelizer::MsgChannelizerNotification::match(cmd)) { DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; @@ -284,94 +297,48 @@ bool SSBDemod::handleMessage(const Message& cmd) return true; } - else if (MsgConfigureSSBDemod::match(cmd)) - { - MsgConfigureSSBDemod& cfg = (MsgConfigureSSBDemod&) cmd; + else if (MsgConfigureChannelizer::match(cmd)) + { + MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; - m_settingsMutex.lock(); + m_channelizer->configure(m_channelizer->getInputMessageQueue(), + cfg.getSampleRate(), + cfg.getCenterFrequency()); - band = cfg.getBandwidth(); - lowCutoff = cfg.getLoCutoff(); + qDebug() << "SSBDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << cfg.getSampleRate() + << " centerFrequency: " << cfg.getCenterFrequency(); - if (band < 0) { - band = -band; - lowCutoff = -lowCutoff; - m_usb = false; - } else - m_usb = true; + return true; + } + else if (MsgConfigureSSBDemod::match(cmd)) + { + MsgConfigureSSBDemod& cfg = (MsgConfigureSSBDemod&) cmd; - if (band < 100.0f) - { - band = 100.0f; - lowCutoff = 0; - } - m_Bandwidth = band; - m_LowCutoff = lowCutoff; + SSBDemodSettings settings = cfg.getSettings(); - m_interpolator.create(16, m_sampleRate, band * 2.0f); - SSBFilter->create_filter(m_LowCutoff / (float) m_audioSampleRate, m_Bandwidth / (float) m_audioSampleRate); - DSBFilter->create_dsb_filter((2.0f * m_Bandwidth) / (float) m_audioSampleRate); + // These settings are set with DownChannelizer::MsgChannelizerNotification + settings.m_inputSampleRate = m_settings.m_inputSampleRate; + settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset; - m_volume = cfg.getVolume(); - //m_volume *= 2.0; // for 327.68 - m_volume /= 4.0; // for 3276.8 + applySettings(settings, cfg.getForce()); - m_spanLog2 = cfg.getSpanLog2(); - m_audioBinaual = cfg.getAudioBinaural(); - m_audioFlipChannels = cfg.getAudioFlipChannels(); - m_dsb = cfg.getDSB(); - m_audioMute = cfg.getAudioMute(); - m_agcActive = cfg.getAGC(); + qDebug() << "SSBDemod::handleMessage: MsgConfigureSSBDemod:" + << " m_rfBandwidth: " << settings.m_rfBandwidth + << " m_lowCutoff: " << settings.m_lowCutoff + << " m_volume: " << settings.m_volume + << " m_spanLog2: " << settings.m_spanLog2 + << " m_audioBinaual: " << settings.m_audioBinaural + << " m_audioFlipChannels: " << settings.m_audioFlipChannels + << " m_dsb: " << settings.m_dsb + << " m_audioMute: " << settings.m_audioMute + << " m_agcActive: " << settings.m_agc + << " m_agcClamping: " << settings.m_agcClamping + << " m_agcTimeLog2: " << settings.m_agcTimeLog2 + << " agcPowerThreshold: " << settings.m_agcPowerThreshold + << " agcThresholdGate: " << settings.m_agcThresholdGate; - int agcNbSamples = 48 * (1<create_filter(m_LowCutoff / (float) m_audioSampleRate, m_Bandwidth / (float) m_audioSampleRate); + DSBFilter->create_dsb_filter((2.0f * m_Bandwidth) / (float) m_audioSampleRate); + m_settingsMutex.unlock(); + } + + if ((m_settings.m_volume != settings.m_volume) || force) + { + m_volume = settings.m_volume; + m_volume /= 4.0; // for 3276.8 + } + + if ((m_settings.m_agcTimeLog2 != settings.m_agcTimeLog2) || + (m_settings.m_agcPowerThreshold != settings.m_agcPowerThreshold) || + (m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) || + (m_settings.m_agcClamping != settings.m_agcClamping) || force) + { + int agcNbSamples = 48 * (1<setAddress(const_cast(settings.m_udpAddress)); +// m_udpBufferAudio->setPort(settings.m_udpPort); +// } + + m_spanLog2 = settings.m_spanLog2; + m_audioBinaual = settings.m_audioBinaural; + m_audioFlipChannels = settings.m_audioFlipChannels; + m_dsb = settings.m_dsb; + m_audioMute = settings.m_audioMute; + m_agcActive = settings.m_agc; + + m_settings = settings; +} + diff --git a/plugins/channelrx/demodssb/ssbdemod.h b/plugins/channelrx/demodssb/ssbdemod.h index dd6e4f74b..f5b148f3d 100644 --- a/plugins/channelrx/demodssb/ssbdemod.h +++ b/plugins/channelrx/demodssb/ssbdemod.h @@ -18,9 +18,10 @@ #ifndef INCLUDE_SSBDEMOD_H #define INCLUDE_SSBDEMOD_H -#include #include #include + +#include #include "dsp/ncof.h" #include "dsp/interpolator.h" #include "dsp/fftfilt.h" @@ -28,13 +29,66 @@ #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: - SSBDemod(BasebandSampleSink* sampleSink); + 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, @@ -71,7 +125,7 @@ public: } private: - class MsgConfigureSSBDemod : public Message { + class MsgConfigureSSBDemodPrivate : public Message { MESSAGE_CLASS_DECLARATION public: @@ -89,7 +143,7 @@ private: int getAGCPowerThershold() const { return m_agcPowerThreshold; } int getAGCThersholdGate() const { return m_agcThresholdGate; } - static MsgConfigureSSBDemod* create(Real Bandwidth, + static MsgConfigureSSBDemodPrivate* create(Real Bandwidth, Real LowCutoff, Real volume, int spanLog2, @@ -103,7 +157,7 @@ private: int agcPowerThreshold, int agcThresholdGate) { - return new MsgConfigureSSBDemod( + return new MsgConfigureSSBDemodPrivate( Bandwidth, LowCutoff, volume, @@ -134,7 +188,7 @@ private: int m_agcPowerThreshold; int m_agcThresholdGate; - MsgConfigureSSBDemod(Real Bandwidth, + MsgConfigureSSBDemodPrivate(Real Bandwidth, Real LowCutoff, Real volume, int spanLog2, @@ -164,6 +218,11 @@ private: { } }; + DeviceSourceAPI *m_deviceAPI; + ThreadedBasebandSampleSink* m_threadedChannelizer; + DownChannelizer* m_channelizer; + SSBDemodSettings m_settings; + Real m_Bandwidth; Real m_LowCutoff; Real m_volume; @@ -204,6 +263,8 @@ private: 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 2af1b61a4..80ba67b83 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.cpp +++ b/plugins/channelrx/demodssb/ssbdemodgui.cpp @@ -2,12 +2,9 @@ #include "ssbdemodgui.h" #include -#include #include #include -#include "dsp/threadedbasebandsamplesink.h" -#include "ui_ssbdemodgui.h" #include "ui_ssbdemodgui.h" #include "dsp/spectrumvis.h" #include "gui/glspectrum.h" @@ -50,113 +47,36 @@ qint64 SSBDemodGUI::getCenterFrequency() const void SSBDemodGUI::setCenterFrequency(qint64 centerFrequency) { m_channelMarker.setCenterFrequency(centerFrequency); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); applySettings(); } void SSBDemodGUI::resetToDefaults() { - blockApplySettings(true); - - ui->BW->setValue(30); - ui->volume->setValue(30); - ui->deltaFrequency->setValue(0); - ui->spanLog2->setValue(3); - ui->agc->setChecked(false); - ui->agcTimeLog2->setValue(7); - ui->agcPowerThreshold->setValue(-40); - ui->agcThresholdGate->setValue(4); - - blockApplySettings(false); + m_settings.resetToDefaults(); } QByteArray SSBDemodGUI::serialize() const { - SimpleSerializer s(1); - s.writeS32(1, m_channelMarker.getCenterFrequency()); - s.writeS32(2, ui->BW->value()); - s.writeS32(3, ui->volume->value()); - s.writeBlob(4, ui->spectrumGUI->serialize()); - s.writeU32(5, m_channelMarker.getColor().rgb()); - s.writeS32(6, ui->lowCut->value()); - s.writeS32(7, ui->spanLog2->value()); - s.writeBool(8, m_audioBinaural); - s.writeBool(9, m_audioFlipChannels); - s.writeBool(10, m_dsb); - s.writeBool(11, ui->agc->isChecked()); - s.writeS32(12, ui->agcTimeLog2->value()); - s.writeS32(13, ui->agcPowerThreshold->value()); - s.writeS32(14, ui->agcThresholdGate->value()); - s.writeBool(15, ui->agcClamping->isChecked()); - return s.final(); + return m_settings.serialize(); } bool SSBDemodGUI::deserialize(const QByteArray& data) { - SimpleDeserializer d(data); - - if (!d.isValid()) - { - resetToDefaults(); - applySettings(); - return false; - } - - if (d.getVersion() == 1) - { - QByteArray bytetmp; - quint32 u32tmp; - qint32 tmp; - bool booltmp; - - blockApplySettings(true); - m_channelMarker.blockSignals(true); - - d.readS32(1, &tmp, 0); - m_channelMarker.setCenterFrequency(tmp); - d.readS32(2, &tmp, 30); - ui->BW->setValue(tmp); - d.readS32(3, &tmp, 30); - ui->volume->setValue(tmp); - d.readBlob(4, &bytetmp); - ui->spectrumGUI->deserialize(bytetmp); - if(d.readU32(5, &u32tmp)) - m_channelMarker.setColor(u32tmp); - d.readS32(6, &tmp, 3); - ui->lowCut->setValue(tmp); - d.readS32(7, &tmp, 20); - ui->spanLog2->setValue(tmp); - setNewRate(tmp); - d.readBool(8, &m_audioBinaural); - ui->audioBinaural->setChecked(m_audioBinaural); - d.readBool(9, &m_audioFlipChannels); - ui->audioFlipChannels->setChecked(m_audioFlipChannels); - d.readBool(10, &m_dsb); - ui->dsb->setChecked(m_dsb); - d.readBool(11, &booltmp, false); - ui->agc->setChecked(booltmp); - d.readS32(12, &tmp, 7); - ui->agcTimeLog2->setValue(tmp); - d.readS32(13, &tmp, -40); - ui->agcPowerThreshold->setValue(tmp); - d.readS32(14, &tmp, 4); - ui->agcThresholdGate->setValue(tmp); - d.readBool(15, &booltmp, false); - ui->agcClamping->setChecked(booltmp); - + if(m_settings.deserialize(data)) + { + updateChannelMarker(); displaySettings(); - - blockApplySettings(false); - m_channelMarker.blockSignals(false); - - applySettings(); - return true; - } - else - { - resetToDefaults(); - applySettings(); - return false; - } + applySettings(true); // will have true + return true; + } + else + { + m_settings.resetToDefaults(); + displaySettings(); + applySettings(true); // will have true + return false; + } } bool SSBDemodGUI::handleMessage(const Message& message __attribute__((unused))) @@ -172,18 +92,21 @@ void SSBDemodGUI::viewChanged() void SSBDemodGUI::on_audioBinaural_toggled(bool binaural) { m_audioBinaural = binaural; + m_settings.m_audioBinaural = binaural; applySettings(); } void SSBDemodGUI::on_audioFlipChannels_toggled(bool flip) { m_audioFlipChannels = flip; + m_settings.m_audioFlipChannels = flip; applySettings(); } void SSBDemodGUI::on_dsb_toggled(bool dsb) { m_dsb = dsb; + m_settings.m_dsb = dsb; if (m_dsb) { @@ -220,6 +143,8 @@ void SSBDemodGUI::on_dsb_toggled(bool dsb) void SSBDemodGUI::on_deltaFrequency_changed(qint64 value) { m_channelMarker.setCenterFrequency(value); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); + applySettings(); } void SSBDemodGUI::on_BW_valueChanged(int value) @@ -236,6 +161,7 @@ void SSBDemodGUI::on_BW_valueChanged(int value) ui->BWText->setText(tr("%1k").arg(s)); } + m_settings.m_rfBandwidth = value * 100; on_lowCut_valueChanged(m_channelMarker.getLowCutoff()/100); setNewRate(m_spanLog2); } @@ -279,22 +205,26 @@ void SSBDemodGUI::on_lowCut_valueChanged(int value) QString s = QString::number(lowCutoff/1000.0, 'f', 1); ui->lowCutText->setText(tr("%1k").arg(s)); ui->lowCut->setValue(lowCutoff/100); + m_settings.m_lowCutoff = lowCutoff; applySettings(); } void SSBDemodGUI::on_volume_valueChanged(int value) { ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_volume = value / 10.0; applySettings(); } -void SSBDemodGUI::on_agc_toggled(bool checked __attribute((__unused__))) +void SSBDemodGUI::on_agc_toggled(bool checked) { + m_settings.m_agc = checked; applySettings(); } -void SSBDemodGUI::on_agcClamping_toggled(bool checked __attribute((__unused__))) +void SSBDemodGUI::on_agcClamping_toggled(bool checked) { + m_settings.m_agcClamping = checked; applySettings(); } @@ -302,12 +232,14 @@ void SSBDemodGUI::on_agcTimeLog2_valueChanged(int value) { QString s = QString::number((1<agcTimeText->setText(s); + m_settings.m_agcTimeLog2 = value; applySettings(); } void SSBDemodGUI::on_agcPowerThreshold_valueChanged(int value) { displayAGCPowerThreshold(value); + m_settings.m_agcPowerThreshold = value; applySettings(); } @@ -315,12 +247,14 @@ void SSBDemodGUI::on_agcThresholdGate_valueChanged(int value) { QString s = QString::number(value, 'f', 0); ui->agcThresholdGateText->setText(s); + m_settings.m_agcThresholdGate = value; applySettings(); } void SSBDemodGUI::on_audioMute_toggled(bool checked) { m_audioMute = checked; + m_settings.m_audioMute = checked; applySettings(); } @@ -328,6 +262,7 @@ void SSBDemodGUI::on_spanLog2_valueChanged(int value) { if (setNewRate(value)) { + m_settings.m_spanLog2 = value; applySettings(); } @@ -373,10 +308,9 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked())); m_spectrumVis = new SpectrumVis(ui->glSpectrum); - m_ssbDemod = new SSBDemod(m_spectrumVis); - m_channelizer = new DownChannelizer(m_ssbDemod); - m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); - m_deviceAPI->addThreadedSink(m_threadedChannelizer); + m_ssbDemod = new SSBDemod(m_deviceAPI); + m_ssbDemod->setMessageQueueToGUI(getInputMessageQueue()); + m_ssbDemod->setSampleSink(m_spectrumVis); ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03))); ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); @@ -389,13 +323,11 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); - //m_channelMarker = new ChannelMarker(this); - m_channelMarker.setColor(Qt::green); - m_channelMarker.setBandwidth(m_rate); - m_channelMarker.setSidebands(ChannelMarker::usb); - m_channelMarker.setCenterFrequency(0); m_channelMarker.setVisible(true); + m_settings.setChannelMarker(&m_channelMarker); + m_settings.setSpectrumGUI(ui->spectrumGUI); + connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); m_deviceAPI->registerChannelInstance(m_channelID, this); @@ -404,21 +336,16 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum); - resetToDefaults(); displaySettings(); - applySettings(); + applySettings(true); setNewRate(m_spanLog2); } SSBDemodGUI::~SSBDemodGUI() { m_deviceAPI->removeChannelInstance(this); - m_deviceAPI->removeThreadedSink(m_threadedChannelizer); - delete m_threadedChannelizer; - delete m_channelizer; delete m_ssbDemod; delete m_spectrumVis; - //delete m_channelMarker; delete ui; } @@ -454,7 +381,6 @@ bool SSBDemodGUI::setNewRate(int spanLog2) m_channelMarker.setLowCutoff(m_rate); } - QString s = QString::number(m_rate/1000.0, 'f', 1); if (m_dsb) @@ -504,41 +430,101 @@ void SSBDemodGUI::blockApplySettings(bool block) m_doApplySettings = !block; } -void SSBDemodGUI::applySettings() +void SSBDemodGUI::applySettings(bool force) { if (m_doApplySettings) { setTitleColor(m_channelMarker.getColor()); ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); - m_channelizer->configure(m_channelizer->getInputMessageQueue(), - 48000, - m_channelMarker.getCenterFrequency()); + SSBDemod::MsgConfigureChannelizer* channelConfigMsg = SSBDemod::MsgConfigureChannelizer::create( + 48000, m_channelMarker.getCenterFrequency()); + m_ssbDemod->getInputMessageQueue()->push(channelConfigMsg); - m_ssbDemod->configure(m_ssbDemod->getInputMessageQueue(), - ui->BW->value() * 100.0, - ui->lowCut->value() * 100.0, - ui->volume->value() / 10.0, - m_spanLog2, - m_audioBinaural, - m_audioFlipChannels, - m_dsb, - ui->audioMute->isChecked(), - ui->agc->isChecked(), - ui->agcClamping->isChecked(), - ui->agcTimeLog2->value(), - ui->agcPowerThreshold->value(), - ui->agcThresholdGate->value()); + SSBDemod::MsgConfigureSSBDemod* message = SSBDemod::MsgConfigureSSBDemod::create( m_settings, force); + m_ssbDemod->getInputMessageQueue()->push(message); } } void SSBDemodGUI::displaySettings() { - QString s = QString::number((1<agcTimeLog2->value()), 'f', 0); + m_channelMarker.blockSignals(true); + m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth * 2); + m_channelMarker.setLowCutoff(m_settings.m_lowCutoff); + m_channelMarker.setUDPAddress(m_settings.m_udpAddress); + m_channelMarker.setUDPSendPort(m_settings.m_udpPort); + m_channelMarker.setColor(m_settings.m_rgbColor); + setTitleColor(m_settings.m_rgbColor); + + if (m_settings.m_dsb) { + m_channelMarker.setSidebands(ChannelMarker::dsb); + } else { + if (m_settings.m_rfBandwidth < 0) { + m_channelMarker.setSidebands(ChannelMarker::lsb); + } else { + m_channelMarker.setSidebands(ChannelMarker::usb); + } + } + + m_channelMarker.blockSignals(false); + + blockApplySettings(true); + + ui->agc->setChecked(m_settings.m_agc); + ui->agcClamping->setChecked(m_settings.m_agcClamping); + ui->audioBinaural->setChecked(m_settings.m_audioBinaural); + ui->audioFlipChannels->setChecked(m_settings.m_audioFlipChannels); + ui->audioMute->setChecked(m_settings.m_audioMute); + ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); + ui->dsb->setChecked(m_settings.m_dsb); + ui->spanLog2->setValue(m_settings.m_spanLog2); + + ui->BW->setValue(m_settings.m_rfBandwidth / 100.0); + QString s = QString::number(m_settings.m_rfBandwidth/1000.0, 'f', 1); + + if (m_settings.m_dsb) + { + ui->BWText->setText(tr("%1%2k").arg(QChar(0xB1, 0x00)).arg(s)); + } + else + { + ui->BWText->setText(tr("%1k").arg(s)); + } + + ui->lowCut->setValue(m_settings.m_lowCutoff / 100.0); + ui->lowCutText->setText(tr("%1k").arg(m_settings.m_lowCutoff / 1000.0)); + + ui->volume->setValue(m_settings.m_volume * 10.0); + ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1)); + + ui->agcTimeLog2->setValue(m_settings.m_agcTimeLog2); + s = QString::number((1<agcTimeLog2->value()), 'f', 0); ui->agcTimeText->setText(s); + + ui->agcPowerThreshold->setValue(m_settings.m_agcPowerThreshold); displayAGCPowerThreshold(ui->agcPowerThreshold->value()); + + ui->agcThresholdGate->setValue(m_settings.m_agcThresholdGate); s = QString::number(ui->agcThresholdGate->value(), 'f', 0); ui->agcThresholdGateText->setText(s); + + blockApplySettings(false); +} + +void SSBDemodGUI::displayUDPAddress() +{ + //TODO: ui->copyAudioToUDP->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort())); +} + +void SSBDemodGUI::updateChannelMarker() +{ + m_channelMarker.blockSignals(true); + + //m_channelMarker.deserialize(m_settings.m_channelMarkerBytes); + this->setWindowTitle(m_channelMarker.getTitle()); + + m_channelMarker.blockSignals(false); } void SSBDemodGUI::displayAGCPowerThreshold(int value) diff --git a/plugins/channelrx/demodssb/ssbdemodgui.h b/plugins/channelrx/demodssb/ssbdemodgui.h index 0be23c5be..789707e0f 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.h +++ b/plugins/channelrx/demodssb/ssbdemodgui.h @@ -1,18 +1,17 @@ #ifndef INCLUDE_SSBDEMODGUI_H #define INCLUDE_SSBDEMODGUI_H +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" +#include "ssbdemodsettings.h" class PluginAPI; class DeviceSourceAPI; class AudioFifo; -class ThreadedBasebandSampleSink; -class DownChannelizer; class SSBDemod; class SpectrumVis; @@ -20,7 +19,7 @@ namespace Ui { class SSBDemodGUI; } -class SSBDemodGUI : public RollupWidget, public PluginInstanceUI { +class SSBDemodGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -65,6 +64,7 @@ private: PluginAPI* m_pluginAPI; DeviceSourceAPI* m_deviceAPI; ChannelMarker m_channelMarker; + SSBDemodSettings m_settings; bool m_basicSettingsShown; bool m_doApplySettings; int m_rate; @@ -76,8 +76,6 @@ private: bool m_squelchOpen; uint32_t m_tickCount; - ThreadedBasebandSampleSink* m_threadedChannelizer; - DownChannelizer* m_channelizer; SSBDemod* m_ssbDemod; SpectrumVis* m_spectrumVis; MessageQueue m_inputMessageQueue; @@ -89,8 +87,10 @@ private: bool setNewRate(int spanLog2); void blockApplySettings(bool block); - void applySettings(); + void applySettings(bool force = false); void displaySettings(); + void displayUDPAddress(); + void updateChannelMarker(); void displayAGCPowerThreshold(int value); diff --git a/plugins/channelrx/demodssb/ssbdemodsettings.cpp b/plugins/channelrx/demodssb/ssbdemodsettings.cpp new file mode 100644 index 000000000..fd18ea716 --- /dev/null +++ b/plugins/channelrx/demodssb/ssbdemodsettings.cpp @@ -0,0 +1,124 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 + +#include "dsp/dspengine.h" +#include "util/simpleserializer.h" +#include "settings/serializable.h" +#include "ssbdemodsettings.h" + +SSBDemodSettings::SSBDemodSettings() : + m_channelMarker(0), + m_spectrumGUI(0) +{ + resetToDefaults(); +} + +void SSBDemodSettings::resetToDefaults() +{ + m_audioBinaural = false; + m_audioFlipChannels = false; + m_dsb = false; + m_audioMute = false; + m_agc = false; + m_agcClamping = false; + m_agcPowerThreshold = -40; + m_agcThresholdGate = 4; + m_agcTimeLog2 = 7; + m_rfBandwidth = 3000; + m_lowCutoff = 300; + m_volume = 3.0; + m_spanLog2 = 3; + m_inputSampleRate = 96000; + m_inputFrequencyOffset = 0; + m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); + m_rgbColor = QColor(0, 255, 0).rgb(); +} + +QByteArray SSBDemodSettings::serialize() const +{ + SimpleSerializer s(1); + s.writeS32(1, m_inputFrequencyOffset); + s.writeS32(2, m_rfBandwidth / 100.0); + s.writeS32(3, m_volume * 10.0); + + if (m_spectrumGUI) { + s.writeBlob(4, m_spectrumGUI->serialize()); + } + + s.writeU32(5, m_rgbColor); + s.writeS32(6, m_lowCutoff / 100.0); + s.writeS32(7, m_spanLog2); + s.writeBool(8, m_audioBinaural); + s.writeBool(9, m_audioFlipChannels); + s.writeBool(10, m_dsb); + s.writeBool(11, m_agc); + s.writeS32(12, m_agcTimeLog2); + s.writeS32(13, m_agcPowerThreshold); + s.writeS32(14, m_agcThresholdGate); + s.writeBool(15, m_agcClamping); + return s.final(); +} + +bool SSBDemodSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) + { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) + { + QByteArray bytetmp; + qint32 tmp; + QString strtmp; + + d.readS32(1, &m_inputFrequencyOffset, 0); + d.readS32(2, &tmp, 30); + m_rfBandwidth = tmp * 100.0; + d.readS32(3, &tmp, 30); + m_volume = tmp / 10.0; + + if (m_spectrumGUI) { + d.readBlob(4, &bytetmp); + m_spectrumGUI->deserialize(bytetmp); + } + + d.readU32(5, &m_rgbColor); + d.readS32(6, &tmp, 30); + m_lowCutoff = tmp * 100.0; + d.readS32(7, &m_spanLog2, 3); + d.readBool(8, &m_audioBinaural, false); + d.readBool(9, &m_audioFlipChannels, false); + d.readBool(10, &m_dsb, false); + d.readBool(11, &m_agc, false); + d.readS32(12, &m_agcTimeLog2, 7); + d.readS32(13, &m_agcPowerThreshold, -40); + d.readS32(14, &m_agcThresholdGate, 4); + d.readBool(15, &m_agcClamping, false); + + return true; + } + else + { + resetToDefaults(); + return false; + } +} diff --git a/plugins/channelrx/demodssb/ssbdemodsettings.h b/plugins/channelrx/demodssb/ssbdemodsettings.h new file mode 100644 index 000000000..0fc1ca589 --- /dev/null +++ b/plugins/channelrx/demodssb/ssbdemodsettings.h @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 PLUGINS_CHANNELRX_DEMODSSB_SSBDEMODSETTINGS_H_ +#define PLUGINS_CHANNELRX_DEMODSSB_SSBDEMODSETTINGS_H_ + +#include + +class Serializable; + +struct SSBDemodSettings +{ + int m_inputSampleRate; + qint32 m_inputFrequencyOffset; + quint32 m_audioSampleRate; + Real m_rfBandwidth; + 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; + QString m_udpAddress; + quint16 m_udpPort; + quint32 m_rgbColor; + + Serializable *m_channelMarker; + Serializable *m_spectrumGUI; + + SSBDemodSettings(); + void resetToDefaults(); + void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } + void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; } + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + + +#endif /* PLUGINS_CHANNELRX_DEMODSSB_SSBDEMODSETTINGS_H_ */ diff --git a/plugins/channelrx/demodssb/ssbplugin.cpp b/plugins/channelrx/demodssb/ssbplugin.cpp index a7931ccee..3373cdc03 100644 --- a/plugins/channelrx/demodssb/ssbplugin.cpp +++ b/plugins/channelrx/demodssb/ssbplugin.cpp @@ -7,7 +7,7 @@ const PluginDescriptor SSBPlugin::m_pluginDescriptor = { QString("SSB Demodulator"), - QString("3.5.4"), + QString("3.7.3"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -33,7 +33,7 @@ void SSBPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(SSBDemodGUI::m_channelID, this); } -PluginInstanceUI* SSBPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* SSBPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == SSBDemodGUI::m_channelID) { diff --git a/plugins/channelrx/demodssb/ssbplugin.h b/plugins/channelrx/demodssb/ssbplugin.h index 5901a3671..e87d6c03e 100644 --- a/plugins/channelrx/demodssb/ssbplugin.h +++ b/plugins/channelrx/demodssb/ssbplugin.h @@ -17,7 +17,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/demodwfm/wfmdemodgui.h b/plugins/channelrx/demodwfm/wfmdemodgui.h index 630fdc1cc..b322d702f 100644 --- a/plugins/channelrx/demodwfm/wfmdemodgui.h +++ b/plugins/channelrx/demodwfm/wfmdemodgui.h @@ -1,10 +1,10 @@ #ifndef INCLUDE_WFMDEMODGUI_H #define INCLUDE_WFMDEMODGUI_H +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" class PluginAPI; @@ -18,7 +18,7 @@ namespace Ui { class WFMDemodGUI; } -class WFMDemodGUI : public RollupWidget, public PluginInstanceUI { +class WFMDemodGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channelrx/demodwfm/wfmplugin.cpp b/plugins/channelrx/demodwfm/wfmplugin.cpp index bb620ff0f..9cf3fe06f 100644 --- a/plugins/channelrx/demodwfm/wfmplugin.cpp +++ b/plugins/channelrx/demodwfm/wfmplugin.cpp @@ -33,7 +33,7 @@ void WFMPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(WFMDemodGUI::m_channelID, this); } -PluginInstanceUI* WFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* WFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == WFMDemodGUI::m_channelID) { diff --git a/plugins/channelrx/demodwfm/wfmplugin.h b/plugins/channelrx/demodwfm/wfmplugin.h index 84a06fe18..51cfc52ef 100644 --- a/plugins/channelrx/demodwfm/wfmplugin.h +++ b/plugins/channelrx/demodwfm/wfmplugin.h @@ -17,7 +17,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channelrx/tcpsrc/tcpsrcgui.h b/plugins/channelrx/tcpsrc/tcpsrcgui.h index 5986380ef..01e431374 100644 --- a/plugins/channelrx/tcpsrc/tcpsrcgui.h +++ b/plugins/channelrx/tcpsrc/tcpsrcgui.h @@ -1,12 +1,12 @@ #ifndef INCLUDE_TCPSRCGUI_H #define INCLUDE_TCPSRCGUI_H +#include #include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "tcpsrc.h" @@ -22,7 +22,7 @@ namespace Ui { class TCPSrcGUI; } -class TCPSrcGUI : public RollupWidget, public PluginInstanceUI { +class TCPSrcGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channelrx/tcpsrc/tcpsrcplugin.cpp b/plugins/channelrx/tcpsrc/tcpsrcplugin.cpp index 8c5d2b6fe..fc80ff9d0 100644 --- a/plugins/channelrx/tcpsrc/tcpsrcplugin.cpp +++ b/plugins/channelrx/tcpsrc/tcpsrcplugin.cpp @@ -33,7 +33,7 @@ void TCPSrcPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(TCPSrcGUI::m_channelID, this); } -PluginInstanceUI* TCPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* TCPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == TCPSrcGUI::m_channelID) { diff --git a/plugins/channelrx/tcpsrc/tcpsrcplugin.h b/plugins/channelrx/tcpsrc/tcpsrcplugin.h index 19224b73a..a48356ba4 100644 --- a/plugins/channelrx/tcpsrc/tcpsrcplugin.h +++ b/plugins/channelrx/tcpsrc/tcpsrcplugin.h @@ -17,7 +17,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* 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 5a91326b1..3954b6582 100644 --- a/plugins/channelrx/udpsrc/udpsrc.cpp +++ b/plugins/channelrx/udpsrc/udpsrc.cpp @@ -476,7 +476,7 @@ void UDPSrc::apply(bool force) m_outMovingAverage.resize(m_config.m_outputSampleRate * 0.01, 1e-10); // 10 ms } - if ((m_config.m_audioActive != m_config.m_audioActive) || force) + if ((m_config.m_audioActive != m_running.m_audioActive) || force) { if (m_config.m_audioActive) { diff --git a/plugins/channelrx/udpsrc/udpsrcgui.h b/plugins/channelrx/udpsrc/udpsrcgui.h index 2c3973091..55e51243c 100644 --- a/plugins/channelrx/udpsrc/udpsrcgui.h +++ b/plugins/channelrx/udpsrc/udpsrcgui.h @@ -18,11 +18,11 @@ #ifndef INCLUDE_UDPSRCGUI_H #define INCLUDE_UDPSRCGUI_H +#include #include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "udpsrc.h" @@ -38,7 +38,7 @@ namespace Ui { class UDPSrcGUI; } -class UDPSrcGUI : public RollupWidget, public PluginInstanceUI { +class UDPSrcGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channelrx/udpsrc/udpsrcplugin.cpp b/plugins/channelrx/udpsrc/udpsrcplugin.cpp index 1940602f5..f8b5f0cbe 100644 --- a/plugins/channelrx/udpsrc/udpsrcplugin.cpp +++ b/plugins/channelrx/udpsrc/udpsrcplugin.cpp @@ -50,7 +50,7 @@ void UDPSrcPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerRxChannel(UDPSrcGUI::m_channelID, this); } -PluginInstanceUI* UDPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* UDPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI) { if(channelName == UDPSrcGUI::m_channelID) { diff --git a/plugins/channelrx/udpsrc/udpsrcplugin.h b/plugins/channelrx/udpsrc/udpsrcplugin.h index 39707665b..798ecbd9c 100644 --- a/plugins/channelrx/udpsrc/udpsrcplugin.h +++ b/plugins/channelrx/udpsrc/udpsrcplugin.h @@ -34,7 +34,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); + PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channeltx/modam/ammod.cpp b/plugins/channeltx/modam/ammod.cpp index dc724f09b..793389dee 100644 --- a/plugins/channeltx/modam/ammod.cpp +++ b/plugins/channeltx/modam/ammod.cpp @@ -338,7 +338,7 @@ bool AMMod::handleMessage(const Message& cmd) MsgReportFileSourceStreamTiming *report; report = MsgReportFileSourceStreamTiming::create(samplesCount); - getOutputMessageQueue()->push(report); + getMessageQueueToGUI()->push(report); return true; } @@ -415,7 +415,7 @@ void AMMod::openFileStream() MsgReportFileSourceStreamData *report; report = MsgReportFileSourceStreamData::create(m_sampleRate, m_recordLength); - getOutputMessageQueue()->push(report); + getMessageQueueToGUI()->push(report); } void AMMod::seekFileStream(int seekPercentage) diff --git a/plugins/channeltx/modam/ammodgui.cpp b/plugins/channeltx/modam/ammodgui.cpp index 125804ffe..fba939cb6 100644 --- a/plugins/channeltx/modam/ammodgui.cpp +++ b/plugins/channeltx/modam/ammodgui.cpp @@ -178,7 +178,7 @@ void AMModGUI::handleSourceMessages() { Message* message; - while ((message = m_amMod->getOutputMessageQueue()->pop()) != 0) + while ((message = getInputMessageQueue()->pop()) != 0) { if (handleMessage(*message)) { @@ -339,6 +339,7 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pare connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked())); m_amMod = new AMMod(); + m_amMod->setMessageQueueToGUI(getInputMessageQueue()); m_channelizer = new UpChannelizer(m_amMod); m_threadedChannelizer = new ThreadedBasebandSampleSource(m_channelizer, this); //m_pluginAPI->addThreadedSink(m_threadedChannelizer); @@ -372,7 +373,7 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pare applySettings(); - connect(m_amMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); connect(m_amMod, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int))); } diff --git a/plugins/channeltx/modam/ammodgui.h b/plugins/channeltx/modam/ammodgui.h index 6c2c523c2..25ca8e315 100644 --- a/plugins/channeltx/modam/ammodgui.h +++ b/plugins/channeltx/modam/ammodgui.h @@ -17,10 +17,10 @@ #ifndef PLUGINS_CHANNELTX_MODAM_AMMODGUI_H_ #define PLUGINS_CHANNELTX_MODAM_AMMODGUI_H_ +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "ammod.h" @@ -36,7 +36,7 @@ namespace Ui { class AMModGUI; } -class AMModGUI : public RollupWidget, public PluginInstanceUI { +class AMModGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channeltx/modam/ammodplugin.cpp b/plugins/channeltx/modam/ammodplugin.cpp index 96b269ed8..2846d34c6 100644 --- a/plugins/channeltx/modam/ammodplugin.cpp +++ b/plugins/channeltx/modam/ammodplugin.cpp @@ -49,7 +49,7 @@ void AMModPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerTxChannel(AMModGUI::m_channelID, this); } -PluginInstanceUI* AMModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* AMModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) { if(channelName == AMModGUI::m_channelID) { diff --git a/plugins/channeltx/modam/ammodplugin.h b/plugins/channeltx/modam/ammodplugin.h index 9a87c0012..ce74622b7 100644 --- a/plugins/channeltx/modam/ammodplugin.h +++ b/plugins/channeltx/modam/ammodplugin.h @@ -33,7 +33,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); + PluginInstanceGUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channeltx/modatv/atvmod.cpp b/plugins/channeltx/modatv/atvmod.cpp index 046b9a967..643857d92 100644 --- a/plugins/channeltx/modatv/atvmod.cpp +++ b/plugins/channeltx/modatv/atvmod.cpp @@ -385,16 +385,20 @@ void ATVMod::pullVideo(Real& sample) time_t start, end; cv::Mat frame; - MsgReportCameraData *report; - report = MsgReportCameraData::create( - camera.m_cameraNumber, - 0.0f, - camera.m_videoFPSManual, - camera.m_videoFPSManualEnable, - camera.m_videoWidth, - camera.m_videoHeight, - 1); // open splash screen on GUI side - getOutputMessageQueue()->push(report); + if (getMessageQueueToGUI()) + { + MsgReportCameraData *report; + report = MsgReportCameraData::create( + camera.m_cameraNumber, + 0.0f, + camera.m_videoFPSManual, + camera.m_videoFPSManualEnable, + camera.m_videoWidth, + camera.m_videoHeight, + 1); // open splash screen on GUI side + getMessageQueueToGUI()->push(report); + } + int nbFrames = 0; time(&start); @@ -414,15 +418,19 @@ void ATVMod::pullVideo(Real& sample) camera.m_videoFPSCount = camera.m_videoFPSq; camera.m_videoPrevFPSCount = 0; - report = MsgReportCameraData::create( - camera.m_cameraNumber, - camera.m_videoFPS, - camera.m_videoFPSManual, - camera.m_videoFPSManualEnable, - camera.m_videoWidth, - camera.m_videoHeight, - 2); // close splash screen on GUI side - getOutputMessageQueue()->push(report); + if (getMessageQueueToGUI()) + { + MsgReportCameraData *report; + report = MsgReportCameraData::create( + camera.m_cameraNumber, + camera.m_videoFPS, + camera.m_videoFPSManual, + camera.m_videoFPSManualEnable, + camera.m_videoWidth, + camera.m_videoHeight, + 2); // close splash screen on GUI side + getMessageQueueToGUI()->push(report); + } } else if (camera.m_videoFPS == 0.0f) // Hideous hack for windows { @@ -431,16 +439,19 @@ void ATVMod::pullVideo(Real& sample) camera.m_videoFPSCount = camera.m_videoFPSq; camera.m_videoPrevFPSCount = 0; - MsgReportCameraData *report; - report = MsgReportCameraData::create( - camera.m_cameraNumber, - camera.m_videoFPS, - camera.m_videoFPSManual, - camera.m_videoFPSManualEnable, - camera.m_videoWidth, - camera.m_videoHeight, - 0); - getOutputMessageQueue()->push(report); + if (getMessageQueueToGUI()) + { + MsgReportCameraData *report; + report = MsgReportCameraData::create( + camera.m_cameraNumber, + camera.m_videoFPS, + camera.m_videoFPSManual, + camera.m_videoFPSManualEnable, + camera.m_videoWidth, + camera.m_videoHeight, + 0); + getMessageQueueToGUI()->push(report); + } } int fpsIncrement = (int) camera.m_videoFPSCount - camera.m_videoPrevFPSCount; @@ -601,9 +612,12 @@ bool ATVMod::handleMessage(const Message& cmd) framesCount = 0; } - MsgReportVideoFileSourceStreamTiming *report; - report = MsgReportVideoFileSourceStreamTiming::create(framesCount); - getOutputMessageQueue()->push(report); + if (getMessageQueueToGUI()) + { + MsgReportVideoFileSourceStreamTiming *report; + report = MsgReportVideoFileSourceStreamTiming::create(framesCount); + getMessageQueueToGUI()->push(report); + } return true; } @@ -615,16 +629,20 @@ bool ATVMod::handleMessage(const Message& cmd) if (index < m_cameras.size()) { m_cameraIndex = index; - MsgReportCameraData *report; - report = MsgReportCameraData::create( - m_cameras[m_cameraIndex].m_cameraNumber, - m_cameras[m_cameraIndex].m_videoFPS, - m_cameras[m_cameraIndex].m_videoFPSManual, - m_cameras[m_cameraIndex].m_videoFPSManualEnable, - m_cameras[m_cameraIndex].m_videoWidth, - m_cameras[m_cameraIndex].m_videoHeight, - 0); - getOutputMessageQueue()->push(report); + + if (getMessageQueueToGUI()) + { + MsgReportCameraData *report; + report = MsgReportCameraData::create( + m_cameras[m_cameraIndex].m_cameraNumber, + m_cameras[m_cameraIndex].m_videoFPS, + m_cameras[m_cameraIndex].m_videoFPSManual, + m_cameras[m_cameraIndex].m_videoFPSManualEnable, + m_cameras[m_cameraIndex].m_videoWidth, + m_cameras[m_cameraIndex].m_videoHeight, + 0); + getMessageQueueToGUI()->push(report); + } } return true; @@ -721,9 +739,12 @@ void ATVMod::apply(bool force) applyStandard(); // set all timings m_settingsMutex.unlock(); - MsgReportEffectiveSampleRate *report; - report = MsgReportEffectiveSampleRate::create(m_tvSampleRate, m_pointsPerLine); - getOutputMessageQueue()->push(report); + if (getMessageQueueToGUI()) + { + MsgReportEffectiveSampleRate *report; + report = MsgReportEffectiveSampleRate::create(m_tvSampleRate, m_pointsPerLine); + getMessageQueueToGUI()->push(report); + } } if ((m_config.m_outputSampleRate != m_running.m_outputSampleRate) @@ -977,9 +998,12 @@ void ATVMod::openVideo(const QString& fileName) calculateVideoSizes(); m_videoEOF = false; - MsgReportVideoFileSourceStreamData *report; - report = MsgReportVideoFileSourceStreamData::create(m_videoFPS, m_videoLength); - getOutputMessageQueue()->push(report); + if (getMessageQueueToGUI()) + { + MsgReportVideoFileSourceStreamData *report; + report = MsgReportVideoFileSourceStreamData::create(m_videoFPS, m_videoLength); + getMessageQueueToGUI()->push(report); + } } else { @@ -1114,16 +1138,20 @@ void ATVMod::getCameraNumbers(std::vector& numbers) if (m_cameras.size() > 0) { m_cameraIndex = 0; - MsgReportCameraData *report; - report = MsgReportCameraData::create( - m_cameras[0].m_cameraNumber, - m_cameras[0].m_videoFPS, - m_cameras[0].m_videoFPSManual, - m_cameras[0].m_videoFPSManualEnable, - m_cameras[0].m_videoWidth, - m_cameras[0].m_videoHeight, - 0); - getOutputMessageQueue()->push(report); + + if (getMessageQueueToGUI()) + { + MsgReportCameraData *report; + report = MsgReportCameraData::create( + m_cameras[0].m_cameraNumber, + m_cameras[0].m_videoFPS, + m_cameras[0].m_videoFPSManual, + m_cameras[0].m_videoFPSManualEnable, + m_cameras[0].m_videoWidth, + m_cameras[0].m_videoHeight, + 0); + getMessageQueueToGUI()->push(report); + } } } diff --git a/plugins/channeltx/modatv/atvmodgui.cpp b/plugins/channeltx/modatv/atvmodgui.cpp index 0e1738d59..52d16f23d 100644 --- a/plugins/channeltx/modatv/atvmodgui.cpp +++ b/plugins/channeltx/modatv/atvmodgui.cpp @@ -363,7 +363,7 @@ void ATVModGUI::handleSourceMessages() { Message* message; - while ((message = m_atvMod->getOutputMessageQueue()->pop()) != 0) + while ((message = getInputMessageQueue()->pop()) != 0) { if (handleMessage(*message)) { @@ -622,6 +622,7 @@ ATVModGUI::ATVModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked())); m_atvMod = new ATVMod(); + m_atvMod->setMessageQueueToGUI(getInputMessageQueue()); m_channelizer = new UpChannelizer(m_atvMod); m_threadedChannelizer = new ThreadedBasebandSampleSource(m_channelizer, this); //m_pluginAPI->addThreadedSink(m_threadedChannelizer); @@ -648,7 +649,7 @@ ATVModGUI::ATVModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa resetToDefaults(); - connect(m_atvMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); connect(m_atvMod, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int))); std::vector cameraNumbers; diff --git a/plugins/channeltx/modatv/atvmodgui.h b/plugins/channeltx/modatv/atvmodgui.h index 66cd4c38d..febd1730e 100644 --- a/plugins/channeltx/modatv/atvmodgui.h +++ b/plugins/channeltx/modatv/atvmodgui.h @@ -17,10 +17,10 @@ #ifndef PLUGINS_CHANNELTX_MODTV_ATVMODGUI_H_ #define PLUGINS_CHANNELTX_MODTV_ATVMODGUI_H_ +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "atvmod.h" @@ -37,7 +37,7 @@ namespace Ui { class ATVModGUI; } -class ATVModGUI : public RollupWidget, public PluginInstanceUI { +class ATVModGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channeltx/modatv/atvmodplugin.cpp b/plugins/channeltx/modatv/atvmodplugin.cpp index 5e5e4156e..4fe1e9f68 100644 --- a/plugins/channeltx/modatv/atvmodplugin.cpp +++ b/plugins/channeltx/modatv/atvmodplugin.cpp @@ -23,7 +23,7 @@ const PluginDescriptor ATVModPlugin::m_pluginDescriptor = { QString("ATV Modulator"), - QString("3.5.0"), + QString("3.7.3"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -49,7 +49,7 @@ void ATVModPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerTxChannel(ATVModGUI::m_channelID, this); } -PluginInstanceUI* ATVModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* ATVModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) { if(channelName == ATVModGUI::m_channelID) { diff --git a/plugins/channeltx/modatv/atvmodplugin.h b/plugins/channeltx/modatv/atvmodplugin.h index de2c6ec57..6061dbd26 100644 --- a/plugins/channeltx/modatv/atvmodplugin.h +++ b/plugins/channeltx/modatv/atvmodplugin.h @@ -33,7 +33,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); + PluginInstanceGUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channeltx/modnfm/nfmmod.cpp b/plugins/channeltx/modnfm/nfmmod.cpp index 1e2fc94ff..3078e7785 100644 --- a/plugins/channeltx/modnfm/nfmmod.cpp +++ b/plugins/channeltx/modnfm/nfmmod.cpp @@ -367,7 +367,7 @@ bool NFMMod::handleMessage(const Message& cmd) MsgReportFileSourceStreamTiming *report; report = MsgReportFileSourceStreamTiming::create(samplesCount); - getOutputMessageQueue()->push(report); + getMessageQueueToGUI()->push(report); return true; } @@ -462,7 +462,7 @@ void NFMMod::openFileStream() MsgReportFileSourceStreamData *report; report = MsgReportFileSourceStreamData::create(m_sampleRate, m_recordLength); - getOutputMessageQueue()->push(report); + getMessageQueueToGUI()->push(report); } void NFMMod::seekFileStream(int seekPercentage) diff --git a/plugins/channeltx/modnfm/nfmmodgui.cpp b/plugins/channeltx/modnfm/nfmmodgui.cpp index 48845be99..09e469538 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.cpp +++ b/plugins/channeltx/modnfm/nfmmodgui.cpp @@ -202,7 +202,7 @@ void NFMModGUI::handleSourceMessages() { Message* message; - while ((message = m_nfmMod->getOutputMessageQueue()->pop()) != 0) + while ((message = getInputMessageQueue()->pop()) != 0) { if (handleMessage(*message)) { @@ -388,6 +388,7 @@ NFMModGUI::NFMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked())); m_nfmMod = new NFMMod(); + m_nfmMod->setMessageQueueToGUI(getInputMessageQueue()); m_channelizer = new UpChannelizer(m_nfmMod); m_threadedChannelizer = new ThreadedBasebandSampleSource(m_channelizer, this); //m_pluginAPI->addThreadedSink(m_threadedChannelizer); @@ -425,7 +426,7 @@ NFMModGUI::NFMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa applySettings(); - connect(m_nfmMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); connect(m_nfmMod, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int))); } diff --git a/plugins/channeltx/modnfm/nfmmodgui.h b/plugins/channeltx/modnfm/nfmmodgui.h index 8e9759e50..7cb026320 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.h +++ b/plugins/channeltx/modnfm/nfmmodgui.h @@ -17,10 +17,10 @@ #ifndef PLUGINS_CHANNELTX_MODNFM_NFMMODGUI_H_ #define PLUGINS_CHANNELTX_MODNFM_NFMMODGUI_H_ +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "nfmmod.h" @@ -36,7 +36,7 @@ namespace Ui { class NFMModGUI; } -class NFMModGUI : public RollupWidget, public PluginInstanceUI { +class NFMModGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channeltx/modnfm/nfmmodplugin.cpp b/plugins/channeltx/modnfm/nfmmodplugin.cpp index 2f876202f..a1a787825 100644 --- a/plugins/channeltx/modnfm/nfmmodplugin.cpp +++ b/plugins/channeltx/modnfm/nfmmodplugin.cpp @@ -49,7 +49,7 @@ void NFMModPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerTxChannel(NFMModGUI::m_channelID, this); } -PluginInstanceUI* NFMModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* NFMModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) { if(channelName == NFMModGUI::m_channelID) { diff --git a/plugins/channeltx/modnfm/nfmmodplugin.h b/plugins/channeltx/modnfm/nfmmodplugin.h index 6fa9d098d..8c35aba10 100644 --- a/plugins/channeltx/modnfm/nfmmodplugin.h +++ b/plugins/channeltx/modnfm/nfmmodplugin.h @@ -33,7 +33,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); + PluginInstanceGUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channeltx/modssb/ssbmod.cpp b/plugins/channeltx/modssb/ssbmod.cpp index 71405ace8..7ab668f09 100644 --- a/plugins/channeltx/modssb/ssbmod.cpp +++ b/plugins/channeltx/modssb/ssbmod.cpp @@ -685,7 +685,7 @@ bool SSBMod::handleMessage(const Message& cmd) MsgReportFileSourceStreamTiming *report; report = MsgReportFileSourceStreamTiming::create(samplesCount); - getOutputMessageQueue()->push(report); + getMessageQueueToGUI()->push(report); return true; } @@ -824,7 +824,7 @@ void SSBMod::openFileStream() MsgReportFileSourceStreamData *report; report = MsgReportFileSourceStreamData::create(m_sampleRate, m_recordLength); - getOutputMessageQueue()->push(report); + getMessageQueueToGUI()->push(report); } void SSBMod::seekFileStream(int seekPercentage) diff --git a/plugins/channeltx/modssb/ssbmodgui.cpp b/plugins/channeltx/modssb/ssbmodgui.cpp index fd5b77a78..b3f63d49d 100644 --- a/plugins/channeltx/modssb/ssbmodgui.cpp +++ b/plugins/channeltx/modssb/ssbmodgui.cpp @@ -237,7 +237,7 @@ void SSBModGUI::handleSourceMessages() { Message* message; - while ((message = m_ssbMod->getOutputMessageQueue()->pop()) != 0) + while ((message = getInputMessageQueue()->pop()) != 0) { if (handleMessage(*message)) { @@ -540,6 +540,7 @@ SSBModGUI::SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa m_spectrumVis = new SpectrumVis(ui->glSpectrum); m_ssbMod = new SSBMod(m_spectrumVis); + m_ssbMod->setMessageQueueToGUI(getInputMessageQueue()); m_channelizer = new UpChannelizer(m_ssbMod); m_threadedChannelizer = new ThreadedBasebandSampleSource(m_channelizer, this); //m_pluginAPI->addThreadedSink(m_threadedChannelizer); @@ -580,7 +581,7 @@ SSBModGUI::SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa applySettings(); setNewRate(m_spanLog2); - connect(m_ssbMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); connect(m_ssbMod, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int))); } diff --git a/plugins/channeltx/modssb/ssbmodgui.h b/plugins/channeltx/modssb/ssbmodgui.h index 098a7e079..eceb0642b 100644 --- a/plugins/channeltx/modssb/ssbmodgui.h +++ b/plugins/channeltx/modssb/ssbmodgui.h @@ -17,10 +17,10 @@ #ifndef PLUGINS_CHANNELTX_MODSSB_SSBMODGUI_H_ #define PLUGINS_CHANNELTX_MODSSB_SSBMODGUI_H_ +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "ssbmod.h" @@ -37,7 +37,7 @@ namespace Ui { class SSBModGUI; } -class SSBModGUI : public RollupWidget, public PluginInstanceUI { +class SSBModGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channeltx/modssb/ssbmodplugin.cpp b/plugins/channeltx/modssb/ssbmodplugin.cpp index e616cd916..e3a2b6494 100644 --- a/plugins/channeltx/modssb/ssbmodplugin.cpp +++ b/plugins/channeltx/modssb/ssbmodplugin.cpp @@ -49,7 +49,7 @@ void SSBModPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerTxChannel(SSBModGUI::m_channelID, this); } -PluginInstanceUI* SSBModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* SSBModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) { if(channelName == SSBModGUI::m_channelID) { diff --git a/plugins/channeltx/modssb/ssbmodplugin.h b/plugins/channeltx/modssb/ssbmodplugin.h index 3b58e24ab..3c8ef8c98 100644 --- a/plugins/channeltx/modssb/ssbmodplugin.h +++ b/plugins/channeltx/modssb/ssbmodplugin.h @@ -33,7 +33,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); + PluginInstanceGUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channeltx/modwfm/wfmmod.cpp b/plugins/channeltx/modwfm/wfmmod.cpp index d6be5516d..8038f67d1 100644 --- a/plugins/channeltx/modwfm/wfmmod.cpp +++ b/plugins/channeltx/modwfm/wfmmod.cpp @@ -367,7 +367,7 @@ bool WFMMod::handleMessage(const Message& cmd) MsgReportFileSourceStreamTiming *report; report = MsgReportFileSourceStreamTiming::create(samplesCount); - getOutputMessageQueue()->push(report); + getMessageQueueToGUI()->push(report); return true; } @@ -463,7 +463,7 @@ void WFMMod::openFileStream() MsgReportFileSourceStreamData *report; report = MsgReportFileSourceStreamData::create(m_sampleRate, m_recordLength); - getOutputMessageQueue()->push(report); + getMessageQueueToGUI()->push(report); } void WFMMod::seekFileStream(int seekPercentage) diff --git a/plugins/channeltx/modwfm/wfmmodgui.cpp b/plugins/channeltx/modwfm/wfmmodgui.cpp index 7b84e6f13..3f5e45d86 100644 --- a/plugins/channeltx/modwfm/wfmmodgui.cpp +++ b/plugins/channeltx/modwfm/wfmmodgui.cpp @@ -183,7 +183,7 @@ void WFMModGUI::handleSourceMessages() { Message* message; - while ((message = m_wfmMod->getOutputMessageQueue()->pop()) != 0) + while ((message = getInputMessageQueue()->pop()) != 0) { if (handleMessage(*message)) { @@ -358,6 +358,7 @@ WFMModGUI::WFMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked())); m_wfmMod = new WFMMod(); + m_wfmMod->setMessageQueueToGUI(getInputMessageQueue()); m_channelizer = new UpChannelizer(m_wfmMod); m_threadedChannelizer = new ThreadedBasebandSampleSource(m_channelizer, this); //m_pluginAPI->addThreadedSink(m_threadedChannelizer); @@ -390,7 +391,7 @@ WFMModGUI::WFMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa applySettings(); - connect(m_wfmMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); connect(m_wfmMod, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int))); } diff --git a/plugins/channeltx/modwfm/wfmmodgui.h b/plugins/channeltx/modwfm/wfmmodgui.h index 8add57c38..a929135db 100644 --- a/plugins/channeltx/modwfm/wfmmodgui.h +++ b/plugins/channeltx/modwfm/wfmmodgui.h @@ -17,10 +17,10 @@ #ifndef PLUGINS_CHANNELTX_MODWFM_WFMMODGUI_H_ #define PLUGINS_CHANNELTX_MODWFM_WFMMODGUI_H_ +#include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "wfmmod.h" @@ -36,7 +36,7 @@ namespace Ui { class WFMModGUI; } -class WFMModGUI : public RollupWidget, public PluginInstanceUI { +class WFMModGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channeltx/modwfm/wfmmodplugin.cpp b/plugins/channeltx/modwfm/wfmmodplugin.cpp index 0b08dd2ef..e18c82a4d 100644 --- a/plugins/channeltx/modwfm/wfmmodplugin.cpp +++ b/plugins/channeltx/modwfm/wfmmodplugin.cpp @@ -49,7 +49,7 @@ void WFMModPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerTxChannel(WFMModGUI::m_channelID, this); } -PluginInstanceUI* WFMModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* WFMModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) { if(channelName == WFMModGUI::m_channelID) { diff --git a/plugins/channeltx/modwfm/wfmmodplugin.h b/plugins/channeltx/modwfm/wfmmodplugin.h index 48616d21d..e4b67ba1c 100644 --- a/plugins/channeltx/modwfm/wfmmodplugin.h +++ b/plugins/channeltx/modwfm/wfmmodplugin.h @@ -33,7 +33,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); + PluginInstanceGUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/channeltx/udpsink/udpsinkgui.cpp b/plugins/channeltx/udpsink/udpsinkgui.cpp index fcd9c860f..300f92e97 100644 --- a/plugins/channeltx/udpsink/udpsinkgui.cpp +++ b/plugins/channeltx/udpsink/udpsinkgui.cpp @@ -178,7 +178,7 @@ void UDPSinkGUI::handleSourceMessages() { Message* message; - while ((message = m_udpSink->getOutputMessageQueue()->pop()) != 0) + while ((message = getInputMessageQueue()->pop()) != 0) { if (handleMessage(*message)) { @@ -205,6 +205,7 @@ UDPSinkGUI::UDPSinkGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* m_spectrumVis = new SpectrumVis(ui->glSpectrum); m_udpSink = new UDPSink(m_pluginAPI->getMainWindowMessageQueue(), this, m_spectrumVis); + m_udpSink->setMessageQueueToGUI(getInputMessageQueue()); m_channelizer = new UpChannelizer(m_udpSink); m_threadedChannelizer = new ThreadedBasebandSampleSource(m_channelizer, this); m_deviceAPI->addThreadedSource(m_threadedChannelizer); @@ -241,7 +242,7 @@ UDPSinkGUI::UDPSinkGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* displaySettings(); applySettings(true); - connect(m_udpSink->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); connect(m_udpSink, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int))); } diff --git a/plugins/channeltx/udpsink/udpsinkgui.h b/plugins/channeltx/udpsink/udpsinkgui.h index f4291ca0f..a6abfb8b5 100644 --- a/plugins/channeltx/udpsink/udpsinkgui.h +++ b/plugins/channeltx/udpsink/udpsinkgui.h @@ -17,11 +17,11 @@ #ifndef PLUGINS_CHANNELTX_UDPSINK_UDPSINKGUI_H_ #define PLUGINS_CHANNELTX_UDPSINK_UDPSINKGUI_H_ +#include #include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "udpsink.h" @@ -37,7 +37,7 @@ namespace Ui { class UDPSinkGUI; } -class UDPSinkGUI : public RollupWidget, public PluginInstanceUI { +class UDPSinkGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/channeltx/udpsink/udpsinkplugin.cpp b/plugins/channeltx/udpsink/udpsinkplugin.cpp index 88b7ff3d8..46d829c84 100644 --- a/plugins/channeltx/udpsink/udpsinkplugin.cpp +++ b/plugins/channeltx/udpsink/udpsinkplugin.cpp @@ -50,7 +50,7 @@ void UDPSinkPlugin::initPlugin(PluginAPI* pluginAPI) m_pluginAPI->registerTxChannel(UDPSinkGUI::m_channelID, this); } -PluginInstanceUI* UDPSinkPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* UDPSinkPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI) { if(channelName == UDPSinkGUI::m_channelID) { diff --git a/plugins/channeltx/udpsink/udpsinkplugin.h b/plugins/channeltx/udpsink/udpsinkplugin.h index e56d94318..7574f2951 100644 --- a/plugins/channeltx/udpsink/udpsinkplugin.h +++ b/plugins/channeltx/udpsink/udpsinkplugin.h @@ -34,7 +34,7 @@ public: const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); - PluginInstanceUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); + PluginInstanceGUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI); private: static const PluginDescriptor m_pluginDescriptor; diff --git a/plugins/samplesink/bladerfoutput/bladerfoutputgui.h b/plugins/samplesink/bladerfoutput/bladerfoutputgui.h index 9865f8784..e275d3b30 100644 --- a/plugins/samplesink/bladerfoutput/bladerfoutputgui.h +++ b/plugins/samplesink/bladerfoutput/bladerfoutputgui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_BLADERFOUTPUTGUI_H #define INCLUDE_BLADERFOUTPUTGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "bladerfoutput.h" @@ -32,7 +32,7 @@ namespace Ui { class BladerfOutputGui; } -class BladerfOutputGui : public QWidget, public PluginInstanceUI { +class BladerfOutputGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesink/bladerfoutput/bladerfoutputplugin.cpp b/plugins/samplesink/bladerfoutput/bladerfoutputplugin.cpp index 7af7a8ec0..6ea15cc63 100644 --- a/plugins/samplesink/bladerfoutput/bladerfoutputplugin.cpp +++ b/plugins/samplesink/bladerfoutput/bladerfoutputplugin.cpp @@ -77,7 +77,7 @@ PluginInterface::SamplingDevices BladerfOutputPlugin::enumSampleSinks() return result; } -PluginInstanceUI* BladerfOutputPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId,QWidget **widget, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* BladerfOutputPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId,QWidget **widget, DeviceSinkAPI *deviceAPI) { if(sinkId == m_deviceTypeID) { diff --git a/plugins/samplesink/bladerfoutput/bladerfoutputplugin.h b/plugins/samplesink/bladerfoutput/bladerfoutputplugin.h index 3126667cc..62fd5755d 100644 --- a/plugins/samplesink/bladerfoutput/bladerfoutputplugin.h +++ b/plugins/samplesink/bladerfoutput/bladerfoutputplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSinks(); - virtual PluginInstanceUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesink/filesink/filesinkgui.h b/plugins/samplesink/filesink/filesinkgui.h index 7153834b1..2c45b9dda 100644 --- a/plugins/samplesink/filesink/filesinkgui.h +++ b/plugins/samplesink/filesink/filesinkgui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_FILESINKGUI_H #define INCLUDE_FILESINKGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "filesinkoutput.h" @@ -34,7 +34,7 @@ namespace Ui { class FileSinkGui; } -class FileSinkGui : public QWidget, public PluginInstanceUI { +class FileSinkGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesink/filesink/filesinkplugin.cpp b/plugins/samplesink/filesink/filesinkplugin.cpp index b70155a6e..e2497ae1e 100644 --- a/plugins/samplesink/filesink/filesinkplugin.cpp +++ b/plugins/samplesink/filesink/filesinkplugin.cpp @@ -69,7 +69,7 @@ PluginInterface::SamplingDevices FileSinkPlugin::enumSampleSinks() return result; } -PluginInstanceUI* FileSinkPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* FileSinkPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI) { if(sinkId == m_deviceTypeID) { diff --git a/plugins/samplesink/filesink/filesinkplugin.h b/plugins/samplesink/filesink/filesinkplugin.h index 5beea7402..fcc706167 100644 --- a/plugins/samplesink/filesink/filesinkplugin.h +++ b/plugins/samplesink/filesink/filesinkplugin.h @@ -37,7 +37,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSinks(); - virtual PluginInstanceUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesink/hackrfoutput/hackrfoutputgui.h b/plugins/samplesink/hackrfoutput/hackrfoutputgui.h index 5c62c7e25..b5ced5931 100644 --- a/plugins/samplesink/hackrfoutput/hackrfoutputgui.h +++ b/plugins/samplesink/hackrfoutput/hackrfoutputgui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_HACKRFOUTPUTGUI_H #define INCLUDE_HACKRFOUTPUTGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "hackrfoutput.h" @@ -34,7 +34,7 @@ namespace Ui { class HackRFOutputGui; } -class HackRFOutputGui : public QWidget, public PluginInstanceUI { +class HackRFOutputGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesink/hackrfoutput/hackrfoutputplugin.cpp b/plugins/samplesink/hackrfoutput/hackrfoutputplugin.cpp index f90a8a60e..a65a24218 100644 --- a/plugins/samplesink/hackrfoutput/hackrfoutputplugin.cpp +++ b/plugins/samplesink/hackrfoutput/hackrfoutputplugin.cpp @@ -116,7 +116,7 @@ PluginInterface::SamplingDevices HackRFOutputPlugin::enumSampleSinks() return result; } -PluginInstanceUI* HackRFOutputPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* HackRFOutputPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI) { if(sinkId == m_deviceTypeID) { diff --git a/plugins/samplesink/hackrfoutput/hackrfoutputplugin.h b/plugins/samplesink/hackrfoutput/hackrfoutputplugin.h index 3bc320a12..6ba7809b2 100644 --- a/plugins/samplesink/hackrfoutput/hackrfoutputplugin.h +++ b/plugins/samplesink/hackrfoutput/hackrfoutputplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSinks(); - virtual PluginInstanceUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesink/limesdroutput/limesdroutput.cpp b/plugins/samplesink/limesdroutput/limesdroutput.cpp index 5208eab7d..39eabcf5d 100644 --- a/plugins/samplesink/limesdroutput/limesdroutput.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutput.cpp @@ -45,17 +45,21 @@ LimeSDROutput::LimeSDROutput(DeviceSinkAPI *deviceAPI) : m_channelAcquired(false) { m_streamId.handle = 0; - suspendBuddies(); + suspendRxBuddies(); + suspendTxBuddies(); openDevice(); - resumeBuddies(); + resumeTxBuddies(); + resumeRxBuddies(); } LimeSDROutput::~LimeSDROutput() { if (m_running) stop(); - suspendBuddies(); + suspendRxBuddies(); + suspendTxBuddies(); closeDevice(); - resumeBuddies(); + resumeTxBuddies(); + resumeRxBuddies(); } void LimeSDROutput::destroy() @@ -161,56 +165,74 @@ bool LimeSDROutput::openDevice() return true; } -void LimeSDROutput::suspendBuddies() +void LimeSDROutput::suspendRxBuddies() { - // suspend Tx buddy's threads + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); - for (unsigned int i = 0; i < m_deviceAPI->getSinkBuddies().size(); i++) + for (; itSource != sourceBuddies.end(); ++itSource) { - DeviceSinkAPI *buddy = m_deviceAPI->getSinkBuddies()[i]; - DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr(); + DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr(); - if (buddyShared->m_thread) { - buddyShared->m_thread->stopWork(); + if (buddySharedPtr->m_thread && buddySharedPtr->m_thread->isRunning()) + { + buddySharedPtr->m_thread->stopWork(); + buddySharedPtr->m_threadWasRunning = true; } - } - - // suspend Rx buddy's threads - - for (unsigned int i = 0; i < m_deviceAPI->getSourceBuddies().size(); i++) - { - DeviceSourceAPI *buddy = m_deviceAPI->getSourceBuddies()[i]; - DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr(); - - if (buddyShared->m_thread) { - buddyShared->m_thread->stopWork(); + else + { + buddySharedPtr->m_threadWasRunning = false; } } } -void LimeSDROutput::resumeBuddies() +void LimeSDROutput::suspendTxBuddies() { - // resume Tx buddy's threads + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); - for (unsigned int i = 0; i < m_deviceAPI->getSinkBuddies().size(); i++) + for (; itSink != sinkBuddies.end(); ++itSink) { - DeviceSinkAPI *buddy = m_deviceAPI->getSinkBuddies()[i]; - DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr(); + DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); - if (buddyShared->m_thread) { - buddyShared->m_thread->startWork(); + if (buddySharedPtr->m_thread && buddySharedPtr->m_thread->isRunning()) + { + buddySharedPtr->m_thread->stopWork(); + buddySharedPtr->m_threadWasRunning = true; + } + else + { + buddySharedPtr->m_threadWasRunning = false; } } +} - // resume Rx buddy's threads +void LimeSDROutput::resumeRxBuddies() +{ + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); - for (unsigned int i = 0; i < m_deviceAPI->getSourceBuddies().size(); i++) + for (; itSource != sourceBuddies.end(); ++itSource) { - DeviceSourceAPI *buddy = m_deviceAPI->getSourceBuddies()[i]; - DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr(); + DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr(); - if (buddyShared->m_thread) { - buddyShared->m_thread->startWork(); + if (buddySharedPtr->m_threadWasRunning) { + buddySharedPtr->m_thread->startWork(); + } + } +} + +void LimeSDROutput::resumeTxBuddies() +{ + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); + + if (buddySharedPtr->m_threadWasRunning) { + buddySharedPtr->m_thread->startWork(); } } } @@ -237,6 +259,9 @@ void LimeSDROutput::closeDevice() bool LimeSDROutput::acquireChannel() { + suspendRxBuddies(); + suspendTxBuddies(); + // acquire the channel if (LMS_EnableChannel(m_deviceShared.m_deviceParams->getDevice(), LMS_CH_TX, m_deviceShared.m_channel, true) != 0) @@ -260,6 +285,8 @@ bool LimeSDROutput::acquireChannel() if (LMS_SetupStream(m_deviceShared.m_deviceParams->getDevice(), &m_streamId) != 0) { qCritical("LimeSDROutput::acquireChannel: cannot setup the stream on Tx channel %d", m_deviceShared.m_channel); + resumeTxBuddies(); + resumeRxBuddies(); return false; } else @@ -268,11 +295,17 @@ bool LimeSDROutput::acquireChannel() } m_channelAcquired = true; + resumeTxBuddies(); + resumeRxBuddies(); + return true; } void LimeSDROutput::releaseChannel() { + suspendRxBuddies(); + suspendTxBuddies(); + // destroy the stream LMS_DestroyStream(m_deviceShared.m_deviceParams->getDevice(), &m_streamId); m_streamId.handle = 0; @@ -285,6 +318,8 @@ void LimeSDROutput::releaseChannel() } m_channelAcquired = false; + resumeTxBuddies(); + resumeRxBuddies(); } bool LimeSDROutput::start() @@ -293,7 +328,7 @@ bool LimeSDROutput::start() return false; } - if (m_running) stop(); + if (m_running) { stop(); } if (!acquireChannel()) { @@ -573,41 +608,8 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo if (suspendAllThread) { - const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); - std::vector::const_iterator itSource = sourceBuddies.begin(); - - for (; itSource != sourceBuddies.end(); ++itSource) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr(); - - if (buddySharedPtr->m_thread && buddySharedPtr->m_thread->isRunning()) - { - buddySharedPtr->m_thread->stopWork(); - buddySharedPtr->m_threadWasRunning = true; - } - else - { - buddySharedPtr->m_threadWasRunning = false; - } - } - - const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); - std::vector::const_iterator itSink = sinkBuddies.begin(); - - for (; itSink != sinkBuddies.end(); ++itSink) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); - - if (buddySharedPtr->m_thread && buddySharedPtr->m_thread->isRunning()) - { - buddySharedPtr->m_thread->stopWork(); - buddySharedPtr->m_threadWasRunning = true; - } - else - { - buddySharedPtr->m_threadWasRunning = false; - } - } + suspendRxBuddies(); + suspendTxBuddies(); if (m_limeSDROutputThread && m_limeSDROutputThread->isRunning()) { @@ -617,17 +619,7 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo } else if (suspendTxThread) { - const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); - std::vector::const_iterator itSink = sinkBuddies.begin(); - - for (; itSink != sinkBuddies.end(); ++itSink) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); - - if (buddySharedPtr->m_thread) { - buddySharedPtr->m_thread->stopWork(); - } - } + suspendTxBuddies(); if (m_limeSDROutputThread && m_limeSDROutputThread->isRunning()) { @@ -851,29 +843,8 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo if (suspendAllThread) { - const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); - std::vector::const_iterator itSource = sourceBuddies.begin(); - - for (; itSource != sourceBuddies.end(); ++itSource) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr(); - - if (buddySharedPtr->m_threadWasRunning) { - buddySharedPtr->m_thread->startWork(); - } - } - - const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); - std::vector::const_iterator itSink = sinkBuddies.begin(); - - for (; itSink != sinkBuddies.end(); ++itSink) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); - - if (buddySharedPtr->m_threadWasRunning) { - buddySharedPtr->m_thread->startWork(); - } - } + resumeTxBuddies(); + resumeRxBuddies(); if (ownThreadWasRunning) { m_limeSDROutputThread->startWork(); @@ -881,17 +852,7 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo } else if (suspendTxThread) { - const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); - std::vector::const_iterator itSink = sinkBuddies.begin(); - - for (; itSink != sinkBuddies.end(); ++itSink) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); - - if (buddySharedPtr->m_threadWasRunning) { - buddySharedPtr->m_thread->startWork(); - } - } + resumeTxBuddies(); if (ownThreadWasRunning) { m_limeSDROutputThread->startWork(); diff --git a/plugins/samplesink/limesdroutput/limesdroutput.h b/plugins/samplesink/limesdroutput/limesdroutput.h index 9f2e9baca..8166e6b85 100644 --- a/plugins/samplesink/limesdroutput/limesdroutput.h +++ b/plugins/samplesink/limesdroutput/limesdroutput.h @@ -224,8 +224,10 @@ private: void closeDevice(); bool acquireChannel(); void releaseChannel(); - void suspendBuddies(); - void resumeBuddies(); + void suspendRxBuddies(); + void resumeRxBuddies(); + void suspendTxBuddies(); + void resumeTxBuddies(); bool applySettings(const LimeSDROutputSettings& settings, bool force = false); }; diff --git a/plugins/samplesink/limesdroutput/limesdroutputgui.h b/plugins/samplesink/limesdroutput/limesdroutputgui.h index 219831fa0..55ebd4d91 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputgui.h +++ b/plugins/samplesink/limesdroutput/limesdroutputgui.h @@ -17,10 +17,10 @@ #ifndef PLUGINS_SAMPLESOURCE_LIMESDROUTPUT_LIMESDROUTPUTGUI_H_ #define PLUGINS_SAMPLESOURCE_LIMESDROUTPUT_LIMESDROUTPUTGUI_H_ +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "limesdroutput.h" @@ -32,7 +32,7 @@ namespace Ui { class LimeSDROutputGUI; } -class LimeSDROutputGUI : public QWidget, public PluginInstanceUI { +class LimeSDROutputGUI : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp b/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp index 1bff816a6..14cbff296 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp @@ -96,7 +96,7 @@ PluginInterface::SamplingDevices LimeSDROutputPlugin::enumSampleSinks() return result; } -PluginInstanceUI* LimeSDROutputPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId,QWidget **widget, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* LimeSDROutputPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId,QWidget **widget, DeviceSinkAPI *deviceAPI) { if(sinkId == m_deviceTypeID) { diff --git a/plugins/samplesink/limesdroutput/limesdroutputplugin.h b/plugins/samplesink/limesdroutput/limesdroutputplugin.h index 0fbbc40f5..bf012aa38 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputplugin.h +++ b/plugins/samplesink/limesdroutput/limesdroutputplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSinks(); - virtual PluginInstanceUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesink/plutosdroutput/plutosdroutput.cpp b/plugins/samplesink/plutosdroutput/plutosdroutput.cpp index 39459fff3..e979fe627 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutput.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutput.cpp @@ -343,11 +343,23 @@ bool PlutoSDROutput::applySettings(const PlutoSDROutputSettings& settings, bool std::vector params; bool paramsToSet = false; - if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) + if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) + || (m_settings.m_transverterMode != settings.m_transverterMode) + || (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)) + { - params.push_back(QString(tr("out_altvoltage1_TX_LO_frequency=%1").arg(settings.m_centerFrequency)).toStdString()); + qint64 deviceCenterFrequency = settings.m_centerFrequency; + deviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0; + deviceCenterFrequency = deviceCenterFrequency < 0 ? 0 : deviceCenterFrequency; + + + params.push_back(QString(tr("out_altvoltage1_TX_LO_frequency=%1").arg(deviceCenterFrequency)).toStdString()); paramsToSet = true; forwardChangeOwnDSP = true; + + qDebug() << "PlutoSDROutput::applySettings: center freq: " << settings.m_centerFrequency << " Hz" + << " device center freq: " << deviceCenterFrequency << " Hz"; + } if ((m_settings.m_lpfBW != settings.m_lpfBW) || force) diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp index 8d4a48521..893c2055e 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp @@ -44,7 +44,7 @@ PlutoSDROutputGUI::PlutoSDROutputGUI(DeviceSinkAPI *deviceAPI, QWidget* parent) ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); - ui->centerFrequency->setValueRange(7, DevicePlutoSDR::loLowLimitFreq/1000, DevicePlutoSDR::loHighLimitFreq/1000); + updateFrequencyLimits(); ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow)); ui->sampleRate->setValueRange(8, DevicePlutoSDR::srLowLimitFreq, DevicePlutoSDR::srHighLimitFreq); @@ -238,8 +238,21 @@ void PlutoSDROutputGUI::on_antenna_currentIndexChanged(int index) sendSettings(); } +void PlutoSDROutputGUI::on_transverter_clicked() +{ + m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive(); + m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency(); + qDebug("PlutoSDROutputGUI::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off"); + updateFrequencyLimits(); + m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000; + sendSettings(); +} + void PlutoSDROutputGUI::displaySettings() { + ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency); + ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode); + updateFrequencyLimits(); ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); ui->sampleRate->setValue(m_settings.m_devSampleRate); @@ -362,6 +375,21 @@ void PlutoSDROutputGUI::setSampleRateLimits() ui->sampleRate->setValue(m_settings.m_devSampleRate); } +void PlutoSDROutputGUI::updateFrequencyLimits() +{ + // values in kHz + qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0; + qint64 minLimit = DevicePlutoSDR::loLowLimitFreq/1000 + deltaFrequency; + qint64 maxLimit = DevicePlutoSDR::loHighLimitFreq/1000 + deltaFrequency; + + minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit; + maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit; + + qDebug("PlutoSDRInputGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit); + + ui->centerFrequency->setValueRange(7, minLimit, maxLimit); +} + void PlutoSDROutputGUI::handleInputMessages() { Message* message; diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputgui.h b/plugins/samplesink/plutosdroutput/plutosdroutputgui.h index 570a9e93e..ece73df40 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputgui.h +++ b/plugins/samplesink/plutosdroutput/plutosdroutputgui.h @@ -17,11 +17,11 @@ #ifndef PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDROUTPUTGUI_H_ #define PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDROUTPUTGUI_H_ +#include #include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "plutosdroutputsettings.h" @@ -33,7 +33,7 @@ namespace Ui { class PlutoSDROutputGUI; } -class PlutoSDROutputGUI : public QWidget, public PluginInstanceUI { +class PlutoSDROutputGUI : public QWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -72,6 +72,7 @@ private: void updateSampleRateAndFrequency(); void setFIRBWLimits(); void setSampleRateLimits(); + void updateFrequencyLimits(); private slots: void on_startStop_toggled(bool checked); @@ -86,6 +87,7 @@ private slots: void on_lpFIRGain_currentIndexChanged(int index); void on_att_valueChanged(int value); void on_antenna_currentIndexChanged(int index); + void on_transverter_clicked(); void updateHardware(); void updateStatus(); void handleInputMessages(); diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui b/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui index a8c7e7183..ea61bf9c4 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui +++ b/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui @@ -240,6 +240,22 @@ + + + + + 24 + 24 + + + + Transverter frequency translation dialog + + + X + + + @@ -766,6 +782,11 @@ QToolButton
gui/buttonswitch.h
+ + TransverterButton + QPushButton +
gui/transverterbutton.h
+
diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp index 1c5b9c479..c8d5bc761 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp @@ -28,7 +28,7 @@ class DeviceSourceAPI; const PluginDescriptor PlutoSDROutputPlugin::m_pluginDescriptor = { QString("PlutoSDR Output"), - QString("3.7.2"), + QString("3.7.3"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -81,7 +81,7 @@ PluginInterface::SamplingDevices PlutoSDROutputPlugin::enumSampleSinks() return result; } -PluginInstanceUI* PlutoSDROutputPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* PlutoSDROutputPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI) { if(sinkId == m_deviceTypeID) { diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputplugin.h b/plugins/samplesink/plutosdroutput/plutosdroutputplugin.h index 2e0880fc8..730a28473 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputplugin.h +++ b/plugins/samplesink/plutosdroutput/plutosdroutputplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSinks(); - virtual PluginInstanceUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputsettings.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputsettings.cpp index 631da14d6..21ef340c4 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputsettings.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutputsettings.cpp @@ -36,6 +36,8 @@ void PlutoSDROutputSettings::resetToDefaults() m_lpfFIRlog2Interp = 0; m_att = -50; m_antennaPath = RFPATH_A; + m_transverterMode = false; + m_transverterDeltaFrequency = 0; } QByteArray PlutoSDROutputSettings::serialize() const @@ -52,6 +54,8 @@ QByteArray PlutoSDROutputSettings::serialize() const s.writeU64(12, m_devSampleRate); s.writeS32(13, m_att); s.writeS32(14, (int) m_antennaPath); + s.writeBool(15, m_transverterMode); + s.writeS64(16, m_transverterDeltaFrequency); return s.final(); } @@ -91,6 +95,8 @@ bool PlutoSDROutputSettings::deserialize(const QByteArray& data) } else { m_antennaPath = RFPATH_A; } + d.readBool(15, &m_transverterMode, false); + d.readS64(16, &m_transverterDeltaFrequency, 0); return true; } diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputsettings.h b/plugins/samplesink/plutosdroutput/plutosdroutputsettings.h index a3ad223b3..672dbd4fd 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputsettings.h +++ b/plugins/samplesink/plutosdroutput/plutosdroutputsettings.h @@ -42,6 +42,8 @@ struct PlutoSDROutputSettings { quint32 m_lpfBW; //!< analog lowpass filter bandwidth (Hz) qint32 m_att; //!< "hardware" attenuation in dB fourths RFPath m_antennaPath; + bool m_transverterMode; + qint64 m_transverterDeltaFrequency; PlutoSDROutputSettings(); diff --git a/plugins/samplesink/plutosdroutput/readme.md b/plugins/samplesink/plutosdroutput/readme.md index 5ed3f9ef1..b8724eb6a 100644 --- a/plugins/samplesink/plutosdroutput/readme.md +++ b/plugins/samplesink/plutosdroutput/readme.md @@ -59,6 +59,36 @@ Baseband I/Q sample rate in kS/s. This is the host to device sample rate (5) div Use this slider to adjust LO correction in ppm. It can be varied from -20.0 to 20.0 in 0.1 steps and is applied in hardware. This applies to the oscillator that controls both the Tx and Rx frequency therefore it is also changed on the Rx plugin if it is active. +

2a: Transverter mode open dialog

+ +This button opens a dialog to set the transverter mode frequency translation options: + +![SDR Daemon source input stream trasverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png) + +Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit. + +

2a.1: Translating frequency

+ +You can set the translating frequency in Hz with this dial. Use the wheels to adjust the sample rate. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arroews. Pressing shift simultanoeusly moves digit by 5 and pressing control moves it by 2. + +The frequency set in the device is the frequency on the main dial (1) minus this frequency. Thus it is positive for up converters and negative for down converters. + +For example with a mixer at 120 MHz for HF operation you would set the value to -120,000,000 Hz so that if the main dial frequency is set to 7,130 kHz the PuotSDR will be set to 127.130 MHz. + +If you use an up converter to transmit at the 6 cm band narrowband center frequency of 5670 MHz aith the PlutoSDR set at 432 MHz you would set the translating frequency to 5760 - 432 = 5328 MHz thus dial +5,328,000,000 Hz. + +For bands even higher in the frequency spectrum the GHz digits are not really significant so you can have them set at 1 GHz. Thus to transmit at the 10368 MHz frequency with 432 MHz for the PlutoSDR you would set the translating frequency to 1368 - 432 = 936 MHz. Note that in this case the frequency of the LO used in the mixer of the transverter is set at 9936 MHz. + +The Hz precision allows a fine tuning of the transverter LO offset + +

2a.2: Translating frequency enable/disable

+ +Use this toggle button to activate or deactivate the frequency translation + +

2a.3: Confirmation buttons

+ +Use these buttons to confirm ("OK") or dismiss ("Cancel") your changes. +

3: Software interpolation factor

The I/Q stream to the PlutoSDR is upsampled by a power of two by software inside the plugin from the signal coming from the passband. Possible values are increasing powers of two: 1 (no interpolation), 2, 4, 8, 16, 32. diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h index dd5bef6d0..91f51ca7d 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h @@ -17,11 +17,11 @@ #ifndef INCLUDE_SDRDAEMONSINKGUI_H #define INCLUDE_SDRDAEMONSINKGUI_H +#include #include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "sdrdaemonsinksettings.h" @@ -35,7 +35,7 @@ namespace Ui { class SDRdaemonSinkGui; } -class SDRdaemonSinkGui : public QWidget, public PluginInstanceUI { +class SDRdaemonSinkGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.cpp b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.cpp index 58526827d..53f56c003 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.cpp +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.cpp @@ -70,7 +70,7 @@ PluginInterface::SamplingDevices SDRdaemonSinkPlugin::enumSampleSinks() return result; } -PluginInstanceUI* SDRdaemonSinkPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI) +PluginInstanceGUI* SDRdaemonSinkPlugin::createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI) { if(sinkId == m_deviceTypeID) { diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.h b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.h index 07c3dbfba..2980b19e9 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.h +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.h @@ -37,7 +37,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSinks(); - virtual PluginInstanceUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSinkPluginInstanceGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI); virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesource/airspy/airspygui.cpp b/plugins/samplesource/airspy/airspygui.cpp index 81b38db59..bb7756dc2 100644 --- a/plugins/samplesource/airspy/airspygui.cpp +++ b/plugins/samplesource/airspy/airspygui.cpp @@ -42,7 +42,7 @@ AirspyGui::AirspyGui(DeviceSourceAPI *deviceAPI, QWidget* parent) : ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); - ui->centerFrequency->setValueRange(7, 24000U, 1900000U); + updateFrequencyLimits(); connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); @@ -114,17 +114,6 @@ bool AirspyGui::deserialize(const QByteArray& data) bool AirspyGui::handleMessage(const Message& message __attribute__((unused))) { return false; -// if (AirspyInput::MsgReportAirspy::match(message)) -// { -// qDebug() << "AirspyGui::handleMessage: MsgReportAirspy"; -// m_rates = ((AirspyInput::MsgReportAirspy&) message).getSampleRates(); -// displaySampleRates(); -// return true; -// } -// else -// { -// return false; -// } } void AirspyGui::handleInputMessages() @@ -162,8 +151,26 @@ void AirspyGui::updateSampleRateAndFrequency() ui->deviceRateText->setText(tr("%1k").arg((float)m_sampleRate / 1000)); } +void AirspyGui::updateFrequencyLimits() +{ + // values in kHz + qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0; + qint64 minLimit = AirspyInput::loLowLimitFreq/1000 + deltaFrequency; + qint64 maxLimit = AirspyInput::loHighLimitFreq/1000 + deltaFrequency; + + minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit; + maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit; + + qDebug("AirspyGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit); + + ui->centerFrequency->setValueRange(7, minLimit, maxLimit); +} + void AirspyGui::displaySettings() { + ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency); + ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode); + updateFrequencyLimits(); ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); ui->LOppm->setValue(m_settings.m_LOppmTenths); @@ -355,6 +362,16 @@ void AirspyGui::on_record_toggled(bool checked) m_sampleSource->getInputMessageQueue()->push(message); } +void AirspyGui::on_transverter_clicked() +{ + m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive(); + m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency(); + qDebug("AirspyGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off"); + updateFrequencyLimits(); + m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000; + sendSettings(); +} + void AirspyGui::updateHardware() { qDebug() << "AirspyGui::updateHardware"; diff --git a/plugins/samplesource/airspy/airspygui.h b/plugins/samplesource/airspy/airspygui.h index 145caca75..c507a6dd7 100644 --- a/plugins/samplesource/airspy/airspygui.h +++ b/plugins/samplesource/airspy/airspygui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_AIRSPYGUI_H #define INCLUDE_AIRSPYGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "airspyinput.h" @@ -33,7 +33,7 @@ namespace Ui { class AirspySampleRates; } -class AirspyGui : public QWidget, public PluginInstanceUI { +class AirspyGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -72,6 +72,7 @@ private: void displaySampleRates(); void sendSettings(); void updateSampleRateAndFrequency(); + void updateFrequencyLimits(); private slots: void on_centerFrequency_changed(quint64 value); @@ -89,6 +90,7 @@ private slots: void on_mixAGC_stateChanged(int state); void on_startStop_toggled(bool checked); void on_record_toggled(bool checked); + void on_transverter_clicked(); void updateHardware(); void updateStatus(); void handleInputMessages(); diff --git a/plugins/samplesource/airspy/airspygui.ui b/plugins/samplesource/airspy/airspygui.ui index 29095605b..f26919185 100644 --- a/plugins/samplesource/airspy/airspygui.ui +++ b/plugins/samplesource/airspy/airspygui.ui @@ -267,6 +267,22 @@
+ + + + + 24 + 24 + + + + Transverter frequency translation dialog + + + X + + + @@ -645,6 +661,11 @@ QToolButton
gui/buttonswitch.h
+ + TransverterButton + QPushButton +
gui/transverterbutton.h
+
diff --git a/plugins/samplesource/airspy/airspyinput.cpp b/plugins/samplesource/airspy/airspyinput.cpp index 8c7e4865f..02410cdbd 100644 --- a/plugins/samplesource/airspy/airspyinput.cpp +++ b/plugins/samplesource/airspy/airspyinput.cpp @@ -30,7 +30,9 @@ MESSAGE_CLASS_DEFINITION(AirspyInput::MsgConfigureAirspy, Message) MESSAGE_CLASS_DEFINITION(AirspyInput::MsgFileRecord, Message) -//MESSAGE_CLASS_DEFINITION(AirspyInput::MsgReportAirspy, Message) + +const qint64 AirspyInput::loLowLimitFreq = 24000000L; +const qint64 AirspyInput::loHighLimitFreq = 1900000000L; AirspyInput::AirspyInput(DeviceSourceAPI *deviceAPI) : m_deviceAPI(deviceAPI), @@ -332,32 +334,37 @@ bool AirspyInput::applySettings(const AirspySettings& settings, bool force) } } - qint64 deviceCenterFrequency = m_settings.m_centerFrequency; - qint64 f_img = deviceCenterFrequency; - quint32 devSampleRate = m_sampleRates[m_settings.m_devSampleRateIndex]; - - if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) || - (m_settings.m_LOppmTenths != settings.m_LOppmTenths) || - (m_settings.m_fcPos != settings.m_fcPos)) + if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) + || (m_settings.m_LOppmTenths != settings.m_LOppmTenths) + || (m_settings.m_fcPos != settings.m_fcPos) + || (m_settings.m_transverterMode != settings.m_transverterMode) + || (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)) { - m_settings.m_centerFrequency = settings.m_centerFrequency; - m_settings.m_LOppmTenths = settings.m_LOppmTenths; + m_settings.m_centerFrequency = settings.m_centerFrequency; + m_settings.m_transverterMode = settings.m_transverterMode; + m_settings.m_transverterDeltaFrequency = settings.m_transverterDeltaFrequency; + m_settings.m_LOppmTenths = settings.m_LOppmTenths; + + qint64 deviceCenterFrequency = m_settings.m_centerFrequency; + deviceCenterFrequency -= m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency : 0; + deviceCenterFrequency = deviceCenterFrequency < 0 ? 0 : deviceCenterFrequency; + qint64 f_img = deviceCenterFrequency; + quint32 devSampleRate = m_sampleRates[m_settings.m_devSampleRateIndex]; if ((m_settings.m_log2Decim == 0) || (settings.m_fcPos == AirspySettings::FC_POS_CENTER)) { - deviceCenterFrequency = m_settings.m_centerFrequency; f_img = deviceCenterFrequency; } else { if (settings.m_fcPos == AirspySettings::FC_POS_INFRA) { - deviceCenterFrequency = m_settings.m_centerFrequency + (devSampleRate / 4); + deviceCenterFrequency += (devSampleRate / 4); f_img = deviceCenterFrequency + devSampleRate/2; } else if (settings.m_fcPos == AirspySettings::FC_POS_SUPRA) { - deviceCenterFrequency = m_settings.m_centerFrequency - (devSampleRate / 4); + deviceCenterFrequency -= (devSampleRate / 4); f_img = deviceCenterFrequency - devSampleRate/2; } } @@ -503,7 +510,7 @@ bool AirspyInput::applySettings(const AirspySettings& settings, bool force) if (forwardChange) { - int sampleRate = devSampleRate/(1<handleMessage(*notif); // forward to file sink m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); diff --git a/plugins/samplesource/airspy/airspyinput.h b/plugins/samplesource/airspy/airspyinput.h index d8af4f729..9981367b5 100644 --- a/plugins/samplesource/airspy/airspyinput.h +++ b/plugins/samplesource/airspy/airspyinput.h @@ -68,26 +68,6 @@ public: { } }; -// class MsgReportAirspy : public Message { -// MESSAGE_CLASS_DECLARATION -// -// public: -// const std::vector& getSampleRates() const { return m_sampleRates; } -// -// static MsgReportAirspy* create(const std::vector& sampleRates) -// { -// return new MsgReportAirspy(sampleRates); -// } -// -// protected: -// std::vector m_sampleRates; -// -// MsgReportAirspy(const std::vector& sampleRates) : -// Message(), -// m_sampleRates(sampleRates) -// { } -// }; - AirspyInput(DeviceSourceAPI *deviceAPI); virtual ~AirspyInput(); virtual void destroy(); @@ -102,6 +82,9 @@ public: virtual bool handleMessage(const Message& message); + static const qint64 loLowLimitFreq; + static const qint64 loHighLimitFreq; + private: bool openDevice(); void closeDevice(); diff --git a/plugins/samplesource/airspy/airspyplugin.cpp b/plugins/samplesource/airspy/airspyplugin.cpp index 64e097e4d..13d856eb2 100644 --- a/plugins/samplesource/airspy/airspyplugin.cpp +++ b/plugins/samplesource/airspy/airspyplugin.cpp @@ -27,7 +27,7 @@ const PluginDescriptor AirspyPlugin::m_pluginDescriptor = { QString("Airspy Input"), - QString("3.5.0"), + QString("3.7.3"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -119,7 +119,7 @@ PluginInterface::SamplingDevices AirspyPlugin::enumSampleSources() return result; } -PluginInstanceUI* AirspyPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* AirspyPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) { if (sourceId == m_deviceTypeID) { diff --git a/plugins/samplesource/airspy/airspyplugin.h b/plugins/samplesource/airspy/airspyplugin.h index 0a3f6ffe2..0406ffd68 100644 --- a/plugins/samplesource/airspy/airspyplugin.h +++ b/plugins/samplesource/airspy/airspyplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesource/airspy/airspysettings.cpp b/plugins/samplesource/airspy/airspysettings.cpp index dca1edc7b..ef8dbb1a0 100644 --- a/plugins/samplesource/airspy/airspysettings.cpp +++ b/plugins/samplesource/airspy/airspysettings.cpp @@ -38,6 +38,8 @@ void AirspySettings::resetToDefaults() m_biasT = false; m_dcBlock = false; m_iqCorrection = false; + m_transverterMode = false; + m_transverterDeltaFrequency = 0; } QByteArray AirspySettings::serialize() const @@ -56,6 +58,8 @@ QByteArray AirspySettings::serialize() const s.writeBool(10, m_iqCorrection); s.writeBool(11, m_lnaAGC); s.writeBool(12, m_mixerAGC); + s.writeBool(13, m_transverterMode); + s.writeS64(14, m_transverterDeltaFrequency); return s.final(); } @@ -87,6 +91,8 @@ bool AirspySettings::deserialize(const QByteArray& data) d.readBool(10, &m_iqCorrection, false); d.readBool(11, &m_lnaAGC, false); d.readBool(12, &m_mixerAGC, false); + d.readBool(13, &m_transverterMode, false); + d.readS64(14, &m_transverterDeltaFrequency, 0); return true; } diff --git a/plugins/samplesource/airspy/airspysettings.h b/plugins/samplesource/airspy/airspysettings.h index 6cbf16aec..4e42fe061 100644 --- a/plugins/samplesource/airspy/airspysettings.h +++ b/plugins/samplesource/airspy/airspysettings.h @@ -37,6 +37,8 @@ struct AirspySettings { bool m_biasT; bool m_dcBlock; bool m_iqCorrection; + bool m_transverterMode; + qint64 m_transverterDeltaFrequency; AirspySettings(); void resetToDefaults(); diff --git a/plugins/samplesource/bladerfinput/bladerfinputgui.h b/plugins/samplesource/bladerfinput/bladerfinputgui.h index 234e29197..0d75c6ab9 100644 --- a/plugins/samplesource/bladerfinput/bladerfinputgui.h +++ b/plugins/samplesource/bladerfinput/bladerfinputgui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_BLADERFINPUTGUI_H #define INCLUDE_BLADERFINPUTGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "bladerfinput.h" @@ -31,7 +31,7 @@ namespace Ui { class BladerfInputGui; } -class BladerfInputGui : public QWidget, public PluginInstanceUI { +class BladerfInputGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesource/bladerfinput/bladerfinputplugin.cpp b/plugins/samplesource/bladerfinput/bladerfinputplugin.cpp index c73877ef7..ae7ba37fc 100644 --- a/plugins/samplesource/bladerfinput/bladerfinputplugin.cpp +++ b/plugins/samplesource/bladerfinput/bladerfinputplugin.cpp @@ -78,7 +78,7 @@ PluginInterface::SamplingDevices BlderfInputPlugin::enumSampleSources() return result; } -PluginInstanceUI* BlderfInputPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId,QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* BlderfInputPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId,QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == m_deviceTypeID) { diff --git a/plugins/samplesource/bladerfinput/bladerfinputplugin.h b/plugins/samplesource/bladerfinput/bladerfinputplugin.h index a13e93bc9..e21998654 100644 --- a/plugins/samplesource/bladerfinput/bladerfinputplugin.h +++ b/plugins/samplesource/bladerfinput/bladerfinputplugin.h @@ -37,7 +37,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesource/fcdpro/fcdprogui.cpp b/plugins/samplesource/fcdpro/fcdprogui.cpp index 0ffb02b08..e07dd8304 100644 --- a/plugins/samplesource/fcdpro/fcdprogui.cpp +++ b/plugins/samplesource/fcdpro/fcdprogui.cpp @@ -25,6 +25,7 @@ #include #include "fcdproconst.h" +#include "fcdtraits.h" FCDProGui::FCDProGui(DeviceSourceAPI *deviceAPI, QWidget* parent) : QWidget(parent), @@ -38,7 +39,7 @@ FCDProGui::FCDProGui(DeviceSourceAPI *deviceAPI, QWidget* parent) : ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); - ui->centerFrequency->setValueRange(7, 64000U, 1700000U); + updateFrequencyLimits(); ui->lnaGain->clear(); for (int i = 0; i < FCDProConstants::fcdpro_lna_gain_nb_values(); i++) @@ -237,8 +238,26 @@ void FCDProGui::updateSampleRateAndFrequency() ui->deviceRateText->setText(tr("%1k").arg((float)m_sampleRate / 1000)); } +void FCDProGui::updateFrequencyLimits() +{ + // values in kHz + qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0; + qint64 minLimit = fcd_traits::loLowLimitFreq/1000 + deltaFrequency; + qint64 maxLimit = fcd_traits::loHighLimitFreq/1000 + deltaFrequency; + + minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit; + maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit; + + qDebug("FCDProGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit); + + ui->centerFrequency->setValueRange(7, minLimit, maxLimit); +} + void FCDProGui::displaySettings() { + ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency); + ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode); + updateFrequencyLimits(); ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); ui->ppm->setValue(m_settings.m_LOppmTenths); ui->ppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1))); @@ -440,6 +459,16 @@ void FCDProGui::on_record_toggled(bool checked) m_sampleSource->getInputMessageQueue()->push(message); } +void FCDProGui::on_transverter_clicked() +{ + m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive(); + m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency(); + qDebug("FCDProGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off"); + updateFrequencyLimits(); + m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000; + sendSettings(); +} + void FCDProGui::updateStatus() { int state = m_deviceAPI->state(); diff --git a/plugins/samplesource/fcdpro/fcdprogui.h b/plugins/samplesource/fcdpro/fcdprogui.h index 8d93580f3..d9c1a1742 100644 --- a/plugins/samplesource/fcdpro/fcdprogui.h +++ b/plugins/samplesource/fcdpro/fcdprogui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_FCDPROGUI_H #define INCLUDE_FCDPROGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "fcdproinput.h" @@ -32,7 +32,7 @@ namespace Ui { class FCDProGui; } -class FCDProGui : public QWidget, public PluginInstanceUI { +class FCDProGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -68,6 +68,7 @@ private: void displaySettings(); void sendSettings(); void updateSampleRateAndFrequency(); + void updateFrequencyLimits(); private slots: void handleInputMessages(); @@ -95,6 +96,7 @@ private slots: void on_setDefaults_clicked(bool checked); void on_startStop_toggled(bool checked); void on_record_toggled(bool checked); + void on_transverter_clicked(); void updateHardware(); void updateStatus(); }; diff --git a/plugins/samplesource/fcdpro/fcdprogui.ui b/plugins/samplesource/fcdpro/fcdprogui.ui index 0ad31ead9..f368fea64 100644 --- a/plugins/samplesource/fcdpro/fcdprogui.ui +++ b/plugins/samplesource/fcdpro/fcdprogui.ui @@ -6,20 +6,20 @@ 0 0 - 270 - 335 + 320 + 350 - + 0 0 - 270 - 335 + 320 + 350 @@ -238,6 +238,22 @@
+ + + + + 24 + 24 + + + + Transverter frequency translation dialog + + + X + + + @@ -484,6 +500,11 @@ QToolButton
gui/buttonswitch.h
+ + TransverterButton + QPushButton +
gui/transverterbutton.h
+
diff --git a/plugins/samplesource/fcdpro/fcdproinput.cpp b/plugins/samplesource/fcdpro/fcdproinput.cpp index 2a374dae7..764ce22e7 100644 --- a/plugins/samplesource/fcdpro/fcdproinput.cpp +++ b/plugins/samplesource/fcdpro/fcdproinput.cpp @@ -201,16 +201,23 @@ void FCDProInput::applySettings(const FCDProSettings& settings, bool force) { bool signalChange = false; - if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) + if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) + || (m_settings.m_transverterMode != settings.m_transverterMode) + || (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)) { - qDebug() << "FCDProInput::applySettings: fc: " << settings.m_centerFrequency; + qint64 deviceCenterFrequency = settings.m_centerFrequency; + deviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0; + deviceCenterFrequency = deviceCenterFrequency < 0 ? 0 : deviceCenterFrequency; + + if (m_dev != 0) + { + set_center_freq((double) deviceCenterFrequency); + } + + qDebug() << "FCDProInput::applySettings: center freq: " << settings.m_centerFrequency << " Hz" + << " device center freq: " << deviceCenterFrequency << " Hz"; + m_settings.m_centerFrequency = settings.m_centerFrequency; - - if (m_dev != 0) - { - set_center_freq((double) m_settings.m_centerFrequency); - } - signalChange = true; } diff --git a/plugins/samplesource/fcdpro/fcdproplugin.cpp b/plugins/samplesource/fcdpro/fcdproplugin.cpp index 268f28841..f6d0bfdee 100644 --- a/plugins/samplesource/fcdpro/fcdproplugin.cpp +++ b/plugins/samplesource/fcdpro/fcdproplugin.cpp @@ -74,7 +74,7 @@ PluginInterface::SamplingDevices FCDProPlugin::enumSampleSources() return result; } -PluginInstanceUI* FCDProPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* FCDProPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == fcd_traits::interfaceIID) { diff --git a/plugins/samplesource/fcdpro/fcdproplugin.h b/plugins/samplesource/fcdpro/fcdproplugin.h index fe55f5aa3..4005bc47e 100644 --- a/plugins/samplesource/fcdpro/fcdproplugin.h +++ b/plugins/samplesource/fcdpro/fcdproplugin.h @@ -20,7 +20,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); private: diff --git a/plugins/samplesource/fcdpro/fcdprosettings.cpp b/plugins/samplesource/fcdpro/fcdprosettings.cpp index 6ef1873a5..88f19bc73 100644 --- a/plugins/samplesource/fcdpro/fcdprosettings.cpp +++ b/plugins/samplesource/fcdpro/fcdprosettings.cpp @@ -45,6 +45,8 @@ void FCDProSettings::resetToDefaults() m_ifFilterIndex = 0; m_gain5Index = 0; m_gain6Index = 0; + m_transverterMode = false; + m_transverterDeltaFrequency = 0; } QByteArray FCDProSettings::serialize() const @@ -70,6 +72,8 @@ QByteArray FCDProSettings::serialize() const s.writeS32(17, m_ifFilterIndex); s.writeS32(18, m_gain5Index); s.writeS32(19, m_gain6Index); + s.writeBool(20, m_transverterMode); + s.writeS64(21, m_transverterDeltaFrequency); return s.final(); } @@ -105,6 +109,8 @@ bool FCDProSettings::deserialize(const QByteArray& data) d.readS32(17, &m_ifFilterIndex, 0); d.readS32(18, &m_gain5Index, 0); d.readS32(19, &m_gain6Index, 0); + d.readBool(20, &m_transverterMode, false); + d.readS64(21, &m_transverterDeltaFrequency, 0); return true; } diff --git a/plugins/samplesource/fcdpro/fcdprosettings.h b/plugins/samplesource/fcdpro/fcdprosettings.h index aaa3ff384..59f4e3860 100644 --- a/plugins/samplesource/fcdpro/fcdprosettings.h +++ b/plugins/samplesource/fcdpro/fcdprosettings.h @@ -38,6 +38,8 @@ struct FCDProSettings { qint32 m_gain6Index; bool m_dcBlock; bool m_iqCorrection; + bool m_transverterMode; + qint64 m_transverterDeltaFrequency; FCDProSettings(); void resetToDefaults(); diff --git a/plugins/samplesource/fcdproplus/fcdproplusgui.cpp b/plugins/samplesource/fcdproplus/fcdproplusgui.cpp index 1d2c56798..01221162b 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusgui.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusgui.cpp @@ -26,6 +26,7 @@ #include #include "fcdproplusconst.h" +#include "fcdtraits.h" FCDProPlusGui::FCDProPlusGui(DeviceSourceAPI *deviceAPI, QWidget* parent) : QWidget(parent), @@ -40,7 +41,7 @@ FCDProPlusGui::FCDProPlusGui(DeviceSourceAPI *deviceAPI, QWidget* parent) : ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); - ui->centerFrequency->setValueRange(7, 150U, 2000000U); + updateFrequencyLimits(); ui->filterIF->clear(); for (int i = 0; i < FCDProPlusConstants::fcdproplus_if_filter_nb_values(); i++) @@ -155,8 +156,26 @@ void FCDProPlusGui::updateSampleRateAndFrequency() ui->deviceRateText->setText(tr("%1k").arg((float)m_sampleRate / 1000)); } +void FCDProPlusGui::updateFrequencyLimits() +{ + // values in kHz + qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0; + qint64 minLimit = fcd_traits::loLowLimitFreq/1000 + deltaFrequency; + qint64 maxLimit = fcd_traits::loHighLimitFreq/1000 + deltaFrequency; + + minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit; + maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit; + + qDebug("FCDProPlusGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit); + + ui->centerFrequency->setValueRange(7, minLimit, maxLimit); +} + void FCDProPlusGui::displaySettings() { + ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency); + ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode); + updateFrequencyLimits(); ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); ui->dcOffset->setChecked(m_settings.m_dcBlock); ui->iqImbalance->setChecked(m_settings.m_iqImbalance); @@ -303,3 +322,13 @@ void FCDProPlusGui::on_record_toggled(bool checked) FCDProPlusInput::MsgFileRecord* message = FCDProPlusInput::MsgFileRecord::create(checked); m_sampleSource->getInputMessageQueue()->push(message); } + +void FCDProPlusGui::on_transverter_clicked() +{ + m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive(); + m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency(); + qDebug("FCDProPlusGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off"); + updateFrequencyLimits(); + m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000; + sendSettings(); +} diff --git a/plugins/samplesource/fcdproplus/fcdproplusgui.h b/plugins/samplesource/fcdproplus/fcdproplusgui.h index 8628df0af..586170bb6 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusgui.h +++ b/plugins/samplesource/fcdproplus/fcdproplusgui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_FCDGUI_H #define INCLUDE_FCDGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "fcdproplusinput.h" @@ -31,7 +31,7 @@ namespace Ui { class FCDProPlusGui; } -class FCDProPlusGui : public QWidget, public PluginInstanceUI { +class FCDProPlusGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -67,6 +67,7 @@ private: void displaySettings(); void sendSettings(); void updateSampleRateAndFrequency(); + void updateFrequencyLimits(); private slots: void handleInputMessages(); @@ -82,6 +83,7 @@ private slots: void on_ppm_valueChanged(int value); void on_startStop_toggled(bool checked); void on_record_toggled(bool checked); + void on_transverter_clicked(); void updateHardware(); void updateStatus(); }; diff --git a/plugins/samplesource/fcdproplus/fcdproplusgui.ui b/plugins/samplesource/fcdproplus/fcdproplusgui.ui index cc0720819..270db02c2 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusgui.ui +++ b/plugins/samplesource/fcdproplus/fcdproplusgui.ui @@ -238,6 +238,22 @@
+ + + + + 24 + 24 + + + + Transverter frequency translation dialog + + + X + + + @@ -391,6 +407,11 @@ QToolButton
gui/buttonswitch.h
+ + TransverterButton + QPushButton +
gui/transverterbutton.h
+
diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp index d17641487..e860f88fe 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp @@ -195,17 +195,24 @@ void FCDProPlusInput::applySettings(const FCDProPlusSettings& settings, bool for { bool signalChange = false; - if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) + if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) + || (m_settings.m_transverterMode != settings.m_transverterMode) + || (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)) { - qDebug() << "FCDProPlusInput::applySettings: fc: " << settings.m_centerFrequency; - m_settings.m_centerFrequency = settings.m_centerFrequency; + qint64 deviceCenterFrequency = settings.m_centerFrequency; + deviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0; + deviceCenterFrequency = deviceCenterFrequency < 0 ? 0 : deviceCenterFrequency; - if (m_dev != 0) - { - set_center_freq((double) m_settings.m_centerFrequency); - } + if (m_dev != 0) + { + set_center_freq((double) deviceCenterFrequency); + } - signalChange = true; + qDebug() << "FCDProPlusInput::applySettings: center freq: " << settings.m_centerFrequency << " Hz" + << " device center freq: " << deviceCenterFrequency << " Hz"; + + m_settings.m_centerFrequency = settings.m_centerFrequency; + signalChange = true; } if ((m_settings.m_lnaGain != settings.m_lnaGain) || force) diff --git a/plugins/samplesource/fcdproplus/fcdproplusplugin.cpp b/plugins/samplesource/fcdproplus/fcdproplusplugin.cpp index ab5958e56..14159c0b7 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusplugin.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusplugin.cpp @@ -76,7 +76,7 @@ PluginInterface::SamplingDevices FCDProPlusPlugin::enumSampleSources() return result; } -PluginInstanceUI* FCDProPlusPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* FCDProPlusPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == fcd_traits::interfaceIID) { diff --git a/plugins/samplesource/fcdproplus/fcdproplusplugin.h b/plugins/samplesource/fcdproplus/fcdproplusplugin.h index ecad2455a..c122e8b9b 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusplugin.h +++ b/plugins/samplesource/fcdproplus/fcdproplusplugin.h @@ -20,7 +20,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_deviceTypeID; diff --git a/plugins/samplesource/fcdproplus/fcdproplussettings.cpp b/plugins/samplesource/fcdproplus/fcdproplussettings.cpp index ad557d39d..0751c78ac 100644 --- a/plugins/samplesource/fcdproplus/fcdproplussettings.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplussettings.cpp @@ -35,6 +35,8 @@ void FCDProPlusSettings::resetToDefaults() m_LOppmTenths = 0; m_dcBlock = false; m_iqImbalance = false; + m_transverterMode = false; + m_transverterDeltaFrequency = 0; } QByteArray FCDProPlusSettings::serialize() const @@ -50,6 +52,8 @@ QByteArray FCDProPlusSettings::serialize() const s.writeBool(7, m_iqImbalance); s.writeS32(8, m_LOppmTenths); s.writeU32(9, m_ifGain); + s.writeBool(10, m_transverterMode); + s.writeS64(11, m_transverterDeltaFrequency); return s.final(); } @@ -75,6 +79,8 @@ bool FCDProPlusSettings::deserialize(const QByteArray& data) d.readBool(7, &m_iqImbalance, false); d.readS32(8, &m_LOppmTenths, 0); d.readU32(9, &m_ifGain, 0); + d.readBool(10, &m_transverterMode, false); + d.readS64(11, &m_transverterDeltaFrequency, 0); return true; } diff --git a/plugins/samplesource/fcdproplus/fcdproplussettings.h b/plugins/samplesource/fcdproplus/fcdproplussettings.h index fc4373a05..b0978fb17 100644 --- a/plugins/samplesource/fcdproplus/fcdproplussettings.h +++ b/plugins/samplesource/fcdproplus/fcdproplussettings.h @@ -29,6 +29,8 @@ struct FCDProPlusSettings { qint32 m_LOppmTenths; bool m_dcBlock; bool m_iqImbalance; + bool m_transverterMode; + qint64 m_transverterDeltaFrequency; FCDProPlusSettings(); void resetToDefaults(); diff --git a/plugins/samplesource/filesource/filesourcegui.h b/plugins/samplesource/filesource/filesourcegui.h index 5b706ecd8..bef589100 100644 --- a/plugins/samplesource/filesource/filesourcegui.h +++ b/plugins/samplesource/filesource/filesourcegui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_FILESOURCEGUI_H #define INCLUDE_FILESOURCEGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "filesourceinput.h" @@ -31,7 +31,7 @@ namespace Ui { class FileSourceGui; } -class FileSourceGui : public QWidget, public PluginInstanceUI { +class FileSourceGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesource/filesource/filesourceplugin.cpp b/plugins/samplesource/filesource/filesourceplugin.cpp index 1f7df67dc..04ed32ba6 100644 --- a/plugins/samplesource/filesource/filesourceplugin.cpp +++ b/plugins/samplesource/filesource/filesourceplugin.cpp @@ -69,7 +69,7 @@ PluginInterface::SamplingDevices FileSourcePlugin::enumSampleSources() return result; } -PluginInstanceUI* FileSourcePlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* FileSourcePlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == m_deviceTypeID) { diff --git a/plugins/samplesource/filesource/filesourceplugin.h b/plugins/samplesource/filesource/filesourceplugin.h index 4e7a47a45..04fb820ad 100644 --- a/plugins/samplesource/filesource/filesourceplugin.h +++ b/plugins/samplesource/filesource/filesourceplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesource/hackrfinput/hackrfinputgui.h b/plugins/samplesource/hackrfinput/hackrfinputgui.h index 6370ee2e7..5f78a2f34 100644 --- a/plugins/samplesource/hackrfinput/hackrfinputgui.h +++ b/plugins/samplesource/hackrfinput/hackrfinputgui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_HACKRFINPUTGUI_H #define INCLUDE_HACKRFINPUTGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "hackrfinput.h" @@ -33,7 +33,7 @@ namespace Ui { class HackRFInputGui; } -class HackRFInputGui : public QWidget, public PluginInstanceUI { +class HackRFInputGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesource/hackrfinput/hackrfinputplugin.cpp b/plugins/samplesource/hackrfinput/hackrfinputplugin.cpp index eb9901d07..833722be8 100644 --- a/plugins/samplesource/hackrfinput/hackrfinputplugin.cpp +++ b/plugins/samplesource/hackrfinput/hackrfinputplugin.cpp @@ -117,7 +117,7 @@ PluginInterface::SamplingDevices HackRFInputPlugin::enumSampleSources() return result; } -PluginInstanceUI* HackRFInputPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* HackRFInputPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == m_deviceTypeID) { diff --git a/plugins/samplesource/hackrfinput/hackrfinputplugin.h b/plugins/samplesource/hackrfinput/hackrfinputplugin.h index c5c7f1c2e..c779cb880 100644 --- a/plugins/samplesource/hackrfinput/hackrfinputplugin.h +++ b/plugins/samplesource/hackrfinput/hackrfinputplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index 73f7f55c9..6620dc3d5 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -46,9 +46,11 @@ LimeSDRInput::LimeSDRInput(DeviceSourceAPI *deviceAPI) : m_firstConfig(true) { m_streamId.handle = 0; - suspendBuddies(); + suspendRxBuddies(); + suspendTxBuddies(); openDevice(); - resumeBuddies(); + resumeTxBuddies(); + resumeRxBuddies(); char recFileNameCStr[30]; sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceAPI->getDeviceUID()); @@ -61,9 +63,11 @@ LimeSDRInput::~LimeSDRInput() if (m_running) stop(); m_deviceAPI->removeSink(m_fileSink); delete m_fileSink; - suspendBuddies(); + suspendRxBuddies(); + suspendTxBuddies(); closeDevice(); - resumeBuddies(); + resumeTxBuddies(); + resumeRxBuddies(); } void LimeSDRInput::destroy() @@ -209,56 +213,73 @@ bool LimeSDRInput::openDevice() return true; } -void LimeSDRInput::suspendBuddies() +void LimeSDRInput::suspendRxBuddies() { - // suspend Rx buddy's threads + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); - for (unsigned int i = 0; i < m_deviceAPI->getSourceBuddies().size(); i++) + for (; itSource != sourceBuddies.end(); ++itSource) { - DeviceSourceAPI *buddy = m_deviceAPI->getSourceBuddies()[i]; - DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr(); + DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr(); - if (buddyShared->m_thread) { - buddyShared->m_thread->stopWork(); + if (buddySharedPtr->m_thread && buddySharedPtr->m_thread->isRunning()) + { + buddySharedPtr->m_thread->stopWork(); + buddySharedPtr->m_threadWasRunning = true; } - } - - // suspend Tx buddy's threads - - for (unsigned int i = 0; i < m_deviceAPI->getSinkBuddies().size(); i++) - { - DeviceSinkAPI *buddy = m_deviceAPI->getSinkBuddies()[i]; - DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr(); - - if (buddyShared->m_thread) { - buddyShared->m_thread->stopWork(); + else + { + buddySharedPtr->m_threadWasRunning = false; } } } -void LimeSDRInput::resumeBuddies() +void LimeSDRInput::suspendTxBuddies() { - // resume Rx buddy's threads + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); - for (unsigned int i = 0; i < m_deviceAPI->getSourceBuddies().size(); i++) + for (; itSink != sinkBuddies.end(); ++itSink) { - DeviceSourceAPI *buddy = m_deviceAPI->getSourceBuddies()[i]; - DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr(); + DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); - if (buddyShared->m_thread) { - buddyShared->m_thread->startWork(); + if (buddySharedPtr->m_thread) { + buddySharedPtr->m_thread->stopWork(); + buddySharedPtr->m_threadWasRunning = true; + } + else + { + buddySharedPtr->m_threadWasRunning = false; } } +} - // resume Tx buddy's threads +void LimeSDRInput::resumeRxBuddies() +{ + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); - for (unsigned int i = 0; i < m_deviceAPI->getSinkBuddies().size(); i++) + for (; itSource != sourceBuddies.end(); ++itSource) { - DeviceSinkAPI *buddy = m_deviceAPI->getSinkBuddies()[i]; - DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr(); + DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr(); - if (buddyShared->m_thread) { - buddyShared->m_thread->startWork(); + if (buddySharedPtr->m_threadWasRunning) { + buddySharedPtr->m_thread->startWork(); + } + } +} + +void LimeSDRInput::resumeTxBuddies() +{ + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); + + if (buddySharedPtr->m_threadWasRunning) { + buddySharedPtr->m_thread->startWork(); } } } @@ -269,6 +290,8 @@ void LimeSDRInput::closeDevice() return; } + if (m_running) { stop(); } + // destroy the stream LMS_DestroyStream(m_deviceShared.m_deviceParams->getDevice(), &m_streamId); m_streamId.handle = 0; @@ -298,7 +321,7 @@ bool LimeSDRInput::start() return false; } - if (m_running) stop(); + if (m_running) { stop(); } applySettings(m_settings, true); @@ -591,40 +614,8 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc if (suspendAllThread) { - const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); - std::vector::const_iterator itSource = sourceBuddies.begin(); - - for (; itSource != sourceBuddies.end(); ++itSource) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr(); - - if (buddySharedPtr->m_thread && buddySharedPtr->m_thread->isRunning()) - { - buddySharedPtr->m_thread->stopWork(); - buddySharedPtr->m_threadWasRunning = true; - } - else - { - buddySharedPtr->m_threadWasRunning = false; - } - } - - const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); - std::vector::const_iterator itSink = sinkBuddies.begin(); - - for (; itSink != sinkBuddies.end(); ++itSink) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); - - if (buddySharedPtr->m_thread) { - buddySharedPtr->m_thread->stopWork(); - buddySharedPtr->m_threadWasRunning = true; - } - else - { - buddySharedPtr->m_threadWasRunning = false; - } - } + suspendRxBuddies(); + suspendTxBuddies(); if (m_limeSDRInputThread && m_limeSDRInputThread->isRunning()) { @@ -634,17 +625,7 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc } else if (suspendRxThread) { - const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); - std::vector::const_iterator itSource = sourceBuddies.begin(); - - for (; itSource != sourceBuddies.end(); ++itSource) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr(); - - if (buddySharedPtr->m_thread) { - buddySharedPtr->m_thread->stopWork(); - } - } + suspendRxBuddies(); if (m_limeSDRInputThread && m_limeSDRInputThread->isRunning()) { @@ -1013,29 +994,8 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc if (suspendAllThread) { - const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); - std::vector::const_iterator itSource = sourceBuddies.begin(); - - for (; itSource != sourceBuddies.end(); ++itSource) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSource)->getBuddySharedPtr(); - - if (buddySharedPtr->m_threadWasRunning) { - buddySharedPtr->m_thread->startWork(); - } - } - - const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); - std::vector::const_iterator itSink = sinkBuddies.begin(); - - for (; itSink != sinkBuddies.end(); ++itSink) - { - DeviceLimeSDRShared *buddySharedPtr = (DeviceLimeSDRShared *) (*itSink)->getBuddySharedPtr(); - - if (buddySharedPtr->m_threadWasRunning) { - buddySharedPtr->m_thread->startWork(); - } - } + resumeTxBuddies(); + resumeRxBuddies(); if (ownThreadWasRunning) { m_limeSDRInputThread->startWork(); diff --git a/plugins/samplesource/limesdrinput/limesdrinput.h b/plugins/samplesource/limesdrinput/limesdrinput.h index 1b0b96143..1411b1ada 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.h +++ b/plugins/samplesource/limesdrinput/limesdrinput.h @@ -241,8 +241,10 @@ private: bool openDevice(); void closeDevice(); - void suspendBuddies(); - void resumeBuddies(); + void suspendRxBuddies(); + void resumeRxBuddies(); + void suspendTxBuddies(); + void resumeTxBuddies(); bool applySettings(const LimeSDRInputSettings& settings, bool force = false); }; diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.h b/plugins/samplesource/limesdrinput/limesdrinputgui.h index 5b8d20f0c..7484f03db 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.h +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.h @@ -17,10 +17,10 @@ #ifndef PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUTGUI_H_ #define PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUTGUI_H_ +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "limesdrinput.h" @@ -31,7 +31,7 @@ namespace Ui { class LimeSDRInputGUI; } -class LimeSDRInputGUI : public QWidget, public PluginInstanceUI { +class LimeSDRInputGUI : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp b/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp index 17f576753..f3dd6ef78 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp @@ -97,7 +97,7 @@ PluginInterface::SamplingDevices LimeSDRInputPlugin::enumSampleSources() return result; } -PluginInstanceUI* LimeSDRInputPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId,QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* LimeSDRInputPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId,QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == m_deviceTypeID) { diff --git a/plugins/samplesource/limesdrinput/limesdrinputplugin.h b/plugins/samplesource/limesdrinput/limesdrinputplugin.h index a366d5803..ee1dc218f 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputplugin.h +++ b/plugins/samplesource/limesdrinput/limesdrinputplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp index c5593b426..3d6b26651 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp @@ -367,15 +367,6 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo forwardChangeOwnDSP = true; } - if ((m_settings.m_fcPos != settings.m_fcPos) || force) - { - if (m_plutoSDRInputThread != 0) - { - m_plutoSDRInputThread->setFcPos(settings.m_fcPos); - qDebug() << "PlutoSDRInput::applySettings: set fcPos to " << settings.m_fcPos; - } - } - if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) { plutoBox->setLOPPMTenths(settings.m_LOppmTenths); @@ -385,11 +376,59 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo std::vector params; bool paramsToSet = false; - if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) + if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) + || (m_settings.m_fcPos != settings.m_fcPos) + || (m_settings.m_transverterMode != settings.m_transverterMode) + || (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)) { - params.push_back(QString(tr("out_altvoltage0_RX_LO_frequency=%1").arg(settings.m_centerFrequency)).toStdString()); - paramsToSet = true; - forwardChangeOwnDSP = true; + qint64 deviceCenterFrequency = settings.m_centerFrequency; + deviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0; + qint64 f_img = deviceCenterFrequency; + quint32 devSampleRate = settings.m_devSampleRate; + + if ((m_settings.m_log2Decim == 0) || (settings.m_fcPos == PlutoSDRInputSettings::FC_POS_CENTER)) + { + f_img = deviceCenterFrequency; + } + else + { + if (settings.m_fcPos == PlutoSDRInputSettings::FC_POS_INFRA) + { + deviceCenterFrequency += (devSampleRate / 4); + f_img = deviceCenterFrequency + devSampleRate/2; + } + else if (settings.m_fcPos == PlutoSDRInputSettings::FC_POS_SUPRA) + { + deviceCenterFrequency -= (devSampleRate / 4); + f_img = deviceCenterFrequency - devSampleRate/2; + } + } + + deviceCenterFrequency = deviceCenterFrequency < 0 ? 0 : deviceCenterFrequency; + + if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) + || (m_settings.m_transverterMode != settings.m_transverterMode) + || (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)) + { + params.push_back(QString(tr("out_altvoltage0_RX_LO_frequency=%1").arg(deviceCenterFrequency)).toStdString()); + paramsToSet = true; + forwardChangeOwnDSP = true; + } + + if ((m_settings.m_fcPos != settings.m_fcPos) || force) + { + if (m_plutoSDRInputThread != 0) + { + m_plutoSDRInputThread->setFcPos(settings.m_fcPos); + qDebug() << "PlutoSDRInput::applySettings: set fcPos to " << settings.m_fcPos; + } + } + + qDebug() << "PlutoSDRInput::applySettings: center freq: " << settings.m_centerFrequency << " Hz" + << " device center freq: " << deviceCenterFrequency << " Hz" + << " device sample rate: " << devSampleRate << "S/s" + << " Actual sample rate: " << devSampleRate/(1<setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); - ui->centerFrequency->setValueRange(7, DevicePlutoSDR::loLowLimitFreq/1000, DevicePlutoSDR::loHighLimitFreq/1000); + updateFrequencyLimits(); ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow)); ui->sampleRate->setValueRange(8, DevicePlutoSDR::srLowLimitFreq, DevicePlutoSDR::srHighLimitFreq); @@ -275,8 +275,21 @@ void PlutoSDRInputGui::on_antenna_currentIndexChanged(int index) sendSettings(); } +void PlutoSDRInputGui::on_transverter_clicked() +{ + m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive(); + m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency(); + qDebug("PlutoSDRInputGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off"); + updateFrequencyLimits(); + m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000; + sendSettings(); +} + void PlutoSDRInputGui::displaySettings() { + ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency); + ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode); + updateFrequencyLimits(); ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); ui->sampleRate->setValue(m_settings.m_devSampleRate); @@ -402,20 +415,35 @@ void PlutoSDRInputGui::setSampleRateLimits() ui->sampleRate->setValue(m_settings.m_devSampleRate); } +void PlutoSDRInputGui::updateFrequencyLimits() +{ + // values in kHz + qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0; + qint64 minLimit = DevicePlutoSDR::loLowLimitFreq/1000 + deltaFrequency; + qint64 maxLimit = DevicePlutoSDR::loHighLimitFreq/1000 + deltaFrequency; + + minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit; + maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit; + + qDebug("PlutoSDRInputGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit); + + ui->centerFrequency->setValueRange(7, minLimit, maxLimit); +} + void PlutoSDRInputGui::handleInputMessages() { Message* message; while ((message = m_inputMessageQueue.pop()) != 0) { - qDebug("LimeSDRInputGUI::handleInputMessages: message: %s", message->getIdentifier()); + qDebug("PlutoSDRInputGui::handleInputMessages: message: %s", message->getIdentifier()); if (DSPSignalNotification::match(*message)) { DSPSignalNotification* notif = (DSPSignalNotification*) message; m_sampleRate = notif->getSampleRate(); m_deviceCenterFrequency = notif->getCenterFrequency(); - qDebug("LimeSDRInputGUI::handleInputMessages: DSPSignalNotification: SampleRate: %d, CenterFrequency: %llu", notif->getSampleRate(), notif->getCenterFrequency()); + qDebug("PlutoSDRInputGui::handleInputMessages: DSPSignalNotification: SampleRate: %d, CenterFrequency: %llu", notif->getSampleRate(), notif->getCenterFrequency()); updateSampleRateAndFrequency(); setFIRBWLimits(); diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputgui.h b/plugins/samplesource/plutosdrinput/plutosdrinputgui.h index 20c62ac04..e8b22eab5 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputgui.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinputgui.h @@ -17,11 +17,11 @@ #ifndef PLUGINS_SAMPLESOURCE_PLUTOSDRINPUT_PLUTOSDRINPUTGUI_H_ #define PLUGINS_SAMPLESOURCE_PLUTOSDRINPUT_PLUTOSDRINPUTGUI_H_ +#include #include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "plutosdrinputsettings.h" @@ -33,7 +33,7 @@ namespace Ui { class PlutoSDRInputGUI; } -class PlutoSDRInputGui : public QWidget, public PluginInstanceUI { +class PlutoSDRInputGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -72,6 +72,7 @@ private: void updateSampleRateAndFrequency(); void setFIRBWLimits(); void setSampleRateLimits(); + void updateFrequencyLimits(); private slots: void on_startStop_toggled(bool checked); @@ -91,6 +92,7 @@ private slots: void on_gainMode_currentIndexChanged(int index); void on_gain_valueChanged(int value); void on_antenna_currentIndexChanged(int index); + void on_transverter_clicked(); void updateHardware(); void updateStatus(); void handleInputMessages(); diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui b/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui index f858acfcc..2ea09a0ec 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui +++ b/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui @@ -275,6 +275,22 @@
+ + + + + 24 + 24 + + + + Transverter frequency translation dialog + + + X + + + @@ -937,6 +953,11 @@ QToolButton
gui/buttonswitch.h
+ + TransverterButton + QPushButton +
gui/transverterbutton.h
+
diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp index e5a6a43d3..8dcdf86ff 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp @@ -28,7 +28,7 @@ class DeviceSourceAPI; const PluginDescriptor PlutoSDRInputPlugin::m_pluginDescriptor = { QString("PlutoSDR Input"), - QString("3.7.2"), + QString("3.7.3"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -81,7 +81,7 @@ PluginInterface::SamplingDevices PlutoSDRInputPlugin::enumSampleSources() return result; } -PluginInstanceUI* PlutoSDRInputPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* PlutoSDRInputPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == m_deviceTypeID) { diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputplugin.h b/plugins/samplesource/plutosdrinput/plutosdrinputplugin.h index 2c3b959d1..a4feaf21f 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputplugin.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinputplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp index b0d4f5e08..ac5f7cb33 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp @@ -41,6 +41,8 @@ void PlutoSDRInputSettings::resetToDefaults() m_gain = 40; m_antennaPath = RFPATH_A_BAL; m_gainMode = GAIN_MANUAL; + m_transverterMode = false; + m_transverterDeltaFrequency = 0; } QByteArray PlutoSDRInputSettings::serialize() const @@ -61,6 +63,8 @@ QByteArray PlutoSDRInputSettings::serialize() const s.writeU32(13, m_gain); s.writeS32(14, (int) m_antennaPath); s.writeS32(15, (int) m_gainMode); + s.writeBool(16, m_transverterMode); + s.writeS64(17, m_transverterDeltaFrequency); return s.final(); } @@ -114,6 +118,8 @@ bool PlutoSDRInputSettings::deserialize(const QByteArray& data) } else { m_gainMode = GAIN_MANUAL; } + d.readBool(16, &m_transverterMode, false); + d.readS64(17, &m_transverterDeltaFrequency, 0); return true; } diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h index 1003329e9..19d4793b2 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h @@ -71,6 +71,8 @@ struct PlutoSDRInputSettings { quint32 m_gain; //!< "hardware" gain RFPath m_antennaPath; GainMode m_gainMode; + bool m_transverterMode; + qint64 m_transverterDeltaFrequency; PlutoSDRInputSettings(); diff --git a/plugins/samplesource/plutosdrinput/readme.md b/plugins/samplesource/plutosdrinput/readme.md index 6bbffc080..351e7bceb 100644 --- a/plugins/samplesource/plutosdrinput/readme.md +++ b/plugins/samplesource/plutosdrinput/readme.md @@ -72,6 +72,36 @@ These buttons control the software DSP auto correction options: ☞ AD9363 has a good hardware DC and I/Q compensation so there should not be a use for this software auto-correction. +

4a: Transverter mode open dialog

+ +This button opens a dialog to set the transverter mode frequency translation options: + +![SDR Daemon source input stream trasverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png) + +Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit. + +

4a.1: Translating frequency

+ +You can set the translating frequency in Hz with this dial. Use the wheels to adjust the sample rate. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arroews. Pressing shift simultanoeusly moves digit by 5 and pressing control moves it by 2. + +The frequency set in the device is the frequency on the main dial (1) minus this frequency. Thus it is positive for down converters and negative for up converters. + +For example a mixer at 120 MHz for HF operation you would set the value to -120,000,000 Hz so that if the main dial frequency is set at 7,130 kHz the PlutoSDR will be set to 127.130 MHz. + +If you use a down converter to receive the 6 cm band narrowband center frequency of 5670 MHz at 432 MHz you would set the translating frequency to 5760 - 432 = 5328 MHz thus dial +5,328,000,000 Hz. + +For bands even higher in the frequency spectrum the GHz digits are not really significant so you can have them set at 1 GHz. Thus to receive the 10368 MHz frequency at 432 MHz you would set the translating frequency to 1368 - 432 = 936 MHz. Note that in this case the frequency of the LO used in the mixer of the transverter is set at 9936 MHz. + +The Hz precision allows a fine tuning of the transverter LO offset + +

4a.2: Translating frequency enable/disable

+ +Use this toggle button to activate or deactivate the frequency translation + +

4a.3: Confirmation buttons

+ +Use these buttons to confirm ("OK") or dismiss ("Cancel") your changes. +

5: Software decimation factor

The I/Q stream from the PlutoSDR is doensampled by a power of two by software inside the plugin before being sent to the passband. Possible values are increasing powers of two: 1 (no decimation), 2, 4, 8, 16, 32, 64. diff --git a/plugins/samplesource/rtlsdr/readme.md b/plugins/samplesource/rtlsdr/readme.md index c086f574a..d89e58e88 100644 --- a/plugins/samplesource/rtlsdr/readme.md +++ b/plugins/samplesource/rtlsdr/readme.md @@ -57,6 +57,36 @@ Possible values are: - **Inf**: the decimation operation takes place around the center of the lower half of the BladeRF Rx passband. - **Sup**: the decimation operation takes place around the center of the upper half of the BladeRF Rx passband. +

4a: Transverter mode open dialog

+ +This button opens a dialog to set the transverter mode frequency translation options: + +![SDR Daemon source input stream trasverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png) + +Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit. + +

4a.1: Translating frequency

+ +You can set the translating frequency in Hz with this dial. Use the wheels to adjust the sample rate. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arroews. Pressing shift simultanoeusly moves digit by 5 and pressing control moves it by 2. + +The frequency set in the device is the frequency on the main dial (1) minus this frequency. Thus it is positive for down converters and negative for up converters. + +For example with the DX Patrol that has a mixer at 120 MHz for HF operation you would set the value to -120,000,000 Hz so that if the main dial frequency is set at 7,130 kHz the RTLSDR of the DX Patrol will be set to 127.130 MHz. + +If you use a down converter to receive the 6 cm band narrowband center frequency of 5670 MHz at 432 MHz you would set the translating frequency to 5760 - 432 = 5328 MHz thus dial +5,328,000,000 Hz. + +For bands even higher in the frequency spectrum the GHz digits are not really significant so you can have them set at 1 GHz. Thus to receive the 10368 MHz frequency at 432 MHz you would set the translating frequency to 1368 - 432 = 936 MHz. Note that in this case the frequency of the LO used in the mixer of the transverter is set at 9936 MHz. + +The Hz precision allows a fine tuning of the transverter LO offset + +

4a.2: Translating frequency enable/disable

+ +Use this toggle button to activate or deactivate the frequency translation + +

4a.3: Confirmation buttons

+ +Use these buttons to confirm ("OK") or dismiss ("Cancel") your changes. +

5: Toggle low/high sample rate range

When button is on the sample rate can vary from 230 kS/s to 300 kS/s diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.cpp b/plugins/samplesource/rtlsdr/rtlsdrgui.cpp index 6c2b84309..9e23c9e0d 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.cpp @@ -28,6 +28,7 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" + RTLSDRGui::RTLSDRGui(DeviceSourceAPI *deviceAPI, QWidget* parent) : QWidget(parent), ui(new Ui::RTLSDRGui), @@ -40,10 +41,10 @@ RTLSDRGui::RTLSDRGui(DeviceSourceAPI *deviceAPI, QWidget* parent) : ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); - ui->centerFrequency->setValueRange(7, 24000U, 1900000U); + updateFrequencyLimits(); ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow)); - ui->sampleRate->setValueRange(7, 950000U, 2400000U); + ui->sampleRate->setValueRange(7, RTLSDRInput::sampleRateHighRangeMin, RTLSDRInput::sampleRateHighRangeMax); connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); @@ -175,6 +176,21 @@ void RTLSDRGui::updateSampleRateAndFrequency() ui->deviceRateText->setText(tr("%1k").arg(QString::number(m_sampleRate / 1000.0f, 'g', 5))); } +void RTLSDRGui::updateFrequencyLimits() +{ + // values in kHz + qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0; + qint64 minLimit = (m_settings.m_noModMode ? RTLSDRInput::frequencyLowRangeMin : RTLSDRInput::frequencyHighRangeMin) + deltaFrequency; + qint64 maxLimit = (m_settings.m_noModMode ? RTLSDRInput::frequencyLowRangeMax : RTLSDRInput::frequencyHighRangeMax) + deltaFrequency; + + minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit; + maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit; + + qDebug("RTLSDRGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit); + + ui->centerFrequency->setValueRange(7, minLimit, maxLimit); +} + void RTLSDRGui::displayGains() { if (m_gains.size() > 0) @@ -206,6 +222,9 @@ void RTLSDRGui::displayGains() void RTLSDRGui::displaySettings() { + ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency); + ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode); + updateFrequencyLimits(); ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); ui->sampleRate->setValue(m_settings.m_devSampleRate); ui->dcOffset->setChecked(m_settings.m_dcBlock); @@ -214,6 +233,8 @@ void RTLSDRGui::displaySettings() ui->ppmText->setText(tr("%1").arg(m_settings.m_loPpmCorrection)); ui->decim->setCurrentIndex(m_settings.m_log2Decim); ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos); + ui->checkBox->setChecked(m_settings.m_noModMode); + ui->agc->setChecked(m_settings.m_agc); } void RTLSDRGui::sendSettings() @@ -283,10 +304,6 @@ void RTLSDRGui::on_gain_valueChanged(int value) sendSettings(); } -void RTLSDRGui::on_sampleRate_currentIndexChanged(int index __attribute__((unused))) -{ -} - void RTLSDRGui::on_startStop_toggled(bool checked) { if (checked) @@ -316,6 +333,16 @@ void RTLSDRGui::on_record_toggled(bool checked) m_sampleSource->getInputMessageQueue()->push(message); } +void RTLSDRGui::on_transverter_clicked() +{ + m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive(); + m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency(); + qDebug("RTLSDRGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off"); + updateFrequencyLimits(); + m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000; + sendSettings(); +} + void RTLSDRGui::updateHardware() { RTLSDRInput::MsgConfigureRTLSDR* message = RTLSDRInput::MsgConfigureRTLSDR::create(m_settings); @@ -356,18 +383,17 @@ void RTLSDRGui::on_checkBox_stateChanged(int state) { if (state == Qt::Checked) { - // Direct Modes: 0: off, 1: I, 2: Q, 3: NoMod. - ((RTLSDRInput*)m_sampleSource)->set_ds_mode(3); ui->gain->setEnabled(false); - ui->centerFrequency->setValueRange(7, 1000U, 275000U); + m_settings.m_noModMode = true; + updateFrequencyLimits(); ui->centerFrequency->setValue(7000); m_settings.m_centerFrequency = 7000 * 1000; } else { - ((RTLSDRInput*)m_sampleSource)->set_ds_mode(0); ui->gain->setEnabled(true); - ui->centerFrequency->setValueRange(7, 28500U, 1700000U); + m_settings.m_noModMode = false; + updateFrequencyLimits(); ui->centerFrequency->setValue(434000); ui->gain->setValue(0); m_settings.m_centerFrequency = 435000 * 1000; @@ -391,9 +417,9 @@ void RTLSDRGui::on_sampleRate_changed(quint64 value) void RTLSDRGui::on_lowSampleRate_toggled(bool checked) { if (checked) { - ui->sampleRate->setValueRange(7, 230000U, 300000U); + ui->sampleRate->setValueRange(7, RTLSDRInput::sampleRateLowRangeMin, RTLSDRInput::sampleRateLowRangeMax); } else { - ui->sampleRate->setValueRange(7, 950000U, 2400000U); + ui->sampleRate->setValueRange(7, RTLSDRInput::sampleRateHighRangeMin, RTLSDRInput::sampleRateHighRangeMax); } m_settings.m_devSampleRate = ui->sampleRate->getValueNew(); diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.h b/plugins/samplesource/rtlsdr/rtlsdrgui.h index 5b8b002ee..168a295f5 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.h +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.h @@ -17,10 +17,10 @@ #ifndef INCLUDE_RTLSDRGUI_H #define INCLUDE_RTLSDRGUI_H +#include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "rtlsdrinput.h" @@ -32,7 +32,7 @@ namespace Ui { class RTLSDRSampleRates; } -class RTLSDRGui : public QWidget, public PluginInstanceUI { +class RTLSDRGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: @@ -69,6 +69,7 @@ private: void displaySettings(); void sendSettings(); void updateSampleRateAndFrequency(); + void updateFrequencyLimits(); private slots: void handleInputMessages(); @@ -81,11 +82,11 @@ private slots: void on_fcPos_currentIndexChanged(int index); void on_ppm_valueChanged(int value); void on_gain_valueChanged(int value); - void on_sampleRate_currentIndexChanged(int index); void on_checkBox_stateChanged(int state); void on_agc_stateChanged(int state); void on_startStop_toggled(bool checked); void on_record_toggled(bool checked); + void on_transverter_clicked(); void updateHardware(); void updateStatus(); }; diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.ui b/plugins/samplesource/rtlsdr/rtlsdrgui.ui index d56fa26f4..c09070110 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.ui +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.ui @@ -298,6 +298,25 @@
+ + + + + 24 + 24 + + + + Transverter frequency translation dialog + + + X + + + false + + + @@ -581,6 +600,11 @@ QToolButton
gui/buttonswitch.h
+ + TransverterButton + QPushButton +
gui/transverterbutton.h
+
diff --git a/plugins/samplesource/rtlsdr/rtlsdrinput.cpp b/plugins/samplesource/rtlsdr/rtlsdrinput.cpp index 147b06904..533f9f2c0 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrinput.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrinput.cpp @@ -32,6 +32,15 @@ MESSAGE_CLASS_DEFINITION(RTLSDRInput::MsgConfigureRTLSDR, Message) MESSAGE_CLASS_DEFINITION(RTLSDRInput::MsgReportRTLSDR, Message) MESSAGE_CLASS_DEFINITION(RTLSDRInput::MsgFileRecord, Message) +const quint64 RTLSDRInput::frequencyLowRangeMin = 1000UL; +const quint64 RTLSDRInput::frequencyLowRangeMax = 275000UL; +const quint64 RTLSDRInput::frequencyHighRangeMin = 24000UL; +const quint64 RTLSDRInput::frequencyHighRangeMax = 1900000UL; +const int RTLSDRInput::sampleRateLowRangeMin = 230000U; +const int RTLSDRInput::sampleRateLowRangeMax = 300000U; +const int RTLSDRInput::sampleRateHighRangeMin = 950000U; +const int RTLSDRInput::sampleRateHighRangeMax = 2400000U; + RTLSDRInput::RTLSDRInput(DeviceSourceAPI *deviceAPI) : m_deviceAPI(deviceAPI), m_settings(), @@ -354,31 +363,36 @@ bool RTLSDRInput::applySettings(const RTLSDRSettings& settings, bool force) } } - qint64 deviceCenterFrequency = m_settings.m_centerFrequency; - qint64 f_img = deviceCenterFrequency; - quint32 devSampleRate =m_settings.m_devSampleRate; - if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) - || (m_settings.m_fcPos != settings.m_fcPos)) + || (m_settings.m_fcPos != settings.m_fcPos) + || (m_settings.m_transverterMode != settings.m_transverterMode) + || (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)) { m_settings.m_centerFrequency = settings.m_centerFrequency; + m_settings.m_transverterMode = settings.m_transverterMode; + m_settings.m_transverterDeltaFrequency = settings.m_transverterDeltaFrequency; + qint64 deviceCenterFrequency = m_settings.m_centerFrequency; + deviceCenterFrequency -= m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency : 0; + deviceCenterFrequency = deviceCenterFrequency < 0 ? 0 : deviceCenterFrequency; + qint64 f_img = deviceCenterFrequency; + quint32 devSampleRate = m_settings.m_devSampleRate; + forwardChange = true; if ((m_settings.m_log2Decim == 0) || (settings.m_fcPos == RTLSDRSettings::FC_POS_CENTER)) { - deviceCenterFrequency = m_settings.m_centerFrequency; f_img = deviceCenterFrequency; } else { if (settings.m_fcPos == RTLSDRSettings::FC_POS_INFRA) { - deviceCenterFrequency = m_settings.m_centerFrequency + (devSampleRate / 4); + deviceCenterFrequency += (devSampleRate / 4); f_img = deviceCenterFrequency + devSampleRate/2; } else if (settings.m_fcPos == RTLSDRSettings::FC_POS_SUPRA) { - deviceCenterFrequency = m_settings.m_centerFrequency - (devSampleRate / 4); + deviceCenterFrequency -= (devSampleRate / 4); f_img = deviceCenterFrequency - devSampleRate/2; } } @@ -411,6 +425,18 @@ bool RTLSDRInput::applySettings(const RTLSDRSettings& settings, bool force) } } + if ((m_settings.m_noModMode != settings.m_noModMode) || force) + { + m_settings.m_noModMode = settings.m_noModMode; + + // Direct Modes: 0: off, 1: I, 2: Q, 3: NoMod. + if (m_settings.m_noModMode) { + set_ds_mode(3); + } else { + set_ds_mode(0); + } + } + if (forwardChange) { int sampleRate = m_settings.m_devSampleRate/(1<& getGains() const { return m_gains; } void set_ds_mode(int on); + static const quint64 frequencyLowRangeMin; + static const quint64 frequencyLowRangeMax; + static const quint64 frequencyHighRangeMin; + static const quint64 frequencyHighRangeMax; + static const int sampleRateLowRangeMin; + static const int sampleRateLowRangeMax; + static const int sampleRateHighRangeMin; + static const int sampleRateHighRangeMax; + private: DeviceSourceAPI *m_deviceAPI; FileRecord *m_fileSink; //!< File sink to record device I/Q output diff --git a/plugins/samplesource/rtlsdr/rtlsdrplugin.cpp b/plugins/samplesource/rtlsdr/rtlsdrplugin.cpp index b168512fd..7b84b270c 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrplugin.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrplugin.cpp @@ -11,7 +11,7 @@ const PluginDescriptor RTLSDRPlugin::m_pluginDescriptor = { QString("RTL-SDR Input"), - QString("3.7.2"), + QString("3.7.3"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, @@ -62,7 +62,7 @@ PluginInterface::SamplingDevices RTLSDRPlugin::enumSampleSources() return result; } -PluginInstanceUI* RTLSDRPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* RTLSDRPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == m_deviceTypeID) { RTLSDRGui* gui = new RTLSDRGui(deviceAPI); diff --git a/plugins/samplesource/rtlsdr/rtlsdrplugin.h b/plugins/samplesource/rtlsdr/rtlsdrplugin.h index 505bdd8de..72cee65ec 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrplugin.h +++ b/plugins/samplesource/rtlsdr/rtlsdrplugin.h @@ -20,7 +20,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesource/rtlsdr/rtlsdrsettings.cpp b/plugins/samplesource/rtlsdr/rtlsdrsettings.cpp index edf29351d..703306865 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrsettings.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrsettings.cpp @@ -35,6 +35,9 @@ void RTLSDRSettings::resetToDefaults() m_dcBlock = false; m_iqImbalance = false; m_agc = false; + m_noModMode = false; + m_transverterMode = false; + m_transverterDeltaFrequency = 0; } QByteArray RTLSDRSettings::serialize() const @@ -50,6 +53,9 @@ QByteArray RTLSDRSettings::serialize() const s.writeS32(8, m_devSampleRate); s.writeBool(9, m_lowSampleRate); s.writeBool(10, m_agc); + s.writeBool(11, m_noModMode); + s.writeBool(12, m_transverterMode); + s.writeS64(13, m_transverterDeltaFrequency); return s.final(); } @@ -78,6 +84,9 @@ bool RTLSDRSettings::deserialize(const QByteArray& data) d.readS32(8, &m_devSampleRate, 1024*1000); d.readBool(9, &m_lowSampleRate, false); d.readBool(10, &m_agc, false); + d.readBool(11, &m_noModMode, false); + d.readBool(12, &m_transverterMode, false); + d.readS64(13, &m_transverterDeltaFrequency, 0); return true; } diff --git a/plugins/samplesource/rtlsdr/rtlsdrsettings.h b/plugins/samplesource/rtlsdr/rtlsdrsettings.h index ff257de71..d9c9a2476 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrsettings.h +++ b/plugins/samplesource/rtlsdr/rtlsdrsettings.h @@ -34,6 +34,9 @@ struct RTLSDRSettings { bool m_dcBlock; bool m_iqImbalance; bool m_agc; + bool m_noModMode; + bool m_transverterMode; + qint64 m_transverterDeltaFrequency; RTLSDRSettings(); void resetToDefaults(); diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.h b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.h index 44cbaf9c4..dbc71a083 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.h +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.h @@ -17,11 +17,11 @@ #ifndef INCLUDE_SDRDAEMONSOURCEGUI_H #define INCLUDE_SDRDAEMONSOURCEGUI_H +#include #include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "sdrdaemonsourceinput.h" @@ -32,7 +32,7 @@ namespace Ui { class SDRdaemonSourceGui; } -class SDRdaemonSourceGui : public QWidget, public PluginInstanceUI { +class SDRdaemonSourceGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceplugin.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceplugin.cpp index 82caeab55..0f4417cef 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceplugin.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceplugin.cpp @@ -70,7 +70,7 @@ PluginInterface::SamplingDevices SDRdaemonSourcePlugin::enumSampleSources() return result; } -PluginInstanceUI* SDRdaemonSourcePlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* SDRdaemonSourcePlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == m_deviceTypeID) { diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceplugin.h b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceplugin.h index d33d1ecb6..1c154d112 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceplugin.h +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_hardwareID; diff --git a/plugins/samplesource/sdrplay/sdrplaygui.h b/plugins/samplesource/sdrplay/sdrplaygui.h index 2824dfaae..8310c01a8 100644 --- a/plugins/samplesource/sdrplay/sdrplaygui.h +++ b/plugins/samplesource/sdrplay/sdrplaygui.h @@ -17,11 +17,11 @@ #ifndef PLUGINS_SAMPLESOURCE_SDRPLAY_SDRPLAYGUI_H_ #define PLUGINS_SAMPLESOURCE_SDRPLAY_SDRPLAYGUI_H_ +#include #include #include #include -#include "plugin/plugininstanceui.h" #include "util/messagequeue.h" #include "sdrplayinput.h" @@ -34,7 +34,7 @@ namespace Ui { class SDRPlayGui; } -class SDRPlayGui : public QWidget, public PluginInstanceUI { +class SDRPlayGui : public QWidget, public PluginInstanceGUI { Q_OBJECT public: diff --git a/plugins/samplesource/sdrplay/sdrplayplugin.cpp b/plugins/samplesource/sdrplay/sdrplayplugin.cpp index bcf0cb2f1..99553ad4b 100644 --- a/plugins/samplesource/sdrplay/sdrplayplugin.cpp +++ b/plugins/samplesource/sdrplay/sdrplayplugin.cpp @@ -83,7 +83,7 @@ PluginInterface::SamplingDevices SDRPlayPlugin::enumSampleSources() return result; } -PluginInstanceUI* SDRPlayPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId,QWidget **widget, DeviceSourceAPI *deviceAPI) +PluginInstanceGUI* SDRPlayPlugin::createSampleSourcePluginInstanceGUI(const QString& sourceId,QWidget **widget, DeviceSourceAPI *deviceAPI) { if(sourceId == m_deviceTypeID) { diff --git a/plugins/samplesource/sdrplay/sdrplayplugin.h b/plugins/samplesource/sdrplay/sdrplayplugin.h index 6015527e0..12417334d 100644 --- a/plugins/samplesource/sdrplay/sdrplayplugin.h +++ b/plugins/samplesource/sdrplay/sdrplayplugin.h @@ -36,7 +36,7 @@ public: void initPlugin(PluginAPI* pluginAPI); virtual SamplingDevices enumSampleSources(); - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId, QWidget **widget, DeviceSourceAPI *deviceAPI); virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); static const QString m_hardwareID; diff --git a/sdrbase/device/devicesinkapi.cpp b/sdrbase/device/devicesinkapi.cpp index f7fc083bd..d5e3413b1 100644 --- a/sdrbase/device/devicesinkapi.cpp +++ b/sdrbase/device/devicesinkapi.cpp @@ -14,7 +14,7 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include +#include #include "device/devicesinkapi.h" #include "device/devicesourceapi.h" #include "dsp/devicesamplesink.h" @@ -194,18 +194,18 @@ void DeviceSinkAPI::setSampleSinkPluginInterface(PluginInterface *iface) m_pluginInterface = iface; } -void DeviceSinkAPI::setSampleSinkPluginInstanceUI(PluginInstanceUI *gui) +void DeviceSinkAPI::setSampleSinkPluginInstanceUI(PluginInstanceGUI *gui) { m_sampleSinkPluginInstanceUI = gui; } -void DeviceSinkAPI::registerChannelInstance(const QString& channelName, PluginInstanceUI* pluginGUI) +void DeviceSinkAPI::registerChannelInstance(const QString& channelName, PluginInstanceGUI* pluginGUI) { m_channelInstanceRegistrations.append(ChannelInstanceRegistration(channelName, pluginGUI)); renameChannelInstances(); } -void DeviceSinkAPI::removeChannelInstance(PluginInstanceUI* pluginGUI) +void DeviceSinkAPI::removeChannelInstance(PluginInstanceGUI* pluginGUI) { for(ChannelInstanceRegistrations::iterator it = m_channelInstanceRegistrations.begin(); it != m_channelInstanceRegistrations.end(); ++it) { @@ -395,8 +395,6 @@ bool DeviceSinkAPI::ChannelInstanceRegistration::operator<(const ChannelInstance void DeviceSinkAPI::addSourceBuddy(DeviceSourceAPI* buddy) { - std::vector::iterator it = m_sourceBuddies.begin(); - m_sourceBuddies.push_back(buddy); buddy->m_sinkBuddies.push_back(this); qDebug("DeviceSinkAPI::addSourceBuddy: added buddy %s(%s) to the list [%lx] <-> [%lx]", @@ -408,8 +406,6 @@ void DeviceSinkAPI::addSourceBuddy(DeviceSourceAPI* buddy) void DeviceSinkAPI::addSinkBuddy(DeviceSinkAPI* buddy) { - std::vector::iterator it = m_sinkBuddies.begin(); - m_sinkBuddies.push_back(buddy); buddy->m_sinkBuddies.push_back(this); qDebug("DeviceSinkAPI::addSinkBuddy: added buddy %s(%s) to the list [%lx] <-> [%lx]", diff --git a/sdrbase/device/devicesinkapi.h b/sdrbase/device/devicesinkapi.h index 3f2be5c8d..45c67ec97 100644 --- a/sdrbase/device/devicesinkapi.h +++ b/sdrbase/device/devicesinkapi.h @@ -32,7 +32,7 @@ class DeviceSampleSink; class MessageQueue; class ChannelMarker; class QWidget; -class PluginInstanceUI; +class PluginInstanceGUI; class PluginAPI; class PluginInterface; class Preset; @@ -74,7 +74,7 @@ public: void setSampleSinkDisplayName(const QString& serial); void setSampleSinkSequence(int sequence); void setSampleSinkPluginInterface(PluginInterface *iface); - void setSampleSinkPluginInstanceUI(PluginInstanceUI *gui); + void setSampleSinkPluginInstanceUI(PluginInstanceGUI *gui); const QString& getHardwareId() const { return m_hardwareId; } const QString& getSampleSinkId() const { return m_sampleSinkId; } @@ -82,10 +82,10 @@ public: const QString& getSampleSinkDisplayName() const { return m_sampleSinkDisplayName; } PluginInterface *getPluginInterface() { return m_pluginInterface; } uint32_t getSampleSinkSequence() const { return m_sampleSinkSequence; } - PluginInstanceUI *getSampleSinkPluginInstanceGUI() { return m_sampleSinkPluginInstanceUI; } + PluginInstanceGUI *getSampleSinkPluginInstanceGUI() { return m_sampleSinkPluginInstanceUI; } - void registerChannelInstance(const QString& channelName, PluginInstanceUI* pluginGUI); - void removeChannelInstance(PluginInstanceUI* pluginGUI); + void registerChannelInstance(const QString& channelName, PluginInstanceGUI* pluginGUI); + void removeChannelInstance(PluginInstanceGUI* pluginGUI); void freeChannels(); @@ -115,14 +115,14 @@ protected: struct ChannelInstanceRegistration { QString m_channelName; - PluginInstanceUI* m_gui; + PluginInstanceGUI* m_gui; ChannelInstanceRegistration() : m_channelName(), m_gui(0) { } - ChannelInstanceRegistration(const QString& channelName, PluginInstanceUI* pluginGUI) : + ChannelInstanceRegistration(const QString& channelName, PluginInstanceGUI* pluginGUI) : m_channelName(channelName), m_gui(pluginGUI) { } @@ -153,7 +153,7 @@ protected: QString m_sampleSinkDisplayName; uint32_t m_sampleSinkSequence; PluginInterface* m_pluginInterface; - PluginInstanceUI* m_sampleSinkPluginInstanceUI; + PluginInstanceGUI* m_sampleSinkPluginInstanceUI; ChannelInstanceRegistrations m_channelInstanceRegistrations; diff --git a/sdrbase/device/devicesourceapi.cpp b/sdrbase/device/devicesourceapi.cpp index 2251941fe..fb63fc50a 100644 --- a/sdrbase/device/devicesourceapi.cpp +++ b/sdrbase/device/devicesourceapi.cpp @@ -14,7 +14,7 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include +#include #include "device/devicesourceapi.h" #include "device/devicesinkapi.h" #include "dsp/devicesamplesource.h" @@ -186,18 +186,18 @@ void DeviceSourceAPI::setSampleSourcePluginInterface(PluginInterface *iface) m_pluginInterface = iface; } -void DeviceSourceAPI::setSampleSourcePluginInstanceGUI(PluginInstanceUI *gui) +void DeviceSourceAPI::setSampleSourcePluginInstanceGUI(PluginInstanceGUI *gui) { m_sampleSourcePluginInstanceUI = gui; } -void DeviceSourceAPI::registerChannelInstance(const QString& channelName, PluginInstanceUI* pluginGUI) +void DeviceSourceAPI::registerChannelInstance(const QString& channelName, PluginInstanceGUI* pluginGUI) { m_channelInstanceRegistrations.append(ChannelInstanceRegistration(channelName, pluginGUI)); renameChannelInstances(); } -void DeviceSourceAPI::removeChannelInstance(PluginInstanceUI* pluginGUI) +void DeviceSourceAPI::removeChannelInstance(PluginInstanceGUI* pluginGUI) { for(ChannelInstanceRegistrations::iterator it = m_channelInstanceRegistrations.begin(); it != m_channelInstanceRegistrations.end(); ++it) { @@ -398,8 +398,6 @@ bool DeviceSourceAPI::ChannelInstanceRegistration::operator<(const ChannelInstan void DeviceSourceAPI::addSourceBuddy(DeviceSourceAPI* buddy) { - std::vector::iterator it = m_sourceBuddies.begin(); - m_sourceBuddies.push_back(buddy); buddy->m_sourceBuddies.push_back(this); qDebug("DeviceSourceAPI::addSourceBuddy: added buddy %s(%s) [%lx] <-> [%lx]", @@ -411,8 +409,6 @@ void DeviceSourceAPI::addSourceBuddy(DeviceSourceAPI* buddy) void DeviceSourceAPI::addSinkBuddy(DeviceSinkAPI* buddy) { - std::vector::iterator it = m_sinkBuddies.begin(); - m_sinkBuddies.push_back(buddy); buddy->m_sourceBuddies.push_back(this); qDebug("DeviceSourceAPI::addSinkBuddy: added buddy %s(%s) [%lx] <-> [%lx]", diff --git a/sdrbase/device/devicesourceapi.h b/sdrbase/device/devicesourceapi.h index b169b96de..3e9e9c6f8 100644 --- a/sdrbase/device/devicesourceapi.h +++ b/sdrbase/device/devicesourceapi.h @@ -34,7 +34,7 @@ class DeviceSampleSource; class MessageQueue; class ChannelMarker; class QWidget; -class PluginInstanceUI; +class PluginInstanceGUI; class PluginAPI; class PluginInterface; class Preset; @@ -75,7 +75,7 @@ public: void setSampleSourceDisplayName(const QString& serial); void setSampleSourceSequence(int sequence); void setSampleSourcePluginInterface(PluginInterface *iface); - void setSampleSourcePluginInstanceGUI(PluginInstanceUI *gui); + void setSampleSourcePluginInstanceGUI(PluginInstanceGUI *gui); const QString& getHardwareId() const { return m_hardwareId; } const QString& getSampleSourceId() const { return m_sampleSourceId; } @@ -83,10 +83,10 @@ public: const QString& getSampleSourceDisplayName() const { return m_sampleSourceDisplayName; } PluginInterface *getPluginInterface() { return m_pluginInterface; } uint32_t getSampleSourceSequence() const { return m_sampleSourceSequence; } - PluginInstanceUI *getSampleSourcePluginInstanceGUI() { return m_sampleSourcePluginInstanceUI; } + PluginInstanceGUI *getSampleSourcePluginInstanceGUI() { return m_sampleSourcePluginInstanceUI; } - void registerChannelInstance(const QString& channelName, PluginInstanceUI* pluginGUI); - void removeChannelInstance(PluginInstanceUI* pluginGUI); + void registerChannelInstance(const QString& channelName, PluginInstanceGUI* pluginGUI); + void removeChannelInstance(PluginInstanceGUI* pluginGUI); void freeChannels(); @@ -116,14 +116,14 @@ protected: struct ChannelInstanceRegistration { QString m_channelName; - PluginInstanceUI* m_gui; + PluginInstanceGUI* m_gui; ChannelInstanceRegistration() : m_channelName(), m_gui(NULL) { } - ChannelInstanceRegistration(const QString& channelName, PluginInstanceUI* pluginGUI) : + ChannelInstanceRegistration(const QString& channelName, PluginInstanceGUI* pluginGUI) : m_channelName(channelName), m_gui(pluginGUI) { } @@ -154,7 +154,7 @@ protected: QString m_sampleSourceDisplayName; uint32_t m_sampleSourceSequence; PluginInterface* m_pluginInterface; - PluginInstanceUI* m_sampleSourcePluginInstanceUI; + PluginInstanceGUI* m_sampleSourcePluginInstanceUI; ChannelInstanceRegistrations m_channelInstanceRegistrations; diff --git a/sdrbase/dsp/basebandsamplesink.cpp b/sdrbase/dsp/basebandsamplesink.cpp index dac936700..7887f768d 100644 --- a/sdrbase/dsp/basebandsamplesink.cpp +++ b/sdrbase/dsp/basebandsamplesink.cpp @@ -1,7 +1,8 @@ #include #include "util/message.h" -BasebandSampleSink::BasebandSampleSink() +BasebandSampleSink::BasebandSampleSink() : + m_guiMessageQueue(0) { connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); } diff --git a/sdrbase/dsp/basebandsamplesink.h b/sdrbase/dsp/basebandsamplesink.h index adf47fe9e..9897d280f 100644 --- a/sdrbase/dsp/basebandsamplesink.h +++ b/sdrbase/dsp/basebandsamplesink.h @@ -37,11 +37,12 @@ public: virtual bool handleMessage(const Message& cmd) = 0; //!< Processing of a message. Returns true if message has actually been processed MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication - MessageQueue *getOutputMessageQueue() { return &m_outputMessageQueue; } //!< Get the queue for asynchronous outbound communication + virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; } + MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; } protected: MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication - MessageQueue m_outputMessageQueue; //!< Queue for asynchronous outbound communication + MessageQueue *m_guiMessageQueue; //!< Input message queue to the GUI protected slots: void handleInputMessages(); diff --git a/sdrbase/dsp/basebandsamplesource.cpp b/sdrbase/dsp/basebandsamplesource.cpp index 76ea093a3..edbf2d2f4 100644 --- a/sdrbase/dsp/basebandsamplesource.cpp +++ b/sdrbase/dsp/basebandsamplesource.cpp @@ -19,6 +19,7 @@ #include "util/message.h" BasebandSampleSource::BasebandSampleSource() : + m_guiMessageQueue(0), m_sampleFifo(48000) // arbitrary, will be adjusted to match device sink FIFO size { connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); diff --git a/sdrbase/dsp/basebandsamplesource.h b/sdrbase/dsp/basebandsamplesource.h index 0e257297d..d860505d1 100644 --- a/sdrbase/dsp/basebandsamplesource.h +++ b/sdrbase/dsp/basebandsamplesource.h @@ -56,11 +56,12 @@ public: virtual bool handleMessage(const Message& cmd) = 0; //!< Processing of a message. Returns true if message has actually been processed MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication - MessageQueue *getOutputMessageQueue() { return &m_outputMessageQueue; } //!< Get the queue for asynchronous outbound communication + virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; } + MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; } protected: MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication - MessageQueue m_outputMessageQueue; //!< Queue for asynchronous outbound communication + MessageQueue *m_guiMessageQueue; //!< Input message queue to the GUI SampleSourceFifo m_sampleFifo; //!< Internal FIFO for multi-channel processing protected slots: diff --git a/sdrbase/dsp/channelmarker.h b/sdrbase/dsp/channelmarker.h index f64365b5e..8685ac887 100644 --- a/sdrbase/dsp/channelmarker.h +++ b/sdrbase/dsp/channelmarker.h @@ -5,9 +5,10 @@ #include #include +#include "settings/serializable.h" #include "util/export.h" -class SDRANGEL_API ChannelMarker : public QObject { +class SDRANGEL_API ChannelMarker : public QObject, public Serializable { Q_OBJECT public: @@ -76,8 +77,8 @@ public: const QString& getDisplayAddressSend() const { return m_displayAddressSend; } const QString& getDisplayAddressReceive() const { return m_displayAddressReceive; } - QByteArray serialize() const; - bool deserialize(const QByteArray& data); + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); protected: static QRgb m_colorTable[]; diff --git a/sdrbase/dsp/dspdevicesourceengine.cpp b/sdrbase/dsp/dspdevicesourceengine.cpp index ca0b8aed0..14c9d2f75 100644 --- a/sdrbase/dsp/dspdevicesourceengine.cpp +++ b/sdrbase/dsp/dspdevicesourceengine.cpp @@ -73,8 +73,11 @@ void DSPDeviceSourceEngine::start() void DSPDeviceSourceEngine::stop() { qDebug() << "DSPDeviceSourceEngine::stop"; - DSPExit cmd; - m_syncMessenger.sendWait(cmd); + gotoIdle(); + m_state = StNotStarted; + QThread::exit(); +// DSPExit cmd; +// m_syncMessenger.sendWait(cmd); } bool DSPDeviceSourceEngine::initAcquisition() diff --git a/sdrbase/dsp/threadedbasebandsamplesink.h b/sdrbase/dsp/threadedbasebandsamplesink.h index 416d4d283..93368c6bb 100644 --- a/sdrbase/dsp/threadedbasebandsamplesink.h +++ b/sdrbase/dsp/threadedbasebandsamplesink.h @@ -58,8 +58,6 @@ public: ~ThreadedBasebandSampleSink(); const BasebandSampleSink *getSink() const { return m_basebandSampleSink; } - MessageQueue* getInputMessageQueue() { return m_basebandSampleSink->getInputMessageQueue(); } //!< Return pointer to sample sink's input message queue - MessageQueue* getOutputMessageQueue() { return m_basebandSampleSink->getOutputMessageQueue(); } //!< Return pointer to sample sink's output message queue void start(); //!< this thread start() void stop(); //!< this thread exit() and wait() diff --git a/sdrbase/dsp/threadedbasebandsamplesource.h b/sdrbase/dsp/threadedbasebandsamplesource.h index 35fd47bdc..4f509ee88 100644 --- a/sdrbase/dsp/threadedbasebandsamplesource.h +++ b/sdrbase/dsp/threadedbasebandsamplesource.h @@ -38,8 +38,6 @@ public: ~ThreadedBasebandSampleSource(); const BasebandSampleSource *getSource() const { return m_basebandSampleSource; } - MessageQueue* getInputMessageQueue() { return m_basebandSampleSource->getInputMessageQueue(); } //!< Return pointer to sample source's input message queue - MessageQueue* getOutputMessageQueue() { return m_basebandSampleSource->getOutputMessageQueue(); } //!< Return pointer to sample source's output message queue void start(); //!< this thread start() void stop(); //!< this thread exit() and wait() diff --git a/sdrbase/gui/aboutdialog.ui b/sdrbase/gui/aboutdialog.ui index fa0e4dc2e..d713dea7f 100644 --- a/sdrbase/gui/aboutdialog.ui +++ b/sdrbase/gui/aboutdialog.ui @@ -84,7 +84,7 @@ - <html><head/><body><p>Version 3.7.2 - Copyright (C) 2015-2017 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">RTL-SDRangelove</span></a></p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html> + <html><head/><body><p>Version 3.7.3 - Copyright (C) 2015-2017 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">RTL-SDRangelove</span></a></p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html> true diff --git a/sdrbase/gui/audiodialog.cpp b/sdrbase/gui/audiodialog.cpp index 827f336b6..c8874cfa7 100644 --- a/sdrbase/gui/audiodialog.cpp +++ b/sdrbase/gui/audiodialog.cpp @@ -54,11 +54,13 @@ AudioDialog::AudioDialog(AudioDeviceInfo* audioDeviceInfo, QWidget* parent) : i++; } - if(ui->audioOutTree->currentItem() == NULL) + if(ui->audioOutTree->currentItem() == 0) { ui->audioOutTree->setCurrentItem(ui->audioOutTree->topLevelItem(0)); + } - if(ui->audioInTree->currentItem() == NULL) + if(ui->audioInTree->currentItem() == 0) { ui->audioInTree->setCurrentItem(ui->audioInTree->topLevelItem(0)); + } ui->tabWidget->setCurrentIndex(0); diff --git a/sdrbase/gui/glscopegui.h b/sdrbase/gui/glscopegui.h index 74c17b1e9..38866cbd5 100644 --- a/sdrbase/gui/glscopegui.h +++ b/sdrbase/gui/glscopegui.h @@ -6,6 +6,7 @@ #include "util/export.h" #include "util/message.h" #include "dsp/scopevis.h" +#include "settings/serializable.h" namespace Ui { class GLScopeGUI; @@ -14,7 +15,7 @@ namespace Ui { class MessageQueue; class GLScope; -class SDRANGEL_API GLScopeGUI : public QWidget { +class SDRANGEL_API GLScopeGUI : public QWidget, public Serializable { Q_OBJECT public: @@ -25,8 +26,8 @@ public: void setSampleRate(int sampleRate); void resetToDefaults(); - QByteArray serialize() const; - bool deserialize(const QByteArray& data); + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); bool handleMessage(Message* message); diff --git a/sdrbase/gui/glscopenggui.h b/sdrbase/gui/glscopenggui.h index e58408902..8b3c67891 100644 --- a/sdrbase/gui/glscopenggui.h +++ b/sdrbase/gui/glscopenggui.h @@ -25,6 +25,7 @@ #include "util/export.h" #include "util/message.h" #include "dsp/scopevisng.h" +#include "settings/serializable.h" namespace Ui { class GLScopeNGGUI; @@ -33,7 +34,7 @@ namespace Ui { class MessageQueue; class GLScopeNG; -class SDRANGEL_API GLScopeNGGUI : public QWidget { +class SDRANGEL_API GLScopeNGGUI : public QWidget, public Serializable { Q_OBJECT public: @@ -52,8 +53,8 @@ public: void setSampleRate(int sampleRate); void resetToDefaults(); - QByteArray serialize() const; - bool deserialize(const QByteArray& data); + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); bool handleMessage(Message* message); diff --git a/sdrbase/gui/glspectrumgui.h b/sdrbase/gui/glspectrumgui.h index 51514aeb5..4f29d9da9 100644 --- a/sdrbase/gui/glspectrumgui.h +++ b/sdrbase/gui/glspectrumgui.h @@ -4,6 +4,7 @@ #include #include "dsp/dsptypes.h" #include "util/export.h" +#include "settings/serializable.h" namespace Ui { class GLSpectrumGUI; @@ -13,7 +14,7 @@ class MessageQueue; class SpectrumVis; class GLSpectrum; -class SDRANGEL_API GLSpectrumGUI : public QWidget { +class SDRANGEL_API GLSpectrumGUI : public QWidget, public Serializable { Q_OBJECT public: @@ -23,8 +24,8 @@ public: void setBuddies(MessageQueue* messageQueue, SpectrumVis* spectrumVis, GLSpectrum* glSpectrum); void resetToDefaults(); - QByteArray serialize() const; - bool deserialize(const QByteArray& data); + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); private: Ui::GLSpectrumGUI* ui; diff --git a/sdrbase/gui/transverterbutton.cpp b/sdrbase/gui/transverterbutton.cpp new file mode 100644 index 000000000..8f1edd1b1 --- /dev/null +++ b/sdrbase/gui/transverterbutton.cpp @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 F4EXB // +// written by Edouard Griffiths // +// // +// OpenGL interface modernization. // +// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html // +// // +// 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 "transverterdialog.h" +#include "transverterbutton.h" + +TransverterButton::TransverterButton(QWidget* parent) : + QPushButton(parent), + m_deltaFrequency(0), + m_deltaFrequencyActive(false) +{ + setObjectName("TransverterButton"); + connect(this, SIGNAL(clicked()), this, SLOT(onClicked())); +} + +void TransverterButton::onClicked() +{ + TransverterDialog transverterDialog(m_deltaFrequency, m_deltaFrequencyActive, this); + transverterDialog.exec(); + updateState(); +} + +void TransverterButton::updateState() +{ + setToolTip(tr("Transverter frequency translation dialog. Delta frequency %1 MHz %2") + .arg(m_deltaFrequency/1000000.0) + .arg(m_deltaFrequencyActive ? "enabled" : "disabled")); + + if(m_deltaFrequencyActive) + { + setStyleSheet("TransverterButton { background:rgb(128, 70, 0); }"); + } + else + { + setStyleSheet("TransverterButton { background:rgb(48, 48, 48); }"); + } + +} diff --git a/sdrbase/gui/transverterbutton.h b/sdrbase/gui/transverterbutton.h new file mode 100644 index 000000000..b526fb02c --- /dev/null +++ b/sdrbase/gui/transverterbutton.h @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 F4EXB // +// written by Edouard Griffiths // +// // +// OpenGL interface modernization. // +// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html // +// // +// 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 SDRBASE_GUI_TRANSVERTERBUTTON_H_ +#define SDRBASE_GUI_TRANSVERTERBUTTON_H_ + +#include + +class TransverterButton : public QPushButton { + Q_OBJECT + +public: + TransverterButton(QWidget* parent = 0); + qint64 getDeltaFrequency() const { return m_deltaFrequency; } + bool getDeltaFrequencyAcive() const { return m_deltaFrequencyActive; } + + void setDeltaFrequency(qint64 deltaFrequency) + { + m_deltaFrequency = deltaFrequency; + updateState(); + } + + void setDeltaFrequencyActive(bool active) + { + m_deltaFrequencyActive = active; + updateState(); + } + +private slots: + void onClicked(); + +private: + qint64 m_deltaFrequency; + bool m_deltaFrequencyActive; + + void updateState(); +}; + + +#endif /* SDRBASE_GUI_TRANSVERTERBUTTON_H_ */ diff --git a/sdrbase/gui/transverterdialog.cpp b/sdrbase/gui/transverterdialog.cpp new file mode 100644 index 000000000..d75e33a2f --- /dev/null +++ b/sdrbase/gui/transverterdialog.cpp @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 F4EXB // +// written by Edouard Griffiths // +// // +// OpenGL interface modernization. // +// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html // +// // +// 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 "transverterdialog.h" + +#include "ui_transverterdialog.h" + + +TransverterDialog::TransverterDialog(qint64& deltaFrequency, bool& deltaFrequencyActive, QWidget* parent) : + QDialog(parent), + ui(new Ui::TransverterDialog), + m_deltaFrequency(deltaFrequency), + m_deltaFrequencyActive(deltaFrequencyActive) +{ + ui->setupUi(this); + ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03))); + ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + ui->deltaFrequency->setValueRange(false, 10, -9999999999L, 9999999999L); + ui->deltaFrequency->setValue(m_deltaFrequency); + ui->deltaFrequencyActive->setChecked(m_deltaFrequencyActive); +} + +TransverterDialog::~TransverterDialog() +{ + delete ui; +} + +void TransverterDialog::accept() +{ + m_deltaFrequency = ui->deltaFrequency->getValueNew(); + m_deltaFrequencyActive = ui->deltaFrequencyActive->isChecked(); + QDialog::accept(); +} diff --git a/sdrbase/gui/transverterdialog.h b/sdrbase/gui/transverterdialog.h new file mode 100644 index 000000000..581617482 --- /dev/null +++ b/sdrbase/gui/transverterdialog.h @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 F4EXB // +// written by Edouard Griffiths // +// // +// OpenGL interface modernization. // +// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html // +// // +// 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 SDRBASE_GUI_TRANSVERTERDIALOG_H_ +#define SDRBASE_GUI_TRANSVERTERDIALOG_H_ + +#include + +namespace Ui { + class TransverterDialog; +} + +class TransverterDialog : public QDialog { + Q_OBJECT + +public: + explicit TransverterDialog(qint64& deltaFrequency, bool& deltaFrequencyActive, QWidget* parent = 0); + ~TransverterDialog(); + +private: + Ui::TransverterDialog* ui; + qint64& m_deltaFrequency; + bool& m_deltaFrequencyActive; + +private slots: + void accept(); +}; + + + +#endif /* SDRBASE_GUI_TRANSVERTERDIALOG_H_ */ diff --git a/sdrbase/gui/transverterdialog.ui b/sdrbase/gui/transverterdialog.ui new file mode 100644 index 000000000..c657b3994 --- /dev/null +++ b/sdrbase/gui/transverterdialog.ui @@ -0,0 +1,168 @@ + + + TransverterDialog + + + + 0 + 0 + 324 + 81 + + + + + Sans Serif + 9 + + + + Delta Frequency + + + + + + + + + + Df + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + DejaVu Sans Mono + 12 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Transverter delta frequency (Hz) + + + + + + + Hz + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Enable or disable frequency translation + + + + + + + :/checkmark.png:/checkmark.png + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + ValueDialZ + QWidget +
gui/valuedialz.h
+ 1 +
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+
+ + buttonBox + + + + + + + buttonBox + accepted() + TransverterDialog + accept() + + + 257 + 194 + + + 157 + 203 + + + + + buttonBox + rejected() + TransverterDialog + reject() + + + 314 + 194 + + + 286 + 203 + + + + +
diff --git a/sdrbase/gui/valuedialz.cpp b/sdrbase/gui/valuedialz.cpp index 23aa5d56e..53b3f134e 100644 --- a/sdrbase/gui/valuedialz.cpp +++ b/sdrbase/gui/valuedialz.cpp @@ -185,7 +185,8 @@ QChar ValueDialZ::digitNeigh(QChar c, bool dir) QString ValueDialZ::formatText(qint64 value) { - QString str = QString("%1%2").arg(m_positiveOnly ? "" : value < 0 ? "-" : "+").arg(abs(value), m_numDigits, 10, QChar('0')); + qDebug("ValueDialZ::formatText: value: %lld", value); + QString str = QString("%1%2").arg(m_positiveOnly ? "" : value < 0 ? "-" : "+").arg(value < 0 ? -value : value, m_numDigits, 10, QChar('0')); for(int i = 0; i < m_numDecimalPoints; i++) { diff --git a/sdrbase/mainwindow.cpp b/sdrbase/mainwindow.cpp index 66e3b3ff1..ec2896270 100644 --- a/sdrbase/mainwindow.cpp +++ b/sdrbase/mainwindow.cpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include -#include +#include +#include #include #include #include @@ -146,7 +146,7 @@ MainWindow::MainWindow(QWidget* parent) : m_deviceUIs.back()->m_deviceSourceAPI->getSampleSourceId(), m_deviceUIs.back()->m_deviceSourceAPI); m_deviceUIs.back()->m_deviceSourceAPI->setSampleSource(source); QWidget *gui; - PluginInstanceUI *pluginGUI = m_deviceUIs.back()->m_deviceSourceAPI->getPluginInterface()->createSampleSourcePluginInstanceGUI( + PluginInstanceGUI *pluginGUI = m_deviceUIs.back()->m_deviceSourceAPI->getPluginInterface()->createSampleSourcePluginInstanceGUI( m_deviceUIs.back()->m_deviceSourceAPI->getSampleSourceId(), &gui, m_deviceUIs.back()->m_deviceSourceAPI); m_deviceUIs.back()->m_deviceSourceAPI->getSampleSource()->setMessageQueueToGUI(pluginGUI->getInputMessageQueue()); m_deviceUIs.back()->m_deviceSourceAPI->setSampleSourcePluginInstanceGUI(pluginGUI); @@ -230,7 +230,7 @@ void MainWindow::addSourceDevice() m_deviceUIs.back()->m_deviceSourceAPI->getSampleSourceId(), m_deviceUIs.back()->m_deviceSourceAPI); m_deviceUIs.back()->m_deviceSourceAPI->setSampleSource(source); QWidget *gui; - PluginInstanceUI *pluginGUI = m_deviceUIs.back()->m_deviceSourceAPI->getPluginInterface()->createSampleSourcePluginInstanceGUI( + PluginInstanceGUI *pluginGUI = m_deviceUIs.back()->m_deviceSourceAPI->getPluginInterface()->createSampleSourcePluginInstanceGUI( m_deviceUIs.back()->m_deviceSourceAPI->getSampleSourceId(), &gui, m_deviceUIs.back()->m_deviceSourceAPI); m_deviceUIs.back()->m_deviceSourceAPI->getSampleSource()->setMessageQueueToGUI(pluginGUI->getInputMessageQueue()); m_deviceUIs.back()->m_deviceSourceAPI->setSampleSourcePluginInstanceGUI(pluginGUI); @@ -286,7 +286,7 @@ void MainWindow::addSinkDevice() m_deviceUIs.back()->m_deviceSinkAPI->getSampleSinkId(), m_deviceUIs.back()->m_deviceSinkAPI); m_deviceUIs.back()->m_deviceSinkAPI->setSampleSink(sink); QWidget *gui; - PluginInstanceUI *pluginUI = m_deviceUIs.back()->m_deviceSinkAPI->getPluginInterface()->createSampleSinkPluginInstanceGUI( + PluginInstanceGUI *pluginUI = m_deviceUIs.back()->m_deviceSinkAPI->getPluginInterface()->createSampleSinkPluginInstanceGUI( m_deviceUIs.back()->m_deviceSinkAPI->getSampleSinkId(), &gui, m_deviceUIs.back()->m_deviceSinkAPI); m_deviceUIs.back()->m_deviceSinkAPI->getSampleSink()->setMessageQueueToGUI(pluginUI->getInputMessageQueue()); m_deviceUIs.back()->m_deviceSinkAPI->setSampleSinkPluginInstanceUI(pluginUI); @@ -501,9 +501,9 @@ void MainWindow::createStatusBar() { QString qtVersionStr = QString("Qt %1 ").arg(QT_VERSION_STR); #if QT_VERSION >= 0x050400 - m_showSystemWidget = new QLabel("SDRangel v3.7.2 " + qtVersionStr + QSysInfo::prettyProductName(), this); + m_showSystemWidget = new QLabel("SDRangel v3.7.3 " + qtVersionStr + QSysInfo::prettyProductName(), this); #else - m_showSystemWidget = new QLabel("SDRangel v3.7.2 " + qtVersionStr, this); + m_showSystemWidget = new QLabel("SDRangel v3.7.3 " + qtVersionStr, this); #endif statusBar()->addPermanentWidget(m_showSystemWidget); @@ -895,7 +895,7 @@ void MainWindow::on_sampleSource_confirmClicked(bool checked __attribute__((unus deviceUI->m_deviceSourceAPI->getSampleSourceId(), deviceUI->m_deviceSourceAPI); deviceUI->m_deviceSourceAPI->setSampleSource(source); QWidget *gui; - PluginInstanceUI *pluginUI = deviceUI->m_deviceSourceAPI->getPluginInterface()->createSampleSourcePluginInstanceGUI( + PluginInstanceGUI *pluginUI = deviceUI->m_deviceSourceAPI->getPluginInterface()->createSampleSourcePluginInstanceGUI( deviceUI->m_deviceSourceAPI->getSampleSourceId(), &gui, deviceUI->m_deviceSourceAPI); deviceUI->m_deviceSourceAPI->getSampleSource()->setMessageQueueToGUI(pluginUI->getInputMessageQueue()); deviceUI->m_deviceSourceAPI->setSampleSourcePluginInstanceGUI(pluginUI); @@ -974,7 +974,7 @@ void MainWindow::on_sampleSink_confirmClicked(bool checked __attribute__((unused deviceUI->m_deviceSinkAPI->getSampleSinkId(), deviceUI->m_deviceSinkAPI); deviceUI->m_deviceSinkAPI->setSampleSink(sink); QWidget *gui; - PluginInstanceUI *pluginUI = deviceUI->m_deviceSinkAPI->getPluginInterface()->createSampleSinkPluginInstanceGUI( + PluginInstanceGUI *pluginUI = deviceUI->m_deviceSinkAPI->getPluginInterface()->createSampleSinkPluginInstanceGUI( deviceUI->m_deviceSinkAPI->getSampleSinkId(), &gui, deviceUI->m_deviceSinkAPI); deviceUI->m_deviceSinkAPI->getSampleSink()->setMessageQueueToGUI(pluginUI->getInputMessageQueue()); deviceUI->m_deviceSinkAPI->setSampleSinkPluginInstanceUI(pluginUI); diff --git a/sdrbase/mainwindow.h b/sdrbase/mainwindow.h index c575ba6dd..3137730b2 100644 --- a/sdrbase/mainwindow.h +++ b/sdrbase/mainwindow.h @@ -41,7 +41,7 @@ class GLSpectrum; class GLSpectrumGUI; class ChannelWindow; class PluginAPI; -class PluginInstanceUI; +class PluginInstanceGUI; class ChannelMarker; class PluginManager; class DeviceSourceAPI; diff --git a/sdrbase/plugin/pluginapi.h b/sdrbase/plugin/pluginapi.h index ebc2d91e6..b0b5d4bcb 100644 --- a/sdrbase/plugin/pluginapi.h +++ b/sdrbase/plugin/pluginapi.h @@ -12,7 +12,7 @@ class PluginManager; class PluginInterface; class MainWindow; class MessageQueue; -class PluginInstanceUI; +class PluginInstanceGUI; class SDRANGEL_API PluginAPI : public QObject { Q_OBJECT diff --git a/sdrbase/plugin/plugininstanceui.h b/sdrbase/plugin/plugininstancegui.h similarity index 87% rename from sdrbase/plugin/plugininstanceui.h rename to sdrbase/plugin/plugininstancegui.h index 3a6a302c3..8871c1ec4 100644 --- a/sdrbase/plugin/plugininstanceui.h +++ b/sdrbase/plugin/plugininstancegui.h @@ -10,10 +10,10 @@ class Message; class MessageQueue; -class SDRANGEL_API PluginInstanceUI { +class SDRANGEL_API PluginInstanceGUI { public: - PluginInstanceUI() { }; - virtual ~PluginInstanceUI() { }; + PluginInstanceGUI() { }; + virtual ~PluginInstanceGUI() { }; virtual void destroy() = 0; diff --git a/sdrbase/plugin/plugininterface.cpp b/sdrbase/plugin/plugininterface.cpp index 38cb20750..7db1c63ed 100644 --- a/sdrbase/plugin/plugininterface.cpp +++ b/sdrbase/plugin/plugininterface.cpp @@ -1,10 +1,10 @@ +#include #include "dsp/devicesamplesource.h" #include "dsp/devicesamplesink.h" #include "plugin/plugininterface.h" -#include "plugininstanceui.h" -void PluginInterface::deleteSampleSourcePluginInstanceGUI(PluginInstanceUI *ui) +void PluginInterface::deleteSampleSourcePluginInstanceGUI(PluginInstanceGUI *ui) { ui->destroy(); } @@ -14,7 +14,7 @@ void PluginInterface::deleteSampleSourcePluginInstanceInput(DeviceSampleSource * source->destroy(); } -void PluginInterface::deleteSampleSinkPluginInstanceGUI(PluginInstanceUI *ui) +void PluginInterface::deleteSampleSinkPluginInstanceGUI(PluginInstanceGUI *ui) { ui->destroy(); } diff --git a/sdrbase/plugin/plugininterface.h b/sdrbase/plugin/plugininterface.h index 067cd1b15..612cbb05e 100644 --- a/sdrbase/plugin/plugininterface.h +++ b/sdrbase/plugin/plugininterface.h @@ -17,7 +17,7 @@ struct PluginDescriptor { class PluginAPI; class DeviceSourceAPI; class DeviceSinkAPI; -class PluginInstanceUI; +class PluginInstanceGUI; class QWidget; class DeviceSampleSource; class DeviceSampleSink; @@ -52,23 +52,23 @@ public: virtual void initPlugin(PluginAPI* pluginAPI) = 0; // channel Rx plugins - virtual PluginInstanceUI* createRxChannel(const QString& channelName __attribute__((unused)), DeviceSourceAPI *deviceAPI __attribute__((unused)) ) { return 0; } + virtual PluginInstanceGUI* createRxChannel(const QString& channelName __attribute__((unused)), DeviceSourceAPI *deviceAPI __attribute__((unused)) ) { return 0; } // channel Tx plugins - virtual PluginInstanceUI* createTxChannel(const QString& channelName __attribute__((unused)), DeviceSinkAPI *deviceAPI __attribute__((unused)) ) { return 0; } + virtual PluginInstanceGUI* createTxChannel(const QString& channelName __attribute__((unused)), DeviceSinkAPI *deviceAPI __attribute__((unused)) ) { return 0; } // device source plugins only virtual SamplingDevices enumSampleSources() { return SamplingDevices(); } - virtual PluginInstanceUI* createSampleSourcePluginInstanceGUI(const QString& sourceId __attribute__((unused)), QWidget **widget __attribute__((unused)), DeviceSourceAPI *deviceAPI __attribute__((unused))) { return 0; } + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(const QString& sourceId __attribute__((unused)), QWidget **widget __attribute__((unused)), DeviceSourceAPI *deviceAPI __attribute__((unused))) { return 0; } virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId __attribute__((unused)), DeviceSourceAPI *deviceAPI __attribute__((unused))) { return 0; } // creates the input "core" - virtual void deleteSampleSourcePluginInstanceGUI(PluginInstanceUI *ui); + virtual void deleteSampleSourcePluginInstanceGUI(PluginInstanceGUI *ui); virtual void deleteSampleSourcePluginInstanceInput(DeviceSampleSource *source); // device sink plugins only virtual SamplingDevices enumSampleSinks() { return SamplingDevices(); } - virtual PluginInstanceUI* createSampleSinkPluginInstanceGUI(const QString& sinkId __attribute__((unused)), QWidget **widget __attribute__((unused)), DeviceSinkAPI *deviceAPI __attribute__((unused))) { return 0; } + virtual PluginInstanceGUI* createSampleSinkPluginInstanceGUI(const QString& sinkId __attribute__((unused)), QWidget **widget __attribute__((unused)), DeviceSinkAPI *deviceAPI __attribute__((unused))) { return 0; } virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput(const QString& sinkId __attribute__((unused)), DeviceSinkAPI *deviceAPI __attribute__((unused))) { return 0; } // creates the output "core" - virtual void deleteSampleSinkPluginInstanceGUI(PluginInstanceUI *ui); + virtual void deleteSampleSinkPluginInstanceGUI(PluginInstanceGUI *ui); virtual void deleteSampleSinkPluginInstanceOutput(DeviceSampleSink *sink); }; diff --git a/sdrbase/plugin/pluginmanager.cpp b/sdrbase/plugin/pluginmanager.cpp index 24083218d..a318152a2 100644 --- a/sdrbase/plugin/pluginmanager.cpp +++ b/sdrbase/plugin/pluginmanager.cpp @@ -14,7 +14,7 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include +#include #include "device/devicesourceapi.h" #include "device/devicesinkapi.h" #include @@ -32,10 +32,8 @@ #include "dsp/dspdevicesourceengine.h" #include "dsp/dspdevicesinkengine.h" -const QString PluginManager::m_sdrDaemonHardwareID = "SDRdaemon"; -const QString PluginManager::m_sdrDaemonDeviceTypeID = "sdrangel.samplesource.sdrdaemon"; -const QString PluginManager::m_sdrDaemonFECHardwareID = "SDRdaemonFEC"; -const QString PluginManager::m_sdrDaemonFECDeviceTypeID = "sdrangel.samplesource.sdrdaemonfec"; +const QString PluginManager::m_sdrDaemonHardwareID = "SDRdaemonSource"; +const QString PluginManager::m_sdrDaemonDeviceTypeID = "sdrangel.samplesource.sdrdaemonsource"; const QString PluginManager::m_fileSourceHardwareID = "FileSource"; const QString PluginManager::m_fileSourceDeviceTypeID = "sdrangel.samplesource.filesource"; const QString PluginManager::m_fileSinkDeviceTypeID = "sdrangel.samplesink.filesink"; @@ -169,10 +167,8 @@ void PluginManager::duplicateLocalSampleSourceDevices(uint deviceUID) } SamplingDevice *sdrDaemonSSD0 = 0; - SamplingDevice *sdrDaemonFECSSD0 = 0; SamplingDevice *fileSourceSSD0 = 0; bool duplicateSDRDaemon = true; - bool duplicateSDRDaemonFEC = true; bool duplicateFileSource = true; for(int i = 0; i < m_sampleSourceDevices.count(); ++i) @@ -186,15 +182,6 @@ void PluginManager::duplicateLocalSampleSourceDevices(uint deviceUID) duplicateSDRDaemon = false; } } - else if (m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonFECDeviceTypeID) // SDRdaemon with FEC - { - if (m_sampleSourceDevices[i].m_deviceSequence == 0) { // reference to device 0 - sdrDaemonFECSSD0 = &m_sampleSourceDevices[i]; - } - else if (m_sampleSourceDevices[i].m_deviceSequence == deviceUID) { // already there - duplicateSDRDaemonFEC = false; - } - } else if (m_sampleSourceDevices[i].m_deviceId == m_fileSourceDeviceTypeID) // File Source { if (m_sampleSourceDevices[i].m_deviceSequence == 0) { // reference to device 0 @@ -211,7 +198,7 @@ void PluginManager::duplicateLocalSampleSourceDevices(uint deviceUID) m_sampleSourceDevices.append( SamplingDevice( sdrDaemonSSD0->m_plugin, - QString("SDRdaemon[%1]").arg(deviceUID), + QString("SDRdaemonSource[%1]").arg(deviceUID), sdrDaemonSSD0->m_hadrwareId, sdrDaemonSSD0->m_deviceId, sdrDaemonSSD0->m_deviceSerial, @@ -220,20 +207,6 @@ void PluginManager::duplicateLocalSampleSourceDevices(uint deviceUID) ); } - if (sdrDaemonFECSSD0 && duplicateSDRDaemonFEC) // append item for a new instance - { - m_sampleSourceDevices.append( - SamplingDevice( - sdrDaemonFECSSD0->m_plugin, - QString("SDRdaemonFEC[%1]").arg(deviceUID), - sdrDaemonFECSSD0->m_hadrwareId, - sdrDaemonFECSSD0->m_deviceId, - sdrDaemonFECSSD0->m_deviceSerial, - deviceUID - ) - ); - } - if (fileSourceSSD0 && duplicateFileSource) // append item for a new instance { m_sampleSourceDevices.append( @@ -294,7 +267,6 @@ void PluginManager::fillSampleSourceSelector(QComboBox* comboBox, uint deviceUID { // For "local" devices show only ones that concern this device set if ((m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonDeviceTypeID) - || (m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonFECDeviceTypeID) || (m_sampleSourceDevices[i].m_deviceId == m_fileSourceDeviceTypeID)) { if (deviceUID != m_sampleSourceDevices[i].m_deviceSequence) { diff --git a/sdrbase/plugin/pluginmanager.h b/sdrbase/plugin/pluginmanager.h index d447a3ee7..d2f5ca9ef 100644 --- a/sdrbase/plugin/pluginmanager.h +++ b/sdrbase/plugin/pluginmanager.h @@ -127,8 +127,6 @@ private: // "Local" sample source device IDs static const QString m_sdrDaemonHardwareID; //!< SDRdaemon hardware ID static const QString m_sdrDaemonDeviceTypeID; //!< SDRdaemon source plugin ID - static const QString m_sdrDaemonFECHardwareID; //!< SDRdaemon with FEC hardware ID - static const QString m_sdrDaemonFECDeviceTypeID; //!< SDRdaemon with FEC source plugin ID static const QString m_fileSourceHardwareID; //!< FileSource source hardware ID static const QString m_fileSourceDeviceTypeID; //!< FileSource source plugin ID diff --git a/sdrbase/sdrbase.pro b/sdrbase/sdrbase.pro index bed3eb47b..cadd268f6 100644 --- a/sdrbase/sdrbase.pro +++ b/sdrbase/sdrbase.pro @@ -119,6 +119,8 @@ SOURCES += mainwindow.cpp\ gui/mypositiondialog.cpp\ gui/scale.cpp\ gui/scaleengine.cpp\ + gui/transverterbutton.cpp\ + gui/transverterdialog.cpp\ gui/valuedial.cpp\ gui/valuedialz.cpp\ dsp/devicesamplesource.cpp\ @@ -228,12 +230,14 @@ HEADERS += mainwindow.h\ gui/mypositiondialog.h\ gui/scale.h\ gui/scaleengine.h\ + gui/transverterbutton.h\ + gui/transverterdialog.h\ gui/valuedial.h\ gui/valuedialz.h\ dsp/devicesamplesource.h\ dsp/devicesamplesink.h\ plugin/pluginapi.h\ - plugin/plugininstanceui.h\ + plugin/plugininstancegui.h\ plugin/plugininterface.h\ plugin/pluginmanager.h\ settings/preferences.h\ @@ -263,6 +267,7 @@ FORMS += mainwindow.ui\ gui/samplingdevicecontrol.ui\ gui/myposdialog.ui\ gui/glspectrumgui.ui\ + gui/transverterdialog.ui\ mainwindow.ui RESOURCES = resources/res.qrc diff --git a/sdrbase/settings/serializable.h b/sdrbase/settings/serializable.h new file mode 100644 index 000000000..b5a088e74 --- /dev/null +++ b/sdrbase/settings/serializable.h @@ -0,0 +1,28 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 SDRBASE_SETTINGS_SERIALIZABLE_H_ +#define SDRBASE_SETTINGS_SERIALIZABLE_H_ + +class Serializable +{ +public: + virtual ~Serializable() {} + virtual QByteArray serialize() const = 0; + virtual bool deserialize(const QByteArray& data) = 0; +}; + +#endif /* SDRBASE_SETTINGS_SERIALIZABLE_H_ */