mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-04 08:21:16 -05:00
Merge pull request #192 from cjcliffe/demod_refactor
Demodulator Refactor
This commit is contained in:
commit
3eb3ef4a74
@ -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
|
||||
|
@ -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<int, RtAudio::DeviceInfo>::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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 <wx/cmdline.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
|
||||
|
@ -7,24 +7,6 @@
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
#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<liquid_float_complex> 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") {
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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<std::string *> 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<float> currentAudioGain;
|
||||
|
@ -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<DemodulatorInstance *> *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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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<DemodulatorThreadPostIQData> buffers;
|
||||
|
||||
iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput");
|
||||
@ -99,9 +61,10 @@ void DemodulatorPreThread::run() {
|
||||
|
||||
std::vector<liquid_float_complex> in_buf_data;
|
||||
std::vector<liquid_float_complex> 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;
|
||||
}
|
||||
|
@ -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<liquid_float_complex> 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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,25 +5,24 @@
|
||||
|
||||
#include "DemodDefs.h"
|
||||
#include "AudioThread.h"
|
||||
#include "Modem.h"
|
||||
|
||||
typedef ThreadQueue<AudioThreadInput *> 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<AudioThreadInput> outputBuffers;
|
||||
|
||||
std::vector<liquid_float_complex> agcData;
|
||||
std::vector<float> agcAMData;
|
||||
std::vector<float> demodOutputData;
|
||||
std::vector<float> demodStereoData;
|
||||
std::vector<float> resampledOutputData;
|
||||
std::vector<float> resampledStereoData;
|
||||
std::vector<unsigned int> demodOutputDataDigital;
|
||||
//std::vector<unsigned int> demodOutputDataDigitalTest;
|
||||
|
||||
//std::vector<unsigned char> demodOutputSoftbits;
|
||||
//std::vector<unsigned char> 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<float> squelchLevel;
|
||||
std::atomic<float> 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;
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <vector>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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<DemodulatorWorkerThreadCommand> DemodulatorThreadWorkerCommandQueue;
|
||||
@ -92,4 +89,7 @@ protected:
|
||||
|
||||
DemodulatorThreadWorkerCommandQueue *commandQueue;
|
||||
DemodulatorThreadWorkerResultQueue *resultQueue;
|
||||
Modem *cModem;
|
||||
ModemKit *cModemKit;
|
||||
std::string cModemType;
|
||||
};
|
||||
|
27
src/modules/modem/Modem.cpp
Normal file
27
src/modules/modem/Modem.cpp
Normal file
@ -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() {
|
||||
|
||||
}
|
52
src/modules/modem/Modem.h
Normal file
52
src/modules/modem/Modem.h
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "liquid/liquid.h"
|
||||
#include "IOThread.h"
|
||||
#include "AudioThread.h"
|
||||
#include <cmath>
|
||||
|
||||
class ModemKit {
|
||||
public:
|
||||
ModemKit() : sampleRate(0), audioSampleRate(0) {
|
||||
|
||||
}
|
||||
|
||||
long long sampleRate;
|
||||
int audioSampleRate;
|
||||
};
|
||||
|
||||
class ModemIQData: public ReferenceCounter {
|
||||
public:
|
||||
std::vector<liquid_float_complex> data;
|
||||
long long sampleRate;
|
||||
|
||||
ModemIQData() : sampleRate(0) {
|
||||
|
||||
}
|
||||
|
||||
~ModemIQData() {
|
||||
std::lock_guard < std::mutex > lock(m_mutex);
|
||||
}
|
||||
};
|
||||
|
||||
class Modem;
|
||||
typedef std::map<std::string,Modem *> 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;
|
||||
};
|
91
src/modules/modem/ModemAnalog.cpp
Normal file
91
src/modules/modem/ModemAnalog.cpp
Normal file
@ -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<float> *ModemAnalog::getDemodOutputData() {
|
||||
return &demodOutputData;
|
||||
}
|
||||
|
||||
std::vector<float> *ModemAnalog::getResampledOutputData() {
|
||||
return &resampledOutputData;
|
||||
}
|
33
src/modules/modem/ModemAnalog.h
Normal file
33
src/modules/modem/ModemAnalog.h
Normal file
@ -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<float> *getDemodOutputData();
|
||||
std::vector<float> *getResampledOutputData();
|
||||
protected:
|
||||
int bufSize;
|
||||
std::vector<float> demodOutputData;
|
||||
std::vector<float> resampledOutputData;
|
||||
|
||||
float aOutputCeil;
|
||||
float aOutputCeilMA;
|
||||
float aOutputCeilMAA;
|
||||
};
|
71
src/modules/modem/ModemDigital.cpp
Normal file
71
src/modules/modem/ModemDigital.cpp
Normal file
@ -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();
|
||||
}
|
||||
|
39
src/modules/modem/ModemDigital.h
Normal file
39
src/modules/modem/ModemDigital.h
Normal file
@ -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<unsigned int> demodOutputDataDigital;
|
||||
std::atomic_int demodulatorCons;
|
||||
std::atomic_bool currentDemodLock;
|
||||
std::atomic_int currentDemodCons;
|
||||
|
||||
// std::vector<unsigned int> demodOutputDataDigitalTest;
|
||||
// std::vector<unsigned char> demodOutputSoftbits;
|
||||
// std::vector<unsigned char> demodOutputSoftbitsTest;
|
||||
};
|
30
src/modules/modem/analog/ModemAM.cpp
Normal file
30
src/modules/modem/analog/ModemAM.cpp
Normal file
@ -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);
|
||||
}
|
14
src/modules/modem/analog/ModemAM.h
Normal file
14
src/modules/modem/analog/ModemAM.h
Normal file
@ -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;
|
||||
};
|
30
src/modules/modem/analog/ModemDSB.cpp
Normal file
30
src/modules/modem/analog/ModemDSB.cpp
Normal file
@ -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);
|
||||
}
|
14
src/modules/modem/analog/ModemDSB.h
Normal file
14
src/modules/modem/analog/ModemDSB.h
Normal file
@ -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;
|
||||
};
|
28
src/modules/modem/analog/ModemFM.cpp
Normal file
28
src/modules/modem/analog/ModemFM.cpp
Normal file
@ -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);
|
||||
}
|
15
src/modules/modem/analog/ModemFM.h
Normal file
15
src/modules/modem/analog/ModemFM.h
Normal file
@ -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;
|
||||
};
|
186
src/modules/modem/analog/ModemFMStereo.cpp
Normal file
186
src/modules/modem/analog/ModemFMStereo.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
41
src/modules/modem/analog/ModemFMStereo.h
Normal file
41
src/modules/modem/analog/ModemFMStereo.h
Normal file
@ -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<float> demodOutputData;
|
||||
std::vector<float> demodStereoData;
|
||||
std::vector<float> resampledOutputData;
|
||||
std::vector<float> resampledStereoData;
|
||||
freqdem demodFM;
|
||||
|
||||
firhilbf firStereoR2C;
|
||||
firhilbf firStereoC2R;
|
||||
|
||||
nco_crcf stereoPilot;
|
||||
};
|
46
src/modules/modem/analog/ModemIQ.cpp
Normal file
46
src/modules/modem/analog/ModemIQ.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
16
src/modules/modem/analog/ModemIQ.h
Normal file
16
src/modules/modem/analog/ModemIQ.h
Normal file
@ -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:
|
||||
|
||||
};
|
39
src/modules/modem/analog/ModemLSB.cpp
Normal file
39
src/modules/modem/analog/ModemLSB.cpp
Normal file
@ -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);
|
||||
}
|
16
src/modules/modem/analog/ModemLSB.h
Normal file
16
src/modules/modem/analog/ModemLSB.h
Normal file
@ -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;
|
||||
};
|
40
src/modules/modem/analog/ModemUSB.cpp
Normal file
40
src/modules/modem/analog/ModemUSB.cpp
Normal file
@ -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);
|
||||
}
|
||||
|
15
src/modules/modem/analog/ModemUSB.h
Normal file
15
src/modules/modem/analog/ModemUSB.h
Normal file
@ -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;
|
||||
};
|
89
src/modules/modem/digital/ModemAPSK.cpp
Normal file
89
src/modules/modem/digital/ModemAPSK.cpp
Normal file
@ -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);
|
||||
}
|
22
src/modules/modem/digital/ModemAPSK.h
Normal file
22
src/modules/modem/digital/ModemAPSK.h
Normal file
@ -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;
|
||||
};
|
91
src/modules/modem/digital/ModemASK.cpp
Normal file
91
src/modules/modem/digital/ModemASK.cpp
Normal file
@ -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);
|
||||
}
|
23
src/modules/modem/digital/ModemASK.h
Normal file
23
src/modules/modem/digital/ModemASK.h
Normal file
@ -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;
|
||||
};
|
35
src/modules/modem/digital/ModemBPSK.cpp
Normal file
35
src/modules/modem/digital/ModemBPSK.cpp
Normal file
@ -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);
|
||||
}
|
16
src/modules/modem/digital/ModemBPSK.h
Normal file
16
src/modules/modem/digital/ModemBPSK.h
Normal file
@ -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;
|
||||
|
||||
};
|
91
src/modules/modem/digital/ModemDPSK.cpp
Normal file
91
src/modules/modem/digital/ModemDPSK.cpp
Normal file
@ -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);
|
||||
}
|
24
src/modules/modem/digital/ModemDPSK.h
Normal file
24
src/modules/modem/digital/ModemDPSK.h
Normal file
@ -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;
|
||||
};
|
||||
|
35
src/modules/modem/digital/ModemOOK.cpp
Normal file
35
src/modules/modem/digital/ModemOOK.cpp
Normal file
@ -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);
|
||||
}
|
16
src/modules/modem/digital/ModemOOK.h
Normal file
16
src/modules/modem/digital/ModemOOK.h
Normal file
@ -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;
|
||||
|
||||
};
|
91
src/modules/modem/digital/ModemPSK.cpp
Normal file
91
src/modules/modem/digital/ModemPSK.cpp
Normal file
@ -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);
|
||||
}
|
24
src/modules/modem/digital/ModemPSK.h
Normal file
24
src/modules/modem/digital/ModemPSK.h
Normal file
@ -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;
|
||||
};
|
||||
|
88
src/modules/modem/digital/ModemQAM.cpp
Normal file
88
src/modules/modem/digital/ModemQAM.cpp
Normal file
@ -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);
|
||||
}
|
24
src/modules/modem/digital/ModemQAM.h
Normal file
24
src/modules/modem/digital/ModemQAM.h
Normal file
@ -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;
|
||||
};
|
||||
|
||||
|
35
src/modules/modem/digital/ModemQPSK.cpp
Normal file
35
src/modules/modem/digital/ModemQPSK.cpp
Normal file
@ -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);
|
||||
}
|
15
src/modules/modem/digital/ModemQPSK.h
Normal file
15
src/modules/modem/digital/ModemQPSK.h
Normal file
@ -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;
|
||||
};
|
79
src/modules/modem/digital/ModemSQAM.cpp
Normal file
79
src/modules/modem/digital/ModemSQAM.cpp
Normal file
@ -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);
|
||||
}
|
17
src/modules/modem/digital/ModemSQAM.h
Normal file
17
src/modules/modem/digital/ModemSQAM.h
Normal file
@ -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;
|
||||
};
|
35
src/modules/modem/digital/ModemST.cpp
Normal file
35
src/modules/modem/digital/ModemST.cpp
Normal file
@ -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);
|
||||
}
|
16
src/modules/modem/digital/ModemST.h
Normal file
16
src/modules/modem/digital/ModemST.h
Normal file
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user