From c0eca0b2f3ca5a57520da45b4060d3a0ac37f0f2 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 22 Nov 2015 19:56:25 -0500 Subject: [PATCH 01/24] Allow modems to limit/control input rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Modems can now over-ride user rate input and lock/step as needed - Separate digital code defs a bit more so it’s not required when disabled - Testing FSK based on @andresv ’s example at https://github.com/jgaeddert/liquid-dsp/issues/9 --- CMakeLists.txt | 56 ++++++++++++------- src/AppFrame.cpp | 11 ++-- src/CubicSDR.cpp | 5 +- src/CubicSDR.h | 3 ++ src/demod/DemodulatorInstance.cpp | 36 +++---------- src/demod/DemodulatorInstance.h | 3 -- src/demod/DemodulatorPreThread.cpp | 11 ++-- src/demod/DemodulatorPreThread.h | 5 +- src/demod/DemodulatorWorkerThread.cpp | 58 ++++++++++---------- src/modules/modem/Modem.h | 1 + src/modules/modem/ModemAnalog.cpp | 4 ++ src/modules/modem/ModemAnalog.h | 13 ++--- src/modules/modem/ModemDigital.cpp | 4 ++ src/modules/modem/ModemDigital.h | 9 ++-- src/modules/modem/analog/ModemFMStereo.cpp | 8 +++ src/modules/modem/analog/ModemFMStereo.h | 1 + src/modules/modem/analog/ModemIQ.cpp | 6 +++ src/modules/modem/analog/ModemIQ.h | 1 + src/modules/modem/analog/ModemLSB.cpp | 7 +++ src/modules/modem/analog/ModemLSB.h | 1 + src/modules/modem/analog/ModemUSB.cpp | 7 +++ src/modules/modem/analog/ModemUSB.h | 1 + src/modules/modem/digital/ModemFSK.cpp | 62 ++++++++++++++++++++++ src/modules/modem/digital/ModemFSK.h | 29 ++++++++++ src/visual/WaterfallCanvas.cpp | 4 +- src/visual/WaterfallCanvas.h | 1 + 26 files changed, 242 insertions(+), 105 deletions(-) create mode 100644 src/modules/modem/digital/ModemFSK.cpp create mode 100644 src/modules/modem/digital/ModemFSK.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a09cb5c..e15696e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -237,16 +237,6 @@ SET (cubicsdr_sources src/modules/modem/Modem.cpp src/modules/modem/ModemAnalog.cpp src/modules/modem/ModemDigital.cpp - src/modules/modem/digital/ModemASK.cpp - src/modules/modem/digital/ModemAPSK.cpp - src/modules/modem/digital/ModemBPSK.cpp - src/modules/modem/digital/ModemDPSK.cpp - src/modules/modem/digital/ModemPSK.cpp - src/modules/modem/digital/ModemOOK.cpp - src/modules/modem/digital/ModemST.cpp - src/modules/modem/digital/ModemSQAM.cpp - src/modules/modem/digital/ModemQAM.cpp - src/modules/modem/digital/ModemQPSK.cpp src/modules/modem/analog/ModemAM.cpp src/modules/modem/analog/ModemDSB.cpp src/modules/modem/analog/ModemFM.cpp @@ -296,6 +286,23 @@ SET (cubicsdr_sources external/cubicvr2/math/cubic_math.cpp ) +IF(ENABLE_DIGITAL_LAB) + SET (cubicsdr_sources + ${cubicsdr_sources} + src/modules/modem/digital/ModemASK.cpp + src/modules/modem/digital/ModemAPSK.cpp + src/modules/modem/digital/ModemBPSK.cpp + src/modules/modem/digital/ModemDPSK.cpp + src/modules/modem/digital/ModemFSK.cpp + src/modules/modem/digital/ModemPSK.cpp + src/modules/modem/digital/ModemOOK.cpp + src/modules/modem/digital/ModemST.cpp + src/modules/modem/digital/ModemSQAM.cpp + src/modules/modem/digital/ModemQAM.cpp + src/modules/modem/digital/ModemQPSK.cpp + ) +ENDIF() + SET (cubicsdr_headers src/CubicSDRDefs.h src/CubicSDR.h @@ -316,16 +323,6 @@ SET (cubicsdr_headers src/modules/modem/Modem.h src/modules/modem/ModemAnalog.h src/modules/modem/ModemDigital.h - src/modules/modem/digital/ModemASK.h - src/modules/modem/digital/ModemAPSK.h - src/modules/modem/digital/ModemBPSK.h - src/modules/modem/digital/ModemDPSK.h - src/modules/modem/digital/ModemPSK.h - src/modules/modem/digital/ModemOOK.h - src/modules/modem/digital/ModemST.h - src/modules/modem/digital/ModemSQAM.h - src/modules/modem/digital/ModemQAM.h - src/modules/modem/digital/ModemQPSK.h src/modules/modem/analog/ModemAM.h src/modules/modem/analog/ModemDSB.h src/modules/modem/analog/ModemFM.h @@ -391,6 +388,23 @@ SET (cubicsdr_headers external/cubicvr2/math/vec4.h ) +IF(ENABLE_DIGITAL_LAB) +SET(cubicsdr_headers + ${cubicsdr_headers} + src/modules/modem/digital/ModemASK.h + src/modules/modem/digital/ModemAPSK.h + src/modules/modem/digital/ModemBPSK.h + src/modules/modem/digital/ModemDPSK.h + src/modules/modem/digital/ModemFSK.h + src/modules/modem/digital/ModemPSK.h + src/modules/modem/digital/ModemOOK.h + src/modules/modem/digital/ModemST.h + src/modules/modem/digital/ModemSQAM.h + src/modules/modem/digital/ModemQAM.h + src/modules/modem/digital/ModemQPSK.h +) +ENDIF() + SET (CUBICSDR_RESOURCES ${PROJECT_SOURCE_DIR}/font/vera_sans_mono12.fnt ${PROJECT_SOURCE_DIR}/font/vera_sans_mono16.fnt @@ -414,7 +428,9 @@ SOURCE_GROUP("SDR" REGULAR_EXPRESSION "src/sdr/${REG_EXT}") SOURCE_GROUP("Demodulator" REGULAR_EXPRESSION "src/demod/${REG_EXT}") SOURCE_GROUP("Modem" REGULAR_EXPRESSION "src/modules/modem/${REG_EXT}") SOURCE_GROUP("Modem-Analog" REGULAR_EXPRESSION "src/modules/modem/analog/${REG_EXT}") +IF(ENABLE_DIGITAL_LAB) SOURCE_GROUP("Modem-Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}") +ENDIF() SOURCE_GROUP("Audio" REGULAR_EXPRESSION "src/audio/${REG_EXT}") SOURCE_GROUP("Utility" REGULAR_EXPRESSION "src/util/${REG_EXT}") SOURCE_GROUP("Visual" REGULAR_EXPRESSION "src/visual/${REG_EXT}") diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 5b3daa2..35f0b43 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -85,11 +85,12 @@ AppFrame::AppFrame() : demodModeSelectorAdv->addChoice(2, "BPSK"); demodModeSelectorAdv->addChoice(3, "DPSK"); demodModeSelectorAdv->addChoice(4, "PSK"); - demodModeSelectorAdv->addChoice(5, "OOK"); - demodModeSelectorAdv->addChoice(6, "ST"); - demodModeSelectorAdv->addChoice(7, "SQAM"); - demodModeSelectorAdv->addChoice(8, "QAM"); - demodModeSelectorAdv->addChoice(9, "QPSK"); + demodModeSelectorAdv->addChoice(5, "FSK"); + demodModeSelectorAdv->addChoice(6, "OOK"); + demodModeSelectorAdv->addChoice(7, "ST"); + demodModeSelectorAdv->addChoice(8, "SQAM"); + demodModeSelectorAdv->addChoice(9, "QAM"); + demodModeSelectorAdv->addChoice(10, "QPSK"); demodModeSelectorAdv->setHelpTip("Choose advanced modulation types."); demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0); diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 4227bdf..5084294 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -172,17 +172,20 @@ bool CubicSDR::OnInit() { Modem::addModemFactory(new ModemDSB); Modem::addModemFactory(new ModemIQ); +#ifdef ENABLE_DIGITAL_LAB Modem::addModemFactory(new ModemAPSK); Modem::addModemFactory(new ModemASK); Modem::addModemFactory(new ModemBPSK); Modem::addModemFactory(new ModemDPSK); + Modem::addModemFactory(new ModemFSK); Modem::addModemFactory(new ModemOOK); Modem::addModemFactory(new ModemPSK); Modem::addModemFactory(new ModemQAM); Modem::addModemFactory(new ModemQPSK); Modem::addModemFactory(new ModemSQAM); Modem::addModemFactory(new ModemST); - +#endif + frequency = wxGetApp().getConfig()->getCenterFreq(); offset = 0; ppm = 0; diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 54bb4b0..fd774ce 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -37,16 +37,19 @@ #include "ModemDSB.h" #include "ModemIQ.h" +#ifdef ENABLE_DIGITAL_LAB #include "ModemAPSK.h" #include "ModemASK.h" #include "ModemBPSK.h" #include "ModemDPSK.h" +#include "ModemFSK.h" #include "ModemOOK.h" #include "ModemPSK.h" #include "ModemQAM.h" #include "ModemQPSK.h" #include "ModemSQAM.h" #include "ModemST.h" +#endif #include diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 88139be..62074c8 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -14,7 +14,6 @@ DemodulatorInstance::DemodulatorInstance() : follow.store(false); currentAudioSampleRate.store(0); currentFrequency.store(0); - currentBandwidth.store(0); currentOutputDevice.store(-1); currentAudioGain.store(1.0); @@ -24,7 +23,7 @@ DemodulatorInstance::DemodulatorInstance() : pipeDemodCommand = new DemodulatorThreadCommandQueue; pipeDemodNotify = new DemodulatorThreadCommandQueue; - demodulatorPreThread = new DemodulatorPreThread(); + demodulatorPreThread = new DemodulatorPreThread(this); demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData); demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData); demodulatorPreThread->setOutputQueue("NotifyQueue",pipeDemodNotify); @@ -254,12 +253,6 @@ int DemodulatorInstance::getOutputDevice() { return currentOutputDevice; } -void DemodulatorInstance::checkBandwidth() { -// if ((currentDemodType == DEMOD_TYPE_USB || currentDemodType == DEMOD_TYPE_LSB) && (getBandwidth() % 2)) { -// setBandwidth(getBandwidth()+1); -// } -} - void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) { currentDemodType = demod_type_in; @@ -274,7 +267,6 @@ void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) { demodulatorPreThread->getParams().demodType = currentDemodType; if (!active) { - checkBandwidth(); demodulatorPreThread->setDemodType(currentDemodType); } else if (demodulatorThread && threadQueueControl) { demodulatorPreThread->setDemodType(currentDemodType); @@ -318,32 +310,18 @@ int DemodulatorInstance::getDemodulatorCons() { } void DemodulatorInstance::setBandwidth(int bw) { - if (currentDemodType == "I/Q") { - if (currentAudioSampleRate) { - bw = currentAudioSampleRate; - } else { - bw = AudioThread::deviceSampleRate[getOutputDevice()]; - } - } if (!active && demodulatorPreThread != NULL) { - currentBandwidth = bw; - checkBandwidth(); - demodulatorPreThread->getParams().bandwidth = currentBandwidth; + demodulatorPreThread->getParams().bandwidth = bw; } else if (demodulatorPreThread && pipeDemodCommand) { DemodulatorThreadCommand command; command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH; - currentBandwidth = bw; - checkBandwidth(); - command.llong_value = currentBandwidth; + command.llong_value = bw; pipeDemodCommand->push(command); } } int DemodulatorInstance::getBandwidth() { - if (!currentBandwidth) { - currentBandwidth = demodulatorPreThread->getParams().bandwidth; - } - return currentBandwidth; + return demodulatorPreThread->getParams().bandwidth; } void DemodulatorInstance::setFrequency(long long freq) { @@ -387,9 +365,9 @@ void DemodulatorInstance::setAudioSampleRate(int sampleRate) { } int DemodulatorInstance::getAudioSampleRate() { - if (!currentAudioSampleRate) { - currentAudioSampleRate = audioThread->getSampleRate(); - } + currentAudioSampleRate = audioThread->getSampleRate(); + demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate; + return currentAudioSampleRate; } diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index 818d72b..d559f69 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -97,8 +97,6 @@ protected: private: - void checkBandwidth(); - std::atomic label; // std::atomic_bool terminated; // std::atomic_bool demodTerminated; // @@ -109,7 +107,6 @@ private: std::atomic_bool muted; std::atomic_llong currentFrequency; - std::atomic_int currentBandwidth; std::string currentDemodType; std::atomic_int currentOutputDevice; std::atomic_int currentAudioSampleRate; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 86bac7f..9604a38 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -7,10 +7,12 @@ #include "DemodulatorPreThread.h" #include "CubicSDR.h" +#include "DemodulatorInstance.h" -DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL) +DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL) { initialized.store(false); + this->parent = parent; freqShifter = nco_crcf_create(LIQUID_VCO); shiftFrequency = 0; @@ -82,11 +84,7 @@ void DemodulatorPreThread::run() { if (command.llong_value < 1500) { command.llong_value = 1500; } - if (command.llong_value > params.sampleRate) { - tempParams.bandwidth = params.sampleRate; - } else { - tempParams.bandwidth = command.llong_value; - } + tempParams.bandwidth = command.llong_value; bandwidthChanged = true; break; case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY: @@ -257,6 +255,7 @@ void DemodulatorPreThread::setParams(DemodulatorThreadParameters ¶ms_in) { void DemodulatorPreThread::setDemodType(std::string demodType) { this->newDemodType = demodType; DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD); + command.sampleRate = params.sampleRate; command.demodType = demodType; command.bandwidth = params.bandwidth; command.audioSampleRate = params.audioSampleRate; diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index f339a70..810cd4e 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -7,10 +7,12 @@ #include "DemodDefs.h" #include "DemodulatorWorkerThread.h" +class DemodulatorInstance; + class DemodulatorPreThread : public IOThread { public: - DemodulatorPreThread(); + DemodulatorPreThread(DemodulatorInstance *parent); ~DemodulatorPreThread(); void run(); @@ -28,6 +30,7 @@ public: ModemKit *getModemKit(); protected: + DemodulatorInstance *parent; msresamp_crcf iqResampler; double iqResampleRatio; std::vector resampledData; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index df7fab2..46fdadb 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -26,62 +26,62 @@ void DemodulatorWorkerThread::run() { while (!done) { commandQueue->pop(command); switch (command.cmd) { - case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS: - filterChanged = true; - filterCommand = command; - break; - case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD: - makeDemod = true; - demodCommand = command; - break; - default: - break; + case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS: + filterChanged = true; + filterCommand = command; + break; + case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD: + makeDemod = true; + demodCommand = command; + break; + default: + break; } done = commandQueue->empty(); } - if ((makeDemod || filterChanged) && !terminated) { DemodulatorWorkerThreadResult result(DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS); - - float As = 60.0f; // stop-band attenuation [dB] - - if (filterCommand.sampleRate && filterCommand.bandwidth) { - result.iqResampleRatio = (double) (filterCommand.bandwidth) / (double) filterCommand.sampleRate; - result.iqResampler = msresamp_crcf_create(result.iqResampleRatio, As); + + + if (filterCommand.sampleRate) { + result.sampleRate = filterCommand.sampleRate; } - + if (makeDemod) { cModem = Modem::makeModem(demodCommand.demodType); cModemType = demodCommand.demodType; + result.sampleRate = demodCommand.sampleRate; } result.modem = cModem; if (makeDemod && demodCommand.bandwidth && demodCommand.audioSampleRate) { if (cModem != nullptr) { - cModemKit = cModem->buildKit(demodCommand.bandwidth, demodCommand.audioSampleRate); + result.bandwidth = cModem->checkSampleRate(demodCommand.bandwidth, demodCommand.audioSampleRate); + cModemKit = cModem->buildKit(result.bandwidth, demodCommand.audioSampleRate); } else { cModemKit = nullptr; } } else if (filterChanged && filterCommand.bandwidth && filterCommand.audioSampleRate) { if (cModem != nullptr) { - cModemKit = cModem->buildKit(filterCommand.bandwidth, filterCommand.audioSampleRate); + result.bandwidth = cModem->checkSampleRate(filterCommand.bandwidth, filterCommand.audioSampleRate); + cModemKit = cModem->buildKit(result.bandwidth, filterCommand.audioSampleRate); } else { cModemKit = nullptr; } } else if (makeDemod) { cModemKit = nullptr; } + + float As = 60.0f; // stop-band attenuation [dB] + + if (result.sampleRate && result.bandwidth) { + result.bandwidth = cModem->checkSampleRate(result.bandwidth, makeDemod?demodCommand.audioSampleRate:filterCommand.audioSampleRate); + result.iqResampleRatio = (double) (result.bandwidth) / (double) result.sampleRate; + result.iqResampler = msresamp_crcf_create(result.iqResampleRatio, As); + } + result.modemKit = cModemKit; - - if (filterCommand.bandwidth) { - result.bandwidth = filterCommand.bandwidth; - } - - if (filterCommand.sampleRate) { - result.sampleRate = filterCommand.sampleRate; - } - result.modemType = cModemType; resultQueue->push(result); diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h index 035bbe4..51629e5 100644 --- a/src/modules/modem/Modem.h +++ b/src/modules/modem/Modem.h @@ -44,6 +44,7 @@ public: Modem(); virtual ~Modem(); + virtual int checkSampleRate(long long sampleRate, int audioSampleRate) = 0; virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate) = 0; virtual void disposeKit(ModemKit *kit) = 0; virtual void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) = 0; diff --git a/src/modules/modem/ModemAnalog.cpp b/src/modules/modem/ModemAnalog.cpp index eed8d5c..c9020f5 100644 --- a/src/modules/modem/ModemAnalog.cpp +++ b/src/modules/modem/ModemAnalog.cpp @@ -8,6 +8,10 @@ std::string ModemAnalog::getType() { return "analog"; } +int ModemAnalog::checkSampleRate(long long sampleRate, int audioSampleRate) { + return sampleRate; +} + ModemKit *ModemAnalog::buildKit(long long sampleRate, int audioSampleRate) { ModemKitAnalog *akit = new ModemKitAnalog; diff --git a/src/modules/modem/ModemAnalog.h b/src/modules/modem/ModemAnalog.h index f73a933..dbf07b9 100644 --- a/src/modules/modem/ModemAnalog.h +++ b/src/modules/modem/ModemAnalog.h @@ -16,12 +16,13 @@ class ModemAnalog : public Modem { public: ModemAnalog(); std::string getType(); - ModemKit *buildKit(long long sampleRate, int audioSampleRate); - void disposeKit(ModemKit *kit); - void initOutputBuffers(ModemKitAnalog *akit, ModemIQData *input); - void buildAudioOutput(ModemKitAnalog *akit, AudioThreadInput *audioOut, bool autoGain); - std::vector *getDemodOutputData(); - std::vector *getResampledOutputData(); + virtual int checkSampleRate(long long sampleRate, int audioSampleRate); + virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate); + virtual void disposeKit(ModemKit *kit); + virtual void initOutputBuffers(ModemKitAnalog *akit, ModemIQData *input); + virtual void buildAudioOutput(ModemKitAnalog *akit, AudioThreadInput *audioOut, bool autoGain); + virtual std::vector *getDemodOutputData(); + virtual std::vector *getResampledOutputData(); protected: int bufSize; std::vector demodOutputData; diff --git a/src/modules/modem/ModemDigital.cpp b/src/modules/modem/ModemDigital.cpp index 6c2224d..00f40ac 100644 --- a/src/modules/modem/ModemDigital.cpp +++ b/src/modules/modem/ModemDigital.cpp @@ -8,6 +8,10 @@ std::string ModemDigital::getType() { return "digital"; } +int ModemDigital::checkSampleRate(long long sampleRate, int audioSampleRate) { + return sampleRate; +} + ModemKit *ModemDigital::buildKit(long long sampleRate, int audioSampleRate) { ModemKitDigital *dkit = new ModemKitDigital; diff --git a/src/modules/modem/ModemDigital.h b/src/modules/modem/ModemDigital.h index 34a119b..e78b5a7 100644 --- a/src/modules/modem/ModemDigital.h +++ b/src/modules/modem/ModemDigital.h @@ -13,10 +13,11 @@ class ModemDigital : public Modem { public: ModemDigital(); std::string getType(); - ModemKit *buildKit(long long sampleRate, int audioSampleRate); - void disposeKit(ModemKit *kit); - void digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input); - void digitalFinish(ModemKitDigital *kit, modem mod); + virtual int checkSampleRate(long long sampleRate, int audioSampleRate); + virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate); + virtual void disposeKit(ModemKit *kit); + virtual void digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input); + virtual void digitalFinish(ModemKitDigital *kit, modem mod); virtual void setDemodulatorLock(bool demod_lock_in); virtual int getDemodulatorLock(); diff --git a/src/modules/modem/analog/ModemFMStereo.cpp b/src/modules/modem/analog/ModemFMStereo.cpp index 04ec5d7..864e566 100644 --- a/src/modules/modem/analog/ModemFMStereo.cpp +++ b/src/modules/modem/analog/ModemFMStereo.cpp @@ -30,6 +30,14 @@ Modem *ModemFMStereo::factory() { return new ModemFMStereo; } +int ModemFMStereo::checkSampleRate(long long sampleRate, int audioSampleRate) { + if (sampleRate < 100000) { + return 100000; + } else { + return sampleRate; + } +} + ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) { ModemKitFMStereo *kit = new ModemKitFMStereo; diff --git a/src/modules/modem/analog/ModemFMStereo.h b/src/modules/modem/analog/ModemFMStereo.h index cbc5aec..88d49f5 100644 --- a/src/modules/modem/analog/ModemFMStereo.h +++ b/src/modules/modem/analog/ModemFMStereo.h @@ -23,6 +23,7 @@ public: std::string getType(); std::string getName(); Modem *factory(); + int checkSampleRate(long long sampleRate, int audioSampleRate); ModemKit *buildKit(long long sampleRate, int audioSampleRate); void disposeKit(ModemKit *kit); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); diff --git a/src/modules/modem/analog/ModemIQ.cpp b/src/modules/modem/analog/ModemIQ.cpp index 6c984f6..bcf7d97 100644 --- a/src/modules/modem/analog/ModemIQ.cpp +++ b/src/modules/modem/analog/ModemIQ.cpp @@ -10,6 +10,8 @@ Modem *ModemIQ::factory() { ModemKit *ModemIQ::buildKit(long long sampleRate, int audioSampleRate) { ModemKit *kit = new ModemKit; + kit->sampleRate = sampleRate; + kit->audioSampleRate = audioSampleRate; return kit; } @@ -25,6 +27,10 @@ void ModemIQ::disposeKit(ModemKit *kit) { delete kit; } +int ModemIQ::checkSampleRate(long long sampleRate, int audioSampleRate) { + return audioSampleRate; +} + void ModemIQ::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { int bufSize = input->data.size(); diff --git a/src/modules/modem/analog/ModemIQ.h b/src/modules/modem/analog/ModemIQ.h index abd9d94..ea0c614 100644 --- a/src/modules/modem/analog/ModemIQ.h +++ b/src/modules/modem/analog/ModemIQ.h @@ -8,6 +8,7 @@ public: std::string getName(); Modem *factory(); ModemKit *buildKit(long long sampleRate, int audioSampleRate); + int checkSampleRate(long long sampleRate, int audioSampleRate); void disposeKit(ModemKit *kit); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp index 44fb116..06e1584 100644 --- a/src/modules/modem/analog/ModemLSB.cpp +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -19,6 +19,13 @@ ModemLSB::~ModemLSB() { ampmodem_destroy(demodAM_LSB); } +int ModemLSB::checkSampleRate(long long sampleRate, int audioSampleRate) { + if (sampleRate % 2 == 0) { + return sampleRate; + } + return sampleRate+1; +} + void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitAnalog *akit = (ModemKitAnalog *)kit; diff --git a/src/modules/modem/analog/ModemLSB.h b/src/modules/modem/analog/ModemLSB.h index cbdc176..9ea4c0e 100644 --- a/src/modules/modem/analog/ModemLSB.h +++ b/src/modules/modem/analog/ModemLSB.h @@ -8,6 +8,7 @@ public: ~ModemLSB(); std::string getName(); Modem *factory(); + int checkSampleRate(long long sampleRate, int audioSampleRate); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp index 0482d4f..408d314 100644 --- a/src/modules/modem/analog/ModemUSB.cpp +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -19,6 +19,13 @@ ModemUSB::~ModemUSB() { ampmodem_destroy(demodAM_USB); } +int ModemUSB::checkSampleRate(long long sampleRate, int audioSampleRate) { + if (sampleRate % 2 == 0) { + return sampleRate; + } + return sampleRate+1; +} + void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitAnalog *akit = (ModemKitAnalog *)kit; diff --git a/src/modules/modem/analog/ModemUSB.h b/src/modules/modem/analog/ModemUSB.h index d6d3a4d..cff6ac4 100644 --- a/src/modules/modem/analog/ModemUSB.h +++ b/src/modules/modem/analog/ModemUSB.h @@ -7,6 +7,7 @@ public: ~ModemUSB(); std::string getName(); Modem *factory(); + int checkSampleRate(long long sampleRate, int audioSampleRate); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/modules/modem/digital/ModemFSK.cpp b/src/modules/modem/digital/ModemFSK.cpp new file mode 100644 index 0000000..f73d99c --- /dev/null +++ b/src/modules/modem/digital/ModemFSK.cpp @@ -0,0 +1,62 @@ +#include "ModemFSK.h" + +ModemFSK::ModemFSK() { + demodulatorCons.store(2); + currentDemodCons.store(0); + updateDemodulatorCons(2); +} + +Modem *ModemFSK::factory() { + return new ModemFSK; +} + +ModemKit *ModemFSK::buildKit(long long sampleRate, int audioSampleRate) { + ModemKitFSK *dkit = new ModemKitFSK; + dkit->m = 1; + dkit->k = sampleRate / 9600; + dkit->bandwidth = 7000.0 / sampleRate; + + dkit->demodFSK = fskdem_create(dkit->m, dkit->k, dkit->bandwidth); + + dkit->sampleRate = sampleRate; + dkit->audioSampleRate = audioSampleRate; + + return dkit; +} + +void ModemFSK::disposeKit(ModemKit *kit) { + ModemKitFSK *dkit = (ModemKitFSK *)kit; + + delete dkit; +} + +std::string ModemFSK::getName() { + return "FSK"; +} + +ModemFSK::~ModemFSK() { + +} + +void ModemFSK::updateDemodulatorCons(int cons) { + +} + +void ModemFSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitFSK *dkit = (ModemKitFSK *)kit; + + digitalStart(dkit, nullptr, input); + + dkit->inputBuffer.insert(dkit->inputBuffer.end(),input->data.begin(),input->data.end()); + + while (dkit->inputBuffer.size() >= dkit->k) { + unsigned int sym_out; + + sym_out = fskdem_demodulate(dkit->demodFSK, &dkit->inputBuffer[0]); +// std::cout << "ferror: " << fskdem_get_frequency_error(dkit->demodFSK) << std::endl; + printf("%01X", sym_out); + dkit->inputBuffer.erase(dkit->inputBuffer.begin(),dkit->inputBuffer.begin()+dkit->k); + } + + digitalFinish(dkit, nullptr); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemFSK.h b/src/modules/modem/digital/ModemFSK.h new file mode 100644 index 0000000..f1fe62c --- /dev/null +++ b/src/modules/modem/digital/ModemFSK.h @@ -0,0 +1,29 @@ +#pragma once +#include "ModemDigital.h" + +class ModemKitFSK : public ModemKitDigital { +public: + float sps, spacing, bandwidth; + unsigned int m, k; + + fskdem demodFSK; + std::vector inputBuffer; +}; + + +class ModemFSK : public ModemDigital { +public: + ModemFSK(); + ~ModemFSK(); + std::string getName(); + Modem *factory(); + ModemKit *buildKit(long long sampleRate, int audioSampleRate); + void disposeKit(ModemKit *kit); + void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + + +private: + fskdem dem; +}; + diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index ce4630e..319dc5a 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -461,7 +461,7 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { bwDiff = -bwDiff; } - int currentBW = demod->getBandwidth(); + int currentBW = dragBW; currentBW = currentBW + bwDiff; if (currentBW > CHANNELIZER_RATE_MAX) { @@ -472,6 +472,7 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { } demod->setBandwidth(currentBW); + dragBW = currentBW; } if (dragState == WF_DRAG_FREQUENCY) { @@ -601,6 +602,7 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) { DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator(); if (demod) { dragOfs = (long long) (mouseTracker.getMouseX() * (float) getBandwidth()) + getCenterFrequency() - (getBandwidth() / 2) - demod->getFrequency(); + dragBW = demod->getBandwidth(); } wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getActiveDemodulator(), false); } diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index 9efa8c4..093036d 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -68,6 +68,7 @@ private: float hoverAlpha; int linesPerSecond; float scaleMove; + int dragBW; SpectrumVisualDataQueue visualDataQueue; Timer gTimer; From 7b301fadc16c5062b90d33633f2dd9b7149ca4b2 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 22 Nov 2015 23:25:45 -0500 Subject: [PATCH 02/24] Clean up some early prototype garbage.. --- src/demod/DemodDefs.h | 23 --- src/demod/DemodulatorInstance.cpp | 92 ++-------- src/demod/DemodulatorInstance.h | 6 +- src/demod/DemodulatorPreThread.cpp | 190 +++++++++++++-------- src/demod/DemodulatorPreThread.h | 26 ++- src/demod/DemodulatorThread.cpp | 10 +- src/demod/DemodulatorThread.h | 1 - src/modules/modem/analog/ModemFMStereo.cpp | 4 +- src/visual/PrimaryGLContext.h | 1 - 9 files changed, 156 insertions(+), 197 deletions(-) diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index 52f1050..8bc962a 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -14,9 +14,6 @@ class DemodulatorThreadCommand { public: enum DemodulatorThreadCommandEnum { DEMOD_THREAD_CMD_NULL, - DEMOD_THREAD_CMD_SET_BANDWIDTH, - DEMOD_THREAD_CMD_SET_FREQUENCY, - DEMOD_THREAD_CMD_SET_AUDIO_RATE, DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED, DEMOD_THREAD_CMD_DEMOD_TERMINATED, DEMOD_THREAD_CMD_AUDIO_TERMINATED @@ -124,23 +121,3 @@ typedef ThreadQueue DemodulatorThreadInputQueue; typedef ThreadQueue DemodulatorThreadPostInputQueue; typedef ThreadQueue DemodulatorThreadCommandQueue; typedef ThreadQueue DemodulatorThreadControlCommandQueue; - -class DemodulatorThreadParameters { -public: - long long frequency; - long long sampleRate; - unsigned int bandwidth; // set equal to disable second stage re-sampling? - unsigned int audioSampleRate; - - std::string demodType; - - DemodulatorThreadParameters() : - frequency(0), sampleRate(DEFAULT_SAMPLE_RATE), bandwidth(200000), audioSampleRate(0), - demodType("FM") { - - } - - ~DemodulatorThreadParameters() { - - } -}; diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 62074c8..cf9ba0f 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -12,22 +12,18 @@ DemodulatorInstance::DemodulatorInstance() : muted.store(false); tracking.store(false); follow.store(false); - currentAudioSampleRate.store(0); - currentFrequency.store(0); currentOutputDevice.store(-1); currentAudioGain.store(1.0); label = new std::string("Unnamed"); pipeIQInputData = new DemodulatorThreadInputQueue; pipeIQDemodData = new DemodulatorThreadPostInputQueue; - pipeDemodCommand = new DemodulatorThreadCommandQueue; pipeDemodNotify = new DemodulatorThreadCommandQueue; demodulatorPreThread = new DemodulatorPreThread(this); demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData); demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData); demodulatorPreThread->setOutputQueue("NotifyQueue",pipeDemodNotify); - demodulatorPreThread->setInputQueue("CommandQueue",pipeDemodCommand); pipeAudioData = new AudioThreadInputQueue; threadQueueControl = new DemodulatorThreadControlCommandQueue; @@ -41,8 +37,6 @@ DemodulatorInstance::DemodulatorInstance() : audioThread = new AudioThread(); audioThread->setInputQueue("AudioDataInput", pipeAudioData); audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify); - - currentDemodType = demodulatorPreThread->getParams().demodType; } DemodulatorInstance::~DemodulatorInstance() { @@ -51,7 +45,6 @@ DemodulatorInstance::~DemodulatorInstance() { delete demodulatorPreThread; delete pipeIQInputData; delete pipeIQDemodData; - delete pipeDemodCommand; delete pipeDemodNotify; delete threadQueueControl; delete pipeAudioData; @@ -66,17 +59,8 @@ void DemodulatorInstance::run() { return; } -// while (!isTerminated()) { -// std::this_thread::sleep_for(std::chrono::milliseconds(1)); -// } - - currentFrequency = demodulatorPreThread->getParams().frequency; - currentAudioSampleRate = AudioThread::deviceSampleRate[getOutputDevice()]; - demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate; - setDemodulatorType(demodulatorPreThread->getParams().demodType); - t_Audio = new std::thread(&AudioThread::threadMain, audioThread); - + #ifdef __APPLE__ // Already using pthreads, might as well do some custom init.. pthread_attr_t attr; size_t size; @@ -112,10 +96,6 @@ void DemodulatorInstance::updateLabel(long long freq) { setLabel(newLabel.str()); } -DemodulatorThreadCommandQueue *DemodulatorInstance::getCommandQueue() { - return pipeDemodCommand; -} - void DemodulatorInstance::terminate() { std::cout << "Terminating demodulator audio thread.." << std::endl; audioThread->terminate(); @@ -254,27 +234,14 @@ int DemodulatorInstance::getOutputDevice() { } void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) { - currentDemodType = demod_type_in; - - if (currentDemodType == "I/Q") { - if (currentAudioSampleRate) { - setBandwidth(currentAudioSampleRate); - } else { - setBandwidth(AudioThread::deviceSampleRate[getOutputDevice()]); - } - } setGain(getGain()); - - demodulatorPreThread->getParams().demodType = currentDemodType; - if (!active) { - demodulatorPreThread->setDemodType(currentDemodType); - } else if (demodulatorThread && threadQueueControl) { - demodulatorPreThread->setDemodType(currentDemodType); + if (demodulatorPreThread) { + demodulatorPreThread->setDemodType(demod_type_in); } } std::string DemodulatorInstance::getDemodulatorType() { - return currentDemodType; + return demodulatorPreThread->getDemodType(); } void DemodulatorInstance::setDemodulatorLock(bool demod_lock_in) { @@ -310,65 +277,34 @@ int DemodulatorInstance::getDemodulatorCons() { } void DemodulatorInstance::setBandwidth(int bw) { - if (!active && demodulatorPreThread != NULL) { - demodulatorPreThread->getParams().bandwidth = bw; - } else if (demodulatorPreThread && pipeDemodCommand) { - DemodulatorThreadCommand command; - command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH; - command.llong_value = bw; - pipeDemodCommand->push(command); - } + demodulatorPreThread->setBandwidth(bw); } int DemodulatorInstance::getBandwidth() { - return demodulatorPreThread->getParams().bandwidth; + return demodulatorPreThread->getBandwidth(); } void DemodulatorInstance::setFrequency(long long freq) { if ((freq - getBandwidth() / 2) <= 0) { freq = getBandwidth() / 2; } - if (!active) { - currentFrequency = freq; - demodulatorPreThread->getParams().frequency = currentFrequency; - } else if (demodulatorPreThread && pipeDemodCommand) { - DemodulatorThreadCommand command; - command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY; - currentFrequency = freq; - command.llong_value = freq; - pipeDemodCommand->push(command); - } + + demodulatorPreThread->setFrequency(freq); } long long DemodulatorInstance::getFrequency() { - if (!currentFrequency) { - currentFrequency = demodulatorPreThread->getParams().frequency; - } - return currentFrequency; + return demodulatorPreThread->getFrequency(); } - void DemodulatorInstance::setAudioSampleRate(int sampleRate) { - if (terminated) { - currentAudioSampleRate = sampleRate; - demodulatorPreThread->getParams().audioSampleRate = sampleRate; - } else if (demodulatorPreThread && pipeDemodCommand) { - DemodulatorThreadCommand command; - command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE; - currentAudioSampleRate = sampleRate; - command.llong_value = sampleRate; - pipeDemodCommand->push(command); - } - if (currentDemodType == "I/Q") { - setBandwidth(currentAudioSampleRate); - } + demodulatorPreThread->setSampleRate(sampleRate); } int DemodulatorInstance::getAudioSampleRate() { - currentAudioSampleRate = audioThread->getSampleRate(); - demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate; - - return currentAudioSampleRate; + if (!audioThread) { + return 0; + } + return audioThread->getSampleRate(); } diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index d559f69..fa14679 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -73,7 +73,7 @@ public: void setAudioSampleRate(int sampleRate); int getAudioSampleRate(); - + bool isFollow(); void setFollow(bool follow); @@ -89,7 +89,6 @@ protected: DemodulatorThreadInputQueue* pipeIQInputData; DemodulatorThreadPostInputQueue* pipeIQDemodData; AudioThreadInputQueue *pipeAudioData; - DemodulatorThreadCommandQueue* pipeDemodCommand; DemodulatorThreadCommandQueue* pipeDemodNotify; DemodulatorPreThread *demodulatorPreThread; DemodulatorThread *demodulatorThread; @@ -106,10 +105,7 @@ private: std::atomic_bool squelch; std::atomic_bool muted; - std::atomic_llong currentFrequency; - std::string currentDemodType; std::atomic_int currentOutputDevice; - std::atomic_int currentAudioSampleRate; std::atomic currentAudioGain; std::atomic_bool follow, tracking; }; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 9604a38..9a4d5db 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -9,7 +9,7 @@ #include "CubicSDR.h" #include "DemodulatorInstance.h" -DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL) +DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL) { initialized.store(false); this->parent = parent; @@ -23,18 +23,20 @@ DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThre workerThread = new DemodulatorWorkerThread(); workerThread->setInputQueue("WorkerCommandQueue",workerQueue); workerThread->setOutputQueue("WorkerResultQueue",workerResults); + + newSampleRate = currentSampleRate = 0; + newBandwidth = currentBandwidth = 0; + newAudioSampleRate = currentAudioSampleRate = 0; + newFrequency = currentFrequency = 0; + + sampleRateChanged.store(false); + frequencyChanged.store(false); + bandwidthChanged.store(false); + audioSampleRateChanged.store(false); } void DemodulatorPreThread::initialize() { - iqResampleRatio = (double) (params.bandwidth) / (double) params.sampleRate; - - float As = 60.0f; // stop-band attenuation [dB] - - iqResampler = msresamp_crcf_create(iqResampleRatio, As); - initialized.store(true); - - lastParams = params; } DemodulatorPreThread::~DemodulatorPreThread() { @@ -59,83 +61,86 @@ void DemodulatorPreThread::run() { iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput"); iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOutput"); threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); - commandQueue = ( DemodulatorThreadCommandQueue*)getInputQueue("CommandQueue"); std::vector in_buf_data; std::vector out_buf_data; - setDemodType(params.demodType); t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread); while (!terminated) { DemodulatorThreadIQData *inp; iqInputQueue->pop(inp); - - bool bandwidthChanged = false; - bool rateChanged = false; - DemodulatorThreadParameters tempParams = params; - - if (!commandQueue->empty()) { - while (!commandQueue->empty()) { - DemodulatorThreadCommand command; - commandQueue->pop(command); - switch (command.cmd) { - case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH: - if (command.llong_value < 1500) { - command.llong_value = 1500; - } - tempParams.bandwidth = command.llong_value; - bandwidthChanged = true; - break; - case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY: - params.frequency = tempParams.frequency = command.llong_value; - break; - case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE: - tempParams.audioSampleRate = (int)command.llong_value; - rateChanged = true; - break; - default: - break; - } + + if (frequencyChanged.load()) { + currentFrequency = newFrequency; + frequencyChanged.store(false); + } + + if (inp->sampleRate != currentSampleRate) { + newSampleRate = inp->sampleRate; + if (newSampleRate) { + sampleRateChanged.store(true); } } - - if (inp->sampleRate != tempParams.sampleRate && inp->sampleRate) { - tempParams.sampleRate = inp->sampleRate; - rateChanged = true; + + if (!newAudioSampleRate) { + newAudioSampleRate = parent->getAudioSampleRate(); + if (newAudioSampleRate) { + audioSampleRateChanged.store(true); + } + } else if (parent->getAudioSampleRate() != newAudioSampleRate) { + int newRate; + if ((newRate = parent->getAudioSampleRate())) { + newAudioSampleRate = parent->getAudioSampleRate(); + audioSampleRateChanged.store(true); + } } - - if (bandwidthChanged || rateChanged) { + + if (demodTypeChanged.load() && (newSampleRate && newAudioSampleRate && newBandwidth)) { + DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD); + command.frequency = newFrequency; + command.sampleRate = newSampleRate; + command.demodType = newDemodType; + command.bandwidth = newBandwidth; + command.audioSampleRate = newAudioSampleRate; + workerQueue->push(command); + demodType = newDemodType; + sampleRateChanged.store(false); + audioSampleRateChanged.store(false); + demodTypeChanged.store(false); + } else if (cModemKit && cModem && (bandwidthChanged.load() || sampleRateChanged.load() || audioSampleRateChanged.load()) && (newSampleRate && newAudioSampleRate && newBandwidth)) { DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS); - command.sampleRate = tempParams.sampleRate; - command.audioSampleRate = tempParams.audioSampleRate; - command.bandwidth = tempParams.bandwidth; - command.frequency = tempParams.frequency; - + command.frequency = newFrequency; + command.sampleRate = newSampleRate; + command.bandwidth = newBandwidth; + command.audioSampleRate = newAudioSampleRate; + bandwidthChanged.store(false); + sampleRateChanged.store(false); + audioSampleRateChanged.store(false); workerQueue->push(command); } - + if (!initialized) { inp->decRefCount(); continue; } // Requested frequency is not center, shift it into the center! - if ((params.frequency - inp->frequency) != shiftFrequency || rateChanged) { - shiftFrequency = params.frequency - inp->frequency; + if ((currentFrequency - inp->frequency) != shiftFrequency) { + shiftFrequency = currentFrequency - inp->frequency; if (abs(shiftFrequency) <= (int) ((double) (inp->sampleRate / 2) * 1.5)) { nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) inp->sampleRate))); } } - if (abs(shiftFrequency) > (int) ((double) (inp->sampleRate / 2) * 1.5)) { + if (cModem && cModemKit && abs(shiftFrequency) > (int) ((double) (inp->sampleRate / 2) * 1.5)) { inp->decRefCount(); continue; } // std::lock_guard < std::mutex > lock(inp->m_mutex); std::vector *data = &inp->data; - if (data->size() && (inp->sampleRate == params.sampleRate)) { + if (data->size() && (inp->sampleRate == currentSampleRate) && cModem && cModemKit) { int bufSize = data->size(); if (in_buf_data.size() != bufSize) { @@ -184,7 +189,7 @@ void DemodulatorPreThread::run() { resamp->modemType = demodType; resamp->modem = cModem; resamp->modemKit = cModemKit; - resamp->sampleRate = params.bandwidth; + resamp->sampleRate = currentBandwidth; iqOutputQueue->push(resamp); } @@ -198,7 +203,6 @@ void DemodulatorPreThread::run() { switch (result.cmd) { case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS: - if (result.iqResampler) { if (iqResampler) { msresamp_crcf_destroy(iqResampler); @@ -213,21 +217,23 @@ void DemodulatorPreThread::run() { if (result.modemKit != nullptr) { cModemKit = result.modemKit; + currentAudioSampleRate = cModemKit->audioSampleRate; } if (result.bandwidth) { - params.bandwidth = result.bandwidth; + currentBandwidth = result.bandwidth; } if (result.sampleRate) { - params.sampleRate = result.sampleRate; + currentSampleRate = result.sampleRate; } if (result.modemType != "") { demodType = result.modemType; - params.demodType = result.modemType; demodTypeChanged.store(false); } + + shiftFrequency = inp->frequency-1; break; default: break; @@ -244,22 +250,8 @@ void DemodulatorPreThread::run() { std::cout << "Demodulator preprocessor thread done." << std::endl; } -DemodulatorThreadParameters &DemodulatorPreThread::getParams() { - return params; -} - -void DemodulatorPreThread::setParams(DemodulatorThreadParameters ¶ms_in) { - params = params_in; -} - void DemodulatorPreThread::setDemodType(std::string demodType) { - this->newDemodType = demodType; - DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD); - command.sampleRate = params.sampleRate; - command.demodType = demodType; - command.bandwidth = params.bandwidth; - command.audioSampleRate = params.audioSampleRate; - workerQueue->push(command); + newDemodType = demodType; demodTypeChanged.store(true); } @@ -270,6 +262,55 @@ std::string DemodulatorPreThread::getDemodType() { return demodType; } +void DemodulatorPreThread::setFrequency(long long freq) { + frequencyChanged.store(true); + newFrequency = freq; +} + +long long DemodulatorPreThread::getFrequency() { + if (frequencyChanged.load()) { + return newFrequency; + } + return currentFrequency; +} + +void DemodulatorPreThread::setSampleRate(long long sampleRate) { + sampleRateChanged.store(true); + newSampleRate = sampleRate; +} + +long long DemodulatorPreThread::getSampleRate() { + if (sampleRateChanged.load()) { + return newSampleRate; + } + return currentSampleRate; +} + +void DemodulatorPreThread::setBandwidth(int bandwidth) { + bandwidthChanged.store(true); + newBandwidth = bandwidth; +} + +int DemodulatorPreThread::getBandwidth() { +// if (bandwidthChanged.load()) { +// return newBandwidth; +// } + + return currentBandwidth; +} + +void DemodulatorPreThread::setAudioSampleRate(int rate) { + audioSampleRateChanged.store(true); + newAudioSampleRate = rate; +} + +int DemodulatorPreThread::getAudioSampleRate() { + if (audioSampleRateChanged.load()) { + return newAudioSampleRate; + } + return currentAudioSampleRate; +} + void DemodulatorPreThread::terminate() { terminated = true; DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue @@ -284,7 +325,6 @@ void DemodulatorPreThread::terminate() { delete workerQueue; } - Modem *DemodulatorPreThread::getModem() { return cModem; } diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index 810cd4e..c90105c 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -16,13 +16,22 @@ public: ~DemodulatorPreThread(); void run(); - - DemodulatorThreadParameters &getParams(); - void setParams(DemodulatorThreadParameters ¶ms_in); void setDemodType(std::string demodType); std::string getDemodType(); + void setFrequency(long long sampleRate); + long long getFrequency(); + + void setSampleRate(long long sampleRate); + long long getSampleRate(); + + void setBandwidth(int bandwidth); + int getBandwidth(); + + void setAudioSampleRate(int rate); + int getAudioSampleRate(); + void initialize(); void terminate(); @@ -37,10 +46,14 @@ protected: Modem *cModem; ModemKit *cModemKit; + + long long currentSampleRate, newSampleRate; + long long currentFrequency, newFrequency; + int currentBandwidth, newBandwidth; + int currentAudioSampleRate, newAudioSampleRate; - DemodulatorThreadParameters params; - DemodulatorThreadParameters lastParams; - + std::atomic_bool sampleRateChanged, frequencyChanged, bandwidthChanged, audioSampleRateChanged; + nco_crcf freqShifter; int shiftFrequency; @@ -58,5 +71,4 @@ protected: DemodulatorThreadInputQueue* iqInputQueue; DemodulatorThreadPostInputQueue* iqOutputQueue; DemodulatorThreadCommandQueue* threadQueueNotify; - DemodulatorThreadCommandQueue* commandQueue; }; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index b16dd27..1437d1d 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -12,7 +12,7 @@ #include #endif -DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) : IOThread(), audioSampleRate(0), squelchLevel(-100), signalLevel(-100), squelchEnabled(false), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) { +DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) : IOThread(), squelchLevel(-100), signalLevel(-100), squelchEnabled(false), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) { demodInstance = parent; muted.store(false); @@ -73,8 +73,6 @@ void DemodulatorThread::run() { iqInputQueue->pop(inp); // std::lock_guard < std::mutex > lock(inp->m_mutex); - audioSampleRate = demodInstance->getAudioSampleRate(); - int bufSize = inp->data.size(); if (!bufSize) { @@ -127,7 +125,7 @@ void DemodulatorThread::run() { if (modemAnalog != nullptr) { ati = outputBuffers.getBuffer(); - ati->sampleRate = audioSampleRate; + ati->sampleRate = cModemKit->audioSampleRate; ati->inputRate = inp->sampleRate; ati->setRefCount(1); } @@ -178,7 +176,7 @@ void DemodulatorThread::run() { } } else { for (int i = 0; i < stereoSize / 2; i++) { - ati_vis->inputRate = audioSampleRate; + ati_vis->inputRate = cModemKit->audioSampleRate; ati_vis->sampleRate = 36000; ati_vis->data[i] = ati->data[i * 2]; ati_vis->data[i + stereoSize / 2] = ati->data[i * 2 + 1]; @@ -189,7 +187,7 @@ void DemodulatorThread::run() { ati_vis->channels = 1; std::vector *demodOutData = (modemAnalog != nullptr)?modemAnalog->getDemodOutputData():nullptr; if ((numAudioWritten > bufSize) || (demodOutData == nullptr)) { - ati_vis->inputRate = audioSampleRate; + ati_vis->inputRate = cModemKit->audioSampleRate; if (num_vis > numAudioWritten) { num_vis = numAudioWritten; } diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 9cc2ecf..06a81ea 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -43,7 +43,6 @@ protected: ReBuffer outputBuffers; std::atomic_bool muted; - int audioSampleRate; std::atomic squelchLevel; std::atomic signalLevel; diff --git a/src/modules/modem/analog/ModemFMStereo.cpp b/src/modules/modem/analog/ModemFMStereo.cpp index 864e566..7e0954f 100644 --- a/src/modules/modem/analog/ModemFMStereo.cpp +++ b/src/modules/modem/analog/ModemFMStereo.cpp @@ -42,7 +42,9 @@ ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) { ModemKitFMStereo *kit = new ModemKitFMStereo; kit->audioResampleRatio = double(audioSampleRate) / double(sampleRate); - + kit->sampleRate = sampleRate; + kit->audioSampleRate = audioSampleRate; + float As = 60.0f; // stop-band attenuation [dB] kit->audioResampler = msresamp_rrrf_create(kit->audioResampleRatio, As); diff --git a/src/visual/PrimaryGLContext.h b/src/visual/PrimaryGLContext.h index 254d2e7..9bab239 100644 --- a/src/visual/PrimaryGLContext.h +++ b/src/visual/PrimaryGLContext.h @@ -29,6 +29,5 @@ public: void setHoverAlpha(float hoverAlpha); private: - DemodulatorThreadParameters defaultDemodParams; float hoverAlpha; }; From 407abac8e8f851f629529da509f601ad82542fc7 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 22 Nov 2015 23:38:26 -0500 Subject: [PATCH 03/24] Move minimum frequency check to modem checkSampleRate() --- src/modules/modem/ModemAnalog.cpp | 3 +++ src/modules/modem/ModemDigital.cpp | 3 +++ src/modules/modem/analog/ModemFMStereo.cpp | 2 ++ src/modules/modem/analog/ModemLSB.cpp | 3 +++ src/modules/modem/analog/ModemUSB.cpp | 3 +++ 5 files changed, 14 insertions(+) diff --git a/src/modules/modem/ModemAnalog.cpp b/src/modules/modem/ModemAnalog.cpp index c9020f5..77e1957 100644 --- a/src/modules/modem/ModemAnalog.cpp +++ b/src/modules/modem/ModemAnalog.cpp @@ -9,6 +9,9 @@ std::string ModemAnalog::getType() { } int ModemAnalog::checkSampleRate(long long sampleRate, int audioSampleRate) { + if (sampleRate < 1500) { + return 1500; + } return sampleRate; } diff --git a/src/modules/modem/ModemDigital.cpp b/src/modules/modem/ModemDigital.cpp index 00f40ac..6ed184f 100644 --- a/src/modules/modem/ModemDigital.cpp +++ b/src/modules/modem/ModemDigital.cpp @@ -9,6 +9,9 @@ std::string ModemDigital::getType() { } int ModemDigital::checkSampleRate(long long sampleRate, int audioSampleRate) { + if (sampleRate < 1500) { + return 1500; + } return sampleRate; } diff --git a/src/modules/modem/analog/ModemFMStereo.cpp b/src/modules/modem/analog/ModemFMStereo.cpp index 7e0954f..f871ac9 100644 --- a/src/modules/modem/analog/ModemFMStereo.cpp +++ b/src/modules/modem/analog/ModemFMStereo.cpp @@ -33,6 +33,8 @@ Modem *ModemFMStereo::factory() { int ModemFMStereo::checkSampleRate(long long sampleRate, int audioSampleRate) { if (sampleRate < 100000) { return 100000; + } else if (sampleRate < 1500) { + return 1500; } else { return sampleRate; } diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp index 06e1584..d4d6ce8 100644 --- a/src/modules/modem/analog/ModemLSB.cpp +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -20,6 +20,9 @@ ModemLSB::~ModemLSB() { } int ModemLSB::checkSampleRate(long long sampleRate, int audioSampleRate) { + if (sampleRate < 1500) { + return 1500; + } if (sampleRate % 2 == 0) { return sampleRate; } diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp index 408d314..780d44a 100644 --- a/src/modules/modem/analog/ModemUSB.cpp +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -20,6 +20,9 @@ ModemUSB::~ModemUSB() { } int ModemUSB::checkSampleRate(long long sampleRate, int audioSampleRate) { + if (sampleRate < 1500) { + return 1500; + } if (sampleRate % 2 == 0) { return sampleRate; } From de1264fe1717f0a8447b48def0f707cebf34f5b6 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 23 Nov 2015 18:41:10 -0500 Subject: [PATCH 04/24] Copy SoapySDR::ArgInfo to bootstrap ModemArgInfo --- CMakeLists.txt | 4 +- src/forms/SDRDevices/SDRDevices.h | 1 - src/modules/modem/Modem.cpp | 14 ++++++ src/modules/modem/Modem.h | 77 +++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e15696e..b89525f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,7 +287,7 @@ SET (cubicsdr_sources ) IF(ENABLE_DIGITAL_LAB) - SET (cubicsdr_sources + SET (cubicsdr_sources ${cubicsdr_sources} src/modules/modem/digital/ModemASK.cpp src/modules/modem/digital/ModemAPSK.cpp @@ -389,7 +389,7 @@ SET (cubicsdr_headers ) IF(ENABLE_DIGITAL_LAB) -SET(cubicsdr_headers +SET (cubicsdr_headers ${cubicsdr_headers} src/modules/modem/digital/ModemASK.h src/modules/modem/digital/ModemAPSK.h diff --git a/src/forms/SDRDevices/SDRDevices.h b/src/forms/SDRDevices/SDRDevices.h index 74441ae..c6052a1 100644 --- a/src/forms/SDRDevices/SDRDevices.h +++ b/src/forms/SDRDevices/SDRDevices.h @@ -3,7 +3,6 @@ #include #include -#include "SDRDevices.h" #include "SDRDevicesForm.h" #include "SoapySDRThread.h" #include "SDREnumerator.h" diff --git a/src/modules/modem/Modem.cpp b/src/modules/modem/Modem.cpp index 8a1ff0e..30ea605 100644 --- a/src/modules/modem/Modem.cpp +++ b/src/modules/modem/Modem.cpp @@ -18,6 +18,20 @@ Modem *Modem::makeModem(std::string modemType) { return nullptr; } +ModemArgInfoList Modem::getSettings() { + ModemArgInfoList args; + + return args; +} + +void Modem::writeSetting(std::string setting, std::string value) { + // ... +} + +std::string Modem::readSetting(std::string setting) { + return ""; +} + Modem::Modem() { } diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h index 51629e5..cda7a95 100644 --- a/src/modules/modem/Modem.h +++ b/src/modules/modem/Modem.h @@ -29,6 +29,80 @@ public: } }; + +// Copy of SoapySDR::Range, original comments +class ModemRange +{ +public: + + //! Create an empty range (0.0, 0.0) + ModemRange(void); + + //! Create a min/max range + ModemRange(const double minimum, const double maximum); + + //! Get the range minimum + double minimum(void) const; + + //! Get the range maximum + double maximum(void) const; + +private: + double _min, _max; +}; + + +// Modified version of SoapySDR::ArgInfo, original comments +class ModemArgInfo +{ +public: + //! Default constructor + ModemArgInfo(void); + + //! The key used to identify the argument (required) + std::string key; + + /*! + * The default value of the argument when not specified (required) + * Numbers should use standard floating point and integer formats. + * Boolean values should be represented as "true" and "false". + */ + std::string value; + + //! The displayable name of the argument (optional, use key if empty) + std::string name; + + //! A brief description about the argument (optional) + std::string description; + + //! The units of the argument: dB, Hz, etc (optional) + std::string units; + + //! The data type of the argument (required) + enum Type { BOOL, INT, FLOAT, STRING, PATH_DIR, PATH_FILE, COLOR } type; + + /*! + * The range of possible numeric values (optional) + * When specified, the argument should be restricted to this range. + * The range is only applicable to numeric argument types. + */ + ModemRange range; + + /*! + * A discrete list of possible values (optional) + * When specified, the argument should be restricted to this options set. + */ + std::vector options; + + /*! + * A discrete list of displayable names for the enumerated options (optional) + * When not specified, the option value itself can be used as a display name. + */ + std::vector optionNames; +}; + +typedef std::vector ModemArgInfoList; + class Modem; typedef std::map ModemFactoryList; @@ -44,6 +118,9 @@ public: Modem(); virtual ~Modem(); + virtual ModemArgInfoList getSettings(); + virtual void writeSetting(std::string setting, std::string value); + virtual std::string readSetting(std::string setting); virtual int checkSampleRate(long long sampleRate, int audioSampleRate) = 0; virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate) = 0; virtual void disposeKit(ModemKit *kit) = 0; From 4a62eae0961a3b3b09acb6e7c787f5db733d8ab1 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 23 Nov 2015 20:03:47 -0500 Subject: [PATCH 05/24] Convert constellation code to ModemArgInfo settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Note: can’t set constellation yet until property grid is added --- src/AppFrame.cpp | 27 ------ src/AppFrame.h | 1 - src/demod/DemodulatorInstance.cpp | 15 ---- src/demod/DemodulatorInstance.h | 3 - src/demod/DemodulatorMgr.cpp | 9 -- src/demod/DemodulatorMgr.h | 4 - src/modules/modem/Modem.cpp | 16 ++++ src/modules/modem/Modem.h | 5 +- src/modules/modem/ModemDigital.cpp | 21 +---- src/modules/modem/ModemDigital.h | 12 ++- src/modules/modem/digital/ModemAPSK.cpp | 113 +++++++++++++++--------- src/modules/modem/digital/ModemAPSK.h | 8 ++ src/modules/modem/digital/ModemASK.cpp | 108 +++++++++++++--------- src/modules/modem/digital/ModemASK.h | 8 ++ src/modules/modem/digital/ModemBPSK.cpp | 6 -- src/modules/modem/digital/ModemBPSK.h | 5 +- src/modules/modem/digital/ModemDPSK.cpp | 109 ++++++++++++++--------- src/modules/modem/digital/ModemDPSK.h | 8 ++ src/modules/modem/digital/ModemFSK.cpp | 32 +++++-- src/modules/modem/digital/ModemFSK.h | 12 ++- src/modules/modem/digital/ModemOOK.cpp | 6 -- src/modules/modem/digital/ModemOOK.h | 5 +- src/modules/modem/digital/ModemPSK.cpp | 110 ++++++++++++++--------- src/modules/modem/digital/ModemPSK.h | 8 ++ src/modules/modem/digital/ModemQAM.cpp | 105 +++++++++++++--------- src/modules/modem/digital/ModemQAM.h | 8 ++ src/modules/modem/digital/ModemQPSK.cpp | 6 -- src/modules/modem/digital/ModemQPSK.h | 4 +- src/modules/modem/digital/ModemSQAM.cpp | 85 +++++++++--------- src/modules/modem/digital/ModemSQAM.h | 8 ++ src/modules/modem/digital/ModemST.cpp | 6 -- src/modules/modem/digital/ModemST.h | 4 +- src/visual/PrimaryGLContext.cpp | 6 +- 33 files changed, 495 insertions(+), 388 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 35f0b43..0f9b47c 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -93,19 +93,6 @@ AppFrame::AppFrame() : demodModeSelectorAdv->addChoice(10, "QPSK"); demodModeSelectorAdv->setHelpTip("Choose advanced modulation types."); demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0); - - demodModeSelectorCons = new ModeSelectorCanvas(this, attribList); - demodModeSelectorCons->addChoice(1, "auto"); - demodModeSelectorCons->addChoice(2, "2"); - demodModeSelectorCons->addChoice(4, "4"); - demodModeSelectorCons->addChoice(8, "8"); - demodModeSelectorCons->addChoice(16, "16"); - demodModeSelectorCons->addChoice(32, "32"); - demodModeSelectorCons->addChoice(64, "64"); - demodModeSelectorCons->addChoice(128, "128"); - demodModeSelectorCons->addChoice(256, "256"); - demodModeSelectorCons->setHelpTip("Choose number of constallations types."); - demodTray->Add(demodModeSelectorCons, 2, wxEXPAND | wxALL, 0); #endif wxGetApp().getDemodSpectrumProcessor()->setup(1024); @@ -862,9 +849,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { std::string dType = demod->getDemodulatorType(); demodModeSelector->setSelection(dType); #ifdef ENABLE_DIGITAL_LAB - int dCons = demod->getDemodulatorCons(); demodModeSelectorAdv->setSelection(dType); - demodModeSelectorCons->setSelection(dCons); #endif demodMuteButton->setSelection(demod->isMuted()?1:-1); } @@ -896,7 +881,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) { std::string dSelection = demodModeSelector->getSelectionLabel(); #ifdef ENABLE_DIGITAL_LAB std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel(); - int dSelectionCons = demodModeSelectorCons->getSelection(); // basic demodulators if (dSelection != "" && dSelection != demod->getDemodulatorType()) { @@ -908,11 +892,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demod->setDemodulatorType(dSelectionadv); demodModeSelector->setSelection(-1); } - - // set constellations - if (dSelectionCons != demod->getDemodulatorCons()) { - demod->setDemodulatorCons(dSelectionCons); - } #else // basic demodulators if (dSelection != "" && dSelection != demod->getDemodulatorType()) { @@ -958,7 +937,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) { std::string dSelection = demodModeSelector->getSelectionLabel(); #ifdef ENABLE_DIGITAL_LAB std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel(); - int dSelectionCons = demodModeSelectorCons->getSelection(); // basic demodulators if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) { @@ -970,11 +948,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) { mgr->setLastDemodulatorType(dSelectionadv); demodModeSelector->setSelection(-1); } - - // set constellations - if (dSelectionCons != mgr->getLastDemodulatorCons()) { - mgr->setLastDemodulatorCons(dSelectionCons); - } #else // basic demodulators if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) { diff --git a/src/AppFrame.h b/src/AppFrame.h index 694d8c7..2ca576a 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -81,7 +81,6 @@ private: ModeSelectorCanvas *demodModeSelector; #ifdef ENABLE_DIGITAL_LAB ModeSelectorCanvas *demodModeSelectorAdv; - ModeSelectorCanvas *demodModeSelectorCons; #endif SpectrumCanvas *demodSpectrumCanvas; WaterfallCanvas *demodWaterfallCanvas; diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index cf9ba0f..33c5832 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -261,21 +261,6 @@ int DemodulatorInstance::getDemodulatorLock() { return 0; } -void DemodulatorInstance::setDemodulatorCons(int demod_cons_in) { - Modem *cModem = demodulatorPreThread->getModem(); - if (cModem && cModem->getType() == "digital") { - ((ModemDigital *)cModem)->setDemodulatorCons(demod_cons_in); - } -} - -int DemodulatorInstance::getDemodulatorCons() { - Modem *cModem = demodulatorPreThread->getModem(); - if (cModem && cModem->getType() == "digital") { - return ((ModemDigital *)cModem)->getDemodulatorCons(); - } - return 0; -} - void DemodulatorInstance::setBandwidth(int bw) { demodulatorPreThread->setBandwidth(bw); } diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index fa14679..58801ae 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -58,9 +58,6 @@ public: void setDemodulatorLock(bool demod_lock_in); int getDemodulatorLock(); - - void setDemodulatorCons(int demod_cons_in); - int getDemodulatorCons(); void setBandwidth(int bw); int getBandwidth(); diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index fc6c4e1..939bed0 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -162,7 +162,6 @@ void DemodulatorMgr::updateLastState() { lastBandwidth = lastActiveDemodulator->getBandwidth(); lastDemodType = lastActiveDemodulator->getDemodulatorType(); lastDemodLock = lastActiveDemodulator->getDemodulatorLock(); - lastDemodCons = lastActiveDemodulator->getDemodulatorCons(); lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled(); lastSquelch = lastActiveDemodulator->getSquelchLevel(); lastGain = lastActiveDemodulator->getGain(); @@ -191,14 +190,6 @@ void DemodulatorMgr::setLastDemodulatorType(std::string lastDemodType) { this->lastDemodType = lastDemodType; } -int DemodulatorMgr::getLastDemodulatorCons() const { - return lastDemodCons; -} - -void DemodulatorMgr::setLastDemodulatorCons(int lastDemodCons) { - this->lastDemodCons = lastDemodCons; -} - float DemodulatorMgr::getLastGain() const { return lastGain; } diff --git a/src/demod/DemodulatorMgr.h b/src/demod/DemodulatorMgr.h index c57386a..a93204e 100644 --- a/src/demod/DemodulatorMgr.h +++ b/src/demod/DemodulatorMgr.h @@ -27,9 +27,6 @@ public: std::string getLastDemodulatorType() const; void setLastDemodulatorType(std::string lastDemodType); - - int getLastDemodulatorCons() const; - void setLastDemodulatorCons(int lastDemodCons); float getLastGain() const; void setLastGain(float lastGain); @@ -56,7 +53,6 @@ private: int lastBandwidth; std::string lastDemodType; bool lastDemodLock; - int lastDemodCons; bool lastSquelchEnabled; float lastSquelch; float lastGain; diff --git a/src/modules/modem/Modem.cpp b/src/modules/modem/Modem.cpp index 30ea605..69adc7b 100644 --- a/src/modules/modem/Modem.cpp +++ b/src/modules/modem/Modem.cpp @@ -2,6 +2,22 @@ ModemFactoryList Modem::modemFactories; +//! Create an empty range (0.0, 0.0) +ModemRange::ModemRange(void) { + _min = 0; + _max = 0; +} + +//! Create a min/max range +ModemRange::ModemRange(const double minimum, const double maximum) { + _min = minimum; + _max = maximum; +} + +ModemArgInfo::ModemArgInfo(void) { + +} + void Modem::addModemFactory(Modem *factorySingle) { modemFactories[factorySingle->getName()] = factorySingle; } diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h index cda7a95..7edb2d5 100644 --- a/src/modules/modem/Modem.h +++ b/src/modules/modem/Modem.h @@ -29,7 +29,6 @@ public: } }; - // Copy of SoapySDR::Range, original comments class ModemRange { @@ -51,7 +50,6 @@ private: double _min, _max; }; - // Modified version of SoapySDR::ArgInfo, original comments class ModemArgInfo { @@ -121,9 +119,12 @@ public: virtual ModemArgInfoList getSettings(); virtual void writeSetting(std::string setting, std::string value); virtual std::string readSetting(std::string setting); + virtual int checkSampleRate(long long sampleRate, int audioSampleRate) = 0; + virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate) = 0; virtual void disposeKit(ModemKit *kit) = 0; + virtual void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) = 0; private: static ModemFactoryList modemFactories; diff --git a/src/modules/modem/ModemDigital.cpp b/src/modules/modem/ModemDigital.cpp index 6ed184f..c8c09f6 100644 --- a/src/modules/modem/ModemDigital.cpp +++ b/src/modules/modem/ModemDigital.cpp @@ -38,24 +38,10 @@ int ModemDigital::getDemodulatorLock() { return currentDemodLock.load(); } -void ModemDigital::setDemodulatorCons(int demod_cons_in) { - demodulatorCons.store(demod_cons_in); -} - -int ModemDigital::getDemodulatorCons() { - return currentDemodCons.load(); -} - void ModemDigital::updateDemodulatorLock(modem mod, float sensitivity) { setDemodulatorLock(modem_get_demodulator_evm(mod) <= sensitivity); } -void ModemDigital::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - } -} - void ModemDigital::digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input) { int bufSize = input->data.size(); @@ -65,14 +51,9 @@ void ModemDigital::digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *in } demodOutputDataDigital.resize(bufSize); } - - if (demodulatorCons.load() != currentDemodCons.load()) { - updateDemodulatorCons(demodulatorCons.load()); - currentDemodLock.store(false); - } } void ModemDigital::digitalFinish(ModemKitDigital *kit, modem mod) { demodOutputDataDigital.empty(); } - + \ No newline at end of file diff --git a/src/modules/modem/ModemDigital.h b/src/modules/modem/ModemDigital.h index e78b5a7..3c0e1be 100644 --- a/src/modules/modem/ModemDigital.h +++ b/src/modules/modem/ModemDigital.h @@ -12,28 +12,26 @@ public: class ModemDigital : public Modem { public: ModemDigital(); + std::string getType(); + virtual int checkSampleRate(long long sampleRate, int audioSampleRate); + virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate); virtual void disposeKit(ModemKit *kit); + virtual void digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input); virtual void digitalFinish(ModemKitDigital *kit, modem mod); virtual void setDemodulatorLock(bool demod_lock_in); virtual int getDemodulatorLock(); - virtual void setDemodulatorCons(int demod_cons_in); - virtual int getDemodulatorCons(); - - virtual void updateDemodulatorCons(int cons); virtual void updateDemodulatorLock(modem mod, float sensitivity); protected: std::vector demodOutputDataDigital; - std::atomic_int demodulatorCons; std::atomic_bool currentDemodLock; - std::atomic_int currentDemodCons; - + // std::vector demodOutputDataDigitalTest; // std::vector demodOutputSoftbits; // std::vector demodOutputSoftbitsTest; diff --git a/src/modules/modem/digital/ModemAPSK.cpp b/src/modules/modem/digital/ModemAPSK.cpp index ed04c10..f7d72d5 100644 --- a/src/modules/modem/digital/ModemAPSK.cpp +++ b/src/modules/modem/digital/ModemAPSK.cpp @@ -8,9 +8,8 @@ ModemAPSK::ModemAPSK() { demodAPSK64 = modem_create(LIQUID_MODEM_APSK64); demodAPSK128 = modem_create(LIQUID_MODEM_APSK128); demodAPSK256 = modem_create(LIQUID_MODEM_APSK256); - demodulatorCons.store(4); - currentDemodCons.store(0); - updateDemodulatorCons(4); + demodAPSK = demodAPSK4; + cons = 4; } Modem *ModemAPSK::factory() { @@ -31,46 +30,76 @@ std::string ModemAPSK::getName() { return "APSK"; } +ModemArgInfoList ModemAPSK::getSettings() { + ModemArgInfoList args; + + ModemArgInfo consArg; + consArg.key = "cons"; + consArg.name = "Constellation"; + consArg.description = "Modem Constellation Pattern"; + consArg.value = std::to_string(cons); + consArg.type = ModemArgInfo::STRING; + std::vector consOpts; + consOpts.push_back("4"); + consOpts.push_back("8"); + consOpts.push_back("16"); + consOpts.push_back("32"); + consOpts.push_back("64"); + consOpts.push_back("128"); + consOpts.push_back("256"); + consArg.options = consOpts; + args.push_back(consArg); + + return args; +} + +void ModemAPSK::writeSetting(std::string setting, std::string value) { + if (setting == "cons") { + int newCons = std::stoi(value); + updateDemodulatorCons(newCons); + } +} + +std::string ModemAPSK::readSetting(std::string setting) { + if (setting == "cons") { + return std::to_string(cons); + } + return ""; +} + void ModemAPSK::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - switch (demodulatorCons.load()) { - case 2: - demodAPSK = demodAPSK4; - updateDemodulatorCons(4); - break; - case 4: - demodAPSK = demodAPSK4; - updateDemodulatorCons(4); - break; - case 8: - demodAPSK = demodAPSK8; - updateDemodulatorCons(8); - break; - case 16: - demodAPSK = demodAPSK16; - updateDemodulatorCons(16); - break; - case 32: - demodAPSK = demodAPSK32; - updateDemodulatorCons(32); - break; - case 64: - demodAPSK = demodAPSK64; - updateDemodulatorCons(64); - break; - case 128: - demodAPSK = demodAPSK128; - updateDemodulatorCons(128); - break; - case 256: - demodAPSK = demodAPSK256; - updateDemodulatorCons(256); - break; - default: - demodAPSK = demodAPSK4; - break; - } + switch (cons) { + case 4: + demodAPSK = demodAPSK4; + updateDemodulatorCons(4); + break; + case 8: + demodAPSK = demodAPSK8; + updateDemodulatorCons(8); + break; + case 16: + demodAPSK = demodAPSK16; + updateDemodulatorCons(16); + break; + case 32: + demodAPSK = demodAPSK32; + updateDemodulatorCons(32); + break; + case 64: + demodAPSK = demodAPSK64; + updateDemodulatorCons(64); + break; + case 128: + demodAPSK = demodAPSK128; + updateDemodulatorCons(128); + break; + case 256: + demodAPSK = demodAPSK256; + updateDemodulatorCons(256); + break; + default: + demodAPSK = demodAPSK4; + break; } } diff --git a/src/modules/modem/digital/ModemAPSK.h b/src/modules/modem/digital/ModemAPSK.h index f5497df..dc9a4c6 100644 --- a/src/modules/modem/digital/ModemAPSK.h +++ b/src/modules/modem/digital/ModemAPSK.h @@ -5,12 +5,20 @@ class ModemAPSK : public ModemDigital { public: ModemAPSK(); ~ModemAPSK(); + std::string getName(); + Modem *factory(); + + ModemArgInfoList getSettings(); + void writeSetting(std::string setting, std::string value); + std::string readSetting(std::string setting); + void updateDemodulatorCons(int cons); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: + int cons; modem demodAPSK; modem demodAPSK4; modem demodAPSK8; diff --git a/src/modules/modem/digital/ModemASK.cpp b/src/modules/modem/digital/ModemASK.cpp index af09b76..fb9adf4 100644 --- a/src/modules/modem/digital/ModemASK.cpp +++ b/src/modules/modem/digital/ModemASK.cpp @@ -10,9 +10,7 @@ ModemASK::ModemASK() { demodASK128 = modem_create(LIQUID_MODEM_ASK128); demodASK256 = modem_create(LIQUID_MODEM_ASK256); demodASK = demodASK2; - demodulatorCons.store(2); - currentDemodCons.store(0); - updateDemodulatorCons(2); + cons = 2; } Modem *ModemASK::factory() { @@ -33,47 +31,71 @@ std::string ModemASK::getName() { return "ASK"; } +ModemArgInfoList ModemASK::getSettings() { + ModemArgInfoList args; + + ModemArgInfo consArg; + consArg.key = "cons"; + consArg.name = "Constellation"; + consArg.description = "Modem Constellation Pattern"; + consArg.value = std::to_string(cons); + consArg.type = ModemArgInfo::STRING; + std::vector consOpts; + consOpts.push_back("2"); + consOpts.push_back("4"); + consOpts.push_back("8"); + consOpts.push_back("16"); + consOpts.push_back("32"); + consOpts.push_back("64"); + consOpts.push_back("128"); + consOpts.push_back("256"); + consArg.options = consOpts; + args.push_back(consArg); + + return args; +} + +void ModemASK::writeSetting(std::string setting, std::string value) { + if (setting == "cons") { + int newCons = std::stoi(value); + updateDemodulatorCons(newCons); + } +} + +std::string ModemASK::readSetting(std::string setting) { + if (setting == "cons") { + return std::to_string(cons); + } + return ""; +} + void ModemASK::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - - switch (demodulatorCons.load()) { - case 2: - demodASK = demodASK2; - updateDemodulatorCons(2); - break; - case 4: - demodASK = demodASK4; - updateDemodulatorCons(4); - break; - case 8: - demodASK = demodASK8; - updateDemodulatorCons(8); - break; - case 16: - demodASK = demodASK16; - updateDemodulatorCons(16); - break; - case 32: - demodASK = demodASK32; - updateDemodulatorCons(32); - break; - case 64: - demodASK = demodASK64; - updateDemodulatorCons(64); - break; - case 128: - demodASK = demodASK128; - updateDemodulatorCons(128); - break; - case 256: - demodASK = demodASK256; - updateDemodulatorCons(256); - break; - default: - demodASK = demodASK2; - break; - } + this->cons = cons; + switch (cons) { + case 2: + demodASK = demodASK2; + break; + case 4: + demodASK = demodASK4; + break; + case 8: + demodASK = demodASK8; + break; + case 16: + demodASK = demodASK16; + break; + case 32: + demodASK = demodASK32; + break; + case 64: + demodASK = demodASK64; + break; + case 128: + demodASK = demodASK128; + break; + case 256: + demodASK = demodASK256; + break; } } diff --git a/src/modules/modem/digital/ModemASK.h b/src/modules/modem/digital/ModemASK.h index 5dfffc1..e102b96 100644 --- a/src/modules/modem/digital/ModemASK.h +++ b/src/modules/modem/digital/ModemASK.h @@ -5,12 +5,20 @@ class ModemASK : public ModemDigital { public: ModemASK(); ~ModemASK(); + std::string getName(); + Modem *factory(); + + ModemArgInfoList getSettings(); + void writeSetting(std::string setting, std::string value); + std::string readSetting(std::string setting); + void updateDemodulatorCons(int cons); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: + int cons; modem demodASK; modem demodASK2; modem demodASK4; diff --git a/src/modules/modem/digital/ModemBPSK.cpp b/src/modules/modem/digital/ModemBPSK.cpp index 535cdae..6e2b3a1 100644 --- a/src/modules/modem/digital/ModemBPSK.cpp +++ b/src/modules/modem/digital/ModemBPSK.cpp @@ -16,12 +16,6 @@ std::string ModemBPSK::getName() { return "BPSK"; } -void ModemBPSK::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - } -} - void ModemBPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitDigital *dkit = (ModemKitDigital *)kit; digitalStart(dkit, demodBPSK, input); diff --git a/src/modules/modem/digital/ModemBPSK.h b/src/modules/modem/digital/ModemBPSK.h index ef26c5c..e571478 100644 --- a/src/modules/modem/digital/ModemBPSK.h +++ b/src/modules/modem/digital/ModemBPSK.h @@ -5,12 +5,13 @@ class ModemBPSK : public ModemDigital { public: ModemBPSK(); ~ModemBPSK(); + std::string getName(); + Modem *factory(); - void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: modem demodBPSK; - }; diff --git a/src/modules/modem/digital/ModemDPSK.cpp b/src/modules/modem/digital/ModemDPSK.cpp index b44ebb7..9698e8c 100644 --- a/src/modules/modem/digital/ModemDPSK.cpp +++ b/src/modules/modem/digital/ModemDPSK.cpp @@ -9,9 +9,8 @@ ModemDPSK::ModemDPSK() { demodDPSK64 = modem_create(LIQUID_MODEM_DPSK64); demodDPSK128 = modem_create(LIQUID_MODEM_DPSK128); demodDPSK256 = modem_create(LIQUID_MODEM_DPSK256); - demodulatorCons.store(2); - currentDemodCons.store(0); - updateDemodulatorCons(2); + demodDPSK = demodDPSK2; + cons = 2; } Modem *ModemDPSK::factory() { @@ -33,47 +32,71 @@ ModemDPSK::~ModemDPSK() { modem_destroy(demodDPSK256); } +ModemArgInfoList ModemDPSK::getSettings() { + ModemArgInfoList args; + + ModemArgInfo consArg; + consArg.key = "cons"; + consArg.name = "Constellation"; + consArg.description = "Modem Constellation Pattern"; + consArg.value = std::to_string(cons); + consArg.type = ModemArgInfo::STRING; + std::vector consOpts; + consOpts.push_back("2"); + consOpts.push_back("4"); + consOpts.push_back("8"); + consOpts.push_back("16"); + consOpts.push_back("32"); + consOpts.push_back("64"); + consOpts.push_back("128"); + consOpts.push_back("256"); + consArg.options = consOpts; + args.push_back(consArg); + + return args; +} + +void ModemDPSK::writeSetting(std::string setting, std::string value) { + if (setting == "cons") { + int newCons = std::stoi(value); + updateDemodulatorCons(newCons); + } +} + +std::string ModemDPSK::readSetting(std::string setting) { + if (setting == "cons") { + return std::to_string(cons); + } + return ""; +} + void ModemDPSK::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - - switch (demodulatorCons.load()) { - case 2: - demodDPSK = demodDPSK2; - updateDemodulatorCons(2); - break; - case 4: - demodDPSK = demodDPSK4; - updateDemodulatorCons(4); - break; - case 8: - demodDPSK = demodDPSK8; - updateDemodulatorCons(8); - break; - case 16: - demodDPSK = demodDPSK16; - updateDemodulatorCons(16); - break; - case 32: - demodDPSK = demodDPSK32; - updateDemodulatorCons(32); - break; - case 64: - demodDPSK = demodDPSK64; - updateDemodulatorCons(64); - break; - case 128: - demodDPSK = demodDPSK128; - updateDemodulatorCons(128); - break; - case 256: - demodDPSK = demodDPSK256; - updateDemodulatorCons(256); - break; - default: - demodDPSK = demodDPSK2; - break; - } + this->cons = cons; + switch (cons) { + case 2: + demodDPSK = demodDPSK2; + break; + case 4: + demodDPSK = demodDPSK4; + break; + case 8: + demodDPSK = demodDPSK8; + break; + case 16: + demodDPSK = demodDPSK16; + break; + case 32: + demodDPSK = demodDPSK32; + break; + case 64: + demodDPSK = demodDPSK64; + break; + case 128: + demodDPSK = demodDPSK128; + break; + case 256: + demodDPSK = demodDPSK256; + break; } } diff --git a/src/modules/modem/digital/ModemDPSK.h b/src/modules/modem/digital/ModemDPSK.h index b431ffd..3b76e00 100644 --- a/src/modules/modem/digital/ModemDPSK.h +++ b/src/modules/modem/digital/ModemDPSK.h @@ -5,12 +5,20 @@ class ModemDPSK : public ModemDigital { public: ModemDPSK(); ~ModemDPSK(); + std::string getName(); + Modem *factory(); + + ModemArgInfoList getSettings(); + void writeSetting(std::string setting, std::string value); + std::string readSetting(std::string setting); + void updateDemodulatorCons(int cons); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: + int cons; modem demodDPSK; modem demodDPSK2; modem demodDPSK4; diff --git a/src/modules/modem/digital/ModemFSK.cpp b/src/modules/modem/digital/ModemFSK.cpp index f73d99c..aad5bfd 100644 --- a/src/modules/modem/digital/ModemFSK.cpp +++ b/src/modules/modem/digital/ModemFSK.cpp @@ -1,15 +1,37 @@ #include "ModemFSK.h" ModemFSK::ModemFSK() { - demodulatorCons.store(2); - currentDemodCons.store(0); - updateDemodulatorCons(2); + bps = 9600; + spacing = 7000; } Modem *ModemFSK::factory() { return new ModemFSK; } +ModemArgInfoList ModemFSK::getSettings() { + ModemArgInfoList args; + + return args; +} + +void ModemFSK::writeSetting(std::string setting, std::string value) { + if (setting == "bps") { + + } else if (setting == "spacing") { + + } +} + +std::string ModemFSK::readSetting(std::string setting) { + if (setting == "bps") { + return std::to_string(bps); + } else if (setting == "spacing") { + return std::to_string(spacing); + } + return ""; +} + ModemKit *ModemFSK::buildKit(long long sampleRate, int audioSampleRate) { ModemKitFSK *dkit = new ModemKitFSK; dkit->m = 1; @@ -38,10 +60,6 @@ ModemFSK::~ModemFSK() { } -void ModemFSK::updateDemodulatorCons(int cons) { - -} - void ModemFSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitFSK *dkit = (ModemKitFSK *)kit; diff --git a/src/modules/modem/digital/ModemFSK.h b/src/modules/modem/digital/ModemFSK.h index f1fe62c..a5392ae 100644 --- a/src/modules/modem/digital/ModemFSK.h +++ b/src/modules/modem/digital/ModemFSK.h @@ -15,15 +15,21 @@ class ModemFSK : public ModemDigital { public: ModemFSK(); ~ModemFSK(); + std::string getName(); + Modem *factory(); + + ModemArgInfoList getSettings(); + void writeSetting(std::string setting, std::string value); + std::string readSetting(std::string setting); + ModemKit *buildKit(long long sampleRate, int audioSampleRate); void disposeKit(ModemKit *kit); - void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); - private: - fskdem dem; + int bps, spacing; }; diff --git a/src/modules/modem/digital/ModemOOK.cpp b/src/modules/modem/digital/ModemOOK.cpp index 7be56d7..d0e92f9 100644 --- a/src/modules/modem/digital/ModemOOK.cpp +++ b/src/modules/modem/digital/ModemOOK.cpp @@ -16,12 +16,6 @@ std::string ModemOOK::getName() { return "OOK"; } -void ModemOOK::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - } -} - void ModemOOK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitDigital *dkit = (ModemKitDigital *)kit; digitalStart(dkit, demodOOK, input); diff --git a/src/modules/modem/digital/ModemOOK.h b/src/modules/modem/digital/ModemOOK.h index 6f15c8b..4266113 100644 --- a/src/modules/modem/digital/ModemOOK.h +++ b/src/modules/modem/digital/ModemOOK.h @@ -5,12 +5,13 @@ class ModemOOK : public ModemDigital { public: ModemOOK(); ~ModemOOK(); + std::string getName(); + Modem *factory(); - void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: modem demodOOK; - }; diff --git a/src/modules/modem/digital/ModemPSK.cpp b/src/modules/modem/digital/ModemPSK.cpp index cf05a9e..1f33ff3 100644 --- a/src/modules/modem/digital/ModemPSK.cpp +++ b/src/modules/modem/digital/ModemPSK.cpp @@ -9,9 +9,8 @@ ModemPSK::ModemPSK() { demodPSK64 = modem_create(LIQUID_MODEM_PSK64); demodPSK128 = modem_create(LIQUID_MODEM_PSK128); demodPSK256 = modem_create(LIQUID_MODEM_PSK256); - demodulatorCons.store(2); - currentDemodCons.store(0); - updateDemodulatorCons(2); + demodPSK = demodPSK2; + cons = 2; } Modem *ModemPSK::factory() { @@ -33,47 +32,72 @@ ModemPSK::~ModemPSK() { modem_destroy(demodPSK256); } + +ModemArgInfoList ModemPSK::getSettings() { + ModemArgInfoList args; + + ModemArgInfo consArg; + consArg.key = "cons"; + consArg.name = "Constellation"; + consArg.description = "Modem Constellation Pattern"; + consArg.value = std::to_string(cons); + consArg.type = ModemArgInfo::STRING; + std::vector consOpts; + consOpts.push_back("2"); + consOpts.push_back("4"); + consOpts.push_back("8"); + consOpts.push_back("16"); + consOpts.push_back("32"); + consOpts.push_back("64"); + consOpts.push_back("128"); + consOpts.push_back("256"); + consArg.options = consOpts; + args.push_back(consArg); + + return args; +} + +void ModemPSK::writeSetting(std::string setting, std::string value) { + if (setting == "cons") { + int newCons = std::stoi(value); + updateDemodulatorCons(newCons); + } +} + +std::string ModemPSK::readSetting(std::string setting) { + if (setting == "cons") { + return std::to_string(cons); + } + return ""; +} + void ModemPSK::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - - switch (demodulatorCons.load()) { - case 2: - demodPSK = demodPSK2; - updateDemodulatorCons(2); - break; - case 4: - demodPSK = demodPSK4; - updateDemodulatorCons(4); - break; - case 8: - demodPSK = demodPSK8; - updateDemodulatorCons(8); - break; - case 16: - demodPSK = demodPSK16; - updateDemodulatorCons(16); - break; - case 32: - demodPSK = demodPSK32; - updateDemodulatorCons(32); - break; - case 64: - demodPSK = demodPSK64; - updateDemodulatorCons(64); - break; - case 128: - demodPSK = demodPSK128; - updateDemodulatorCons(128); - break; - case 256: - demodPSK = demodPSK256; - updateDemodulatorCons(256); - break; - default: - demodPSK = demodPSK2; - break; - } + this->cons = cons; + switch (cons) { + case 2: + demodPSK = demodPSK2; + break; + case 4: + demodPSK = demodPSK4; + break; + case 8: + demodPSK = demodPSK8; + break; + case 16: + demodPSK = demodPSK16; + break; + case 32: + demodPSK = demodPSK32; + break; + case 64: + demodPSK = demodPSK64; + break; + case 128: + demodPSK = demodPSK128; + break; + case 256: + demodPSK = demodPSK256; + break; } } diff --git a/src/modules/modem/digital/ModemPSK.h b/src/modules/modem/digital/ModemPSK.h index 913f8f8..6f51a58 100644 --- a/src/modules/modem/digital/ModemPSK.h +++ b/src/modules/modem/digital/ModemPSK.h @@ -5,12 +5,20 @@ class ModemPSK : public ModemDigital { public: ModemPSK(); ~ModemPSK(); + std::string getName(); + Modem *factory(); + + ModemArgInfoList getSettings(); + void writeSetting(std::string setting, std::string value); + std::string readSetting(std::string setting); + void updateDemodulatorCons(int cons); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: + int cons; modem demodPSK; modem demodPSK2; modem demodPSK4; diff --git a/src/modules/modem/digital/ModemQAM.cpp b/src/modules/modem/digital/ModemQAM.cpp index f14b5b5..63659a3 100644 --- a/src/modules/modem/digital/ModemQAM.cpp +++ b/src/modules/modem/digital/ModemQAM.cpp @@ -8,9 +8,8 @@ ModemQAM::ModemQAM() { demodQAM64 = modem_create(LIQUID_MODEM_QAM64); demodQAM128 = modem_create(LIQUID_MODEM_QAM128); demodQAM256 = modem_create(LIQUID_MODEM_QAM256); - demodulatorCons.store(4); - currentDemodCons.store(0); - updateDemodulatorCons(4); + demodQAM = demodQAM4; + cons = 4; } Modem *ModemQAM::factory() { @@ -31,47 +30,67 @@ ModemQAM::~ModemQAM() { modem_destroy(demodQAM256); } +ModemArgInfoList ModemQAM::getSettings() { + ModemArgInfoList args; + + ModemArgInfo consArg; + consArg.key = "cons"; + consArg.name = "Constellation"; + consArg.description = "Modem Constellation Pattern"; + consArg.value = std::to_string(cons); + consArg.type = ModemArgInfo::STRING; + std::vector consOpts; + consOpts.push_back("4"); + consOpts.push_back("8"); + consOpts.push_back("16"); + consOpts.push_back("32"); + consOpts.push_back("64"); + consOpts.push_back("128"); + consOpts.push_back("256"); + consArg.options = consOpts; + args.push_back(consArg); + + return args; +} + +void ModemQAM::writeSetting(std::string setting, std::string value) { + if (setting == "cons") { + int newCons = std::stoi(value); + updateDemodulatorCons(newCons); + } +} + +std::string ModemQAM::readSetting(std::string setting) { + if (setting == "cons") { + return std::to_string(cons); + } + return ""; +} + void ModemQAM::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - - switch (demodulatorCons.load()) { - case 2: - demodQAM = demodQAM4; - updateDemodulatorCons(4); - break; - case 4: - demodQAM = demodQAM4; - updateDemodulatorCons(4); - break; - case 8: - demodQAM = demodQAM8; - updateDemodulatorCons(8); - break; - case 16: - demodQAM = demodQAM16; - updateDemodulatorCons(16); - break; - case 32: - demodQAM = demodQAM32; - updateDemodulatorCons(32); - break; - case 64: - demodQAM = demodQAM64; - updateDemodulatorCons(64); - break; - case 128: - demodQAM = demodQAM128; - updateDemodulatorCons(128); - break; - case 256: - demodQAM = demodQAM256; - updateDemodulatorCons(256); - break; - default: - demodQAM = demodQAM4; - break; - } + this->cons = cons; + switch (cons) { + case 4: + demodQAM = demodQAM4; + break; + case 8: + demodQAM = demodQAM8; + break; + case 16: + demodQAM = demodQAM16; + break; + case 32: + demodQAM = demodQAM32; + break; + case 64: + demodQAM = demodQAM64; + break; + case 128: + demodQAM = demodQAM128; + break; + case 256: + demodQAM = demodQAM256; + break; } } diff --git a/src/modules/modem/digital/ModemQAM.h b/src/modules/modem/digital/ModemQAM.h index 973f9ff..3be6936 100644 --- a/src/modules/modem/digital/ModemQAM.h +++ b/src/modules/modem/digital/ModemQAM.h @@ -5,12 +5,20 @@ class ModemQAM : public ModemDigital { public: ModemQAM(); ~ModemQAM(); + std::string getName(); + Modem *factory(); + + ModemArgInfoList getSettings(); + void writeSetting(std::string setting, std::string value); + std::string readSetting(std::string setting); + void updateDemodulatorCons(int cons); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: + int cons; modem demodQAM; modem demodQAM4; modem demodQAM8; diff --git a/src/modules/modem/digital/ModemQPSK.cpp b/src/modules/modem/digital/ModemQPSK.cpp index 309cadb..98dfb7f 100644 --- a/src/modules/modem/digital/ModemQPSK.cpp +++ b/src/modules/modem/digital/ModemQPSK.cpp @@ -16,12 +16,6 @@ std::string ModemQPSK::getName() { return "QPSK"; } -void ModemQPSK::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - } -} - void ModemQPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitDigital *dkit = (ModemKitDigital *)kit; digitalStart(dkit, demodQPSK, input); diff --git a/src/modules/modem/digital/ModemQPSK.h b/src/modules/modem/digital/ModemQPSK.h index 4d26e49..9de5d4e 100644 --- a/src/modules/modem/digital/ModemQPSK.h +++ b/src/modules/modem/digital/ModemQPSK.h @@ -5,9 +5,11 @@ class ModemQPSK : public ModemDigital { public: ModemQPSK(); ~ModemQPSK(); + std::string getName(); + Modem *factory(); - void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/modules/modem/digital/ModemSQAM.cpp b/src/modules/modem/digital/ModemSQAM.cpp index a4abd39..fbb8f47 100644 --- a/src/modules/modem/digital/ModemSQAM.cpp +++ b/src/modules/modem/digital/ModemSQAM.cpp @@ -3,9 +3,8 @@ ModemSQAM::ModemSQAM() { demodSQAM32 = modem_create(LIQUID_MODEM_SQAM32); demodSQAM128 = modem_create(LIQUID_MODEM_SQAM128); - demodulatorCons.store(32); - currentDemodCons.store(0); - updateDemodulatorCons(32); + demodSQAM = demodSQAM32; + cons = 32; } Modem *ModemSQAM::factory() { @@ -21,47 +20,47 @@ std::string ModemSQAM::getName() { return "SQAM"; } +ModemArgInfoList ModemSQAM::getSettings() { + ModemArgInfoList args; + + ModemArgInfo consArg; + consArg.key = "cons"; + consArg.name = "Constellation"; + consArg.description = "Modem Constellation Pattern"; + consArg.value = std::to_string(cons); + consArg.type = ModemArgInfo::STRING; + std::vector consOpts; + consOpts.push_back("32"); + consOpts.push_back("128"); + consArg.options = consOpts; + args.push_back(consArg); + + return args; +} + +void ModemSQAM::writeSetting(std::string setting, std::string value) { + if (setting == "cons") { + int newCons = std::stoi(value); + updateDemodulatorCons(newCons); + } +} + +std::string ModemSQAM::readSetting(std::string setting) { + if (setting == "cons") { + return std::to_string(cons); + } + return ""; +} + void ModemSQAM::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - - switch (demodulatorCons.load()) { - case 2: - demodSQAM = demodSQAM32; - updateDemodulatorCons(32); - break; - case 4: - demodSQAM = demodSQAM32; - updateDemodulatorCons(32); - break; - case 8: - demodSQAM = demodSQAM32; - updateDemodulatorCons(32); - break; - case 16: - demodSQAM = demodSQAM32; - updateDemodulatorCons(32); - break; - case 32: - demodSQAM = demodSQAM32; - updateDemodulatorCons(32); - break; - case 64: - demodSQAM = demodSQAM32; - updateDemodulatorCons(32); - break; - case 128: - demodSQAM = demodSQAM128; - updateDemodulatorCons(128); - break; - case 256: - demodSQAM = demodSQAM128; - updateDemodulatorCons(128); - break; - default: - demodSQAM = demodSQAM32; - break; - } + this->cons = cons; + switch (cons) { + case 32: + demodSQAM = demodSQAM32; + break; + case 128: + demodSQAM = demodSQAM128; + break; } } diff --git a/src/modules/modem/digital/ModemSQAM.h b/src/modules/modem/digital/ModemSQAM.h index e26b497..cb5b3af 100644 --- a/src/modules/modem/digital/ModemSQAM.h +++ b/src/modules/modem/digital/ModemSQAM.h @@ -5,12 +5,20 @@ class ModemSQAM : public ModemDigital { public: ModemSQAM(); ~ModemSQAM(); + std::string getName(); + Modem *factory(); + + ModemArgInfoList getSettings(); + void writeSetting(std::string setting, std::string value); + std::string readSetting(std::string setting); + void updateDemodulatorCons(int cons); void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: + int cons; modem demodSQAM; modem demodSQAM32; modem demodSQAM128; diff --git a/src/modules/modem/digital/ModemST.cpp b/src/modules/modem/digital/ModemST.cpp index b5d8e3f..7adbe71 100644 --- a/src/modules/modem/digital/ModemST.cpp +++ b/src/modules/modem/digital/ModemST.cpp @@ -16,12 +16,6 @@ ModemST::~ModemST() { modem_destroy(demodST); } -void ModemST::updateDemodulatorCons(int cons) { - if (currentDemodCons.load() != cons) { - currentDemodCons = cons; - } -} - void ModemST::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitDigital *dkit = (ModemKitDigital *)kit; digitalStart(dkit, demodST, input); diff --git a/src/modules/modem/digital/ModemST.h b/src/modules/modem/digital/ModemST.h index ac9ee10..2e92ae2 100644 --- a/src/modules/modem/digital/ModemST.h +++ b/src/modules/modem/digital/ModemST.h @@ -5,9 +5,11 @@ class ModemST : public ModemDigital { public: ModemST(); ~ModemST(); + std::string getName(); + Modem *factory(); - void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/visual/PrimaryGLContext.cpp b/src/visual/PrimaryGLContext.cpp index 7aea40a..612e6bf 100644 --- a/src/visual/PrimaryGLContext.cpp +++ b/src/visual/PrimaryGLContext.cpp @@ -230,9 +230,9 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBA4f color, long } // advanced demodulators start here - if (demod->getDemodulatorCons() > 0) { - demodStr = demodStr + std::to_string(demod->getDemodulatorCons()); - } +// if (demod->getDemodulatorCons() > 0) { +// demodStr = demodStr + std::to_string(demod->getDemodulatorCons()); +// } // add lock to string if we have an lock if(demod->getDemodulatorLock()) { From 4af943791b1e57be72ef8905e4c3d59a91a60045 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 23 Nov 2015 20:44:48 -0500 Subject: [PATCH 06/24] Modem can now trigger kit rebuild, add FSK test settings --- src/demod/DemodulatorPreThread.cpp | 7 ++++- src/demod/DemodulatorWorkerThread.cpp | 3 +++ src/modules/modem/Modem.cpp | 12 +++++++++ src/modules/modem/Modem.h | 10 +++++++ src/modules/modem/digital/ModemFSK.cpp | 37 +++++++++++++++++++++++--- 5 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 9a4d5db..1c9718f 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -108,7 +108,12 @@ void DemodulatorPreThread::run() { sampleRateChanged.store(false); audioSampleRateChanged.store(false); demodTypeChanged.store(false); - } else if (cModemKit && cModem && (bandwidthChanged.load() || sampleRateChanged.load() || audioSampleRateChanged.load()) && (newSampleRate && newAudioSampleRate && newBandwidth)) { + } + else if ( + cModemKit && cModem && + (bandwidthChanged.load() || sampleRateChanged.load() || audioSampleRateChanged.load() || cModem->shouldRebuildKit()) && + (newSampleRate && newAudioSampleRate && newBandwidth) + ) { DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS); command.frequency = newFrequency; command.sampleRate = newSampleRate; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index 46fdadb..fcf4276 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -72,6 +72,9 @@ void DemodulatorWorkerThread::run() { } else if (makeDemod) { cModemKit = nullptr; } + if (cModem != nullptr) { + cModem->clearRebuildKit(); + } float As = 60.0f; // stop-band attenuation [dB] diff --git a/src/modules/modem/Modem.cpp b/src/modules/modem/Modem.cpp index 69adc7b..21fb816 100644 --- a/src/modules/modem/Modem.cpp +++ b/src/modules/modem/Modem.cpp @@ -55,3 +55,15 @@ Modem::Modem() { Modem::~Modem() { } + +bool Modem::shouldRebuildKit() { + return refreshKit.load(); +} + +void Modem::rebuildKit() { + refreshKit.store(true); +} + +void Modem::clearRebuildKit() { + refreshKit.store(false); +} diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h index 7edb2d5..1ca1ece 100644 --- a/src/modules/modem/Modem.h +++ b/src/modules/modem/Modem.h @@ -4,6 +4,7 @@ #include "IOThread.h" #include "AudioThread.h" #include +#include class ModemKit { public: @@ -108,9 +109,12 @@ class Modem { public: static void addModemFactory(Modem *factorySingle); static ModemFactoryList getFactories(); + static Modem *makeModem(std::string modemType); + virtual std::string getType() = 0; virtual std::string getName() = 0; + virtual Modem *factory() = 0; Modem(); @@ -126,6 +130,12 @@ public: virtual void disposeKit(ModemKit *kit) = 0; virtual void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) = 0; + + bool shouldRebuildKit(); + void rebuildKit(); + void clearRebuildKit(); + private: static ModemFactoryList modemFactories; + std::atomic_bool refreshKit; }; diff --git a/src/modules/modem/digital/ModemFSK.cpp b/src/modules/modem/digital/ModemFSK.cpp index aad5bfd..38c9871 100644 --- a/src/modules/modem/digital/ModemFSK.cpp +++ b/src/modules/modem/digital/ModemFSK.cpp @@ -1,6 +1,7 @@ #include "ModemFSK.h" ModemFSK::ModemFSK() { + // DMR defaults? bps = 9600; spacing = 7000; } @@ -12,14 +13,42 @@ Modem *ModemFSK::factory() { ModemArgInfoList ModemFSK::getSettings() { ModemArgInfoList args; + ModemArgInfo bpsArg; + bpsArg.key = "bps"; + bpsArg.name = "Bits per-symbol"; + bpsArg.value = std::to_string(bps); + bpsArg.description = "FSK modem bits-per-symbol"; + bpsArg.type = ModemArgInfo::STRING; + + std::vector bpsOpts; + bpsOpts.push_back("9600"); + bpsArg.options = bpsOpts; + + args.push_back(bpsArg); + + ModemArgInfo spacingArg; + spacingArg.key = "spacing"; + spacingArg.name = "Symbol Spacing?"; + spacingArg.description = "Not quite sure yet :-)"; + spacingArg.type = ModemArgInfo::STRING; + spacingArg.value = std::to_string(spacing); + + std::vector spacingOpts; + spacingOpts.push_back("7000"); + spacingArg.options = spacingOpts; + + args.push_back(spacingArg); + return args; } void ModemFSK::writeSetting(std::string setting, std::string value) { if (setting == "bps") { - + bps = std::stoi(value); + rebuildKit(); } else if (setting == "spacing") { - + spacing = std::stoi(value); + rebuildKit(); } } @@ -35,8 +64,8 @@ std::string ModemFSK::readSetting(std::string setting) { ModemKit *ModemFSK::buildKit(long long sampleRate, int audioSampleRate) { ModemKitFSK *dkit = new ModemKitFSK; dkit->m = 1; - dkit->k = sampleRate / 9600; - dkit->bandwidth = 7000.0 / sampleRate; + dkit->k = sampleRate / bps; + dkit->bandwidth = double(spacing) / sampleRate; dkit->demodFSK = fskdem_create(dkit->m, dkit->k, dkit->bandwidth); From 5303f329df80e88fee625c9a9acf08ee3ae508f9 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 23 Nov 2015 21:32:50 -0500 Subject: [PATCH 07/24] ModemProperties panel property grid init --- CMakeLists.txt | 4 +- src/AppFrame.cpp | 5 +- src/AppFrame.h | 3 + src/ModemProperties.cpp | 108 ++++++++++++++++++++++++++++++++++++ src/ModemProperties.h | 30 ++++++++++ src/modules/modem/Modem.cpp | 10 ++++ 6 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 src/ModemProperties.cpp create mode 100644 src/ModemProperties.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b89525f..e4bf852 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ SET(CPACK_PACKAGE_VERSION_PATCH ${CUBICSDR_VERSION_PATCH}) SET (VERSION_SUFFIX "" CACHE STRING "Add custom version suffix to CubicSDR application title.") ADD_DEFINITIONS( - -DCUBICSDR_VERSION="${CUBICSDR_VERSION}-${VERSION_SUFFIX}" + -DCUBICSDR_VERSION="${CUBICSDR_VERSION}${VERSION_SUFFIX}" ) SET (ENABLE_DIGITAL_LAB OFF CACHE BOOL "Enable 'Digital Lab' testing features.") @@ -225,6 +225,7 @@ SET (cubicsdr_sources src/AppConfig.cpp src/FrequencyDialog.cpp src/IOThread.cpp + src/ModemProperties.cpp src/sdr/SDRDeviceInfo.cpp src/sdr/SDRPostThread.cpp src/sdr/SDREnumerator.cpp @@ -310,6 +311,7 @@ SET (cubicsdr_headers src/AppConfig.h src/FrequencyDialog.h src/IOThread.h + src/ModemProperties.h src/sdr/SDRDeviceInfo.h src/sdr/SDRPostThread.h src/sdr/SDREnumerator.h diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 0f9b47c..beb457f 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -79,7 +79,7 @@ AppFrame::AppFrame() : demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0); #ifdef ENABLE_DIGITAL_LAB - demodModeSelectorAdv = new ModeSelectorCanvas(this, attribList); + demodModeSelectorAdv = new ModeSelectorCanvas(demodPanel, attribList); demodModeSelectorAdv->addChoice(0, "ASK"); demodModeSelectorAdv->addChoice(1, "APSK"); demodModeSelectorAdv->addChoice(2, "BPSK"); @@ -93,6 +93,9 @@ AppFrame::AppFrame() : demodModeSelectorAdv->addChoice(10, "QPSK"); demodModeSelectorAdv->setHelpTip("Choose advanced modulation types."); demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0); + + modemProps = new ModemProperties(demodPanel, wxID_ANY); + demodTray->Add(modemProps, 10, wxEXPAND | wxALL, 0); #endif wxGetApp().getDemodSpectrumProcessor()->setup(1024); diff --git a/src/AppFrame.h b/src/AppFrame.h index 2ca576a..3700579 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -16,6 +16,7 @@ #include "GainCanvas.h" #include "FFTVisualDataThread.h" #include "SDRDeviceInfo.h" +#include "ModemProperties.h" //#include "UITestCanvas.h" #include @@ -120,6 +121,8 @@ private: std::thread *t_FFTData; SDRDeviceInfo *devInfo; std::atomic_bool deviceChanged; + + ModemProperties *modemProps; wxDECLARE_EVENT_TABLE(); }; diff --git a/src/ModemProperties.cpp b/src/ModemProperties.cpp new file mode 100644 index 0000000..07485f9 --- /dev/null +++ b/src/ModemProperties.cpp @@ -0,0 +1,108 @@ +#include "ModemProperties.h" + +ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid, + const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel(parent, winid, pos, size, style, name) { + + m_propertyGrid = new wxPropertyGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPG_DEFAULT_STYLE); + + wxBoxSizer* bSizer; + + bSizer = new wxBoxSizer( wxVERTICAL ); + + bSizer->Add(m_propertyGrid, wxEXPAND ); + + this->SetSizer(bSizer); +} + +ModemProperties::~ModemProperties() { + +} + +void ModemProperties::initProperties(ModemArgInfoList newArgs) { + args = newArgs; + +// props.erase(props.begin(), props.end()); + + m_propertyGrid->Clear(); + m_propertyGrid->Append(new wxPropertyCategory("Modem Settings")); + + ModemArgInfoList::const_iterator args_i; + + for (args_i = args.begin(); args_i != args.end(); args_i++) { + ModemArgInfo arg = (*args_i); + props.push_back(addArgInfoProperty(m_propertyGrid, arg)); + } +} + +wxPGProperty *ModemProperties::addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg) { + wxPGProperty *prop = nullptr; + + int intVal; + double floatVal; + std::vector::iterator stringIter; + + switch (arg.type) { + case ModemArgInfo::INT: + try { + intVal = std::stoi(arg.value); + } catch (std::invalid_argument e) { + intVal = 0; + } + prop = pg->Append( new wxIntProperty(arg.name, wxPG_LABEL, intVal) ); + if (arg.range.minimum() != arg.range.maximum()) { + pg->SetPropertyAttribute( prop, wxPG_ATTR_MIN, arg.range.minimum()); + pg->SetPropertyAttribute( prop, wxPG_ATTR_MAX, arg.range.maximum()); + } + break; + case ModemArgInfo::FLOAT: + try { + floatVal = std::stod(arg.value); + } catch (std::invalid_argument e) { + floatVal = 0; + } + prop = pg->Append( new wxFloatProperty(arg.name, wxPG_LABEL, floatVal) ); + if (arg.range.minimum() != arg.range.maximum()) { + pg->SetPropertyAttribute( prop, wxPG_ATTR_MIN, arg.range.minimum()); + pg->SetPropertyAttribute( prop, wxPG_ATTR_MAX, arg.range.maximum()); + } + break; + case ModemArgInfo::BOOL: + prop = pg->Append( new wxBoolProperty(arg.name, wxPG_LABEL, (arg.value=="true")) ); + break; + case ModemArgInfo::STRING: + if (arg.options.size()) { + intVal = 0; + prop = pg->Append( new wxEnumProperty(arg.name, wxPG_LABEL) ); + for (stringIter = arg.options.begin(); stringIter != arg.options.end(); stringIter++) { + std::string optName = (*stringIter); + std::string displayName = optName; + if (arg.optionNames.size()) { + displayName = arg.optionNames[intVal]; + } + + prop->AddChoice(displayName); + if ((*stringIter)==arg.value) { + prop->SetChoiceSelection(intVal); + } + + intVal++; + } + } else { + prop = pg->Append( new wxStringProperty(arg.name, wxPG_LABEL, arg.value) ); + } + break; + case ModemArgInfo::PATH_DIR: + break; + case ModemArgInfo::PATH_FILE: + break; + case ModemArgInfo::COLOR: + break; + } + + if (prop != NULL) { + prop->SetHelpString(arg.key + ": " + arg.description); + } + + return prop; +} + diff --git a/src/ModemProperties.h b/src/ModemProperties.h new file mode 100644 index 0000000..a2dd775 --- /dev/null +++ b/src/ModemProperties.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include + +#include "Modem.h" + +class ModemProperties : public wxPanel { +public: + ModemProperties( + wxWindow *parent, + wxWindowID winid = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTAB_TRAVERSAL | wxNO_BORDER, + const wxString& name = wxPanelNameStr + ); + ~ModemProperties(); + + void initProperties(ModemArgInfoList newArgs); + +private: + wxPGProperty *addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg); + + wxPropertyGrid* m_propertyGrid; + ModemArgInfoList args; + std::vector props; +}; \ No newline at end of file diff --git a/src/modules/modem/Modem.cpp b/src/modules/modem/Modem.cpp index 21fb816..c2cd74b 100644 --- a/src/modules/modem/Modem.cpp +++ b/src/modules/modem/Modem.cpp @@ -14,6 +14,16 @@ ModemRange::ModemRange(const double minimum, const double maximum) { _max = maximum; } +//! Get the range minimum +double ModemRange::minimum(void) const { + return _min; +} + +//! Get the range maximum +double ModemRange::maximum(void) const { + return _max; +} + ModemArgInfo::ModemArgInfo(void) { } From c5bccb42115bdc79eeeb5a9d89688bc60a7356c3 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 23 Nov 2015 22:03:14 -0500 Subject: [PATCH 08/24] Modem property grid now shows interactive settings - Not yet applied --- src/AppFrame.cpp | 12 +++++++++++- src/AppFrame.h | 4 ++++ src/ModemProperties.cpp | 2 +- src/demod/DemodulatorWorkerThread.cpp | 2 ++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index beb457f..85aaaf6 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -94,8 +94,9 @@ AppFrame::AppFrame() : demodModeSelectorAdv->setHelpTip("Choose advanced modulation types."); demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0); + modemPropertiesUpdated.store(false); modemProps = new ModemProperties(demodPanel, wxID_ANY); - demodTray->Add(modemProps, 10, wxEXPAND | wxALL, 0); + demodTray->Add(modemProps, 15, wxEXPAND | wxALL, 0); #endif wxGetApp().getDemodSpectrumProcessor()->setup(1024); @@ -1046,6 +1047,10 @@ void AppFrame::OnIdle(wxIdleEvent& event) { wproc->setCenterFrequency(waterfallCanvas->getCenterFrequency()); wxGetApp().getSDRPostThread()->setIQVisualRange(waterfallCanvas->getCenterFrequency(), waterfallCanvas->getBandwidth()); + if (modemPropertiesUpdated.load()) { + modemProps->initProperties(newModemArgs); + modemPropertiesUpdated.store(false); + } // waterfallCanvas->processInputQueue(); // waterfallCanvas->Refresh(); // demodWaterfallCanvas->processInputQueue(); @@ -1246,3 +1251,8 @@ FFTVisualDataThread *AppFrame::getWaterfallDataThread() { return waterfallDataThread; } +void AppFrame::updateModemProperties(ModemArgInfoList args) { + newModemArgs = args; + modemPropertiesUpdated.store(true); +} + diff --git a/src/AppFrame.h b/src/AppFrame.h index 3700579..454b5e4 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -68,6 +68,8 @@ public: FFTVisualDataThread *getWaterfallDataThread(); + void updateModemProperties(ModemArgInfoList args); + private: void OnMenu(wxCommandEvent& event); void OnClose(wxCloseEvent& event); @@ -123,6 +125,8 @@ private: std::atomic_bool deviceChanged; ModemProperties *modemProps; + std::atomic_bool modemPropertiesUpdated; + ModemArgInfoList newModemArgs; wxDECLARE_EVENT_TABLE(); }; diff --git a/src/ModemProperties.cpp b/src/ModemProperties.cpp index 07485f9..ec46160 100644 --- a/src/ModemProperties.cpp +++ b/src/ModemProperties.cpp @@ -9,7 +9,7 @@ ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid, bSizer = new wxBoxSizer( wxVERTICAL ); - bSizer->Add(m_propertyGrid, wxEXPAND ); + bSizer->Add(m_propertyGrid, 1, wxEXPAND | wxALL, 5); this->SetSizer(bSizer); } diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index fcf4276..03aac69 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -1,5 +1,6 @@ #include "DemodulatorWorkerThread.h" #include "CubicSDRDefs.h" +#include "CubicSDR.h" #include DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(), @@ -52,6 +53,7 @@ void DemodulatorWorkerThread::run() { cModem = Modem::makeModem(demodCommand.demodType); cModemType = demodCommand.demodType; result.sampleRate = demodCommand.sampleRate; + wxGetApp().getAppFrame()->updateModemProperties(cModem->getSettings()); } result.modem = cModem; From abdb5d32d9c62c0e841a4bcf5b87502bfed1bd6a Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 23 Nov 2015 22:16:09 -0500 Subject: [PATCH 09/24] Modem instance setting read/write --- src/AppFrame.cpp | 2 ++ src/demod/DemodulatorInstance.cpp | 27 +++++++++++++++++++++++++++ src/demod/DemodulatorInstance.h | 4 ++++ 3 files changed, 33 insertions(+) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 85aaaf6..98106a2 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -856,6 +856,8 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demodModeSelectorAdv->setSelection(dType); #endif demodMuteButton->setSelection(demod->isMuted()?1:-1); + newModemArgs = demod->getModemArgs(); + modemPropertiesUpdated.store(true); } if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) { long long centerFreq = demod->getFrequency(); diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 33c5832..1866c4b 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -330,3 +330,30 @@ void DemodulatorInstance::setMuted(bool muted) { DemodulatorThreadInputQueue *DemodulatorInstance::getIQInputDataPipe() { return pipeIQInputData; } + +ModemArgInfoList DemodulatorInstance::getModemArgs() { + Modem *m = demodulatorPreThread->getModem(); + + ModemArgInfoList args; + if (m != nullptr) { + args = m->getSettings(); + } + return args; +} + +std::string DemodulatorInstance::readModemSetting(std::string setting) { + Modem *m = demodulatorPreThread->getModem(); + + if (m) { + return m->readSetting(setting); + } + return ""; +} + +void DemodulatorInstance::writeModemSetting(std::string setting, std::string value) { + Modem *m = demodulatorPreThread->getModem(); + + if (m) { + m->writeSetting(setting, value); + } +} diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index 58801ae..4b0e86f 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -82,6 +82,10 @@ public: DemodulatorThreadInputQueue *getIQInputDataPipe(); + ModemArgInfoList getModemArgs(); + std::string readModemSetting(std::string setting); + void writeModemSetting(std::string setting, std::string value); + protected: DemodulatorThreadInputQueue* pipeIQInputData; DemodulatorThreadPostInputQueue* pipeIQDemodData; From 6e74662518a9f43baa8cd41a2bd26091ae7e75fd Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 23 Nov 2015 22:39:39 -0500 Subject: [PATCH 10/24] Modem property grid settings now applying/working - Still some races with initializing the grid on new demodulators --- src/ModemProperties.cpp | 43 +++++++++++++++++++++++-- src/ModemProperties.h | 6 ++-- src/modules/modem/digital/ModemAPSK.cpp | 11 +------ 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/ModemProperties.cpp b/src/ModemProperties.cpp index ec46160..7dc579b 100644 --- a/src/ModemProperties.cpp +++ b/src/ModemProperties.cpp @@ -1,4 +1,5 @@ #include "ModemProperties.h" +#include "CubicSDR.h" ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel(parent, winid, pos, size, style, name) { @@ -12,6 +13,8 @@ ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid, bSizer->Add(m_propertyGrid, 1, wxEXPAND | wxALL, 5); this->SetSizer(bSizer); + + m_propertyGrid->Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( ModemProperties::OnChange ), NULL, this ); } ModemProperties::~ModemProperties() { @@ -21,8 +24,6 @@ ModemProperties::~ModemProperties() { void ModemProperties::initProperties(ModemArgInfoList newArgs) { args = newArgs; -// props.erase(props.begin(), props.end()); - m_propertyGrid->Clear(); m_propertyGrid->Append(new wxPropertyCategory("Modem Settings")); @@ -30,7 +31,7 @@ void ModemProperties::initProperties(ModemArgInfoList newArgs) { for (args_i = args.begin(); args_i != args.end(); args_i++) { ModemArgInfo arg = (*args_i); - props.push_back(addArgInfoProperty(m_propertyGrid, arg)); + props[arg.key] = addArgInfoProperty(m_propertyGrid, arg); } } @@ -106,3 +107,39 @@ wxPGProperty *ModemProperties::addArgInfoProperty(wxPropertyGrid *pg, ModemArgIn return prop; } +std::string ModemProperties::readProperty(std::string key) { + int i = 0; + ModemArgInfoList::const_iterator args_i; + + for (args_i = args.begin(); args_i != args.end(); args_i++) { + ModemArgInfo arg = (*args_i); + if (arg.key == key) { + wxPGProperty *prop = props[key]; + + std::string result = ""; + if (arg.type == ModemArgInfo::STRING && arg.options.size()) { + return arg.options[prop->GetChoiceSelection()]; + } else if (arg.type == ModemArgInfo::BOOL) { + return (prop->GetValueAsString()=="True")?"true":"false"; + } else { + return prop->GetValueAsString().ToStdString(); + } + } + i++; + } + return ""; +} + +void ModemProperties::OnChange(wxPropertyGridEvent &event) { + DemodulatorInstance *inst = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + + std::map::const_iterator prop_i; + for (prop_i = props.begin(); prop_i != props.end(); prop_i++) { + if (prop_i->second == event.m_property) { + std::string key = prop_i->first; + std::string value = readProperty(prop_i->first); + inst->writeModemSetting(key, value); + return; + } + } +} diff --git a/src/ModemProperties.h b/src/ModemProperties.h index a2dd775..453a102 100644 --- a/src/ModemProperties.h +++ b/src/ModemProperties.h @@ -20,11 +20,13 @@ public: ~ModemProperties(); void initProperties(ModemArgInfoList newArgs); - + private: wxPGProperty *addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg); + std::string readProperty(std::string); + void OnChange(wxPropertyGridEvent &event); wxPropertyGrid* m_propertyGrid; ModemArgInfoList args; - std::vector props; + std::map props; }; \ No newline at end of file diff --git a/src/modules/modem/digital/ModemAPSK.cpp b/src/modules/modem/digital/ModemAPSK.cpp index f7d72d5..febd4fe 100644 --- a/src/modules/modem/digital/ModemAPSK.cpp +++ b/src/modules/modem/digital/ModemAPSK.cpp @@ -68,37 +68,28 @@ std::string ModemAPSK::readSetting(std::string setting) { } void ModemAPSK::updateDemodulatorCons(int cons) { + this->cons = cons; switch (cons) { case 4: demodAPSK = demodAPSK4; - updateDemodulatorCons(4); break; case 8: demodAPSK = demodAPSK8; - updateDemodulatorCons(8); break; case 16: demodAPSK = demodAPSK16; - updateDemodulatorCons(16); break; case 32: demodAPSK = demodAPSK32; - updateDemodulatorCons(32); break; case 64: demodAPSK = demodAPSK64; - updateDemodulatorCons(64); break; case 128: demodAPSK = demodAPSK128; - updateDemodulatorCons(128); break; case 256: demodAPSK = demodAPSK256; - updateDemodulatorCons(256); - break; - default: - demodAPSK = demodAPSK4; break; } } From d14dfed0638c9baebcaf131d663eb7f779ac0110 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 24 Nov 2015 00:20:17 -0500 Subject: [PATCH 11/24] FSK now appears somewhat functional (outputs symbols to console) --- src/modules/modem/analog/ModemFMStereo.h | 5 ++ src/modules/modem/digital/ModemFSK.cpp | 73 +++++++++++++++--------- src/modules/modem/digital/ModemFSK.h | 6 +- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/modules/modem/analog/ModemFMStereo.h b/src/modules/modem/analog/ModemFMStereo.h index 88d49f5..10808f8 100644 --- a/src/modules/modem/analog/ModemFMStereo.h +++ b/src/modules/modem/analog/ModemFMStereo.h @@ -20,12 +20,17 @@ class ModemFMStereo : public Modem { public: ModemFMStereo(); ~ModemFMStereo(); + std::string getType(); std::string getName(); + Modem *factory(); + int checkSampleRate(long long sampleRate, int audioSampleRate); + ModemKit *buildKit(long long sampleRate, int audioSampleRate); void disposeKit(ModemKit *kit); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/modules/modem/digital/ModemFSK.cpp b/src/modules/modem/digital/ModemFSK.cpp index 38c9871..f5b08fa 100644 --- a/src/modules/modem/digital/ModemFSK.cpp +++ b/src/modules/modem/digital/ModemFSK.cpp @@ -2,43 +2,62 @@ ModemFSK::ModemFSK() { // DMR defaults? - bps = 9600; - spacing = 7000; + bps = 1; + sps = 9600; } Modem *ModemFSK::factory() { return new ModemFSK; } +int ModemFSK::checkSampleRate(long long sampleRate, int audioSampleRate) { + float minSps = pow(2.0,bps); + float nextSps = (float(sampleRate) / float(sps)); + if (nextSps < minSps) { + return 2 * bps * sps; + } else { + return sampleRate; + } +} + ModemArgInfoList ModemFSK::getSettings() { ModemArgInfoList args; ModemArgInfo bpsArg; bpsArg.key = "bps"; - bpsArg.name = "Bits per-symbol"; + bpsArg.name = "Bits/symbol"; bpsArg.value = std::to_string(bps); - bpsArg.description = "FSK modem bits-per-symbol"; + bpsArg.description = "Modem bits-per-symbol"; bpsArg.type = ModemArgInfo::STRING; std::vector bpsOpts; - bpsOpts.push_back("9600"); + bpsOpts.push_back("1"); + bpsOpts.push_back("2"); + bpsOpts.push_back("4"); + bpsOpts.push_back("8"); bpsArg.options = bpsOpts; args.push_back(bpsArg); - - ModemArgInfo spacingArg; - spacingArg.key = "spacing"; - spacingArg.name = "Symbol Spacing?"; - spacingArg.description = "Not quite sure yet :-)"; - spacingArg.type = ModemArgInfo::STRING; - spacingArg.value = std::to_string(spacing); - - std::vector spacingOpts; - spacingOpts.push_back("7000"); - spacingArg.options = spacingOpts; - args.push_back(spacingArg); + ModemArgInfo spsArg; + spsArg.key = "sps"; + spsArg.name = "Symbols/second"; + spsArg.value = std::to_string(sps); + spsArg.description = "Modem symbols-per-second"; + spsArg.type = ModemArgInfo::STRING; + std::vector spsOpts; + // some common modem rates ..? + spsOpts.push_back("1200"); + spsOpts.push_back("2400"); + spsOpts.push_back("4800"); + spsOpts.push_back("9600"); + spsOpts.push_back("19200"); + spsOpts.push_back("38400"); + spsArg.options = spsOpts; + + args.push_back(spsArg); + return args; } @@ -46,8 +65,8 @@ void ModemFSK::writeSetting(std::string setting, std::string value) { if (setting == "bps") { bps = std::stoi(value); rebuildKit(); - } else if (setting == "spacing") { - spacing = std::stoi(value); + } else if (setting == "sps") { + sps = std::stoi(value); rebuildKit(); } } @@ -55,19 +74,18 @@ void ModemFSK::writeSetting(std::string setting, std::string value) { std::string ModemFSK::readSetting(std::string setting) { if (setting == "bps") { return std::to_string(bps); - } else if (setting == "spacing") { - return std::to_string(spacing); + } else if (setting == "sps") { + return std::to_string(sps); } return ""; } ModemKit *ModemFSK::buildKit(long long sampleRate, int audioSampleRate) { ModemKitFSK *dkit = new ModemKitFSK; - dkit->m = 1; - dkit->k = sampleRate / bps; - dkit->bandwidth = double(spacing) / sampleRate; + dkit->m = bps; + dkit->k = sampleRate / sps; - dkit->demodFSK = fskdem_create(dkit->m, dkit->k, dkit->bandwidth); + dkit->demodFSK = fskdem_create(dkit->m, dkit->k, 0.45); dkit->sampleRate = sampleRate; dkit->audioSampleRate = audioSampleRate; @@ -78,6 +96,8 @@ ModemKit *ModemFSK::buildKit(long long sampleRate, int audioSampleRate) { void ModemFSK::disposeKit(ModemKit *kit) { ModemKitFSK *dkit = (ModemKitFSK *)kit; + fskdem_destroy(dkit->demodFSK); + delete dkit; } @@ -100,7 +120,8 @@ void ModemFSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a unsigned int sym_out; sym_out = fskdem_demodulate(dkit->demodFSK, &dkit->inputBuffer[0]); -// std::cout << "ferror: " << fskdem_get_frequency_error(dkit->demodFSK) << std::endl; +// float err = fskdem_get_frequency_error(dkit->demodFSK); +// std::cout << "ferror: " << err << std::endl; printf("%01X", sym_out); dkit->inputBuffer.erase(dkit->inputBuffer.begin(),dkit->inputBuffer.begin()+dkit->k); } diff --git a/src/modules/modem/digital/ModemFSK.h b/src/modules/modem/digital/ModemFSK.h index a5392ae..2eab813 100644 --- a/src/modules/modem/digital/ModemFSK.h +++ b/src/modules/modem/digital/ModemFSK.h @@ -3,7 +3,6 @@ class ModemKitFSK : public ModemKitDigital { public: - float sps, spacing, bandwidth; unsigned int m, k; fskdem demodFSK; @@ -20,6 +19,8 @@ public: Modem *factory(); + int checkSampleRate(long long sampleRate, int audioSampleRate); + ModemArgInfoList getSettings(); void writeSetting(std::string setting, std::string value); std::string readSetting(std::string setting); @@ -30,6 +31,7 @@ public: void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: - int bps, spacing; + int sps; + int bps; }; From 67edfab862a9105fecee10627d3ae947f0eedf12 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 24 Nov 2015 23:00:43 -0500 Subject: [PATCH 12/24] Show/Hide modem properties when available --- src/AppFrame.cpp | 2 ++ src/ModemProperties.cpp | 22 +++++++++++++++++++--- src/ModemProperties.h | 4 +++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 98106a2..fd584f9 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -96,6 +96,7 @@ AppFrame::AppFrame() : modemPropertiesUpdated.store(false); modemProps = new ModemProperties(demodPanel, wxID_ANY); + modemProps->Hide(); demodTray->Add(modemProps, 15, wxEXPAND | wxALL, 0); #endif @@ -1052,6 +1053,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { if (modemPropertiesUpdated.load()) { modemProps->initProperties(newModemArgs); modemPropertiesUpdated.store(false); + demodTray->Layout(); } // waterfallCanvas->processInputQueue(); // waterfallCanvas->Refresh(); diff --git a/src/ModemProperties.cpp b/src/ModemProperties.cpp index 7dc579b..c679e3d 100644 --- a/src/ModemProperties.cpp +++ b/src/ModemProperties.cpp @@ -5,8 +5,6 @@ ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel(parent, winid, pos, size, style, name) { m_propertyGrid = new wxPropertyGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPG_DEFAULT_STYLE); - - wxBoxSizer* bSizer; bSizer = new wxBoxSizer( wxVERTICAL ); @@ -15,6 +13,11 @@ ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid, this->SetSizer(bSizer); m_propertyGrid->Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( ModemProperties::OnChange ), NULL, this ); + this->Connect( wxEVT_SHOW, wxShowEventHandler( ModemProperties::OnShow ), NULL, this ); +} + +void ModemProperties::OnShow(wxShowEvent &event) { + m_propertyGrid->FitColumns(); } ModemProperties::~ModemProperties() { @@ -23,8 +26,19 @@ ModemProperties::~ModemProperties() { void ModemProperties::initProperties(ModemArgInfoList newArgs) { args = newArgs; - + m_propertyGrid->Clear(); + + if (newArgs.size() == 0) { + Hide(); + return; + } else { + Show(); + } + + bSizer->Layout(); + Layout(); + m_propertyGrid->Append(new wxPropertyCategory("Modem Settings")); ModemArgInfoList::const_iterator args_i; @@ -33,6 +47,8 @@ void ModemProperties::initProperties(ModemArgInfoList newArgs) { ModemArgInfo arg = (*args_i); props[arg.key] = addArgInfoProperty(m_propertyGrid, arg); } + + m_propertyGrid->FitColumns(); } wxPGProperty *ModemProperties::addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg) { diff --git a/src/ModemProperties.h b/src/ModemProperties.h index 453a102..5a101c0 100644 --- a/src/ModemProperties.h +++ b/src/ModemProperties.h @@ -25,7 +25,9 @@ private: wxPGProperty *addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg); std::string readProperty(std::string); void OnChange(wxPropertyGridEvent &event); - + void OnShow(wxShowEvent &event); + + wxBoxSizer* bSizer; wxPropertyGrid* m_propertyGrid; ModemArgInfoList args; std::map props; From 1fb5dc42365a8d0dafac3c6bdd819e83981bb645 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 24 Nov 2015 23:32:40 -0500 Subject: [PATCH 13/24] Fix non-digital-lab build --- src/AppFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index fd584f9..0547cd3 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -93,12 +93,12 @@ AppFrame::AppFrame() : demodModeSelectorAdv->addChoice(10, "QPSK"); demodModeSelectorAdv->setHelpTip("Choose advanced modulation types."); demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0); +#endif modemPropertiesUpdated.store(false); modemProps = new ModemProperties(demodPanel, wxID_ANY); modemProps->Hide(); demodTray->Add(modemProps, 15, wxEXPAND | wxALL, 0); -#endif wxGetApp().getDemodSpectrumProcessor()->setup(1024); demodSpectrumCanvas = new SpectrumCanvas(demodPanel, attribList); From 4fa0cb7c677c7670ed1b9083c53c774f9b38fae2 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 26 Nov 2015 01:54:54 -0500 Subject: [PATCH 14/24] Persist modem settings on new instances --- src/AppFrame.cpp | 20 +++++++-- src/CubicSDR.h | 1 - src/demod/DemodulatorInstance.cpp | 34 +++++++++----- src/demod/DemodulatorInstance.h | 4 ++ src/demod/DemodulatorMgr.cpp | 27 +++++++++-- src/demod/DemodulatorMgr.h | 12 ++++- src/demod/DemodulatorPreThread.cpp | 65 ++++++++++++++++++++------- src/demod/DemodulatorPreThread.h | 11 ++++- src/demod/DemodulatorWorkerThread.cpp | 3 ++ src/demod/DemodulatorWorkerThread.h | 1 + src/modules/modem/Modem.cpp | 23 ++++++++-- src/modules/modem/Modem.h | 4 ++ src/visual/WaterfallCanvas.cpp | 28 +++++++++--- 13 files changed, 185 insertions(+), 48 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 0547cd3..5efdd4a 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -826,7 +826,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); - if (demod) { + if (demod && demod->isModemInitialized()) { if (demod->isTracking()) { if (spectrumCanvas->getViewState()) { long long diff = abs(demod->getFrequency() - spectrumCanvas->getCenterFrequency()) + (demod->getBandwidth()/2) + (demod->getBandwidth()/4); @@ -844,6 +844,10 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demod->setTracking(false); } } + + if (demod->getBandwidth() != wxGetApp().getDemodMgr().getLastBandwidth()) { + wxGetApp().getDemodMgr().setLastBandwidth(demod->getBandwidth()); + } if (demod != activeDemodulator) { demodSignalMeter->setInputValue(demod->getSquelchLevel()); @@ -857,7 +861,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demodModeSelectorAdv->setSelection(dType); #endif demodMuteButton->setSelection(demod->isMuted()?1:-1); - newModemArgs = demod->getModemArgs(); modemPropertiesUpdated.store(true); } if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) { @@ -893,16 +896,25 @@ void AppFrame::OnIdle(wxIdleEvent& event) { if (dSelection != "" && dSelection != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelection); demodModeSelectorAdv->setSelection(-1); + if (int lastDemodBw = wxGetApp().getDemodMgr().getLastBandwidth(dSelection)) { + demod->setBandwidth(lastDemodBw); + } } // advanced demodulators else if (dSelectionadv != "" && dSelectionadv != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelectionadv); demodModeSelector->setSelection(-1); + if (int lastDemodBw = wxGetApp().getDemodMgr().getLastBandwidth(dSelection)) { + demod->setBandwidth(lastDemodBw); + } } #else // basic demodulators if (dSelection != "" && dSelection != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelection); + if (int lastDemodBw = wxGetApp().getDemodMgr().getLastBandwidth(dSelection)) { + demod->setBandwidth(lastDemodBw); + } } #endif @@ -1050,8 +1062,10 @@ void AppFrame::OnIdle(wxIdleEvent& event) { wproc->setCenterFrequency(waterfallCanvas->getCenterFrequency()); wxGetApp().getSDRPostThread()->setIQVisualRange(waterfallCanvas->getCenterFrequency(), waterfallCanvas->getBandwidth()); + demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + if (modemPropertiesUpdated.load()) { - modemProps->initProperties(newModemArgs); + modemProps->initProperties(demod->getModemArgs()); modemPropertiesUpdated.store(false); demodTray->Layout(); } diff --git a/src/CubicSDR.h b/src/CubicSDR.h index fd774ce..6de2843 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -126,7 +126,6 @@ public: void setDeviceSelectorClosed(); bool isDeviceSelectorOpen(); void closeDeviceSelector(); - void setAGCMode(bool mode); bool getAGCMode(); diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 1866c4b..d09b587 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -1,4 +1,5 @@ #include "DemodulatorInstance.h" +#include "CubicSDR.h" DemodulatorInstance::DemodulatorInstance() : t_PreDemod(NULL), t_Demod(NULL), t_Audio(NULL) { @@ -20,6 +21,8 @@ DemodulatorInstance::DemodulatorInstance() : pipeIQDemodData = new DemodulatorThreadPostInputQueue; pipeDemodNotify = new DemodulatorThreadCommandQueue; + audioThread = new AudioThread(); + demodulatorPreThread = new DemodulatorPreThread(this); demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData); demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData); @@ -34,7 +37,6 @@ DemodulatorInstance::DemodulatorInstance() : demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify); demodulatorThread->setOutputQueue("AudioDataOutput", pipeAudioData); - audioThread = new AudioThread(); audioThread->setInputQueue("AudioDataInput", pipeAudioData); audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify); } @@ -204,6 +206,8 @@ float DemodulatorInstance::getSignalLevel() { void DemodulatorInstance::setSquelchLevel(float signal_level_in) { demodulatorThread->setSquelchLevel(signal_level_in); + wxGetApp().getDemodMgr().setLastSquelchLevel(signal_level_in); + wxGetApp().getDemodMgr().setLastSquelchEnabled(true); } float DemodulatorInstance::getSquelchLevel() { @@ -263,6 +267,7 @@ int DemodulatorInstance::getDemodulatorLock() { void DemodulatorInstance::setBandwidth(int bw) { demodulatorPreThread->setBandwidth(bw); + wxGetApp().getDemodMgr().setLastBandwidth(bw); } int DemodulatorInstance::getBandwidth() { @@ -296,6 +301,7 @@ int DemodulatorInstance::getAudioSampleRate() { void DemodulatorInstance::setGain(float gain_in) { currentAudioGain = gain_in; audioThread->setGain(gain_in); + wxGetApp().getDemodMgr().setLastGain(gain_in); } float DemodulatorInstance::getGain() { @@ -325,6 +331,7 @@ bool DemodulatorInstance::isMuted() { void DemodulatorInstance::setMuted(bool muted) { this->muted = muted; demodulatorThread->setMuted(muted); + wxGetApp().getDemodMgr().setLastMuted(muted); } DemodulatorThreadInputQueue *DemodulatorInstance::getIQInputDataPipe() { @@ -342,18 +349,21 @@ ModemArgInfoList DemodulatorInstance::getModemArgs() { } std::string DemodulatorInstance::readModemSetting(std::string setting) { - Modem *m = demodulatorPreThread->getModem(); - - if (m) { - return m->readSetting(setting); - } - return ""; + return demodulatorPreThread->readModemSetting(setting); } void DemodulatorInstance::writeModemSetting(std::string setting, std::string value) { - Modem *m = demodulatorPreThread->getModem(); - - if (m) { - m->writeSetting(setting, value); - } + demodulatorPreThread->writeModemSetting(setting, value); } + +ModemSettings DemodulatorInstance::readModemSettings() { + return demodulatorPreThread->readModemSettings(); +} + +void DemodulatorInstance::writeModemSettings(ModemSettings settings) { + demodulatorPreThread->writeModemSettings(settings); +} + +bool DemodulatorInstance::isModemInitialized() { + return demodulatorPreThread->isInitialized(); +} \ No newline at end of file diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index 4b0e86f..6f01ee7 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -84,8 +84,12 @@ public: ModemArgInfoList getModemArgs(); std::string readModemSetting(std::string setting); + ModemSettings readModemSettings(); void writeModemSetting(std::string setting, std::string value); + void writeModemSettings(ModemSettings settings); + bool isModemInitialized(); + protected: DemodulatorThreadInputQueue* pipeIQInputData; DemodulatorThreadPostInputQueue* pipeIQDemodData; diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index 939bed0..4d6f874 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -8,7 +8,13 @@ DemodulatorMgr::DemodulatorMgr() : activeDemodulator(NULL), lastActiveDemodulator(NULL), activeVisualDemodulator(NULL), lastBandwidth(DEFAULT_DEMOD_BW), lastDemodType( DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(-100), lastGain(1.0), lastMuted(false) { - + setLastBandwidth("FM",200000); + setLastBandwidth("FMS",200000); + setLastBandwidth("AM",6000); + setLastBandwidth("USB",5400); + setLastBandwidth("LSB",5400); + setLastBandwidth("DSB",5400); + setLastBandwidth("IQ",48000); } DemodulatorMgr::~DemodulatorMgr() { @@ -88,6 +94,7 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo if (!temporary) { if (activeDemodulator != NULL) { lastActiveDemodulator = activeDemodulator; + updateLastState(); } else { lastActiveDemodulator = demod; } @@ -121,8 +128,6 @@ DemodulatorInstance *DemodulatorMgr::getActiveDemodulator() { } DemodulatorInstance *DemodulatorMgr::getLastActiveDemodulator() { - updateLastState(); - return lastActiveDemodulator; } @@ -165,6 +170,8 @@ void DemodulatorMgr::updateLastState() { lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled(); lastSquelch = lastActiveDemodulator->getSquelchLevel(); lastGain = lastActiveDemodulator->getGain(); + lastModemSettings[lastDemodType] = lastActiveDemodulator->readModemSettings(); + lastBandwidthNamed[lastDemodType] = lastBandwidth; } } @@ -222,3 +229,17 @@ void DemodulatorMgr::setLastMuted(bool lastMuted) { this->lastMuted = lastMuted; } +ModemSettings DemodulatorMgr::getLastModemSettings(std::string modemType) { + return lastModemSettings[modemType]; +} + +void DemodulatorMgr::setLastModemSettings(std::string modemType, ModemSettings settings) { + lastModemSettings[modemType] = settings; +} + +int DemodulatorMgr::getLastBandwidth(std::string modemType) { + return lastBandwidthNamed[modemType]; +} +void DemodulatorMgr::setLastBandwidth(std::string modemType, int lastBandwidth_in) { + lastBandwidthNamed[modemType] = lastBandwidth_in; +} diff --git a/src/demod/DemodulatorMgr.h b/src/demod/DemodulatorMgr.h index a93204e..1b178d9 100644 --- a/src/demod/DemodulatorMgr.h +++ b/src/demod/DemodulatorMgr.h @@ -25,6 +25,9 @@ public: int getLastBandwidth() const; void setLastBandwidth(int lastBandwidth); + int getLastBandwidth(std::string modemType); + void setLastBandwidth(std::string modemType, int lastBandwidth); + std::string getLastDemodulatorType() const; void setLastDemodulatorType(std::string lastDemodType); @@ -40,9 +43,13 @@ public: bool isLastMuted() const; void setLastMuted(bool lastMuted); + ModemSettings getLastModemSettings(std::string); + void setLastModemSettings(std::string, ModemSettings); + + void updateLastState(); + private: void garbageCollect(); - void updateLastState(); std::vector demods; std::vector demods_deleted; @@ -50,6 +57,7 @@ private: DemodulatorInstance *lastActiveDemodulator; DemodulatorInstance *activeVisualDemodulator; + std::map lastBandwidthNamed; int lastBandwidth; std::string lastDemodType; bool lastDemodLock; @@ -57,4 +65,6 @@ private: float lastSquelch; float lastGain; bool lastMuted; + + std::map lastModemSettings; }; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 1c9718f..471fafe 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -33,10 +33,11 @@ DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThre frequencyChanged.store(false); bandwidthChanged.store(false); audioSampleRateChanged.store(false); + modemSettingsChanged.store(false); } -void DemodulatorPreThread::initialize() { - initialized.store(true); +bool DemodulatorPreThread::isInitialized() { + return initialized.load(); } DemodulatorPreThread::~DemodulatorPreThread() { @@ -50,10 +51,6 @@ void DemodulatorPreThread::run() { pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif - if (!initialized) { - initialize(); - } - std::cout << "Demodulator preprocessor thread started.." << std::endl; ReBuffer buffers; @@ -103,10 +100,17 @@ void DemodulatorPreThread::run() { command.demodType = newDemodType; command.bandwidth = newBandwidth; command.audioSampleRate = newAudioSampleRate; - workerQueue->push(command); demodType = newDemodType; sampleRateChanged.store(false); audioSampleRateChanged.store(false); + if (modemSettingsBuffered.size()) { + command.settings = modemSettingsBuffered; + } + modemSettingsBuffered.clear(); + modemSettingsChanged.store(false); + workerQueue->push(command); + cModem = nullptr; + cModemKit = nullptr; demodTypeChanged.store(false); } else if ( @@ -122,14 +126,10 @@ void DemodulatorPreThread::run() { bandwidthChanged.store(false); sampleRateChanged.store(false); audioSampleRateChanged.store(false); + modemSettingsBuffered.clear(); workerQueue->push(command); } - if (!initialized) { - inp->decRefCount(); - continue; - } - // Requested frequency is not center, shift it into the center! if ((currentFrequency - inp->frequency) != shiftFrequency) { shiftFrequency = currentFrequency - inp->frequency; @@ -239,12 +239,19 @@ void DemodulatorPreThread::run() { } shiftFrequency = inp->frequency-1; + initialized.store(cModem != nullptr); break; default: break; } } } + + if ((cModem != nullptr) && modemSettingsChanged.load()) { + cModem->writeSettings(modemSettingsBuffered); + modemSettingsBuffered.clear(); + modemSettingsChanged.store(false); + } } buffers.purge(); @@ -296,11 +303,7 @@ void DemodulatorPreThread::setBandwidth(int bandwidth) { newBandwidth = bandwidth; } -int DemodulatorPreThread::getBandwidth() { -// if (bandwidthChanged.load()) { -// return newBandwidth; -// } - +int DemodulatorPreThread::getBandwidth() { return currentBandwidth; } @@ -337,3 +340,31 @@ Modem *DemodulatorPreThread::getModem() { ModemKit *DemodulatorPreThread::getModemKit() { return cModemKit; } + + +std::string DemodulatorPreThread::readModemSetting(std::string setting) { + if (cModem) { + return cModem->readSetting(setting); + } else if (modemSettingsBuffered.find(setting) != modemSettingsBuffered.end()) { + return modemSettingsBuffered[setting]; + } + return ""; +} + +void DemodulatorPreThread::writeModemSetting(std::string setting, std::string value) { + modemSettingsBuffered[setting] = value; + modemSettingsChanged.store(true); +} + +ModemSettings DemodulatorPreThread::readModemSettings() { + if (cModem) { + return cModem->readSettings(); + } else { + return modemSettingsBuffered; + } +} + +void DemodulatorPreThread::writeModemSettings(ModemSettings settings) { + modemSettingsBuffered = settings; + modemSettingsChanged.store(true); +} diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index c90105c..e8c8879 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -32,12 +32,18 @@ public: void setAudioSampleRate(int rate); int getAudioSampleRate(); - void initialize(); + bool isInitialized(); + void terminate(); Modem *getModem(); ModemKit *getModemKit(); + std::string readModemSetting(std::string setting); + void writeModemSetting(std::string setting, std::string value); + ModemSettings readModemSettings(); + void writeModemSettings(ModemSettings settings); + protected: DemodulatorInstance *parent; msresamp_crcf iqResampler; @@ -53,6 +59,9 @@ protected: int currentAudioSampleRate, newAudioSampleRate; std::atomic_bool sampleRateChanged, frequencyChanged, bandwidthChanged, audioSampleRateChanged; + + ModemSettings modemSettingsBuffered; + std::atomic_bool modemSettingsChanged; nco_crcf freqShifter; int shiftFrequency; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index 03aac69..b6f9457 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -52,6 +52,9 @@ void DemodulatorWorkerThread::run() { if (makeDemod) { cModem = Modem::makeModem(demodCommand.demodType); cModemType = demodCommand.demodType; + if (demodCommand.settings.size()) { + cModem->writeSettings(demodCommand.settings); + } result.sampleRate = demodCommand.sampleRate; wxGetApp().getAppFrame()->updateModemProperties(cModem->getSettings()); } diff --git a/src/demod/DemodulatorWorkerThread.h b/src/demod/DemodulatorWorkerThread.h index 5455a5f..472543b 100644 --- a/src/demod/DemodulatorWorkerThread.h +++ b/src/demod/DemodulatorWorkerThread.h @@ -62,6 +62,7 @@ public: unsigned int bandwidth; unsigned int audioSampleRate; std::string demodType; + ModemSettings settings; }; typedef ThreadQueue DemodulatorThreadWorkerCommandQueue; diff --git a/src/modules/modem/Modem.cpp b/src/modules/modem/Modem.cpp index c2cd74b..cd8bf58 100644 --- a/src/modules/modem/Modem.cpp +++ b/src/modules/modem/Modem.cpp @@ -28,6 +28,14 @@ ModemArgInfo::ModemArgInfo(void) { } +Modem::Modem() { + +} + +Modem::~Modem() { + +} + void Modem::addModemFactory(Modem *factorySingle) { modemFactories[factorySingle->getName()] = factorySingle; } @@ -58,12 +66,19 @@ std::string Modem::readSetting(std::string setting) { return ""; } -Modem::Modem() { - +void Modem::writeSettings(ModemSettings settings) { + for (ModemSettings::const_iterator i = settings.begin(); i != settings.end(); i++) { + writeSetting(i->first, i->second); + } } -Modem::~Modem() { - +ModemSettings Modem::readSettings() { + ModemArgInfoList args = getSettings(); + ModemSettings rs; + for (ModemArgInfoList::const_iterator i = args.begin(); i != args.end(); i++) { + rs[i->key] = readSetting(i->key); + } + return rs; } bool Modem::shouldRebuildKit() { diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h index 1ca1ece..c952e39 100644 --- a/src/modules/modem/Modem.h +++ b/src/modules/modem/Modem.h @@ -105,6 +105,8 @@ typedef std::vector ModemArgInfoList; class Modem; typedef std::map ModemFactoryList; +typedef std::map ModemSettings; + class Modem { public: static void addModemFactory(Modem *factorySingle); @@ -122,7 +124,9 @@ public: virtual ModemArgInfoList getSettings(); virtual void writeSetting(std::string setting, std::string value); + virtual void writeSettings(ModemSettings settings); virtual std::string readSetting(std::string setting); + virtual ModemSettings readSettings(); virtual int checkSampleRate(long long sampleRate, int audioSampleRate) = 0; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 319dc5a..4b3dec3 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -597,6 +597,7 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) { InteractiveCanvas::OnMouseDown(event); dragState = nextDragState; + wxGetApp().getDemodMgr().updateLastState(); if (dragState && dragState != WF_DRAG_RANGE) { DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator(); @@ -617,6 +618,7 @@ void WaterfallCanvas::OnMouseWheelMoved(wxMouseEvent& event) { void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { InteractiveCanvas::OnMouseReleased(event); + wxGetApp().getDemodMgr().updateLastState(); bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); @@ -653,6 +655,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { if (dragState == WF_DRAG_NONE) { if (!isNew && wxGetApp().getDemodMgr().getDemodulators().size()) { + mgr->updateLastState(); demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); } else { isNew = true; @@ -660,12 +663,16 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { demod->setFrequency(freq); demod->setDemodulatorType(mgr->getLastDemodulatorType()); - demod->setBandwidth(mgr->getLastBandwidth()); + if (int lastDemodBw = mgr->getLastBandwidth(mgr->getLastDemodulatorType())) { + demod->setBandwidth(lastDemodBw); + } else { + demod->setBandwidth(mgr->getLastBandwidth()); + } demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); demod->setGain(mgr->getLastGain()); demod->setMuted(mgr->isLastMuted()); - + demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType())); demod->run(); wxGetApp().bindDemodulator(demod); @@ -678,7 +685,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { demod->updateLabel(freq); demod->setFrequency(freq); - + if (isNew) { setStatusText("New demodulator at frequency: %s", freq); } else { @@ -686,13 +693,14 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { } wxGetApp().getDemodMgr().setActiveDemodulator(demod, false); - SetCursor(wxCURSOR_SIZING); + SetCursor(wxCURSOR_SIZING); nextDragState = WF_DRAG_FREQUENCY; mouseTracker.setVertDragLock(true); mouseTracker.setHorizDragLock(false); } else { if (activeDemod) { wxGetApp().getDemodMgr().setActiveDemodulator(activeDemod, false); + mgr->updateLastState(); activeDemod->setTracking(true); nextDragState = WF_DRAG_FREQUENCY; } else { @@ -742,15 +750,22 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { if (!isNew && wxGetApp().getDemodMgr().getDemodulators().size()) { + mgr->updateLastState(); demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); } else { demod = wxGetApp().getDemodMgr().newThread(); demod->setFrequency(freq); demod->setDemodulatorType(mgr->getLastDemodulatorType()); - demod->setBandwidth(bw); + if (int lastDemodBw = mgr->getLastBandwidth(mgr->getLastDemodulatorType())) { + demod->setBandwidth(lastDemodBw); + } else { + demod->setBandwidth(mgr->getLastBandwidth()); + } demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); demod->setGain(mgr->getLastGain()); + demod->setMuted(mgr->isLastMuted()); + demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType())); demod->run(); @@ -767,7 +782,8 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { demod->updateLabel(freq); demod->setFrequency(freq); demod->setBandwidth(bw); - wxGetApp().getDemodMgr().setActiveDemodulator(demod, false); + mgr->setActiveDemodulator(demod, false); + mgr->updateLastState(); } dragState = WF_DRAG_NONE; From e68ab1e82f18e8453128f287fd9e54a93fccefba Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 26 Nov 2015 22:06:29 -0500 Subject: [PATCH 15/24] Remember settings when toggling modem types - Some additional race condition fixes for showing/hiding the modem property grid --- src/AppFrame.cpp | 2 ++ src/demod/DemodulatorInstance.cpp | 15 ++++++++++++++- src/demod/DemodulatorInstance.h | 4 +++- src/demod/DemodulatorPreThread.cpp | 10 +++++++++- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 5efdd4a..808a6b9 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -950,6 +950,8 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demodGainMeter->setLevel(demodGainMeter->getInputValue()); } activeDemodulator = demod; + } else if (demod) { + // Wait state for current demodulator modem to activate.. } else { DemodulatorMgr *mgr = &wxGetApp().getDemodMgr(); diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index d09b587..d10f8cb 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -240,6 +240,10 @@ int DemodulatorInstance::getOutputDevice() { void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) { setGain(getGain()); if (demodulatorPreThread) { + std::string currentDemodType = demodulatorPreThread->getDemodType(); + if ((currentDemodType != "") && (currentDemodType != demod_type_in)) { + lastModemSettings[currentDemodType] = demodulatorPreThread->readModemSettings(); + } demodulatorPreThread->setDemodType(demod_type_in); } } @@ -366,4 +370,13 @@ void DemodulatorInstance::writeModemSettings(ModemSettings settings) { bool DemodulatorInstance::isModemInitialized() { return demodulatorPreThread->isInitialized(); -} \ No newline at end of file +} + +ModemSettings DemodulatorInstance::getLastModemSettings(std::string demodType) { + if (lastModemSettings.find(demodType) != lastModemSettings.end()) { + return lastModemSettings[demodType]; + } else { + ModemSettings mods; + return mods; + } +} diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index 6f01ee7..84a91e0 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -89,7 +89,8 @@ public: void writeModemSettings(ModemSettings settings); bool isModemInitialized(); - + ModemSettings getLastModemSettings(std::string demodType); + protected: DemodulatorThreadInputQueue* pipeIQInputData; DemodulatorThreadPostInputQueue* pipeIQDemodData; @@ -113,4 +114,5 @@ private: std::atomic_int currentOutputDevice; std::atomic currentAudioGain; std::atomic_bool follow, tracking; + std::map lastModemSettings; }; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 471fafe..277b6c9 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -103,7 +103,15 @@ void DemodulatorPreThread::run() { demodType = newDemodType; sampleRateChanged.store(false); audioSampleRateChanged.store(false); - if (modemSettingsBuffered.size()) { + ModemSettings lastSettings = parent->getLastModemSettings(newDemodType); + if (lastSettings.size() != 0) { + command.settings = lastSettings; + if (modemSettingsBuffered.size()) { + for (ModemSettings::const_iterator msi = modemSettingsBuffered.begin(); msi != modemSettingsBuffered.end(); msi++) { + command.settings[msi->first] = msi->second; + } + } + } else { command.settings = modemSettingsBuffered; } modemSettingsBuffered.clear(); From eb7986e25f90234ed41419f874409946856ce0f2 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 27 Nov 2015 00:05:21 -0500 Subject: [PATCH 16/24] Save/load modem settings, race fixes, legacy session support --- src/AppFrame.cpp | 90 ++++++++++++++++++++++++------- src/demod/DemodulatorInstance.cpp | 3 ++ 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 808a6b9..bc79dcd 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -1066,7 +1066,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); - if (modemPropertiesUpdated.load()) { + if (modemPropertiesUpdated.load() && demod && demod->isModemInitialized()) { modemProps->initProperties(demod->getModemArgs()); modemPropertiesUpdated.store(false); demodTray->Layout(); @@ -1136,6 +1136,14 @@ void AppFrame::saveSession(std::string fileName) { *demod->newChild("output_device") = outputDevices[(*instance_i)->getOutputDevice()].name; *demod->newChild("gain") = (*instance_i)->getGain(); *demod->newChild("muted") = (*instance_i)->isMuted() ? 1 : 0; + + ModemSettings saveSettings = (*instance_i)->readModemSettings(); + if (saveSettings.size()) { + DataNode *settingsNode = demod->newChild("settings"); + for (ModemSettings::const_iterator msi = saveSettings.begin(); msi != saveSettings.end(); msi++) { + *settingsNode->newChild(msi->first.c_str()) = msi->second; + } + } } s.SaveToFileXML(fileName); @@ -1179,35 +1187,77 @@ bool AppFrame::loadSession(std::string fileName) { long bandwidth = *demod->getNext("bandwidth"); long long freq = *demod->getNext("frequency"); - std::string type = demod->hasAnother("type") ? string(*demod->getNext("type")) : "FM"; float squelch_level = demod->hasAnother("squelch_level") ? (float) *demod->getNext("squelch_level") : 0; int squelch_enabled = demod->hasAnother("squelch_enabled") ? (int) *demod->getNext("squelch_enabled") : 0; int muted = demod->hasAnother("muted") ? (int) *demod->getNext("muted") : 0; std::string output_device = demod->hasAnother("output_device") ? string(*(demod->getNext("output_device"))) : ""; float gain = demod->hasAnother("gain") ? (float) *demod->getNext("gain") : 1.0; - // TODO: Check if "type" is numeric and perform update to new values - //#define DEMOD_TYPE_NULL 0 - //#define DEMOD_TYPE_FM 1 - //#define DEMOD_TYPE_AM 2 - //#define DEMOD_TYPE_LSB 3 - //#define DEMOD_TYPE_USB 4 - //#define DEMOD_TYPE_DSB 5 - //#define DEMOD_TYPE_ASK 6 - //#define DEMOD_TYPE_APSK 7 - //#define DEMOD_TYPE_BPSK 8 - //#define DEMOD_TYPE_DPSK 9 - //#define DEMOD_TYPE_PSK 10 - //#define DEMOD_TYPE_OOK 11 - //#define DEMOD_TYPE_ST 12 - //#define DEMOD_TYPE_SQAM 13 - //#define DEMOD_TYPE_QAM 14 - //#define DEMOD_TYPE_QPSK 15 - //#define DEMOD_TYPE_RAW 16 + std::string type = demod->hasAnother("type") ? string(*demod->getNext("type")) : "FM"; + std::istringstream typeCheck(type); + + int legacyType = 0; + if (!(typeCheck >> legacyType).fail()) { + int legacyStereo = demod->hasAnother("stereo") ? (int) *demod->getNext("stereo") : 0; + switch (legacyType) { // legacy demod ID + case 1: type = legacyStereo?"FMS":"FM"; break; + case 2: type = "AM"; break; + case 3: type = "LSB"; break; + case 4: type = "USB"; break; + case 5: type = "DSB"; break; + case 6: type = "ASK"; break; + case 7: type = "APSK"; break; + case 8: type = "BPSK"; break; + case 9: type = "DPSK"; break; + case 10: type = "PSK"; break; + case 11: type = "OOK"; break; + case 12: type = "ST"; break; + case 13: type = "SQAM"; break; + case 14: type = "QAM"; break; + case 15: type = "QPSK"; break; + case 16: type = "I/Q"; break; + default: type = "FM"; break; + } + } + + ModemSettings mSettings; + + if (demod->hasAnother("settings")) { + DataNode *modemSettings = demod->getNext("settings"); + for (int msi = 0, numSettings = modemSettings->numChildren(); msi < numSettings; msi++) { + DataNode *settingNode = modemSettings->child(msi); + std::string keyName = settingNode->getName(); + std::string strSettingValue = ""; + + int dataType = settingNode->element()->getDataType(); + + try { + if (dataType == DATA_STRING) { + settingNode->element()->get(strSettingValue); + } else if (dataType == DATA_INT || dataType == DATA_LONG || dataType == DATA_LONGLONG) { + long long intSettingValue = *settingNode; + strSettingValue = std::to_string(intSettingValue); + } else if (dataType == DATA_FLOAT || dataType == DATA_DOUBLE) { + double floatSettingValue = *settingNode; + strSettingValue = std::to_string(floatSettingValue); + } else { + std::cout << "Unhandled setting data type: " << dataType << std::endl; + } + } catch (DataTypeMismatchException e) { + std::cout << "Setting data type mismatch: " << dataType << std::endl; + } + + if (keyName != "" && strSettingValue != "") { + mSettings[keyName] = strSettingValue; + } + } + } + DemodulatorInstance *newDemod = wxGetApp().getDemodMgr().newThread(); loadedDemod = newDemod; numDemodulators++; + newDemod->writeModemSettings(mSettings); newDemod->setDemodulatorType(type); newDemod->setBandwidth(bandwidth); newDemod->setFrequency(freq); diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index d10f8cb..a326ea3 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -369,6 +369,9 @@ void DemodulatorInstance::writeModemSettings(ModemSettings settings) { } bool DemodulatorInstance::isModemInitialized() { + if (!demodulatorPreThread || isTerminated()) { + return false; + } return demodulatorPreThread->isInitialized(); } From cdddd5850f9e762d7248c227b1d28ab7e613ebf6 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 27 Nov 2015 00:16:13 -0500 Subject: [PATCH 17/24] Legacy session load tweak, modem type selection refresh fix --- src/AppFrame.cpp | 12 +++++++----- src/visual/ModeSelectorCanvas.cpp | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index bc79dcd..b1a8711 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -1193,11 +1193,12 @@ bool AppFrame::loadSession(std::string fileName) { std::string output_device = demod->hasAnother("output_device") ? string(*(demod->getNext("output_device"))) : ""; float gain = demod->hasAnother("gain") ? (float) *demod->getNext("gain") : 1.0; - std::string type = demod->hasAnother("type") ? string(*demod->getNext("type")) : "FM"; - std::istringstream typeCheck(type); + std::string type = "FM"; + + DataNode *demodTypeNode = demod->hasAnother("type")?demod->getNext("type"):nullptr; - int legacyType = 0; - if (!(typeCheck >> legacyType).fail()) { + if (demodTypeNode->element()->getDataType() == DATA_INT) { + int legacyType = *demodTypeNode; int legacyStereo = demod->hasAnother("stereo") ? (int) *demod->getNext("stereo") : 0; switch (legacyType) { // legacy demod ID case 1: type = legacyStereo?"FMS":"FM"; break; @@ -1218,9 +1219,10 @@ bool AppFrame::loadSession(std::string fileName) { case 16: type = "I/Q"; break; default: type = "FM"; break; } + } else if (demodTypeNode->element()->getDataType() == DATA_STRING) { + demodTypeNode->element()->get(type); } - ModemSettings mSettings; if (demod->hasAnother("settings")) { diff --git a/src/visual/ModeSelectorCanvas.cpp b/src/visual/ModeSelectorCanvas.cpp index d89be48..7f57c56 100644 --- a/src/visual/ModeSelectorCanvas.cpp +++ b/src/visual/ModeSelectorCanvas.cpp @@ -159,6 +159,7 @@ void ModeSelectorCanvas::setSelection(std::string label) { for (int i = 0; i < numChoices; i++) { if (selections[i].label == label) { currentSelection = i; + Refresh(); return; } } From 7e4d173996e123f0f96805deacff5bad4e29a1c9 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 28 Nov 2015 23:03:07 -0500 Subject: [PATCH 18/24] Basic console window for digital output - Probably end up making this a single tabbed dialog but this works for the moment --- CMakeLists.txt | 10 +- src/AppFrame.cpp | 27 +- src/CubicSDR.cpp | 52 +- src/ModemProperties.cpp | 4 +- src/demod/DemodulatorInstance.cpp | 76 ++- src/demod/DemodulatorInstance.h | 19 +- src/demod/DemodulatorPreThread.cpp | 7 + src/forms/DigitalConsole/DigitalConsole.cpp | 138 +++++ src/forms/DigitalConsole/DigitalConsole.fbp | 474 ++++++++++++++++++ src/forms/DigitalConsole/DigitalConsole.h | 61 +++ .../DigitalConsole/DigitalConsoleFrame.cpp | 67 +++ .../DigitalConsole/DigitalConsoleFrame.h | 57 +++ src/modules/modem/ModemDigital.cpp | 29 +- src/modules/modem/ModemDigital.h | 31 +- src/modules/modem/analog/ModemAM.cpp | 2 +- src/modules/modem/analog/ModemDSB.cpp | 2 +- src/modules/modem/analog/ModemFM.cpp | 2 +- src/modules/modem/analog/ModemLSB.cpp | 2 +- src/modules/modem/analog/ModemUSB.cpp | 2 +- src/modules/modem/digital/ModemAPSK.cpp | 2 +- src/modules/modem/digital/ModemASK.cpp | 2 +- src/modules/modem/digital/ModemBPSK.cpp | 2 +- src/modules/modem/digital/ModemDPSK.cpp | 2 +- src/modules/modem/digital/ModemFSK.cpp | 14 +- src/modules/modem/digital/ModemFSK.h | 1 + src/modules/modem/digital/ModemOOK.cpp | 2 +- src/modules/modem/digital/ModemPSK.cpp | 2 +- src/modules/modem/digital/ModemQAM.cpp | 2 +- src/modules/modem/digital/ModemQPSK.cpp | 2 +- src/modules/modem/digital/ModemSQAM.cpp | 2 +- src/modules/modem/digital/ModemST.cpp | 2 +- 31 files changed, 1030 insertions(+), 67 deletions(-) create mode 100644 src/forms/DigitalConsole/DigitalConsole.cpp create mode 100644 src/forms/DigitalConsole/DigitalConsole.fbp create mode 100644 src/forms/DigitalConsole/DigitalConsole.h create mode 100644 src/forms/DigitalConsole/DigitalConsoleFrame.cpp create mode 100644 src/forms/DigitalConsole/DigitalConsoleFrame.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e4bf852..1f07098 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -290,6 +290,8 @@ SET (cubicsdr_sources IF(ENABLE_DIGITAL_LAB) SET (cubicsdr_sources ${cubicsdr_sources} + src/forms/DigitalConsole/DigitalConsole.cpp + src/forms/DigitalConsole/DigitalConsoleFrame.cpp src/modules/modem/digital/ModemASK.cpp src/modules/modem/digital/ModemAPSK.cpp src/modules/modem/digital/ModemBPSK.cpp @@ -393,6 +395,8 @@ SET (cubicsdr_headers IF(ENABLE_DIGITAL_LAB) SET (cubicsdr_headers ${cubicsdr_headers} + src/forms/DigitalConsole/DigitalConsole.h + src/forms/DigitalConsole/DigitalConsoleFrame.h src/modules/modem/digital/ModemASK.h src/modules/modem/digital/ModemAPSK.h src/modules/modem/digital/ModemBPSK.h @@ -429,9 +433,10 @@ SOURCE_GROUP("Forms\\SDRDevices" REGULAR_EXPRESSION "src/forms/SDRDevices/${REG_ SOURCE_GROUP("SDR" REGULAR_EXPRESSION "src/sdr/${REG_EXT}") SOURCE_GROUP("Demodulator" REGULAR_EXPRESSION "src/demod/${REG_EXT}") SOURCE_GROUP("Modem" REGULAR_EXPRESSION "src/modules/modem/${REG_EXT}") -SOURCE_GROUP("Modem-Analog" REGULAR_EXPRESSION "src/modules/modem/analog/${REG_EXT}") +SOURCE_GROUP("Modem\\Analog" REGULAR_EXPRESSION "src/modules/modem/analog/${REG_EXT}") IF(ENABLE_DIGITAL_LAB) -SOURCE_GROUP("Modem-Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}") +SOURCE_GROUP("Modem\\Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}") +SOURCE_GROUP("Forms\\DigitalConsole" REGULAR_EXPRESSION "src/forms/DigitalConsole/${REG_EXT}") ENDIF() SOURCE_GROUP("Audio" REGULAR_EXPRESSION "src/audio/${REG_EXT}") SOURCE_GROUP("Utility" REGULAR_EXPRESSION "src/util/${REG_EXT}") @@ -446,6 +451,7 @@ SOURCE_GROUP("_ext-CubicVR2" REGULAR_EXPRESSION "external/cubicvr2/.*${REG_EXT}" include_directories ( ${PROJECT_SOURCE_DIR}/src/forms/SDRDevices + ${PROJECT_SOURCE_DIR}/src/forms/DigitalConsole ${PROJECT_SOURCE_DIR}/src/sdr ${PROJECT_SOURCE_DIR}/src/demod ${PROJECT_SOURCE_DIR}/src/modules diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index b1a8711..7cc5339 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -76,6 +76,8 @@ AppFrame::AppFrame() : demodModeSelector->addChoice(6, "I/Q"); demodModeSelector->setSelection("FM"); demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation, Amplitude Modulation and Lower, Upper or Double Side-Band."); + demodModeSelector->SetMinSize(wxSize(40,-1)); + demodModeSelector->SetMaxSize(wxSize(40,-1)); demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0); #ifdef ENABLE_DIGITAL_LAB @@ -92,11 +94,16 @@ AppFrame::AppFrame() : demodModeSelectorAdv->addChoice(9, "QAM"); demodModeSelectorAdv->addChoice(10, "QPSK"); demodModeSelectorAdv->setHelpTip("Choose advanced modulation types."); + demodModeSelectorAdv->SetMinSize(wxSize(40,-1)); + demodModeSelectorAdv->SetMaxSize(wxSize(40,-1)); demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0); #endif modemPropertiesUpdated.store(false); modemProps = new ModemProperties(demodPanel, wxID_ANY); + modemProps->SetMinSize(wxSize(200,-1)); + modemProps->SetMaxSize(wxSize(200,-1)); + modemProps->Hide(); demodTray->Add(modemProps, 15, wxEXPAND | wxALL, 0); @@ -117,6 +124,8 @@ AppFrame::AppFrame() : wxGetApp().getDemodSpectrumProcessor()->attachOutput(demodWaterfallCanvas->getVisualDataQueue()); demodWaterfallCanvas->getVisualDataQueue()->set_max_num_items(3); + demodVisuals->SetMinSize(wxSize(128,-1)); + demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0); demodTray->AddSpacer(1); @@ -135,6 +144,7 @@ AppFrame::AppFrame() : scopeCanvas = new ScopeCanvas(demodPanel, attribList); scopeCanvas->setHelpTip("Audio Visuals, drag left/right to toggle Scope or Spectrum."); + scopeCanvas->SetMinSize(wxSize(128,-1)); demodScopeTray->Add(scopeCanvas, 8, wxEXPAND | wxALL, 0); wxGetApp().getScopeProcessor()->setup(2048); wxGetApp().getScopeProcessor()->attachOutput(scopeCanvas->getInputQueue()); @@ -1021,7 +1031,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) { wxGetApp().getAudioVisualQueue()->set_max_num_items((scopeCanvas->scopeVisible()?1:0) + (scopeCanvas->spectrumVisible()?1:0)); wxGetApp().getScopeProcessor()->run(); -// wxGetApp().getSpectrumDistributor()->run(); SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcessor(); @@ -1070,12 +1079,18 @@ void AppFrame::OnIdle(wxIdleEvent& event) { modemProps->initProperties(demod->getModemArgs()); modemPropertiesUpdated.store(false); demodTray->Layout(); +#if ENABLE_DIGITAL_LAB + if (demod->getModemType() == "digital") { + ModemDigitalOutputConsole *outp = (ModemDigitalOutputConsole *)demod->getOutput(); + if (!outp->getDialog()) { + outp->setTitle(demod->getDemodulatorType() + ": " + frequencyToStr(demod->getFrequency())); + outp->setDialog(new DigitalConsole(this, outp)); + } + demod->showOutput(); + } +#endif } -// waterfallCanvas->processInputQueue(); -// waterfallCanvas->Refresh(); -// demodWaterfallCanvas->processInputQueue(); -// demodWaterfallCanvas->Refresh(); - + if (!this->IsActive()) { std::this_thread::sleep_for(std::chrono::milliseconds(25)); } diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 5084294..2e917e6 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -20,20 +20,20 @@ IMPLEMENT_APP(CubicSDR) -#ifdef ENABLE_DIGITAL_LAB -// console output buffer for windows -#ifdef _WINDOWS -class outbuf : public std::streambuf { - public: - outbuf() { - setp(0, 0); - } - virtual int_type overflow(int_type c = traits_type::eof()) { - return fputc(c, stdout) == EOF ? traits_type::eof() : c; - } -}; -#endif -#endif +//#ifdef ENABLE_DIGITAL_LAB +//// console output buffer for windows +//#ifdef _WINDOWS +//class outbuf : public std::streambuf { +// public: +// outbuf() { +// setp(0, 0); +// } +// virtual int_type overflow(int_type c = traits_type::eof()) { +// return fputc(c, stdout) == EOF ? traits_type::eof() : c; +// } +//}; +//#endif +//#endif #ifdef MINGW_PATCH FILE _iob[] = { *stdin, *stdout, *stderr }; @@ -149,18 +149,18 @@ bool CubicSDR::OnInit() { return false; } -#ifdef ENABLE_DIGITAL_LAB - // console output for windows - #ifdef _WINDOWS - if (AllocConsole()) { - freopen("CONOUT$", "w", stdout); - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED); - } - outbuf ob; - std::streambuf *sb = std::cout.rdbuf(&ob); - std::cout.rdbuf(sb); - #endif -#endif +//#ifdef ENABLE_DIGITAL_LAB +// // console output for windows +// #ifdef _WINDOWS +// if (AllocConsole()) { +// freopen("CONOUT$", "w", stdout); +// SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED); +// } +// outbuf ob; +// std::streambuf *sb = std::cout.rdbuf(&ob); +// std::cout.rdbuf(sb); +// #endif +//#endif wxApp::SetAppName("CubicSDR"); diff --git a/src/ModemProperties.cpp b/src/ModemProperties.cpp index c679e3d..d8c2546 100644 --- a/src/ModemProperties.cpp +++ b/src/ModemProperties.cpp @@ -5,10 +5,10 @@ ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel(parent, winid, pos, size, style, name) { m_propertyGrid = new wxPropertyGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPG_DEFAULT_STYLE); - + bSizer = new wxBoxSizer( wxVERTICAL ); - bSizer->Add(m_propertyGrid, 1, wxEXPAND | wxALL, 5); + bSizer->Add(m_propertyGrid, 1, wxEXPAND, 5); this->SetSizer(bSizer); diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index a326ea3..5ba905a 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -2,8 +2,11 @@ #include "CubicSDR.h" DemodulatorInstance::DemodulatorInstance() : - t_PreDemod(NULL), t_Demod(NULL), t_Audio(NULL) { + t_PreDemod(nullptr), t_Demod(nullptr), t_Audio(nullptr) { +#if ENABLE_DIGITAL_LAB + activeOutput = nullptr; +#endif terminated.store(true); audioTerminated.store(true); demodTerminated.store(true); @@ -42,6 +45,9 @@ DemodulatorInstance::DemodulatorInstance() : } DemodulatorInstance::~DemodulatorInstance() { +#if ENABLE_DIGITAL_LAB + delete activeOutput; +#endif delete audioThread; delete demodulatorThread; delete demodulatorPreThread; @@ -137,6 +143,11 @@ bool DemodulatorInstance::isTerminated() { #else t_Demod->join(); delete t_Demod; +#endif +#if ENABLE_DIGITAL_LAB + if (activeOutput) { + closeOutput(); + } #endif demodTerminated = true; break; @@ -165,8 +176,18 @@ bool DemodulatorInstance::isActive() { void DemodulatorInstance::setActive(bool state) { if (active && !state) { +#if ENABLE_DIGITAL_LAB + if (activeOutput && !isTerminated()) { + activeOutput->Hide(); + } +#endif audioThread->setActive(state); } else if (!active && state) { +#if ENABLE_DIGITAL_LAB + if (activeOutput) { + activeOutput->Show(); + } +#endif audioThread->setActive(state); } if (!state) { @@ -244,6 +265,11 @@ void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) { if ((currentDemodType != "") && (currentDemodType != demod_type_in)) { lastModemSettings[currentDemodType] = demodulatorPreThread->readModemSettings(); } +#if ENABLE_DIGITAL_LAB + if (activeOutput) { + activeOutput->Hide(); + } +#endif demodulatorPreThread->setDemodType(demod_type_in); } } @@ -284,6 +310,14 @@ void DemodulatorInstance::setFrequency(long long freq) { } demodulatorPreThread->setFrequency(freq); +#if ENABLE_DIGITAL_LAB + if (activeOutput) { + if (isModemInitialized() && getModemType() == "digital") { + ModemDigitalOutputConsole *outp = (ModemDigitalOutputConsole *)getOutput(); + outp->setTitle(getDemodulatorType() + ": " + frequencyToStr(getFrequency())); + } + } +#endif } long long DemodulatorInstance::getFrequency() { @@ -375,6 +409,13 @@ bool DemodulatorInstance::isModemInitialized() { return demodulatorPreThread->isInitialized(); } +std::string DemodulatorInstance::getModemType() { + if (isModemInitialized()) { + return demodulatorPreThread->getModem()->getType(); + } + return ""; +} + ModemSettings DemodulatorInstance::getLastModemSettings(std::string demodType) { if (lastModemSettings.find(demodType) != lastModemSettings.end()) { return lastModemSettings[demodType]; @@ -383,3 +424,36 @@ ModemSettings DemodulatorInstance::getLastModemSettings(std::string demodType) { return mods; } } + +#if ENABLE_DIGITAL_LAB +ModemDigitalOutput *DemodulatorInstance::getOutput() { + if (activeOutput == nullptr) { + activeOutput = new ModemDigitalOutputConsole(); + } + return activeOutput; +} + +void DemodulatorInstance::showOutput() { + if (activeOutput != nullptr) { + activeOutput->Show(); + } +} + +void DemodulatorInstance::hideOutput() { + if (activeOutput != nullptr) { + activeOutput->Hide(); + } +} + +void DemodulatorInstance::closeOutput() { + if (isModemInitialized()) { + if (getModemType() == "digital") { + ModemDigital *dModem = (ModemDigital *)demodulatorPreThread->getModem(); + dModem->setOutput(nullptr); + } + } + if (activeOutput) { + activeOutput->Close(); + } +} +#endif \ No newline at end of file diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index 84a91e0..d3d3671 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -10,6 +10,10 @@ #include "ModemDigital.h" #include "ModemAnalog.h" +#if ENABLE_DIGITAL_LAB +#include "DigitalConsole.h" +#endif + class DemodulatorInstance { public: @@ -89,8 +93,16 @@ public: void writeModemSettings(ModemSettings settings); bool isModemInitialized(); + std::string getModemType(); ModemSettings getLastModemSettings(std::string demodType); - + +#if ENABLE_DIGITAL_LAB + ModemDigitalOutput *getOutput(); + void showOutput(); + void hideOutput(); + void closeOutput(); +#endif + protected: DemodulatorThreadInputQueue* pipeIQInputData; DemodulatorThreadPostInputQueue* pipeIQDemodData; @@ -115,4 +127,7 @@ private: std::atomic currentAudioGain; std::atomic_bool follow, tracking; std::map lastModemSettings; - }; +#if ENABLE_DIGITAL_LAB + ModemDigitalOutput *activeOutput; +#endif +}; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 277b6c9..98716fd 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -120,6 +120,7 @@ void DemodulatorPreThread::run() { cModem = nullptr; cModemKit = nullptr; demodTypeChanged.store(false); + initialized.store(false); } else if ( cModemKit && cModem && @@ -226,6 +227,12 @@ void DemodulatorPreThread::run() { if (result.modem != nullptr) { cModem = result.modem; +#if ENABLE_DIGITAL_LAB + if (cModem->getType() == "digital") { + ModemDigital *mDigi = (ModemDigital *)cModem; + mDigi->setOutput(parent->getOutput()); + } +#endif } if (result.modemKit != nullptr) { diff --git a/src/forms/DigitalConsole/DigitalConsole.cpp b/src/forms/DigitalConsole/DigitalConsole.cpp new file mode 100644 index 0000000..f472ca1 --- /dev/null +++ b/src/forms/DigitalConsole/DigitalConsole.cpp @@ -0,0 +1,138 @@ +#include "DigitalConsole.h" +#include "CubicSDR.h" +#include + +DigitalConsole::DigitalConsole( wxWindow* parent, ModemDigitalOutputConsole *doParent ): DigitalConsoleFrame( parent ), doParent(doParent) { + streamWritten.store(false); + streamPaused.store(false); +} + +DigitalConsole::~DigitalConsole() { + doParent->setDialog(nullptr); +} + +void DigitalConsole::OnClose( wxCloseEvent& event ) { + doParent->setDialog(nullptr); +} + +void DigitalConsole::OnCopy( wxCommandEvent& event ) { + m_dataView->SelectAll(); + m_dataView->Copy(); +} + +void DigitalConsole::OnPause( wxCommandEvent& event ) { + if (streamPaused.load()) { + m_pauseButton->SetLabel("Stop"); + streamPaused.store(false); + } else { + m_pauseButton->SetLabel("Run"); + streamPaused.store(true); + } +} + +void DoRefresh( wxTimerEvent& event ) { + event.Skip(); +} + +void DigitalConsole::DoRefresh( wxTimerEvent& event ) { + if (streamWritten.load()) { + stream_busy.lock(); + m_dataView->AppendText(streamBuf.str()); + streamBuf.str(""); + streamWritten.store(false); + stream_busy.unlock(); + } +} + +void DigitalConsole::OnClear( wxCommandEvent& event ) { + m_dataView->Clear(); +} + +void DigitalConsole::write(std::string outp) { + if (streamPaused.load()) { + return; + } + stream_busy.lock(); + streamBuf << outp; + streamWritten.store(true); + stream_busy.unlock(); +} + +void DigitalConsole::write(char outc) { + if (streamPaused.load()) { + return; + } + stream_busy.lock(); + streamBuf << outc; + streamWritten.store(true); + stream_busy.unlock(); +} + + +ModemDigitalOutputConsole::ModemDigitalOutputConsole(): ModemDigitalOutput(), dialog(nullptr) { + streamWritten.store(false); +} + +ModemDigitalOutputConsole::~ModemDigitalOutputConsole() { + +} + +void ModemDigitalOutputConsole::setDialog(DigitalConsole *dialog_in) { + dialog = dialog_in; + if (dialog && dialogTitle != "") { + dialog->SetTitle(dialogTitle); + } +} + +DigitalConsole *ModemDigitalOutputConsole::getDialog() { + return dialog; +} + +void ModemDigitalOutputConsole::Show() { + if (!dialog) { + return; + } + if (!dialog->IsShown()) { + dialog->Show(); + } +} + + +void ModemDigitalOutputConsole::Hide() { + if (!dialog) { + return; + } + if (dialog->IsShown()) { + dialog->Hide(); + } +} + +void ModemDigitalOutputConsole::Close() { + if (!dialog) { + return; + } + dialog->Hide(); + dialog->Close(); + dialog = nullptr; +} + +void ModemDigitalOutputConsole::setTitle(std::string title) { + if (dialog) { + dialog->SetTitle(title); + } + dialogTitle = title; +} + +void ModemDigitalOutputConsole::write(std::string outp) { + if (!dialog) { + return; + } + dialog->write(outp); +} + +void ModemDigitalOutputConsole::write(char outc) { + if (!dialog) { + return; + } + dialog->write(outc); +} diff --git a/src/forms/DigitalConsole/DigitalConsole.fbp b/src/forms/DigitalConsole/DigitalConsole.fbp new file mode 100644 index 0000000..cd41a92 --- /dev/null +++ b/src/forms/DigitalConsole/DigitalConsole.fbp @@ -0,0 +1,474 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + DigitalConsoleFrame + 1000 + none + 0 + DigitalConsole + + . + + 1 + 1 + 1 + 1 + UI + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DigitalConsoleFrame + + 441,394 + wxCAPTION|wxFRAME_FLOAT_ON_PARENT|wxMAXIMIZE|wxMAXIMIZE_BOX|wxMINIMIZE|wxMINIMIZE_BOX|wxRESIZE_BORDER + ; + Digital Output + + wxWS_EX_PROCESS_UI_UPDATES + + wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL + 1 + + + + + + + + + + OnClose + + + + + + + + + + + + + + + + + + + + + + + + + + + + bSizer + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,90,-1,76,0 + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_dataView + 1 + + + protected + 1 + + Resizable + 1 + + wxTE_CHARWRAP|wxTE_MULTILINE|wxTE_NOHIDESEL|wxTE_READONLY|wxTE_WORDWRAP + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + wxWS_EX_PROCESS_UI_UPDATES + + wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE|wxNO_BORDER|wxSIMPLE_BORDER|wxVSCROLL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + + bSizer2 + wxHORIZONTAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Clear + + 0 + + + 0 + + 1 + m_clearButton + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnClear + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Copy + + 0 + + + 0 + + 1 + m_copyButton + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnCopy + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Stop + + 0 + + + 0 + + 1 + m_pauseButton + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnPause + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + wxID_ANY + m_refreshTimer + 0 + 250 + protected + DoRefresh + + + + diff --git a/src/forms/DigitalConsole/DigitalConsole.h b/src/forms/DigitalConsole/DigitalConsole.h new file mode 100644 index 0000000..5d5321d --- /dev/null +++ b/src/forms/DigitalConsole/DigitalConsole.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "DigitalConsoleFrame.h" +#include "ModemDigital.h" + +class ModemDigitalOutputConsole; +class DigitalConsole: public DigitalConsoleFrame { +public: + DigitalConsole( wxWindow* parent, ModemDigitalOutputConsole *doParent ); + ~DigitalConsole(); + + + void write(std::string outp); + void write(char outc); + +private: + void DoRefresh( wxTimerEvent& event ); + void OnClose( wxCloseEvent& event ); + void OnClear( wxCommandEvent& event ); + + void OnCopy( wxCommandEvent& event ); + void OnPause( wxCommandEvent& event ); + + std::stringstream streamBuf; + std::mutex stream_busy; + std::atomic streamWritten; + std::atomic streamPaused; + ModemDigitalOutputConsole *doParent; +}; + +class ModemDigitalOutputConsole: public ModemDigitalOutput { +public: + ModemDigitalOutputConsole(); + ~ModemDigitalOutputConsole(); + + void setDialog(DigitalConsole *dialog_in); + DigitalConsole *getDialog(); + + void setTitle(std::string title); + + void write(std::string outp); + void write(char outc); + + void Show(); + void Hide(); + void Close(); + +private: + DigitalConsole *dialog; + std::stringstream streamBuf; + std::mutex stream_busy; + std::atomic streamWritten; + std::string dialogTitle; +}; + diff --git a/src/forms/DigitalConsole/DigitalConsoleFrame.cpp b/src/forms/DigitalConsole/DigitalConsoleFrame.cpp new file mode 100644 index 0000000..565a054 --- /dev/null +++ b/src/forms/DigitalConsole/DigitalConsoleFrame.cpp @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Aug 23 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "DigitalConsoleFrame.h" + +/////////////////////////////////////////////////////////////////////////// + +DigitalConsoleFrame::DigitalConsoleFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetExtraStyle( wxWS_EX_PROCESS_UI_UPDATES ); + + wxBoxSizer* bSizer; + bSizer = new wxBoxSizer( wxVERTICAL ); + + m_dataView = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_CHARWRAP|wxTE_MULTILINE|wxTE_NOHIDESEL|wxTE_READONLY|wxTE_WORDWRAP|wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE|wxNO_BORDER|wxSIMPLE_BORDER|wxVSCROLL ); + m_dataView->SetExtraStyle( wxWS_EX_PROCESS_UI_UPDATES ); + m_dataView->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 76, 90, 90, false, wxEmptyString ) ); + + bSizer->Add( m_dataView, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer( wxHORIZONTAL ); + + m_clearButton = new wxButton( this, wxID_ANY, wxT("Clear"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2->Add( m_clearButton, 0, wxALL, 5 ); + + m_copyButton = new wxButton( this, wxID_ANY, wxT("Copy"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2->Add( m_copyButton, 0, wxALL, 5 ); + + m_pauseButton = new wxButton( this, wxID_ANY, wxT("Stop"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2->Add( m_pauseButton, 0, wxEXPAND, 5 ); + + + bSizer->Add( bSizer2, 0, wxEXPAND, 5 ); + + + this->SetSizer( bSizer ); + this->Layout(); + m_refreshTimer.SetOwner( this, wxID_ANY ); + m_refreshTimer.Start( 250 ); + + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DigitalConsoleFrame::OnClose ) ); + m_clearButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnClear ), NULL, this ); + m_copyButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnCopy ), NULL, this ); + m_pauseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnPause ), NULL, this ); + this->Connect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( DigitalConsoleFrame::DoRefresh ) ); +} + +DigitalConsoleFrame::~DigitalConsoleFrame() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DigitalConsoleFrame::OnClose ) ); + m_clearButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnClear ), NULL, this ); + m_copyButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnCopy ), NULL, this ); + m_pauseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnPause ), NULL, this ); + this->Disconnect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( DigitalConsoleFrame::DoRefresh ) ); + +} diff --git a/src/forms/DigitalConsole/DigitalConsoleFrame.h b/src/forms/DigitalConsole/DigitalConsoleFrame.h new file mode 100644 index 0000000..05fdd9f --- /dev/null +++ b/src/forms/DigitalConsole/DigitalConsoleFrame.h @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Aug 23 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIGITALCONSOLEFRAME_H__ +#define __DIGITALCONSOLEFRAME_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DigitalConsoleFrame +/////////////////////////////////////////////////////////////////////////////// +class DigitalConsoleFrame : public wxFrame +{ + private: + + protected: + wxTextCtrl* m_dataView; + wxButton* m_clearButton; + wxButton* m_copyButton; + wxButton* m_pauseButton; + wxTimer m_refreshTimer; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } + virtual void OnClear( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCopy( wxCommandEvent& event ) { event.Skip(); } + virtual void OnPause( wxCommandEvent& event ) { event.Skip(); } + virtual void DoRefresh( wxTimerEvent& event ) { event.Skip(); } + + + public: + + DigitalConsoleFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Digital Output"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 441,394 ), long style = wxCAPTION|wxFRAME_FLOAT_ON_PARENT|wxMAXIMIZE|wxMAXIMIZE_BOX|wxMINIMIZE|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL ); + + ~DigitalConsoleFrame(); + +}; + +#endif //__DIGITALCONSOLEFRAME_H__ diff --git a/src/modules/modem/ModemDigital.cpp b/src/modules/modem/ModemDigital.cpp index c8c09f6..aa8e123 100644 --- a/src/modules/modem/ModemDigital.cpp +++ b/src/modules/modem/ModemDigital.cpp @@ -1,7 +1,18 @@ #include "ModemDigital.h" -ModemDigital::ModemDigital() { +ModemDigitalOutput::ModemDigitalOutput() { + +} + +ModemDigital::ModemDigital() { +#if ENABLE_DIGITAL_LAB + digitalOut = nullptr; +#endif +} + +ModemDigitalOutput::~ModemDigitalOutput() { + } std::string ModemDigital::getType() { @@ -54,6 +65,18 @@ void ModemDigital::digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *in } void ModemDigital::digitalFinish(ModemKitDigital *kit, modem mod) { - demodOutputDataDigital.empty(); +#if ENABLE_DIGITAL_LAB + if (digitalOut && outStream.str().length()) { + digitalOut->write(outStream.str()); + outStream.str(""); + } else { + outStream.str(""); + } +#endif } - \ No newline at end of file + +#if ENABLE_DIGITAL_LAB +void ModemDigital::setOutput(ModemDigitalOutput *modemDigitalOutput) { + digitalOut = modemDigitalOutput; +} +#endif \ No newline at end of file diff --git a/src/modules/modem/ModemDigital.h b/src/modules/modem/ModemDigital.h index 3c0e1be..e1991c1 100644 --- a/src/modules/modem/ModemDigital.h +++ b/src/modules/modem/ModemDigital.h @@ -1,5 +1,10 @@ #pragma once #include "Modem.h" +#include +#include +#include +#include +#include class ModemKitDigital : public ModemKit { public: @@ -8,6 +13,20 @@ public: }; }; +class ModemDigitalOutput { +public: + ModemDigitalOutput(); + virtual ~ModemDigitalOutput(); + + virtual void write(std::string outp) = 0; + virtual void write(char outc) = 0; + + virtual void Show() = 0; + virtual void Hide() = 0; + virtual void Close() = 0; + +private: +}; class ModemDigital : public Modem { public: @@ -28,11 +47,15 @@ public: virtual void updateDemodulatorLock(modem mod, float sensitivity); +#if ENABLE_DIGITAL_LAB + void setOutput(ModemDigitalOutput *digitalOutput); +#endif + protected: std::vector demodOutputDataDigital; std::atomic_bool currentDemodLock; - -// std::vector demodOutputDataDigitalTest; -// std::vector demodOutputSoftbits; -// std::vector demodOutputSoftbitsTest; +#if ENABLE_DIGITAL_LAB + ModemDigitalOutput *digitalOut; + std::stringstream outStream; +#endif }; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemAM.cpp b/src/modules/modem/analog/ModemAM.cpp index 678832e..114d81b 100644 --- a/src/modules/modem/analog/ModemAM.cpp +++ b/src/modules/modem/analog/ModemAM.cpp @@ -1,6 +1,6 @@ #include "ModemAM.h" -ModemAM::ModemAM() { +ModemAM::ModemAM() : ModemAnalog() { demodAM = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0); } diff --git a/src/modules/modem/analog/ModemDSB.cpp b/src/modules/modem/analog/ModemDSB.cpp index c343425..b40b11f 100644 --- a/src/modules/modem/analog/ModemDSB.cpp +++ b/src/modules/modem/analog/ModemDSB.cpp @@ -1,6 +1,6 @@ #include "ModemDSB.h" -ModemDSB::ModemDSB() { +ModemDSB::ModemDSB() : ModemAnalog() { demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1); } diff --git a/src/modules/modem/analog/ModemFM.cpp b/src/modules/modem/analog/ModemFM.cpp index 259fcfd..1e90ea4 100644 --- a/src/modules/modem/analog/ModemFM.cpp +++ b/src/modules/modem/analog/ModemFM.cpp @@ -1,6 +1,6 @@ #include "ModemFM.h" -ModemFM::ModemFM() { +ModemFM::ModemFM() : ModemAnalog() { demodFM = freqdem_create(0.5); } diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp index d4d6ce8..3838f1d 100644 --- a/src/modules/modem/analog/ModemLSB.cpp +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -1,6 +1,6 @@ #include "ModemLSB.h" -ModemLSB::ModemLSB() { +ModemLSB::ModemLSB() : ModemAnalog() { // half band filter used for side-band elimination ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f); demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1); diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp index 780d44a..17392c5 100644 --- a/src/modules/modem/analog/ModemUSB.cpp +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -1,6 +1,6 @@ #include "ModemUSB.h" -ModemUSB::ModemUSB() { +ModemUSB::ModemUSB() : ModemAnalog() { // half band filter used for side-band elimination ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f); demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1); diff --git a/src/modules/modem/digital/ModemAPSK.cpp b/src/modules/modem/digital/ModemAPSK.cpp index febd4fe..8d4ffc6 100644 --- a/src/modules/modem/digital/ModemAPSK.cpp +++ b/src/modules/modem/digital/ModemAPSK.cpp @@ -1,6 +1,6 @@ #include "ModemAPSK.h" -ModemAPSK::ModemAPSK() { +ModemAPSK::ModemAPSK() : ModemDigital() { demodAPSK4 = modem_create(LIQUID_MODEM_APSK4); demodAPSK8 = modem_create(LIQUID_MODEM_APSK8); demodAPSK16 = modem_create(LIQUID_MODEM_APSK16); diff --git a/src/modules/modem/digital/ModemASK.cpp b/src/modules/modem/digital/ModemASK.cpp index fb9adf4..f952a55 100644 --- a/src/modules/modem/digital/ModemASK.cpp +++ b/src/modules/modem/digital/ModemASK.cpp @@ -1,6 +1,6 @@ #include "ModemASK.h" -ModemASK::ModemASK() { +ModemASK::ModemASK() : ModemDigital() { demodASK2 = modem_create(LIQUID_MODEM_ASK2); demodASK4 = modem_create(LIQUID_MODEM_ASK4); demodASK8 = modem_create(LIQUID_MODEM_ASK8); diff --git a/src/modules/modem/digital/ModemBPSK.cpp b/src/modules/modem/digital/ModemBPSK.cpp index 6e2b3a1..bd82d88 100644 --- a/src/modules/modem/digital/ModemBPSK.cpp +++ b/src/modules/modem/digital/ModemBPSK.cpp @@ -1,6 +1,6 @@ #include "ModemBPSK.h" -ModemBPSK::ModemBPSK() { +ModemBPSK::ModemBPSK() : ModemDigital() { demodBPSK = modem_create(LIQUID_MODEM_BPSK); } diff --git a/src/modules/modem/digital/ModemDPSK.cpp b/src/modules/modem/digital/ModemDPSK.cpp index 9698e8c..13f5083 100644 --- a/src/modules/modem/digital/ModemDPSK.cpp +++ b/src/modules/modem/digital/ModemDPSK.cpp @@ -1,6 +1,6 @@ #include "ModemDPSK.h" -ModemDPSK::ModemDPSK() { +ModemDPSK::ModemDPSK() : ModemDigital() { demodDPSK2 = modem_create(LIQUID_MODEM_DPSK2); demodDPSK4 = modem_create(LIQUID_MODEM_DPSK4); demodDPSK8 = modem_create(LIQUID_MODEM_DPSK8); diff --git a/src/modules/modem/digital/ModemFSK.cpp b/src/modules/modem/digital/ModemFSK.cpp index f5b08fa..43b8180 100644 --- a/src/modules/modem/digital/ModemFSK.cpp +++ b/src/modules/modem/digital/ModemFSK.cpp @@ -1,9 +1,11 @@ #include "ModemFSK.h" +#include -ModemFSK::ModemFSK() { +ModemFSK::ModemFSK() : ModemDigital() { // DMR defaults? bps = 1; sps = 9600; + outStream << std::hex; } Modem *ModemFSK::factory() { @@ -35,6 +37,7 @@ ModemArgInfoList ModemFSK::getSettings() { bpsOpts.push_back("2"); bpsOpts.push_back("4"); bpsOpts.push_back("8"); + bpsOpts.push_back("16"); bpsArg.options = bpsOpts; args.push_back(bpsArg); @@ -48,6 +51,8 @@ ModemArgInfoList ModemFSK::getSettings() { std::vector spsOpts; // some common modem rates ..? + spsOpts.push_back("300"); + spsOpts.push_back("600"); spsOpts.push_back("1200"); spsOpts.push_back("2400"); spsOpts.push_back("4800"); @@ -117,12 +122,9 @@ void ModemFSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a dkit->inputBuffer.insert(dkit->inputBuffer.end(),input->data.begin(),input->data.end()); while (dkit->inputBuffer.size() >= dkit->k) { - unsigned int sym_out; - - sym_out = fskdem_demodulate(dkit->demodFSK, &dkit->inputBuffer[0]); + outStream << fskdem_demodulate(dkit->demodFSK, &dkit->inputBuffer[0]); + // float err = fskdem_get_frequency_error(dkit->demodFSK); -// std::cout << "ferror: " << err << std::endl; - printf("%01X", sym_out); dkit->inputBuffer.erase(dkit->inputBuffer.begin(),dkit->inputBuffer.begin()+dkit->k); } diff --git a/src/modules/modem/digital/ModemFSK.h b/src/modules/modem/digital/ModemFSK.h index 2eab813..8f2e00b 100644 --- a/src/modules/modem/digital/ModemFSK.h +++ b/src/modules/modem/digital/ModemFSK.h @@ -1,5 +1,6 @@ #pragma once #include "ModemDigital.h" +#include class ModemKitFSK : public ModemKitDigital { public: diff --git a/src/modules/modem/digital/ModemOOK.cpp b/src/modules/modem/digital/ModemOOK.cpp index d0e92f9..7b5d54f 100644 --- a/src/modules/modem/digital/ModemOOK.cpp +++ b/src/modules/modem/digital/ModemOOK.cpp @@ -1,6 +1,6 @@ #include "ModemOOK.h" -ModemOOK::ModemOOK() { +ModemOOK::ModemOOK() : ModemDigital() { demodOOK = modem_create(LIQUID_MODEM_OOK); } diff --git a/src/modules/modem/digital/ModemPSK.cpp b/src/modules/modem/digital/ModemPSK.cpp index 1f33ff3..8789435 100644 --- a/src/modules/modem/digital/ModemPSK.cpp +++ b/src/modules/modem/digital/ModemPSK.cpp @@ -1,6 +1,6 @@ #include "ModemPSK.h" -ModemPSK::ModemPSK() { +ModemPSK::ModemPSK() : ModemDigital() { demodPSK2 = modem_create(LIQUID_MODEM_PSK2); demodPSK4 = modem_create(LIQUID_MODEM_PSK4); demodPSK8 = modem_create(LIQUID_MODEM_PSK8); diff --git a/src/modules/modem/digital/ModemQAM.cpp b/src/modules/modem/digital/ModemQAM.cpp index 63659a3..c593357 100644 --- a/src/modules/modem/digital/ModemQAM.cpp +++ b/src/modules/modem/digital/ModemQAM.cpp @@ -1,6 +1,6 @@ #include "ModemQAM.h" -ModemQAM::ModemQAM() { +ModemQAM::ModemQAM() : ModemDigital() { demodQAM4 = modem_create(LIQUID_MODEM_QAM4); demodQAM8 = modem_create(LIQUID_MODEM_QAM8); demodQAM16 = modem_create(LIQUID_MODEM_QAM16); diff --git a/src/modules/modem/digital/ModemQPSK.cpp b/src/modules/modem/digital/ModemQPSK.cpp index 98dfb7f..4754e78 100644 --- a/src/modules/modem/digital/ModemQPSK.cpp +++ b/src/modules/modem/digital/ModemQPSK.cpp @@ -1,6 +1,6 @@ #include "ModemQPSK.h" -ModemQPSK::ModemQPSK() { +ModemQPSK::ModemQPSK() : ModemDigital() { demodQPSK = modem_create(LIQUID_MODEM_QPSK); } diff --git a/src/modules/modem/digital/ModemSQAM.cpp b/src/modules/modem/digital/ModemSQAM.cpp index fbb8f47..f2ef57f 100644 --- a/src/modules/modem/digital/ModemSQAM.cpp +++ b/src/modules/modem/digital/ModemSQAM.cpp @@ -1,6 +1,6 @@ #include "ModemSQAM.h" -ModemSQAM::ModemSQAM() { +ModemSQAM::ModemSQAM() : ModemDigital() { demodSQAM32 = modem_create(LIQUID_MODEM_SQAM32); demodSQAM128 = modem_create(LIQUID_MODEM_SQAM128); demodSQAM = demodSQAM32; diff --git a/src/modules/modem/digital/ModemST.cpp b/src/modules/modem/digital/ModemST.cpp index 7adbe71..b827fc2 100644 --- a/src/modules/modem/digital/ModemST.cpp +++ b/src/modules/modem/digital/ModemST.cpp @@ -1,6 +1,6 @@ #include "ModemST.h" -ModemST::ModemST() { +ModemST::ModemST() : ModemDigital() { demodST = modem_create(LIQUID_MODEM_V29); } From c303b6828431608d5248e24770b8d685b3bb6b52 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 29 Nov 2015 13:35:12 -0500 Subject: [PATCH 19/24] Basic X/Y scope plot while in digital mode --- src/audio/AudioThread.h | 1 + src/demod/DemodDefs.h | 1 + src/demod/DemodulatorPreThread.cpp | 7 +- src/demod/DemodulatorThread.cpp | 24 +- src/demod/DemodulatorWorkerThread.cpp | 4 +- src/demod/DemodulatorWorkerThread.h | 2 + src/forms/DigitalConsole/DigitalConsole.fbp | 209 +++++++++--------- .../DigitalConsole/DigitalConsoleFrame.cpp | 26 ++- .../DigitalConsole/DigitalConsoleFrame.h | 2 +- src/modules/modem/Modem.cpp | 6 +- src/modules/modem/Modem.h | 2 +- src/panel/ScopePanel.cpp | 25 ++- src/panel/ScopePanel.h | 1 + src/process/ScopeVisualProcessor.cpp | 14 +- src/process/ScopeVisualProcessor.h | 2 + src/visual/ScopeCanvas.cpp | 36 +-- src/visual/ScopeCanvas.h | 2 - src/visual/ScopeContext.cpp | 10 +- src/visual/ScopeContext.h | 2 +- 19 files changed, 226 insertions(+), 150 deletions(-) diff --git a/src/audio/AudioThread.h b/src/audio/AudioThread.h index 01ebda5..7af40b3 100644 --- a/src/audio/AudioThread.h +++ b/src/audio/AudioThread.h @@ -18,6 +18,7 @@ public: int sampleRate; int channels; float peak; + int type; std::vector data; std::mutex busy_update; diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index 8bc962a..b7d78a3 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -79,6 +79,7 @@ class DemodulatorThreadPostIQData: public ReferenceCounter { public: std::vector data; long long sampleRate; + std::string modemName; std::string modemType; Modem *modem; ModemKit *modemKit; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 98716fd..f79eebf 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -200,7 +200,8 @@ void DemodulatorPreThread::run() { resamp->setRefCount(1); resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten); - resamp->modemType = demodType; + resamp->modemType = cModem->getType(); + resamp->modemName = cModem->getName(); resamp->modem = cModem; resamp->modemKit = cModemKit; resamp->sampleRate = currentBandwidth; @@ -248,8 +249,8 @@ void DemodulatorPreThread::run() { currentSampleRate = result.sampleRate; } - if (result.modemType != "") { - demodType = result.modemType; + if (result.modemName != "") { + demodType = result.modemName; demodTypeChanged.store(false); } diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 1437d1d..a7db28e 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -120,7 +120,7 @@ void DemodulatorThread::run() { AudioThreadInput *ati = NULL; ModemAnalog *modemAnalog = (cModem->getType() == "analog")?((ModemAnalog *)cModem):nullptr; -// ModemDigital *modemDigital = (cModem->getType() == "digital")?((ModemDigital *)cModem):nullptr; + ModemDigital *modemDigital = (cModem->getType() == "digital")?((ModemDigital *)cModem):nullptr; if (modemAnalog != nullptr) { ati = outputBuffers.getBuffer(); @@ -128,7 +128,14 @@ void DemodulatorThread::run() { ati->sampleRate = cModemKit->audioSampleRate; ati->inputRate = inp->sampleRate; ati->setRefCount(1); + } else if (modemDigital != nullptr) { + ati = outputBuffers.getBuffer(); + + ati->sampleRate = cModemKit->sampleRate; + ati->inputRate = inp->sampleRate; + ati->setRefCount(1); } + cModem->demodulate(cModemKit, &modemData, ati); if (currentSignalLevel > signalLevel) { @@ -160,7 +167,15 @@ void DemodulatorThread::run() { ati_vis->inputRate = inp->sampleRate; int num_vis = DEMOD_VIS_SIZE; - if (ati->channels==2) { + if (modemDigital) { + ati_vis->data.resize(inputData->size()); + ati_vis->channels = 2; + for (int i = 0, iMax = inputData->size() / 2; i < iMax; i++) { + ati_vis->data[i * 2] = (*inputData)[i].real; + ati_vis->data[i * 2 + 1] = (*inputData)[i].imag; + } + ati_vis->type = 2; + } else if (ati->channels==2) { ati_vis->channels = 2; int stereoSize = ati->data.size(); if (stereoSize > DEMOD_VIS_SIZE * 2) { @@ -169,7 +184,7 @@ void DemodulatorThread::run() { ati_vis->data.resize(stereoSize); - if (inp->modemType == "I/Q") { + if (inp->modemName == "I/Q") { for (int i = 0; i < stereoSize / 2; i++) { ati_vis->data[i] = (*inputData)[i].real * 0.75; ati_vis->data[i + stereoSize / 2] = (*inputData)[i].imag * 0.75; @@ -182,6 +197,7 @@ void DemodulatorThread::run() { ati_vis->data[i + stereoSize / 2] = ati->data[i * 2 + 1]; } } + ati_vis->type = 1; } else { int numAudioWritten = ati->data.size(); ati_vis->channels = 1; @@ -198,7 +214,7 @@ void DemodulatorThread::run() { } ati_vis->data.assign(demodOutData->begin(), demodOutData->begin() + num_vis); } - + ati_vis->type = 0; } audioVisOutputQueue->push(ati_vis); diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index b6f9457..492b439 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -51,7 +51,8 @@ void DemodulatorWorkerThread::run() { if (makeDemod) { cModem = Modem::makeModem(demodCommand.demodType); - cModemType = demodCommand.demodType; + cModemName = cModem->getName(); + cModemType = cModem->getType(); if (demodCommand.settings.size()) { cModem->writeSettings(demodCommand.settings); } @@ -91,6 +92,7 @@ void DemodulatorWorkerThread::run() { result.modemKit = cModemKit; result.modemType = cModemType; + result.modemName = cModemName; resultQueue->push(result); } diff --git a/src/demod/DemodulatorWorkerThread.h b/src/demod/DemodulatorWorkerThread.h index 472543b..d2a8b4c 100644 --- a/src/demod/DemodulatorWorkerThread.h +++ b/src/demod/DemodulatorWorkerThread.h @@ -37,6 +37,7 @@ public: Modem *modem; ModemKit *modemKit; std::string modemType; + std::string modemName; }; class DemodulatorWorkerThreadCommand { @@ -93,4 +94,5 @@ protected: Modem *cModem; ModemKit *cModemKit; std::string cModemType; + std::string cModemName; }; diff --git a/src/forms/DigitalConsole/DigitalConsole.fbp b/src/forms/DigitalConsole/DigitalConsole.fbp index cd41a92..90aed1d 100644 --- a/src/forms/DigitalConsole/DigitalConsole.fbp +++ b/src/forms/DigitalConsole/DigitalConsole.fbp @@ -90,114 +90,125 @@ - bSizer + mainSizer wxVERTICAL none 5 wxEXPAND 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - ,90,90,-1,76,0 - 0 - 0 - wxID_ANY - - 0 - - - - 0 + - 1 - m_dataView - 1 - - - protected - 1 - - Resizable - 1 - - wxTE_CHARWRAP|wxTE_MULTILINE|wxTE_NOHIDESEL|wxTE_READONLY|wxTE_WORDWRAP - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - wxWS_EX_PROCESS_UI_UPDATES - - wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE|wxNO_BORDER|wxSIMPLE_BORDER|wxVSCROLL - - - - - - - - - - - - - - - - - - - - - - - - - - - + dataViewSizer + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,90,-1,76,0 + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_dataView + 1 + + + protected + 1 + + Resizable + 1 + + wxTE_CHARWRAP|wxTE_MULTILINE|wxTE_NOHIDESEL|wxTE_READONLY|wxTE_WORDWRAP + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + wxWS_EX_PROCESS_UI_UPDATES + + wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE|wxNO_BORDER|wxSIMPLE_BORDER|wxVSCROLL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 - wxEXPAND + wxALL|wxEXPAND 0 - + - bSizer2 + buttonSizer wxHORIZONTAL none - + 5 - wxALL - 0 - + wxEXPAND + 1 + 1 1 1 @@ -281,11 +292,11 @@ - + 5 - wxALL - 0 - + wxEXPAND + 1 + 1 1 1 @@ -369,11 +380,11 @@ - + 5 wxEXPAND - 0 - + 1 + 1 1 1 diff --git a/src/forms/DigitalConsole/DigitalConsoleFrame.cpp b/src/forms/DigitalConsole/DigitalConsoleFrame.cpp index 565a054..b1e4885 100644 --- a/src/forms/DigitalConsole/DigitalConsoleFrame.cpp +++ b/src/forms/DigitalConsole/DigitalConsoleFrame.cpp @@ -14,32 +14,38 @@ DigitalConsoleFrame::DigitalConsoleFrame( wxWindow* parent, wxWindowID id, const this->SetSizeHints( wxDefaultSize, wxDefaultSize ); this->SetExtraStyle( wxWS_EX_PROCESS_UI_UPDATES ); - wxBoxSizer* bSizer; - bSizer = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* mainSizer; + mainSizer = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* dataViewSizer; + dataViewSizer = new wxBoxSizer( wxVERTICAL ); m_dataView = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_CHARWRAP|wxTE_MULTILINE|wxTE_NOHIDESEL|wxTE_READONLY|wxTE_WORDWRAP|wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE|wxNO_BORDER|wxSIMPLE_BORDER|wxVSCROLL ); m_dataView->SetExtraStyle( wxWS_EX_PROCESS_UI_UPDATES ); m_dataView->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 76, 90, 90, false, wxEmptyString ) ); - bSizer->Add( m_dataView, 1, wxEXPAND, 5 ); + dataViewSizer->Add( m_dataView, 1, wxEXPAND, 5 ); - wxBoxSizer* bSizer2; - bSizer2 = new wxBoxSizer( wxHORIZONTAL ); + + mainSizer->Add( dataViewSizer, 1, wxEXPAND, 5 ); + + wxBoxSizer* buttonSizer; + buttonSizer = new wxBoxSizer( wxHORIZONTAL ); m_clearButton = new wxButton( this, wxID_ANY, wxT("Clear"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer2->Add( m_clearButton, 0, wxALL, 5 ); + buttonSizer->Add( m_clearButton, 1, wxEXPAND, 5 ); m_copyButton = new wxButton( this, wxID_ANY, wxT("Copy"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer2->Add( m_copyButton, 0, wxALL, 5 ); + buttonSizer->Add( m_copyButton, 1, wxEXPAND, 5 ); m_pauseButton = new wxButton( this, wxID_ANY, wxT("Stop"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer2->Add( m_pauseButton, 0, wxEXPAND, 5 ); + buttonSizer->Add( m_pauseButton, 1, wxEXPAND, 5 ); - bSizer->Add( bSizer2, 0, wxEXPAND, 5 ); + mainSizer->Add( buttonSizer, 0, wxALL|wxEXPAND, 5 ); - this->SetSizer( bSizer ); + this->SetSizer( mainSizer ); this->Layout(); m_refreshTimer.SetOwner( this, wxID_ANY ); m_refreshTimer.Start( 250 ); diff --git a/src/forms/DigitalConsole/DigitalConsoleFrame.h b/src/forms/DigitalConsole/DigitalConsoleFrame.h index 05fdd9f..6665b66 100644 --- a/src/forms/DigitalConsole/DigitalConsoleFrame.h +++ b/src/forms/DigitalConsole/DigitalConsoleFrame.h @@ -16,8 +16,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/modules/modem/Modem.cpp b/src/modules/modem/Modem.cpp index cd8bf58..6b14b58 100644 --- a/src/modules/modem/Modem.cpp +++ b/src/modules/modem/Modem.cpp @@ -44,9 +44,9 @@ ModemFactoryList Modem::getFactories() { return modemFactories; } -Modem *Modem::makeModem(std::string modemType) { - if (modemFactories.find(modemType) != modemFactories.end()) { - return modemFactories[modemType]->factory(); +Modem *Modem::makeModem(std::string modemName) { + if (modemFactories.find(modemName) != modemFactories.end()) { + return modemFactories[modemName]->factory(); } return nullptr; diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h index c952e39..f87c4db 100644 --- a/src/modules/modem/Modem.h +++ b/src/modules/modem/Modem.h @@ -112,7 +112,7 @@ public: static void addModemFactory(Modem *factorySingle); static ModemFactoryList getFactories(); - static Modem *makeModem(std::string modemType); + static Modem *makeModem(std::string modemName); virtual std::string getType() = 0; virtual std::string getName() = 0; diff --git a/src/panel/ScopePanel.cpp b/src/panel/ScopePanel.cpp index f72a14c..092e227 100644 --- a/src/panel/ScopePanel.cpp +++ b/src/panel/ScopePanel.cpp @@ -16,6 +16,9 @@ void ScopePanel::setMode(ScopeMode scopeMode) { this->scopeMode = scopeMode; } +ScopePanel::ScopeMode ScopePanel::getMode() { + return this->scopeMode; +} void ScopePanel::setPoints(std::vector &points) { this->points.assign(points.begin(),points.end()); @@ -61,14 +64,29 @@ void ScopePanel::drawPanelContents() { glEnd(); } else if (scopeMode == SCOPE_MODE_XY) { - // ... + RGBA4f bg1(ThemeMgr::mgr.currentTheme->scopeBackground), bg2(ThemeMgr::mgr.currentTheme->scopeBackground * 2.0); + bg1.a = 0.1; + bg2.a = 0.1; + bgPanel.setFillColor(bg1, bg2); + bgPanel.calcTransform(transform); + bgPanel.draw(); + glLineWidth(1.0); + glEnable(GL_POINT_SMOOTH); + glPointSize(2.0); + glLoadMatrixf(transform); + glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r * 0.35, ThemeMgr::mgr.currentTheme->scopeLine.g * 0.35, + ThemeMgr::mgr.currentTheme->scopeLine.b * 0.35); } if (points.size()) { glEnable (GL_BLEND); glEnable (GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (scopeMode == SCOPE_MODE_XY) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + } else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } glColor4f(ThemeMgr::mgr.currentTheme->scopeLine.r, ThemeMgr::mgr.currentTheme->scopeLine.g, ThemeMgr::mgr.currentTheme->scopeLine.b, 1.0); glEnableClientState (GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, &points[0]); @@ -83,7 +101,8 @@ void ScopePanel::drawPanelContents() { glLoadMatrixf(bgPanelStereo[1].transform); glDrawArrays(GL_LINE_STRIP, points.size() / 4, points.size() / 4); } else if (scopeMode == SCOPE_MODE_XY) { - // ... + glLoadMatrixf(bgPanel.transform); + glDrawArrays(GL_POINTS, 0, points.size() / 2); } glLineWidth(1.0); glDisableClientState(GL_VERTEX_ARRAY); diff --git a/src/panel/ScopePanel.h b/src/panel/ScopePanel.h index 7d72756..2ce9224 100644 --- a/src/panel/ScopePanel.h +++ b/src/panel/ScopePanel.h @@ -10,6 +10,7 @@ public: ScopePanel(); void setMode(ScopeMode scopeMode); + ScopeMode getMode(); void setPoints(std::vector &points); protected: diff --git a/src/process/ScopeVisualProcessor.cpp b/src/process/ScopeVisualProcessor.cpp index dad6a03..19eb794 100644 --- a/src/process/ScopeVisualProcessor.cpp +++ b/src/process/ScopeVisualProcessor.cpp @@ -95,7 +95,7 @@ void ScopeVisualProcessor::process() { } } - if (audioInputData->channels == 2) { + if (audioInputData->type == 1) { iMax = audioInputData->data.size(); if (renderData->waveform_points.size() != iMax * 2) { renderData->waveform_points.resize(iMax * 2); @@ -104,11 +104,23 @@ void ScopeVisualProcessor::process() { renderData->waveform_points[i * 2] = (((double) (i % (iMax/2)) / (double) iMax) * 2.0 - 0.5) * 2.0; renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] / peak; } + renderData->mode = ScopePanel::SCOPE_MODE_2Y; + } else if (audioInputData->type == 2) { + iMax = audioInputData->data.size(); + if (renderData->waveform_points.size() != iMax) { + renderData->waveform_points.resize(iMax); + } + for (i = 0; i < iMax/2; i++) { + renderData->waveform_points[i * 2] = audioInputData->data[i * 2] / peak; + renderData->waveform_points[i * 2 + 1] = audioInputData->data[i * 2 + 1] / peak; + } + renderData->mode = ScopePanel::SCOPE_MODE_XY; } else { for (i = 0; i < iMax; i++) { renderData->waveform_points[i * 2] = (((double) i / (double) iMax) - 0.5) * 2.0; renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] / peak; } + renderData->mode = ScopePanel::SCOPE_MODE_Y; } renderData->spectrum = false; diff --git a/src/process/ScopeVisualProcessor.h b/src/process/ScopeVisualProcessor.h index 98a2398..daa131f 100644 --- a/src/process/ScopeVisualProcessor.h +++ b/src/process/ScopeVisualProcessor.h @@ -3,10 +3,12 @@ #include "VisualProcessor.h" #include "AudioThread.h" #include "fftw3.h" +#include "ScopePanel.h" class ScopeRenderData: public ReferenceCounter { public: std::vector waveform_points; + ScopePanel::ScopeMode mode; int inputRate; int sampleRate; int channels; diff --git a/src/visual/ScopeCanvas.cpp b/src/visual/ScopeCanvas.cpp index 9dfaced..b98ae83 100644 --- a/src/visual/ScopeCanvas.cpp +++ b/src/visual/ScopeCanvas.cpp @@ -28,7 +28,7 @@ EVT_LEAVE_WINDOW(ScopeCanvas::OnMouseLeftWindow) EVT_ENTER_WINDOW(ScopeCanvas::OnMouseEnterWindow) wxEND_EVENT_TABLE() -ScopeCanvas::ScopeCanvas(wxWindow *parent, int *attribList) : InteractiveCanvas(parent, attribList), stereo(false), ppmMode(false), ctr(0), ctrTarget(0), dragAccel(0), helpTip("") { +ScopeCanvas::ScopeCanvas(wxWindow *parent, int *attribList) : InteractiveCanvas(parent, attribList), ppmMode(false), ctr(0), ctrTarget(0), dragAccel(0), helpTip("") { glContext = new ScopeContext(this, &wxGetApp().GetContext(this)); inputData.set_max_num_items(2); @@ -65,7 +65,7 @@ bool ScopeCanvas::spectrumVisible() { float panelInterval = (2.0 + panelSpacing); ctrTarget = abs(round(ctr / panelInterval)); - + if (ctrTarget == 1 || dragAccel || (ctr != ctrTarget)) { return true; } @@ -73,10 +73,6 @@ bool ScopeCanvas::spectrumVisible() { return false; } -void ScopeCanvas::setStereo(bool state) { - stereo = state; -} - void ScopeCanvas::setDeviceName(std::string device_name) { deviceName = device_name; deviceName.append(" "); @@ -106,12 +102,12 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { ScopeRenderData *avData; inputData.pop(avData); + if (!avData->spectrum) { + scopePanel.setMode(avData->mode); if (avData->waveform_points.size()) { scopePanel.setPoints(avData->waveform_points); - setStereo(avData->channels == 2); } - avData->decRefCount(); } else { if (avData->waveform_points.size()) { @@ -133,14 +129,18 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glViewport(0, 0, ClientSize.x, ClientSize.y); - glContext->DrawBegin(); + if (scopePanel.getMode() == ScopePanel::SCOPE_MODE_XY && !spectrumVisible()) { + glDrawBuffer(GL_FRONT); + glContext->DrawBegin(false); + } else { + glDrawBuffer(GL_BACK); + glContext->DrawBegin(); + + bgPanel.setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground * 3.0, RGBA4f(0,0,0,1)); + bgPanel.calcTransform(CubicVR::mat4::identity()); + bgPanel.draw(); + } - bgPanel.setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground * 3.0, RGBA4f(0,0,0,0)); - bgPanel.calcTransform(CubicVR::mat4::identity()); - bgPanel.draw(); - - scopePanel.setMode(stereo?ScopePanel::SCOPE_MODE_2Y:ScopePanel::SCOPE_MODE_Y); - glMatrixMode(GL_PROJECTION); glLoadIdentity(); glLoadMatrixf(CubicVR::mat4::perspective(45.0, 1.0, 1.0, 1000.0)); @@ -190,7 +190,7 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { spectrumPanel.setPosition(panelInterval+ctr, 0); if (spectrumVisible()) { - spectrumPanel.setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground * 2.0, RGBA4f(0,0,0,0)); + spectrumPanel.setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground * 2.0, RGBA4f(0,0,0,1)); spectrumPanel.contentsVisible = true; roty = atan2(spectrumPanel.pos[0],1.2); spectrumPanel.rot[1] = -(roty * (180.0 / M_PI)); @@ -217,7 +217,9 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glContext->DrawTunerTitles(ppmMode); glContext->DrawEnd(); - SwapBuffers(); + if (scopePanel.getMode() != ScopePanel::SCOPE_MODE_XY || spectrumVisible()) { + SwapBuffers(); + } } diff --git a/src/visual/ScopeCanvas.h b/src/visual/ScopeCanvas.h index d868b2e..3a04f9a 100644 --- a/src/visual/ScopeCanvas.h +++ b/src/visual/ScopeCanvas.h @@ -18,7 +18,6 @@ public: ScopeCanvas(wxWindow *parent, int *attribList = NULL); ~ScopeCanvas(); - void setStereo(bool state); void setDeviceName(std::string device_name); void setPPMMode(bool ppmMode); bool getPPMMode(); @@ -50,7 +49,6 @@ private: GLPanel bgPanel; ScopeContext *glContext; std::string deviceName; - bool stereo; bool ppmMode; bool showDb; float panelSpacing; diff --git a/src/visual/ScopeContext.cpp b/src/visual/ScopeContext.cpp index 8c4a889..a24e4b8 100644 --- a/src/visual/ScopeContext.cpp +++ b/src/visual/ScopeContext.cpp @@ -12,10 +12,12 @@ ScopeContext::ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext) : glLoadIdentity(); } -void ScopeContext::DrawBegin() { - glClearColor(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g, - ThemeMgr::mgr.currentTheme->scopeBackground.b, 1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +void ScopeContext::DrawBegin(bool clear) { + if (clear) { + glClearColor(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g, + ThemeMgr::mgr.currentTheme->scopeBackground.b, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } glMatrixMode (GL_MODELVIEW); glLoadIdentity(); diff --git a/src/visual/ScopeContext.h b/src/visual/ScopeContext.h index c962429..873bde0 100644 --- a/src/visual/ScopeContext.h +++ b/src/visual/ScopeContext.h @@ -11,7 +11,7 @@ class ScopeContext: public PrimaryGLContext { public: ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext); - void DrawBegin(); + void DrawBegin(bool clear=true); void DrawTunerTitles(bool ppmMode=false); void DrawDeviceName(std::string deviceName); void DrawDivider(); From 380a5e4c2e4d846fc3d51e172656934b74f42fc3 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 29 Nov 2015 15:16:44 -0500 Subject: [PATCH 20/24] Fix case where re-activation shows old mode dialog --- src/demod/DemodulatorInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 5ba905a..6a4badd 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -184,7 +184,7 @@ void DemodulatorInstance::setActive(bool state) { audioThread->setActive(state); } else if (!active && state) { #if ENABLE_DIGITAL_LAB - if (activeOutput) { + if (activeOutput && getModemType() == "digital") { activeOutput->Show(); } #endif From ceb6d6208915ef7852f93a00fc0bffa33336b1e2 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 29 Nov 2015 16:42:12 -0500 Subject: [PATCH 21/24] X/Y scope fading tweak --- src/panel/ScopePanel.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/panel/ScopePanel.cpp b/src/panel/ScopePanel.cpp index 092e227..1bc15db 100644 --- a/src/panel/ScopePanel.cpp +++ b/src/panel/ScopePanel.cpp @@ -65,17 +65,17 @@ void ScopePanel::drawPanelContents() { } else if (scopeMode == SCOPE_MODE_XY) { RGBA4f bg1(ThemeMgr::mgr.currentTheme->scopeBackground), bg2(ThemeMgr::mgr.currentTheme->scopeBackground * 2.0); - bg1.a = 0.1; - bg2.a = 0.1; + bg1.a = 0.05; + bg2.a = 0.05; bgPanel.setFillColor(bg1, bg2); bgPanel.calcTransform(transform); bgPanel.draw(); glLineWidth(1.0); glEnable(GL_POINT_SMOOTH); - glPointSize(2.0); + glPointSize(1.0); glLoadMatrixf(transform); - glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r * 0.35, ThemeMgr::mgr.currentTheme->scopeLine.g * 0.35, - ThemeMgr::mgr.currentTheme->scopeLine.b * 0.35); + glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r * 0.15, ThemeMgr::mgr.currentTheme->scopeLine.g * 0.15, + ThemeMgr::mgr.currentTheme->scopeLine.b * 0.15); } if (points.size()) { @@ -83,7 +83,7 @@ void ScopePanel::drawPanelContents() { glEnable (GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); if (scopeMode == SCOPE_MODE_XY) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glBlendFunc(GL_ONE, GL_ONE); } else { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } From 76d69ffd78817a4781dca266d917a6efd3261f0d Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 30 Nov 2015 21:58:54 -0500 Subject: [PATCH 22/24] Add GMSK, fix modem bandwidth logic, cleanup. --- CMakeLists.txt | 2 + src/AppFrame.cpp | 48 ++++---- src/CubicSDR.cpp | 1 + src/CubicSDR.h | 1 + src/ModemProperties.cpp | 26 +++- src/ModemProperties.h | 5 + src/demod/DemodulatorInstance.cpp | 13 +- src/demod/DemodulatorInstance.h | 1 + src/demod/DemodulatorMgr.cpp | 15 --- src/demod/DemodulatorMgr.h | 4 - src/modules/modem/Modem.cpp | 14 +++ src/modules/modem/Modem.h | 2 + src/modules/modem/analog/ModemAM.cpp | 8 ++ src/modules/modem/analog/ModemAM.h | 6 + src/modules/modem/analog/ModemDSB.cpp | 8 ++ src/modules/modem/analog/ModemDSB.h | 6 + src/modules/modem/analog/ModemFM.cpp | 8 ++ src/modules/modem/analog/ModemFM.h | 7 +- src/modules/modem/analog/ModemFMStereo.cpp | 4 + src/modules/modem/analog/ModemFMStereo.h | 1 + src/modules/modem/analog/ModemIQ.cpp | 20 ++-- src/modules/modem/analog/ModemIQ.h | 9 +- src/modules/modem/analog/ModemLSB.cpp | 4 + src/modules/modem/analog/ModemLSB.h | 6 +- src/modules/modem/analog/ModemUSB.cpp | 4 + src/modules/modem/analog/ModemUSB.h | 5 + src/modules/modem/digital/ModemFSK.cpp | 4 + src/modules/modem/digital/ModemFSK.h | 1 + src/modules/modem/digital/ModemGMSK.cpp | 133 +++++++++++++++++++++ src/modules/modem/digital/ModemGMSK.h | 41 +++++++ src/modules/modem/digital/ModemOOK.cpp | 15 ++- src/modules/modem/digital/ModemOOK.h | 2 + src/visual/ModeSelectorCanvas.cpp | 5 + src/visual/ModeSelectorCanvas.h | 1 + src/visual/WaterfallCanvas.cpp | 12 +- 35 files changed, 365 insertions(+), 77 deletions(-) create mode 100644 src/modules/modem/digital/ModemGMSK.cpp create mode 100644 src/modules/modem/digital/ModemGMSK.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f07098..5c2c651 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,6 +297,7 @@ IF(ENABLE_DIGITAL_LAB) src/modules/modem/digital/ModemBPSK.cpp src/modules/modem/digital/ModemDPSK.cpp src/modules/modem/digital/ModemFSK.cpp + src/modules/modem/digital/ModemGMSK.cpp src/modules/modem/digital/ModemPSK.cpp src/modules/modem/digital/ModemOOK.cpp src/modules/modem/digital/ModemST.cpp @@ -402,6 +403,7 @@ SET (cubicsdr_headers src/modules/modem/digital/ModemBPSK.h src/modules/modem/digital/ModemDPSK.h src/modules/modem/digital/ModemFSK.h + src/modules/modem/digital/ModemGMSK.h src/modules/modem/digital/ModemPSK.h src/modules/modem/digital/ModemOOK.h src/modules/modem/digital/ModemST.h diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 7cc5339..82deeac 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -67,13 +67,13 @@ AppFrame::AppFrame() : gainSpacerItem->Show(false); demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList); - demodModeSelector->addChoice(0, "FM"); - demodModeSelector->addChoice(1, "FMS"); - demodModeSelector->addChoice(2, "AM"); - demodModeSelector->addChoice(3, "LSB"); - demodModeSelector->addChoice(4, "USB"); - demodModeSelector->addChoice(5, "DSB"); - demodModeSelector->addChoice(6, "I/Q"); + demodModeSelector->addChoice("FM"); + demodModeSelector->addChoice("FMS"); + demodModeSelector->addChoice("AM"); + demodModeSelector->addChoice("LSB"); + demodModeSelector->addChoice("USB"); + demodModeSelector->addChoice("DSB"); + demodModeSelector->addChoice("I/Q"); demodModeSelector->setSelection("FM"); demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation, Amplitude Modulation and Lower, Upper or Double Side-Band."); demodModeSelector->SetMinSize(wxSize(40,-1)); @@ -82,17 +82,18 @@ AppFrame::AppFrame() : #ifdef ENABLE_DIGITAL_LAB demodModeSelectorAdv = new ModeSelectorCanvas(demodPanel, attribList); - demodModeSelectorAdv->addChoice(0, "ASK"); - demodModeSelectorAdv->addChoice(1, "APSK"); - demodModeSelectorAdv->addChoice(2, "BPSK"); - demodModeSelectorAdv->addChoice(3, "DPSK"); - demodModeSelectorAdv->addChoice(4, "PSK"); - demodModeSelectorAdv->addChoice(5, "FSK"); - demodModeSelectorAdv->addChoice(6, "OOK"); - demodModeSelectorAdv->addChoice(7, "ST"); - demodModeSelectorAdv->addChoice(8, "SQAM"); - demodModeSelectorAdv->addChoice(9, "QAM"); - demodModeSelectorAdv->addChoice(10, "QPSK"); + demodModeSelectorAdv->addChoice("ASK"); + demodModeSelectorAdv->addChoice("APSK"); + demodModeSelectorAdv->addChoice("BPSK"); + demodModeSelectorAdv->addChoice("DPSK"); + demodModeSelectorAdv->addChoice("PSK"); + demodModeSelectorAdv->addChoice("FSK"); + demodModeSelectorAdv->addChoice("GMSK"); + demodModeSelectorAdv->addChoice("OOK"); + demodModeSelectorAdv->addChoice("ST"); + demodModeSelectorAdv->addChoice("SQAM"); + demodModeSelectorAdv->addChoice("QAM"); + demodModeSelectorAdv->addChoice("QPSK"); demodModeSelectorAdv->setHelpTip("Choose advanced modulation types."); demodModeSelectorAdv->SetMinSize(wxSize(40,-1)); demodModeSelectorAdv->SetMaxSize(wxSize(40,-1)); @@ -906,25 +907,16 @@ void AppFrame::OnIdle(wxIdleEvent& event) { if (dSelection != "" && dSelection != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelection); demodModeSelectorAdv->setSelection(-1); - if (int lastDemodBw = wxGetApp().getDemodMgr().getLastBandwidth(dSelection)) { - demod->setBandwidth(lastDemodBw); - } } // advanced demodulators else if (dSelectionadv != "" && dSelectionadv != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelectionadv); demodModeSelector->setSelection(-1); - if (int lastDemodBw = wxGetApp().getDemodMgr().getLastBandwidth(dSelection)) { - demod->setBandwidth(lastDemodBw); - } } #else // basic demodulators if (dSelection != "" && dSelection != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelection); - if (int lastDemodBw = wxGetApp().getDemodMgr().getLastBandwidth(dSelection)) { - demod->setBandwidth(lastDemodBw); - } } #endif @@ -1017,7 +1009,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { if (!demodTuner->HasFocus()) { demodTuner->SetFocus(); } - } else if (!wxGetApp().isDeviceSelectorOpen()) { + } else if (!wxGetApp().isDeviceSelectorOpen() && (!modemProps || !modemProps->isMouseInView())) { if (!waterfallCanvas->HasFocus()) { waterfallCanvas->SetFocus(); } diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 2e917e6..e480765 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -178,6 +178,7 @@ bool CubicSDR::OnInit() { Modem::addModemFactory(new ModemBPSK); Modem::addModemFactory(new ModemDPSK); Modem::addModemFactory(new ModemFSK); + Modem::addModemFactory(new ModemGMSK); Modem::addModemFactory(new ModemOOK); Modem::addModemFactory(new ModemPSK); Modem::addModemFactory(new ModemQAM); diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 6de2843..381b308 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -43,6 +43,7 @@ #include "ModemBPSK.h" #include "ModemDPSK.h" #include "ModemFSK.h" +#include "ModemGMSK.h" #include "ModemOOK.h" #include "ModemPSK.h" #include "ModemQAM.h" diff --git a/src/ModemProperties.cpp b/src/ModemProperties.cpp index d8c2546..0472bff 100644 --- a/src/ModemProperties.cpp +++ b/src/ModemProperties.cpp @@ -14,10 +14,14 @@ ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid, m_propertyGrid->Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( ModemProperties::OnChange ), NULL, this ); this->Connect( wxEVT_SHOW, wxShowEventHandler( ModemProperties::OnShow ), NULL, this ); + + this->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( ModemProperties::OnMouseEnter ), NULL, this); + this->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( ModemProperties::OnMouseLeave ), NULL, this); + + mouseInView = false; } void ModemProperties::OnShow(wxShowEvent &event) { - m_propertyGrid->FitColumns(); } ModemProperties::~ModemProperties() { @@ -27,6 +31,7 @@ ModemProperties::~ModemProperties() { void ModemProperties::initProperties(ModemArgInfoList newArgs) { args = newArgs; + bSizer->Layout(); m_propertyGrid->Clear(); if (newArgs.size() == 0) { @@ -35,9 +40,6 @@ void ModemProperties::initProperties(ModemArgInfoList newArgs) { } else { Show(); } - - bSizer->Layout(); - Layout(); m_propertyGrid->Append(new wxPropertyCategory("Modem Settings")); @@ -149,6 +151,10 @@ std::string ModemProperties::readProperty(std::string key) { void ModemProperties::OnChange(wxPropertyGridEvent &event) { DemodulatorInstance *inst = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + if (!inst) { + return; + } + std::map::const_iterator prop_i; for (prop_i = props.begin(); prop_i != props.end(); prop_i++) { if (prop_i->second == event.m_property) { @@ -159,3 +165,15 @@ void ModemProperties::OnChange(wxPropertyGridEvent &event) { } } } + +void ModemProperties::OnMouseEnter(wxMouseEvent &event) { + mouseInView = true; +} + +void ModemProperties::OnMouseLeave(wxMouseEvent &event) { + mouseInView = false; +} + +bool ModemProperties::isMouseInView() { + return mouseInView; +} diff --git a/src/ModemProperties.h b/src/ModemProperties.h index 5a101c0..326c947 100644 --- a/src/ModemProperties.h +++ b/src/ModemProperties.h @@ -20,15 +20,20 @@ public: ~ModemProperties(); void initProperties(ModemArgInfoList newArgs); + bool isMouseInView(); private: wxPGProperty *addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg); std::string readProperty(std::string); void OnChange(wxPropertyGridEvent &event); void OnShow(wxShowEvent &event); + + void OnMouseEnter(wxMouseEvent &event); + void OnMouseLeave(wxMouseEvent &event); wxBoxSizer* bSizer; wxPropertyGrid* m_propertyGrid; ModemArgInfoList args; std::map props; + bool mouseInView; }; \ No newline at end of file diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 6a4badd..f3da7fb 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -264,13 +264,25 @@ void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) { std::string currentDemodType = demodulatorPreThread->getDemodType(); if ((currentDemodType != "") && (currentDemodType != demod_type_in)) { lastModemSettings[currentDemodType] = demodulatorPreThread->readModemSettings(); + lastModemBandwidth[currentDemodType] = demodulatorPreThread->getBandwidth(); } #if ENABLE_DIGITAL_LAB if (activeOutput) { activeOutput->Hide(); } #endif + demodulatorPreThread->setDemodType(demod_type_in); + int lastbw = 0; + if (currentDemodType != "" && lastModemBandwidth.find(demod_type_in) != lastModemBandwidth.end()) { + lastbw = lastModemBandwidth[demod_type_in]; + } + if (!lastbw) { + lastbw = Modem::getModemDefaultSampleRate(demod_type_in); + } + if (lastbw) { + setBandwidth(lastbw); + } } } @@ -297,7 +309,6 @@ int DemodulatorInstance::getDemodulatorLock() { void DemodulatorInstance::setBandwidth(int bw) { demodulatorPreThread->setBandwidth(bw); - wxGetApp().getDemodMgr().setLastBandwidth(bw); } int DemodulatorInstance::getBandwidth() { diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index d3d3671..b03184e 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -127,6 +127,7 @@ private: std::atomic currentAudioGain; std::atomic_bool follow, tracking; std::map lastModemSettings; + std::map lastModemBandwidth; #if ENABLE_DIGITAL_LAB ModemDigitalOutput *activeOutput; #endif diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index 4d6f874..618c5d0 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -8,13 +8,6 @@ DemodulatorMgr::DemodulatorMgr() : activeDemodulator(NULL), lastActiveDemodulator(NULL), activeVisualDemodulator(NULL), lastBandwidth(DEFAULT_DEMOD_BW), lastDemodType( DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(-100), lastGain(1.0), lastMuted(false) { - setLastBandwidth("FM",200000); - setLastBandwidth("FMS",200000); - setLastBandwidth("AM",6000); - setLastBandwidth("USB",5400); - setLastBandwidth("LSB",5400); - setLastBandwidth("DSB",5400); - setLastBandwidth("IQ",48000); } DemodulatorMgr::~DemodulatorMgr() { @@ -171,7 +164,6 @@ void DemodulatorMgr::updateLastState() { lastSquelch = lastActiveDemodulator->getSquelchLevel(); lastGain = lastActiveDemodulator->getGain(); lastModemSettings[lastDemodType] = lastActiveDemodulator->readModemSettings(); - lastBandwidthNamed[lastDemodType] = lastBandwidth; } } @@ -236,10 +228,3 @@ ModemSettings DemodulatorMgr::getLastModemSettings(std::string modemType) { void DemodulatorMgr::setLastModemSettings(std::string modemType, ModemSettings settings) { lastModemSettings[modemType] = settings; } - -int DemodulatorMgr::getLastBandwidth(std::string modemType) { - return lastBandwidthNamed[modemType]; -} -void DemodulatorMgr::setLastBandwidth(std::string modemType, int lastBandwidth_in) { - lastBandwidthNamed[modemType] = lastBandwidth_in; -} diff --git a/src/demod/DemodulatorMgr.h b/src/demod/DemodulatorMgr.h index 1b178d9..4e8f496 100644 --- a/src/demod/DemodulatorMgr.h +++ b/src/demod/DemodulatorMgr.h @@ -25,9 +25,6 @@ public: int getLastBandwidth() const; void setLastBandwidth(int lastBandwidth); - int getLastBandwidth(std::string modemType); - void setLastBandwidth(std::string modemType, int lastBandwidth); - std::string getLastDemodulatorType() const; void setLastDemodulatorType(std::string lastDemodType); @@ -57,7 +54,6 @@ private: DemodulatorInstance *lastActiveDemodulator; DemodulatorInstance *activeVisualDemodulator; - std::map lastBandwidthNamed; int lastBandwidth; std::string lastDemodType; bool lastDemodLock; diff --git a/src/modules/modem/Modem.cpp b/src/modules/modem/Modem.cpp index 6b14b58..c98e2be 100644 --- a/src/modules/modem/Modem.cpp +++ b/src/modules/modem/Modem.cpp @@ -1,4 +1,6 @@ #include "Modem.h" +#include "CubicSDR.h" + ModemFactoryList Modem::modemFactories; @@ -52,12 +54,24 @@ Modem *Modem::makeModem(std::string modemName) { return nullptr; } +int Modem::getModemDefaultSampleRate(std::string modemName) { + if (modemFactories.find(modemName) != modemFactories.end()) { + return modemFactories[modemName]->getDefaultSampleRate(); + } + + return 0; +} + ModemArgInfoList Modem::getSettings() { ModemArgInfoList args; return args; } +int Modem::getDefaultSampleRate() { + return 200000; +} + void Modem::writeSetting(std::string setting, std::string value) { // ... } diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h index f87c4db..d9ffb4c 100644 --- a/src/modules/modem/Modem.h +++ b/src/modules/modem/Modem.h @@ -113,6 +113,7 @@ public: static ModemFactoryList getFactories(); static Modem *makeModem(std::string modemName); + static int getModemDefaultSampleRate(std::string modemName); virtual std::string getType() = 0; virtual std::string getName() = 0; @@ -123,6 +124,7 @@ public: virtual ~Modem(); virtual ModemArgInfoList getSettings(); + virtual int getDefaultSampleRate(); virtual void writeSetting(std::string setting, std::string value); virtual void writeSettings(ModemSettings settings); virtual std::string readSetting(std::string setting); diff --git a/src/modules/modem/analog/ModemAM.cpp b/src/modules/modem/analog/ModemAM.cpp index 114d81b..a4baa57 100644 --- a/src/modules/modem/analog/ModemAM.cpp +++ b/src/modules/modem/analog/ModemAM.cpp @@ -4,6 +4,10 @@ ModemAM::ModemAM() : ModemAnalog() { demodAM = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0); } +ModemAM::~ModemAM() { + ampmodem_destroy(demodAM); +} + Modem *ModemAM::factory() { return new ModemAM; } @@ -12,6 +16,10 @@ std::string ModemAM::getName() { return "AM"; } +int ModemAM::getDefaultSampleRate() { + return 6000; +} + void ModemAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitAnalog *amkit = (ModemKitAnalog *)kit; diff --git a/src/modules/modem/analog/ModemAM.h b/src/modules/modem/analog/ModemAM.h index 8a1d017..5adf75f 100644 --- a/src/modules/modem/analog/ModemAM.h +++ b/src/modules/modem/analog/ModemAM.h @@ -5,8 +5,14 @@ class ModemAM : public ModemAnalog { public: ModemAM(); + ~ModemAM(); + std::string getName(); + Modem *factory(); + + int getDefaultSampleRate(); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/modules/modem/analog/ModemDSB.cpp b/src/modules/modem/analog/ModemDSB.cpp index b40b11f..b0de272 100644 --- a/src/modules/modem/analog/ModemDSB.cpp +++ b/src/modules/modem/analog/ModemDSB.cpp @@ -4,6 +4,10 @@ ModemDSB::ModemDSB() : ModemAnalog() { demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1); } +ModemDSB::~ModemDSB() { + ampmodem_destroy(demodAM_DSB); +} + Modem *ModemDSB::factory() { return new ModemDSB; } @@ -12,6 +16,10 @@ std::string ModemDSB::getName() { return "DSB"; } +int ModemDSB::getDefaultSampleRate() { + return 5400; +} + void ModemDSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitAnalog *amkit = (ModemKitAnalog *)kit; diff --git a/src/modules/modem/analog/ModemDSB.h b/src/modules/modem/analog/ModemDSB.h index fc0e550..8c99332 100644 --- a/src/modules/modem/analog/ModemDSB.h +++ b/src/modules/modem/analog/ModemDSB.h @@ -5,8 +5,14 @@ class ModemDSB : public ModemAnalog { public: ModemDSB(); + ~ModemDSB(); + std::string getName(); + Modem *factory(); + + int getDefaultSampleRate(); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/modules/modem/analog/ModemFM.cpp b/src/modules/modem/analog/ModemFM.cpp index 1e90ea4..931eef6 100644 --- a/src/modules/modem/analog/ModemFM.cpp +++ b/src/modules/modem/analog/ModemFM.cpp @@ -4,6 +4,10 @@ ModemFM::ModemFM() : ModemAnalog() { demodFM = freqdem_create(0.5); } +ModemFM::~ModemFM() { + freqdem_destroy(demodFM); +} + Modem *ModemFM::factory() { return new ModemFM; } @@ -12,6 +16,10 @@ std::string ModemFM::getName() { return "FM"; } +int ModemFM::getDefaultSampleRate() { + return 200000; +} + void ModemFM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitAnalog *fmkit = (ModemKitAnalog *)kit; diff --git a/src/modules/modem/analog/ModemFM.h b/src/modules/modem/analog/ModemFM.h index a763bc2..267114d 100644 --- a/src/modules/modem/analog/ModemFM.h +++ b/src/modules/modem/analog/ModemFM.h @@ -5,11 +5,16 @@ class ModemFM : public ModemAnalog { public: ModemFM(); + ~ModemFM(); + std::string getName(); + Modem *factory(); + + int getDefaultSampleRate(); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: - freqdem demodFM; }; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemFMStereo.cpp b/src/modules/modem/analog/ModemFMStereo.cpp index f871ac9..935fb4b 100644 --- a/src/modules/modem/analog/ModemFMStereo.cpp +++ b/src/modules/modem/analog/ModemFMStereo.cpp @@ -40,6 +40,10 @@ int ModemFMStereo::checkSampleRate(long long sampleRate, int audioSampleRate) { } } +int ModemFMStereo::getDefaultSampleRate() { + return 200000; +} + ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) { ModemKitFMStereo *kit = new ModemKitFMStereo; diff --git a/src/modules/modem/analog/ModemFMStereo.h b/src/modules/modem/analog/ModemFMStereo.h index 10808f8..21e41c1 100644 --- a/src/modules/modem/analog/ModemFMStereo.h +++ b/src/modules/modem/analog/ModemFMStereo.h @@ -27,6 +27,7 @@ public: Modem *factory(); int checkSampleRate(long long sampleRate, int audioSampleRate); + int getDefaultSampleRate(); ModemKit *buildKit(long long sampleRate, int audioSampleRate); void disposeKit(ModemKit *kit); diff --git a/src/modules/modem/analog/ModemIQ.cpp b/src/modules/modem/analog/ModemIQ.cpp index bcf7d97..7eda625 100644 --- a/src/modules/modem/analog/ModemIQ.cpp +++ b/src/modules/modem/analog/ModemIQ.cpp @@ -4,6 +4,14 @@ ModemIQ::ModemIQ() { } +std::string ModemIQ::getType() { + return "analog"; +} + +std::string ModemIQ::getName() { + return "I/Q"; +} + Modem *ModemIQ::factory() { return new ModemIQ; } @@ -15,14 +23,6 @@ ModemKit *ModemIQ::buildKit(long long sampleRate, int audioSampleRate) { return kit; } -std::string ModemIQ::getType() { - return "analog"; -} - -std::string ModemIQ::getName() { - return "I/Q"; -} - void ModemIQ::disposeKit(ModemKit *kit) { delete kit; } @@ -31,6 +31,10 @@ int ModemIQ::checkSampleRate(long long sampleRate, int audioSampleRate) { return audioSampleRate; } +int ModemIQ::getDefaultSampleRate() { + return 48000; +} + void ModemIQ::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { int bufSize = input->data.size(); diff --git a/src/modules/modem/analog/ModemIQ.h b/src/modules/modem/analog/ModemIQ.h index ea0c614..ca9e5fa 100644 --- a/src/modules/modem/analog/ModemIQ.h +++ b/src/modules/modem/analog/ModemIQ.h @@ -4,12 +4,19 @@ class ModemIQ : public Modem { public: ModemIQ(); + std::string getType(); std::string getName(); + Modem *factory(); - ModemKit *buildKit(long long sampleRate, int audioSampleRate); + int checkSampleRate(long long sampleRate, int audioSampleRate); + int getDefaultSampleRate(); + + ModemKit *buildKit(long long sampleRate, int audioSampleRate); + void disposeKit(ModemKit *kit); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp index 3838f1d..7e38f15 100644 --- a/src/modules/modem/analog/ModemLSB.cpp +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -29,6 +29,10 @@ int ModemLSB::checkSampleRate(long long sampleRate, int audioSampleRate) { return sampleRate+1; } +int ModemLSB::getDefaultSampleRate() { + return 5400; +} + void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitAnalog *akit = (ModemKitAnalog *)kit; diff --git a/src/modules/modem/analog/ModemLSB.h b/src/modules/modem/analog/ModemLSB.h index 9ea4c0e..04a462c 100644 --- a/src/modules/modem/analog/ModemLSB.h +++ b/src/modules/modem/analog/ModemLSB.h @@ -1,14 +1,18 @@ #pragma once -#include "Modem.h" #include "ModemAnalog.h" class ModemLSB : public ModemAnalog { public: ModemLSB(); ~ModemLSB(); + std::string getName(); + Modem *factory(); + int checkSampleRate(long long sampleRate, int audioSampleRate); + int getDefaultSampleRate(); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp index 17392c5..be1c9bd 100644 --- a/src/modules/modem/analog/ModemUSB.cpp +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -29,6 +29,10 @@ int ModemUSB::checkSampleRate(long long sampleRate, int audioSampleRate) { return sampleRate+1; } +int ModemUSB::getDefaultSampleRate() { + return 5400; +} + void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitAnalog *akit = (ModemKitAnalog *)kit; diff --git a/src/modules/modem/analog/ModemUSB.h b/src/modules/modem/analog/ModemUSB.h index cff6ac4..44dd0f3 100644 --- a/src/modules/modem/analog/ModemUSB.h +++ b/src/modules/modem/analog/ModemUSB.h @@ -5,9 +5,14 @@ class ModemUSB : public ModemAnalog { public: ModemUSB(); ~ModemUSB(); + std::string getName(); + Modem *factory(); + int checkSampleRate(long long sampleRate, int audioSampleRate); + int getDefaultSampleRate(); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/modules/modem/digital/ModemFSK.cpp b/src/modules/modem/digital/ModemFSK.cpp index 43b8180..f7f856e 100644 --- a/src/modules/modem/digital/ModemFSK.cpp +++ b/src/modules/modem/digital/ModemFSK.cpp @@ -22,6 +22,10 @@ int ModemFSK::checkSampleRate(long long sampleRate, int audioSampleRate) { } } +int ModemFSK::getDefaultSampleRate() { + return 19200; +} + ModemArgInfoList ModemFSK::getSettings() { ModemArgInfoList args; diff --git a/src/modules/modem/digital/ModemFSK.h b/src/modules/modem/digital/ModemFSK.h index 8f2e00b..03c1d24 100644 --- a/src/modules/modem/digital/ModemFSK.h +++ b/src/modules/modem/digital/ModemFSK.h @@ -21,6 +21,7 @@ public: Modem *factory(); int checkSampleRate(long long sampleRate, int audioSampleRate); + int getDefaultSampleRate(); ModemArgInfoList getSettings(); void writeSetting(std::string setting, std::string value); diff --git a/src/modules/modem/digital/ModemGMSK.cpp b/src/modules/modem/digital/ModemGMSK.cpp new file mode 100644 index 0000000..166641d --- /dev/null +++ b/src/modules/modem/digital/ModemGMSK.cpp @@ -0,0 +1,133 @@ +#include "ModemGMSK.h" +#include + +ModemGMSK::ModemGMSK() : ModemDigital() { + _sps = 4; + _fdelay = 3; + _ebf = 0.3; + outStream << std::hex; +} + +ModemGMSK::~ModemGMSK() { + +} + +std::string ModemGMSK::getName() { + return "GMSK"; +} + +Modem *ModemGMSK::factory() { + return new ModemGMSK; +} + +int ModemGMSK::checkSampleRate(long long sampleRate, int audioSampleRate) { + if (sampleRate < 1500) { + return 1500; + } + return sampleRate; +} + +int ModemGMSK::getDefaultSampleRate() { + return 19200; +} + +ModemArgInfoList ModemGMSK::getSettings() { + ModemArgInfoList args; + + ModemArgInfo fdelayArg; + fdelayArg.key = "fdelay"; + fdelayArg.name = "Filter delay"; + fdelayArg.value = std::to_string(_fdelay); + fdelayArg.description = "Filter delay in samples"; + fdelayArg.type = ModemArgInfo::INT; + fdelayArg.units = "samples"; + fdelayArg.range = ModemRange(1,128); + args.push_back(fdelayArg); + + ModemArgInfo spsArg; + spsArg.key = "sps"; + spsArg.name = "Samples / symbol"; + spsArg.value = std::to_string(_sps); + spsArg.description = "Modem samples-per-symbol"; + spsArg.type = ModemArgInfo::INT; + spsArg.units = "samples/symbol"; + spsArg.range = ModemRange(2,512); + args.push_back(spsArg); + + ModemArgInfo ebfArg; + ebfArg.key = "ebf"; + ebfArg.name = "Excess bandwidth"; + ebfArg.value = std::to_string(_ebf); + ebfArg.description = "Modem excess bandwidth factor"; + ebfArg.type = ModemArgInfo::FLOAT; + ebfArg.range = ModemRange(0.1,0.49); + args.push_back(ebfArg); + + return args; +} + +void ModemGMSK::writeSetting(std::string setting, std::string value) { + if (setting == "fdelay") { + _fdelay = std::stoi(value); + rebuildKit(); + } else if (setting == "sps") { + _sps = std::stoi(value); + rebuildKit(); + } else if (setting == "ebf") { + _ebf = std::stof(value); + rebuildKit(); + } +} + +std::string ModemGMSK::readSetting(std::string setting) { + if (setting == "fdelay") { + return std::to_string(_fdelay); + } else if (setting == "sps") { + return std::to_string(_sps); + } else if (setting == "ebf") { + return std::to_string(_ebf); + } + return ""; +} + +ModemKit *ModemGMSK::buildKit(long long sampleRate, int audioSampleRate) { + ModemKitGMSK *dkit = new ModemKitGMSK; + dkit->sps = _sps; + dkit->fdelay = _fdelay; + dkit->ebf = _ebf; + + dkit->demodGMSK = gmskdem_create(dkit->sps, dkit->fdelay, dkit->ebf); + + dkit->sampleRate = sampleRate; + dkit->audioSampleRate = audioSampleRate; + + return dkit; +} + +void ModemGMSK::disposeKit(ModemKit *kit) { + ModemKitGMSK *dkit = (ModemKitGMSK *)kit; + + gmskdem_destroy(dkit->demodGMSK); + + delete dkit; +} + +void ModemGMSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitGMSK *dkit = (ModemKitGMSK *)kit; + unsigned int sym_out; + + digitalStart(dkit, nullptr, input); + + dkit->inputBuffer.insert(dkit->inputBuffer.end(),input->data.begin(),input->data.end()); + + int numProcessed = 0; + for (int i = 0, iMax = dkit->inputBuffer.size()/dkit->sps; i < iMax; i+= dkit->sps) { + gmskdem_demodulate(dkit->demodGMSK, &input->data[i],&sym_out); + outStream << sym_out; + numProcessed += dkit->sps; + } + + dkit->inputBuffer.erase(dkit->inputBuffer.begin(),dkit->inputBuffer.begin()+numProcessed); + + digitalFinish(dkit, nullptr); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemGMSK.h b/src/modules/modem/digital/ModemGMSK.h new file mode 100644 index 0000000..e2e0635 --- /dev/null +++ b/src/modules/modem/digital/ModemGMSK.h @@ -0,0 +1,41 @@ +#pragma once +#include "ModemDigital.h" +#include + +class ModemKitGMSK : public ModemKitDigital { +public: + unsigned int fdelay, sps; + float ebf; + + gmskdem demodGMSK; + std::vector inputBuffer; +}; + + +class ModemGMSK : public ModemDigital { +public: + ModemGMSK(); + ~ModemGMSK(); + + std::string getName(); + + Modem *factory(); + + int checkSampleRate(long long sampleRate, int audioSampleRate); + int getDefaultSampleRate(); + + ModemArgInfoList getSettings(); + void writeSetting(std::string setting, std::string value); + std::string readSetting(std::string setting); + + ModemKit *buildKit(long long sampleRate, int audioSampleRate); + void disposeKit(ModemKit *kit); + + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + int _sps; // samples per symbol + int _fdelay; // filter delay + float _ebf; +}; + diff --git a/src/modules/modem/digital/ModemOOK.cpp b/src/modules/modem/digital/ModemOOK.cpp index 7b5d54f..faef9d2 100644 --- a/src/modules/modem/digital/ModemOOK.cpp +++ b/src/modules/modem/digital/ModemOOK.cpp @@ -4,10 +4,6 @@ ModemOOK::ModemOOK() : ModemDigital() { demodOOK = modem_create(LIQUID_MODEM_OOK); } -Modem *ModemOOK::factory() { - return new ModemOOK; -} - ModemOOK::~ModemOOK() { modem_destroy(demodOOK); } @@ -16,6 +12,17 @@ std::string ModemOOK::getName() { return "OOK"; } +Modem *ModemOOK::factory() { + return new ModemOOK; +} + +int ModemOOK::checkSampleRate(long long sampleRate, int audioSampleRate) { + if (sampleRate < 100) { + return 100; + } + return sampleRate; +} + void ModemOOK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitDigital *dkit = (ModemKitDigital *)kit; digitalStart(dkit, demodOOK, input); diff --git a/src/modules/modem/digital/ModemOOK.h b/src/modules/modem/digital/ModemOOK.h index 4266113..0c25001 100644 --- a/src/modules/modem/digital/ModemOOK.h +++ b/src/modules/modem/digital/ModemOOK.h @@ -10,6 +10,8 @@ public: Modem *factory(); + int checkSampleRate(long long sampleRate, int audioSampleRate); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: diff --git a/src/visual/ModeSelectorCanvas.cpp b/src/visual/ModeSelectorCanvas.cpp index 7f57c56..4d00f0a 100644 --- a/src/visual/ModeSelectorCanvas.cpp +++ b/src/visual/ModeSelectorCanvas.cpp @@ -155,6 +155,11 @@ void ModeSelectorCanvas::addChoice(int value, std::string label) { numChoices = selections.size(); } +void ModeSelectorCanvas::addChoice(std::string label) { + selections.push_back(ModeSelectorMode(selections.size()+1, label)); + numChoices = selections.size(); +} + void ModeSelectorCanvas::setSelection(std::string label) { for (int i = 0; i < numChoices; i++) { if (selections[i].label == label) { diff --git a/src/visual/ModeSelectorCanvas.h b/src/visual/ModeSelectorCanvas.h index ca2a524..bdbcc41 100644 --- a/src/visual/ModeSelectorCanvas.h +++ b/src/visual/ModeSelectorCanvas.h @@ -32,6 +32,7 @@ public: void setHelpTip(std::string tip); void addChoice(int value, std::string label); + void addChoice(std::string label); void setSelection(std::string label); std::string getSelectionLabel(); void setSelection(int value); diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 4b3dec3..3594900 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -663,11 +663,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { demod->setFrequency(freq); demod->setDemodulatorType(mgr->getLastDemodulatorType()); - if (int lastDemodBw = mgr->getLastBandwidth(mgr->getLastDemodulatorType())) { - demod->setBandwidth(lastDemodBw); - } else { - demod->setBandwidth(mgr->getLastBandwidth()); - } + demod->setBandwidth(mgr->getLastBandwidth()); demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); demod->setGain(mgr->getLastGain()); @@ -756,11 +752,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { demod = wxGetApp().getDemodMgr().newThread(); demod->setFrequency(freq); demod->setDemodulatorType(mgr->getLastDemodulatorType()); - if (int lastDemodBw = mgr->getLastBandwidth(mgr->getLastDemodulatorType())) { - demod->setBandwidth(lastDemodBw); - } else { - demod->setBandwidth(mgr->getLastBandwidth()); - } + demod->setBandwidth(bw); demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); demod->setGain(mgr->getLastGain()); From 0f8065f48a85c5df54eb5f2a1dc5c87f1ab1a9de Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 1 Dec 2015 00:59:11 -0500 Subject: [PATCH 23/24] FSK tweaks, minimum bandwidth adjust --- src/AppFrame.cpp | 1 + src/demod/DemodulatorMgr.cpp | 4 +-- src/modules/modem/Modem.h | 2 ++ src/modules/modem/ModemAnalog.cpp | 4 +-- src/modules/modem/ModemDigital.cpp | 4 +-- src/modules/modem/analog/ModemLSB.cpp | 4 +-- src/modules/modem/analog/ModemUSB.cpp | 4 +-- src/modules/modem/digital/ModemFSK.cpp | 33 +++++++++++++++---------- src/modules/modem/digital/ModemFSK.h | 5 ++-- src/modules/modem/digital/ModemGMSK.cpp | 4 +-- src/visual/WaterfallCanvas.cpp | 11 +++++---- src/visual/WaterfallCanvas.h | 2 ++ 12 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 82deeac..69cf74e 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -120,6 +120,7 @@ AppFrame::AppFrame() : demodWaterfallCanvas->setup(1024, 128); demodWaterfallCanvas->setView(wxGetApp().getConfig()->getCenterFreq(), 300000); demodWaterfallCanvas->attachSpectrumCanvas(demodSpectrumCanvas); + demodWaterfallCanvas->setMinBandwidth(8000); demodSpectrumCanvas->attachWaterfallCanvas(demodWaterfallCanvas); demodVisuals->Add(demodWaterfallCanvas, 6, wxEXPAND | wxALL, 0); wxGetApp().getDemodSpectrumProcessor()->attachOutput(demodWaterfallCanvas->getVisualDataQueue()); diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index 618c5d0..106d31a 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -173,8 +173,8 @@ int DemodulatorMgr::getLastBandwidth() const { } void DemodulatorMgr::setLastBandwidth(int lastBandwidth) { - if (lastBandwidth < 1500) { - lastBandwidth = 1500; + if (lastBandwidth < MIN_BANDWIDTH) { + lastBandwidth = MIN_BANDWIDTH; } else if (lastBandwidth > wxGetApp().getSampleRate()) { lastBandwidth = wxGetApp().getSampleRate(); } diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h index d9ffb4c..0ce8d46 100644 --- a/src/modules/modem/Modem.h +++ b/src/modules/modem/Modem.h @@ -6,6 +6,8 @@ #include #include +#define MIN_BANDWIDTH 500 + class ModemKit { public: ModemKit() : sampleRate(0), audioSampleRate(0) { diff --git a/src/modules/modem/ModemAnalog.cpp b/src/modules/modem/ModemAnalog.cpp index 77e1957..fc98ad8 100644 --- a/src/modules/modem/ModemAnalog.cpp +++ b/src/modules/modem/ModemAnalog.cpp @@ -9,8 +9,8 @@ std::string ModemAnalog::getType() { } int ModemAnalog::checkSampleRate(long long sampleRate, int audioSampleRate) { - if (sampleRate < 1500) { - return 1500; + if (sampleRate < MIN_BANDWIDTH) { + return MIN_BANDWIDTH; } return sampleRate; } diff --git a/src/modules/modem/ModemDigital.cpp b/src/modules/modem/ModemDigital.cpp index aa8e123..a5ec509 100644 --- a/src/modules/modem/ModemDigital.cpp +++ b/src/modules/modem/ModemDigital.cpp @@ -20,8 +20,8 @@ std::string ModemDigital::getType() { } int ModemDigital::checkSampleRate(long long sampleRate, int audioSampleRate) { - if (sampleRate < 1500) { - return 1500; + if (sampleRate < MIN_BANDWIDTH) { + return MIN_BANDWIDTH; } return sampleRate; } diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp index 7e38f15..31d86a3 100644 --- a/src/modules/modem/analog/ModemLSB.cpp +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -20,8 +20,8 @@ ModemLSB::~ModemLSB() { } int ModemLSB::checkSampleRate(long long sampleRate, int audioSampleRate) { - if (sampleRate < 1500) { - return 1500; + if (sampleRate < MIN_BANDWIDTH) { + return MIN_BANDWIDTH; } if (sampleRate % 2 == 0) { return sampleRate; diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp index be1c9bd..8f3202b 100644 --- a/src/modules/modem/analog/ModemUSB.cpp +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -20,8 +20,8 @@ ModemUSB::~ModemUSB() { } int ModemUSB::checkSampleRate(long long sampleRate, int audioSampleRate) { - if (sampleRate < 1500) { - return 1500; + if (sampleRate < MIN_BANDWIDTH) { + return MIN_BANDWIDTH; } if (sampleRate % 2 == 0) { return sampleRate; diff --git a/src/modules/modem/digital/ModemFSK.cpp b/src/modules/modem/digital/ModemFSK.cpp index f7f856e..9aef453 100644 --- a/src/modules/modem/digital/ModemFSK.cpp +++ b/src/modules/modem/digital/ModemFSK.cpp @@ -5,6 +5,7 @@ ModemFSK::ModemFSK() : ModemDigital() { // DMR defaults? bps = 1; sps = 9600; + bw = 0.45; outStream << std::hex; } @@ -35,6 +36,7 @@ ModemArgInfoList ModemFSK::getSettings() { bpsArg.value = std::to_string(bps); bpsArg.description = "Modem bits-per-symbol"; bpsArg.type = ModemArgInfo::STRING; + bpsArg.units = "bits"; std::vector bpsOpts; bpsOpts.push_back("1"); @@ -51,21 +53,20 @@ ModemArgInfoList ModemFSK::getSettings() { spsArg.name = "Symbols/second"; spsArg.value = std::to_string(sps); spsArg.description = "Modem symbols-per-second"; - spsArg.type = ModemArgInfo::STRING; - + spsArg.type = ModemArgInfo::INT; + spsArg.range = ModemRange(10,115200); std::vector spsOpts; - // some common modem rates ..? - spsOpts.push_back("300"); - spsOpts.push_back("600"); - spsOpts.push_back("1200"); - spsOpts.push_back("2400"); - spsOpts.push_back("4800"); - spsOpts.push_back("9600"); - spsOpts.push_back("19200"); - spsOpts.push_back("38400"); - spsArg.options = spsOpts; args.push_back(spsArg); + + ModemArgInfo bwArg; + bwArg.key = "bw"; + bwArg.name = "Signal bandwidth"; + bwArg.value = std::to_string(bw); + bwArg.description = "Total signal bandwidth"; + bwArg.type = ModemArgInfo::FLOAT; + bwArg.range = ModemRange(0.1,0.49); + args.push_back(bwArg); return args; } @@ -77,6 +78,9 @@ void ModemFSK::writeSetting(std::string setting, std::string value) { } else if (setting == "sps") { sps = std::stoi(value); rebuildKit(); + } else if (setting == "bw") { + bw = std::stof(value); + rebuildKit(); } } @@ -85,6 +89,8 @@ std::string ModemFSK::readSetting(std::string setting) { return std::to_string(bps); } else if (setting == "sps") { return std::to_string(sps); + } else if (setting == "bw") { + return std::to_string(bw); } return ""; } @@ -93,8 +99,9 @@ ModemKit *ModemFSK::buildKit(long long sampleRate, int audioSampleRate) { ModemKitFSK *dkit = new ModemKitFSK; dkit->m = bps; dkit->k = sampleRate / sps; + dkit->bw = bw; - dkit->demodFSK = fskdem_create(dkit->m, dkit->k, 0.45); + dkit->demodFSK = fskdem_create(dkit->m, dkit->k, dkit->bw); dkit->sampleRate = sampleRate; dkit->audioSampleRate = audioSampleRate; diff --git a/src/modules/modem/digital/ModemFSK.h b/src/modules/modem/digital/ModemFSK.h index 03c1d24..332681f 100644 --- a/src/modules/modem/digital/ModemFSK.h +++ b/src/modules/modem/digital/ModemFSK.h @@ -5,6 +5,7 @@ class ModemKitFSK : public ModemKitDigital { public: unsigned int m, k; + float bw; fskdem demodFSK; std::vector inputBuffer; @@ -33,7 +34,7 @@ public: void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: - int sps; - int bps; + int sps, bps; + float bw; }; diff --git a/src/modules/modem/digital/ModemGMSK.cpp b/src/modules/modem/digital/ModemGMSK.cpp index 166641d..9786103 100644 --- a/src/modules/modem/digital/ModemGMSK.cpp +++ b/src/modules/modem/digital/ModemGMSK.cpp @@ -21,8 +21,8 @@ Modem *ModemGMSK::factory() { } int ModemGMSK::checkSampleRate(long long sampleRate, int audioSampleRate) { - if (sampleRate < 1500) { - return 1500; + if (sampleRate < MIN_BANDWIDTH) { + return MIN_BANDWIDTH; } return sampleRate; } diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 3594900..6f4ed05 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -17,8 +17,6 @@ #include -#define MIN_BANDWIDTH 1500 - wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas) EVT_PAINT(WaterfallCanvas::OnPaint) EVT_KEY_DOWN(WaterfallCanvas::OnKeyDown) @@ -44,6 +42,7 @@ WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : preBuf = false; SetCursor(wxCURSOR_CROSS); scaleMove = 0; + minBandwidth = 30000; } WaterfallCanvas::~WaterfallCanvas() { @@ -179,8 +178,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { if (currentZoom < 1) { bw = (long long) ceil((long double) bw * currentZoom); - if (bw < 30000) { - bw = 30000; + if (bw < minBandwidth) { + bw = minBandwidth; } if (mouseInView) { long long mfreqA = getFrequencyAt(mpos); @@ -852,4 +851,6 @@ void WaterfallCanvas::setLinesPerSecond(int lps) { tex_update.unlock(); } - +void WaterfallCanvas::setMinBandwidth(int min) { + minBandwidth = min; +} diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index 093036d..89333f0 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -30,6 +30,7 @@ public: SpectrumVisualDataQueue *getVisualDataQueue(); void setLinesPerSecond(int lps); + void setMinBandwidth(int min); private: void OnPaint(wxPaintEvent& event); @@ -75,6 +76,7 @@ private: double lpsIndex; bool preBuf; std::mutex tex_update; + int minBandwidth; // event table wxDECLARE_EVENT_TABLE(); }; From 7d0c667f3edb8d088621363cb400a224b3d0b1d7 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 1 Dec 2015 22:06:50 -0500 Subject: [PATCH 24/24] MSVC temporary fix-up --- CMakeLists.txt | 24 ++++++++++++++++++++++-- src/CubicSDR.cpp | 2 ++ src/CubicSDR.h | 2 ++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c2c651..1785448 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,16 @@ IF(ENABLE_DIGITAL_LAB) ADD_DEFINITIONS( -DENABLE_DIGITAL_LAB=1 ) +IF(MSVC) + SET (ENABLE_LIQUID_EXPERIMENTAL OFF CACHE BOOL "Enable experimental liquid-dsp features (requires latest liquid-dsp installed)") +ELSE() + SET (ENABLE_LIQUID_EXPERIMENTAL ON CACHE BOOL "Enable experimental liquid-dsp features (requires latest liquid-dsp installed)") +ENDIF() +IF(ENABLE_LIQUID_EXPERIMENTAL) +ADD_DEFINITIONS( + -DENABLE_LIQUID_EXPERIMENTAL=1 +) +ENDIF() ENDIF() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") @@ -296,7 +306,6 @@ IF(ENABLE_DIGITAL_LAB) src/modules/modem/digital/ModemAPSK.cpp src/modules/modem/digital/ModemBPSK.cpp src/modules/modem/digital/ModemDPSK.cpp - src/modules/modem/digital/ModemFSK.cpp src/modules/modem/digital/ModemGMSK.cpp src/modules/modem/digital/ModemPSK.cpp src/modules/modem/digital/ModemOOK.cpp @@ -305,6 +314,12 @@ IF(ENABLE_DIGITAL_LAB) src/modules/modem/digital/ModemQAM.cpp src/modules/modem/digital/ModemQPSK.cpp ) + IF(ENABLE_LIQUID_EXPERIMENTAL) + SET (cubicsdr_sources + ${cubicsdr_sources} + src/modules/modem/digital/ModemFSK.cpp + ) + ENDIF() ENDIF() SET (cubicsdr_headers @@ -402,7 +417,6 @@ SET (cubicsdr_headers src/modules/modem/digital/ModemAPSK.h src/modules/modem/digital/ModemBPSK.h src/modules/modem/digital/ModemDPSK.h - src/modules/modem/digital/ModemFSK.h src/modules/modem/digital/ModemGMSK.h src/modules/modem/digital/ModemPSK.h src/modules/modem/digital/ModemOOK.h @@ -411,6 +425,12 @@ SET (cubicsdr_headers src/modules/modem/digital/ModemQAM.h src/modules/modem/digital/ModemQPSK.h ) +IF(ENABLE_LIQUID_EXPERIMENTAL) + SET (cubicsdr_sources + ${cubicsdr_sources} + src/modules/modem/digital/ModemFSK.h + ) +ENDIF() ENDIF() SET (CUBICSDR_RESOURCES diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index e480765..23eebec 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -177,7 +177,9 @@ bool CubicSDR::OnInit() { Modem::addModemFactory(new ModemASK); Modem::addModemFactory(new ModemBPSK); Modem::addModemFactory(new ModemDPSK); +#if ENABLE_LIQUID_EXPERIMENTAL Modem::addModemFactory(new ModemFSK); +#endif Modem::addModemFactory(new ModemGMSK); Modem::addModemFactory(new ModemOOK); Modem::addModemFactory(new ModemPSK); diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 381b308..5895f6b 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -42,7 +42,9 @@ #include "ModemASK.h" #include "ModemBPSK.h" #include "ModemDPSK.h" +#if ENABLE_LIQUID_EXPERIMENTAL #include "ModemFSK.h" +#endif #include "ModemGMSK.h" #include "ModemOOK.h" #include "ModemPSK.h"