diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d7fea..a09cb5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ cmake_minimum_required (VERSION 2.8) SET(CUBICSDR_VERSION_MAJOR "0") SET(CUBICSDR_VERSION_MINOR "1") -SET(CUBICSDR_VERSION_PATCH "16") -SET(CUBICSDR_VERSION_REL "alpha") +SET(CUBICSDR_VERSION_PATCH "17") +SET(CUBICSDR_VERSION_REL "alpha-demod-refactor") SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}-${CUBICSDR_VERSION_REL}") SET(CPACK_PACKAGE_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}") @@ -234,6 +234,26 @@ SET (cubicsdr_sources src/demod/DemodulatorWorkerThread.cpp src/demod/DemodulatorInstance.cpp src/demod/DemodulatorMgr.cpp + 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 + src/modules/modem/analog/ModemFMStereo.cpp + src/modules/modem/analog/ModemIQ.cpp + src/modules/modem/analog/ModemLSB.cpp + src/modules/modem/analog/ModemUSB.cpp src/audio/AudioThread.cpp src/util/Gradient.cpp src/util/Timer.cpp @@ -293,6 +313,26 @@ SET (cubicsdr_headers src/demod/DemodulatorInstance.h src/demod/DemodulatorMgr.h src/demod/DemodDefs.h + 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 + src/modules/modem/analog/ModemFMStereo.h + src/modules/modem/analog/ModemIQ.h + src/modules/modem/analog/ModemLSB.h + src/modules/modem/analog/ModemUSB.h src/audio/AudioThread.h src/util/Gradient.h src/util/Timer.h @@ -372,6 +412,9 @@ SOURCE_GROUP("Base" REGULAR_EXPRESSION "src/${REG_EXT}") SOURCE_GROUP("Forms\\SDRDevices" REGULAR_EXPRESSION "src/forms/SDRDevices/${REG_EXT}") 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-Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}") 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}") @@ -387,6 +430,10 @@ include_directories ( ${PROJECT_SOURCE_DIR}/src/forms/SDRDevices ${PROJECT_SOURCE_DIR}/src/sdr ${PROJECT_SOURCE_DIR}/src/demod + ${PROJECT_SOURCE_DIR}/src/modules + ${PROJECT_SOURCE_DIR}/src/modules/modem + ${PROJECT_SOURCE_DIR}/src/modules/modem/digital + ${PROJECT_SOURCE_DIR}/src/modules/modem/analog ${PROJECT_SOURCE_DIR}/src/audio ${PROJECT_SOURCE_DIR}/src/util ${PROJECT_SOURCE_DIR}/src/panel diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 51f86ef..6b00c74 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -67,28 +67,29 @@ AppFrame::AppFrame() : gainSpacerItem->Show(false); demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList); - demodModeSelector->addChoice(DEMOD_TYPE_FM, "FM"); - demodModeSelector->addChoice(DEMOD_TYPE_AM, "AM"); - demodModeSelector->addChoice(DEMOD_TYPE_LSB, "LSB"); - demodModeSelector->addChoice(DEMOD_TYPE_USB, "USB"); - demodModeSelector->addChoice(DEMOD_TYPE_DSB, "DSB"); - demodModeSelector->addChoice(DEMOD_TYPE_RAW, "I/Q"); - demodModeSelector->setSelection(DEMOD_TYPE_FM); + 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->setSelection("FM"); demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation, Amplitude Modulation and Lower, Upper or Double Side-Band."); demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0); #ifdef ENABLE_DIGITAL_LAB demodModeSelectorAdv = new ModeSelectorCanvas(this, attribList); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_ASK, "ASK"); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_APSK, "APSK"); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_BPSK, "BPSK"); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_DPSK, "DPSK"); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_PSK, "PSK"); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_OOK, "OOK"); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_ST, "ST"); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_SQAM, "SQAM"); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_QAM, "QAM"); - demodModeSelectorAdv->addChoice(DEMOD_TYPE_QPSK, "QPSK"); + demodModeSelectorAdv->addChoice(0, "ASK"); + demodModeSelectorAdv->addChoice(1, "APSK"); + 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->setHelpTip("Choose advanced modulation types."); demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0); @@ -638,10 +639,9 @@ void AppFrame::OnMenu(wxCommandEvent& event) { } else if (event.GetId() == wxID_RESET) { wxGetApp().getDemodMgr().terminateAll(); wxGetApp().setFrequency(100000000); - wxGetApp().getDemodMgr().setLastDemodulatorType(DEMOD_TYPE_FM); + wxGetApp().getDemodMgr().setLastDemodulatorType("FM"); demodModeSelector->setSelection(1); wxGetApp().getDemodMgr().setLastMuted(false); - wxGetApp().getDemodMgr().setLastStereo(false); wxGetApp().getDemodMgr().setLastBandwidth(DEFAULT_DEMOD_BW); wxGetApp().getDemodMgr().setLastGain(1.0); wxGetApp().getDemodMgr().setLastSquelchLevel(0); @@ -855,7 +855,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { int outputDevice = demod->getOutputDevice(); scopeCanvas->setDeviceName(outputDevices[outputDevice].name); outputDeviceMenuItems[outputDevice]->Check(true); - int dType = demod->getDemodulatorType(); + std::string dType = demod->getDemodulatorType(); demodModeSelector->setSelection(dType); #ifdef ENABLE_DIGITAL_LAB int dCons = demod->getDemodulatorCons(); @@ -868,12 +868,12 @@ void AppFrame::OnIdle(wxIdleEvent& event) { long long centerFreq = demod->getFrequency(); unsigned int demodBw = (unsigned int) ceil((float) demod->getBandwidth() * 2.25); - if (demod->getDemodulatorType() == DEMOD_TYPE_USB) { + if (demod->getDemodulatorType() == "USB") { demodBw /= 2; centerFreq += demod->getBandwidth() / 4; } - if (demod->getDemodulatorType() == DEMOD_TYPE_LSB) { + if (demod->getDemodulatorType() == "LSB") { demodBw /= 2; centerFreq -= demod->getBandwidth() / 4; } @@ -889,18 +889,18 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demodWaterfallCanvas->setCenterFrequency(centerFreq); demodSpectrumCanvas->setCenterFrequency(centerFreq); } - int dSelection = demodModeSelector->getSelection(); + std::string dSelection = demodModeSelector->getSelectionLabel(); #ifdef ENABLE_DIGITAL_LAB - int dSelectionadv = demodModeSelectorAdv->getSelection(); + std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel(); int dSelectionCons = demodModeSelectorCons->getSelection(); // basic demodulators - if (dSelection != -1 && dSelection != demod->getDemodulatorType()) { + if (dSelection != "" && dSelection != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelection); demodModeSelectorAdv->setSelection(-1); } // advanced demodulators - else if (dSelectionadv != -1 && dSelectionadv != demod->getDemodulatorType()) { + else if (dSelectionadv != "" && dSelectionadv != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelectionadv); demodModeSelector->setSelection(-1); } @@ -911,7 +911,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { } #else // basic demodulators - if (dSelection != -1 && dSelection != demod->getDemodulatorType()) { + if (dSelection != "" && dSelection != demod->getDemodulatorType()) { demod->setDemodulatorType(dSelection); } #endif @@ -951,18 +951,18 @@ void AppFrame::OnIdle(wxIdleEvent& event) { } else { DemodulatorMgr *mgr = &wxGetApp().getDemodMgr(); - int dSelection = demodModeSelector->getSelection(); + std::string dSelection = demodModeSelector->getSelectionLabel(); #ifdef ENABLE_DIGITAL_LAB - int dSelectionadv = demodModeSelectorAdv->getSelection(); + std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel(); int dSelectionCons = demodModeSelectorCons->getSelection(); // basic demodulators - if (dSelection != -1 && dSelection != mgr->getLastDemodulatorType()) { + if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) { mgr->setLastDemodulatorType(dSelection); demodModeSelectorAdv->setSelection(-1); } // advanced demodulators - else if(dSelectionadv != -1 && dSelectionadv != mgr->getLastDemodulatorType()) { + else if(dSelectionadv != "" && dSelectionadv != mgr->getLastDemodulatorType()) { mgr->setLastDemodulatorType(dSelectionadv); demodModeSelector->setSelection(-1); } @@ -973,7 +973,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { } #else // basic demodulators - if (dSelection != -1 && dSelection != mgr->getLastDemodulatorType()) { + if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) { mgr->setLastDemodulatorType(dSelection); } #endif @@ -1128,7 +1128,6 @@ void AppFrame::saveSession(std::string fileName) { *demod->newChild("type") = (*instance_i)->getDemodulatorType(); *demod->newChild("squelch_level") = (*instance_i)->getSquelchLevel(); *demod->newChild("squelch_enabled") = (*instance_i)->isSquelchEnabled() ? 1 : 0; - *demod->newChild("stereo") = (*instance_i)->isStereo() ? 1 : 0; *demod->newChild("output_device") = outputDevices[(*instance_i)->getOutputDevice()].name; *demod->newChild("gain") = (*instance_i)->getGain(); *demod->newChild("muted") = (*instance_i)->isMuted() ? 1 : 0; @@ -1175,14 +1174,32 @@ bool AppFrame::loadSession(std::string fileName) { long bandwidth = *demod->getNext("bandwidth"); long long freq = *demod->getNext("frequency"); - int type = demod->hasAnother("type") ? *demod->getNext("type") : DEMOD_TYPE_FM; + 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 stereo = demod->hasAnother("stereo") ? (int) *demod->getNext("stereo") : 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 + DemodulatorInstance *newDemod = wxGetApp().getDemodMgr().newThread(); loadedDemod = newDemod; numDemodulators++; @@ -1196,10 +1213,7 @@ bool AppFrame::loadSession(std::string fileName) { newDemod->setSquelchEnabled(true); newDemod->setSquelchLevel(squelch_level); } - if (stereo) { - newDemod->setStereo(true); - } - + bool found_device = false; std::map::iterator i; for (i = outputDevices.begin(); i != outputDevices.end(); i++) { @@ -1221,7 +1235,6 @@ bool AppFrame::loadSession(std::string fileName) { std::cout << "\t\tBandwidth: " << bandwidth << std::endl; std::cout << "\t\tSquelch Level: " << squelch_level << std::endl; std::cout << "\t\tSquelch Enabled: " << (squelch_enabled ? "true" : "false") << std::endl; - std::cout << "\t\tStereo: " << (stereo ? "true" : "false") << std::endl; std::cout << "\t\tOutput Device: " << output_device << std::endl; } diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 3081026..4227bdf 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -164,6 +164,25 @@ bool CubicSDR::OnInit() { wxApp::SetAppName("CubicSDR"); + Modem::addModemFactory(new ModemFM); + Modem::addModemFactory(new ModemFMStereo); + Modem::addModemFactory(new ModemAM); + Modem::addModemFactory(new ModemLSB); + Modem::addModemFactory(new ModemUSB); + Modem::addModemFactory(new ModemDSB); + Modem::addModemFactory(new ModemIQ); + + Modem::addModemFactory(new ModemAPSK); + Modem::addModemFactory(new ModemASK); + Modem::addModemFactory(new ModemBPSK); + Modem::addModemFactory(new ModemDPSK); + Modem::addModemFactory(new ModemOOK); + Modem::addModemFactory(new ModemPSK); + Modem::addModemFactory(new ModemQAM); + Modem::addModemFactory(new ModemQPSK); + Modem::addModemFactory(new ModemSQAM); + Modem::addModemFactory(new ModemST); + frequency = wxGetApp().getConfig()->getCenterFreq(); offset = 0; ppm = 0; diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 9cba67a..54bb4b0 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -27,6 +27,26 @@ #include "SpectrumVisualProcessor.h" #include "SpectrumVisualDataThread.h" #include "SDRDevices.h" +#include "Modem.h" + +#include "ModemFM.h" +#include "ModemFMStereo.h" +#include "ModemAM.h" +#include "ModemUSB.h" +#include "ModemLSB.h" +#include "ModemDSB.h" +#include "ModemIQ.h" + +#include "ModemAPSK.h" +#include "ModemASK.h" +#include "ModemBPSK.h" +#include "ModemDPSK.h" +#include "ModemOOK.h" +#include "ModemPSK.h" +#include "ModemQAM.h" +#include "ModemQPSK.h" +#include "ModemSQAM.h" +#include "ModemST.h" #include diff --git a/src/CubicSDRDefs.h b/src/CubicSDRDefs.h index 07d7d02..38b2913 100644 --- a/src/CubicSDRDefs.h +++ b/src/CubicSDRDefs.h @@ -30,7 +30,7 @@ const char filePathSeparator = #define DEFAULT_SAMPLE_RATE 2500000 #define DEFAULT_FFT_SIZE 2048 -#define DEFAULT_DEMOD_TYPE 1 +#define DEFAULT_DEMOD_TYPE "FM" #define DEFAULT_DEMOD_BW 200000 #define DEFAULT_WATERFALL_LPS 30 diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index a9a0d48..52f1050 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -7,24 +7,6 @@ #include #include -#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 - #include "IOThread.h" class DemodulatorThread; @@ -62,11 +44,11 @@ public: }; DemodulatorThreadControlCommand() : - cmd(DEMOD_THREAD_CMD_CTL_NULL), demodType(DEMOD_TYPE_NULL) { + cmd(DEMOD_THREAD_CMD_CTL_NULL), demodType("") { } DemodulatorThreadControlCommandEnum cmd; - int demodType; + std::string demodType; }; class DemodulatorThreadIQData: public ReferenceCounter { @@ -93,21 +75,19 @@ public: } }; +class Modem; +class ModemKit; + class DemodulatorThreadPostIQData: public ReferenceCounter { public: std::vector data; long long sampleRate; - msresamp_rrrf audioResampler; - msresamp_rrrf stereoResampler; - double audioResampleRatio; - int audioSampleRate; - - firfilt_rrrf firStereoLeft; - firfilt_rrrf firStereoRight; - iirfilt_crcf iirStereoPilot; + std::string modemType; + Modem *modem; + ModemKit *modemKit; DemodulatorThreadPostIQData() : - sampleRate(0), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(0), audioSampleRate(0), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL) { + sampleRate(0), modem(nullptr), modemKit(nullptr) { } @@ -116,6 +96,7 @@ public: } }; + class DemodulatorThreadAudioData: public ReferenceCounter { public: long long frequency; @@ -151,11 +132,11 @@ public: unsigned int bandwidth; // set equal to disable second stage re-sampling? unsigned int audioSampleRate; - int demodType; + std::string demodType; DemodulatorThreadParameters() : frequency(0), sampleRate(DEFAULT_SAMPLE_RATE), bandwidth(200000), audioSampleRate(0), - demodType(DEMOD_TYPE_FM) { + demodType("FM") { } diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index f5d285a..ecf2383 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -9,7 +9,6 @@ DemodulatorInstance::DemodulatorInstance() : preDemodTerminated.store(true); active.store(false); squelch.store(false); - stereo.store(false); muted.store(false); tracking.store(false); follow.store(false); @@ -34,7 +33,7 @@ DemodulatorInstance::DemodulatorInstance() : pipeAudioData = new AudioThreadInputQueue; threadQueueControl = new DemodulatorThreadControlCommandQueue; - demodulatorThread = new DemodulatorThread(); + demodulatorThread = new DemodulatorThread(this); demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData); demodulatorThread->setInputQueue("ControlQueue",threadQueueControl); demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify); @@ -44,8 +43,7 @@ DemodulatorInstance::DemodulatorInstance() : audioThread->setInputQueue("AudioDataInput", pipeAudioData); audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify); - currentDemodType = demodulatorThread->getDemodulatorType(); - currentDemodCons = demodulatorThread->getDemodulatorCons(); + currentDemodType = demodulatorPreThread->getParams().demodType; } DemodulatorInstance::~DemodulatorInstance() { @@ -74,10 +72,9 @@ void DemodulatorInstance::run() { // } currentFrequency = demodulatorPreThread->getParams().frequency; - currentDemodType = demodulatorThread->getDemodulatorType(); - currentDemodCons = demodulatorThread->getDemodulatorCons(); currentAudioSampleRate = AudioThread::deviceSampleRate[getOutputDevice()]; demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate; + setDemodulatorType(demodulatorPreThread->getParams().demodType); t_Audio = new std::thread(&AudioThread::threadMain, audioThread); @@ -103,6 +100,7 @@ void DemodulatorInstance::run() { t_PreDemod = new std::thread(&DemodulatorPreThread::threadMain, demodulatorPreThread); t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread); #endif + active = true; audioTerminated = demodTerminated = preDemodTerminated = terminated = false; @@ -196,15 +194,6 @@ void DemodulatorInstance::setActive(bool state) { active = state; } -bool DemodulatorInstance::isStereo() { - return stereo; -} - -void DemodulatorInstance::setStereo(bool state) { - stereo = state; - demodulatorThread->setStereo(state); -} - void DemodulatorInstance::squelchAuto() { DemodulatorThreadControlCommand command; command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON; @@ -271,57 +260,69 @@ void DemodulatorInstance::checkBandwidth() { // } } -void DemodulatorInstance::setDemodulatorType(int demod_type_in) { +void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) { currentDemodType = demod_type_in; - if (currentDemodType == DEMOD_TYPE_RAW) { + if (currentDemodType == "I/Q") { if (currentAudioSampleRate) { setBandwidth(currentAudioSampleRate); } else { setBandwidth(AudioThread::deviceSampleRate[getOutputDevice()]); } - } else if (currentDemodType == DEMOD_TYPE_USB || currentDemodType == DEMOD_TYPE_LSB || currentDemodType == DEMOD_TYPE_DSB || currentDemodType == DEMOD_TYPE_AM) { + } else if (currentDemodType == "USB" || currentDemodType == "LSB" || currentDemodType == "DSB" || currentDemodType == "AM") { demodulatorThread->setAGC(false); } else { demodulatorThread->setAGC(true); } setGain(getGain()); + demodulatorPreThread->getParams().demodType = currentDemodType; if (!active) { checkBandwidth(); - demodulatorPreThread->getParams().demodType = currentDemodType; - demodulatorThread->setDemodulatorType(currentDemodType); + demodulatorPreThread->setDemodType(currentDemodType); } else if (demodulatorThread && threadQueueControl) { - DemodulatorThreadControlCommand command; - command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE; - command.demodType = demod_type_in; - checkBandwidth(); - threadQueueControl->push(command); + demodulatorPreThread->setDemodType(currentDemodType); } } -int DemodulatorInstance::getDemodulatorType() { +std::string DemodulatorInstance::getDemodulatorType() { return currentDemodType; } void DemodulatorInstance::setDemodulatorLock(bool demod_lock_in) { - demodulatorThread->setDemodulatorLock(demod_lock_in); + Modem *cModem = demodulatorPreThread->getModem(); + if (cModem && cModem->getType() == "digital") { + ((ModemDigital *)cModem)->setDemodulatorLock(demod_lock_in); + } } int DemodulatorInstance::getDemodulatorLock() { - return demodulatorThread->getDemodulatorLock(); + Modem *cModem = demodulatorPreThread->getModem(); + + if (cModem && cModem->getType() == "digital") { + return ((ModemDigital *)cModem)->getDemodulatorLock(); + } + + return 0; } void DemodulatorInstance::setDemodulatorCons(int demod_cons_in) { - demodulatorThread->setDemodulatorCons(demod_cons_in); + Modem *cModem = demodulatorPreThread->getModem(); + if (cModem && cModem->getType() == "digital") { + ((ModemDigital *)cModem)->setDemodulatorCons(demod_cons_in); + } } int DemodulatorInstance::getDemodulatorCons() { - return demodulatorThread->getDemodulatorCons(); + Modem *cModem = demodulatorPreThread->getModem(); + if (cModem && cModem->getType() == "digital") { + return ((ModemDigital *)cModem)->getDemodulatorCons(); + } + return 0; } void DemodulatorInstance::setBandwidth(int bw) { - if (currentDemodType == DEMOD_TYPE_RAW) { + if (currentDemodType == "I/Q") { if (currentAudioSampleRate) { bw = currentAudioSampleRate; } else { @@ -384,7 +385,7 @@ void DemodulatorInstance::setAudioSampleRate(int sampleRate) { command.llong_value = sampleRate; pipeDemodCommand->push(command); } - if (currentDemodType == DEMOD_TYPE_RAW) { + if (currentDemodType == "I/Q") { setBandwidth(currentAudioSampleRate); } } @@ -400,7 +401,7 @@ int DemodulatorInstance::getAudioSampleRate() { void DemodulatorInstance::setGain(float gain_in) { currentAudioGain = gain_in; - if (currentDemodType == DEMOD_TYPE_RAW) { + if (currentDemodType == "I/Q") { if (gain_in < 0.25) { audioThread->setGain(1.0); demodulatorThread->setAGC(false); diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index 19d3fb6..818d72b 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -7,6 +7,9 @@ #include "DemodulatorThread.h" #include "DemodulatorPreThread.h" +#include "ModemDigital.h" +#include "ModemAnalog.h" + class DemodulatorInstance { public: @@ -39,9 +42,6 @@ public: bool isActive(); void setActive(bool state); - bool isStereo(); - void setStereo(bool state); - void squelchAuto(); bool isSquelchEnabled(); void setSquelchEnabled(bool state); @@ -53,8 +53,8 @@ public: void setOutputDevice(int device_id); int getOutputDevice(); - void setDemodulatorType(int demod_type_in); - int getDemodulatorType(); + void setDemodulatorType(std::string demod_type_in); + std::string getDemodulatorType(); void setDemodulatorLock(bool demod_lock_in); int getDemodulatorLock(); @@ -98,7 +98,7 @@ protected: private: void checkBandwidth(); - + std::atomic label; // std::atomic_bool terminated; // std::atomic_bool demodTerminated; // @@ -106,13 +106,11 @@ private: std::atomic_bool preDemodTerminated; std::atomic_bool active; std::atomic_bool squelch; - std::atomic_bool stereo; std::atomic_bool muted; std::atomic_llong currentFrequency; std::atomic_int currentBandwidth; - std::atomic_int currentDemodType; - std::atomic_int currentDemodCons; + std::string currentDemodType; std::atomic_int currentOutputDevice; std::atomic_int currentAudioSampleRate; std::atomic currentAudioGain; diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index fcc2c1b..9a0ffec 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -7,7 +7,7 @@ DemodulatorMgr::DemodulatorMgr() : activeDemodulator(NULL), lastActiveDemodulator(NULL), activeVisualDemodulator(NULL), lastBandwidth(DEFAULT_DEMOD_BW), lastDemodType( - DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(0), lastGain(1.0), lastStereo(false), lastMuted(false) { + DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(0), lastGain(1.0), lastMuted(false) { } @@ -76,7 +76,7 @@ std::vector *DemodulatorMgr::getDemodulatorsAt(long long long long halfBuffer = bandwidth / 2; - if ((freq <= (freqTest + ((testDemod->getDemodulatorType() != DEMOD_TYPE_LSB)?halfBandwidthTest:0) + halfBuffer)) && (freq >= (freqTest - ((testDemod->getDemodulatorType() != DEMOD_TYPE_USB)?halfBandwidthTest:0) - halfBuffer))) { + if ((freq <= (freqTest + ((testDemod->getDemodulatorType() != "LSB")?halfBandwidthTest:0) + halfBuffer)) && (freq >= (freqTest - ((testDemod->getDemodulatorType() != "USB")?halfBandwidthTest:0) - halfBuffer))) { foundDemods->push_back(testDemod); } } @@ -166,7 +166,6 @@ void DemodulatorMgr::updateLastState() { lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled(); lastSquelch = lastActiveDemodulator->getSquelchLevel(); lastGain = lastActiveDemodulator->getGain(); - lastStereo = lastActiveDemodulator->isStereo(); } } @@ -184,11 +183,11 @@ void DemodulatorMgr::setLastBandwidth(int lastBandwidth) { this->lastBandwidth = lastBandwidth; } -int DemodulatorMgr::getLastDemodulatorType() const { +std::string DemodulatorMgr::getLastDemodulatorType() const { return lastDemodType; } -void DemodulatorMgr::setLastDemodulatorType(int lastDemodType) { +void DemodulatorMgr::setLastDemodulatorType(std::string lastDemodType) { this->lastDemodType = lastDemodType; } @@ -224,15 +223,6 @@ void DemodulatorMgr::setLastSquelchEnabled(bool lastSquelchEnabled) { this->lastSquelchEnabled = lastSquelchEnabled; } -bool DemodulatorMgr::isLastStereo() const { - return lastStereo; -} - -void DemodulatorMgr::setLastStereo(bool lastStereo) { - this->lastStereo = lastStereo; -} - - bool DemodulatorMgr::isLastMuted() const { return lastMuted; } diff --git a/src/demod/DemodulatorMgr.h b/src/demod/DemodulatorMgr.h index 0cfb4ed..c57386a 100644 --- a/src/demod/DemodulatorMgr.h +++ b/src/demod/DemodulatorMgr.h @@ -25,8 +25,8 @@ public: int getLastBandwidth() const; void setLastBandwidth(int lastBandwidth); - int getLastDemodulatorType() const; - void setLastDemodulatorType(int lastDemodType); + std::string getLastDemodulatorType() const; + void setLastDemodulatorType(std::string lastDemodType); int getLastDemodulatorCons() const; void setLastDemodulatorCons(int lastDemodCons); @@ -39,10 +39,7 @@ public: bool isLastSquelchEnabled() const; void setLastSquelchEnabled(bool lastSquelchEnabled); - - bool isLastStereo() const; - void setLastStereo(bool lastStereo); - + bool isLastMuted() const; void setLastMuted(bool lastMuted); @@ -57,11 +54,11 @@ private: DemodulatorInstance *activeVisualDemodulator; int lastBandwidth; - int lastDemodType; + std::string lastDemodType; bool lastDemodLock; int lastDemodCons; bool lastSquelchEnabled; float lastSquelch; float lastGain; - bool lastStereo, lastMuted; + bool lastMuted; }; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index f96dc2c..86bac7f 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -8,7 +8,7 @@ #include "DemodulatorPreThread.h" #include "CubicSDR.h" -DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(1), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL) +DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL) { initialized.store(false); @@ -24,50 +24,14 @@ DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iq } void DemodulatorPreThread::initialize() { - initialized = false; - iqResampleRatio = (double) (params.bandwidth) / (double) params.sampleRate; - audioResampleRatio = (double) (params.audioSampleRate) / (double) params.bandwidth; - float As = 120.0f; // stop-band attenuation [dB] + float As = 60.0f; // stop-band attenuation [dB] iqResampler = msresamp_crcf_create(iqResampleRatio, As); - audioResampler = msresamp_rrrf_create(audioResampleRatio, As); - stereoResampler = msresamp_rrrf_create(audioResampleRatio, As); - // Stereo filters / shifters - double firStereoCutoff = ((double) 16000 / (double) params.audioSampleRate); - float ft = ((double) 1000 / (double) params.audioSampleRate); // filter transition - float mu = 0.0f; // fractional timing offset - - if (firStereoCutoff < 0) { - firStereoCutoff = 0; - } - - if (firStereoCutoff > 0.5) { - firStereoCutoff = 0.5; - } - - unsigned int h_len = estimate_req_filter_len(ft, As); - float *h = new float[h_len]; - liquid_firdes_kaiser(h_len, firStereoCutoff, As, mu, h); - - firStereoLeft = firfilt_rrrf_create(h, h_len); - firStereoRight = firfilt_rrrf_create(h, h_len); - - // stereo pilot filter - float bw = params.bandwidth; - if (bw < 100000.0) { - bw = 100000.0; - } - unsigned int order = 5; // filter order - float f0 = ((double) 19000 / bw); - float fc = ((double) 19500 / bw); - float Ap = 1.0f; - As = 60.0f; - iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As); - - initialized = true; + initialized.store(true); + lastParams = params; } @@ -88,8 +52,6 @@ void DemodulatorPreThread::run() { std::cout << "Demodulator preprocessor thread started.." << std::endl; - t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread); - ReBuffer buffers; iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput"); @@ -99,9 +61,10 @@ void DemodulatorPreThread::run() { std::vector in_buf_data; std::vector out_buf_data; -// liquid_float_complex carrySample; // Keep the stream count even to simplify some demod operations -// bool carrySampleFlag = false; + setDemodType(params.demodType); + t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread); + while (!terminated) { DemodulatorThreadIQData *inp; iqInputQueue->pop(inp); @@ -218,40 +181,11 @@ void DemodulatorPreThread::run() { msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten); resamp->setRefCount(1); - resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten); -// bool uneven = (numWritten % 2 != 0); - -// if (!carrySampleFlag && !uneven) { -// resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten); -// carrySampleFlag = false; -// } else if (!carrySampleFlag && uneven) { -// resamp->data.assign(resampledData.begin(), resampledData.begin() + (numWritten-1)); -// carrySample = resampledData.back(); -// carrySampleFlag = true; -// } else if (carrySampleFlag && uneven) { -// resamp->data.resize(numWritten+1); -// resamp->data[0] = carrySample; -// memcpy(&resamp->data[1],&resampledData[0],sizeof(liquid_float_complex)*numWritten); -// carrySampleFlag = false; -// } else if (carrySampleFlag && !uneven) { -// resamp->data.resize(numWritten); -// resamp->data[0] = carrySample; -// memcpy(&resamp->data[1],&resampledData[0],sizeof(liquid_float_complex)*(numWritten-1)); -// carrySample = resampledData.back(); -// carrySampleFlag = true; -// } - - - - resamp->audioResampleRatio = audioResampleRatio; - resamp->audioResampler = audioResampler; - resamp->audioSampleRate = params.audioSampleRate; - resamp->stereoResampler = stereoResampler; - resamp->firStereoLeft = firStereoLeft; - resamp->firStereoRight = firStereoRight; - resamp->iirStereoPilot = iirStereoPilot; + resamp->modemType = demodType; + resamp->modem = cModem; + resamp->modemKit = cModemKit; resamp->sampleRate = params.bandwidth; iqOutputQueue->push(resamp); @@ -266,35 +200,23 @@ void DemodulatorPreThread::run() { switch (result.cmd) { case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS: - msresamp_crcf_destroy(iqResampler); if (result.iqResampler) { + if (iqResampler) { + msresamp_crcf_destroy(iqResampler); + } iqResampler = result.iqResampler; iqResampleRatio = result.iqResampleRatio; } - if (result.firStereoLeft) { - firStereoLeft = result.firStereoLeft; - } - - if (result.firStereoRight) { - firStereoRight = result.firStereoRight; - } - - if (result.iirStereoPilot) { - iirStereoPilot = result.iirStereoPilot; + if (result.modem != nullptr) { + cModem = result.modem; } - if (result.audioResampler) { - audioResampler = result.audioResampler; - audioResampleRatio = result.audioResamplerRatio; - stereoResampler = result.stereoResampler; + if (result.modemKit != nullptr) { + cModemKit = result.modemKit; } - - if (result.audioSampleRate) { - params.audioSampleRate = result.audioSampleRate; - } - + if (result.bandwidth) { params.bandwidth = result.bandwidth; } @@ -302,6 +224,12 @@ void DemodulatorPreThread::run() { if (result.sampleRate) { params.sampleRate = result.sampleRate; } + + if (result.modemType != "") { + demodType = result.modemType; + params.demodType = result.modemType; + demodTypeChanged.store(false); + } break; default: break; @@ -318,6 +246,31 @@ 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.demodType = demodType; + command.bandwidth = params.bandwidth; + command.audioSampleRate = params.audioSampleRate; + workerQueue->push(command); + demodTypeChanged.store(true); +} + +std::string DemodulatorPreThread::getDemodType() { + if (demodTypeChanged.load()) { + return newDemodType; + } + return demodType; +} + void DemodulatorPreThread::terminate() { terminated = true; DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue @@ -331,3 +284,12 @@ void DemodulatorPreThread::terminate() { delete workerResults; delete workerQueue; } + + +Modem *DemodulatorPreThread::getModem() { + return cModem; +} + +ModemKit *DemodulatorPreThread::getModemKit() { + return cModemKit; +} diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index f3edc41..f339a70 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -15,35 +15,25 @@ public: void run(); - DemodulatorThreadParameters &getParams() { - return params; - } - - void setParams(DemodulatorThreadParameters ¶ms_in) { - params = params_in; - } + DemodulatorThreadParameters &getParams(); + void setParams(DemodulatorThreadParameters ¶ms_in); + + void setDemodType(std::string demodType); + std::string getDemodType(); void initialize(); void terminate(); -#ifdef __APPLE__ - static void *pthread_helper(void *context) { - return ((DemodulatorPreThread *) context)->threadMain(); - } -#endif - + Modem *getModem(); + ModemKit *getModemKit(); + protected: msresamp_crcf iqResampler; double iqResampleRatio; std::vector resampledData; - msresamp_rrrf audioResampler; - msresamp_rrrf stereoResampler; - double audioResampleRatio; - - firfilt_rrrf firStereoLeft; - firfilt_rrrf firStereoRight; - iirfilt_crcf iirStereoPilot; + Modem *cModem; + ModemKit *cModemKit; DemodulatorThreadParameters params; DemodulatorThreadParameters lastParams; @@ -52,6 +42,9 @@ protected: int shiftFrequency; std::atomic_bool initialized; + std::atomic_bool demodTypeChanged; + std::string demodType; + std::string newDemodType; DemodulatorWorkerThread *workerThread; std::thread *t_Worker; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index b46ff03..8047e5a 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -1,5 +1,6 @@ #include "CubicSDRDefs.h" #include "DemodulatorThread.h" +#include "DemodulatorInstance.h" #include #include @@ -11,89 +12,16 @@ #include #endif -DemodulatorThread::DemodulatorThread() : IOThread(), iqAutoGain(NULL), amOutputCeil(1), amOutputCeilMA(1), amOutputCeilMAA(1), audioSampleRate(0), squelchLevel(0), signalLevel(0), squelchEnabled(false), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) { - - stereo.store(false); +DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) : IOThread(), iqAutoGain(NULL), audioSampleRate(0), squelchLevel(0), signalLevel(0), squelchEnabled(false), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) { + + demodInstance = parent; muted.store(false); - agcEnabled.store(false); - demodulatorType.store(DEMOD_TYPE_FM); - - demodFM = freqdem_create(0.5); - demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1); - demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1); - demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1); - demodAM_DSB_CSP = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0); - demodAM = demodAM_DSB_CSP; - - // advanced demodulators - - demodulatorCons.store(2); - currentDemodCons = 0; - - demodASK = demodASK2; - demodASK2 = modem_create(LIQUID_MODEM_ASK2); - demodASK4 = modem_create(LIQUID_MODEM_ASK4); - demodASK8 = modem_create(LIQUID_MODEM_ASK8); - demodASK16 = modem_create(LIQUID_MODEM_ASK16); - demodASK32 = modem_create(LIQUID_MODEM_ASK32); - demodASK64 = modem_create(LIQUID_MODEM_ASK64); - demodASK128 = modem_create(LIQUID_MODEM_ASK128); - demodASK256 = modem_create(LIQUID_MODEM_ASK256); - - demodAPSK = demodAPSK4; - demodAPSK4 = modem_create(LIQUID_MODEM_APSK4); - demodAPSK8 = modem_create(LIQUID_MODEM_APSK8); - demodAPSK16 = modem_create(LIQUID_MODEM_APSK16); - demodAPSK32 = modem_create(LIQUID_MODEM_APSK32); - demodAPSK64 = modem_create(LIQUID_MODEM_APSK64); - demodAPSK128 = modem_create(LIQUID_MODEM_APSK128); - demodAPSK256 = modem_create(LIQUID_MODEM_APSK256); - - demodBPSK = modem_create(LIQUID_MODEM_BPSK); - - demodDPSK = demodDPSK2; - demodDPSK2 = modem_create(LIQUID_MODEM_DPSK2); - demodDPSK4 = modem_create(LIQUID_MODEM_DPSK4); - demodDPSK8 = modem_create(LIQUID_MODEM_DPSK8); - demodDPSK16 = modem_create(LIQUID_MODEM_DPSK16); - demodDPSK32 = modem_create(LIQUID_MODEM_DPSK32); - demodDPSK64 = modem_create(LIQUID_MODEM_DPSK64); - demodDPSK128 = modem_create(LIQUID_MODEM_DPSK128); - demodDPSK256 = modem_create(LIQUID_MODEM_DPSK256); - - demodPSK = demodPSK2; - demodPSK2 = modem_create(LIQUID_MODEM_PSK2); - demodPSK4 = modem_create(LIQUID_MODEM_PSK4); - demodPSK8 = modem_create(LIQUID_MODEM_PSK8); - demodPSK16 = modem_create(LIQUID_MODEM_PSK16); - demodPSK32 = modem_create(LIQUID_MODEM_PSK32); - demodPSK64 = modem_create(LIQUID_MODEM_PSK64); - demodPSK128 = modem_create(LIQUID_MODEM_PSK128); - demodPSK256 = modem_create(LIQUID_MODEM_PSK256); - - demodOOK = modem_create(LIQUID_MODEM_OOK); - - demodSQAM = demodSQAM32; - demodSQAM32 = modem_create(LIQUID_MODEM_SQAM32); - demodSQAM128 = modem_create(LIQUID_MODEM_SQAM128); - - demodST = modem_create(LIQUID_MODEM_V29); - - demodQAM = demodQAM4; - demodQAM4 = modem_create(LIQUID_MODEM_QAM4); - demodQAM8 = modem_create(LIQUID_MODEM_QAM8); - demodQAM16 = modem_create(LIQUID_MODEM_QAM16); - demodQAM32 = modem_create(LIQUID_MODEM_QAM32); - demodQAM64 = modem_create(LIQUID_MODEM_QAM64); - demodQAM128 = modem_create(LIQUID_MODEM_QAM128); - demodQAM256 = modem_create(LIQUID_MODEM_QAM256); - - demodQPSK = modem_create(LIQUID_MODEM_QPSK); - - currentDemodLock = false; + agcEnabled.store(false); } + DemodulatorThread::~DemodulatorThread() { + } void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) { @@ -109,618 +37,104 @@ void DemodulatorThread::run() { sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif - - msresamp_rrrf audioResampler = NULL; - msresamp_rrrf stereoResampler = NULL; - firfilt_rrrf firStereoLeft = NULL; - firfilt_rrrf firStereoRight = NULL; - iirfilt_crcf iirStereoPilot = NULL; - - liquid_float_complex u, v, w, x, y; - - firhilbf firStereoR2C = firhilbf_create(5, 60.0f); - firhilbf firStereoC2R = firhilbf_create(5, 60.0f); - - nco_crcf stereoPilot = nco_crcf_create(LIQUID_VCO); - nco_crcf_reset(stereoPilot); - nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f); - - // half band filter used for side-band elimination - resamp2_crcf ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f); - + // Automatic IQ gain iqAutoGain = agc_crcf_create(); agc_crcf_set_bandwidth(iqAutoGain, 0.1); - + ReBuffer audioVisBuffers; - + std::cout << "Demodulator thread started.." << std::endl; - + iqInputQueue = (DemodulatorThreadPostInputQueue*)getInputQueue("IQDataInput"); audioOutputQueue = (AudioThreadInputQueue*)getOutputQueue("AudioDataOutput"); threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue"); threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); - switch (demodulatorType.load()) { - case DEMOD_TYPE_FM: - break; - case DEMOD_TYPE_LSB: - demodAM = demodAM_LSB; - break; - case DEMOD_TYPE_USB: - demodAM = demodAM_USB; - break; - case DEMOD_TYPE_DSB: - demodAM = demodAM_DSB; - break; - case DEMOD_TYPE_AM: - demodAM = demodAM_DSB_CSP; - break; - } - + ModemIQData modemData; + while (!terminated) { DemodulatorThreadPostIQData *inp; iqInputQueue->pop(inp); -// std::lock_guard < std::mutex > lock(inp->m_mutex); - + // std::lock_guard < std::mutex > lock(inp->m_mutex); + + audioSampleRate = demodInstance->getAudioSampleRate(); + int bufSize = inp->data.size(); - + if (!bufSize) { inp->decRefCount(); continue; } - - if (audioResampler == NULL) { - audioResampler = inp->audioResampler; - stereoResampler = inp->stereoResampler; - firStereoLeft = inp->firStereoLeft; - firStereoRight = inp->firStereoRight; - iirStereoPilot = inp->iirStereoPilot; - audioSampleRate = inp->audioSampleRate; - } else if (audioResampler != inp->audioResampler) { - msresamp_rrrf_destroy(audioResampler); - msresamp_rrrf_destroy(stereoResampler); - audioResampler = inp->audioResampler; - stereoResampler = inp->stereoResampler; - audioSampleRate = inp->audioSampleRate; - - if (demodAM) { - ampmodem_reset(demodAM); + + if (inp->modemKit && inp->modemKit != cModemKit) { + if (cModemKit != nullptr) { + cModem->disposeKit(cModemKit); } - freqdem_reset(demodFM); - nco_crcf_reset(stereoPilot); + cModemKit = inp->modemKit; } - - if (firStereoLeft != inp->firStereoLeft) { - if (firStereoLeft != NULL) { - firfilt_rrrf_destroy(firStereoLeft); - } - firStereoLeft = inp->firStereoLeft; + + if (inp->modem && inp->modem != cModem) { + delete cModem; + cModem = inp->modem; } - - if (firStereoRight != inp->firStereoRight) { - if (firStereoRight != NULL) { - firfilt_rrrf_destroy(firStereoRight); - } - firStereoRight = inp->firStereoRight; + + if (!cModem || !cModemKit) { + inp->decRefCount(); + continue; } - - if (iirStereoPilot != inp->iirStereoPilot) { - if (iirStereoPilot != NULL) { - iirfilt_crcf_destroy(iirStereoPilot); - } - iirStereoPilot = inp->iirStereoPilot; - } - + if (agcData.size() != bufSize) { if (agcData.capacity() < bufSize) { agcData.reserve(bufSize); - agcAMData.reserve(bufSize); } agcData.resize(bufSize); - agcAMData.resize(bufSize); } - - double audio_resample_ratio = inp->audioResampleRatio; - - if (demodOutputData.size() != bufSize) { - if (demodOutputData.capacity() < bufSize) { - demodOutputData.reserve(bufSize); - } - demodOutputData.resize(bufSize); - } - - if (demodOutputDataDigital.size() != bufSize) { - if (demodOutputDataDigital.capacity() < bufSize) { - demodOutputDataDigital.reserve(bufSize); - } - demodOutputDataDigital.resize(bufSize); - } - - int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512; - + agc_crcf_execute_block(iqAutoGain, &(inp->data[0]), bufSize, &agcData[0]); - + float currentSignalLevel = 0; - + currentSignalLevel = ((60.0 / fabs(agc_crcf_get_rssi(iqAutoGain))) / 15.0 - signalLevel); - + if (agc_crcf_get_signal_level(iqAutoGain) > currentSignalLevel) { currentSignalLevel = agc_crcf_get_signal_level(iqAutoGain); } - + std::vector *inputData; - + if (agcEnabled) { - inputData = &agcData; + inputData = &agcData; } else { - inputData = &inp->data; + inputData = &inp->data; } - - // Reset demodulator Constellations & Lock - updateDemodulatorCons(0); - - if (demodulatorType == DEMOD_TYPE_FM) { - currentDemodLock = false; - freqdem_demodulate_block(demodFM, &(*inputData)[0], bufSize, &demodOutputData[0]); - } else if (demodulatorType == DEMOD_TYPE_RAW) { - // do nothing here.. - } else { - switch (demodulatorType.load()) { - case DEMOD_TYPE_LSB: - currentDemodLock = false; - for (int i = 0; i < bufSize; i++) { // Reject upper band - resamp2_crcf_filter_execute(ssbFilt,(*inputData)[i],&x,&y); - ampmodem_demodulate(demodAM, x, &demodOutputData[i]); - } - break; - case DEMOD_TYPE_USB: - currentDemodLock = false; - for (int i = 0; i < bufSize; i++) { // Reject lower band - resamp2_crcf_filter_execute(ssbFilt,(*inputData)[i],&x,&y); - ampmodem_demodulate(demodAM, y, &demodOutputData[i]); - } - break; - case DEMOD_TYPE_AM: - case DEMOD_TYPE_DSB: - currentDemodLock = false; - for (int i = 0; i < bufSize; i++) { - ampmodem_demodulate(demodAM, (*inputData)[i], &demodOutputData[i]); - } - break; - // advanced demodulators - case DEMOD_TYPE_ASK: - - 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; - } - - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodASK, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodASK, 0.005f); - break; - case DEMOD_TYPE_APSK: - - 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; - } - - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodAPSK, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodAPSK, 0.005f); - break; - case DEMOD_TYPE_BPSK: - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodBPSK, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodBPSK, 0.005f); - break; - case DEMOD_TYPE_DPSK: - - 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; - } - - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodDPSK, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodDPSK, 0.005f); - break; - case DEMOD_TYPE_PSK: - - 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; - } - - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodPSK, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodPSK, 0.005f); - break; - case DEMOD_TYPE_OOK: - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodOOK, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodOOK, 0.005f); - break; - case DEMOD_TYPE_SQAM: - - 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; - } - - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodSQAM, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodSQAM, 0.005f); - break; - case DEMOD_TYPE_ST: - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodST, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodST, 0.005f); - break; - case DEMOD_TYPE_QAM: - - 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; - } - - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodQAM, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodQAM, 0.5f); - break; - case DEMOD_TYPE_QPSK: - for (int i = 0; i < bufSize; i++) { - modem_demodulate(demodQPSK, inp->data[i], &demodOutputDataDigital[i]); - } - updateDemodulatorLock(demodQPSK, 0.8f); - break; - } - - amOutputCeilMA = amOutputCeilMA + (amOutputCeil - amOutputCeilMA) * 0.025; - amOutputCeilMAA = amOutputCeilMAA + (amOutputCeilMA - amOutputCeilMAA) * 0.025; - - amOutputCeil = 0; - - for (int i = 0; i < bufSize; i++) { - if (demodOutputData[i] > amOutputCeil) { - amOutputCeil = demodOutputData[i]; - } - } - - float gain = 0.5 / amOutputCeilMAA; - - for (int i = 0; i < bufSize; i++) { - demodOutputData[i] *= gain; - } - } - - if (audio_out_size != resampledOutputData.size()) { - if (resampledOutputData.capacity() < audio_out_size) { - resampledOutputData.reserve(audio_out_size); - } - resampledOutputData.resize(audio_out_size); - } - - unsigned int numAudioWritten; - - if (demodulatorType == DEMOD_TYPE_RAW) { - numAudioWritten = bufSize; - } else { - msresamp_rrrf_execute(audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten); - - if (stereo && inp->sampleRate >= 100000) { - if (demodStereoData.size() != bufSize) { - if (demodStereoData.capacity() < bufSize) { - demodStereoData.reserve(bufSize); - } - demodStereoData.resize(bufSize); - } - + + modemData.sampleRate = inp->sampleRate; + modemData.data.assign(inputData->begin(), inputData->end()); + modemData.setRefCount(1); + + AudioThreadInput *ati = NULL; + + ModemAnalog *modemAnalog = (cModem->getType() == "analog")?((ModemAnalog *)cModem):nullptr; +// ModemDigital *modemDigital = (cModem->getType() == "digital")?((ModemDigital *)cModem):nullptr; + + if (modemAnalog != nullptr) { + ati = outputBuffers.getBuffer(); - float phase_error = 0; - - for (int i = 0; i < bufSize; i++) { - // real -> complex - firhilbf_r2c_execute(firStereoR2C, demodOutputData[i], &x); - - // 19khz pilot band-pass - iirfilt_crcf_execute(iirStereoPilot, x, &v); - nco_crcf_cexpf(stereoPilot, &w); - - w.imag = -w.imag; // conjf(w) - - // multiply u = v * conjf(w) - u.real = v.real * w.real - v.imag * w.imag; - u.imag = v.real * w.imag + v.imag * w.real; - - // cargf(u) - phase_error = atan2f(u.imag,u.real); - - // step pll - nco_crcf_pll_step(stereoPilot, phase_error); - nco_crcf_step(stereoPilot); - - // 38khz down-mix - nco_crcf_mix_down(stereoPilot, x, &y); - nco_crcf_mix_down(stereoPilot, y, &x); - - // complex -> real - firhilbf_c2r_execute(firStereoC2R, x, &demodStereoData[i]); - } - -// std::cout << "[PLL] phase error: " << phase_error; -// std::cout << " freq:" << (((nco_crcf_get_frequency(stereoPilot) / (2.0 * M_PI)) * inp->sampleRate)) << std::endl; - - if (audio_out_size != resampledStereoData.size()) { - if (resampledStereoData.capacity() < audio_out_size) { - resampledStereoData.reserve(audio_out_size); - } - resampledStereoData.resize(audio_out_size); - } - - msresamp_rrrf_execute(stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten); + ati->sampleRate = audioSampleRate; + ati->inputRate = inp->sampleRate; + ati->setRefCount(1); } - } - + cModem->demodulate(cModemKit, &modemData, ati); + if (currentSignalLevel > signalLevel) { signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5; } else { signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05; } - - AudioThreadInput *ati = NULL; - + if (audioOutputQueue != NULL) { - if (!squelchEnabled || (signalLevel >= squelchLevel)) { - - ati = outputBuffers.getBuffer(); - - ati->sampleRate = audioSampleRate; - ati->inputRate = inp->sampleRate; - ati->setRefCount(1); - - if (demodulatorType == DEMOD_TYPE_RAW) { - ati->channels = 2; - if (ati->data.capacity() < (numAudioWritten * 2)) { - ati->data.reserve(numAudioWritten * 2); - } - ati->data.resize(numAudioWritten * 2); - for (int i = 0; i < numAudioWritten; i++) { - ati->data[i * 2] = (*inputData)[i].imag; - ati->data[i * 2 + 1] = (*inputData)[i].real; - } - } else if (stereo && inp->sampleRate >= 100000) { - ati->channels = 2; - if (ati->data.capacity() < (numAudioWritten * 2)) { - ati->data.reserve(numAudioWritten * 2); - } - ati->data.resize(numAudioWritten * 2); - for (int i = 0; i < numAudioWritten; i++) { - float l, r; - - firfilt_rrrf_push(firStereoLeft, 0.568 * (resampledOutputData[i] - (resampledStereoData[i]))); - firfilt_rrrf_execute(firStereoLeft, &l); - - firfilt_rrrf_push(firStereoRight, 0.568 * (resampledOutputData[i] + (resampledStereoData[i]))); - firfilt_rrrf_execute(firStereoRight, &r); - - ati->data[i * 2] = l; - ati->data[i * 2 + 1] = r; - } - } else { - ati->channels = 1; - ati->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + numAudioWritten); - } - + if (ati && (!squelchEnabled || (signalLevel >= squelchLevel))) { std::vector::iterator data_i; ati->peak = 0; for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) { @@ -731,24 +145,24 @@ void DemodulatorThread::run() { } } } - + if (ati && audioVisOutputQueue != NULL && audioVisOutputQueue->empty()) { - AudioThreadInput *ati_vis = audioVisBuffers.getBuffer(); - ati_vis->setRefCount(1); + AudioThreadInput *ati_vis = audioVisBuffers.getBuffer(); + ati_vis->setRefCount(1); ati_vis->sampleRate = inp->sampleRate; ati_vis->inputRate = inp->sampleRate; int num_vis = DEMOD_VIS_SIZE; - if (demodulatorType == DEMOD_TYPE_RAW || (stereo && inp->sampleRate >= 100000)) { + if (ati->channels==2) { ati_vis->channels = 2; int stereoSize = ati->data.size(); if (stereoSize > DEMOD_VIS_SIZE * 2) { stereoSize = DEMOD_VIS_SIZE * 2; } - + ati_vis->data.resize(stereoSize); - - if (demodulatorType == DEMOD_TYPE_RAW) { + + if (inp->modemType == "I/Q") { for (int i = 0; i < stereoSize / 2; i++) { ati_vis->data[i] = agcData[i].real * 0.75; ati_vis->data[i + stereoSize / 2] = agcData[i].imag * 0.75; @@ -762,26 +176,29 @@ void DemodulatorThread::run() { } } } else { + int numAudioWritten = ati->data.size(); ati_vis->channels = 1; - if (numAudioWritten > bufSize) { + std::vector *demodOutData = (modemAnalog != nullptr)?modemAnalog->getDemodOutputData():nullptr; + if ((numAudioWritten > bufSize) || (demodOutData == nullptr)) { ati_vis->inputRate = audioSampleRate; if (num_vis > numAudioWritten) { num_vis = numAudioWritten; } - ati_vis->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + num_vis); + ati_vis->data.assign(ati->data.begin(), ati->data.begin() + num_vis); } else { - if (num_vis > bufSize) { - num_vis = bufSize; + if (num_vis > demodOutData->size()) { + num_vis = demodOutData->size(); } - ati_vis->data.assign(demodOutputData.begin(), demodOutputData.begin() + num_vis); + ati_vis->data.assign(demodOutData->begin(), demodOutData->begin() + num_vis); } - -// std::cout << "Signal: " << agc_crcf_get_signal_level(agc) << " -- " << agc_crcf_get_rssi(agc) << "dB " << std::endl; + + // std::cout << "Signal: " << agc_crcf_get_signal_level(agc) << " -- " << agc_crcf_get_rssi(agc) << "dB " << std::endl; } - + audioVisOutputQueue->push(ati_vis); } - + + if (ati != NULL) { if (!muted.load()) { audioOutputQueue->push(ati); @@ -789,124 +206,37 @@ void DemodulatorThread::run() { ati->setRefCount(0); } } - + if (!threadQueueControl->empty()) { - int newDemodType = DEMOD_TYPE_NULL; - while (!threadQueueControl->empty()) { DemodulatorThreadControlCommand command; threadQueueControl->pop(command); - + switch (command.cmd) { - case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON: - squelchEnabled = true; - break; - case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF: - squelchEnabled = false; - break; - case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE: - newDemodType = command.demodType; - break; - default: - break; + case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON: + squelchEnabled = true; + break; + case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF: + squelchEnabled = false; + break; + default: + break; } } - - if (newDemodType != DEMOD_TYPE_NULL) { - switch (newDemodType) { - case DEMOD_TYPE_FM: - freqdem_reset(demodFM); - break; - case DEMOD_TYPE_LSB: - demodAM = demodAM_LSB; - ampmodem_reset(demodAM); - break; - case DEMOD_TYPE_USB: - demodAM = demodAM_USB; - ampmodem_reset(demodAM); - break; - case DEMOD_TYPE_DSB: - demodAM = demodAM_DSB; - ampmodem_reset(demodAM); - break; - case DEMOD_TYPE_AM: - demodAM = demodAM_DSB_CSP; - ampmodem_reset(demodAM); - break; - case DEMOD_TYPE_ASK: - //modem_reset(demodASK); - break; - case DEMOD_TYPE_APSK: - //modem_reset(demodAPSK); - break; - case DEMOD_TYPE_BPSK: - //modem_reset(demodBPSK); - break; - case DEMOD_TYPE_DPSK: - //modem_reset(demodDPSK); - break; - case DEMOD_TYPE_PSK: - //modem_reset(demodPSK); - break; - case DEMOD_TYPE_OOK: - //modem_reset(demodOOK); - break; - case DEMOD_TYPE_SQAM: - //modem_reset(demodSQAM); - break; - case DEMOD_TYPE_ST: - //modem_reset(demodST); - break; - case DEMOD_TYPE_QAM: - //modem_reset(demodQAM); - break; - case DEMOD_TYPE_QPSK: - //modem_reset(demodQPSK); - break; - default: - // empty default to prevent exceptions - break; - } - demodulatorType = newDemodType; - } } - - demodOutputDataDigital.empty(); - + inp->decRefCount(); } - // end while !terminated - - if (audioResampler != NULL) { - msresamp_rrrf_destroy(audioResampler); - } - if (stereoResampler != NULL) { - msresamp_rrrf_destroy(stereoResampler); - } - if (firStereoLeft != NULL) { - firfilt_rrrf_destroy(firStereoLeft); - } - if (firStereoRight != NULL) { - firfilt_rrrf_destroy(firStereoRight); - } - if (iirStereoPilot != NULL) { - iirfilt_crcf_destroy(iirStereoPilot); - } - - agc_crcf_destroy(iqAutoGain); - firhilbf_destroy(firStereoR2C); - firhilbf_destroy(firStereoC2R); - nco_crcf_destroy(stereoPilot); - resamp2_crcf_destroy(ssbFilt); - + // end while !terminated + outputBuffers.purge(); - + if (audioVisOutputQueue && !audioVisOutputQueue->empty()) { AudioThreadInput *dummy_vis; audioVisOutputQueue->pop(dummy_vis); } - audioVisBuffers.purge(); - + audioVisBuffers.purge(); + DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); @@ -920,15 +250,6 @@ void DemodulatorThread::terminate() { iqInputQueue->push(inp); } -void DemodulatorThread::setStereo(bool state) { - stereo.store(state); - std::cout << "Stereo " << (state ? "Enabled" : "Disabled") << std::endl; -} - -bool DemodulatorThread::isStereo() { - return stereo.load(); -} - bool DemodulatorThread::isMuted() { return muted.load(); } @@ -938,14 +259,13 @@ void DemodulatorThread::setMuted(bool muted) { } void DemodulatorThread::setAGC(bool state) { - agcEnabled.store(state); + agcEnabled.store(state); } bool DemodulatorThread::getAGC() { - return agcEnabled.load(); + return agcEnabled.load(); } - float DemodulatorThread::getSignalLevel() { return signalLevel.load(); } @@ -960,37 +280,3 @@ void DemodulatorThread::setSquelchLevel(float signal_level_in) { float DemodulatorThread::getSquelchLevel() { return squelchLevel; } - -void DemodulatorThread::setDemodulatorType(int demod_type_in) { - demodulatorType = demod_type_in; -} - -int DemodulatorThread::getDemodulatorType() { - return demodulatorType; -} - -void DemodulatorThread::setDemodulatorLock(bool demod_lock_in) { - demod_lock_in ? currentDemodLock = true : currentDemodLock = false; -} - -int DemodulatorThread::getDemodulatorLock() { - return currentDemodLock; -} - -void DemodulatorThread::setDemodulatorCons(int demod_cons_in) { - demodulatorCons.store(demod_cons_in); -} - -int DemodulatorThread::getDemodulatorCons() { - return currentDemodCons; -} - -void DemodulatorThread::updateDemodulatorLock(modem demod, float sensitivity) { - modem_get_demodulator_evm(demod) <= sensitivity ? setDemodulatorLock(true) : setDemodulatorLock(false); -} - -void DemodulatorThread::updateDemodulatorCons(int Cons) { - if (currentDemodCons != Cons) { - currentDemodCons = Cons; - } -} diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 891849f..4cbc2ef 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -5,25 +5,24 @@ #include "DemodDefs.h" #include "AudioThread.h" +#include "Modem.h" typedef ThreadQueue DemodulatorThreadOutputQueue; #define DEMOD_VIS_SIZE 2048 +class DemodulatorInstance; class DemodulatorThread : public IOThread { public: - DemodulatorThread(); + DemodulatorThread(DemodulatorInstance *parent); ~DemodulatorThread(); void onBindOutput(std::string name, ThreadQueueBase *threadQueue); void run(); void terminate(); - - void setStereo(bool state); - bool isStereo(); - + void setAGC(bool state); bool getAGC(); @@ -34,126 +33,25 @@ public: void setSquelchLevel(float signal_level_in); float getSquelchLevel(); - void setDemodulatorType(int demod_type_in); - int getDemodulatorType(); - - void setDemodulatorLock(bool demod_lock_in); - int getDemodulatorLock(); - - void setDemodulatorCons(int demod_cons_in); - int getDemodulatorCons(); - -#ifdef __APPLE__ - static void *pthread_helper(void *context) { - return ((DemodulatorThread *) context)->threadMain(); - } -#endif - protected: + DemodulatorInstance *demodInstance; ReBuffer outputBuffers; std::vector agcData; - std::vector agcAMData; - std::vector demodOutputData; - std::vector demodStereoData; - std::vector resampledOutputData; - std::vector resampledStereoData; - std::vector demodOutputDataDigital; - //std::vector demodOutputDataDigitalTest; - - //std::vector demodOutputSoftbits; - //std::vector demodOutputSoftbitsTest; - - freqdem demodFM; - ampmodem demodAM; - ampmodem demodAM_DSB_CSP; - ampmodem demodAM_DSB; - ampmodem demodAM_LSB; - ampmodem demodAM_USB; - - modem demodASK; - modem demodASK2; - modem demodASK4; - modem demodASK8; - modem demodASK16; - modem demodASK32; - modem demodASK64; - modem demodASK128; - modem demodASK256; - - modem demodAPSK; - modem demodAPSK4; - modem demodAPSK8; - modem demodAPSK16; - modem demodAPSK32; - modem demodAPSK64; - modem demodAPSK128; - modem demodAPSK256; - - modem demodBPSK; - - modem demodDPSK; - modem demodDPSK2; - modem demodDPSK4; - modem demodDPSK8; - modem demodDPSK16; - modem demodDPSK32; - modem demodDPSK64; - modem demodDPSK128; - modem demodDPSK256; - - modem demodPSK; - modem demodPSK2; - modem demodPSK4; - modem demodPSK8; - modem demodPSK16; - modem demodPSK32; - modem demodPSK64; - modem demodPSK128; - modem demodPSK256; - - modem demodOOK; - - modem demodSQAM; - modem demodSQAM32; - modem demodSQAM128; - - modem demodST; - - modem demodQAM; - modem demodQAM4; - modem demodQAM8; - modem demodQAM16; - modem demodQAM32; - modem demodQAM64; - modem demodQAM128; - modem demodQAM256; - - modem demodQPSK; agc_crcf iqAutoGain; - float amOutputCeil; - float amOutputCeilMA; - float amOutputCeilMAA; - - std::atomic_bool stereo; std::atomic_bool muted; std::atomic_bool agcEnabled; - std::atomic_int demodulatorType; - std::atomic_int demodulatorCons; int audioSampleRate; std::atomic squelchLevel; std::atomic signalLevel; bool squelchEnabled; - bool currentDemodLock; - int currentDemodCons; - - void updateDemodulatorCons(int Cons); - void updateDemodulatorLock(modem demod, float sensitivity); - + Modem *cModem; + ModemKit *cModemKit; + DemodulatorThreadPostInputQueue* iqInputQueue; AudioThreadInputQueue *audioOutputQueue; DemodulatorThreadOutputQueue* audioVisOutputQueue; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index c9c5761..4e63ca5 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -3,7 +3,7 @@ #include DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(), - commandQueue(NULL), resultQueue(NULL) { + commandQueue(NULL), resultQueue(NULL), cModem(nullptr), cModemKit(nullptr) { } DemodulatorWorkerThread::~DemodulatorWorkerThread() { @@ -18,7 +18,8 @@ void DemodulatorWorkerThread::run() { while (!terminated) { bool filterChanged = false; - DemodulatorWorkerThreadCommand filterCommand; + bool makeDemod = false; + DemodulatorWorkerThreadCommand filterCommand, demodCommand; DemodulatorWorkerThreadCommand command; bool done = false; @@ -29,6 +30,10 @@ void DemodulatorWorkerThread::run() { filterChanged = true; filterCommand = command; break; + case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD: + makeDemod = true; + demodCommand = command; + break; default: break; } @@ -36,7 +41,7 @@ void DemodulatorWorkerThread::run() { } - if (filterChanged && !terminated) { + if ((makeDemod || filterChanged) && !terminated) { DemodulatorWorkerThreadResult result(DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS); float As = 60.0f; // stop-band attenuation [dB] @@ -46,45 +51,22 @@ void DemodulatorWorkerThread::run() { result.iqResampler = msresamp_crcf_create(result.iqResampleRatio, As); } - if (filterCommand.bandwidth && filterCommand.audioSampleRate) { - result.audioResamplerRatio = (double) (filterCommand.audioSampleRate) / (double) filterCommand.bandwidth; - result.audioResampler = msresamp_rrrf_create(result.audioResamplerRatio, As); - result.stereoResampler = msresamp_rrrf_create(result.audioResamplerRatio, As); - result.audioSampleRate = filterCommand.audioSampleRate; - - // Stereo filters / shifters - double firStereoCutoff = ((double) 16000 / (double) filterCommand.audioSampleRate); - float ft = ((double) 1000 / (double) filterCommand.audioSampleRate); // filter transition - float mu = 0.0f; // fractional timing offset - - if (firStereoCutoff < 0) { - firStereoCutoff = 0; - } - - if (firStereoCutoff > 0.5) { - firStereoCutoff = 0.5; - } - - unsigned int h_len = estimate_req_filter_len(ft, As); - float *h = new float[h_len]; - liquid_firdes_kaiser(h_len, firStereoCutoff, As, mu, h); - - result.firStereoLeft = firfilt_rrrf_create(h, h_len); - result.firStereoRight = firfilt_rrrf_create(h, h_len); - - float bw = filterCommand.bandwidth; - if (bw < 100000.0) { - bw = 100000.0; - } - // stereo pilot filter - unsigned int order = 5; // filter order - float f0 = ((double) 19000 / bw); - float fc = ((double) 19500 / bw); - float Ap = 1.0f; - As = 60.0f; - - result.iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As); + if (makeDemod) { + cModem = Modem::makeModem(demodCommand.demodType); + cModemType = demodCommand.demodType; } + result.modem = cModem; + + if (makeDemod && demodCommand.bandwidth && demodCommand.audioSampleRate) { + if (cModem != nullptr) { + cModemKit = cModem->buildKit(demodCommand.bandwidth, demodCommand.audioSampleRate); + } else { + cModemKit = nullptr; + } + } else if (makeDemod) { + cModemKit = nullptr; + } + result.modemKit = cModemKit; if (filterCommand.bandwidth) { result.bandwidth = filterCommand.bandwidth; @@ -94,6 +76,8 @@ void DemodulatorWorkerThread::run() { result.sampleRate = filterCommand.sampleRate; } + result.modemType = cModemType; + resultQueue->push(result); } diff --git a/src/demod/DemodulatorWorkerThread.h b/src/demod/DemodulatorWorkerThread.h index 490ed5d..5455a5f 100644 --- a/src/demod/DemodulatorWorkerThread.h +++ b/src/demod/DemodulatorWorkerThread.h @@ -7,6 +7,7 @@ #include "AudioThread.h" #include "ThreadQueue.h" #include "CubicSDRDefs.h" +#include "Modem.h" class DemodulatorWorkerThreadResult { public: @@ -15,8 +16,7 @@ public: }; DemodulatorWorkerThreadResult() : - cmd(DEMOD_WORKER_THREAD_RESULT_NULL), iqResampler(NULL), iqResampleRatio(0), audioResampler(NULL), stereoResampler(NULL), audioResamplerRatio( - 0), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL), sampleRate(0), bandwidth(0), audioSampleRate(0) { + cmd(DEMOD_WORKER_THREAD_RESULT_NULL), iqResampler(nullptr), iqResampleRatio(0), sampleRate(0), bandwidth(0), modemKit(nullptr), modemType("") { } @@ -29,33 +29,29 @@ public: msresamp_crcf iqResampler; double iqResampleRatio; - msresamp_rrrf audioResampler; - msresamp_rrrf stereoResampler; - double audioResamplerRatio; - - firfilt_rrrf firStereoLeft; - firfilt_rrrf firStereoRight; - iirfilt_crcf iirStereoPilot; + + DemodulatorThread *demodThread; long long sampleRate; unsigned int bandwidth; - unsigned int audioSampleRate; - + Modem *modem; + ModemKit *modemKit; + std::string modemType; }; class DemodulatorWorkerThreadCommand { public: enum DemodulatorThreadCommandEnum { - DEMOD_WORKER_THREAD_CMD_NULL, DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS + DEMOD_WORKER_THREAD_CMD_NULL, DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS, DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD }; DemodulatorWorkerThreadCommand() : - cmd(DEMOD_WORKER_THREAD_CMD_NULL), frequency(0), sampleRate(0), bandwidth(0), audioSampleRate(0) { + cmd(DEMOD_WORKER_THREAD_CMD_NULL), frequency(0), sampleRate(0), bandwidth(0), audioSampleRate(0), demodType("") { } DemodulatorWorkerThreadCommand(DemodulatorThreadCommandEnum cmd) : - cmd(cmd), frequency(0), sampleRate(0), bandwidth(0), audioSampleRate(0) { + cmd(cmd), frequency(0), sampleRate(0), bandwidth(0), audioSampleRate(0), demodType("") { } @@ -65,6 +61,7 @@ public: long long sampleRate; unsigned int bandwidth; unsigned int audioSampleRate; + std::string demodType; }; typedef ThreadQueue DemodulatorThreadWorkerCommandQueue; @@ -92,4 +89,7 @@ protected: DemodulatorThreadWorkerCommandQueue *commandQueue; DemodulatorThreadWorkerResultQueue *resultQueue; + Modem *cModem; + ModemKit *cModemKit; + std::string cModemType; }; diff --git a/src/modules/modem/Modem.cpp b/src/modules/modem/Modem.cpp new file mode 100644 index 0000000..8a1ff0e --- /dev/null +++ b/src/modules/modem/Modem.cpp @@ -0,0 +1,27 @@ +#include "Modem.h" + +ModemFactoryList Modem::modemFactories; + +void Modem::addModemFactory(Modem *factorySingle) { + modemFactories[factorySingle->getName()] = factorySingle; +} + +ModemFactoryList Modem::getFactories() { + return modemFactories; +} + +Modem *Modem::makeModem(std::string modemType) { + if (modemFactories.find(modemType) != modemFactories.end()) { + return modemFactories[modemType]->factory(); + } + + return nullptr; +} + +Modem::Modem() { + +} + +Modem::~Modem() { + +} diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h new file mode 100644 index 0000000..035bbe4 --- /dev/null +++ b/src/modules/modem/Modem.h @@ -0,0 +1,52 @@ +#pragma once + +#include "liquid/liquid.h" +#include "IOThread.h" +#include "AudioThread.h" +#include + +class ModemKit { +public: + ModemKit() : sampleRate(0), audioSampleRate(0) { + + } + + long long sampleRate; + int audioSampleRate; +}; + +class ModemIQData: public ReferenceCounter { +public: + std::vector data; + long long sampleRate; + + ModemIQData() : sampleRate(0) { + + } + + ~ModemIQData() { + std::lock_guard < std::mutex > lock(m_mutex); + } +}; + +class Modem; +typedef std::map ModemFactoryList; + +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(); + virtual ~Modem(); + + 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/ModemAnalog.cpp b/src/modules/modem/ModemAnalog.cpp new file mode 100644 index 0000000..eed8d5c --- /dev/null +++ b/src/modules/modem/ModemAnalog.cpp @@ -0,0 +1,91 @@ +#include "ModemAnalog.h" + +ModemAnalog::ModemAnalog() : aOutputCeil(1), aOutputCeilMA(1), aOutputCeilMAA(1) { + +} + +std::string ModemAnalog::getType() { + return "analog"; +} + +ModemKit *ModemAnalog::buildKit(long long sampleRate, int audioSampleRate) { + ModemKitAnalog *akit = new ModemKitAnalog; + + // stop-band attenuation [dB] + float As = 60.0f; + + akit->sampleRate = sampleRate; + akit->audioSampleRate = audioSampleRate; + akit->audioResampleRatio = double(audioSampleRate) / double(sampleRate); + akit->audioResampler = msresamp_rrrf_create(akit->audioResampleRatio, As); + + return akit; +} + +void ModemAnalog::disposeKit(ModemKit *kit) { + ModemKitAnalog *akit = (ModemKitAnalog *)kit; + + msresamp_rrrf_destroy(akit->audioResampler); + delete akit; +} + +void ModemAnalog::initOutputBuffers(ModemKitAnalog *akit, ModemIQData *input) { + bufSize = input->data.size(); + + if (!bufSize) { + return; + } + + double audio_resample_ratio = akit->audioResampleRatio; + + int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512; + + if (demodOutputData.size() != bufSize) { + if (demodOutputData.capacity() < bufSize) { + demodOutputData.reserve(bufSize); + } + demodOutputData.resize(bufSize); + } + if (resampledOutputData.size() != audio_out_size) { + if (resampledOutputData.capacity() < audio_out_size) { + resampledOutputData.reserve(audio_out_size); + } + resampledOutputData.resize(audio_out_size); + } +} + +void ModemAnalog::buildAudioOutput(ModemKitAnalog *akit, AudioThreadInput *audioOut, bool autoGain) { + unsigned int numAudioWritten; + + if (autoGain) { + aOutputCeilMA = aOutputCeilMA + (aOutputCeil - aOutputCeilMA) * 0.025; + aOutputCeilMAA = aOutputCeilMAA + (aOutputCeilMA - aOutputCeilMAA) * 0.025; + aOutputCeil = 0; + + for (int i = 0; i < bufSize; i++) { + if (demodOutputData[i] > aOutputCeil) { + aOutputCeil = demodOutputData[i]; + } + } + + float gain = 0.5 / aOutputCeilMAA; + + for (int i = 0; i < bufSize; i++) { + demodOutputData[i] *= gain; + } + } + + msresamp_rrrf_execute(akit->audioResampler, &demodOutputData[0], demodOutputData.size(), &resampledOutputData[0], &numAudioWritten); + + audioOut->channels = 1; + audioOut->sampleRate = akit->audioSampleRate; + audioOut->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + numAudioWritten); +} + +std::vector *ModemAnalog::getDemodOutputData() { + return &demodOutputData; +} + +std::vector *ModemAnalog::getResampledOutputData() { + return &resampledOutputData; +} diff --git a/src/modules/modem/ModemAnalog.h b/src/modules/modem/ModemAnalog.h new file mode 100644 index 0000000..f73a933 --- /dev/null +++ b/src/modules/modem/ModemAnalog.h @@ -0,0 +1,33 @@ +#pragma once +#include "Modem.h" + +class ModemKitAnalog : public ModemKit { +public: + ModemKitAnalog() : ModemKit(), audioResampler(nullptr), audioResampleRatio(0) { + + }; + + msresamp_rrrf audioResampler; + double audioResampleRatio; +}; + + +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(); +protected: + int bufSize; + std::vector demodOutputData; + std::vector resampledOutputData; + + float aOutputCeil; + float aOutputCeilMA; + float aOutputCeilMAA; +}; \ No newline at end of file diff --git a/src/modules/modem/ModemDigital.cpp b/src/modules/modem/ModemDigital.cpp new file mode 100644 index 0000000..6c2224d --- /dev/null +++ b/src/modules/modem/ModemDigital.cpp @@ -0,0 +1,71 @@ +#include "ModemDigital.h" + +ModemDigital::ModemDigital() { + +} + +std::string ModemDigital::getType() { + return "digital"; +} + +ModemKit *ModemDigital::buildKit(long long sampleRate, int audioSampleRate) { + ModemKitDigital *dkit = new ModemKitDigital; + + dkit->sampleRate = sampleRate; + dkit->audioSampleRate = audioSampleRate; + + return dkit; +} + +void ModemDigital::disposeKit(ModemKit *kit) { + ModemKitDigital *dkit = (ModemKitDigital *)kit; + + delete dkit; +} + +void ModemDigital::setDemodulatorLock(bool demod_lock_in) { + currentDemodLock.store(demod_lock_in); +} + +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(); + + if (demodOutputDataDigital.size() != bufSize) { + if (demodOutputDataDigital.capacity() < bufSize) { + demodOutputDataDigital.reserve(bufSize); + } + demodOutputDataDigital.resize(bufSize); + } + + if (demodulatorCons.load() != currentDemodCons.load()) { + updateDemodulatorCons(demodulatorCons.load()); + currentDemodLock.store(false); + } +} + +void ModemDigital::digitalFinish(ModemKitDigital *kit, modem mod) { + demodOutputDataDigital.empty(); +} + diff --git a/src/modules/modem/ModemDigital.h b/src/modules/modem/ModemDigital.h new file mode 100644 index 0000000..34a119b --- /dev/null +++ b/src/modules/modem/ModemDigital.h @@ -0,0 +1,39 @@ +#pragma once +#include "Modem.h" + +class ModemKitDigital : public ModemKit { +public: + ModemKitDigital() : ModemKit() { + + }; +}; + + +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 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; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemAM.cpp b/src/modules/modem/analog/ModemAM.cpp new file mode 100644 index 0000000..678832e --- /dev/null +++ b/src/modules/modem/analog/ModemAM.cpp @@ -0,0 +1,30 @@ +#include "ModemAM.h" + +ModemAM::ModemAM() { + demodAM = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0); +} + +Modem *ModemAM::factory() { + return new ModemAM; +} + +std::string ModemAM::getName() { + return "AM"; +} + +void ModemAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitAnalog *amkit = (ModemKitAnalog *)kit; + + initOutputBuffers(amkit,input); + + if (!bufSize) { + input->decRefCount(); + return; + } + + for (int i = 0; i < bufSize; i++) { + ampmodem_demodulate(demodAM, input->data[i], &demodOutputData[i]); + } + + buildAudioOutput(amkit,audioOut,true); +} diff --git a/src/modules/modem/analog/ModemAM.h b/src/modules/modem/analog/ModemAM.h new file mode 100644 index 0000000..8a1d017 --- /dev/null +++ b/src/modules/modem/analog/ModemAM.h @@ -0,0 +1,14 @@ +#pragma once +#include "Modem.h" +#include "ModemAnalog.h" + +class ModemAM : public ModemAnalog { +public: + ModemAM(); + std::string getName(); + Modem *factory(); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + ampmodem demodAM; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemDSB.cpp b/src/modules/modem/analog/ModemDSB.cpp new file mode 100644 index 0000000..c343425 --- /dev/null +++ b/src/modules/modem/analog/ModemDSB.cpp @@ -0,0 +1,30 @@ +#include "ModemDSB.h" + +ModemDSB::ModemDSB() { + demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1); +} + +Modem *ModemDSB::factory() { + return new ModemDSB; +} + +std::string ModemDSB::getName() { + return "DSB"; +} + +void ModemDSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitAnalog *amkit = (ModemKitAnalog *)kit; + + initOutputBuffers(amkit, input); + + if (!bufSize) { + input->decRefCount(); + return; + } + + for (int i = 0; i < bufSize; i++) { + ampmodem_demodulate(demodAM_DSB, input->data[i], &demodOutputData[i]); + } + + buildAudioOutput(amkit, audioOut, true); +} diff --git a/src/modules/modem/analog/ModemDSB.h b/src/modules/modem/analog/ModemDSB.h new file mode 100644 index 0000000..fc0e550 --- /dev/null +++ b/src/modules/modem/analog/ModemDSB.h @@ -0,0 +1,14 @@ +#pragma once +#include "Modem.h" +#include "ModemAnalog.h" + +class ModemDSB : public ModemAnalog { +public: + ModemDSB(); + std::string getName(); + Modem *factory(); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + ampmodem demodAM_DSB; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemFM.cpp b/src/modules/modem/analog/ModemFM.cpp new file mode 100644 index 0000000..259fcfd --- /dev/null +++ b/src/modules/modem/analog/ModemFM.cpp @@ -0,0 +1,28 @@ +#include "ModemFM.h" + +ModemFM::ModemFM() { + demodFM = freqdem_create(0.5); +} + +Modem *ModemFM::factory() { + return new ModemFM; +} + +std::string ModemFM::getName() { + return "FM"; +} + +void ModemFM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitAnalog *fmkit = (ModemKitAnalog *)kit; + + initOutputBuffers(fmkit, input); + + if (!bufSize) { + input->decRefCount(); + return; + } + + freqdem_demodulate_block(demodFM, &input->data[0], bufSize, &demodOutputData[0]); + + buildAudioOutput(fmkit, audioOut, false); +} diff --git a/src/modules/modem/analog/ModemFM.h b/src/modules/modem/analog/ModemFM.h new file mode 100644 index 0000000..a763bc2 --- /dev/null +++ b/src/modules/modem/analog/ModemFM.h @@ -0,0 +1,15 @@ +#pragma once +#include "Modem.h" +#include "ModemAnalog.h" + +class ModemFM : public ModemAnalog { +public: + ModemFM(); + std::string getName(); + Modem *factory(); + 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 new file mode 100644 index 0000000..04ec5d7 --- /dev/null +++ b/src/modules/modem/analog/ModemFMStereo.cpp @@ -0,0 +1,186 @@ +#include "ModemFMStereo.h" + +ModemFMStereo::ModemFMStereo() { + demodFM = freqdem_create(0.5); + + firStereoR2C = firhilbf_create(5, 60.0f); + firStereoC2R = firhilbf_create(5, 60.0f); + + stereoPilot = nco_crcf_create(LIQUID_VCO); + nco_crcf_reset(stereoPilot); + nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f); +} + +ModemFMStereo::~ModemFMStereo() { + firhilbf_destroy(firStereoR2C); + firhilbf_destroy(firStereoC2R); + + nco_crcf_destroy(stereoPilot); +} + +std::string ModemFMStereo::getType() { + return "analog"; +} + +std::string ModemFMStereo::getName() { + return "FMS"; +} + +Modem *ModemFMStereo::factory() { + return new ModemFMStereo; +} + +ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) { + ModemKitFMStereo *kit = new ModemKitFMStereo; + + kit->audioResampleRatio = double(audioSampleRate) / double(sampleRate); + + float As = 60.0f; // stop-band attenuation [dB] + + kit->audioResampler = msresamp_rrrf_create(kit->audioResampleRatio, As); + kit->stereoResampler = msresamp_rrrf_create(kit->audioResampleRatio, As); + + // Stereo filters / shifters + double firStereoCutoff = 16000.0 / double(audioSampleRate); + // filter transition + float ft = 1000.0 / double(audioSampleRate); + // fractional timing offset + float mu = 0.0f; + + if (firStereoCutoff < 0) { + firStereoCutoff = 0; + } + + if (firStereoCutoff > 0.5) { + firStereoCutoff = 0.5; + } + + unsigned int h_len = estimate_req_filter_len(ft, As); + float *h = new float[h_len]; + liquid_firdes_kaiser(h_len, firStereoCutoff, As, mu, h); + + kit->firStereoLeft = firfilt_rrrf_create(h, h_len); + kit->firStereoRight = firfilt_rrrf_create(h, h_len); + + // stereo pilot filter + float bw = sampleRate; + if (bw < 100000.0) { + bw = 100000.0; + } + unsigned int order = 5; // filter order + float f0 = ((double) 19000 / bw); + float fc = ((double) 19500 / bw); + float Ap = 1.0f; + + kit->iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As); + + return kit; +} + +void ModemFMStereo::disposeKit(ModemKit *kit) { + ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit; + + msresamp_rrrf_destroy(fmkit->audioResampler); + msresamp_rrrf_destroy(fmkit->stereoResampler); + firfilt_rrrf_destroy(fmkit->firStereoLeft); + firfilt_rrrf_destroy(fmkit->firStereoRight); +} + + +void ModemFMStereo::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit; + int bufSize = input->data.size(); + liquid_float_complex u, v, w, x, y; + + double audio_resample_ratio = fmkit->audioResampleRatio; + + if (demodOutputData.size() != bufSize) { + if (demodOutputData.capacity() < bufSize) { + demodOutputData.reserve(bufSize); + } + demodOutputData.resize(bufSize); + } + + int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512; + + freqdem_demodulate_block(demodFM, &input->data[0], bufSize, &demodOutputData[0]); + + if (resampledOutputData.size() != audio_out_size) { + if (resampledOutputData.capacity() < audio_out_size) { + resampledOutputData.reserve(audio_out_size); + } + resampledOutputData.resize(audio_out_size); + } + + unsigned int numAudioWritten; + + msresamp_rrrf_execute(fmkit->audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten); + + if (demodStereoData.size() != bufSize) { + if (demodStereoData.capacity() < bufSize) { + demodStereoData.reserve(bufSize); + } + demodStereoData.resize(bufSize); + } + + float phase_error = 0; + + for (int i = 0; i < bufSize; i++) { + // real -> complex + firhilbf_r2c_execute(firStereoR2C, demodOutputData[i], &x); + + // 19khz pilot band-pass + iirfilt_crcf_execute(fmkit->iirStereoPilot, x, &v); + nco_crcf_cexpf(stereoPilot, &w); + + w.imag = -w.imag; // conjf(w) + + // multiply u = v * conjf(w) + u.real = v.real * w.real - v.imag * w.imag; + u.imag = v.real * w.imag + v.imag * w.real; + + // cargf(u) + phase_error = atan2f(u.imag,u.real); + + // step pll + nco_crcf_pll_step(stereoPilot, phase_error); + nco_crcf_step(stereoPilot); + + // 38khz down-mix + nco_crcf_mix_down(stereoPilot, x, &y); + nco_crcf_mix_down(stereoPilot, y, &x); + + // complex -> real + firhilbf_c2r_execute(firStereoC2R, x, &demodStereoData[i]); + } + + // std::cout << "[PLL] phase error: " << phase_error; + // std::cout << " freq:" << (((nco_crcf_get_frequency(stereoPilot) / (2.0 * M_PI)) * inp->sampleRate)) << std::endl; + + if (audio_out_size != resampledStereoData.size()) { + if (resampledStereoData.capacity() < audio_out_size) { + resampledStereoData.reserve(audio_out_size); + } + resampledStereoData.resize(audio_out_size); + } + + msresamp_rrrf_execute(fmkit->stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten); + + audioOut->channels = 2; + if (audioOut->data.capacity() < (numAudioWritten * 2)) { + audioOut->data.reserve(numAudioWritten * 2); + } + audioOut->data.resize(numAudioWritten * 2); + for (int i = 0; i < numAudioWritten; i++) { + float l, r; + + firfilt_rrrf_push(fmkit->firStereoLeft, 0.568 * (resampledOutputData[i] - (resampledStereoData[i]))); + firfilt_rrrf_execute(fmkit->firStereoLeft, &l); + + firfilt_rrrf_push(fmkit->firStereoRight, 0.568 * (resampledOutputData[i] + (resampledStereoData[i]))); + firfilt_rrrf_execute(fmkit->firStereoRight, &r); + + audioOut->data[i * 2] = l; + audioOut->data[i * 2 + 1] = r; + } +} diff --git a/src/modules/modem/analog/ModemFMStereo.h b/src/modules/modem/analog/ModemFMStereo.h new file mode 100644 index 0000000..cbc5aec --- /dev/null +++ b/src/modules/modem/analog/ModemFMStereo.h @@ -0,0 +1,41 @@ +#pragma once +#include "Modem.h" + +class ModemKitFMStereo: public ModemKit { +public: + ModemKitFMStereo() : audioResampler(nullptr), stereoResampler(nullptr), audioResampleRatio(0), firStereoLeft(nullptr), firStereoRight(nullptr), iirStereoPilot(nullptr) { + } + + msresamp_rrrf audioResampler; + msresamp_rrrf stereoResampler; + double audioResampleRatio; + + firfilt_rrrf firStereoLeft; + firfilt_rrrf firStereoRight; + iirfilt_crcf iirStereoPilot; +}; + + +class ModemFMStereo : public Modem { +public: + ModemFMStereo(); + ~ModemFMStereo(); + std::string getType(); + std::string getName(); + Modem *factory(); + ModemKit *buildKit(long long sampleRate, int audioSampleRate); + void disposeKit(ModemKit *kit); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + std::vector demodOutputData; + std::vector demodStereoData; + std::vector resampledOutputData; + std::vector resampledStereoData; + freqdem demodFM; + + firhilbf firStereoR2C; + firhilbf firStereoC2R; + + nco_crcf stereoPilot; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemIQ.cpp b/src/modules/modem/analog/ModemIQ.cpp new file mode 100644 index 0000000..6c984f6 --- /dev/null +++ b/src/modules/modem/analog/ModemIQ.cpp @@ -0,0 +1,46 @@ +#include "ModemIQ.h" + +ModemIQ::ModemIQ() { + +} + +Modem *ModemIQ::factory() { + return new ModemIQ; +} + +ModemKit *ModemIQ::buildKit(long long sampleRate, int audioSampleRate) { + ModemKit *kit = new ModemKit; + return kit; +} + +std::string ModemIQ::getType() { + return "analog"; +} + +std::string ModemIQ::getName() { + return "I/Q"; +} + +void ModemIQ::disposeKit(ModemKit *kit) { + delete kit; +} + +void ModemIQ::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + int bufSize = input->data.size(); + + if (!bufSize) { + input->decRefCount(); + return; + } + + audioOut->channels = 2; + if (audioOut->data.capacity() < (bufSize * 2)) { + audioOut->data.reserve(bufSize * 2); + } + + audioOut->data.resize(bufSize * 2); + for (int i = 0; i < bufSize; i++) { + audioOut->data[i * 2] = input->data[i].imag; + audioOut->data[i * 2 + 1] = input->data[i].real; + } +} diff --git a/src/modules/modem/analog/ModemIQ.h b/src/modules/modem/analog/ModemIQ.h new file mode 100644 index 0000000..abd9d94 --- /dev/null +++ b/src/modules/modem/analog/ModemIQ.h @@ -0,0 +1,16 @@ +#pragma once +#include "Modem.h" + +class ModemIQ : public Modem { +public: + ModemIQ(); + std::string getType(); + std::string getName(); + Modem *factory(); + ModemKit *buildKit(long long sampleRate, int audioSampleRate); + void disposeKit(ModemKit *kit); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp new file mode 100644 index 0000000..44fb116 --- /dev/null +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -0,0 +1,39 @@ +#include "ModemLSB.h" + +ModemLSB::ModemLSB() { + // 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); +} + +Modem *ModemLSB::factory() { + return new ModemLSB; +} + +std::string ModemLSB::getName() { + return "LSB"; +} + +ModemLSB::~ModemLSB() { + resamp2_crcf_destroy(ssbFilt); + ampmodem_destroy(demodAM_LSB); +} + +void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitAnalog *akit = (ModemKitAnalog *)kit; + + initOutputBuffers(akit,input); + + if (!bufSize) { + input->decRefCount(); + return; + } + + liquid_float_complex x, y; + for (int i = 0; i < bufSize; i++) { // Reject upper band + resamp2_crcf_filter_execute(ssbFilt,input->data[i],&x,&y); + ampmodem_demodulate(demodAM_LSB, x, &demodOutputData[i]); + } + + buildAudioOutput(akit, audioOut, true); +} diff --git a/src/modules/modem/analog/ModemLSB.h b/src/modules/modem/analog/ModemLSB.h new file mode 100644 index 0000000..cbdc176 --- /dev/null +++ b/src/modules/modem/analog/ModemLSB.h @@ -0,0 +1,16 @@ +#pragma once +#include "Modem.h" +#include "ModemAnalog.h" + +class ModemLSB : public ModemAnalog { +public: + ModemLSB(); + ~ModemLSB(); + std::string getName(); + Modem *factory(); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + resamp2_crcf ssbFilt; + ampmodem demodAM_LSB; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp new file mode 100644 index 0000000..0482d4f --- /dev/null +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -0,0 +1,40 @@ +#include "ModemUSB.h" + +ModemUSB::ModemUSB() { + // 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); +} + +Modem *ModemUSB::factory() { + return new ModemUSB; +} + +std::string ModemUSB::getName() { + return "USB"; +} + +ModemUSB::~ModemUSB() { + resamp2_crcf_destroy(ssbFilt); + ampmodem_destroy(demodAM_USB); +} + +void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitAnalog *akit = (ModemKitAnalog *)kit; + + initOutputBuffers(akit,input); + + if (!bufSize) { + input->decRefCount(); + return; + } + + liquid_float_complex x, y; + for (int i = 0; i < bufSize; i++) { // Reject lower band + resamp2_crcf_filter_execute(ssbFilt,input->data[i],&x,&y); + ampmodem_demodulate(demodAM_USB, y, &demodOutputData[i]); + } + + buildAudioOutput(akit, audioOut, true); +} + diff --git a/src/modules/modem/analog/ModemUSB.h b/src/modules/modem/analog/ModemUSB.h new file mode 100644 index 0000000..d6d3a4d --- /dev/null +++ b/src/modules/modem/analog/ModemUSB.h @@ -0,0 +1,15 @@ +#pragma once +#include "ModemAnalog.h" + +class ModemUSB : public ModemAnalog { +public: + ModemUSB(); + ~ModemUSB(); + std::string getName(); + Modem *factory(); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + resamp2_crcf ssbFilt; + ampmodem demodAM_USB; +}; \ No newline at end of file diff --git a/src/modules/modem/digital/ModemAPSK.cpp b/src/modules/modem/digital/ModemAPSK.cpp new file mode 100644 index 0000000..ed04c10 --- /dev/null +++ b/src/modules/modem/digital/ModemAPSK.cpp @@ -0,0 +1,89 @@ +#include "ModemAPSK.h" + +ModemAPSK::ModemAPSK() { + demodAPSK4 = modem_create(LIQUID_MODEM_APSK4); + demodAPSK8 = modem_create(LIQUID_MODEM_APSK8); + demodAPSK16 = modem_create(LIQUID_MODEM_APSK16); + demodAPSK32 = modem_create(LIQUID_MODEM_APSK32); + 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); +} + +Modem *ModemAPSK::factory() { + return new ModemAPSK; +} + +ModemAPSK::~ModemAPSK() { + modem_destroy(demodAPSK4); + modem_destroy(demodAPSK8); + modem_destroy(demodAPSK16); + modem_destroy(demodAPSK32); + modem_destroy(demodAPSK64); + modem_destroy(demodAPSK128); + modem_destroy(demodAPSK256); +} + +std::string ModemAPSK::getName() { + return "APSK"; +} + +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; + } + } +} + +void ModemAPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitDigital *dkit = (ModemKitDigital *)kit; + + digitalStart(dkit, demodAPSK, input); + + for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) { + modem_demodulate(demodAPSK, input->data[i], &demodOutputDataDigital[i]); + } + + updateDemodulatorLock(demodAPSK, 0.005f); + + digitalFinish(dkit, demodAPSK); +} diff --git a/src/modules/modem/digital/ModemAPSK.h b/src/modules/modem/digital/ModemAPSK.h new file mode 100644 index 0000000..f5497df --- /dev/null +++ b/src/modules/modem/digital/ModemAPSK.h @@ -0,0 +1,22 @@ +#pragma once +#include "ModemDigital.h" + +class ModemAPSK : public ModemDigital { +public: + ModemAPSK(); + ~ModemAPSK(); + std::string getName(); + Modem *factory(); + void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + modem demodAPSK; + modem demodAPSK4; + modem demodAPSK8; + modem demodAPSK16; + modem demodAPSK32; + modem demodAPSK64; + modem demodAPSK128; + modem demodAPSK256; +}; diff --git a/src/modules/modem/digital/ModemASK.cpp b/src/modules/modem/digital/ModemASK.cpp new file mode 100644 index 0000000..af09b76 --- /dev/null +++ b/src/modules/modem/digital/ModemASK.cpp @@ -0,0 +1,91 @@ +#include "ModemASK.h" + +ModemASK::ModemASK() { + demodASK2 = modem_create(LIQUID_MODEM_ASK2); + demodASK4 = modem_create(LIQUID_MODEM_ASK4); + demodASK8 = modem_create(LIQUID_MODEM_ASK8); + demodASK16 = modem_create(LIQUID_MODEM_ASK16); + demodASK32 = modem_create(LIQUID_MODEM_ASK32); + demodASK64 = modem_create(LIQUID_MODEM_ASK64); + demodASK128 = modem_create(LIQUID_MODEM_ASK128); + demodASK256 = modem_create(LIQUID_MODEM_ASK256); + demodASK = demodASK2; + demodulatorCons.store(2); + currentDemodCons.store(0); + updateDemodulatorCons(2); +} + +Modem *ModemASK::factory() { + return new ModemASK; +} + +ModemASK::~ModemASK() { + modem_destroy(demodASK4); + modem_destroy(demodASK8); + modem_destroy(demodASK16); + modem_destroy(demodASK32); + modem_destroy(demodASK64); + modem_destroy(demodASK128); + modem_destroy(demodASK256); +} + +std::string ModemASK::getName() { + return "ASK"; +} + +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; + } + } +} + +void ModemASK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitDigital *dkit = (ModemKitDigital *)kit; + + digitalStart(dkit, demodASK, input); + + for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) { + modem_demodulate(demodASK, input->data[i], &demodOutputDataDigital[i]); + } + updateDemodulatorLock(demodASK, 0.005f); + + digitalFinish(dkit, demodASK); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemASK.h b/src/modules/modem/digital/ModemASK.h new file mode 100644 index 0000000..5dfffc1 --- /dev/null +++ b/src/modules/modem/digital/ModemASK.h @@ -0,0 +1,23 @@ +#pragma once +#include "ModemDigital.h" + +class ModemASK : public ModemDigital { +public: + ModemASK(); + ~ModemASK(); + std::string getName(); + Modem *factory(); + void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + modem demodASK; + modem demodASK2; + modem demodASK4; + modem demodASK8; + modem demodASK16; + modem demodASK32; + modem demodASK64; + modem demodASK128; + modem demodASK256; +}; diff --git a/src/modules/modem/digital/ModemBPSK.cpp b/src/modules/modem/digital/ModemBPSK.cpp new file mode 100644 index 0000000..535cdae --- /dev/null +++ b/src/modules/modem/digital/ModemBPSK.cpp @@ -0,0 +1,35 @@ +#include "ModemBPSK.h" + +ModemBPSK::ModemBPSK() { + demodBPSK = modem_create(LIQUID_MODEM_BPSK); +} + +Modem *ModemBPSK::factory() { + return new ModemBPSK; +} + +ModemBPSK::~ModemBPSK() { + modem_destroy(demodBPSK); +} + +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); + + for (int i = 0, bufSize=input->data.size(); i < bufSize; i++) { + modem_demodulate(demodBPSK, input->data[i], &demodOutputDataDigital[i]); + } + updateDemodulatorLock(demodBPSK, 0.005f); + + digitalFinish(dkit, demodBPSK); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemBPSK.h b/src/modules/modem/digital/ModemBPSK.h new file mode 100644 index 0000000..ef26c5c --- /dev/null +++ b/src/modules/modem/digital/ModemBPSK.h @@ -0,0 +1,16 @@ +#pragma once +#include "ModemDigital.h" + +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 new file mode 100644 index 0000000..b44ebb7 --- /dev/null +++ b/src/modules/modem/digital/ModemDPSK.cpp @@ -0,0 +1,91 @@ +#include "ModemDPSK.h" + +ModemDPSK::ModemDPSK() { + demodDPSK2 = modem_create(LIQUID_MODEM_DPSK2); + demodDPSK4 = modem_create(LIQUID_MODEM_DPSK4); + demodDPSK8 = modem_create(LIQUID_MODEM_DPSK8); + demodDPSK16 = modem_create(LIQUID_MODEM_DPSK16); + demodDPSK32 = modem_create(LIQUID_MODEM_DPSK32); + 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); +} + +Modem *ModemDPSK::factory() { + return new ModemDPSK; +} + +std::string ModemDPSK::getName() { + return "DPSK"; +} + +ModemDPSK::~ModemDPSK() { + modem_destroy(demodDPSK2); + modem_destroy(demodDPSK4); + modem_destroy(demodDPSK8); + modem_destroy(demodDPSK16); + modem_destroy(demodDPSK32); + modem_destroy(demodDPSK64); + modem_destroy(demodDPSK128); + modem_destroy(demodDPSK256); +} + +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; + } + } +} + +void ModemDPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitDigital *dkit = (ModemKitDigital *)kit; + + digitalStart(dkit, demodDPSK, input); + + for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) { + modem_demodulate(demodDPSK, input->data[i], &demodOutputDataDigital[i]); + } + updateDemodulatorLock(demodDPSK, 0.005f); + + digitalFinish(dkit, demodDPSK); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemDPSK.h b/src/modules/modem/digital/ModemDPSK.h new file mode 100644 index 0000000..b431ffd --- /dev/null +++ b/src/modules/modem/digital/ModemDPSK.h @@ -0,0 +1,24 @@ +#pragma once +#include "ModemDigital.h" + +class ModemDPSK : public ModemDigital { +public: + ModemDPSK(); + ~ModemDPSK(); + std::string getName(); + Modem *factory(); + void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + modem demodDPSK; + modem demodDPSK2; + modem demodDPSK4; + modem demodDPSK8; + modem demodDPSK16; + modem demodDPSK32; + modem demodDPSK64; + modem demodDPSK128; + modem demodDPSK256; +}; + diff --git a/src/modules/modem/digital/ModemOOK.cpp b/src/modules/modem/digital/ModemOOK.cpp new file mode 100644 index 0000000..7be56d7 --- /dev/null +++ b/src/modules/modem/digital/ModemOOK.cpp @@ -0,0 +1,35 @@ +#include "ModemOOK.h" + +ModemOOK::ModemOOK() { + demodOOK = modem_create(LIQUID_MODEM_OOK); +} + +Modem *ModemOOK::factory() { + return new ModemOOK; +} + +ModemOOK::~ModemOOK() { + modem_destroy(demodOOK); +} + +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); + + for (int i = 0, bufSize=input->data.size(); i < bufSize; i++) { + modem_demodulate(demodOOK, input->data[i], &demodOutputDataDigital[i]); + } + updateDemodulatorLock(demodOOK, 0.005f); + + digitalFinish(dkit, demodOOK); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemOOK.h b/src/modules/modem/digital/ModemOOK.h new file mode 100644 index 0000000..6f15c8b --- /dev/null +++ b/src/modules/modem/digital/ModemOOK.h @@ -0,0 +1,16 @@ +#pragma once +#include "ModemDigital.h" + +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 new file mode 100644 index 0000000..cf05a9e --- /dev/null +++ b/src/modules/modem/digital/ModemPSK.cpp @@ -0,0 +1,91 @@ +#include "ModemPSK.h" + +ModemPSK::ModemPSK() { + demodPSK2 = modem_create(LIQUID_MODEM_PSK2); + demodPSK4 = modem_create(LIQUID_MODEM_PSK4); + demodPSK8 = modem_create(LIQUID_MODEM_PSK8); + demodPSK16 = modem_create(LIQUID_MODEM_PSK16); + demodPSK32 = modem_create(LIQUID_MODEM_PSK32); + 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); +} + +Modem *ModemPSK::factory() { + return new ModemPSK; +} + +std::string ModemPSK::getName() { + return "PSK"; +} + +ModemPSK::~ModemPSK() { + modem_destroy(demodPSK2); + modem_destroy(demodPSK4); + modem_destroy(demodPSK8); + modem_destroy(demodPSK16); + modem_destroy(demodPSK32); + modem_destroy(demodPSK64); + modem_destroy(demodPSK128); + modem_destroy(demodPSK256); +} + +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; + } + } +} + +void ModemPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitDigital *dkit = (ModemKitDigital *)kit; + + digitalStart(dkit, demodPSK, input); + + for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) { + modem_demodulate(demodPSK, input->data[i], &demodOutputDataDigital[i]); + } + updateDemodulatorLock(demodPSK, 0.005f); + + digitalFinish(dkit, demodPSK); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemPSK.h b/src/modules/modem/digital/ModemPSK.h new file mode 100644 index 0000000..913f8f8 --- /dev/null +++ b/src/modules/modem/digital/ModemPSK.h @@ -0,0 +1,24 @@ +#pragma once +#include "ModemDigital.h" + +class ModemPSK : public ModemDigital { +public: + ModemPSK(); + ~ModemPSK(); + std::string getName(); + Modem *factory(); + void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + modem demodPSK; + modem demodPSK2; + modem demodPSK4; + modem demodPSK8; + modem demodPSK16; + modem demodPSK32; + modem demodPSK64; + modem demodPSK128; + modem demodPSK256; +}; + diff --git a/src/modules/modem/digital/ModemQAM.cpp b/src/modules/modem/digital/ModemQAM.cpp new file mode 100644 index 0000000..f14b5b5 --- /dev/null +++ b/src/modules/modem/digital/ModemQAM.cpp @@ -0,0 +1,88 @@ +#include "ModemQAM.h" + +ModemQAM::ModemQAM() { + demodQAM4 = modem_create(LIQUID_MODEM_QAM4); + demodQAM8 = modem_create(LIQUID_MODEM_QAM8); + demodQAM16 = modem_create(LIQUID_MODEM_QAM16); + demodQAM32 = modem_create(LIQUID_MODEM_QAM32); + 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); +} + +Modem *ModemQAM::factory() { + return new ModemQAM; +} + +std::string ModemQAM::getName() { + return "QAM"; +} + +ModemQAM::~ModemQAM() { + modem_destroy(demodQAM4); + modem_destroy(demodQAM8); + modem_destroy(demodQAM16); + modem_destroy(demodQAM32); + modem_destroy(demodQAM64); + modem_destroy(demodQAM128); + modem_destroy(demodQAM256); +} + +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; + } + } +} + +void ModemQAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitDigital *dkit = (ModemKitDigital *)kit; + digitalStart(dkit, demodQAM, input); + + for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) { + modem_demodulate(demodQAM, input->data[i], &demodOutputDataDigital[i]); + } + updateDemodulatorLock(demodQAM, 0.5f); + + digitalFinish(dkit, demodQAM); +} diff --git a/src/modules/modem/digital/ModemQAM.h b/src/modules/modem/digital/ModemQAM.h new file mode 100644 index 0000000..973f9ff --- /dev/null +++ b/src/modules/modem/digital/ModemQAM.h @@ -0,0 +1,24 @@ +#pragma once +#include "ModemDigital.h" + +class ModemQAM : public ModemDigital { +public: + ModemQAM(); + ~ModemQAM(); + std::string getName(); + Modem *factory(); + void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + modem demodQAM; + modem demodQAM4; + modem demodQAM8; + modem demodQAM16; + modem demodQAM32; + modem demodQAM64; + modem demodQAM128; + modem demodQAM256; +}; + + diff --git a/src/modules/modem/digital/ModemQPSK.cpp b/src/modules/modem/digital/ModemQPSK.cpp new file mode 100644 index 0000000..309cadb --- /dev/null +++ b/src/modules/modem/digital/ModemQPSK.cpp @@ -0,0 +1,35 @@ +#include "ModemQPSK.h" + +ModemQPSK::ModemQPSK() { + demodQPSK = modem_create(LIQUID_MODEM_QPSK); +} + +Modem *ModemQPSK::factory() { + return new ModemQPSK; +} + +ModemQPSK::~ModemQPSK() { + modem_destroy(demodQPSK); +} + +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); + + for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) { + modem_demodulate(demodQPSK, input->data[i], &demodOutputDataDigital[i]); + } + updateDemodulatorLock(demodQPSK, 0.8f); + + digitalFinish(dkit, demodQPSK); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemQPSK.h b/src/modules/modem/digital/ModemQPSK.h new file mode 100644 index 0000000..4d26e49 --- /dev/null +++ b/src/modules/modem/digital/ModemQPSK.h @@ -0,0 +1,15 @@ +#pragma once +#include "ModemDigital.h" + +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: + modem demodQPSK; +}; diff --git a/src/modules/modem/digital/ModemSQAM.cpp b/src/modules/modem/digital/ModemSQAM.cpp new file mode 100644 index 0000000..a4abd39 --- /dev/null +++ b/src/modules/modem/digital/ModemSQAM.cpp @@ -0,0 +1,79 @@ +#include "ModemSQAM.h" + +ModemSQAM::ModemSQAM() { + demodSQAM32 = modem_create(LIQUID_MODEM_SQAM32); + demodSQAM128 = modem_create(LIQUID_MODEM_SQAM128); + demodulatorCons.store(32); + currentDemodCons.store(0); + updateDemodulatorCons(32); +} + +Modem *ModemSQAM::factory() { + return new ModemSQAM; +} + +ModemSQAM::~ModemSQAM() { + modem_destroy(demodSQAM32); + modem_destroy(demodSQAM128); +} + +std::string ModemSQAM::getName() { + return "SQAM"; +} + +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; + } + } +} + +void ModemSQAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { + ModemKitDigital *dkit = (ModemKitDigital *)kit; + + digitalStart(dkit, demodSQAM, input); + + for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) { + modem_demodulate(demodSQAM, input->data[i], &demodOutputDataDigital[i]); + } + updateDemodulatorLock(demodSQAM, 0.005f); + + digitalFinish(dkit, demodSQAM); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemSQAM.h b/src/modules/modem/digital/ModemSQAM.h new file mode 100644 index 0000000..e26b497 --- /dev/null +++ b/src/modules/modem/digital/ModemSQAM.h @@ -0,0 +1,17 @@ +#pragma once +#include "ModemDigital.h" + +class ModemSQAM : public ModemDigital { +public: + ModemSQAM(); + ~ModemSQAM(); + std::string getName(); + Modem *factory(); + void updateDemodulatorCons(int cons); + void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); + +private: + modem demodSQAM; + modem demodSQAM32; + modem demodSQAM128; +}; diff --git a/src/modules/modem/digital/ModemST.cpp b/src/modules/modem/digital/ModemST.cpp new file mode 100644 index 0000000..b5d8e3f --- /dev/null +++ b/src/modules/modem/digital/ModemST.cpp @@ -0,0 +1,35 @@ +#include "ModemST.h" + +ModemST::ModemST() { + demodST = modem_create(LIQUID_MODEM_V29); +} + +Modem *ModemST::factory() { + return new ModemST; +} + +std::string ModemST::getName() { + return "ST"; +} + +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); + + for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) { + modem_demodulate(demodST, input->data[i], &demodOutputDataDigital[i]); + } + updateDemodulatorLock(demodST, 0.005f); + + digitalFinish(dkit, demodST); +} \ No newline at end of file diff --git a/src/modules/modem/digital/ModemST.h b/src/modules/modem/digital/ModemST.h new file mode 100644 index 0000000..ac9ee10 --- /dev/null +++ b/src/modules/modem/digital/ModemST.h @@ -0,0 +1,16 @@ +#pragma once +#include "ModemDigital.h" + +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: + modem demodST; +}; + diff --git a/src/process/FFTDataDistributor.cpp b/src/process/FFTDataDistributor.cpp index a2e10db..db121fe 100644 --- a/src/process/FFTDataDistributor.cpp +++ b/src/process/FFTDataDistributor.cpp @@ -1,6 +1,6 @@ #include "FFTDataDistributor.h" -FFTDataDistributor::FFTDataDistributor() : linesPerSecond(DEFAULT_WATERFALL_LPS), lineRateAccum(0.0), fftSize(DEFAULT_FFT_SIZE) { +FFTDataDistributor::FFTDataDistributor() : fftSize(DEFAULT_FFT_SIZE), linesPerSecond(DEFAULT_WATERFALL_LPS), lineRateAccum(0.0) { bufferedItems = 0; } diff --git a/src/util/DataTree.cpp b/src/util/DataTree.cpp index e150307..8fc1f85 100755 --- a/src/util/DataTree.cpp +++ b/src/util/DataTree.cpp @@ -33,7 +33,7 @@ using namespace std; #define STRINGIFY(A) #A -DataElement::DataElement() : data_type(DATA_NULL), data_val(NULL), data_size(0), unit_size(0) { +DataElement::DataElement() : data_type(DATA_NULL), data_size(0), unit_size(0), data_val(NULL) { } DataElement::~DataElement() { @@ -393,11 +393,11 @@ void DataElement::setSerialized(char *ser_str) { /* DataNode class */ -DataNode::DataNode(): ptr(0), parentNode(NULL) { +DataNode::DataNode(): parentNode(NULL), ptr(0) { data_elem = new DataElement(); } -DataNode::DataNode(const char *name_in): ptr(0), parentNode(NULL) { +DataNode::DataNode(const char *name_in): parentNode(NULL), ptr(0) { node_name = name_in; data_elem = new DataElement(); } @@ -1528,7 +1528,7 @@ bool DataTree::SaveToFileXML(const std::string& filename) { bool DataTree::SaveToFile(const std::string& filename, bool compress, int compress_level) { long dataSize, compressedSize, headerSize; - char *serialized, *hdr_serialized, *compressed; + char *serialized = nullptr, *hdr_serialized = nullptr, *compressed = nullptr; DataTree dtHeader; dataSize = getSerialized(&serialized); @@ -1580,7 +1580,10 @@ bool DataTree::SaveToFile(const std::string& filename, bool compress, int compre } bool DataTree::LoadFromFile(const std::string& filename) { - char *compressed, *serialized, *hdr_serialized; +#if USE_FASTLZ + char *compressed; +#endif + char *serialized, *hdr_serialized; long dataSize, headerSize, compressedSize; ifstream fin(filename.c_str(), ios::binary); diff --git a/src/visual/ModeSelectorCanvas.cpp b/src/visual/ModeSelectorCanvas.cpp index f52f533..d89be48 100644 --- a/src/visual/ModeSelectorCanvas.cpp +++ b/src/visual/ModeSelectorCanvas.cpp @@ -155,6 +155,24 @@ void ModeSelectorCanvas::addChoice(int value, std::string label) { numChoices = selections.size(); } +void ModeSelectorCanvas::setSelection(std::string label) { + for (int i = 0; i < numChoices; i++) { + if (selections[i].label == label) { + currentSelection = i; + return; + } + } + currentSelection = -1; + Refresh(); +} + +std::string ModeSelectorCanvas::getSelectionLabel() { + if (currentSelection == -1) { + return ""; + } + return selections[currentSelection].label; +} + void ModeSelectorCanvas::setSelection(int value) { for (int i = 0; i < numChoices; i++) { if (selections[i].value == value) { diff --git a/src/visual/ModeSelectorCanvas.h b/src/visual/ModeSelectorCanvas.h index 2c76294..ca2a524 100644 --- a/src/visual/ModeSelectorCanvas.h +++ b/src/visual/ModeSelectorCanvas.h @@ -32,6 +32,8 @@ public: void setHelpTip(std::string tip); void addChoice(int value, std::string label); + void setSelection(std::string label); + std::string getSelectionLabel(); void setSelection(int value); int getSelection(); diff --git a/src/visual/PrimaryGLContext.cpp b/src/visual/PrimaryGLContext.cpp index f11fdac..7aea40a 100644 --- a/src/visual/PrimaryGLContext.cpp +++ b/src/visual/PrimaryGLContext.cpp @@ -87,7 +87,7 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, l glColor4f(color.r, color.g, color.b, 0.6); float ofs = ((float) demod->getBandwidth()) / (float) srate; - float ofsLeft = (demod->getDemodulatorType()!=DEMOD_TYPE_USB)?ofs:0, ofsRight = (demod->getDemodulatorType()!=DEMOD_TYPE_LSB)?ofs:0; + float ofsLeft = (demod->getDemodulatorType()!="USB")?ofs:0, ofsRight = (demod->getDemodulatorType()!="LSB")?ofs:0; float labelHeight = 20.0 / viewHeight; float hPos = -1.0 + labelHeight; @@ -139,9 +139,9 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, l demodLabel = std::string("[M] ") + demodLabel; } - if (demod->getDemodulatorType() == DEMOD_TYPE_USB) { + if (demod->getDemodulatorType() == "USB") { GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodLabel, uxPos, hPos, 16, GLFont::GLFONT_ALIGN_LEFT, GLFont::GLFONT_ALIGN_CENTER); - } else if (demod->getDemodulatorType() == DEMOD_TYPE_LSB) { + } else if (demod->getDemodulatorType() == "LSB") { GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodLabel, uxPos, hPos, 16, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER); } else { GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodLabel, uxPos, hPos, 16, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); @@ -172,7 +172,7 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBA4f color, long glColor4f(color.r, color.g, color.b, 0.6); float ofs = ((float) demod->getBandwidth()) / (float) srate; - float ofsLeft = (demod->getDemodulatorType()!=DEMOD_TYPE_USB)?ofs:0, ofsRight = (demod->getDemodulatorType()!=DEMOD_TYPE_LSB)?ofs:0; + float ofsLeft = (demod->getDemodulatorType()!="USB")?ofs:0, ofsRight = (demod->getDemodulatorType()!="LSB")?ofs:0; glBegin(GL_LINES); glVertex3f((uxPos - 0.5) * 2.0, 1.0, 0.0); @@ -217,69 +217,20 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBA4f color, long std::string demodStr = ""; GLFont::Align demodAlign = GLFont::GLFONT_ALIGN_CENTER; - switch (demod->getDemodulatorType()) { - case DEMOD_TYPE_FM: - demodStr = "FM"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_AM: - demodStr = "AM"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_LSB: - demodStr = "LSB"; + demodStr = demod->getDemodulatorType(); + + demodAlign = GLFont::GLFONT_ALIGN_CENTER; + + if (demodStr == "LSB") { demodAlign = GLFont::GLFONT_ALIGN_RIGHT; uxPos -= xOfs; - break; - case DEMOD_TYPE_USB: - demodStr = "USB"; + } else if (demodStr == "USB") { demodAlign = GLFont::GLFONT_ALIGN_LEFT; uxPos += xOfs; - break; - // advanced demodulators start here - case DEMOD_TYPE_ASK: - demodStr = "ASK"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_APSK: - demodStr = "APSK"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_BPSK: - demodStr = "BPSK"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_DPSK: - demodStr = "DPSK"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_PSK: - demodStr = "PSK"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_OOK: - demodStr = "OOK"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_SQAM: - demodStr = "SQAM"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_ST: - demodStr = "ST"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_QAM: - demodStr = "QAM"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; - case DEMOD_TYPE_QPSK: - demodStr = "QPSK"; - demodAlign = GLFont::GLFONT_ALIGN_CENTER; - break; } + // advanced demodulators start here - if (demod->getDemodulatorCons() != NULL && demod->getDemodulatorCons() > 0) { + if (demod->getDemodulatorCons() > 0) { demodStr = demodStr + std::to_string(demod->getDemodulatorCons()); } @@ -306,7 +257,7 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBA4f color, float w, long long long bw = 0; - int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType(); + std::string last_type = wxGetApp().getDemodMgr().getLastDemodulatorType(); if (!demod) { bw = wxGetApp().getDemodMgr().getLastBandwidth(); @@ -337,12 +288,12 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBA4f color, float w, long ofs = ((float) bw) / (float) srate; } - if (last_type != DEMOD_TYPE_USB) { + if (last_type != "USB") { glVertex3f((uxPos - 0.5) * 2.0 - ofs, 1.0, 0.0); glVertex3f((uxPos - 0.5) * 2.0 - ofs, -1.0, 0.0); } - if (last_type != DEMOD_TYPE_LSB) { + if (last_type != "LSB") { glVertex3f((uxPos - 0.5) * 2.0 + ofs, 1.0, 0.0); glVertex3f((uxPos - 0.5) * 2.0 + ofs, -1.0, 0.0); } @@ -359,7 +310,7 @@ void PrimaryGLContext::DrawRangeSelector(float uxPos1, float uxPos2, RGBA4f colo uxPos1=temp; } - int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType(); + std::string last_type = wxGetApp().getDemodMgr().getLastDemodulatorType(); glDisable(GL_TEXTURE_2D); @@ -367,14 +318,14 @@ void PrimaryGLContext::DrawRangeSelector(float uxPos1, float uxPos2, RGBA4f colo glBlendFunc(GL_SRC_ALPHA, GL_ONE); glColor4f(color.r, color.g, color.b, 0.6); - glLineWidth((last_type == DEMOD_TYPE_USB)?2.0:1.0); + glLineWidth((last_type == "USB")?2.0:1.0); glBegin(GL_LINES); glVertex3f((uxPos1 - 0.5) * 2.0, 1.0, 0.0); glVertex3f((uxPos1 - 0.5) * 2.0, -1.0, 0.0); glEnd(); - glLineWidth((last_type == DEMOD_TYPE_LSB)?2.0:1.0); + glLineWidth((last_type == "LSB")?2.0:1.0); glBegin(GL_LINES); glVertex3f((uxPos2 - 0.5) * 2.0, 1.0, 0.0); diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 971552e..ce4630e 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -36,7 +36,7 @@ wxEND_EVENT_TABLE() WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : InteractiveCanvas(parent, attribList), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines(0), - dragOfs(0), mouseZoom(1), zoom(1), freqMove(0.0), freqMoving(false), hoverAlpha(1.0) { + dragOfs(0), mouseZoom(1), zoom(1), freqMoving(false), freqMove(0.0), hoverAlpha(1.0) { glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this)); linesPerSecond = 30; @@ -253,7 +253,7 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { long long currentCenterFreq = getCenterFrequency(); ColorTheme *currentTheme = ThemeMgr::mgr.currentTheme; - int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType(); + std::string last_type = wxGetApp().getDemodMgr().getLastDemodulatorType(); if (mouseTracker.mouseInView() || wxGetApp().getDemodMgr().getActiveDemodulator()) { hoverAlpha += (1.0f-hoverAlpha)*0.1f; @@ -277,7 +277,7 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glContext->DrawDemod(lastActiveDemodulator, isNew?currentTheme->waterfallHighlight:currentTheme->waterfallDestroy, currentCenterFreq, currentBandwidth); - if ((last_type == DEMOD_TYPE_LSB || last_type == DEMOD_TYPE_USB) && mouseTracker.mouseDown()) { + if ((last_type == "LSB" || last_type == "USB") && mouseTracker.mouseDown()) { centerPos = mouseTracker.getMouseX(); glContext->DrawRangeSelector(centerPos, centerPos-width, isNew?currentTheme->waterfallNew:currentTheme->waterfallHover); } else { @@ -416,16 +416,6 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { } activeDemod->setMuted(!activeDemod->isMuted()); break; - case 'S': - if (!activeDemod) { - break; - } - if (activeDemod->isStereo()) { - activeDemod->setStereo(false); - } else { - activeDemod->setStereo(true); - } - break; case 'B': if (spectrumCanvas) { spectrumCanvas->setShowDb(!spectrumCanvas->getShowDb()); @@ -534,8 +524,8 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { double maxDist = ((double)halfBw + bufferBw); if ((double)dist <= maxDist) { - if ((freqDiff > 0 && demod->getDemodulatorType() == DEMOD_TYPE_USB) || - (freqDiff < 0 && demod->getDemodulatorType() == DEMOD_TYPE_LSB)) { + if ((freqDiff > 0 && demod->getDemodulatorType() == "USB") || + (freqDiff < 0 && demod->getDemodulatorType() == "LSB")) { continue; } @@ -565,12 +555,12 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { if (abs(freqDiff) > (activeDemodulator->getBandwidth() / 3)) { if (freqDiff > 0) { - if (activeDemodulator->getDemodulatorType() != DEMOD_TYPE_USB) { + if (activeDemodulator->getDemodulatorType() != "USB") { nextDragState = WF_DRAG_BANDWIDTH_LEFT; SetCursor(wxCURSOR_SIZEWE); } } else { - if (activeDemodulator->getDemodulatorType() != DEMOD_TYPE_LSB) { + if (activeDemodulator->getDemodulatorType() != "LSB") { nextDragState = WF_DRAG_BANDWIDTH_RIGHT; SetCursor(wxCURSOR_SIZEWE); } @@ -578,14 +568,14 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { mouseTracker.setVertDragLock(true); mouseTracker.setHorizDragLock(false); - setStatusText("Click and drag to change demodulator bandwidth. SPACE for direct frequency input. M for mute, D to delete, S for stereo."); + setStatusText("Click and drag to change demodulator bandwidth. SPACE for direct frequency input. M for mute, D to delete."); } else { SetCursor(wxCURSOR_SIZING); nextDragState = WF_DRAG_FREQUENCY; mouseTracker.setVertDragLock(true); mouseTracker.setHorizDragLock(false); - setStatusText("Click and drag to change demodulator frequency; SPACE for direct input. M for mute, D to delete, S for stereo."); + setStatusText("Click and drag to change demodulator frequency; SPACE for direct input. M for mute, D to delete."); } } else { SetCursor(wxCURSOR_CROSS); @@ -671,7 +661,6 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { demod->setBandwidth(mgr->getLastBandwidth()); demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); - demod->setStereo(mgr->isLastStereo()); demod->setGain(mgr->getLastGain()); demod->setMuted(mgr->isLastMuted()); @@ -712,9 +701,9 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { float width = mouseTracker.getOriginDeltaMouseX(); float pos; - int last_type = mgr->getLastDemodulatorType(); + std::string last_type = mgr->getLastDemodulatorType(); - if (last_type == DEMOD_TYPE_LSB || last_type == DEMOD_TYPE_USB) { + if (last_type == "LSB" || last_type == "USB") { float pos1 = mouseTracker.getOriginMouseX(); float pos2 = mouseTracker.getMouseX(); @@ -724,7 +713,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { pos2 = tmp; } - pos = (last_type == DEMOD_TYPE_LSB)?pos2:pos1; + pos = (last_type == "LSB")?pos2:pos1; width *= 2; } else { pos = mouseTracker.getOriginMouseX() + width / 2.0; @@ -759,7 +748,6 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { demod->setBandwidth(bw); demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); - demod->setStereo(mgr->isLastStereo()); demod->setGain(mgr->getLastGain()); demod->run();