mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-08-13 11:02:25 -04: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_MAJOR "0")
|
||||||
SET(CUBICSDR_VERSION_MINOR "1")
|
SET(CUBICSDR_VERSION_MINOR "1")
|
||||||
SET(CUBICSDR_VERSION_PATCH "16")
|
SET(CUBICSDR_VERSION_PATCH "17")
|
||||||
SET(CUBICSDR_VERSION_REL "alpha")
|
SET(CUBICSDR_VERSION_REL "alpha-demod-refactor")
|
||||||
SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}-${CUBICSDR_VERSION_REL}")
|
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}")
|
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/DemodulatorWorkerThread.cpp
|
||||||
src/demod/DemodulatorInstance.cpp
|
src/demod/DemodulatorInstance.cpp
|
||||||
src/demod/DemodulatorMgr.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/audio/AudioThread.cpp
|
||||||
src/util/Gradient.cpp
|
src/util/Gradient.cpp
|
||||||
src/util/Timer.cpp
|
src/util/Timer.cpp
|
||||||
@ -293,6 +313,26 @@ SET (cubicsdr_headers
|
|||||||
src/demod/DemodulatorInstance.h
|
src/demod/DemodulatorInstance.h
|
||||||
src/demod/DemodulatorMgr.h
|
src/demod/DemodulatorMgr.h
|
||||||
src/demod/DemodDefs.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/audio/AudioThread.h
|
||||||
src/util/Gradient.h
|
src/util/Gradient.h
|
||||||
src/util/Timer.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("Forms\\SDRDevices" REGULAR_EXPRESSION "src/forms/SDRDevices/${REG_EXT}")
|
||||||
SOURCE_GROUP("SDR" REGULAR_EXPRESSION "src/sdr/${REG_EXT}")
|
SOURCE_GROUP("SDR" REGULAR_EXPRESSION "src/sdr/${REG_EXT}")
|
||||||
SOURCE_GROUP("Demodulator" REGULAR_EXPRESSION "src/demod/${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("Audio" REGULAR_EXPRESSION "src/audio/${REG_EXT}")
|
||||||
SOURCE_GROUP("Utility" REGULAR_EXPRESSION "src/util/${REG_EXT}")
|
SOURCE_GROUP("Utility" REGULAR_EXPRESSION "src/util/${REG_EXT}")
|
||||||
SOURCE_GROUP("Visual" REGULAR_EXPRESSION "src/visual/${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/forms/SDRDevices
|
||||||
${PROJECT_SOURCE_DIR}/src/sdr
|
${PROJECT_SOURCE_DIR}/src/sdr
|
||||||
${PROJECT_SOURCE_DIR}/src/demod
|
${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/audio
|
||||||
${PROJECT_SOURCE_DIR}/src/util
|
${PROJECT_SOURCE_DIR}/src/util
|
||||||
${PROJECT_SOURCE_DIR}/src/panel
|
${PROJECT_SOURCE_DIR}/src/panel
|
||||||
|
@ -67,28 +67,29 @@ AppFrame::AppFrame() :
|
|||||||
gainSpacerItem->Show(false);
|
gainSpacerItem->Show(false);
|
||||||
|
|
||||||
demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList);
|
demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList);
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_FM, "FM");
|
demodModeSelector->addChoice(0, "FM");
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_AM, "AM");
|
demodModeSelector->addChoice(1, "FMS");
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_LSB, "LSB");
|
demodModeSelector->addChoice(2, "AM");
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_USB, "USB");
|
demodModeSelector->addChoice(3, "LSB");
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_DSB, "DSB");
|
demodModeSelector->addChoice(4, "USB");
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_RAW, "I/Q");
|
demodModeSelector->addChoice(5, "DSB");
|
||||||
demodModeSelector->setSelection(DEMOD_TYPE_FM);
|
demodModeSelector->addChoice(6, "I/Q");
|
||||||
|
demodModeSelector->setSelection("FM");
|
||||||
demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation, Amplitude Modulation and Lower, Upper or Double Side-Band.");
|
demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation, Amplitude Modulation and Lower, Upper or Double Side-Band.");
|
||||||
demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0);
|
demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0);
|
||||||
|
|
||||||
#ifdef ENABLE_DIGITAL_LAB
|
#ifdef ENABLE_DIGITAL_LAB
|
||||||
demodModeSelectorAdv = new ModeSelectorCanvas(this, attribList);
|
demodModeSelectorAdv = new ModeSelectorCanvas(this, attribList);
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_ASK, "ASK");
|
demodModeSelectorAdv->addChoice(0, "ASK");
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_APSK, "APSK");
|
demodModeSelectorAdv->addChoice(1, "APSK");
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_BPSK, "BPSK");
|
demodModeSelectorAdv->addChoice(2, "BPSK");
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_DPSK, "DPSK");
|
demodModeSelectorAdv->addChoice(3, "DPSK");
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_PSK, "PSK");
|
demodModeSelectorAdv->addChoice(4, "PSK");
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_OOK, "OOK");
|
demodModeSelectorAdv->addChoice(5, "OOK");
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_ST, "ST");
|
demodModeSelectorAdv->addChoice(6, "ST");
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_SQAM, "SQAM");
|
demodModeSelectorAdv->addChoice(7, "SQAM");
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_QAM, "QAM");
|
demodModeSelectorAdv->addChoice(8, "QAM");
|
||||||
demodModeSelectorAdv->addChoice(DEMOD_TYPE_QPSK, "QPSK");
|
demodModeSelectorAdv->addChoice(9, "QPSK");
|
||||||
demodModeSelectorAdv->setHelpTip("Choose advanced modulation types.");
|
demodModeSelectorAdv->setHelpTip("Choose advanced modulation types.");
|
||||||
demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0);
|
demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0);
|
||||||
|
|
||||||
@ -638,10 +639,9 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
|||||||
} else if (event.GetId() == wxID_RESET) {
|
} else if (event.GetId() == wxID_RESET) {
|
||||||
wxGetApp().getDemodMgr().terminateAll();
|
wxGetApp().getDemodMgr().terminateAll();
|
||||||
wxGetApp().setFrequency(100000000);
|
wxGetApp().setFrequency(100000000);
|
||||||
wxGetApp().getDemodMgr().setLastDemodulatorType(DEMOD_TYPE_FM);
|
wxGetApp().getDemodMgr().setLastDemodulatorType("FM");
|
||||||
demodModeSelector->setSelection(1);
|
demodModeSelector->setSelection(1);
|
||||||
wxGetApp().getDemodMgr().setLastMuted(false);
|
wxGetApp().getDemodMgr().setLastMuted(false);
|
||||||
wxGetApp().getDemodMgr().setLastStereo(false);
|
|
||||||
wxGetApp().getDemodMgr().setLastBandwidth(DEFAULT_DEMOD_BW);
|
wxGetApp().getDemodMgr().setLastBandwidth(DEFAULT_DEMOD_BW);
|
||||||
wxGetApp().getDemodMgr().setLastGain(1.0);
|
wxGetApp().getDemodMgr().setLastGain(1.0);
|
||||||
wxGetApp().getDemodMgr().setLastSquelchLevel(0);
|
wxGetApp().getDemodMgr().setLastSquelchLevel(0);
|
||||||
@ -855,7 +855,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
int outputDevice = demod->getOutputDevice();
|
int outputDevice = demod->getOutputDevice();
|
||||||
scopeCanvas->setDeviceName(outputDevices[outputDevice].name);
|
scopeCanvas->setDeviceName(outputDevices[outputDevice].name);
|
||||||
outputDeviceMenuItems[outputDevice]->Check(true);
|
outputDeviceMenuItems[outputDevice]->Check(true);
|
||||||
int dType = demod->getDemodulatorType();
|
std::string dType = demod->getDemodulatorType();
|
||||||
demodModeSelector->setSelection(dType);
|
demodModeSelector->setSelection(dType);
|
||||||
#ifdef ENABLE_DIGITAL_LAB
|
#ifdef ENABLE_DIGITAL_LAB
|
||||||
int dCons = demod->getDemodulatorCons();
|
int dCons = demod->getDemodulatorCons();
|
||||||
@ -868,12 +868,12 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
long long centerFreq = demod->getFrequency();
|
long long centerFreq = demod->getFrequency();
|
||||||
unsigned int demodBw = (unsigned int) ceil((float) demod->getBandwidth() * 2.25);
|
unsigned int demodBw = (unsigned int) ceil((float) demod->getBandwidth() * 2.25);
|
||||||
|
|
||||||
if (demod->getDemodulatorType() == DEMOD_TYPE_USB) {
|
if (demod->getDemodulatorType() == "USB") {
|
||||||
demodBw /= 2;
|
demodBw /= 2;
|
||||||
centerFreq += demod->getBandwidth() / 4;
|
centerFreq += demod->getBandwidth() / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demod->getDemodulatorType() == DEMOD_TYPE_LSB) {
|
if (demod->getDemodulatorType() == "LSB") {
|
||||||
demodBw /= 2;
|
demodBw /= 2;
|
||||||
centerFreq -= demod->getBandwidth() / 4;
|
centerFreq -= demod->getBandwidth() / 4;
|
||||||
}
|
}
|
||||||
@ -889,18 +889,18 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
demodWaterfallCanvas->setCenterFrequency(centerFreq);
|
demodWaterfallCanvas->setCenterFrequency(centerFreq);
|
||||||
demodSpectrumCanvas->setCenterFrequency(centerFreq);
|
demodSpectrumCanvas->setCenterFrequency(centerFreq);
|
||||||
}
|
}
|
||||||
int dSelection = demodModeSelector->getSelection();
|
std::string dSelection = demodModeSelector->getSelectionLabel();
|
||||||
#ifdef ENABLE_DIGITAL_LAB
|
#ifdef ENABLE_DIGITAL_LAB
|
||||||
int dSelectionadv = demodModeSelectorAdv->getSelection();
|
std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel();
|
||||||
int dSelectionCons = demodModeSelectorCons->getSelection();
|
int dSelectionCons = demodModeSelectorCons->getSelection();
|
||||||
|
|
||||||
// basic demodulators
|
// basic demodulators
|
||||||
if (dSelection != -1 && dSelection != demod->getDemodulatorType()) {
|
if (dSelection != "" && dSelection != demod->getDemodulatorType()) {
|
||||||
demod->setDemodulatorType(dSelection);
|
demod->setDemodulatorType(dSelection);
|
||||||
demodModeSelectorAdv->setSelection(-1);
|
demodModeSelectorAdv->setSelection(-1);
|
||||||
}
|
}
|
||||||
// advanced demodulators
|
// advanced demodulators
|
||||||
else if (dSelectionadv != -1 && dSelectionadv != demod->getDemodulatorType()) {
|
else if (dSelectionadv != "" && dSelectionadv != demod->getDemodulatorType()) {
|
||||||
demod->setDemodulatorType(dSelectionadv);
|
demod->setDemodulatorType(dSelectionadv);
|
||||||
demodModeSelector->setSelection(-1);
|
demodModeSelector->setSelection(-1);
|
||||||
}
|
}
|
||||||
@ -911,7 +911,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// basic demodulators
|
// basic demodulators
|
||||||
if (dSelection != -1 && dSelection != demod->getDemodulatorType()) {
|
if (dSelection != "" && dSelection != demod->getDemodulatorType()) {
|
||||||
demod->setDemodulatorType(dSelection);
|
demod->setDemodulatorType(dSelection);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -951,18 +951,18 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
} else {
|
} else {
|
||||||
DemodulatorMgr *mgr = &wxGetApp().getDemodMgr();
|
DemodulatorMgr *mgr = &wxGetApp().getDemodMgr();
|
||||||
|
|
||||||
int dSelection = demodModeSelector->getSelection();
|
std::string dSelection = demodModeSelector->getSelectionLabel();
|
||||||
#ifdef ENABLE_DIGITAL_LAB
|
#ifdef ENABLE_DIGITAL_LAB
|
||||||
int dSelectionadv = demodModeSelectorAdv->getSelection();
|
std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel();
|
||||||
int dSelectionCons = demodModeSelectorCons->getSelection();
|
int dSelectionCons = demodModeSelectorCons->getSelection();
|
||||||
|
|
||||||
// basic demodulators
|
// basic demodulators
|
||||||
if (dSelection != -1 && dSelection != mgr->getLastDemodulatorType()) {
|
if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) {
|
||||||
mgr->setLastDemodulatorType(dSelection);
|
mgr->setLastDemodulatorType(dSelection);
|
||||||
demodModeSelectorAdv->setSelection(-1);
|
demodModeSelectorAdv->setSelection(-1);
|
||||||
}
|
}
|
||||||
// advanced demodulators
|
// advanced demodulators
|
||||||
else if(dSelectionadv != -1 && dSelectionadv != mgr->getLastDemodulatorType()) {
|
else if(dSelectionadv != "" && dSelectionadv != mgr->getLastDemodulatorType()) {
|
||||||
mgr->setLastDemodulatorType(dSelectionadv);
|
mgr->setLastDemodulatorType(dSelectionadv);
|
||||||
demodModeSelector->setSelection(-1);
|
demodModeSelector->setSelection(-1);
|
||||||
}
|
}
|
||||||
@ -973,7 +973,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// basic demodulators
|
// basic demodulators
|
||||||
if (dSelection != -1 && dSelection != mgr->getLastDemodulatorType()) {
|
if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) {
|
||||||
mgr->setLastDemodulatorType(dSelection);
|
mgr->setLastDemodulatorType(dSelection);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1128,7 +1128,6 @@ void AppFrame::saveSession(std::string fileName) {
|
|||||||
*demod->newChild("type") = (*instance_i)->getDemodulatorType();
|
*demod->newChild("type") = (*instance_i)->getDemodulatorType();
|
||||||
*demod->newChild("squelch_level") = (*instance_i)->getSquelchLevel();
|
*demod->newChild("squelch_level") = (*instance_i)->getSquelchLevel();
|
||||||
*demod->newChild("squelch_enabled") = (*instance_i)->isSquelchEnabled() ? 1 : 0;
|
*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("output_device") = outputDevices[(*instance_i)->getOutputDevice()].name;
|
||||||
*demod->newChild("gain") = (*instance_i)->getGain();
|
*demod->newChild("gain") = (*instance_i)->getGain();
|
||||||
*demod->newChild("muted") = (*instance_i)->isMuted() ? 1 : 0;
|
*demod->newChild("muted") = (*instance_i)->isMuted() ? 1 : 0;
|
||||||
@ -1175,14 +1174,32 @@ bool AppFrame::loadSession(std::string fileName) {
|
|||||||
|
|
||||||
long bandwidth = *demod->getNext("bandwidth");
|
long bandwidth = *demod->getNext("bandwidth");
|
||||||
long long freq = *demod->getNext("frequency");
|
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;
|
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 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;
|
int muted = demod->hasAnother("muted") ? (int) *demod->getNext("muted") : 0;
|
||||||
std::string output_device = demod->hasAnother("output_device") ? string(*(demod->getNext("output_device"))) : "";
|
std::string output_device = demod->hasAnother("output_device") ? string(*(demod->getNext("output_device"))) : "";
|
||||||
float gain = demod->hasAnother("gain") ? (float) *demod->getNext("gain") : 1.0;
|
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();
|
DemodulatorInstance *newDemod = wxGetApp().getDemodMgr().newThread();
|
||||||
loadedDemod = newDemod;
|
loadedDemod = newDemod;
|
||||||
numDemodulators++;
|
numDemodulators++;
|
||||||
@ -1196,9 +1213,6 @@ bool AppFrame::loadSession(std::string fileName) {
|
|||||||
newDemod->setSquelchEnabled(true);
|
newDemod->setSquelchEnabled(true);
|
||||||
newDemod->setSquelchLevel(squelch_level);
|
newDemod->setSquelchLevel(squelch_level);
|
||||||
}
|
}
|
||||||
if (stereo) {
|
|
||||||
newDemod->setStereo(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool found_device = false;
|
bool found_device = false;
|
||||||
std::map<int, RtAudio::DeviceInfo>::iterator i;
|
std::map<int, RtAudio::DeviceInfo>::iterator i;
|
||||||
@ -1221,7 +1235,6 @@ bool AppFrame::loadSession(std::string fileName) {
|
|||||||
std::cout << "\t\tBandwidth: " << bandwidth << std::endl;
|
std::cout << "\t\tBandwidth: " << bandwidth << std::endl;
|
||||||
std::cout << "\t\tSquelch Level: " << squelch_level << 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\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;
|
std::cout << "\t\tOutput Device: " << output_device << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +164,25 @@ bool CubicSDR::OnInit() {
|
|||||||
|
|
||||||
wxApp::SetAppName("CubicSDR");
|
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();
|
frequency = wxGetApp().getConfig()->getCenterFreq();
|
||||||
offset = 0;
|
offset = 0;
|
||||||
ppm = 0;
|
ppm = 0;
|
||||||
|
@ -27,6 +27,26 @@
|
|||||||
#include "SpectrumVisualProcessor.h"
|
#include "SpectrumVisualProcessor.h"
|
||||||
#include "SpectrumVisualDataThread.h"
|
#include "SpectrumVisualDataThread.h"
|
||||||
#include "SDRDevices.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>
|
#include <wx/cmdline.h>
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ const char filePathSeparator =
|
|||||||
#define DEFAULT_SAMPLE_RATE 2500000
|
#define DEFAULT_SAMPLE_RATE 2500000
|
||||||
#define DEFAULT_FFT_SIZE 2048
|
#define DEFAULT_FFT_SIZE 2048
|
||||||
|
|
||||||
#define DEFAULT_DEMOD_TYPE 1
|
#define DEFAULT_DEMOD_TYPE "FM"
|
||||||
#define DEFAULT_DEMOD_BW 200000
|
#define DEFAULT_DEMOD_BW 200000
|
||||||
|
|
||||||
#define DEFAULT_WATERFALL_LPS 30
|
#define DEFAULT_WATERFALL_LPS 30
|
||||||
|
@ -7,24 +7,6 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <mutex>
|
#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"
|
#include "IOThread.h"
|
||||||
|
|
||||||
class DemodulatorThread;
|
class DemodulatorThread;
|
||||||
@ -62,11 +44,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
DemodulatorThreadControlCommand() :
|
DemodulatorThreadControlCommand() :
|
||||||
cmd(DEMOD_THREAD_CMD_CTL_NULL), demodType(DEMOD_TYPE_NULL) {
|
cmd(DEMOD_THREAD_CMD_CTL_NULL), demodType("") {
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorThreadControlCommandEnum cmd;
|
DemodulatorThreadControlCommandEnum cmd;
|
||||||
int demodType;
|
std::string demodType;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DemodulatorThreadIQData: public ReferenceCounter {
|
class DemodulatorThreadIQData: public ReferenceCounter {
|
||||||
@ -93,21 +75,19 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Modem;
|
||||||
|
class ModemKit;
|
||||||
|
|
||||||
class DemodulatorThreadPostIQData: public ReferenceCounter {
|
class DemodulatorThreadPostIQData: public ReferenceCounter {
|
||||||
public:
|
public:
|
||||||
std::vector<liquid_float_complex> data;
|
std::vector<liquid_float_complex> data;
|
||||||
long long sampleRate;
|
long long sampleRate;
|
||||||
msresamp_rrrf audioResampler;
|
std::string modemType;
|
||||||
msresamp_rrrf stereoResampler;
|
Modem *modem;
|
||||||
double audioResampleRatio;
|
ModemKit *modemKit;
|
||||||
int audioSampleRate;
|
|
||||||
|
|
||||||
firfilt_rrrf firStereoLeft;
|
|
||||||
firfilt_rrrf firStereoRight;
|
|
||||||
iirfilt_crcf iirStereoPilot;
|
|
||||||
|
|
||||||
DemodulatorThreadPostIQData() :
|
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 {
|
class DemodulatorThreadAudioData: public ReferenceCounter {
|
||||||
public:
|
public:
|
||||||
long long frequency;
|
long long frequency;
|
||||||
@ -151,11 +132,11 @@ public:
|
|||||||
unsigned int bandwidth; // set equal to disable second stage re-sampling?
|
unsigned int bandwidth; // set equal to disable second stage re-sampling?
|
||||||
unsigned int audioSampleRate;
|
unsigned int audioSampleRate;
|
||||||
|
|
||||||
int demodType;
|
std::string demodType;
|
||||||
|
|
||||||
DemodulatorThreadParameters() :
|
DemodulatorThreadParameters() :
|
||||||
frequency(0), sampleRate(DEFAULT_SAMPLE_RATE), bandwidth(200000), audioSampleRate(0),
|
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);
|
preDemodTerminated.store(true);
|
||||||
active.store(false);
|
active.store(false);
|
||||||
squelch.store(false);
|
squelch.store(false);
|
||||||
stereo.store(false);
|
|
||||||
muted.store(false);
|
muted.store(false);
|
||||||
tracking.store(false);
|
tracking.store(false);
|
||||||
follow.store(false);
|
follow.store(false);
|
||||||
@ -34,7 +33,7 @@ DemodulatorInstance::DemodulatorInstance() :
|
|||||||
pipeAudioData = new AudioThreadInputQueue;
|
pipeAudioData = new AudioThreadInputQueue;
|
||||||
threadQueueControl = new DemodulatorThreadControlCommandQueue;
|
threadQueueControl = new DemodulatorThreadControlCommandQueue;
|
||||||
|
|
||||||
demodulatorThread = new DemodulatorThread();
|
demodulatorThread = new DemodulatorThread(this);
|
||||||
demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData);
|
demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData);
|
||||||
demodulatorThread->setInputQueue("ControlQueue",threadQueueControl);
|
demodulatorThread->setInputQueue("ControlQueue",threadQueueControl);
|
||||||
demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
|
demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
|
||||||
@ -44,8 +43,7 @@ DemodulatorInstance::DemodulatorInstance() :
|
|||||||
audioThread->setInputQueue("AudioDataInput", pipeAudioData);
|
audioThread->setInputQueue("AudioDataInput", pipeAudioData);
|
||||||
audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify);
|
audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify);
|
||||||
|
|
||||||
currentDemodType = demodulatorThread->getDemodulatorType();
|
currentDemodType = demodulatorPreThread->getParams().demodType;
|
||||||
currentDemodCons = demodulatorThread->getDemodulatorCons();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance::~DemodulatorInstance() {
|
DemodulatorInstance::~DemodulatorInstance() {
|
||||||
@ -74,10 +72,9 @@ void DemodulatorInstance::run() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
currentFrequency = demodulatorPreThread->getParams().frequency;
|
currentFrequency = demodulatorPreThread->getParams().frequency;
|
||||||
currentDemodType = demodulatorThread->getDemodulatorType();
|
|
||||||
currentDemodCons = demodulatorThread->getDemodulatorCons();
|
|
||||||
currentAudioSampleRate = AudioThread::deviceSampleRate[getOutputDevice()];
|
currentAudioSampleRate = AudioThread::deviceSampleRate[getOutputDevice()];
|
||||||
demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate;
|
demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate;
|
||||||
|
setDemodulatorType(demodulatorPreThread->getParams().demodType);
|
||||||
|
|
||||||
t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
|
t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
|
||||||
|
|
||||||
@ -103,6 +100,7 @@ void DemodulatorInstance::run() {
|
|||||||
t_PreDemod = new std::thread(&DemodulatorPreThread::threadMain, demodulatorPreThread);
|
t_PreDemod = new std::thread(&DemodulatorPreThread::threadMain, demodulatorPreThread);
|
||||||
t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread);
|
t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
active = true;
|
active = true;
|
||||||
audioTerminated = demodTerminated = preDemodTerminated = terminated = false;
|
audioTerminated = demodTerminated = preDemodTerminated = terminated = false;
|
||||||
|
|
||||||
@ -196,15 +194,6 @@ void DemodulatorInstance::setActive(bool state) {
|
|||||||
active = state;
|
active = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DemodulatorInstance::isStereo() {
|
|
||||||
return stereo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorInstance::setStereo(bool state) {
|
|
||||||
stereo = state;
|
|
||||||
demodulatorThread->setStereo(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorInstance::squelchAuto() {
|
void DemodulatorInstance::squelchAuto() {
|
||||||
DemodulatorThreadControlCommand command;
|
DemodulatorThreadControlCommand command;
|
||||||
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON;
|
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;
|
currentDemodType = demod_type_in;
|
||||||
|
|
||||||
if (currentDemodType == DEMOD_TYPE_RAW) {
|
if (currentDemodType == "I/Q") {
|
||||||
if (currentAudioSampleRate) {
|
if (currentAudioSampleRate) {
|
||||||
setBandwidth(currentAudioSampleRate);
|
setBandwidth(currentAudioSampleRate);
|
||||||
} else {
|
} else {
|
||||||
setBandwidth(AudioThread::deviceSampleRate[getOutputDevice()]);
|
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);
|
demodulatorThread->setAGC(false);
|
||||||
} else {
|
} else {
|
||||||
demodulatorThread->setAGC(true);
|
demodulatorThread->setAGC(true);
|
||||||
}
|
}
|
||||||
setGain(getGain());
|
setGain(getGain());
|
||||||
|
|
||||||
|
demodulatorPreThread->getParams().demodType = currentDemodType;
|
||||||
if (!active) {
|
if (!active) {
|
||||||
checkBandwidth();
|
checkBandwidth();
|
||||||
demodulatorPreThread->getParams().demodType = currentDemodType;
|
demodulatorPreThread->setDemodType(currentDemodType);
|
||||||
demodulatorThread->setDemodulatorType(currentDemodType);
|
|
||||||
} else if (demodulatorThread && threadQueueControl) {
|
} else if (demodulatorThread && threadQueueControl) {
|
||||||
DemodulatorThreadControlCommand command;
|
demodulatorPreThread->setDemodType(currentDemodType);
|
||||||
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE;
|
|
||||||
command.demodType = demod_type_in;
|
|
||||||
checkBandwidth();
|
|
||||||
threadQueueControl->push(command);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int DemodulatorInstance::getDemodulatorType() {
|
std::string DemodulatorInstance::getDemodulatorType() {
|
||||||
return currentDemodType;
|
return currentDemodType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setDemodulatorLock(bool demod_lock_in) {
|
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() {
|
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) {
|
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() {
|
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) {
|
void DemodulatorInstance::setBandwidth(int bw) {
|
||||||
if (currentDemodType == DEMOD_TYPE_RAW) {
|
if (currentDemodType == "I/Q") {
|
||||||
if (currentAudioSampleRate) {
|
if (currentAudioSampleRate) {
|
||||||
bw = currentAudioSampleRate;
|
bw = currentAudioSampleRate;
|
||||||
} else {
|
} else {
|
||||||
@ -384,7 +385,7 @@ void DemodulatorInstance::setAudioSampleRate(int sampleRate) {
|
|||||||
command.llong_value = sampleRate;
|
command.llong_value = sampleRate;
|
||||||
pipeDemodCommand->push(command);
|
pipeDemodCommand->push(command);
|
||||||
}
|
}
|
||||||
if (currentDemodType == DEMOD_TYPE_RAW) {
|
if (currentDemodType == "I/Q") {
|
||||||
setBandwidth(currentAudioSampleRate);
|
setBandwidth(currentAudioSampleRate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -400,7 +401,7 @@ int DemodulatorInstance::getAudioSampleRate() {
|
|||||||
void DemodulatorInstance::setGain(float gain_in) {
|
void DemodulatorInstance::setGain(float gain_in) {
|
||||||
currentAudioGain = gain_in;
|
currentAudioGain = gain_in;
|
||||||
|
|
||||||
if (currentDemodType == DEMOD_TYPE_RAW) {
|
if (currentDemodType == "I/Q") {
|
||||||
if (gain_in < 0.25) {
|
if (gain_in < 0.25) {
|
||||||
audioThread->setGain(1.0);
|
audioThread->setGain(1.0);
|
||||||
demodulatorThread->setAGC(false);
|
demodulatorThread->setAGC(false);
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
#include "DemodulatorThread.h"
|
#include "DemodulatorThread.h"
|
||||||
#include "DemodulatorPreThread.h"
|
#include "DemodulatorPreThread.h"
|
||||||
|
|
||||||
|
#include "ModemDigital.h"
|
||||||
|
#include "ModemAnalog.h"
|
||||||
|
|
||||||
class DemodulatorInstance {
|
class DemodulatorInstance {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -39,9 +42,6 @@ public:
|
|||||||
bool isActive();
|
bool isActive();
|
||||||
void setActive(bool state);
|
void setActive(bool state);
|
||||||
|
|
||||||
bool isStereo();
|
|
||||||
void setStereo(bool state);
|
|
||||||
|
|
||||||
void squelchAuto();
|
void squelchAuto();
|
||||||
bool isSquelchEnabled();
|
bool isSquelchEnabled();
|
||||||
void setSquelchEnabled(bool state);
|
void setSquelchEnabled(bool state);
|
||||||
@ -53,8 +53,8 @@ public:
|
|||||||
void setOutputDevice(int device_id);
|
void setOutputDevice(int device_id);
|
||||||
int getOutputDevice();
|
int getOutputDevice();
|
||||||
|
|
||||||
void setDemodulatorType(int demod_type_in);
|
void setDemodulatorType(std::string demod_type_in);
|
||||||
int getDemodulatorType();
|
std::string getDemodulatorType();
|
||||||
|
|
||||||
void setDemodulatorLock(bool demod_lock_in);
|
void setDemodulatorLock(bool demod_lock_in);
|
||||||
int getDemodulatorLock();
|
int getDemodulatorLock();
|
||||||
@ -106,13 +106,11 @@ private:
|
|||||||
std::atomic_bool preDemodTerminated;
|
std::atomic_bool preDemodTerminated;
|
||||||
std::atomic_bool active;
|
std::atomic_bool active;
|
||||||
std::atomic_bool squelch;
|
std::atomic_bool squelch;
|
||||||
std::atomic_bool stereo;
|
|
||||||
std::atomic_bool muted;
|
std::atomic_bool muted;
|
||||||
|
|
||||||
std::atomic_llong currentFrequency;
|
std::atomic_llong currentFrequency;
|
||||||
std::atomic_int currentBandwidth;
|
std::atomic_int currentBandwidth;
|
||||||
std::atomic_int currentDemodType;
|
std::string currentDemodType;
|
||||||
std::atomic_int currentDemodCons;
|
|
||||||
std::atomic_int currentOutputDevice;
|
std::atomic_int currentOutputDevice;
|
||||||
std::atomic_int currentAudioSampleRate;
|
std::atomic_int currentAudioSampleRate;
|
||||||
std::atomic<float> currentAudioGain;
|
std::atomic<float> currentAudioGain;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
DemodulatorMgr::DemodulatorMgr() :
|
DemodulatorMgr::DemodulatorMgr() :
|
||||||
activeDemodulator(NULL), lastActiveDemodulator(NULL), activeVisualDemodulator(NULL), lastBandwidth(DEFAULT_DEMOD_BW), lastDemodType(
|
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;
|
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);
|
foundDemods->push_back(testDemod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,7 +166,6 @@ void DemodulatorMgr::updateLastState() {
|
|||||||
lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled();
|
lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled();
|
||||||
lastSquelch = lastActiveDemodulator->getSquelchLevel();
|
lastSquelch = lastActiveDemodulator->getSquelchLevel();
|
||||||
lastGain = lastActiveDemodulator->getGain();
|
lastGain = lastActiveDemodulator->getGain();
|
||||||
lastStereo = lastActiveDemodulator->isStereo();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -184,11 +183,11 @@ void DemodulatorMgr::setLastBandwidth(int lastBandwidth) {
|
|||||||
this->lastBandwidth = lastBandwidth;
|
this->lastBandwidth = lastBandwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DemodulatorMgr::getLastDemodulatorType() const {
|
std::string DemodulatorMgr::getLastDemodulatorType() const {
|
||||||
return lastDemodType;
|
return lastDemodType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorMgr::setLastDemodulatorType(int lastDemodType) {
|
void DemodulatorMgr::setLastDemodulatorType(std::string lastDemodType) {
|
||||||
this->lastDemodType = lastDemodType;
|
this->lastDemodType = lastDemodType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,15 +223,6 @@ void DemodulatorMgr::setLastSquelchEnabled(bool lastSquelchEnabled) {
|
|||||||
this->lastSquelchEnabled = lastSquelchEnabled;
|
this->lastSquelchEnabled = lastSquelchEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DemodulatorMgr::isLastStereo() const {
|
|
||||||
return lastStereo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorMgr::setLastStereo(bool lastStereo) {
|
|
||||||
this->lastStereo = lastStereo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool DemodulatorMgr::isLastMuted() const {
|
bool DemodulatorMgr::isLastMuted() const {
|
||||||
return lastMuted;
|
return lastMuted;
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ public:
|
|||||||
int getLastBandwidth() const;
|
int getLastBandwidth() const;
|
||||||
void setLastBandwidth(int lastBandwidth);
|
void setLastBandwidth(int lastBandwidth);
|
||||||
|
|
||||||
int getLastDemodulatorType() const;
|
std::string getLastDemodulatorType() const;
|
||||||
void setLastDemodulatorType(int lastDemodType);
|
void setLastDemodulatorType(std::string lastDemodType);
|
||||||
|
|
||||||
int getLastDemodulatorCons() const;
|
int getLastDemodulatorCons() const;
|
||||||
void setLastDemodulatorCons(int lastDemodCons);
|
void setLastDemodulatorCons(int lastDemodCons);
|
||||||
@ -40,9 +40,6 @@ public:
|
|||||||
bool isLastSquelchEnabled() const;
|
bool isLastSquelchEnabled() const;
|
||||||
void setLastSquelchEnabled(bool lastSquelchEnabled);
|
void setLastSquelchEnabled(bool lastSquelchEnabled);
|
||||||
|
|
||||||
bool isLastStereo() const;
|
|
||||||
void setLastStereo(bool lastStereo);
|
|
||||||
|
|
||||||
bool isLastMuted() const;
|
bool isLastMuted() const;
|
||||||
void setLastMuted(bool lastMuted);
|
void setLastMuted(bool lastMuted);
|
||||||
|
|
||||||
@ -57,11 +54,11 @@ private:
|
|||||||
DemodulatorInstance *activeVisualDemodulator;
|
DemodulatorInstance *activeVisualDemodulator;
|
||||||
|
|
||||||
int lastBandwidth;
|
int lastBandwidth;
|
||||||
int lastDemodType;
|
std::string lastDemodType;
|
||||||
bool lastDemodLock;
|
bool lastDemodLock;
|
||||||
int lastDemodCons;
|
int lastDemodCons;
|
||||||
bool lastSquelchEnabled;
|
bool lastSquelchEnabled;
|
||||||
float lastSquelch;
|
float lastSquelch;
|
||||||
float lastGain;
|
float lastGain;
|
||||||
bool lastStereo, lastMuted;
|
bool lastMuted;
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "DemodulatorPreThread.h"
|
#include "DemodulatorPreThread.h"
|
||||||
#include "CubicSDR.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);
|
initialized.store(false);
|
||||||
|
|
||||||
@ -24,50 +24,14 @@ DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iq
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorPreThread::initialize() {
|
void DemodulatorPreThread::initialize() {
|
||||||
initialized = false;
|
|
||||||
|
|
||||||
iqResampleRatio = (double) (params.bandwidth) / (double) params.sampleRate;
|
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);
|
iqResampler = msresamp_crcf_create(iqResampleRatio, As);
|
||||||
audioResampler = msresamp_rrrf_create(audioResampleRatio, As);
|
|
||||||
stereoResampler = msresamp_rrrf_create(audioResampleRatio, As);
|
|
||||||
|
|
||||||
// Stereo filters / shifters
|
initialized.store(true);
|
||||||
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;
|
|
||||||
lastParams = params;
|
lastParams = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +52,6 @@ void DemodulatorPreThread::run() {
|
|||||||
|
|
||||||
std::cout << "Demodulator preprocessor thread started.." << std::endl;
|
std::cout << "Demodulator preprocessor thread started.." << std::endl;
|
||||||
|
|
||||||
t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread);
|
|
||||||
|
|
||||||
ReBuffer<DemodulatorThreadPostIQData> buffers;
|
ReBuffer<DemodulatorThreadPostIQData> buffers;
|
||||||
|
|
||||||
iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput");
|
iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput");
|
||||||
@ -99,8 +61,9 @@ void DemodulatorPreThread::run() {
|
|||||||
|
|
||||||
std::vector<liquid_float_complex> in_buf_data;
|
std::vector<liquid_float_complex> in_buf_data;
|
||||||
std::vector<liquid_float_complex> out_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) {
|
while (!terminated) {
|
||||||
DemodulatorThreadIQData *inp;
|
DemodulatorThreadIQData *inp;
|
||||||
@ -218,40 +181,11 @@ void DemodulatorPreThread::run() {
|
|||||||
msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten);
|
msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten);
|
||||||
|
|
||||||
resamp->setRefCount(1);
|
resamp->setRefCount(1);
|
||||||
|
|
||||||
resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
|
resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
|
||||||
|
|
||||||
// bool uneven = (numWritten % 2 != 0);
|
resamp->modemType = demodType;
|
||||||
|
resamp->modem = cModem;
|
||||||
// if (!carrySampleFlag && !uneven) {
|
resamp->modemKit = cModemKit;
|
||||||
// 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->sampleRate = params.bandwidth;
|
resamp->sampleRate = params.bandwidth;
|
||||||
|
|
||||||
iqOutputQueue->push(resamp);
|
iqOutputQueue->push(resamp);
|
||||||
@ -266,33 +200,21 @@ void DemodulatorPreThread::run() {
|
|||||||
|
|
||||||
switch (result.cmd) {
|
switch (result.cmd) {
|
||||||
case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS:
|
case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS:
|
||||||
msresamp_crcf_destroy(iqResampler);
|
|
||||||
|
|
||||||
if (result.iqResampler) {
|
if (result.iqResampler) {
|
||||||
|
if (iqResampler) {
|
||||||
|
msresamp_crcf_destroy(iqResampler);
|
||||||
|
}
|
||||||
iqResampler = result.iqResampler;
|
iqResampler = result.iqResampler;
|
||||||
iqResampleRatio = result.iqResampleRatio;
|
iqResampleRatio = result.iqResampleRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.firStereoLeft) {
|
if (result.modem != nullptr) {
|
||||||
firStereoLeft = result.firStereoLeft;
|
cModem = result.modem;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.firStereoRight) {
|
if (result.modemKit != nullptr) {
|
||||||
firStereoRight = result.firStereoRight;
|
cModemKit = result.modemKit;
|
||||||
}
|
|
||||||
|
|
||||||
if (result.iirStereoPilot) {
|
|
||||||
iirStereoPilot = result.iirStereoPilot;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.audioResampler) {
|
|
||||||
audioResampler = result.audioResampler;
|
|
||||||
audioResampleRatio = result.audioResamplerRatio;
|
|
||||||
stereoResampler = result.stereoResampler;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.audioSampleRate) {
|
|
||||||
params.audioSampleRate = result.audioSampleRate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.bandwidth) {
|
if (result.bandwidth) {
|
||||||
@ -302,6 +224,12 @@ void DemodulatorPreThread::run() {
|
|||||||
if (result.sampleRate) {
|
if (result.sampleRate) {
|
||||||
params.sampleRate = result.sampleRate;
|
params.sampleRate = result.sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.modemType != "") {
|
||||||
|
demodType = result.modemType;
|
||||||
|
params.demodType = result.modemType;
|
||||||
|
demodTypeChanged.store(false);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -318,6 +246,31 @@ void DemodulatorPreThread::run() {
|
|||||||
std::cout << "Demodulator preprocessor thread done." << std::endl;
|
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() {
|
void DemodulatorPreThread::terminate() {
|
||||||
terminated = true;
|
terminated = true;
|
||||||
DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue
|
DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue
|
||||||
@ -331,3 +284,12 @@ void DemodulatorPreThread::terminate() {
|
|||||||
delete workerResults;
|
delete workerResults;
|
||||||
delete workerQueue;
|
delete workerQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Modem *DemodulatorPreThread::getModem() {
|
||||||
|
return cModem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemKit *DemodulatorPreThread::getModemKit() {
|
||||||
|
return cModemKit;
|
||||||
|
}
|
||||||
|
@ -15,35 +15,25 @@ public:
|
|||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
DemodulatorThreadParameters &getParams() {
|
DemodulatorThreadParameters &getParams();
|
||||||
return params;
|
void setParams(DemodulatorThreadParameters ¶ms_in);
|
||||||
}
|
|
||||||
|
|
||||||
void setParams(DemodulatorThreadParameters ¶ms_in) {
|
void setDemodType(std::string demodType);
|
||||||
params = params_in;
|
std::string getDemodType();
|
||||||
}
|
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
#ifdef __APPLE__
|
Modem *getModem();
|
||||||
static void *pthread_helper(void *context) {
|
ModemKit *getModemKit();
|
||||||
return ((DemodulatorPreThread *) context)->threadMain();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
msresamp_crcf iqResampler;
|
msresamp_crcf iqResampler;
|
||||||
double iqResampleRatio;
|
double iqResampleRatio;
|
||||||
std::vector<liquid_float_complex> resampledData;
|
std::vector<liquid_float_complex> resampledData;
|
||||||
|
|
||||||
msresamp_rrrf audioResampler;
|
Modem *cModem;
|
||||||
msresamp_rrrf stereoResampler;
|
ModemKit *cModemKit;
|
||||||
double audioResampleRatio;
|
|
||||||
|
|
||||||
firfilt_rrrf firStereoLeft;
|
|
||||||
firfilt_rrrf firStereoRight;
|
|
||||||
iirfilt_crcf iirStereoPilot;
|
|
||||||
|
|
||||||
DemodulatorThreadParameters params;
|
DemodulatorThreadParameters params;
|
||||||
DemodulatorThreadParameters lastParams;
|
DemodulatorThreadParameters lastParams;
|
||||||
@ -52,6 +42,9 @@ protected:
|
|||||||
int shiftFrequency;
|
int shiftFrequency;
|
||||||
|
|
||||||
std::atomic_bool initialized;
|
std::atomic_bool initialized;
|
||||||
|
std::atomic_bool demodTypeChanged;
|
||||||
|
std::string demodType;
|
||||||
|
std::string newDemodType;
|
||||||
|
|
||||||
DemodulatorWorkerThread *workerThread;
|
DemodulatorWorkerThread *workerThread;
|
||||||
std::thread *t_Worker;
|
std::thread *t_Worker;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "CubicSDRDefs.h"
|
#include "CubicSDRDefs.h"
|
||||||
#include "DemodulatorThread.h"
|
#include "DemodulatorThread.h"
|
||||||
|
#include "DemodulatorInstance.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -11,89 +12,16 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DemodulatorThread::DemodulatorThread() : IOThread(), iqAutoGain(NULL), amOutputCeil(1), amOutputCeilMA(1), amOutputCeilMAA(1), audioSampleRate(0), squelchLevel(0), signalLevel(0), squelchEnabled(false), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) {
|
DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) : IOThread(), iqAutoGain(NULL), audioSampleRate(0), squelchLevel(0), signalLevel(0), squelchEnabled(false), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) {
|
||||||
|
|
||||||
stereo.store(false);
|
demodInstance = parent;
|
||||||
muted.store(false);
|
muted.store(false);
|
||||||
agcEnabled.store(false);
|
agcEnabled.store(false);
|
||||||
demodulatorType.store(DEMOD_TYPE_FM);
|
|
||||||
|
|
||||||
demodFM = freqdem_create(0.5);
|
|
||||||
demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1);
|
|
||||||
demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1);
|
|
||||||
demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1);
|
|
||||||
demodAM_DSB_CSP = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
|
|
||||||
demodAM = demodAM_DSB_CSP;
|
|
||||||
|
|
||||||
// advanced demodulators
|
|
||||||
|
|
||||||
demodulatorCons.store(2);
|
|
||||||
currentDemodCons = 0;
|
|
||||||
|
|
||||||
demodASK = demodASK2;
|
|
||||||
demodASK2 = modem_create(LIQUID_MODEM_ASK2);
|
|
||||||
demodASK4 = modem_create(LIQUID_MODEM_ASK4);
|
|
||||||
demodASK8 = modem_create(LIQUID_MODEM_ASK8);
|
|
||||||
demodASK16 = modem_create(LIQUID_MODEM_ASK16);
|
|
||||||
demodASK32 = modem_create(LIQUID_MODEM_ASK32);
|
|
||||||
demodASK64 = modem_create(LIQUID_MODEM_ASK64);
|
|
||||||
demodASK128 = modem_create(LIQUID_MODEM_ASK128);
|
|
||||||
demodASK256 = modem_create(LIQUID_MODEM_ASK256);
|
|
||||||
|
|
||||||
demodAPSK = demodAPSK4;
|
|
||||||
demodAPSK4 = modem_create(LIQUID_MODEM_APSK4);
|
|
||||||
demodAPSK8 = modem_create(LIQUID_MODEM_APSK8);
|
|
||||||
demodAPSK16 = modem_create(LIQUID_MODEM_APSK16);
|
|
||||||
demodAPSK32 = modem_create(LIQUID_MODEM_APSK32);
|
|
||||||
demodAPSK64 = modem_create(LIQUID_MODEM_APSK64);
|
|
||||||
demodAPSK128 = modem_create(LIQUID_MODEM_APSK128);
|
|
||||||
demodAPSK256 = modem_create(LIQUID_MODEM_APSK256);
|
|
||||||
|
|
||||||
demodBPSK = modem_create(LIQUID_MODEM_BPSK);
|
|
||||||
|
|
||||||
demodDPSK = demodDPSK2;
|
|
||||||
demodDPSK2 = modem_create(LIQUID_MODEM_DPSK2);
|
|
||||||
demodDPSK4 = modem_create(LIQUID_MODEM_DPSK4);
|
|
||||||
demodDPSK8 = modem_create(LIQUID_MODEM_DPSK8);
|
|
||||||
demodDPSK16 = modem_create(LIQUID_MODEM_DPSK16);
|
|
||||||
demodDPSK32 = modem_create(LIQUID_MODEM_DPSK32);
|
|
||||||
demodDPSK64 = modem_create(LIQUID_MODEM_DPSK64);
|
|
||||||
demodDPSK128 = modem_create(LIQUID_MODEM_DPSK128);
|
|
||||||
demodDPSK256 = modem_create(LIQUID_MODEM_DPSK256);
|
|
||||||
|
|
||||||
demodPSK = demodPSK2;
|
|
||||||
demodPSK2 = modem_create(LIQUID_MODEM_PSK2);
|
|
||||||
demodPSK4 = modem_create(LIQUID_MODEM_PSK4);
|
|
||||||
demodPSK8 = modem_create(LIQUID_MODEM_PSK8);
|
|
||||||
demodPSK16 = modem_create(LIQUID_MODEM_PSK16);
|
|
||||||
demodPSK32 = modem_create(LIQUID_MODEM_PSK32);
|
|
||||||
demodPSK64 = modem_create(LIQUID_MODEM_PSK64);
|
|
||||||
demodPSK128 = modem_create(LIQUID_MODEM_PSK128);
|
|
||||||
demodPSK256 = modem_create(LIQUID_MODEM_PSK256);
|
|
||||||
|
|
||||||
demodOOK = modem_create(LIQUID_MODEM_OOK);
|
|
||||||
|
|
||||||
demodSQAM = demodSQAM32;
|
|
||||||
demodSQAM32 = modem_create(LIQUID_MODEM_SQAM32);
|
|
||||||
demodSQAM128 = modem_create(LIQUID_MODEM_SQAM128);
|
|
||||||
|
|
||||||
demodST = modem_create(LIQUID_MODEM_V29);
|
|
||||||
|
|
||||||
demodQAM = demodQAM4;
|
|
||||||
demodQAM4 = modem_create(LIQUID_MODEM_QAM4);
|
|
||||||
demodQAM8 = modem_create(LIQUID_MODEM_QAM8);
|
|
||||||
demodQAM16 = modem_create(LIQUID_MODEM_QAM16);
|
|
||||||
demodQAM32 = modem_create(LIQUID_MODEM_QAM32);
|
|
||||||
demodQAM64 = modem_create(LIQUID_MODEM_QAM64);
|
|
||||||
demodQAM128 = modem_create(LIQUID_MODEM_QAM128);
|
|
||||||
demodQAM256 = modem_create(LIQUID_MODEM_QAM256);
|
|
||||||
|
|
||||||
demodQPSK = modem_create(LIQUID_MODEM_QPSK);
|
|
||||||
|
|
||||||
currentDemodLock = false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorThread::~DemodulatorThread() {
|
DemodulatorThread::~DemodulatorThread() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) {
|
void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) {
|
||||||
@ -110,24 +38,6 @@ void DemodulatorThread::run() {
|
|||||||
pthread_setschedparam(tID, SCHED_FIFO, &prio);
|
pthread_setschedparam(tID, SCHED_FIFO, &prio);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
msresamp_rrrf audioResampler = NULL;
|
|
||||||
msresamp_rrrf stereoResampler = NULL;
|
|
||||||
firfilt_rrrf firStereoLeft = NULL;
|
|
||||||
firfilt_rrrf firStereoRight = NULL;
|
|
||||||
iirfilt_crcf iirStereoPilot = NULL;
|
|
||||||
|
|
||||||
liquid_float_complex u, v, w, x, y;
|
|
||||||
|
|
||||||
firhilbf firStereoR2C = firhilbf_create(5, 60.0f);
|
|
||||||
firhilbf firStereoC2R = firhilbf_create(5, 60.0f);
|
|
||||||
|
|
||||||
nco_crcf stereoPilot = nco_crcf_create(LIQUID_VCO);
|
|
||||||
nco_crcf_reset(stereoPilot);
|
|
||||||
nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f);
|
|
||||||
|
|
||||||
// half band filter used for side-band elimination
|
|
||||||
resamp2_crcf ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
|
||||||
|
|
||||||
// Automatic IQ gain
|
// Automatic IQ gain
|
||||||
iqAutoGain = agc_crcf_create();
|
iqAutoGain = agc_crcf_create();
|
||||||
agc_crcf_set_bandwidth(iqAutoGain, 0.1);
|
agc_crcf_set_bandwidth(iqAutoGain, 0.1);
|
||||||
@ -141,27 +51,14 @@ void DemodulatorThread::run() {
|
|||||||
threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue");
|
threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue");
|
||||||
threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue");
|
threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue");
|
||||||
|
|
||||||
switch (demodulatorType.load()) {
|
ModemIQData modemData;
|
||||||
case DEMOD_TYPE_FM:
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_LSB:
|
|
||||||
demodAM = demodAM_LSB;
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_USB:
|
|
||||||
demodAM = demodAM_USB;
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_DSB:
|
|
||||||
demodAM = demodAM_DSB;
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_AM:
|
|
||||||
demodAM = demodAM_DSB_CSP;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
DemodulatorThreadPostIQData *inp;
|
DemodulatorThreadPostIQData *inp;
|
||||||
iqInputQueue->pop(inp);
|
iqInputQueue->pop(inp);
|
||||||
// std::lock_guard < std::mutex > lock(inp->m_mutex);
|
// std::lock_guard < std::mutex > lock(inp->m_mutex);
|
||||||
|
|
||||||
|
audioSampleRate = demodInstance->getAudioSampleRate();
|
||||||
|
|
||||||
int bufSize = inp->data.size();
|
int bufSize = inp->data.size();
|
||||||
|
|
||||||
@ -170,75 +67,30 @@ void DemodulatorThread::run() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioResampler == NULL) {
|
if (inp->modemKit && inp->modemKit != cModemKit) {
|
||||||
audioResampler = inp->audioResampler;
|
if (cModemKit != nullptr) {
|
||||||
stereoResampler = inp->stereoResampler;
|
cModem->disposeKit(cModemKit);
|
||||||
firStereoLeft = inp->firStereoLeft;
|
|
||||||
firStereoRight = inp->firStereoRight;
|
|
||||||
iirStereoPilot = inp->iirStereoPilot;
|
|
||||||
audioSampleRate = inp->audioSampleRate;
|
|
||||||
} else if (audioResampler != inp->audioResampler) {
|
|
||||||
msresamp_rrrf_destroy(audioResampler);
|
|
||||||
msresamp_rrrf_destroy(stereoResampler);
|
|
||||||
audioResampler = inp->audioResampler;
|
|
||||||
stereoResampler = inp->stereoResampler;
|
|
||||||
audioSampleRate = inp->audioSampleRate;
|
|
||||||
|
|
||||||
if (demodAM) {
|
|
||||||
ampmodem_reset(demodAM);
|
|
||||||
}
|
}
|
||||||
freqdem_reset(demodFM);
|
cModemKit = inp->modemKit;
|
||||||
nco_crcf_reset(stereoPilot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firStereoLeft != inp->firStereoLeft) {
|
if (inp->modem && inp->modem != cModem) {
|
||||||
if (firStereoLeft != NULL) {
|
delete cModem;
|
||||||
firfilt_rrrf_destroy(firStereoLeft);
|
cModem = inp->modem;
|
||||||
}
|
|
||||||
firStereoLeft = inp->firStereoLeft;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firStereoRight != inp->firStereoRight) {
|
if (!cModem || !cModemKit) {
|
||||||
if (firStereoRight != NULL) {
|
inp->decRefCount();
|
||||||
firfilt_rrrf_destroy(firStereoRight);
|
continue;
|
||||||
}
|
|
||||||
firStereoRight = inp->firStereoRight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iirStereoPilot != inp->iirStereoPilot) {
|
|
||||||
if (iirStereoPilot != NULL) {
|
|
||||||
iirfilt_crcf_destroy(iirStereoPilot);
|
|
||||||
}
|
|
||||||
iirStereoPilot = inp->iirStereoPilot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agcData.size() != bufSize) {
|
if (agcData.size() != bufSize) {
|
||||||
if (agcData.capacity() < bufSize) {
|
if (agcData.capacity() < bufSize) {
|
||||||
agcData.reserve(bufSize);
|
agcData.reserve(bufSize);
|
||||||
agcAMData.reserve(bufSize);
|
|
||||||
}
|
}
|
||||||
agcData.resize(bufSize);
|
agcData.resize(bufSize);
|
||||||
agcAMData.resize(bufSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double audio_resample_ratio = inp->audioResampleRatio;
|
|
||||||
|
|
||||||
if (demodOutputData.size() != bufSize) {
|
|
||||||
if (demodOutputData.capacity() < bufSize) {
|
|
||||||
demodOutputData.reserve(bufSize);
|
|
||||||
}
|
|
||||||
demodOutputData.resize(bufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (demodOutputDataDigital.size() != bufSize) {
|
|
||||||
if (demodOutputDataDigital.capacity() < bufSize) {
|
|
||||||
demodOutputDataDigital.reserve(bufSize);
|
|
||||||
}
|
|
||||||
demodOutputDataDigital.resize(bufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512;
|
|
||||||
|
|
||||||
agc_crcf_execute_block(iqAutoGain, &(inp->data[0]), bufSize, &agcData[0]);
|
agc_crcf_execute_block(iqAutoGain, &(inp->data[0]), bufSize, &agcData[0]);
|
||||||
|
|
||||||
float currentSignalLevel = 0;
|
float currentSignalLevel = 0;
|
||||||
@ -257,419 +109,23 @@ void DemodulatorThread::run() {
|
|||||||
inputData = &inp->data;
|
inputData = &inp->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset demodulator Constellations & Lock
|
modemData.sampleRate = inp->sampleRate;
|
||||||
updateDemodulatorCons(0);
|
modemData.data.assign(inputData->begin(), inputData->end());
|
||||||
|
modemData.setRefCount(1);
|
||||||
|
|
||||||
if (demodulatorType == DEMOD_TYPE_FM) {
|
AudioThreadInput *ati = NULL;
|
||||||
currentDemodLock = false;
|
|
||||||
freqdem_demodulate_block(demodFM, &(*inputData)[0], bufSize, &demodOutputData[0]);
|
ModemAnalog *modemAnalog = (cModem->getType() == "analog")?((ModemAnalog *)cModem):nullptr;
|
||||||
} else if (demodulatorType == DEMOD_TYPE_RAW) {
|
// ModemDigital *modemDigital = (cModem->getType() == "digital")?((ModemDigital *)cModem):nullptr;
|
||||||
// do nothing here..
|
|
||||||
} else {
|
if (modemAnalog != nullptr) {
|
||||||
switch (demodulatorType.load()) {
|
ati = outputBuffers.getBuffer();
|
||||||
case DEMOD_TYPE_LSB:
|
|
||||||
currentDemodLock = false;
|
ati->sampleRate = audioSampleRate;
|
||||||
for (int i = 0; i < bufSize; i++) { // Reject upper band
|
ati->inputRate = inp->sampleRate;
|
||||||
resamp2_crcf_filter_execute(ssbFilt,(*inputData)[i],&x,&y);
|
ati->setRefCount(1);
|
||||||
ampmodem_demodulate(demodAM, x, &demodOutputData[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_USB:
|
|
||||||
currentDemodLock = false;
|
|
||||||
for (int i = 0; i < bufSize; i++) { // Reject lower band
|
|
||||||
resamp2_crcf_filter_execute(ssbFilt,(*inputData)[i],&x,&y);
|
|
||||||
ampmodem_demodulate(demodAM, y, &demodOutputData[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_AM:
|
|
||||||
case DEMOD_TYPE_DSB:
|
|
||||||
currentDemodLock = false;
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
ampmodem_demodulate(demodAM, (*inputData)[i], &demodOutputData[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
// advanced demodulators
|
|
||||||
case DEMOD_TYPE_ASK:
|
|
||||||
|
|
||||||
switch (demodulatorCons.load()) {
|
|
||||||
case 2:
|
|
||||||
demodASK = demodASK2;
|
|
||||||
updateDemodulatorCons(2);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
demodASK = demodASK4;
|
|
||||||
updateDemodulatorCons(4);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
demodASK = demodASK8;
|
|
||||||
updateDemodulatorCons(8);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
demodASK = demodASK16;
|
|
||||||
updateDemodulatorCons(16);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
demodASK = demodASK32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
demodASK = demodASK64;
|
|
||||||
updateDemodulatorCons(64);
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
demodASK = demodASK128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
demodASK = demodASK256;
|
|
||||||
updateDemodulatorCons(256);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
demodASK = demodASK2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodASK, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodASK, 0.005f);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_APSK:
|
|
||||||
|
|
||||||
switch (demodulatorCons.load()) {
|
|
||||||
case 2:
|
|
||||||
demodAPSK = demodAPSK4;
|
|
||||||
updateDemodulatorCons(4);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
demodAPSK = demodAPSK4;
|
|
||||||
updateDemodulatorCons(4);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
demodAPSK = demodAPSK8;
|
|
||||||
updateDemodulatorCons(8);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
demodAPSK = demodAPSK16;
|
|
||||||
updateDemodulatorCons(16);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
demodAPSK = demodAPSK32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
demodAPSK = demodAPSK64;
|
|
||||||
updateDemodulatorCons(64);
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
demodAPSK = demodAPSK128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
demodAPSK = demodAPSK256;
|
|
||||||
updateDemodulatorCons(256);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
demodAPSK = demodAPSK4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodAPSK, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodAPSK, 0.005f);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_BPSK:
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodBPSK, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodBPSK, 0.005f);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_DPSK:
|
|
||||||
|
|
||||||
switch (demodulatorCons.load()) {
|
|
||||||
case 2:
|
|
||||||
demodDPSK = demodDPSK2;
|
|
||||||
updateDemodulatorCons(2);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
demodDPSK = demodDPSK4;
|
|
||||||
updateDemodulatorCons(4);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
demodDPSK = demodDPSK8;
|
|
||||||
updateDemodulatorCons(8);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
demodDPSK = demodDPSK16;
|
|
||||||
updateDemodulatorCons(16);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
demodDPSK = demodDPSK32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
demodDPSK = demodDPSK64;
|
|
||||||
updateDemodulatorCons(64);
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
demodDPSK = demodDPSK128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
demodDPSK = demodDPSK256;
|
|
||||||
updateDemodulatorCons(256);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
demodDPSK = demodDPSK2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodDPSK, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodDPSK, 0.005f);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_PSK:
|
|
||||||
|
|
||||||
switch (demodulatorCons.load()) {
|
|
||||||
case 2:
|
|
||||||
demodPSK = demodPSK2;
|
|
||||||
updateDemodulatorCons(2);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
demodPSK = demodPSK4;
|
|
||||||
updateDemodulatorCons(4);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
demodPSK = demodPSK8;
|
|
||||||
updateDemodulatorCons(8);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
demodPSK = demodPSK16;
|
|
||||||
updateDemodulatorCons(16);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
demodPSK = demodPSK32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
demodPSK = demodPSK64;
|
|
||||||
updateDemodulatorCons(64);
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
demodPSK = demodPSK128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
demodPSK = demodPSK256;
|
|
||||||
updateDemodulatorCons(256);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
demodPSK = demodPSK2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodPSK, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodPSK, 0.005f);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_OOK:
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodOOK, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodOOK, 0.005f);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_SQAM:
|
|
||||||
|
|
||||||
switch (demodulatorCons.load()) {
|
|
||||||
case 2:
|
|
||||||
demodSQAM = demodSQAM32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
demodSQAM = demodSQAM32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
demodSQAM = demodSQAM32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
demodSQAM = demodSQAM32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
demodSQAM = demodSQAM32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
demodSQAM = demodSQAM32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
demodSQAM = demodSQAM128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
demodSQAM = demodSQAM128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
demodSQAM = demodSQAM32;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodSQAM, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodSQAM, 0.005f);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_ST:
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodST, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodST, 0.005f);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_QAM:
|
|
||||||
|
|
||||||
switch (demodulatorCons.load()) {
|
|
||||||
case 2:
|
|
||||||
demodQAM = demodQAM4;
|
|
||||||
updateDemodulatorCons(4);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
demodQAM = demodQAM4;
|
|
||||||
updateDemodulatorCons(4);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
demodQAM = demodQAM8;
|
|
||||||
updateDemodulatorCons(8);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
demodQAM = demodQAM16;
|
|
||||||
updateDemodulatorCons(16);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
demodQAM = demodQAM32;
|
|
||||||
updateDemodulatorCons(32);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
demodQAM = demodQAM64;
|
|
||||||
updateDemodulatorCons(64);
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
demodQAM = demodQAM128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
demodQAM = demodQAM256;
|
|
||||||
updateDemodulatorCons(256);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
demodQAM = demodQAM4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodQAM, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodQAM, 0.5f);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_QPSK:
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
modem_demodulate(demodQPSK, inp->data[i], &demodOutputDataDigital[i]);
|
|
||||||
}
|
|
||||||
updateDemodulatorLock(demodQPSK, 0.8f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
amOutputCeilMA = amOutputCeilMA + (amOutputCeil - amOutputCeilMA) * 0.025;
|
|
||||||
amOutputCeilMAA = amOutputCeilMAA + (amOutputCeilMA - amOutputCeilMAA) * 0.025;
|
|
||||||
|
|
||||||
amOutputCeil = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
if (demodOutputData[i] > amOutputCeil) {
|
|
||||||
amOutputCeil = demodOutputData[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float gain = 0.5 / amOutputCeilMAA;
|
|
||||||
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
demodOutputData[i] *= gain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audio_out_size != resampledOutputData.size()) {
|
|
||||||
if (resampledOutputData.capacity() < audio_out_size) {
|
|
||||||
resampledOutputData.reserve(audio_out_size);
|
|
||||||
}
|
|
||||||
resampledOutputData.resize(audio_out_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int numAudioWritten;
|
|
||||||
|
|
||||||
if (demodulatorType == DEMOD_TYPE_RAW) {
|
|
||||||
numAudioWritten = bufSize;
|
|
||||||
} else {
|
|
||||||
msresamp_rrrf_execute(audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten);
|
|
||||||
|
|
||||||
if (stereo && inp->sampleRate >= 100000) {
|
|
||||||
if (demodStereoData.size() != bufSize) {
|
|
||||||
if (demodStereoData.capacity() < bufSize) {
|
|
||||||
demodStereoData.reserve(bufSize);
|
|
||||||
}
|
|
||||||
demodStereoData.resize(bufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float phase_error = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < bufSize; i++) {
|
|
||||||
// real -> complex
|
|
||||||
firhilbf_r2c_execute(firStereoR2C, demodOutputData[i], &x);
|
|
||||||
|
|
||||||
// 19khz pilot band-pass
|
|
||||||
iirfilt_crcf_execute(iirStereoPilot, x, &v);
|
|
||||||
nco_crcf_cexpf(stereoPilot, &w);
|
|
||||||
|
|
||||||
w.imag = -w.imag; // conjf(w)
|
|
||||||
|
|
||||||
// multiply u = v * conjf(w)
|
|
||||||
u.real = v.real * w.real - v.imag * w.imag;
|
|
||||||
u.imag = v.real * w.imag + v.imag * w.real;
|
|
||||||
|
|
||||||
// cargf(u)
|
|
||||||
phase_error = atan2f(u.imag,u.real);
|
|
||||||
|
|
||||||
// step pll
|
|
||||||
nco_crcf_pll_step(stereoPilot, phase_error);
|
|
||||||
nco_crcf_step(stereoPilot);
|
|
||||||
|
|
||||||
// 38khz down-mix
|
|
||||||
nco_crcf_mix_down(stereoPilot, x, &y);
|
|
||||||
nco_crcf_mix_down(stereoPilot, y, &x);
|
|
||||||
|
|
||||||
// complex -> real
|
|
||||||
firhilbf_c2r_execute(firStereoC2R, x, &demodStereoData[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::cout << "[PLL] phase error: " << phase_error;
|
|
||||||
// std::cout << " freq:" << (((nco_crcf_get_frequency(stereoPilot) / (2.0 * M_PI)) * inp->sampleRate)) << std::endl;
|
|
||||||
|
|
||||||
if (audio_out_size != resampledStereoData.size()) {
|
|
||||||
if (resampledStereoData.capacity() < audio_out_size) {
|
|
||||||
resampledStereoData.reserve(audio_out_size);
|
|
||||||
}
|
|
||||||
resampledStereoData.resize(audio_out_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
msresamp_rrrf_execute(stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
cModem->demodulate(cModemKit, &modemData, ati);
|
||||||
|
|
||||||
if (currentSignalLevel > signalLevel) {
|
if (currentSignalLevel > signalLevel) {
|
||||||
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5;
|
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5;
|
||||||
@ -677,50 +133,8 @@ void DemodulatorThread::run() {
|
|||||||
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05;
|
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioThreadInput *ati = NULL;
|
|
||||||
|
|
||||||
if (audioOutputQueue != NULL) {
|
if (audioOutputQueue != NULL) {
|
||||||
if (!squelchEnabled || (signalLevel >= squelchLevel)) {
|
if (ati && (!squelchEnabled || (signalLevel >= squelchLevel))) {
|
||||||
|
|
||||||
ati = outputBuffers.getBuffer();
|
|
||||||
|
|
||||||
ati->sampleRate = audioSampleRate;
|
|
||||||
ati->inputRate = inp->sampleRate;
|
|
||||||
ati->setRefCount(1);
|
|
||||||
|
|
||||||
if (demodulatorType == DEMOD_TYPE_RAW) {
|
|
||||||
ati->channels = 2;
|
|
||||||
if (ati->data.capacity() < (numAudioWritten * 2)) {
|
|
||||||
ati->data.reserve(numAudioWritten * 2);
|
|
||||||
}
|
|
||||||
ati->data.resize(numAudioWritten * 2);
|
|
||||||
for (int i = 0; i < numAudioWritten; i++) {
|
|
||||||
ati->data[i * 2] = (*inputData)[i].imag;
|
|
||||||
ati->data[i * 2 + 1] = (*inputData)[i].real;
|
|
||||||
}
|
|
||||||
} else if (stereo && inp->sampleRate >= 100000) {
|
|
||||||
ati->channels = 2;
|
|
||||||
if (ati->data.capacity() < (numAudioWritten * 2)) {
|
|
||||||
ati->data.reserve(numAudioWritten * 2);
|
|
||||||
}
|
|
||||||
ati->data.resize(numAudioWritten * 2);
|
|
||||||
for (int i = 0; i < numAudioWritten; i++) {
|
|
||||||
float l, r;
|
|
||||||
|
|
||||||
firfilt_rrrf_push(firStereoLeft, 0.568 * (resampledOutputData[i] - (resampledStereoData[i])));
|
|
||||||
firfilt_rrrf_execute(firStereoLeft, &l);
|
|
||||||
|
|
||||||
firfilt_rrrf_push(firStereoRight, 0.568 * (resampledOutputData[i] + (resampledStereoData[i])));
|
|
||||||
firfilt_rrrf_execute(firStereoRight, &r);
|
|
||||||
|
|
||||||
ati->data[i * 2] = l;
|
|
||||||
ati->data[i * 2 + 1] = r;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ati->channels = 1;
|
|
||||||
ati->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + numAudioWritten);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<float>::iterator data_i;
|
std::vector<float>::iterator data_i;
|
||||||
ati->peak = 0;
|
ati->peak = 0;
|
||||||
for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) {
|
for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) {
|
||||||
@ -739,7 +153,7 @@ void DemodulatorThread::run() {
|
|||||||
ati_vis->inputRate = inp->sampleRate;
|
ati_vis->inputRate = inp->sampleRate;
|
||||||
|
|
||||||
int num_vis = DEMOD_VIS_SIZE;
|
int num_vis = DEMOD_VIS_SIZE;
|
||||||
if (demodulatorType == DEMOD_TYPE_RAW || (stereo && inp->sampleRate >= 100000)) {
|
if (ati->channels==2) {
|
||||||
ati_vis->channels = 2;
|
ati_vis->channels = 2;
|
||||||
int stereoSize = ati->data.size();
|
int stereoSize = ati->data.size();
|
||||||
if (stereoSize > DEMOD_VIS_SIZE * 2) {
|
if (stereoSize > DEMOD_VIS_SIZE * 2) {
|
||||||
@ -748,7 +162,7 @@ void DemodulatorThread::run() {
|
|||||||
|
|
||||||
ati_vis->data.resize(stereoSize);
|
ati_vis->data.resize(stereoSize);
|
||||||
|
|
||||||
if (demodulatorType == DEMOD_TYPE_RAW) {
|
if (inp->modemType == "I/Q") {
|
||||||
for (int i = 0; i < stereoSize / 2; i++) {
|
for (int i = 0; i < stereoSize / 2; i++) {
|
||||||
ati_vis->data[i] = agcData[i].real * 0.75;
|
ati_vis->data[i] = agcData[i].real * 0.75;
|
||||||
ati_vis->data[i + stereoSize / 2] = agcData[i].imag * 0.75;
|
ati_vis->data[i + stereoSize / 2] = agcData[i].imag * 0.75;
|
||||||
@ -762,26 +176,29 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
int numAudioWritten = ati->data.size();
|
||||||
ati_vis->channels = 1;
|
ati_vis->channels = 1;
|
||||||
if (numAudioWritten > bufSize) {
|
std::vector<float> *demodOutData = (modemAnalog != nullptr)?modemAnalog->getDemodOutputData():nullptr;
|
||||||
|
if ((numAudioWritten > bufSize) || (demodOutData == nullptr)) {
|
||||||
ati_vis->inputRate = audioSampleRate;
|
ati_vis->inputRate = audioSampleRate;
|
||||||
if (num_vis > numAudioWritten) {
|
if (num_vis > numAudioWritten) {
|
||||||
num_vis = numAudioWritten;
|
num_vis = numAudioWritten;
|
||||||
}
|
}
|
||||||
ati_vis->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + num_vis);
|
ati_vis->data.assign(ati->data.begin(), ati->data.begin() + num_vis);
|
||||||
} else {
|
} else {
|
||||||
if (num_vis > bufSize) {
|
if (num_vis > demodOutData->size()) {
|
||||||
num_vis = bufSize;
|
num_vis = demodOutData->size();
|
||||||
}
|
}
|
||||||
ati_vis->data.assign(demodOutputData.begin(), demodOutputData.begin() + num_vis);
|
ati_vis->data.assign(demodOutData->begin(), demodOutData->begin() + num_vis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::cout << "Signal: " << agc_crcf_get_signal_level(agc) << " -- " << agc_crcf_get_rssi(agc) << "dB " << std::endl;
|
// std::cout << "Signal: " << agc_crcf_get_signal_level(agc) << " -- " << agc_crcf_get_rssi(agc) << "dB " << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
audioVisOutputQueue->push(ati_vis);
|
audioVisOutputQueue->push(ati_vis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ati != NULL) {
|
if (ati != NULL) {
|
||||||
if (!muted.load()) {
|
if (!muted.load()) {
|
||||||
audioOutputQueue->push(ati);
|
audioOutputQueue->push(ati);
|
||||||
@ -791,8 +208,6 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!threadQueueControl->empty()) {
|
if (!threadQueueControl->empty()) {
|
||||||
int newDemodType = DEMOD_TYPE_NULL;
|
|
||||||
|
|
||||||
while (!threadQueueControl->empty()) {
|
while (!threadQueueControl->empty()) {
|
||||||
DemodulatorThreadControlCommand command;
|
DemodulatorThreadControlCommand command;
|
||||||
threadQueueControl->pop(command);
|
threadQueueControl->pop(command);
|
||||||
@ -804,101 +219,16 @@ void DemodulatorThread::run() {
|
|||||||
case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF:
|
case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF:
|
||||||
squelchEnabled = false;
|
squelchEnabled = false;
|
||||||
break;
|
break;
|
||||||
case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE:
|
|
||||||
newDemodType = command.demodType;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newDemodType != DEMOD_TYPE_NULL) {
|
|
||||||
switch (newDemodType) {
|
|
||||||
case DEMOD_TYPE_FM:
|
|
||||||
freqdem_reset(demodFM);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_LSB:
|
|
||||||
demodAM = demodAM_LSB;
|
|
||||||
ampmodem_reset(demodAM);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_USB:
|
|
||||||
demodAM = demodAM_USB;
|
|
||||||
ampmodem_reset(demodAM);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_DSB:
|
|
||||||
demodAM = demodAM_DSB;
|
|
||||||
ampmodem_reset(demodAM);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_AM:
|
|
||||||
demodAM = demodAM_DSB_CSP;
|
|
||||||
ampmodem_reset(demodAM);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_ASK:
|
|
||||||
//modem_reset(demodASK);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_APSK:
|
|
||||||
//modem_reset(demodAPSK);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_BPSK:
|
|
||||||
//modem_reset(demodBPSK);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_DPSK:
|
|
||||||
//modem_reset(demodDPSK);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_PSK:
|
|
||||||
//modem_reset(demodPSK);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_OOK:
|
|
||||||
//modem_reset(demodOOK);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_SQAM:
|
|
||||||
//modem_reset(demodSQAM);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_ST:
|
|
||||||
//modem_reset(demodST);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_QAM:
|
|
||||||
//modem_reset(demodQAM);
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_QPSK:
|
|
||||||
//modem_reset(demodQPSK);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// empty default to prevent exceptions
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
demodulatorType = newDemodType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
demodOutputDataDigital.empty();
|
|
||||||
|
|
||||||
inp->decRefCount();
|
inp->decRefCount();
|
||||||
}
|
}
|
||||||
// end while !terminated
|
// end while !terminated
|
||||||
|
|
||||||
if (audioResampler != NULL) {
|
|
||||||
msresamp_rrrf_destroy(audioResampler);
|
|
||||||
}
|
|
||||||
if (stereoResampler != NULL) {
|
|
||||||
msresamp_rrrf_destroy(stereoResampler);
|
|
||||||
}
|
|
||||||
if (firStereoLeft != NULL) {
|
|
||||||
firfilt_rrrf_destroy(firStereoLeft);
|
|
||||||
}
|
|
||||||
if (firStereoRight != NULL) {
|
|
||||||
firfilt_rrrf_destroy(firStereoRight);
|
|
||||||
}
|
|
||||||
if (iirStereoPilot != NULL) {
|
|
||||||
iirfilt_crcf_destroy(iirStereoPilot);
|
|
||||||
}
|
|
||||||
|
|
||||||
agc_crcf_destroy(iqAutoGain);
|
|
||||||
firhilbf_destroy(firStereoR2C);
|
|
||||||
firhilbf_destroy(firStereoC2R);
|
|
||||||
nco_crcf_destroy(stereoPilot);
|
|
||||||
resamp2_crcf_destroy(ssbFilt);
|
|
||||||
|
|
||||||
outputBuffers.purge();
|
outputBuffers.purge();
|
||||||
|
|
||||||
if (audioVisOutputQueue && !audioVisOutputQueue->empty()) {
|
if (audioVisOutputQueue && !audioVisOutputQueue->empty()) {
|
||||||
@ -920,15 +250,6 @@ void DemodulatorThread::terminate() {
|
|||||||
iqInputQueue->push(inp);
|
iqInputQueue->push(inp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorThread::setStereo(bool state) {
|
|
||||||
stereo.store(state);
|
|
||||||
std::cout << "Stereo " << (state ? "Enabled" : "Disabled") << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemodulatorThread::isStereo() {
|
|
||||||
return stereo.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemodulatorThread::isMuted() {
|
bool DemodulatorThread::isMuted() {
|
||||||
return muted.load();
|
return muted.load();
|
||||||
}
|
}
|
||||||
@ -945,7 +266,6 @@ bool DemodulatorThread::getAGC() {
|
|||||||
return agcEnabled.load();
|
return agcEnabled.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float DemodulatorThread::getSignalLevel() {
|
float DemodulatorThread::getSignalLevel() {
|
||||||
return signalLevel.load();
|
return signalLevel.load();
|
||||||
}
|
}
|
||||||
@ -960,37 +280,3 @@ void DemodulatorThread::setSquelchLevel(float signal_level_in) {
|
|||||||
float DemodulatorThread::getSquelchLevel() {
|
float DemodulatorThread::getSquelchLevel() {
|
||||||
return squelchLevel;
|
return squelchLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorThread::setDemodulatorType(int demod_type_in) {
|
|
||||||
demodulatorType = demod_type_in;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DemodulatorThread::getDemodulatorType() {
|
|
||||||
return demodulatorType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorThread::setDemodulatorLock(bool demod_lock_in) {
|
|
||||||
demod_lock_in ? currentDemodLock = true : currentDemodLock = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DemodulatorThread::getDemodulatorLock() {
|
|
||||||
return currentDemodLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorThread::setDemodulatorCons(int demod_cons_in) {
|
|
||||||
demodulatorCons.store(demod_cons_in);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DemodulatorThread::getDemodulatorCons() {
|
|
||||||
return currentDemodCons;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorThread::updateDemodulatorLock(modem demod, float sensitivity) {
|
|
||||||
modem_get_demodulator_evm(demod) <= sensitivity ? setDemodulatorLock(true) : setDemodulatorLock(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorThread::updateDemodulatorCons(int Cons) {
|
|
||||||
if (currentDemodCons != Cons) {
|
|
||||||
currentDemodCons = Cons;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -5,15 +5,17 @@
|
|||||||
|
|
||||||
#include "DemodDefs.h"
|
#include "DemodDefs.h"
|
||||||
#include "AudioThread.h"
|
#include "AudioThread.h"
|
||||||
|
#include "Modem.h"
|
||||||
|
|
||||||
typedef ThreadQueue<AudioThreadInput *> DemodulatorThreadOutputQueue;
|
typedef ThreadQueue<AudioThreadInput *> DemodulatorThreadOutputQueue;
|
||||||
|
|
||||||
#define DEMOD_VIS_SIZE 2048
|
#define DEMOD_VIS_SIZE 2048
|
||||||
|
class DemodulatorInstance;
|
||||||
|
|
||||||
class DemodulatorThread : public IOThread {
|
class DemodulatorThread : public IOThread {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DemodulatorThread();
|
DemodulatorThread(DemodulatorInstance *parent);
|
||||||
~DemodulatorThread();
|
~DemodulatorThread();
|
||||||
|
|
||||||
void onBindOutput(std::string name, ThreadQueueBase *threadQueue);
|
void onBindOutput(std::string name, ThreadQueueBase *threadQueue);
|
||||||
@ -21,9 +23,6 @@ public:
|
|||||||
void run();
|
void run();
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
void setStereo(bool state);
|
|
||||||
bool isStereo();
|
|
||||||
|
|
||||||
void setAGC(bool state);
|
void setAGC(bool state);
|
||||||
bool getAGC();
|
bool getAGC();
|
||||||
|
|
||||||
@ -34,125 +33,24 @@ public:
|
|||||||
void setSquelchLevel(float signal_level_in);
|
void setSquelchLevel(float signal_level_in);
|
||||||
float getSquelchLevel();
|
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:
|
protected:
|
||||||
|
DemodulatorInstance *demodInstance;
|
||||||
ReBuffer<AudioThreadInput> outputBuffers;
|
ReBuffer<AudioThreadInput> outputBuffers;
|
||||||
|
|
||||||
std::vector<liquid_float_complex> agcData;
|
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;
|
agc_crcf iqAutoGain;
|
||||||
|
|
||||||
float amOutputCeil;
|
|
||||||
float amOutputCeilMA;
|
|
||||||
float amOutputCeilMAA;
|
|
||||||
|
|
||||||
std::atomic_bool stereo;
|
|
||||||
std::atomic_bool muted;
|
std::atomic_bool muted;
|
||||||
std::atomic_bool agcEnabled;
|
std::atomic_bool agcEnabled;
|
||||||
std::atomic_int demodulatorType;
|
|
||||||
std::atomic_int demodulatorCons;
|
|
||||||
int audioSampleRate;
|
int audioSampleRate;
|
||||||
|
|
||||||
std::atomic<float> squelchLevel;
|
std::atomic<float> squelchLevel;
|
||||||
std::atomic<float> signalLevel;
|
std::atomic<float> signalLevel;
|
||||||
bool squelchEnabled;
|
bool squelchEnabled;
|
||||||
|
|
||||||
bool currentDemodLock;
|
Modem *cModem;
|
||||||
int currentDemodCons;
|
ModemKit *cModemKit;
|
||||||
|
|
||||||
void updateDemodulatorCons(int Cons);
|
|
||||||
void updateDemodulatorLock(modem demod, float sensitivity);
|
|
||||||
|
|
||||||
DemodulatorThreadPostInputQueue* iqInputQueue;
|
DemodulatorThreadPostInputQueue* iqInputQueue;
|
||||||
AudioThreadInputQueue *audioOutputQueue;
|
AudioThreadInputQueue *audioOutputQueue;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
|
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
|
||||||
commandQueue(NULL), resultQueue(NULL) {
|
commandQueue(NULL), resultQueue(NULL), cModem(nullptr), cModemKit(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorWorkerThread::~DemodulatorWorkerThread() {
|
DemodulatorWorkerThread::~DemodulatorWorkerThread() {
|
||||||
@ -18,7 +18,8 @@ void DemodulatorWorkerThread::run() {
|
|||||||
|
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
bool filterChanged = false;
|
bool filterChanged = false;
|
||||||
DemodulatorWorkerThreadCommand filterCommand;
|
bool makeDemod = false;
|
||||||
|
DemodulatorWorkerThreadCommand filterCommand, demodCommand;
|
||||||
DemodulatorWorkerThreadCommand command;
|
DemodulatorWorkerThreadCommand command;
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
@ -29,6 +30,10 @@ void DemodulatorWorkerThread::run() {
|
|||||||
filterChanged = true;
|
filterChanged = true;
|
||||||
filterCommand = command;
|
filterCommand = command;
|
||||||
break;
|
break;
|
||||||
|
case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD:
|
||||||
|
makeDemod = true;
|
||||||
|
demodCommand = command;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -36,7 +41,7 @@ void DemodulatorWorkerThread::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (filterChanged && !terminated) {
|
if ((makeDemod || filterChanged) && !terminated) {
|
||||||
DemodulatorWorkerThreadResult result(DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS);
|
DemodulatorWorkerThreadResult result(DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS);
|
||||||
|
|
||||||
float As = 60.0f; // stop-band attenuation [dB]
|
float As = 60.0f; // stop-band attenuation [dB]
|
||||||
@ -46,45 +51,22 @@ void DemodulatorWorkerThread::run() {
|
|||||||
result.iqResampler = msresamp_crcf_create(result.iqResampleRatio, As);
|
result.iqResampler = msresamp_crcf_create(result.iqResampleRatio, As);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterCommand.bandwidth && filterCommand.audioSampleRate) {
|
if (makeDemod) {
|
||||||
result.audioResamplerRatio = (double) (filterCommand.audioSampleRate) / (double) filterCommand.bandwidth;
|
cModem = Modem::makeModem(demodCommand.demodType);
|
||||||
result.audioResampler = msresamp_rrrf_create(result.audioResamplerRatio, As);
|
cModemType = demodCommand.demodType;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
result.modem = cModem;
|
||||||
|
|
||||||
if (firStereoCutoff > 0.5) {
|
if (makeDemod && demodCommand.bandwidth && demodCommand.audioSampleRate) {
|
||||||
firStereoCutoff = 0.5;
|
if (cModem != nullptr) {
|
||||||
|
cModemKit = cModem->buildKit(demodCommand.bandwidth, demodCommand.audioSampleRate);
|
||||||
|
} else {
|
||||||
|
cModemKit = nullptr;
|
||||||
}
|
}
|
||||||
|
} else if (makeDemod) {
|
||||||
unsigned int h_len = estimate_req_filter_len(ft, As);
|
cModemKit = nullptr;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
result.modemKit = cModemKit;
|
||||||
|
|
||||||
if (filterCommand.bandwidth) {
|
if (filterCommand.bandwidth) {
|
||||||
result.bandwidth = filterCommand.bandwidth;
|
result.bandwidth = filterCommand.bandwidth;
|
||||||
@ -94,6 +76,8 @@ void DemodulatorWorkerThread::run() {
|
|||||||
result.sampleRate = filterCommand.sampleRate;
|
result.sampleRate = filterCommand.sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.modemType = cModemType;
|
||||||
|
|
||||||
resultQueue->push(result);
|
resultQueue->push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "AudioThread.h"
|
#include "AudioThread.h"
|
||||||
#include "ThreadQueue.h"
|
#include "ThreadQueue.h"
|
||||||
#include "CubicSDRDefs.h"
|
#include "CubicSDRDefs.h"
|
||||||
|
#include "Modem.h"
|
||||||
|
|
||||||
class DemodulatorWorkerThreadResult {
|
class DemodulatorWorkerThreadResult {
|
||||||
public:
|
public:
|
||||||
@ -15,8 +16,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
DemodulatorWorkerThreadResult() :
|
DemodulatorWorkerThreadResult() :
|
||||||
cmd(DEMOD_WORKER_THREAD_RESULT_NULL), iqResampler(NULL), iqResampleRatio(0), audioResampler(NULL), stereoResampler(NULL), audioResamplerRatio(
|
cmd(DEMOD_WORKER_THREAD_RESULT_NULL), iqResampler(nullptr), iqResampleRatio(0), sampleRate(0), bandwidth(0), modemKit(nullptr), modemType("") {
|
||||||
0), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL), sampleRate(0), bandwidth(0), audioSampleRate(0) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,33 +29,29 @@ public:
|
|||||||
|
|
||||||
msresamp_crcf iqResampler;
|
msresamp_crcf iqResampler;
|
||||||
double iqResampleRatio;
|
double iqResampleRatio;
|
||||||
msresamp_rrrf audioResampler;
|
|
||||||
msresamp_rrrf stereoResampler;
|
|
||||||
double audioResamplerRatio;
|
|
||||||
|
|
||||||
firfilt_rrrf firStereoLeft;
|
DemodulatorThread *demodThread;
|
||||||
firfilt_rrrf firStereoRight;
|
|
||||||
iirfilt_crcf iirStereoPilot;
|
|
||||||
|
|
||||||
long long sampleRate;
|
long long sampleRate;
|
||||||
unsigned int bandwidth;
|
unsigned int bandwidth;
|
||||||
unsigned int audioSampleRate;
|
Modem *modem;
|
||||||
|
ModemKit *modemKit;
|
||||||
|
std::string modemType;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DemodulatorWorkerThreadCommand {
|
class DemodulatorWorkerThreadCommand {
|
||||||
public:
|
public:
|
||||||
enum DemodulatorThreadCommandEnum {
|
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() :
|
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) :
|
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;
|
long long sampleRate;
|
||||||
unsigned int bandwidth;
|
unsigned int bandwidth;
|
||||||
unsigned int audioSampleRate;
|
unsigned int audioSampleRate;
|
||||||
|
std::string demodType;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ThreadQueue<DemodulatorWorkerThreadCommand> DemodulatorThreadWorkerCommandQueue;
|
typedef ThreadQueue<DemodulatorWorkerThreadCommand> DemodulatorThreadWorkerCommandQueue;
|
||||||
@ -92,4 +89,7 @@ protected:
|
|||||||
|
|
||||||
DemodulatorThreadWorkerCommandQueue *commandQueue;
|
DemodulatorThreadWorkerCommandQueue *commandQueue;
|
||||||
DemodulatorThreadWorkerResultQueue *resultQueue;
|
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"
|
#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;
|
bufferedItems = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ using namespace std;
|
|||||||
|
|
||||||
#define STRINGIFY(A) #A
|
#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() {
|
DataElement::~DataElement() {
|
||||||
@ -393,11 +393,11 @@ void DataElement::setSerialized(char *ser_str) {
|
|||||||
|
|
||||||
/* DataNode class */
|
/* DataNode class */
|
||||||
|
|
||||||
DataNode::DataNode(): ptr(0), parentNode(NULL) {
|
DataNode::DataNode(): parentNode(NULL), ptr(0) {
|
||||||
data_elem = new DataElement();
|
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;
|
node_name = name_in;
|
||||||
data_elem = new DataElement();
|
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) {
|
bool DataTree::SaveToFile(const std::string& filename, bool compress, int compress_level) {
|
||||||
long dataSize, compressedSize, headerSize;
|
long dataSize, compressedSize, headerSize;
|
||||||
char *serialized, *hdr_serialized, *compressed;
|
char *serialized = nullptr, *hdr_serialized = nullptr, *compressed = nullptr;
|
||||||
DataTree dtHeader;
|
DataTree dtHeader;
|
||||||
|
|
||||||
dataSize = getSerialized(&serialized);
|
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) {
|
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;
|
long dataSize, headerSize, compressedSize;
|
||||||
|
|
||||||
ifstream fin(filename.c_str(), ios::binary);
|
ifstream fin(filename.c_str(), ios::binary);
|
||||||
|
@ -155,6 +155,24 @@ void ModeSelectorCanvas::addChoice(int value, std::string label) {
|
|||||||
numChoices = selections.size();
|
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) {
|
void ModeSelectorCanvas::setSelection(int value) {
|
||||||
for (int i = 0; i < numChoices; i++) {
|
for (int i = 0; i < numChoices; i++) {
|
||||||
if (selections[i].value == value) {
|
if (selections[i].value == value) {
|
||||||
|
@ -32,6 +32,8 @@ public:
|
|||||||
void setHelpTip(std::string tip);
|
void setHelpTip(std::string tip);
|
||||||
|
|
||||||
void addChoice(int value, std::string label);
|
void addChoice(int value, std::string label);
|
||||||
|
void setSelection(std::string label);
|
||||||
|
std::string getSelectionLabel();
|
||||||
void setSelection(int value);
|
void setSelection(int value);
|
||||||
int getSelection();
|
int getSelection();
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, l
|
|||||||
glColor4f(color.r, color.g, color.b, 0.6);
|
glColor4f(color.r, color.g, color.b, 0.6);
|
||||||
|
|
||||||
float ofs = ((float) demod->getBandwidth()) / (float) srate;
|
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 labelHeight = 20.0 / viewHeight;
|
||||||
float hPos = -1.0 + labelHeight;
|
float hPos = -1.0 + labelHeight;
|
||||||
@ -139,9 +139,9 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, l
|
|||||||
demodLabel = std::string("[M] ") + demodLabel;
|
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);
|
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);
|
GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodLabel, uxPos, hPos, 16, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER);
|
||||||
} else {
|
} else {
|
||||||
GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodLabel, uxPos, hPos, 16, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER);
|
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);
|
glColor4f(color.r, color.g, color.b, 0.6);
|
||||||
|
|
||||||
float ofs = ((float) demod->getBandwidth()) / (float) srate;
|
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);
|
glBegin(GL_LINES);
|
||||||
glVertex3f((uxPos - 0.5) * 2.0, 1.0, 0.0);
|
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 = "";
|
std::string demodStr = "";
|
||||||
GLFont::Align demodAlign = GLFont::GLFONT_ALIGN_CENTER;
|
GLFont::Align demodAlign = GLFont::GLFONT_ALIGN_CENTER;
|
||||||
|
|
||||||
switch (demod->getDemodulatorType()) {
|
demodStr = demod->getDemodulatorType();
|
||||||
case DEMOD_TYPE_FM:
|
|
||||||
demodStr = "FM";
|
|
||||||
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
|
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_AM:
|
if (demodStr == "LSB") {
|
||||||
demodStr = "AM";
|
|
||||||
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
|
|
||||||
break;
|
|
||||||
case DEMOD_TYPE_LSB:
|
|
||||||
demodStr = "LSB";
|
|
||||||
demodAlign = GLFont::GLFONT_ALIGN_RIGHT;
|
demodAlign = GLFont::GLFONT_ALIGN_RIGHT;
|
||||||
uxPos -= xOfs;
|
uxPos -= xOfs;
|
||||||
break;
|
} else if (demodStr == "USB") {
|
||||||
case DEMOD_TYPE_USB:
|
|
||||||
demodStr = "USB";
|
|
||||||
demodAlign = GLFont::GLFONT_ALIGN_LEFT;
|
demodAlign = GLFont::GLFONT_ALIGN_LEFT;
|
||||||
uxPos += xOfs;
|
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());
|
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;
|
long long bw = 0;
|
||||||
|
|
||||||
int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
|
std::string last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
|
||||||
|
|
||||||
if (!demod) {
|
if (!demod) {
|
||||||
bw = wxGetApp().getDemodMgr().getLastBandwidth();
|
bw = wxGetApp().getDemodMgr().getLastBandwidth();
|
||||||
@ -337,12 +288,12 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBA4f color, float w, long
|
|||||||
ofs = ((float) bw) / (float) srate;
|
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);
|
||||||
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);
|
||||||
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;
|
uxPos1=temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
|
std::string last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
@ -367,14 +318,14 @@ void PrimaryGLContext::DrawRangeSelector(float uxPos1, float uxPos2, RGBA4f colo
|
|||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||||
glColor4f(color.r, color.g, color.b, 0.6);
|
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);
|
glBegin(GL_LINES);
|
||||||
glVertex3f((uxPos1 - 0.5) * 2.0, 1.0, 0.0);
|
glVertex3f((uxPos1 - 0.5) * 2.0, 1.0, 0.0);
|
||||||
glVertex3f((uxPos1 - 0.5) * 2.0, -1.0, 0.0);
|
glVertex3f((uxPos1 - 0.5) * 2.0, -1.0, 0.0);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
glLineWidth((last_type == DEMOD_TYPE_LSB)?2.0:1.0);
|
glLineWidth((last_type == "LSB")?2.0:1.0);
|
||||||
|
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
glVertex3f((uxPos2 - 0.5) * 2.0, 1.0, 0.0);
|
glVertex3f((uxPos2 - 0.5) * 2.0, 1.0, 0.0);
|
||||||
|
@ -36,7 +36,7 @@ wxEND_EVENT_TABLE()
|
|||||||
|
|
||||||
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
||||||
InteractiveCanvas(parent, attribList), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines(0),
|
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));
|
glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this));
|
||||||
linesPerSecond = 30;
|
linesPerSecond = 30;
|
||||||
@ -253,7 +253,7 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
long long currentCenterFreq = getCenterFrequency();
|
long long currentCenterFreq = getCenterFrequency();
|
||||||
|
|
||||||
ColorTheme *currentTheme = ThemeMgr::mgr.currentTheme;
|
ColorTheme *currentTheme = ThemeMgr::mgr.currentTheme;
|
||||||
int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
|
std::string last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
|
||||||
|
|
||||||
if (mouseTracker.mouseInView() || wxGetApp().getDemodMgr().getActiveDemodulator()) {
|
if (mouseTracker.mouseInView() || wxGetApp().getDemodMgr().getActiveDemodulator()) {
|
||||||
hoverAlpha += (1.0f-hoverAlpha)*0.1f;
|
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);
|
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();
|
centerPos = mouseTracker.getMouseX();
|
||||||
glContext->DrawRangeSelector(centerPos, centerPos-width, isNew?currentTheme->waterfallNew:currentTheme->waterfallHover);
|
glContext->DrawRangeSelector(centerPos, centerPos-width, isNew?currentTheme->waterfallNew:currentTheme->waterfallHover);
|
||||||
} else {
|
} else {
|
||||||
@ -416,16 +416,6 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
|
|||||||
}
|
}
|
||||||
activeDemod->setMuted(!activeDemod->isMuted());
|
activeDemod->setMuted(!activeDemod->isMuted());
|
||||||
break;
|
break;
|
||||||
case 'S':
|
|
||||||
if (!activeDemod) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (activeDemod->isStereo()) {
|
|
||||||
activeDemod->setStereo(false);
|
|
||||||
} else {
|
|
||||||
activeDemod->setStereo(true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'B':
|
case 'B':
|
||||||
if (spectrumCanvas) {
|
if (spectrumCanvas) {
|
||||||
spectrumCanvas->setShowDb(!spectrumCanvas->getShowDb());
|
spectrumCanvas->setShowDb(!spectrumCanvas->getShowDb());
|
||||||
@ -534,8 +524,8 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
|||||||
double maxDist = ((double)halfBw + bufferBw);
|
double maxDist = ((double)halfBw + bufferBw);
|
||||||
|
|
||||||
if ((double)dist <= maxDist) {
|
if ((double)dist <= maxDist) {
|
||||||
if ((freqDiff > 0 && demod->getDemodulatorType() == DEMOD_TYPE_USB) ||
|
if ((freqDiff > 0 && demod->getDemodulatorType() == "USB") ||
|
||||||
(freqDiff < 0 && demod->getDemodulatorType() == DEMOD_TYPE_LSB)) {
|
(freqDiff < 0 && demod->getDemodulatorType() == "LSB")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,12 +555,12 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
|||||||
if (abs(freqDiff) > (activeDemodulator->getBandwidth() / 3)) {
|
if (abs(freqDiff) > (activeDemodulator->getBandwidth() / 3)) {
|
||||||
|
|
||||||
if (freqDiff > 0) {
|
if (freqDiff > 0) {
|
||||||
if (activeDemodulator->getDemodulatorType() != DEMOD_TYPE_USB) {
|
if (activeDemodulator->getDemodulatorType() != "USB") {
|
||||||
nextDragState = WF_DRAG_BANDWIDTH_LEFT;
|
nextDragState = WF_DRAG_BANDWIDTH_LEFT;
|
||||||
SetCursor(wxCURSOR_SIZEWE);
|
SetCursor(wxCURSOR_SIZEWE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (activeDemodulator->getDemodulatorType() != DEMOD_TYPE_LSB) {
|
if (activeDemodulator->getDemodulatorType() != "LSB") {
|
||||||
nextDragState = WF_DRAG_BANDWIDTH_RIGHT;
|
nextDragState = WF_DRAG_BANDWIDTH_RIGHT;
|
||||||
SetCursor(wxCURSOR_SIZEWE);
|
SetCursor(wxCURSOR_SIZEWE);
|
||||||
}
|
}
|
||||||
@ -578,14 +568,14 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
|||||||
|
|
||||||
mouseTracker.setVertDragLock(true);
|
mouseTracker.setVertDragLock(true);
|
||||||
mouseTracker.setHorizDragLock(false);
|
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 {
|
} else {
|
||||||
SetCursor(wxCURSOR_SIZING);
|
SetCursor(wxCURSOR_SIZING);
|
||||||
nextDragState = WF_DRAG_FREQUENCY;
|
nextDragState = WF_DRAG_FREQUENCY;
|
||||||
|
|
||||||
mouseTracker.setVertDragLock(true);
|
mouseTracker.setVertDragLock(true);
|
||||||
mouseTracker.setHorizDragLock(false);
|
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 {
|
} else {
|
||||||
SetCursor(wxCURSOR_CROSS);
|
SetCursor(wxCURSOR_CROSS);
|
||||||
@ -671,7 +661,6 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
demod->setBandwidth(mgr->getLastBandwidth());
|
demod->setBandwidth(mgr->getLastBandwidth());
|
||||||
demod->setSquelchLevel(mgr->getLastSquelchLevel());
|
demod->setSquelchLevel(mgr->getLastSquelchLevel());
|
||||||
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
|
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
|
||||||
demod->setStereo(mgr->isLastStereo());
|
|
||||||
demod->setGain(mgr->getLastGain());
|
demod->setGain(mgr->getLastGain());
|
||||||
demod->setMuted(mgr->isLastMuted());
|
demod->setMuted(mgr->isLastMuted());
|
||||||
|
|
||||||
@ -712,9 +701,9 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
float width = mouseTracker.getOriginDeltaMouseX();
|
float width = mouseTracker.getOriginDeltaMouseX();
|
||||||
|
|
||||||
float pos;
|
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 pos1 = mouseTracker.getOriginMouseX();
|
||||||
float pos2 = mouseTracker.getMouseX();
|
float pos2 = mouseTracker.getMouseX();
|
||||||
|
|
||||||
@ -724,7 +713,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
pos2 = tmp;
|
pos2 = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = (last_type == DEMOD_TYPE_LSB)?pos2:pos1;
|
pos = (last_type == "LSB")?pos2:pos1;
|
||||||
width *= 2;
|
width *= 2;
|
||||||
} else {
|
} else {
|
||||||
pos = mouseTracker.getOriginMouseX() + width / 2.0;
|
pos = mouseTracker.getOriginMouseX() + width / 2.0;
|
||||||
@ -759,7 +748,6 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
demod->setBandwidth(bw);
|
demod->setBandwidth(bw);
|
||||||
demod->setSquelchLevel(mgr->getLastSquelchLevel());
|
demod->setSquelchLevel(mgr->getLastSquelchLevel());
|
||||||
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
|
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
|
||||||
demod->setStereo(mgr->isLastStereo());
|
|
||||||
demod->setGain(mgr->getLastGain());
|
demod->setGain(mgr->getLastGain());
|
||||||
|
|
||||||
demod->run();
|
demod->run();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user