mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-09-03 13:47:53 -04:00
Merge pull request #199 from cjcliffe/digital_experiments
Digital experiments and cleanup
This commit is contained in:
commit
777e4a3488
@ -14,7 +14,7 @@ SET(CPACK_PACKAGE_VERSION_PATCH ${CUBICSDR_VERSION_PATCH})
|
|||||||
SET (VERSION_SUFFIX "" CACHE STRING "Add custom version suffix to CubicSDR application title.")
|
SET (VERSION_SUFFIX "" CACHE STRING "Add custom version suffix to CubicSDR application title.")
|
||||||
|
|
||||||
ADD_DEFINITIONS(
|
ADD_DEFINITIONS(
|
||||||
-DCUBICSDR_VERSION="${CUBICSDR_VERSION}-${VERSION_SUFFIX}"
|
-DCUBICSDR_VERSION="${CUBICSDR_VERSION}${VERSION_SUFFIX}"
|
||||||
)
|
)
|
||||||
|
|
||||||
SET (ENABLE_DIGITAL_LAB OFF CACHE BOOL "Enable 'Digital Lab' testing features.")
|
SET (ENABLE_DIGITAL_LAB OFF CACHE BOOL "Enable 'Digital Lab' testing features.")
|
||||||
@ -22,6 +22,16 @@ IF(ENABLE_DIGITAL_LAB)
|
|||||||
ADD_DEFINITIONS(
|
ADD_DEFINITIONS(
|
||||||
-DENABLE_DIGITAL_LAB=1
|
-DENABLE_DIGITAL_LAB=1
|
||||||
)
|
)
|
||||||
|
IF(MSVC)
|
||||||
|
SET (ENABLE_LIQUID_EXPERIMENTAL OFF CACHE BOOL "Enable experimental liquid-dsp features (requires latest liquid-dsp installed)")
|
||||||
|
ELSE()
|
||||||
|
SET (ENABLE_LIQUID_EXPERIMENTAL ON CACHE BOOL "Enable experimental liquid-dsp features (requires latest liquid-dsp installed)")
|
||||||
|
ENDIF()
|
||||||
|
IF(ENABLE_LIQUID_EXPERIMENTAL)
|
||||||
|
ADD_DEFINITIONS(
|
||||||
|
-DENABLE_LIQUID_EXPERIMENTAL=1
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||||
@ -225,6 +235,7 @@ SET (cubicsdr_sources
|
|||||||
src/AppConfig.cpp
|
src/AppConfig.cpp
|
||||||
src/FrequencyDialog.cpp
|
src/FrequencyDialog.cpp
|
||||||
src/IOThread.cpp
|
src/IOThread.cpp
|
||||||
|
src/ModemProperties.cpp
|
||||||
src/sdr/SDRDeviceInfo.cpp
|
src/sdr/SDRDeviceInfo.cpp
|
||||||
src/sdr/SDRPostThread.cpp
|
src/sdr/SDRPostThread.cpp
|
||||||
src/sdr/SDREnumerator.cpp
|
src/sdr/SDREnumerator.cpp
|
||||||
@ -237,16 +248,6 @@ SET (cubicsdr_sources
|
|||||||
src/modules/modem/Modem.cpp
|
src/modules/modem/Modem.cpp
|
||||||
src/modules/modem/ModemAnalog.cpp
|
src/modules/modem/ModemAnalog.cpp
|
||||||
src/modules/modem/ModemDigital.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/ModemAM.cpp
|
||||||
src/modules/modem/analog/ModemDSB.cpp
|
src/modules/modem/analog/ModemDSB.cpp
|
||||||
src/modules/modem/analog/ModemFM.cpp
|
src/modules/modem/analog/ModemFM.cpp
|
||||||
@ -296,6 +297,31 @@ SET (cubicsdr_sources
|
|||||||
external/cubicvr2/math/cubic_math.cpp
|
external/cubicvr2/math/cubic_math.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
IF(ENABLE_DIGITAL_LAB)
|
||||||
|
SET (cubicsdr_sources
|
||||||
|
${cubicsdr_sources}
|
||||||
|
src/forms/DigitalConsole/DigitalConsole.cpp
|
||||||
|
src/forms/DigitalConsole/DigitalConsoleFrame.cpp
|
||||||
|
src/modules/modem/digital/ModemASK.cpp
|
||||||
|
src/modules/modem/digital/ModemAPSK.cpp
|
||||||
|
src/modules/modem/digital/ModemBPSK.cpp
|
||||||
|
src/modules/modem/digital/ModemDPSK.cpp
|
||||||
|
src/modules/modem/digital/ModemGMSK.cpp
|
||||||
|
src/modules/modem/digital/ModemPSK.cpp
|
||||||
|
src/modules/modem/digital/ModemOOK.cpp
|
||||||
|
src/modules/modem/digital/ModemST.cpp
|
||||||
|
src/modules/modem/digital/ModemSQAM.cpp
|
||||||
|
src/modules/modem/digital/ModemQAM.cpp
|
||||||
|
src/modules/modem/digital/ModemQPSK.cpp
|
||||||
|
)
|
||||||
|
IF(ENABLE_LIQUID_EXPERIMENTAL)
|
||||||
|
SET (cubicsdr_sources
|
||||||
|
${cubicsdr_sources}
|
||||||
|
src/modules/modem/digital/ModemFSK.cpp
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
SET (cubicsdr_headers
|
SET (cubicsdr_headers
|
||||||
src/CubicSDRDefs.h
|
src/CubicSDRDefs.h
|
||||||
src/CubicSDR.h
|
src/CubicSDR.h
|
||||||
@ -303,6 +329,7 @@ SET (cubicsdr_headers
|
|||||||
src/AppConfig.h
|
src/AppConfig.h
|
||||||
src/FrequencyDialog.h
|
src/FrequencyDialog.h
|
||||||
src/IOThread.h
|
src/IOThread.h
|
||||||
|
src/ModemProperties.h
|
||||||
src/sdr/SDRDeviceInfo.h
|
src/sdr/SDRDeviceInfo.h
|
||||||
src/sdr/SDRPostThread.h
|
src/sdr/SDRPostThread.h
|
||||||
src/sdr/SDREnumerator.h
|
src/sdr/SDREnumerator.h
|
||||||
@ -316,16 +343,6 @@ SET (cubicsdr_headers
|
|||||||
src/modules/modem/Modem.h
|
src/modules/modem/Modem.h
|
||||||
src/modules/modem/ModemAnalog.h
|
src/modules/modem/ModemAnalog.h
|
||||||
src/modules/modem/ModemDigital.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/ModemAM.h
|
||||||
src/modules/modem/analog/ModemDSB.h
|
src/modules/modem/analog/ModemDSB.h
|
||||||
src/modules/modem/analog/ModemFM.h
|
src/modules/modem/analog/ModemFM.h
|
||||||
@ -391,6 +408,31 @@ SET (cubicsdr_headers
|
|||||||
external/cubicvr2/math/vec4.h
|
external/cubicvr2/math/vec4.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
IF(ENABLE_DIGITAL_LAB)
|
||||||
|
SET (cubicsdr_headers
|
||||||
|
${cubicsdr_headers}
|
||||||
|
src/forms/DigitalConsole/DigitalConsole.h
|
||||||
|
src/forms/DigitalConsole/DigitalConsoleFrame.h
|
||||||
|
src/modules/modem/digital/ModemASK.h
|
||||||
|
src/modules/modem/digital/ModemAPSK.h
|
||||||
|
src/modules/modem/digital/ModemBPSK.h
|
||||||
|
src/modules/modem/digital/ModemDPSK.h
|
||||||
|
src/modules/modem/digital/ModemGMSK.h
|
||||||
|
src/modules/modem/digital/ModemPSK.h
|
||||||
|
src/modules/modem/digital/ModemOOK.h
|
||||||
|
src/modules/modem/digital/ModemST.h
|
||||||
|
src/modules/modem/digital/ModemSQAM.h
|
||||||
|
src/modules/modem/digital/ModemQAM.h
|
||||||
|
src/modules/modem/digital/ModemQPSK.h
|
||||||
|
)
|
||||||
|
IF(ENABLE_LIQUID_EXPERIMENTAL)
|
||||||
|
SET (cubicsdr_sources
|
||||||
|
${cubicsdr_sources}
|
||||||
|
src/modules/modem/digital/ModemFSK.h
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
SET (CUBICSDR_RESOURCES
|
SET (CUBICSDR_RESOURCES
|
||||||
${PROJECT_SOURCE_DIR}/font/vera_sans_mono12.fnt
|
${PROJECT_SOURCE_DIR}/font/vera_sans_mono12.fnt
|
||||||
${PROJECT_SOURCE_DIR}/font/vera_sans_mono16.fnt
|
${PROJECT_SOURCE_DIR}/font/vera_sans_mono16.fnt
|
||||||
@ -413,8 +455,11 @@ SOURCE_GROUP("Forms\\SDRDevices" REGULAR_EXPRESSION "src/forms/SDRDevices/${REG_
|
|||||||
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" REGULAR_EXPRESSION "src/modules/modem/${REG_EXT}")
|
||||||
SOURCE_GROUP("Modem-Analog" REGULAR_EXPRESSION "src/modules/modem/analog/${REG_EXT}")
|
SOURCE_GROUP("Modem\\Analog" REGULAR_EXPRESSION "src/modules/modem/analog/${REG_EXT}")
|
||||||
SOURCE_GROUP("Modem-Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}")
|
IF(ENABLE_DIGITAL_LAB)
|
||||||
|
SOURCE_GROUP("Modem\\Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}")
|
||||||
|
SOURCE_GROUP("Forms\\DigitalConsole" REGULAR_EXPRESSION "src/forms/DigitalConsole/${REG_EXT}")
|
||||||
|
ENDIF()
|
||||||
SOURCE_GROUP("Audio" REGULAR_EXPRESSION "src/audio/${REG_EXT}")
|
SOURCE_GROUP("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}")
|
||||||
@ -428,6 +473,7 @@ SOURCE_GROUP("_ext-CubicVR2" REGULAR_EXPRESSION "external/cubicvr2/.*${REG_EXT}"
|
|||||||
|
|
||||||
include_directories (
|
include_directories (
|
||||||
${PROJECT_SOURCE_DIR}/src/forms/SDRDevices
|
${PROJECT_SOURCE_DIR}/src/forms/SDRDevices
|
||||||
|
${PROJECT_SOURCE_DIR}/src/forms/DigitalConsole
|
||||||
${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
|
||||||
|
211
src/AppFrame.cpp
211
src/AppFrame.cpp
@ -67,46 +67,47 @@ AppFrame::AppFrame() :
|
|||||||
gainSpacerItem->Show(false);
|
gainSpacerItem->Show(false);
|
||||||
|
|
||||||
demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList);
|
demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList);
|
||||||
demodModeSelector->addChoice(0, "FM");
|
demodModeSelector->addChoice("FM");
|
||||||
demodModeSelector->addChoice(1, "FMS");
|
demodModeSelector->addChoice("FMS");
|
||||||
demodModeSelector->addChoice(2, "AM");
|
demodModeSelector->addChoice("AM");
|
||||||
demodModeSelector->addChoice(3, "LSB");
|
demodModeSelector->addChoice("LSB");
|
||||||
demodModeSelector->addChoice(4, "USB");
|
demodModeSelector->addChoice("USB");
|
||||||
demodModeSelector->addChoice(5, "DSB");
|
demodModeSelector->addChoice("DSB");
|
||||||
demodModeSelector->addChoice(6, "I/Q");
|
demodModeSelector->addChoice("I/Q");
|
||||||
demodModeSelector->setSelection("FM");
|
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.");
|
||||||
|
demodModeSelector->SetMinSize(wxSize(40,-1));
|
||||||
|
demodModeSelector->SetMaxSize(wxSize(40,-1));
|
||||||
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(demodPanel, attribList);
|
||||||
demodModeSelectorAdv->addChoice(0, "ASK");
|
demodModeSelectorAdv->addChoice("ASK");
|
||||||
demodModeSelectorAdv->addChoice(1, "APSK");
|
demodModeSelectorAdv->addChoice("APSK");
|
||||||
demodModeSelectorAdv->addChoice(2, "BPSK");
|
demodModeSelectorAdv->addChoice("BPSK");
|
||||||
demodModeSelectorAdv->addChoice(3, "DPSK");
|
demodModeSelectorAdv->addChoice("DPSK");
|
||||||
demodModeSelectorAdv->addChoice(4, "PSK");
|
demodModeSelectorAdv->addChoice("PSK");
|
||||||
demodModeSelectorAdv->addChoice(5, "OOK");
|
demodModeSelectorAdv->addChoice("FSK");
|
||||||
demodModeSelectorAdv->addChoice(6, "ST");
|
demodModeSelectorAdv->addChoice("GMSK");
|
||||||
demodModeSelectorAdv->addChoice(7, "SQAM");
|
demodModeSelectorAdv->addChoice("OOK");
|
||||||
demodModeSelectorAdv->addChoice(8, "QAM");
|
demodModeSelectorAdv->addChoice("ST");
|
||||||
demodModeSelectorAdv->addChoice(9, "QPSK");
|
demodModeSelectorAdv->addChoice("SQAM");
|
||||||
|
demodModeSelectorAdv->addChoice("QAM");
|
||||||
|
demodModeSelectorAdv->addChoice("QPSK");
|
||||||
demodModeSelectorAdv->setHelpTip("Choose advanced modulation types.");
|
demodModeSelectorAdv->setHelpTip("Choose advanced modulation types.");
|
||||||
|
demodModeSelectorAdv->SetMinSize(wxSize(40,-1));
|
||||||
|
demodModeSelectorAdv->SetMaxSize(wxSize(40,-1));
|
||||||
demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0);
|
demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0);
|
||||||
|
|
||||||
demodModeSelectorCons = new ModeSelectorCanvas(this, attribList);
|
|
||||||
demodModeSelectorCons->addChoice(1, "auto");
|
|
||||||
demodModeSelectorCons->addChoice(2, "2");
|
|
||||||
demodModeSelectorCons->addChoice(4, "4");
|
|
||||||
demodModeSelectorCons->addChoice(8, "8");
|
|
||||||
demodModeSelectorCons->addChoice(16, "16");
|
|
||||||
demodModeSelectorCons->addChoice(32, "32");
|
|
||||||
demodModeSelectorCons->addChoice(64, "64");
|
|
||||||
demodModeSelectorCons->addChoice(128, "128");
|
|
||||||
demodModeSelectorCons->addChoice(256, "256");
|
|
||||||
demodModeSelectorCons->setHelpTip("Choose number of constallations types.");
|
|
||||||
demodTray->Add(demodModeSelectorCons, 2, wxEXPAND | wxALL, 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
modemPropertiesUpdated.store(false);
|
||||||
|
modemProps = new ModemProperties(demodPanel, wxID_ANY);
|
||||||
|
modemProps->SetMinSize(wxSize(200,-1));
|
||||||
|
modemProps->SetMaxSize(wxSize(200,-1));
|
||||||
|
|
||||||
|
modemProps->Hide();
|
||||||
|
demodTray->Add(modemProps, 15, wxEXPAND | wxALL, 0);
|
||||||
|
|
||||||
wxGetApp().getDemodSpectrumProcessor()->setup(1024);
|
wxGetApp().getDemodSpectrumProcessor()->setup(1024);
|
||||||
demodSpectrumCanvas = new SpectrumCanvas(demodPanel, attribList);
|
demodSpectrumCanvas = new SpectrumCanvas(demodPanel, attribList);
|
||||||
demodSpectrumCanvas->setView(wxGetApp().getConfig()->getCenterFreq(), 300000);
|
demodSpectrumCanvas->setView(wxGetApp().getConfig()->getCenterFreq(), 300000);
|
||||||
@ -119,11 +120,14 @@ AppFrame::AppFrame() :
|
|||||||
demodWaterfallCanvas->setup(1024, 128);
|
demodWaterfallCanvas->setup(1024, 128);
|
||||||
demodWaterfallCanvas->setView(wxGetApp().getConfig()->getCenterFreq(), 300000);
|
demodWaterfallCanvas->setView(wxGetApp().getConfig()->getCenterFreq(), 300000);
|
||||||
demodWaterfallCanvas->attachSpectrumCanvas(demodSpectrumCanvas);
|
demodWaterfallCanvas->attachSpectrumCanvas(demodSpectrumCanvas);
|
||||||
|
demodWaterfallCanvas->setMinBandwidth(8000);
|
||||||
demodSpectrumCanvas->attachWaterfallCanvas(demodWaterfallCanvas);
|
demodSpectrumCanvas->attachWaterfallCanvas(demodWaterfallCanvas);
|
||||||
demodVisuals->Add(demodWaterfallCanvas, 6, wxEXPAND | wxALL, 0);
|
demodVisuals->Add(demodWaterfallCanvas, 6, wxEXPAND | wxALL, 0);
|
||||||
wxGetApp().getDemodSpectrumProcessor()->attachOutput(demodWaterfallCanvas->getVisualDataQueue());
|
wxGetApp().getDemodSpectrumProcessor()->attachOutput(demodWaterfallCanvas->getVisualDataQueue());
|
||||||
demodWaterfallCanvas->getVisualDataQueue()->set_max_num_items(3);
|
demodWaterfallCanvas->getVisualDataQueue()->set_max_num_items(3);
|
||||||
|
|
||||||
|
demodVisuals->SetMinSize(wxSize(128,-1));
|
||||||
|
|
||||||
demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0);
|
demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0);
|
||||||
|
|
||||||
demodTray->AddSpacer(1);
|
demodTray->AddSpacer(1);
|
||||||
@ -142,6 +146,7 @@ AppFrame::AppFrame() :
|
|||||||
|
|
||||||
scopeCanvas = new ScopeCanvas(demodPanel, attribList);
|
scopeCanvas = new ScopeCanvas(demodPanel, attribList);
|
||||||
scopeCanvas->setHelpTip("Audio Visuals, drag left/right to toggle Scope or Spectrum.");
|
scopeCanvas->setHelpTip("Audio Visuals, drag left/right to toggle Scope or Spectrum.");
|
||||||
|
scopeCanvas->SetMinSize(wxSize(128,-1));
|
||||||
demodScopeTray->Add(scopeCanvas, 8, wxEXPAND | wxALL, 0);
|
demodScopeTray->Add(scopeCanvas, 8, wxEXPAND | wxALL, 0);
|
||||||
wxGetApp().getScopeProcessor()->setup(2048);
|
wxGetApp().getScopeProcessor()->setup(2048);
|
||||||
wxGetApp().getScopeProcessor()->attachOutput(scopeCanvas->getInputQueue());
|
wxGetApp().getScopeProcessor()->attachOutput(scopeCanvas->getInputQueue());
|
||||||
@ -833,7 +838,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
|
|
||||||
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
if (demod) {
|
if (demod && demod->isModemInitialized()) {
|
||||||
if (demod->isTracking()) {
|
if (demod->isTracking()) {
|
||||||
if (spectrumCanvas->getViewState()) {
|
if (spectrumCanvas->getViewState()) {
|
||||||
long long diff = abs(demod->getFrequency() - spectrumCanvas->getCenterFrequency()) + (demod->getBandwidth()/2) + (demod->getBandwidth()/4);
|
long long diff = abs(demod->getFrequency() - spectrumCanvas->getCenterFrequency()) + (demod->getBandwidth()/2) + (demod->getBandwidth()/4);
|
||||||
@ -851,6 +856,10 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
demod->setTracking(false);
|
demod->setTracking(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (demod->getBandwidth() != wxGetApp().getDemodMgr().getLastBandwidth()) {
|
||||||
|
wxGetApp().getDemodMgr().setLastBandwidth(demod->getBandwidth());
|
||||||
|
}
|
||||||
|
|
||||||
if (demod != activeDemodulator) {
|
if (demod != activeDemodulator) {
|
||||||
demodSignalMeter->setInputValue(demod->getSquelchLevel());
|
demodSignalMeter->setInputValue(demod->getSquelchLevel());
|
||||||
@ -861,11 +870,10 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
std::string 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();
|
|
||||||
demodModeSelectorAdv->setSelection(dType);
|
demodModeSelectorAdv->setSelection(dType);
|
||||||
demodModeSelectorCons->setSelection(dCons);
|
|
||||||
#endif
|
#endif
|
||||||
demodMuteButton->setSelection(demod->isMuted()?1:-1);
|
demodMuteButton->setSelection(demod->isMuted()?1:-1);
|
||||||
|
modemPropertiesUpdated.store(true);
|
||||||
}
|
}
|
||||||
if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) {
|
if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) {
|
||||||
long long centerFreq = demod->getFrequency();
|
long long centerFreq = demod->getFrequency();
|
||||||
@ -895,7 +903,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
std::string dSelection = demodModeSelector->getSelectionLabel();
|
std::string dSelection = demodModeSelector->getSelectionLabel();
|
||||||
#ifdef ENABLE_DIGITAL_LAB
|
#ifdef ENABLE_DIGITAL_LAB
|
||||||
std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel();
|
std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel();
|
||||||
int dSelectionCons = demodModeSelectorCons->getSelection();
|
|
||||||
|
|
||||||
// basic demodulators
|
// basic demodulators
|
||||||
if (dSelection != "" && dSelection != demod->getDemodulatorType()) {
|
if (dSelection != "" && dSelection != demod->getDemodulatorType()) {
|
||||||
@ -907,11 +914,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
demod->setDemodulatorType(dSelectionadv);
|
demod->setDemodulatorType(dSelectionadv);
|
||||||
demodModeSelector->setSelection(-1);
|
demodModeSelector->setSelection(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set constellations
|
|
||||||
if (dSelectionCons != demod->getDemodulatorCons()) {
|
|
||||||
demod->setDemodulatorCons(dSelectionCons);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
// basic demodulators
|
// basic demodulators
|
||||||
if (dSelection != "" && dSelection != demod->getDemodulatorType()) {
|
if (dSelection != "" && dSelection != demod->getDemodulatorType()) {
|
||||||
@ -951,13 +953,14 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
demodGainMeter->setLevel(demodGainMeter->getInputValue());
|
demodGainMeter->setLevel(demodGainMeter->getInputValue());
|
||||||
}
|
}
|
||||||
activeDemodulator = demod;
|
activeDemodulator = demod;
|
||||||
|
} else if (demod) {
|
||||||
|
// Wait state for current demodulator modem to activate..
|
||||||
} else {
|
} else {
|
||||||
DemodulatorMgr *mgr = &wxGetApp().getDemodMgr();
|
DemodulatorMgr *mgr = &wxGetApp().getDemodMgr();
|
||||||
|
|
||||||
std::string dSelection = demodModeSelector->getSelectionLabel();
|
std::string dSelection = demodModeSelector->getSelectionLabel();
|
||||||
#ifdef ENABLE_DIGITAL_LAB
|
#ifdef ENABLE_DIGITAL_LAB
|
||||||
std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel();
|
std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel();
|
||||||
int dSelectionCons = demodModeSelectorCons->getSelection();
|
|
||||||
|
|
||||||
// basic demodulators
|
// basic demodulators
|
||||||
if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) {
|
if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) {
|
||||||
@ -969,11 +972,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
mgr->setLastDemodulatorType(dSelectionadv);
|
mgr->setLastDemodulatorType(dSelectionadv);
|
||||||
demodModeSelector->setSelection(-1);
|
demodModeSelector->setSelection(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set constellations
|
|
||||||
if (dSelectionCons != mgr->getLastDemodulatorCons()) {
|
|
||||||
mgr->setLastDemodulatorCons(dSelectionCons);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
// basic demodulators
|
// basic demodulators
|
||||||
if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) {
|
if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) {
|
||||||
@ -1012,7 +1010,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
if (!demodTuner->HasFocus()) {
|
if (!demodTuner->HasFocus()) {
|
||||||
demodTuner->SetFocus();
|
demodTuner->SetFocus();
|
||||||
}
|
}
|
||||||
} else if (!wxGetApp().isDeviceSelectorOpen()) {
|
} else if (!wxGetApp().isDeviceSelectorOpen() && (!modemProps || !modemProps->isMouseInView())) {
|
||||||
if (!waterfallCanvas->HasFocus()) {
|
if (!waterfallCanvas->HasFocus()) {
|
||||||
waterfallCanvas->SetFocus();
|
waterfallCanvas->SetFocus();
|
||||||
}
|
}
|
||||||
@ -1026,7 +1024,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
wxGetApp().getAudioVisualQueue()->set_max_num_items((scopeCanvas->scopeVisible()?1:0) + (scopeCanvas->spectrumVisible()?1:0));
|
wxGetApp().getAudioVisualQueue()->set_max_num_items((scopeCanvas->scopeVisible()?1:0) + (scopeCanvas->spectrumVisible()?1:0));
|
||||||
|
|
||||||
wxGetApp().getScopeProcessor()->run();
|
wxGetApp().getScopeProcessor()->run();
|
||||||
// wxGetApp().getSpectrumDistributor()->run();
|
|
||||||
|
|
||||||
SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcessor();
|
SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcessor();
|
||||||
|
|
||||||
@ -1069,11 +1066,24 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
wproc->setCenterFrequency(waterfallCanvas->getCenterFrequency());
|
wproc->setCenterFrequency(waterfallCanvas->getCenterFrequency());
|
||||||
wxGetApp().getSDRPostThread()->setIQVisualRange(waterfallCanvas->getCenterFrequency(), waterfallCanvas->getBandwidth());
|
wxGetApp().getSDRPostThread()->setIQVisualRange(waterfallCanvas->getCenterFrequency(), waterfallCanvas->getBandwidth());
|
||||||
|
|
||||||
// waterfallCanvas->processInputQueue();
|
demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
// waterfallCanvas->Refresh();
|
|
||||||
// demodWaterfallCanvas->processInputQueue();
|
if (modemPropertiesUpdated.load() && demod && demod->isModemInitialized()) {
|
||||||
// demodWaterfallCanvas->Refresh();
|
modemProps->initProperties(demod->getModemArgs());
|
||||||
|
modemPropertiesUpdated.store(false);
|
||||||
|
demodTray->Layout();
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
if (demod->getModemType() == "digital") {
|
||||||
|
ModemDigitalOutputConsole *outp = (ModemDigitalOutputConsole *)demod->getOutput();
|
||||||
|
if (!outp->getDialog()) {
|
||||||
|
outp->setTitle(demod->getDemodulatorType() + ": " + frequencyToStr(demod->getFrequency()));
|
||||||
|
outp->setDialog(new DigitalConsole(this, outp));
|
||||||
|
}
|
||||||
|
demod->showOutput();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->IsActive()) {
|
if (!this->IsActive()) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(25));
|
std::this_thread::sleep_for(std::chrono::milliseconds(25));
|
||||||
}
|
}
|
||||||
@ -1134,6 +1144,14 @@ void AppFrame::saveSession(std::string fileName) {
|
|||||||
*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;
|
||||||
|
|
||||||
|
ModemSettings saveSettings = (*instance_i)->readModemSettings();
|
||||||
|
if (saveSettings.size()) {
|
||||||
|
DataNode *settingsNode = demod->newChild("settings");
|
||||||
|
for (ModemSettings::const_iterator msi = saveSettings.begin(); msi != saveSettings.end(); msi++) {
|
||||||
|
*settingsNode->newChild(msi->first.c_str()) = msi->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.SaveToFileXML(fileName);
|
s.SaveToFileXML(fileName);
|
||||||
@ -1177,35 +1195,79 @@ 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");
|
||||||
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 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
|
std::string type = "FM";
|
||||||
//#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
|
|
||||||
|
|
||||||
|
DataNode *demodTypeNode = demod->hasAnother("type")?demod->getNext("type"):nullptr;
|
||||||
|
|
||||||
|
if (demodTypeNode->element()->getDataType() == DATA_INT) {
|
||||||
|
int legacyType = *demodTypeNode;
|
||||||
|
int legacyStereo = demod->hasAnother("stereo") ? (int) *demod->getNext("stereo") : 0;
|
||||||
|
switch (legacyType) { // legacy demod ID
|
||||||
|
case 1: type = legacyStereo?"FMS":"FM"; break;
|
||||||
|
case 2: type = "AM"; break;
|
||||||
|
case 3: type = "LSB"; break;
|
||||||
|
case 4: type = "USB"; break;
|
||||||
|
case 5: type = "DSB"; break;
|
||||||
|
case 6: type = "ASK"; break;
|
||||||
|
case 7: type = "APSK"; break;
|
||||||
|
case 8: type = "BPSK"; break;
|
||||||
|
case 9: type = "DPSK"; break;
|
||||||
|
case 10: type = "PSK"; break;
|
||||||
|
case 11: type = "OOK"; break;
|
||||||
|
case 12: type = "ST"; break;
|
||||||
|
case 13: type = "SQAM"; break;
|
||||||
|
case 14: type = "QAM"; break;
|
||||||
|
case 15: type = "QPSK"; break;
|
||||||
|
case 16: type = "I/Q"; break;
|
||||||
|
default: type = "FM"; break;
|
||||||
|
}
|
||||||
|
} else if (demodTypeNode->element()->getDataType() == DATA_STRING) {
|
||||||
|
demodTypeNode->element()->get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemSettings mSettings;
|
||||||
|
|
||||||
|
if (demod->hasAnother("settings")) {
|
||||||
|
DataNode *modemSettings = demod->getNext("settings");
|
||||||
|
for (int msi = 0, numSettings = modemSettings->numChildren(); msi < numSettings; msi++) {
|
||||||
|
DataNode *settingNode = modemSettings->child(msi);
|
||||||
|
std::string keyName = settingNode->getName();
|
||||||
|
std::string strSettingValue = "";
|
||||||
|
|
||||||
|
int dataType = settingNode->element()->getDataType();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (dataType == DATA_STRING) {
|
||||||
|
settingNode->element()->get(strSettingValue);
|
||||||
|
} else if (dataType == DATA_INT || dataType == DATA_LONG || dataType == DATA_LONGLONG) {
|
||||||
|
long long intSettingValue = *settingNode;
|
||||||
|
strSettingValue = std::to_string(intSettingValue);
|
||||||
|
} else if (dataType == DATA_FLOAT || dataType == DATA_DOUBLE) {
|
||||||
|
double floatSettingValue = *settingNode;
|
||||||
|
strSettingValue = std::to_string(floatSettingValue);
|
||||||
|
} else {
|
||||||
|
std::cout << "Unhandled setting data type: " << dataType << std::endl;
|
||||||
|
}
|
||||||
|
} catch (DataTypeMismatchException e) {
|
||||||
|
std::cout << "Setting data type mismatch: " << dataType << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyName != "" && strSettingValue != "") {
|
||||||
|
mSettings[keyName] = strSettingValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DemodulatorInstance *newDemod = wxGetApp().getDemodMgr().newThread();
|
DemodulatorInstance *newDemod = wxGetApp().getDemodMgr().newThread();
|
||||||
loadedDemod = newDemod;
|
loadedDemod = newDemod;
|
||||||
numDemodulators++;
|
numDemodulators++;
|
||||||
|
newDemod->writeModemSettings(mSettings);
|
||||||
newDemod->setDemodulatorType(type);
|
newDemod->setDemodulatorType(type);
|
||||||
newDemod->setBandwidth(bandwidth);
|
newDemod->setBandwidth(bandwidth);
|
||||||
newDemod->setFrequency(freq);
|
newDemod->setFrequency(freq);
|
||||||
@ -1269,3 +1331,8 @@ FFTVisualDataThread *AppFrame::getWaterfallDataThread() {
|
|||||||
return waterfallDataThread;
|
return waterfallDataThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppFrame::updateModemProperties(ModemArgInfoList args) {
|
||||||
|
newModemArgs = args;
|
||||||
|
modemPropertiesUpdated.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "GainCanvas.h"
|
#include "GainCanvas.h"
|
||||||
#include "FFTVisualDataThread.h"
|
#include "FFTVisualDataThread.h"
|
||||||
#include "SDRDeviceInfo.h"
|
#include "SDRDeviceInfo.h"
|
||||||
|
#include "ModemProperties.h"
|
||||||
//#include "UITestCanvas.h"
|
//#include "UITestCanvas.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -67,6 +68,8 @@ public:
|
|||||||
|
|
||||||
FFTVisualDataThread *getWaterfallDataThread();
|
FFTVisualDataThread *getWaterfallDataThread();
|
||||||
|
|
||||||
|
void updateModemProperties(ModemArgInfoList args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnMenu(wxCommandEvent& event);
|
void OnMenu(wxCommandEvent& event);
|
||||||
void OnClose(wxCloseEvent& event);
|
void OnClose(wxCloseEvent& event);
|
||||||
@ -81,7 +84,6 @@ private:
|
|||||||
ModeSelectorCanvas *demodModeSelector;
|
ModeSelectorCanvas *demodModeSelector;
|
||||||
#ifdef ENABLE_DIGITAL_LAB
|
#ifdef ENABLE_DIGITAL_LAB
|
||||||
ModeSelectorCanvas *demodModeSelectorAdv;
|
ModeSelectorCanvas *demodModeSelectorAdv;
|
||||||
ModeSelectorCanvas *demodModeSelectorCons;
|
|
||||||
#endif
|
#endif
|
||||||
SpectrumCanvas *demodSpectrumCanvas;
|
SpectrumCanvas *demodSpectrumCanvas;
|
||||||
WaterfallCanvas *demodWaterfallCanvas;
|
WaterfallCanvas *demodWaterfallCanvas;
|
||||||
@ -121,6 +123,10 @@ private:
|
|||||||
std::thread *t_FFTData;
|
std::thread *t_FFTData;
|
||||||
SDRDeviceInfo *devInfo;
|
SDRDeviceInfo *devInfo;
|
||||||
std::atomic_bool deviceChanged;
|
std::atomic_bool deviceChanged;
|
||||||
|
|
||||||
|
ModemProperties *modemProps;
|
||||||
|
std::atomic_bool modemPropertiesUpdated;
|
||||||
|
ModemArgInfoList newModemArgs;
|
||||||
|
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
@ -20,20 +20,20 @@
|
|||||||
|
|
||||||
IMPLEMENT_APP(CubicSDR)
|
IMPLEMENT_APP(CubicSDR)
|
||||||
|
|
||||||
#ifdef ENABLE_DIGITAL_LAB
|
//#ifdef ENABLE_DIGITAL_LAB
|
||||||
// console output buffer for windows
|
//// console output buffer for windows
|
||||||
#ifdef _WINDOWS
|
//#ifdef _WINDOWS
|
||||||
class outbuf : public std::streambuf {
|
//class outbuf : public std::streambuf {
|
||||||
public:
|
// public:
|
||||||
outbuf() {
|
// outbuf() {
|
||||||
setp(0, 0);
|
// setp(0, 0);
|
||||||
}
|
// }
|
||||||
virtual int_type overflow(int_type c = traits_type::eof()) {
|
// virtual int_type overflow(int_type c = traits_type::eof()) {
|
||||||
return fputc(c, stdout) == EOF ? traits_type::eof() : c;
|
// return fputc(c, stdout) == EOF ? traits_type::eof() : c;
|
||||||
}
|
// }
|
||||||
};
|
//};
|
||||||
#endif
|
//#endif
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
#ifdef MINGW_PATCH
|
#ifdef MINGW_PATCH
|
||||||
FILE _iob[] = { *stdin, *stdout, *stderr };
|
FILE _iob[] = { *stdin, *stdout, *stderr };
|
||||||
@ -149,18 +149,18 @@ bool CubicSDR::OnInit() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DIGITAL_LAB
|
//#ifdef ENABLE_DIGITAL_LAB
|
||||||
// console output for windows
|
// // console output for windows
|
||||||
#ifdef _WINDOWS
|
// #ifdef _WINDOWS
|
||||||
if (AllocConsole()) {
|
// if (AllocConsole()) {
|
||||||
freopen("CONOUT$", "w", stdout);
|
// freopen("CONOUT$", "w", stdout);
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
|
// SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
|
||||||
}
|
// }
|
||||||
outbuf ob;
|
// outbuf ob;
|
||||||
std::streambuf *sb = std::cout.rdbuf(&ob);
|
// std::streambuf *sb = std::cout.rdbuf(&ob);
|
||||||
std::cout.rdbuf(sb);
|
// std::cout.rdbuf(sb);
|
||||||
#endif
|
// #endif
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
wxApp::SetAppName("CubicSDR");
|
wxApp::SetAppName("CubicSDR");
|
||||||
|
|
||||||
@ -172,17 +172,23 @@ bool CubicSDR::OnInit() {
|
|||||||
Modem::addModemFactory(new ModemDSB);
|
Modem::addModemFactory(new ModemDSB);
|
||||||
Modem::addModemFactory(new ModemIQ);
|
Modem::addModemFactory(new ModemIQ);
|
||||||
|
|
||||||
|
#ifdef ENABLE_DIGITAL_LAB
|
||||||
Modem::addModemFactory(new ModemAPSK);
|
Modem::addModemFactory(new ModemAPSK);
|
||||||
Modem::addModemFactory(new ModemASK);
|
Modem::addModemFactory(new ModemASK);
|
||||||
Modem::addModemFactory(new ModemBPSK);
|
Modem::addModemFactory(new ModemBPSK);
|
||||||
Modem::addModemFactory(new ModemDPSK);
|
Modem::addModemFactory(new ModemDPSK);
|
||||||
|
#if ENABLE_LIQUID_EXPERIMENTAL
|
||||||
|
Modem::addModemFactory(new ModemFSK);
|
||||||
|
#endif
|
||||||
|
Modem::addModemFactory(new ModemGMSK);
|
||||||
Modem::addModemFactory(new ModemOOK);
|
Modem::addModemFactory(new ModemOOK);
|
||||||
Modem::addModemFactory(new ModemPSK);
|
Modem::addModemFactory(new ModemPSK);
|
||||||
Modem::addModemFactory(new ModemQAM);
|
Modem::addModemFactory(new ModemQAM);
|
||||||
Modem::addModemFactory(new ModemQPSK);
|
Modem::addModemFactory(new ModemQPSK);
|
||||||
Modem::addModemFactory(new ModemSQAM);
|
Modem::addModemFactory(new ModemSQAM);
|
||||||
Modem::addModemFactory(new ModemST);
|
Modem::addModemFactory(new ModemST);
|
||||||
|
#endif
|
||||||
|
|
||||||
frequency = wxGetApp().getConfig()->getCenterFreq();
|
frequency = wxGetApp().getConfig()->getCenterFreq();
|
||||||
offset = 0;
|
offset = 0;
|
||||||
ppm = 0;
|
ppm = 0;
|
||||||
|
@ -37,16 +37,22 @@
|
|||||||
#include "ModemDSB.h"
|
#include "ModemDSB.h"
|
||||||
#include "ModemIQ.h"
|
#include "ModemIQ.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_DIGITAL_LAB
|
||||||
#include "ModemAPSK.h"
|
#include "ModemAPSK.h"
|
||||||
#include "ModemASK.h"
|
#include "ModemASK.h"
|
||||||
#include "ModemBPSK.h"
|
#include "ModemBPSK.h"
|
||||||
#include "ModemDPSK.h"
|
#include "ModemDPSK.h"
|
||||||
|
#if ENABLE_LIQUID_EXPERIMENTAL
|
||||||
|
#include "ModemFSK.h"
|
||||||
|
#endif
|
||||||
|
#include "ModemGMSK.h"
|
||||||
#include "ModemOOK.h"
|
#include "ModemOOK.h"
|
||||||
#include "ModemPSK.h"
|
#include "ModemPSK.h"
|
||||||
#include "ModemQAM.h"
|
#include "ModemQAM.h"
|
||||||
#include "ModemQPSK.h"
|
#include "ModemQPSK.h"
|
||||||
#include "ModemSQAM.h"
|
#include "ModemSQAM.h"
|
||||||
#include "ModemST.h"
|
#include "ModemST.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <wx/cmdline.h>
|
#include <wx/cmdline.h>
|
||||||
|
|
||||||
@ -123,7 +129,6 @@ public:
|
|||||||
void setDeviceSelectorClosed();
|
void setDeviceSelectorClosed();
|
||||||
bool isDeviceSelectorOpen();
|
bool isDeviceSelectorOpen();
|
||||||
void closeDeviceSelector();
|
void closeDeviceSelector();
|
||||||
|
|
||||||
|
|
||||||
void setAGCMode(bool mode);
|
void setAGCMode(bool mode);
|
||||||
bool getAGCMode();
|
bool getAGCMode();
|
||||||
|
179
src/ModemProperties.cpp
Normal file
179
src/ModemProperties.cpp
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
#include "ModemProperties.h"
|
||||||
|
#include "CubicSDR.h"
|
||||||
|
|
||||||
|
ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid,
|
||||||
|
const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel(parent, winid, pos, size, style, name) {
|
||||||
|
|
||||||
|
m_propertyGrid = new wxPropertyGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPG_DEFAULT_STYLE);
|
||||||
|
|
||||||
|
bSizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
bSizer->Add(m_propertyGrid, 1, wxEXPAND, 5);
|
||||||
|
|
||||||
|
this->SetSizer(bSizer);
|
||||||
|
|
||||||
|
m_propertyGrid->Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( ModemProperties::OnChange ), NULL, this );
|
||||||
|
this->Connect( wxEVT_SHOW, wxShowEventHandler( ModemProperties::OnShow ), NULL, this );
|
||||||
|
|
||||||
|
this->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( ModemProperties::OnMouseEnter ), NULL, this);
|
||||||
|
this->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( ModemProperties::OnMouseLeave ), NULL, this);
|
||||||
|
|
||||||
|
mouseInView = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemProperties::OnShow(wxShowEvent &event) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemProperties::~ModemProperties() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemProperties::initProperties(ModemArgInfoList newArgs) {
|
||||||
|
args = newArgs;
|
||||||
|
|
||||||
|
bSizer->Layout();
|
||||||
|
m_propertyGrid->Clear();
|
||||||
|
|
||||||
|
if (newArgs.size() == 0) {
|
||||||
|
Hide();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_propertyGrid->Append(new wxPropertyCategory("Modem Settings"));
|
||||||
|
|
||||||
|
ModemArgInfoList::const_iterator args_i;
|
||||||
|
|
||||||
|
for (args_i = args.begin(); args_i != args.end(); args_i++) {
|
||||||
|
ModemArgInfo arg = (*args_i);
|
||||||
|
props[arg.key] = addArgInfoProperty(m_propertyGrid, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_propertyGrid->FitColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxPGProperty *ModemProperties::addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg) {
|
||||||
|
wxPGProperty *prop = nullptr;
|
||||||
|
|
||||||
|
int intVal;
|
||||||
|
double floatVal;
|
||||||
|
std::vector<std::string>::iterator stringIter;
|
||||||
|
|
||||||
|
switch (arg.type) {
|
||||||
|
case ModemArgInfo::INT:
|
||||||
|
try {
|
||||||
|
intVal = std::stoi(arg.value);
|
||||||
|
} catch (std::invalid_argument e) {
|
||||||
|
intVal = 0;
|
||||||
|
}
|
||||||
|
prop = pg->Append( new wxIntProperty(arg.name, wxPG_LABEL, intVal) );
|
||||||
|
if (arg.range.minimum() != arg.range.maximum()) {
|
||||||
|
pg->SetPropertyAttribute( prop, wxPG_ATTR_MIN, arg.range.minimum());
|
||||||
|
pg->SetPropertyAttribute( prop, wxPG_ATTR_MAX, arg.range.maximum());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ModemArgInfo::FLOAT:
|
||||||
|
try {
|
||||||
|
floatVal = std::stod(arg.value);
|
||||||
|
} catch (std::invalid_argument e) {
|
||||||
|
floatVal = 0;
|
||||||
|
}
|
||||||
|
prop = pg->Append( new wxFloatProperty(arg.name, wxPG_LABEL, floatVal) );
|
||||||
|
if (arg.range.minimum() != arg.range.maximum()) {
|
||||||
|
pg->SetPropertyAttribute( prop, wxPG_ATTR_MIN, arg.range.minimum());
|
||||||
|
pg->SetPropertyAttribute( prop, wxPG_ATTR_MAX, arg.range.maximum());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ModemArgInfo::BOOL:
|
||||||
|
prop = pg->Append( new wxBoolProperty(arg.name, wxPG_LABEL, (arg.value=="true")) );
|
||||||
|
break;
|
||||||
|
case ModemArgInfo::STRING:
|
||||||
|
if (arg.options.size()) {
|
||||||
|
intVal = 0;
|
||||||
|
prop = pg->Append( new wxEnumProperty(arg.name, wxPG_LABEL) );
|
||||||
|
for (stringIter = arg.options.begin(); stringIter != arg.options.end(); stringIter++) {
|
||||||
|
std::string optName = (*stringIter);
|
||||||
|
std::string displayName = optName;
|
||||||
|
if (arg.optionNames.size()) {
|
||||||
|
displayName = arg.optionNames[intVal];
|
||||||
|
}
|
||||||
|
|
||||||
|
prop->AddChoice(displayName);
|
||||||
|
if ((*stringIter)==arg.value) {
|
||||||
|
prop->SetChoiceSelection(intVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
intVal++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prop = pg->Append( new wxStringProperty(arg.name, wxPG_LABEL, arg.value) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ModemArgInfo::PATH_DIR:
|
||||||
|
break;
|
||||||
|
case ModemArgInfo::PATH_FILE:
|
||||||
|
break;
|
||||||
|
case ModemArgInfo::COLOR:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop != NULL) {
|
||||||
|
prop->SetHelpString(arg.key + ": " + arg.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemProperties::readProperty(std::string key) {
|
||||||
|
int i = 0;
|
||||||
|
ModemArgInfoList::const_iterator args_i;
|
||||||
|
|
||||||
|
for (args_i = args.begin(); args_i != args.end(); args_i++) {
|
||||||
|
ModemArgInfo arg = (*args_i);
|
||||||
|
if (arg.key == key) {
|
||||||
|
wxPGProperty *prop = props[key];
|
||||||
|
|
||||||
|
std::string result = "";
|
||||||
|
if (arg.type == ModemArgInfo::STRING && arg.options.size()) {
|
||||||
|
return arg.options[prop->GetChoiceSelection()];
|
||||||
|
} else if (arg.type == ModemArgInfo::BOOL) {
|
||||||
|
return (prop->GetValueAsString()=="True")?"true":"false";
|
||||||
|
} else {
|
||||||
|
return prop->GetValueAsString().ToStdString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemProperties::OnChange(wxPropertyGridEvent &event) {
|
||||||
|
DemodulatorInstance *inst = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
|
if (!inst) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, wxPGProperty *>::const_iterator prop_i;
|
||||||
|
for (prop_i = props.begin(); prop_i != props.end(); prop_i++) {
|
||||||
|
if (prop_i->second == event.m_property) {
|
||||||
|
std::string key = prop_i->first;
|
||||||
|
std::string value = readProperty(prop_i->first);
|
||||||
|
inst->writeModemSetting(key, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemProperties::OnMouseEnter(wxMouseEvent &event) {
|
||||||
|
mouseInView = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemProperties::OnMouseLeave(wxMouseEvent &event) {
|
||||||
|
mouseInView = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModemProperties::isMouseInView() {
|
||||||
|
return mouseInView;
|
||||||
|
}
|
39
src/ModemProperties.h
Normal file
39
src/ModemProperties.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wx/panel.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/propgrid/propgrid.h>
|
||||||
|
#include <wx/propgrid/advprops.h>
|
||||||
|
|
||||||
|
#include "Modem.h"
|
||||||
|
|
||||||
|
class ModemProperties : public wxPanel {
|
||||||
|
public:
|
||||||
|
ModemProperties(
|
||||||
|
wxWindow *parent,
|
||||||
|
wxWindowID winid = wxID_ANY,
|
||||||
|
const wxPoint& pos = wxDefaultPosition,
|
||||||
|
const wxSize& size = wxDefaultSize,
|
||||||
|
long style = wxTAB_TRAVERSAL | wxNO_BORDER,
|
||||||
|
const wxString& name = wxPanelNameStr
|
||||||
|
);
|
||||||
|
~ModemProperties();
|
||||||
|
|
||||||
|
void initProperties(ModemArgInfoList newArgs);
|
||||||
|
bool isMouseInView();
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxPGProperty *addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg);
|
||||||
|
std::string readProperty(std::string);
|
||||||
|
void OnChange(wxPropertyGridEvent &event);
|
||||||
|
void OnShow(wxShowEvent &event);
|
||||||
|
|
||||||
|
void OnMouseEnter(wxMouseEvent &event);
|
||||||
|
void OnMouseLeave(wxMouseEvent &event);
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer;
|
||||||
|
wxPropertyGrid* m_propertyGrid;
|
||||||
|
ModemArgInfoList args;
|
||||||
|
std::map<std::string, wxPGProperty *> props;
|
||||||
|
bool mouseInView;
|
||||||
|
};
|
@ -18,6 +18,7 @@ public:
|
|||||||
int sampleRate;
|
int sampleRate;
|
||||||
int channels;
|
int channels;
|
||||||
float peak;
|
float peak;
|
||||||
|
int type;
|
||||||
std::vector<float> data;
|
std::vector<float> data;
|
||||||
std::mutex busy_update;
|
std::mutex busy_update;
|
||||||
|
|
||||||
|
@ -14,9 +14,6 @@ class DemodulatorThreadCommand {
|
|||||||
public:
|
public:
|
||||||
enum DemodulatorThreadCommandEnum {
|
enum DemodulatorThreadCommandEnum {
|
||||||
DEMOD_THREAD_CMD_NULL,
|
DEMOD_THREAD_CMD_NULL,
|
||||||
DEMOD_THREAD_CMD_SET_BANDWIDTH,
|
|
||||||
DEMOD_THREAD_CMD_SET_FREQUENCY,
|
|
||||||
DEMOD_THREAD_CMD_SET_AUDIO_RATE,
|
|
||||||
DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED,
|
DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED,
|
||||||
DEMOD_THREAD_CMD_DEMOD_TERMINATED,
|
DEMOD_THREAD_CMD_DEMOD_TERMINATED,
|
||||||
DEMOD_THREAD_CMD_AUDIO_TERMINATED
|
DEMOD_THREAD_CMD_AUDIO_TERMINATED
|
||||||
@ -82,6 +79,7 @@ class DemodulatorThreadPostIQData: public ReferenceCounter {
|
|||||||
public:
|
public:
|
||||||
std::vector<liquid_float_complex> data;
|
std::vector<liquid_float_complex> data;
|
||||||
long long sampleRate;
|
long long sampleRate;
|
||||||
|
std::string modemName;
|
||||||
std::string modemType;
|
std::string modemType;
|
||||||
Modem *modem;
|
Modem *modem;
|
||||||
ModemKit *modemKit;
|
ModemKit *modemKit;
|
||||||
@ -124,23 +122,3 @@ typedef ThreadQueue<DemodulatorThreadIQData *> DemodulatorThreadInputQueue;
|
|||||||
typedef ThreadQueue<DemodulatorThreadPostIQData *> DemodulatorThreadPostInputQueue;
|
typedef ThreadQueue<DemodulatorThreadPostIQData *> DemodulatorThreadPostInputQueue;
|
||||||
typedef ThreadQueue<DemodulatorThreadCommand> DemodulatorThreadCommandQueue;
|
typedef ThreadQueue<DemodulatorThreadCommand> DemodulatorThreadCommandQueue;
|
||||||
typedef ThreadQueue<DemodulatorThreadControlCommand> DemodulatorThreadControlCommandQueue;
|
typedef ThreadQueue<DemodulatorThreadControlCommand> DemodulatorThreadControlCommandQueue;
|
||||||
|
|
||||||
class DemodulatorThreadParameters {
|
|
||||||
public:
|
|
||||||
long long frequency;
|
|
||||||
long long sampleRate;
|
|
||||||
unsigned int bandwidth; // set equal to disable second stage re-sampling?
|
|
||||||
unsigned int audioSampleRate;
|
|
||||||
|
|
||||||
std::string demodType;
|
|
||||||
|
|
||||||
DemodulatorThreadParameters() :
|
|
||||||
frequency(0), sampleRate(DEFAULT_SAMPLE_RATE), bandwidth(200000), audioSampleRate(0),
|
|
||||||
demodType("FM") {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
~DemodulatorThreadParameters() {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
#include "DemodulatorInstance.h"
|
#include "DemodulatorInstance.h"
|
||||||
|
#include "CubicSDR.h"
|
||||||
|
|
||||||
DemodulatorInstance::DemodulatorInstance() :
|
DemodulatorInstance::DemodulatorInstance() :
|
||||||
t_PreDemod(NULL), t_Demod(NULL), t_Audio(NULL) {
|
t_PreDemod(nullptr), t_Demod(nullptr), t_Audio(nullptr) {
|
||||||
|
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
activeOutput = nullptr;
|
||||||
|
#endif
|
||||||
terminated.store(true);
|
terminated.store(true);
|
||||||
audioTerminated.store(true);
|
audioTerminated.store(true);
|
||||||
demodTerminated.store(true);
|
demodTerminated.store(true);
|
||||||
@ -12,23 +16,20 @@ DemodulatorInstance::DemodulatorInstance() :
|
|||||||
muted.store(false);
|
muted.store(false);
|
||||||
tracking.store(false);
|
tracking.store(false);
|
||||||
follow.store(false);
|
follow.store(false);
|
||||||
currentAudioSampleRate.store(0);
|
|
||||||
currentFrequency.store(0);
|
|
||||||
currentBandwidth.store(0);
|
|
||||||
currentOutputDevice.store(-1);
|
currentOutputDevice.store(-1);
|
||||||
currentAudioGain.store(1.0);
|
currentAudioGain.store(1.0);
|
||||||
|
|
||||||
label = new std::string("Unnamed");
|
label = new std::string("Unnamed");
|
||||||
pipeIQInputData = new DemodulatorThreadInputQueue;
|
pipeIQInputData = new DemodulatorThreadInputQueue;
|
||||||
pipeIQDemodData = new DemodulatorThreadPostInputQueue;
|
pipeIQDemodData = new DemodulatorThreadPostInputQueue;
|
||||||
pipeDemodCommand = new DemodulatorThreadCommandQueue;
|
|
||||||
pipeDemodNotify = new DemodulatorThreadCommandQueue;
|
pipeDemodNotify = new DemodulatorThreadCommandQueue;
|
||||||
|
|
||||||
demodulatorPreThread = new DemodulatorPreThread();
|
audioThread = new AudioThread();
|
||||||
|
|
||||||
|
demodulatorPreThread = new DemodulatorPreThread(this);
|
||||||
demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData);
|
demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData);
|
||||||
demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData);
|
demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData);
|
||||||
demodulatorPreThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
|
demodulatorPreThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
|
||||||
demodulatorPreThread->setInputQueue("CommandQueue",pipeDemodCommand);
|
|
||||||
|
|
||||||
pipeAudioData = new AudioThreadInputQueue;
|
pipeAudioData = new AudioThreadInputQueue;
|
||||||
threadQueueControl = new DemodulatorThreadControlCommandQueue;
|
threadQueueControl = new DemodulatorThreadControlCommandQueue;
|
||||||
@ -39,20 +40,19 @@ DemodulatorInstance::DemodulatorInstance() :
|
|||||||
demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
|
demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
|
||||||
demodulatorThread->setOutputQueue("AudioDataOutput", pipeAudioData);
|
demodulatorThread->setOutputQueue("AudioDataOutput", pipeAudioData);
|
||||||
|
|
||||||
audioThread = new AudioThread();
|
|
||||||
audioThread->setInputQueue("AudioDataInput", pipeAudioData);
|
audioThread->setInputQueue("AudioDataInput", pipeAudioData);
|
||||||
audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify);
|
audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify);
|
||||||
|
|
||||||
currentDemodType = demodulatorPreThread->getParams().demodType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance::~DemodulatorInstance() {
|
DemodulatorInstance::~DemodulatorInstance() {
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
delete activeOutput;
|
||||||
|
#endif
|
||||||
delete audioThread;
|
delete audioThread;
|
||||||
delete demodulatorThread;
|
delete demodulatorThread;
|
||||||
delete demodulatorPreThread;
|
delete demodulatorPreThread;
|
||||||
delete pipeIQInputData;
|
delete pipeIQInputData;
|
||||||
delete pipeIQDemodData;
|
delete pipeIQDemodData;
|
||||||
delete pipeDemodCommand;
|
|
||||||
delete pipeDemodNotify;
|
delete pipeDemodNotify;
|
||||||
delete threadQueueControl;
|
delete threadQueueControl;
|
||||||
delete pipeAudioData;
|
delete pipeAudioData;
|
||||||
@ -67,17 +67,8 @@ void DemodulatorInstance::run() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// while (!isTerminated()) {
|
|
||||||
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
// }
|
|
||||||
|
|
||||||
currentFrequency = demodulatorPreThread->getParams().frequency;
|
|
||||||
currentAudioSampleRate = AudioThread::deviceSampleRate[getOutputDevice()];
|
|
||||||
demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate;
|
|
||||||
setDemodulatorType(demodulatorPreThread->getParams().demodType);
|
|
||||||
|
|
||||||
t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
|
t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
|
||||||
|
|
||||||
#ifdef __APPLE__ // Already using pthreads, might as well do some custom init..
|
#ifdef __APPLE__ // Already using pthreads, might as well do some custom init..
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
size_t size;
|
size_t size;
|
||||||
@ -113,10 +104,6 @@ void DemodulatorInstance::updateLabel(long long freq) {
|
|||||||
setLabel(newLabel.str());
|
setLabel(newLabel.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorThreadCommandQueue *DemodulatorInstance::getCommandQueue() {
|
|
||||||
return pipeDemodCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorInstance::terminate() {
|
void DemodulatorInstance::terminate() {
|
||||||
std::cout << "Terminating demodulator audio thread.." << std::endl;
|
std::cout << "Terminating demodulator audio thread.." << std::endl;
|
||||||
audioThread->terminate();
|
audioThread->terminate();
|
||||||
@ -156,6 +143,11 @@ bool DemodulatorInstance::isTerminated() {
|
|||||||
#else
|
#else
|
||||||
t_Demod->join();
|
t_Demod->join();
|
||||||
delete t_Demod;
|
delete t_Demod;
|
||||||
|
#endif
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
if (activeOutput) {
|
||||||
|
closeOutput();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
demodTerminated = true;
|
demodTerminated = true;
|
||||||
break;
|
break;
|
||||||
@ -184,8 +176,18 @@ bool DemodulatorInstance::isActive() {
|
|||||||
|
|
||||||
void DemodulatorInstance::setActive(bool state) {
|
void DemodulatorInstance::setActive(bool state) {
|
||||||
if (active && !state) {
|
if (active && !state) {
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
if (activeOutput && !isTerminated()) {
|
||||||
|
activeOutput->Hide();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
audioThread->setActive(state);
|
audioThread->setActive(state);
|
||||||
} else if (!active && state) {
|
} else if (!active && state) {
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
if (activeOutput && getModemType() == "digital") {
|
||||||
|
activeOutput->Show();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
audioThread->setActive(state);
|
audioThread->setActive(state);
|
||||||
}
|
}
|
||||||
if (!state) {
|
if (!state) {
|
||||||
@ -225,6 +227,8 @@ float DemodulatorInstance::getSignalLevel() {
|
|||||||
|
|
||||||
void DemodulatorInstance::setSquelchLevel(float signal_level_in) {
|
void DemodulatorInstance::setSquelchLevel(float signal_level_in) {
|
||||||
demodulatorThread->setSquelchLevel(signal_level_in);
|
demodulatorThread->setSquelchLevel(signal_level_in);
|
||||||
|
wxGetApp().getDemodMgr().setLastSquelchLevel(signal_level_in);
|
||||||
|
wxGetApp().getDemodMgr().setLastSquelchEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
float DemodulatorInstance::getSquelchLevel() {
|
float DemodulatorInstance::getSquelchLevel() {
|
||||||
@ -254,35 +258,36 @@ int DemodulatorInstance::getOutputDevice() {
|
|||||||
return currentOutputDevice;
|
return currentOutputDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::checkBandwidth() {
|
|
||||||
// if ((currentDemodType == DEMOD_TYPE_USB || currentDemodType == DEMOD_TYPE_LSB) && (getBandwidth() % 2)) {
|
|
||||||
// setBandwidth(getBandwidth()+1);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) {
|
void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) {
|
||||||
currentDemodType = demod_type_in;
|
|
||||||
|
|
||||||
if (currentDemodType == "I/Q") {
|
|
||||||
if (currentAudioSampleRate) {
|
|
||||||
setBandwidth(currentAudioSampleRate);
|
|
||||||
} else {
|
|
||||||
setBandwidth(AudioThread::deviceSampleRate[getOutputDevice()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setGain(getGain());
|
setGain(getGain());
|
||||||
|
if (demodulatorPreThread) {
|
||||||
|
std::string currentDemodType = demodulatorPreThread->getDemodType();
|
||||||
|
if ((currentDemodType != "") && (currentDemodType != demod_type_in)) {
|
||||||
|
lastModemSettings[currentDemodType] = demodulatorPreThread->readModemSettings();
|
||||||
|
lastModemBandwidth[currentDemodType] = demodulatorPreThread->getBandwidth();
|
||||||
|
}
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
if (activeOutput) {
|
||||||
|
activeOutput->Hide();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
demodulatorPreThread->getParams().demodType = currentDemodType;
|
demodulatorPreThread->setDemodType(demod_type_in);
|
||||||
if (!active) {
|
int lastbw = 0;
|
||||||
checkBandwidth();
|
if (currentDemodType != "" && lastModemBandwidth.find(demod_type_in) != lastModemBandwidth.end()) {
|
||||||
demodulatorPreThread->setDemodType(currentDemodType);
|
lastbw = lastModemBandwidth[demod_type_in];
|
||||||
} else if (demodulatorThread && threadQueueControl) {
|
}
|
||||||
demodulatorPreThread->setDemodType(currentDemodType);
|
if (!lastbw) {
|
||||||
|
lastbw = Modem::getModemDefaultSampleRate(demod_type_in);
|
||||||
|
}
|
||||||
|
if (lastbw) {
|
||||||
|
setBandwidth(lastbw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DemodulatorInstance::getDemodulatorType() {
|
std::string DemodulatorInstance::getDemodulatorType() {
|
||||||
return currentDemodType;
|
return demodulatorPreThread->getDemodType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setDemodulatorLock(bool demod_lock_in) {
|
void DemodulatorInstance::setDemodulatorLock(bool demod_lock_in) {
|
||||||
@ -302,101 +307,50 @@ int DemodulatorInstance::getDemodulatorLock() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setDemodulatorCons(int demod_cons_in) {
|
|
||||||
Modem *cModem = demodulatorPreThread->getModem();
|
|
||||||
if (cModem && cModem->getType() == "digital") {
|
|
||||||
((ModemDigital *)cModem)->setDemodulatorCons(demod_cons_in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int DemodulatorInstance::getDemodulatorCons() {
|
|
||||||
Modem *cModem = demodulatorPreThread->getModem();
|
|
||||||
if (cModem && cModem->getType() == "digital") {
|
|
||||||
return ((ModemDigital *)cModem)->getDemodulatorCons();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorInstance::setBandwidth(int bw) {
|
void DemodulatorInstance::setBandwidth(int bw) {
|
||||||
if (currentDemodType == "I/Q") {
|
demodulatorPreThread->setBandwidth(bw);
|
||||||
if (currentAudioSampleRate) {
|
|
||||||
bw = currentAudioSampleRate;
|
|
||||||
} else {
|
|
||||||
bw = AudioThread::deviceSampleRate[getOutputDevice()];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!active && demodulatorPreThread != NULL) {
|
|
||||||
currentBandwidth = bw;
|
|
||||||
checkBandwidth();
|
|
||||||
demodulatorPreThread->getParams().bandwidth = currentBandwidth;
|
|
||||||
} else if (demodulatorPreThread && pipeDemodCommand) {
|
|
||||||
DemodulatorThreadCommand command;
|
|
||||||
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH;
|
|
||||||
currentBandwidth = bw;
|
|
||||||
checkBandwidth();
|
|
||||||
command.llong_value = currentBandwidth;
|
|
||||||
pipeDemodCommand->push(command);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DemodulatorInstance::getBandwidth() {
|
int DemodulatorInstance::getBandwidth() {
|
||||||
if (!currentBandwidth) {
|
return demodulatorPreThread->getBandwidth();
|
||||||
currentBandwidth = demodulatorPreThread->getParams().bandwidth;
|
|
||||||
}
|
|
||||||
return currentBandwidth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setFrequency(long long freq) {
|
void DemodulatorInstance::setFrequency(long long freq) {
|
||||||
if ((freq - getBandwidth() / 2) <= 0) {
|
if ((freq - getBandwidth() / 2) <= 0) {
|
||||||
freq = getBandwidth() / 2;
|
freq = getBandwidth() / 2;
|
||||||
}
|
}
|
||||||
if (!active) {
|
|
||||||
currentFrequency = freq;
|
demodulatorPreThread->setFrequency(freq);
|
||||||
demodulatorPreThread->getParams().frequency = currentFrequency;
|
#if ENABLE_DIGITAL_LAB
|
||||||
} else if (demodulatorPreThread && pipeDemodCommand) {
|
if (activeOutput) {
|
||||||
DemodulatorThreadCommand command;
|
if (isModemInitialized() && getModemType() == "digital") {
|
||||||
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
|
ModemDigitalOutputConsole *outp = (ModemDigitalOutputConsole *)getOutput();
|
||||||
currentFrequency = freq;
|
outp->setTitle(getDemodulatorType() + ": " + frequencyToStr(getFrequency()));
|
||||||
command.llong_value = freq;
|
}
|
||||||
pipeDemodCommand->push(command);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
long long DemodulatorInstance::getFrequency() {
|
long long DemodulatorInstance::getFrequency() {
|
||||||
if (!currentFrequency) {
|
return demodulatorPreThread->getFrequency();
|
||||||
currentFrequency = demodulatorPreThread->getParams().frequency;
|
|
||||||
}
|
|
||||||
return currentFrequency;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DemodulatorInstance::setAudioSampleRate(int sampleRate) {
|
void DemodulatorInstance::setAudioSampleRate(int sampleRate) {
|
||||||
if (terminated) {
|
demodulatorPreThread->setSampleRate(sampleRate);
|
||||||
currentAudioSampleRate = sampleRate;
|
|
||||||
demodulatorPreThread->getParams().audioSampleRate = sampleRate;
|
|
||||||
} else if (demodulatorPreThread && pipeDemodCommand) {
|
|
||||||
DemodulatorThreadCommand command;
|
|
||||||
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE;
|
|
||||||
currentAudioSampleRate = sampleRate;
|
|
||||||
command.llong_value = sampleRate;
|
|
||||||
pipeDemodCommand->push(command);
|
|
||||||
}
|
|
||||||
if (currentDemodType == "I/Q") {
|
|
||||||
setBandwidth(currentAudioSampleRate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DemodulatorInstance::getAudioSampleRate() {
|
int DemodulatorInstance::getAudioSampleRate() {
|
||||||
if (!currentAudioSampleRate) {
|
if (!audioThread) {
|
||||||
currentAudioSampleRate = audioThread->getSampleRate();
|
return 0;
|
||||||
}
|
}
|
||||||
return currentAudioSampleRate;
|
return audioThread->getSampleRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DemodulatorInstance::setGain(float gain_in) {
|
void DemodulatorInstance::setGain(float gain_in) {
|
||||||
currentAudioGain = gain_in;
|
currentAudioGain = gain_in;
|
||||||
audioThread->setGain(gain_in);
|
audioThread->setGain(gain_in);
|
||||||
|
wxGetApp().getDemodMgr().setLastGain(gain_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
float DemodulatorInstance::getGain() {
|
float DemodulatorInstance::getGain() {
|
||||||
@ -426,8 +380,91 @@ bool DemodulatorInstance::isMuted() {
|
|||||||
void DemodulatorInstance::setMuted(bool muted) {
|
void DemodulatorInstance::setMuted(bool muted) {
|
||||||
this->muted = muted;
|
this->muted = muted;
|
||||||
demodulatorThread->setMuted(muted);
|
demodulatorThread->setMuted(muted);
|
||||||
|
wxGetApp().getDemodMgr().setLastMuted(muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorThreadInputQueue *DemodulatorInstance::getIQInputDataPipe() {
|
DemodulatorThreadInputQueue *DemodulatorInstance::getIQInputDataPipe() {
|
||||||
return pipeIQInputData;
|
return pipeIQInputData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList DemodulatorInstance::getModemArgs() {
|
||||||
|
Modem *m = demodulatorPreThread->getModem();
|
||||||
|
|
||||||
|
ModemArgInfoList args;
|
||||||
|
if (m != nullptr) {
|
||||||
|
args = m->getSettings();
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DemodulatorInstance::readModemSetting(std::string setting) {
|
||||||
|
return demodulatorPreThread->readModemSetting(setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorInstance::writeModemSetting(std::string setting, std::string value) {
|
||||||
|
demodulatorPreThread->writeModemSetting(setting, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemSettings DemodulatorInstance::readModemSettings() {
|
||||||
|
return demodulatorPreThread->readModemSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorInstance::writeModemSettings(ModemSettings settings) {
|
||||||
|
demodulatorPreThread->writeModemSettings(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DemodulatorInstance::isModemInitialized() {
|
||||||
|
if (!demodulatorPreThread || isTerminated()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return demodulatorPreThread->isInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DemodulatorInstance::getModemType() {
|
||||||
|
if (isModemInitialized()) {
|
||||||
|
return demodulatorPreThread->getModem()->getType();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemSettings DemodulatorInstance::getLastModemSettings(std::string demodType) {
|
||||||
|
if (lastModemSettings.find(demodType) != lastModemSettings.end()) {
|
||||||
|
return lastModemSettings[demodType];
|
||||||
|
} else {
|
||||||
|
ModemSettings mods;
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
ModemDigitalOutput *DemodulatorInstance::getOutput() {
|
||||||
|
if (activeOutput == nullptr) {
|
||||||
|
activeOutput = new ModemDigitalOutputConsole();
|
||||||
|
}
|
||||||
|
return activeOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorInstance::showOutput() {
|
||||||
|
if (activeOutput != nullptr) {
|
||||||
|
activeOutput->Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorInstance::hideOutput() {
|
||||||
|
if (activeOutput != nullptr) {
|
||||||
|
activeOutput->Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorInstance::closeOutput() {
|
||||||
|
if (isModemInitialized()) {
|
||||||
|
if (getModemType() == "digital") {
|
||||||
|
ModemDigital *dModem = (ModemDigital *)demodulatorPreThread->getModem();
|
||||||
|
dModem->setOutput(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (activeOutput) {
|
||||||
|
activeOutput->Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -10,6 +10,10 @@
|
|||||||
#include "ModemDigital.h"
|
#include "ModemDigital.h"
|
||||||
#include "ModemAnalog.h"
|
#include "ModemAnalog.h"
|
||||||
|
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
#include "DigitalConsole.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class DemodulatorInstance {
|
class DemodulatorInstance {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -58,9 +62,6 @@ public:
|
|||||||
|
|
||||||
void setDemodulatorLock(bool demod_lock_in);
|
void setDemodulatorLock(bool demod_lock_in);
|
||||||
int getDemodulatorLock();
|
int getDemodulatorLock();
|
||||||
|
|
||||||
void setDemodulatorCons(int demod_cons_in);
|
|
||||||
int getDemodulatorCons();
|
|
||||||
|
|
||||||
void setBandwidth(int bw);
|
void setBandwidth(int bw);
|
||||||
int getBandwidth();
|
int getBandwidth();
|
||||||
@ -73,7 +74,7 @@ public:
|
|||||||
|
|
||||||
void setAudioSampleRate(int sampleRate);
|
void setAudioSampleRate(int sampleRate);
|
||||||
int getAudioSampleRate();
|
int getAudioSampleRate();
|
||||||
|
|
||||||
bool isFollow();
|
bool isFollow();
|
||||||
void setFollow(bool follow);
|
void setFollow(bool follow);
|
||||||
|
|
||||||
@ -85,11 +86,27 @@ public:
|
|||||||
|
|
||||||
DemodulatorThreadInputQueue *getIQInputDataPipe();
|
DemodulatorThreadInputQueue *getIQInputDataPipe();
|
||||||
|
|
||||||
|
ModemArgInfoList getModemArgs();
|
||||||
|
std::string readModemSetting(std::string setting);
|
||||||
|
ModemSettings readModemSettings();
|
||||||
|
void writeModemSetting(std::string setting, std::string value);
|
||||||
|
void writeModemSettings(ModemSettings settings);
|
||||||
|
|
||||||
|
bool isModemInitialized();
|
||||||
|
std::string getModemType();
|
||||||
|
ModemSettings getLastModemSettings(std::string demodType);
|
||||||
|
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
ModemDigitalOutput *getOutput();
|
||||||
|
void showOutput();
|
||||||
|
void hideOutput();
|
||||||
|
void closeOutput();
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DemodulatorThreadInputQueue* pipeIQInputData;
|
DemodulatorThreadInputQueue* pipeIQInputData;
|
||||||
DemodulatorThreadPostInputQueue* pipeIQDemodData;
|
DemodulatorThreadPostInputQueue* pipeIQDemodData;
|
||||||
AudioThreadInputQueue *pipeAudioData;
|
AudioThreadInputQueue *pipeAudioData;
|
||||||
DemodulatorThreadCommandQueue* pipeDemodCommand;
|
|
||||||
DemodulatorThreadCommandQueue* pipeDemodNotify;
|
DemodulatorThreadCommandQueue* pipeDemodNotify;
|
||||||
DemodulatorPreThread *demodulatorPreThread;
|
DemodulatorPreThread *demodulatorPreThread;
|
||||||
DemodulatorThread *demodulatorThread;
|
DemodulatorThread *demodulatorThread;
|
||||||
@ -97,8 +114,6 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void checkBandwidth();
|
|
||||||
|
|
||||||
std::atomic<std::string *> label; //
|
std::atomic<std::string *> label; //
|
||||||
std::atomic_bool terminated; //
|
std::atomic_bool terminated; //
|
||||||
std::atomic_bool demodTerminated; //
|
std::atomic_bool demodTerminated; //
|
||||||
@ -108,11 +123,12 @@ private:
|
|||||||
std::atomic_bool squelch;
|
std::atomic_bool squelch;
|
||||||
std::atomic_bool muted;
|
std::atomic_bool muted;
|
||||||
|
|
||||||
std::atomic_llong currentFrequency;
|
|
||||||
std::atomic_int currentBandwidth;
|
|
||||||
std::string currentDemodType;
|
|
||||||
std::atomic_int currentOutputDevice;
|
std::atomic_int currentOutputDevice;
|
||||||
std::atomic_int currentAudioSampleRate;
|
|
||||||
std::atomic<float> currentAudioGain;
|
std::atomic<float> currentAudioGain;
|
||||||
std::atomic_bool follow, tracking;
|
std::atomic_bool follow, tracking;
|
||||||
};
|
std::map<std::string, ModemSettings> lastModemSettings;
|
||||||
|
std::map<std::string, int> lastModemBandwidth;
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
ModemDigitalOutput *activeOutput;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
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(-100), lastGain(1.0), lastMuted(false) {
|
DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(-100), lastGain(1.0), lastMuted(false) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorMgr::~DemodulatorMgr() {
|
DemodulatorMgr::~DemodulatorMgr() {
|
||||||
@ -88,6 +87,7 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo
|
|||||||
if (!temporary) {
|
if (!temporary) {
|
||||||
if (activeDemodulator != NULL) {
|
if (activeDemodulator != NULL) {
|
||||||
lastActiveDemodulator = activeDemodulator;
|
lastActiveDemodulator = activeDemodulator;
|
||||||
|
updateLastState();
|
||||||
} else {
|
} else {
|
||||||
lastActiveDemodulator = demod;
|
lastActiveDemodulator = demod;
|
||||||
}
|
}
|
||||||
@ -121,8 +121,6 @@ DemodulatorInstance *DemodulatorMgr::getActiveDemodulator() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::getLastActiveDemodulator() {
|
DemodulatorInstance *DemodulatorMgr::getLastActiveDemodulator() {
|
||||||
updateLastState();
|
|
||||||
|
|
||||||
return lastActiveDemodulator;
|
return lastActiveDemodulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,10 +160,10 @@ void DemodulatorMgr::updateLastState() {
|
|||||||
lastBandwidth = lastActiveDemodulator->getBandwidth();
|
lastBandwidth = lastActiveDemodulator->getBandwidth();
|
||||||
lastDemodType = lastActiveDemodulator->getDemodulatorType();
|
lastDemodType = lastActiveDemodulator->getDemodulatorType();
|
||||||
lastDemodLock = lastActiveDemodulator->getDemodulatorLock();
|
lastDemodLock = lastActiveDemodulator->getDemodulatorLock();
|
||||||
lastDemodCons = lastActiveDemodulator->getDemodulatorCons();
|
|
||||||
lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled();
|
lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled();
|
||||||
lastSquelch = lastActiveDemodulator->getSquelchLevel();
|
lastSquelch = lastActiveDemodulator->getSquelchLevel();
|
||||||
lastGain = lastActiveDemodulator->getGain();
|
lastGain = lastActiveDemodulator->getGain();
|
||||||
|
lastModemSettings[lastDemodType] = lastActiveDemodulator->readModemSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -175,8 +173,8 @@ int DemodulatorMgr::getLastBandwidth() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorMgr::setLastBandwidth(int lastBandwidth) {
|
void DemodulatorMgr::setLastBandwidth(int lastBandwidth) {
|
||||||
if (lastBandwidth < 1500) {
|
if (lastBandwidth < MIN_BANDWIDTH) {
|
||||||
lastBandwidth = 1500;
|
lastBandwidth = MIN_BANDWIDTH;
|
||||||
} else if (lastBandwidth > wxGetApp().getSampleRate()) {
|
} else if (lastBandwidth > wxGetApp().getSampleRate()) {
|
||||||
lastBandwidth = wxGetApp().getSampleRate();
|
lastBandwidth = wxGetApp().getSampleRate();
|
||||||
}
|
}
|
||||||
@ -191,14 +189,6 @@ void DemodulatorMgr::setLastDemodulatorType(std::string lastDemodType) {
|
|||||||
this->lastDemodType = lastDemodType;
|
this->lastDemodType = lastDemodType;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DemodulatorMgr::getLastDemodulatorCons() const {
|
|
||||||
return lastDemodCons;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorMgr::setLastDemodulatorCons(int lastDemodCons) {
|
|
||||||
this->lastDemodCons = lastDemodCons;
|
|
||||||
}
|
|
||||||
|
|
||||||
float DemodulatorMgr::getLastGain() const {
|
float DemodulatorMgr::getLastGain() const {
|
||||||
return lastGain;
|
return lastGain;
|
||||||
}
|
}
|
||||||
@ -231,3 +221,10 @@ void DemodulatorMgr::setLastMuted(bool lastMuted) {
|
|||||||
this->lastMuted = lastMuted;
|
this->lastMuted = lastMuted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemSettings DemodulatorMgr::getLastModemSettings(std::string modemType) {
|
||||||
|
return lastModemSettings[modemType];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorMgr::setLastModemSettings(std::string modemType, ModemSettings settings) {
|
||||||
|
lastModemSettings[modemType] = settings;
|
||||||
|
}
|
||||||
|
@ -27,9 +27,6 @@ public:
|
|||||||
|
|
||||||
std::string getLastDemodulatorType() const;
|
std::string getLastDemodulatorType() const;
|
||||||
void setLastDemodulatorType(std::string lastDemodType);
|
void setLastDemodulatorType(std::string lastDemodType);
|
||||||
|
|
||||||
int getLastDemodulatorCons() const;
|
|
||||||
void setLastDemodulatorCons(int lastDemodCons);
|
|
||||||
|
|
||||||
float getLastGain() const;
|
float getLastGain() const;
|
||||||
void setLastGain(float lastGain);
|
void setLastGain(float lastGain);
|
||||||
@ -43,9 +40,13 @@ public:
|
|||||||
bool isLastMuted() const;
|
bool isLastMuted() const;
|
||||||
void setLastMuted(bool lastMuted);
|
void setLastMuted(bool lastMuted);
|
||||||
|
|
||||||
|
ModemSettings getLastModemSettings(std::string);
|
||||||
|
void setLastModemSettings(std::string, ModemSettings);
|
||||||
|
|
||||||
|
void updateLastState();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void garbageCollect();
|
void garbageCollect();
|
||||||
void updateLastState();
|
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> demods;
|
std::vector<DemodulatorInstance *> demods;
|
||||||
std::vector<DemodulatorInstance *> demods_deleted;
|
std::vector<DemodulatorInstance *> demods_deleted;
|
||||||
@ -56,9 +57,10 @@ private:
|
|||||||
int lastBandwidth;
|
int lastBandwidth;
|
||||||
std::string lastDemodType;
|
std::string lastDemodType;
|
||||||
bool lastDemodLock;
|
bool lastDemodLock;
|
||||||
int lastDemodCons;
|
|
||||||
bool lastSquelchEnabled;
|
bool lastSquelchEnabled;
|
||||||
float lastSquelch;
|
float lastSquelch;
|
||||||
float lastGain;
|
float lastGain;
|
||||||
bool lastMuted;
|
bool lastMuted;
|
||||||
|
|
||||||
|
std::map<std::string, ModemSettings> lastModemSettings;
|
||||||
};
|
};
|
||||||
|
@ -7,10 +7,12 @@
|
|||||||
|
|
||||||
#include "DemodulatorPreThread.h"
|
#include "DemodulatorPreThread.h"
|
||||||
#include "CubicSDR.h"
|
#include "CubicSDR.h"
|
||||||
|
#include "DemodulatorInstance.h"
|
||||||
|
|
||||||
DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL)
|
DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL)
|
||||||
{
|
{
|
||||||
initialized.store(false);
|
initialized.store(false);
|
||||||
|
this->parent = parent;
|
||||||
|
|
||||||
freqShifter = nco_crcf_create(LIQUID_VCO);
|
freqShifter = nco_crcf_create(LIQUID_VCO);
|
||||||
shiftFrequency = 0;
|
shiftFrequency = 0;
|
||||||
@ -21,18 +23,21 @@ DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iq
|
|||||||
workerThread = new DemodulatorWorkerThread();
|
workerThread = new DemodulatorWorkerThread();
|
||||||
workerThread->setInputQueue("WorkerCommandQueue",workerQueue);
|
workerThread->setInputQueue("WorkerCommandQueue",workerQueue);
|
||||||
workerThread->setOutputQueue("WorkerResultQueue",workerResults);
|
workerThread->setOutputQueue("WorkerResultQueue",workerResults);
|
||||||
|
|
||||||
|
newSampleRate = currentSampleRate = 0;
|
||||||
|
newBandwidth = currentBandwidth = 0;
|
||||||
|
newAudioSampleRate = currentAudioSampleRate = 0;
|
||||||
|
newFrequency = currentFrequency = 0;
|
||||||
|
|
||||||
|
sampleRateChanged.store(false);
|
||||||
|
frequencyChanged.store(false);
|
||||||
|
bandwidthChanged.store(false);
|
||||||
|
audioSampleRateChanged.store(false);
|
||||||
|
modemSettingsChanged.store(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorPreThread::initialize() {
|
bool DemodulatorPreThread::isInitialized() {
|
||||||
iqResampleRatio = (double) (params.bandwidth) / (double) params.sampleRate;
|
return initialized.load();
|
||||||
|
|
||||||
float As = 60.0f; // stop-band attenuation [dB]
|
|
||||||
|
|
||||||
iqResampler = msresamp_crcf_create(iqResampleRatio, As);
|
|
||||||
|
|
||||||
initialized.store(true);
|
|
||||||
|
|
||||||
lastParams = params;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorPreThread::~DemodulatorPreThread() {
|
DemodulatorPreThread::~DemodulatorPreThread() {
|
||||||
@ -46,10 +51,6 @@ void DemodulatorPreThread::run() {
|
|||||||
pthread_setschedparam(tID, SCHED_FIFO, &prio);
|
pthread_setschedparam(tID, SCHED_FIFO, &prio);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!initialized) {
|
|
||||||
initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Demodulator preprocessor thread started.." << std::endl;
|
std::cout << "Demodulator preprocessor thread started.." << std::endl;
|
||||||
|
|
||||||
ReBuffer<DemodulatorThreadPostIQData> buffers;
|
ReBuffer<DemodulatorThreadPostIQData> buffers;
|
||||||
@ -57,87 +58,103 @@ void DemodulatorPreThread::run() {
|
|||||||
iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput");
|
iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput");
|
||||||
iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOutput");
|
iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOutput");
|
||||||
threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue");
|
threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue");
|
||||||
commandQueue = ( DemodulatorThreadCommandQueue*)getInputQueue("CommandQueue");
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
setDemodType(params.demodType);
|
|
||||||
t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread);
|
t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread);
|
||||||
|
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
DemodulatorThreadIQData *inp;
|
DemodulatorThreadIQData *inp;
|
||||||
iqInputQueue->pop(inp);
|
iqInputQueue->pop(inp);
|
||||||
|
|
||||||
bool bandwidthChanged = false;
|
if (frequencyChanged.load()) {
|
||||||
bool rateChanged = false;
|
currentFrequency = newFrequency;
|
||||||
DemodulatorThreadParameters tempParams = params;
|
frequencyChanged.store(false);
|
||||||
|
}
|
||||||
if (!commandQueue->empty()) {
|
|
||||||
while (!commandQueue->empty()) {
|
if (inp->sampleRate != currentSampleRate) {
|
||||||
DemodulatorThreadCommand command;
|
newSampleRate = inp->sampleRate;
|
||||||
commandQueue->pop(command);
|
if (newSampleRate) {
|
||||||
switch (command.cmd) {
|
sampleRateChanged.store(true);
|
||||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH:
|
|
||||||
if (command.llong_value < 1500) {
|
|
||||||
command.llong_value = 1500;
|
|
||||||
}
|
|
||||||
if (command.llong_value > params.sampleRate) {
|
|
||||||
tempParams.bandwidth = params.sampleRate;
|
|
||||||
} else {
|
|
||||||
tempParams.bandwidth = command.llong_value;
|
|
||||||
}
|
|
||||||
bandwidthChanged = true;
|
|
||||||
break;
|
|
||||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY:
|
|
||||||
params.frequency = tempParams.frequency = command.llong_value;
|
|
||||||
break;
|
|
||||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE:
|
|
||||||
tempParams.audioSampleRate = (int)command.llong_value;
|
|
||||||
rateChanged = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inp->sampleRate != tempParams.sampleRate && inp->sampleRate) {
|
if (!newAudioSampleRate) {
|
||||||
tempParams.sampleRate = inp->sampleRate;
|
newAudioSampleRate = parent->getAudioSampleRate();
|
||||||
rateChanged = true;
|
if (newAudioSampleRate) {
|
||||||
|
audioSampleRateChanged.store(true);
|
||||||
|
}
|
||||||
|
} else if (parent->getAudioSampleRate() != newAudioSampleRate) {
|
||||||
|
int newRate;
|
||||||
|
if ((newRate = parent->getAudioSampleRate())) {
|
||||||
|
newAudioSampleRate = parent->getAudioSampleRate();
|
||||||
|
audioSampleRateChanged.store(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bandwidthChanged || rateChanged) {
|
if (demodTypeChanged.load() && (newSampleRate && newAudioSampleRate && newBandwidth)) {
|
||||||
|
DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD);
|
||||||
|
command.frequency = newFrequency;
|
||||||
|
command.sampleRate = newSampleRate;
|
||||||
|
command.demodType = newDemodType;
|
||||||
|
command.bandwidth = newBandwidth;
|
||||||
|
command.audioSampleRate = newAudioSampleRate;
|
||||||
|
demodType = newDemodType;
|
||||||
|
sampleRateChanged.store(false);
|
||||||
|
audioSampleRateChanged.store(false);
|
||||||
|
ModemSettings lastSettings = parent->getLastModemSettings(newDemodType);
|
||||||
|
if (lastSettings.size() != 0) {
|
||||||
|
command.settings = lastSettings;
|
||||||
|
if (modemSettingsBuffered.size()) {
|
||||||
|
for (ModemSettings::const_iterator msi = modemSettingsBuffered.begin(); msi != modemSettingsBuffered.end(); msi++) {
|
||||||
|
command.settings[msi->first] = msi->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
command.settings = modemSettingsBuffered;
|
||||||
|
}
|
||||||
|
modemSettingsBuffered.clear();
|
||||||
|
modemSettingsChanged.store(false);
|
||||||
|
workerQueue->push(command);
|
||||||
|
cModem = nullptr;
|
||||||
|
cModemKit = nullptr;
|
||||||
|
demodTypeChanged.store(false);
|
||||||
|
initialized.store(false);
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
cModemKit && cModem &&
|
||||||
|
(bandwidthChanged.load() || sampleRateChanged.load() || audioSampleRateChanged.load() || cModem->shouldRebuildKit()) &&
|
||||||
|
(newSampleRate && newAudioSampleRate && newBandwidth)
|
||||||
|
) {
|
||||||
DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS);
|
DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS);
|
||||||
command.sampleRate = tempParams.sampleRate;
|
command.frequency = newFrequency;
|
||||||
command.audioSampleRate = tempParams.audioSampleRate;
|
command.sampleRate = newSampleRate;
|
||||||
command.bandwidth = tempParams.bandwidth;
|
command.bandwidth = newBandwidth;
|
||||||
command.frequency = tempParams.frequency;
|
command.audioSampleRate = newAudioSampleRate;
|
||||||
|
bandwidthChanged.store(false);
|
||||||
|
sampleRateChanged.store(false);
|
||||||
|
audioSampleRateChanged.store(false);
|
||||||
|
modemSettingsBuffered.clear();
|
||||||
workerQueue->push(command);
|
workerQueue->push(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!initialized) {
|
|
||||||
inp->decRefCount();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Requested frequency is not center, shift it into the center!
|
// Requested frequency is not center, shift it into the center!
|
||||||
if ((params.frequency - inp->frequency) != shiftFrequency || rateChanged) {
|
if ((currentFrequency - inp->frequency) != shiftFrequency) {
|
||||||
shiftFrequency = params.frequency - inp->frequency;
|
shiftFrequency = currentFrequency - inp->frequency;
|
||||||
if (abs(shiftFrequency) <= (int) ((double) (inp->sampleRate / 2) * 1.5)) {
|
if (abs(shiftFrequency) <= (int) ((double) (inp->sampleRate / 2) * 1.5)) {
|
||||||
nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) inp->sampleRate)));
|
nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) inp->sampleRate)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abs(shiftFrequency) > (int) ((double) (inp->sampleRate / 2) * 1.5)) {
|
if (cModem && cModemKit && abs(shiftFrequency) > (int) ((double) (inp->sampleRate / 2) * 1.5)) {
|
||||||
inp->decRefCount();
|
inp->decRefCount();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::lock_guard < std::mutex > lock(inp->m_mutex);
|
// std::lock_guard < std::mutex > lock(inp->m_mutex);
|
||||||
std::vector<liquid_float_complex> *data = &inp->data;
|
std::vector<liquid_float_complex> *data = &inp->data;
|
||||||
if (data->size() && (inp->sampleRate == params.sampleRate)) {
|
if (data->size() && (inp->sampleRate == currentSampleRate) && cModem && cModemKit) {
|
||||||
int bufSize = data->size();
|
int bufSize = data->size();
|
||||||
|
|
||||||
if (in_buf_data.size() != bufSize) {
|
if (in_buf_data.size() != bufSize) {
|
||||||
@ -183,10 +200,11 @@ void DemodulatorPreThread::run() {
|
|||||||
resamp->setRefCount(1);
|
resamp->setRefCount(1);
|
||||||
resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
|
resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
|
||||||
|
|
||||||
resamp->modemType = demodType;
|
resamp->modemType = cModem->getType();
|
||||||
|
resamp->modemName = cModem->getName();
|
||||||
resamp->modem = cModem;
|
resamp->modem = cModem;
|
||||||
resamp->modemKit = cModemKit;
|
resamp->modemKit = cModemKit;
|
||||||
resamp->sampleRate = params.bandwidth;
|
resamp->sampleRate = currentBandwidth;
|
||||||
|
|
||||||
iqOutputQueue->push(resamp);
|
iqOutputQueue->push(resamp);
|
||||||
}
|
}
|
||||||
@ -200,7 +218,6 @@ void DemodulatorPreThread::run() {
|
|||||||
|
|
||||||
switch (result.cmd) {
|
switch (result.cmd) {
|
||||||
case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS:
|
case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS:
|
||||||
|
|
||||||
if (result.iqResampler) {
|
if (result.iqResampler) {
|
||||||
if (iqResampler) {
|
if (iqResampler) {
|
||||||
msresamp_crcf_destroy(iqResampler);
|
msresamp_crcf_destroy(iqResampler);
|
||||||
@ -211,31 +228,46 @@ void DemodulatorPreThread::run() {
|
|||||||
|
|
||||||
if (result.modem != nullptr) {
|
if (result.modem != nullptr) {
|
||||||
cModem = result.modem;
|
cModem = result.modem;
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
if (cModem->getType() == "digital") {
|
||||||
|
ModemDigital *mDigi = (ModemDigital *)cModem;
|
||||||
|
mDigi->setOutput(parent->getOutput());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.modemKit != nullptr) {
|
if (result.modemKit != nullptr) {
|
||||||
cModemKit = result.modemKit;
|
cModemKit = result.modemKit;
|
||||||
|
currentAudioSampleRate = cModemKit->audioSampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.bandwidth) {
|
if (result.bandwidth) {
|
||||||
params.bandwidth = result.bandwidth;
|
currentBandwidth = result.bandwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.sampleRate) {
|
if (result.sampleRate) {
|
||||||
params.sampleRate = result.sampleRate;
|
currentSampleRate = result.sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.modemType != "") {
|
if (result.modemName != "") {
|
||||||
demodType = result.modemType;
|
demodType = result.modemName;
|
||||||
params.demodType = result.modemType;
|
|
||||||
demodTypeChanged.store(false);
|
demodTypeChanged.store(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shiftFrequency = inp->frequency-1;
|
||||||
|
initialized.store(cModem != nullptr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((cModem != nullptr) && modemSettingsChanged.load()) {
|
||||||
|
cModem->writeSettings(modemSettingsBuffered);
|
||||||
|
modemSettingsBuffered.clear();
|
||||||
|
modemSettingsChanged.store(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers.purge();
|
buffers.purge();
|
||||||
@ -246,21 +278,8 @@ 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) {
|
void DemodulatorPreThread::setDemodType(std::string demodType) {
|
||||||
this->newDemodType = demodType;
|
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);
|
demodTypeChanged.store(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,6 +290,51 @@ std::string DemodulatorPreThread::getDemodType() {
|
|||||||
return demodType;
|
return demodType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DemodulatorPreThread::setFrequency(long long freq) {
|
||||||
|
frequencyChanged.store(true);
|
||||||
|
newFrequency = freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long DemodulatorPreThread::getFrequency() {
|
||||||
|
if (frequencyChanged.load()) {
|
||||||
|
return newFrequency;
|
||||||
|
}
|
||||||
|
return currentFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorPreThread::setSampleRate(long long sampleRate) {
|
||||||
|
sampleRateChanged.store(true);
|
||||||
|
newSampleRate = sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long DemodulatorPreThread::getSampleRate() {
|
||||||
|
if (sampleRateChanged.load()) {
|
||||||
|
return newSampleRate;
|
||||||
|
}
|
||||||
|
return currentSampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorPreThread::setBandwidth(int bandwidth) {
|
||||||
|
bandwidthChanged.store(true);
|
||||||
|
newBandwidth = bandwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DemodulatorPreThread::getBandwidth() {
|
||||||
|
return currentBandwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorPreThread::setAudioSampleRate(int rate) {
|
||||||
|
audioSampleRateChanged.store(true);
|
||||||
|
newAudioSampleRate = rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DemodulatorPreThread::getAudioSampleRate() {
|
||||||
|
if (audioSampleRateChanged.load()) {
|
||||||
|
return newAudioSampleRate;
|
||||||
|
}
|
||||||
|
return currentAudioSampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
void DemodulatorPreThread::terminate() {
|
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
|
||||||
@ -285,7 +349,6 @@ void DemodulatorPreThread::terminate() {
|
|||||||
delete workerQueue;
|
delete workerQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Modem *DemodulatorPreThread::getModem() {
|
Modem *DemodulatorPreThread::getModem() {
|
||||||
return cModem;
|
return cModem;
|
||||||
}
|
}
|
||||||
@ -293,3 +356,31 @@ Modem *DemodulatorPreThread::getModem() {
|
|||||||
ModemKit *DemodulatorPreThread::getModemKit() {
|
ModemKit *DemodulatorPreThread::getModemKit() {
|
||||||
return cModemKit;
|
return cModemKit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string DemodulatorPreThread::readModemSetting(std::string setting) {
|
||||||
|
if (cModem) {
|
||||||
|
return cModem->readSetting(setting);
|
||||||
|
} else if (modemSettingsBuffered.find(setting) != modemSettingsBuffered.end()) {
|
||||||
|
return modemSettingsBuffered[setting];
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorPreThread::writeModemSetting(std::string setting, std::string value) {
|
||||||
|
modemSettingsBuffered[setting] = value;
|
||||||
|
modemSettingsChanged.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemSettings DemodulatorPreThread::readModemSettings() {
|
||||||
|
if (cModem) {
|
||||||
|
return cModem->readSettings();
|
||||||
|
} else {
|
||||||
|
return modemSettingsBuffered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorPreThread::writeModemSettings(ModemSettings settings) {
|
||||||
|
modemSettingsBuffered = settings;
|
||||||
|
modemSettingsChanged.store(true);
|
||||||
|
}
|
||||||
|
@ -7,37 +7,62 @@
|
|||||||
#include "DemodDefs.h"
|
#include "DemodDefs.h"
|
||||||
#include "DemodulatorWorkerThread.h"
|
#include "DemodulatorWorkerThread.h"
|
||||||
|
|
||||||
|
class DemodulatorInstance;
|
||||||
|
|
||||||
class DemodulatorPreThread : public IOThread {
|
class DemodulatorPreThread : public IOThread {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DemodulatorPreThread();
|
DemodulatorPreThread(DemodulatorInstance *parent);
|
||||||
~DemodulatorPreThread();
|
~DemodulatorPreThread();
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
DemodulatorThreadParameters &getParams();
|
|
||||||
void setParams(DemodulatorThreadParameters ¶ms_in);
|
|
||||||
|
|
||||||
void setDemodType(std::string demodType);
|
void setDemodType(std::string demodType);
|
||||||
std::string getDemodType();
|
std::string getDemodType();
|
||||||
|
|
||||||
void initialize();
|
void setFrequency(long long sampleRate);
|
||||||
|
long long getFrequency();
|
||||||
|
|
||||||
|
void setSampleRate(long long sampleRate);
|
||||||
|
long long getSampleRate();
|
||||||
|
|
||||||
|
void setBandwidth(int bandwidth);
|
||||||
|
int getBandwidth();
|
||||||
|
|
||||||
|
void setAudioSampleRate(int rate);
|
||||||
|
int getAudioSampleRate();
|
||||||
|
|
||||||
|
bool isInitialized();
|
||||||
|
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
Modem *getModem();
|
Modem *getModem();
|
||||||
ModemKit *getModemKit();
|
ModemKit *getModemKit();
|
||||||
|
|
||||||
|
std::string readModemSetting(std::string setting);
|
||||||
|
void writeModemSetting(std::string setting, std::string value);
|
||||||
|
ModemSettings readModemSettings();
|
||||||
|
void writeModemSettings(ModemSettings settings);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
DemodulatorInstance *parent;
|
||||||
msresamp_crcf iqResampler;
|
msresamp_crcf iqResampler;
|
||||||
double iqResampleRatio;
|
double iqResampleRatio;
|
||||||
std::vector<liquid_float_complex> resampledData;
|
std::vector<liquid_float_complex> resampledData;
|
||||||
|
|
||||||
Modem *cModem;
|
Modem *cModem;
|
||||||
ModemKit *cModemKit;
|
ModemKit *cModemKit;
|
||||||
|
|
||||||
|
long long currentSampleRate, newSampleRate;
|
||||||
|
long long currentFrequency, newFrequency;
|
||||||
|
int currentBandwidth, newBandwidth;
|
||||||
|
int currentAudioSampleRate, newAudioSampleRate;
|
||||||
|
|
||||||
DemodulatorThreadParameters params;
|
std::atomic_bool sampleRateChanged, frequencyChanged, bandwidthChanged, audioSampleRateChanged;
|
||||||
DemodulatorThreadParameters lastParams;
|
|
||||||
|
|
||||||
|
ModemSettings modemSettingsBuffered;
|
||||||
|
std::atomic_bool modemSettingsChanged;
|
||||||
|
|
||||||
nco_crcf freqShifter;
|
nco_crcf freqShifter;
|
||||||
int shiftFrequency;
|
int shiftFrequency;
|
||||||
|
|
||||||
@ -55,5 +80,4 @@ protected:
|
|||||||
DemodulatorThreadInputQueue* iqInputQueue;
|
DemodulatorThreadInputQueue* iqInputQueue;
|
||||||
DemodulatorThreadPostInputQueue* iqOutputQueue;
|
DemodulatorThreadPostInputQueue* iqOutputQueue;
|
||||||
DemodulatorThreadCommandQueue* threadQueueNotify;
|
DemodulatorThreadCommandQueue* threadQueueNotify;
|
||||||
DemodulatorThreadCommandQueue* commandQueue;
|
|
||||||
};
|
};
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) : IOThread(), audioSampleRate(0), squelchLevel(-100), signalLevel(-100), squelchEnabled(false), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) {
|
DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) : IOThread(), squelchLevel(-100), signalLevel(-100), squelchEnabled(false), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) {
|
||||||
|
|
||||||
demodInstance = parent;
|
demodInstance = parent;
|
||||||
muted.store(false);
|
muted.store(false);
|
||||||
@ -73,8 +73,6 @@ void DemodulatorThread::run() {
|
|||||||
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();
|
||||||
|
|
||||||
if (!bufSize) {
|
if (!bufSize) {
|
||||||
@ -122,15 +120,22 @@ void DemodulatorThread::run() {
|
|||||||
AudioThreadInput *ati = NULL;
|
AudioThreadInput *ati = NULL;
|
||||||
|
|
||||||
ModemAnalog *modemAnalog = (cModem->getType() == "analog")?((ModemAnalog *)cModem):nullptr;
|
ModemAnalog *modemAnalog = (cModem->getType() == "analog")?((ModemAnalog *)cModem):nullptr;
|
||||||
// ModemDigital *modemDigital = (cModem->getType() == "digital")?((ModemDigital *)cModem):nullptr;
|
ModemDigital *modemDigital = (cModem->getType() == "digital")?((ModemDigital *)cModem):nullptr;
|
||||||
|
|
||||||
if (modemAnalog != nullptr) {
|
if (modemAnalog != nullptr) {
|
||||||
ati = outputBuffers.getBuffer();
|
ati = outputBuffers.getBuffer();
|
||||||
|
|
||||||
ati->sampleRate = audioSampleRate;
|
ati->sampleRate = cModemKit->audioSampleRate;
|
||||||
|
ati->inputRate = inp->sampleRate;
|
||||||
|
ati->setRefCount(1);
|
||||||
|
} else if (modemDigital != nullptr) {
|
||||||
|
ati = outputBuffers.getBuffer();
|
||||||
|
|
||||||
|
ati->sampleRate = cModemKit->sampleRate;
|
||||||
ati->inputRate = inp->sampleRate;
|
ati->inputRate = inp->sampleRate;
|
||||||
ati->setRefCount(1);
|
ati->setRefCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cModem->demodulate(cModemKit, &modemData, ati);
|
cModem->demodulate(cModemKit, &modemData, ati);
|
||||||
|
|
||||||
if (currentSignalLevel > signalLevel) {
|
if (currentSignalLevel > signalLevel) {
|
||||||
@ -162,7 +167,15 @@ 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 (ati->channels==2) {
|
if (modemDigital) {
|
||||||
|
ati_vis->data.resize(inputData->size());
|
||||||
|
ati_vis->channels = 2;
|
||||||
|
for (int i = 0, iMax = inputData->size() / 2; i < iMax; i++) {
|
||||||
|
ati_vis->data[i * 2] = (*inputData)[i].real;
|
||||||
|
ati_vis->data[i * 2 + 1] = (*inputData)[i].imag;
|
||||||
|
}
|
||||||
|
ati_vis->type = 2;
|
||||||
|
} else if (ati->channels==2) {
|
||||||
ati_vis->channels = 2;
|
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) {
|
||||||
@ -171,25 +184,26 @@ void DemodulatorThread::run() {
|
|||||||
|
|
||||||
ati_vis->data.resize(stereoSize);
|
ati_vis->data.resize(stereoSize);
|
||||||
|
|
||||||
if (inp->modemType == "I/Q") {
|
if (inp->modemName == "I/Q") {
|
||||||
for (int i = 0; i < stereoSize / 2; i++) {
|
for (int i = 0; i < stereoSize / 2; i++) {
|
||||||
ati_vis->data[i] = (*inputData)[i].real * 0.75;
|
ati_vis->data[i] = (*inputData)[i].real * 0.75;
|
||||||
ati_vis->data[i + stereoSize / 2] = (*inputData)[i].imag * 0.75;
|
ati_vis->data[i + stereoSize / 2] = (*inputData)[i].imag * 0.75;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < stereoSize / 2; i++) {
|
for (int i = 0; i < stereoSize / 2; i++) {
|
||||||
ati_vis->inputRate = audioSampleRate;
|
ati_vis->inputRate = cModemKit->audioSampleRate;
|
||||||
ati_vis->sampleRate = 36000;
|
ati_vis->sampleRate = 36000;
|
||||||
ati_vis->data[i] = ati->data[i * 2];
|
ati_vis->data[i] = ati->data[i * 2];
|
||||||
ati_vis->data[i + stereoSize / 2] = ati->data[i * 2 + 1];
|
ati_vis->data[i + stereoSize / 2] = ati->data[i * 2 + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ati_vis->type = 1;
|
||||||
} else {
|
} else {
|
||||||
int numAudioWritten = ati->data.size();
|
int numAudioWritten = ati->data.size();
|
||||||
ati_vis->channels = 1;
|
ati_vis->channels = 1;
|
||||||
std::vector<float> *demodOutData = (modemAnalog != nullptr)?modemAnalog->getDemodOutputData():nullptr;
|
std::vector<float> *demodOutData = (modemAnalog != nullptr)?modemAnalog->getDemodOutputData():nullptr;
|
||||||
if ((numAudioWritten > bufSize) || (demodOutData == nullptr)) {
|
if ((numAudioWritten > bufSize) || (demodOutData == nullptr)) {
|
||||||
ati_vis->inputRate = audioSampleRate;
|
ati_vis->inputRate = cModemKit->audioSampleRate;
|
||||||
if (num_vis > numAudioWritten) {
|
if (num_vis > numAudioWritten) {
|
||||||
num_vis = numAudioWritten;
|
num_vis = numAudioWritten;
|
||||||
}
|
}
|
||||||
@ -200,7 +214,7 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
ati_vis->data.assign(demodOutData->begin(), demodOutData->begin() + num_vis);
|
ati_vis->data.assign(demodOutData->begin(), demodOutData->begin() + num_vis);
|
||||||
}
|
}
|
||||||
|
ati_vis->type = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
audioVisOutputQueue->push(ati_vis);
|
audioVisOutputQueue->push(ati_vis);
|
||||||
|
@ -43,7 +43,6 @@ protected:
|
|||||||
ReBuffer<AudioThreadInput> outputBuffers;
|
ReBuffer<AudioThreadInput> outputBuffers;
|
||||||
|
|
||||||
std::atomic_bool muted;
|
std::atomic_bool muted;
|
||||||
int audioSampleRate;
|
|
||||||
|
|
||||||
std::atomic<float> squelchLevel;
|
std::atomic<float> squelchLevel;
|
||||||
std::atomic<float> signalLevel;
|
std::atomic<float> signalLevel;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "DemodulatorWorkerThread.h"
|
#include "DemodulatorWorkerThread.h"
|
||||||
#include "CubicSDRDefs.h"
|
#include "CubicSDRDefs.h"
|
||||||
|
#include "CubicSDR.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
|
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
|
||||||
@ -26,63 +27,72 @@ void DemodulatorWorkerThread::run() {
|
|||||||
while (!done) {
|
while (!done) {
|
||||||
commandQueue->pop(command);
|
commandQueue->pop(command);
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS:
|
case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS:
|
||||||
filterChanged = true;
|
filterChanged = true;
|
||||||
filterCommand = command;
|
filterCommand = command;
|
||||||
break;
|
break;
|
||||||
case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD:
|
case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD:
|
||||||
makeDemod = true;
|
makeDemod = true;
|
||||||
demodCommand = command;
|
demodCommand = command;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
done = commandQueue->empty();
|
done = commandQueue->empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((makeDemod || 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]
|
|
||||||
|
if (filterCommand.sampleRate) {
|
||||||
if (filterCommand.sampleRate && filterCommand.bandwidth) {
|
result.sampleRate = filterCommand.sampleRate;
|
||||||
result.iqResampleRatio = (double) (filterCommand.bandwidth) / (double) filterCommand.sampleRate;
|
|
||||||
result.iqResampler = msresamp_crcf_create(result.iqResampleRatio, As);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (makeDemod) {
|
if (makeDemod) {
|
||||||
cModem = Modem::makeModem(demodCommand.demodType);
|
cModem = Modem::makeModem(demodCommand.demodType);
|
||||||
cModemType = demodCommand.demodType;
|
cModemName = cModem->getName();
|
||||||
|
cModemType = cModem->getType();
|
||||||
|
if (demodCommand.settings.size()) {
|
||||||
|
cModem->writeSettings(demodCommand.settings);
|
||||||
|
}
|
||||||
|
result.sampleRate = demodCommand.sampleRate;
|
||||||
|
wxGetApp().getAppFrame()->updateModemProperties(cModem->getSettings());
|
||||||
}
|
}
|
||||||
result.modem = cModem;
|
result.modem = cModem;
|
||||||
|
|
||||||
if (makeDemod && demodCommand.bandwidth && demodCommand.audioSampleRate) {
|
if (makeDemod && demodCommand.bandwidth && demodCommand.audioSampleRate) {
|
||||||
if (cModem != nullptr) {
|
if (cModem != nullptr) {
|
||||||
cModemKit = cModem->buildKit(demodCommand.bandwidth, demodCommand.audioSampleRate);
|
result.bandwidth = cModem->checkSampleRate(demodCommand.bandwidth, demodCommand.audioSampleRate);
|
||||||
|
cModemKit = cModem->buildKit(result.bandwidth, demodCommand.audioSampleRate);
|
||||||
} else {
|
} else {
|
||||||
cModemKit = nullptr;
|
cModemKit = nullptr;
|
||||||
}
|
}
|
||||||
} else if (filterChanged && filterCommand.bandwidth && filterCommand.audioSampleRate) {
|
} else if (filterChanged && filterCommand.bandwidth && filterCommand.audioSampleRate) {
|
||||||
if (cModem != nullptr) {
|
if (cModem != nullptr) {
|
||||||
cModemKit = cModem->buildKit(filterCommand.bandwidth, filterCommand.audioSampleRate);
|
result.bandwidth = cModem->checkSampleRate(filterCommand.bandwidth, filterCommand.audioSampleRate);
|
||||||
|
cModemKit = cModem->buildKit(result.bandwidth, filterCommand.audioSampleRate);
|
||||||
} else {
|
} else {
|
||||||
cModemKit = nullptr;
|
cModemKit = nullptr;
|
||||||
}
|
}
|
||||||
} else if (makeDemod) {
|
} else if (makeDemod) {
|
||||||
cModemKit = nullptr;
|
cModemKit = nullptr;
|
||||||
}
|
}
|
||||||
|
if (cModem != nullptr) {
|
||||||
|
cModem->clearRebuildKit();
|
||||||
|
}
|
||||||
|
|
||||||
|
float As = 60.0f; // stop-band attenuation [dB]
|
||||||
|
|
||||||
|
if (result.sampleRate && result.bandwidth) {
|
||||||
|
result.bandwidth = cModem->checkSampleRate(result.bandwidth, makeDemod?demodCommand.audioSampleRate:filterCommand.audioSampleRate);
|
||||||
|
result.iqResampleRatio = (double) (result.bandwidth) / (double) result.sampleRate;
|
||||||
|
result.iqResampler = msresamp_crcf_create(result.iqResampleRatio, As);
|
||||||
|
}
|
||||||
|
|
||||||
result.modemKit = cModemKit;
|
result.modemKit = cModemKit;
|
||||||
|
|
||||||
if (filterCommand.bandwidth) {
|
|
||||||
result.bandwidth = filterCommand.bandwidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterCommand.sampleRate) {
|
|
||||||
result.sampleRate = filterCommand.sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.modemType = cModemType;
|
result.modemType = cModemType;
|
||||||
|
result.modemName = cModemName;
|
||||||
|
|
||||||
resultQueue->push(result);
|
resultQueue->push(result);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ public:
|
|||||||
Modem *modem;
|
Modem *modem;
|
||||||
ModemKit *modemKit;
|
ModemKit *modemKit;
|
||||||
std::string modemType;
|
std::string modemType;
|
||||||
|
std::string modemName;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DemodulatorWorkerThreadCommand {
|
class DemodulatorWorkerThreadCommand {
|
||||||
@ -62,6 +63,7 @@ public:
|
|||||||
unsigned int bandwidth;
|
unsigned int bandwidth;
|
||||||
unsigned int audioSampleRate;
|
unsigned int audioSampleRate;
|
||||||
std::string demodType;
|
std::string demodType;
|
||||||
|
ModemSettings settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ThreadQueue<DemodulatorWorkerThreadCommand> DemodulatorThreadWorkerCommandQueue;
|
typedef ThreadQueue<DemodulatorWorkerThreadCommand> DemodulatorThreadWorkerCommandQueue;
|
||||||
@ -92,4 +94,5 @@ protected:
|
|||||||
Modem *cModem;
|
Modem *cModem;
|
||||||
ModemKit *cModemKit;
|
ModemKit *cModemKit;
|
||||||
std::string cModemType;
|
std::string cModemType;
|
||||||
|
std::string cModemName;
|
||||||
};
|
};
|
||||||
|
138
src/forms/DigitalConsole/DigitalConsole.cpp
Normal file
138
src/forms/DigitalConsole/DigitalConsole.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include "DigitalConsole.h"
|
||||||
|
#include "CubicSDR.h"
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
DigitalConsole::DigitalConsole( wxWindow* parent, ModemDigitalOutputConsole *doParent ): DigitalConsoleFrame( parent ), doParent(doParent) {
|
||||||
|
streamWritten.store(false);
|
||||||
|
streamPaused.store(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
DigitalConsole::~DigitalConsole() {
|
||||||
|
doParent->setDialog(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigitalConsole::OnClose( wxCloseEvent& event ) {
|
||||||
|
doParent->setDialog(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigitalConsole::OnCopy( wxCommandEvent& event ) {
|
||||||
|
m_dataView->SelectAll();
|
||||||
|
m_dataView->Copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigitalConsole::OnPause( wxCommandEvent& event ) {
|
||||||
|
if (streamPaused.load()) {
|
||||||
|
m_pauseButton->SetLabel("Stop");
|
||||||
|
streamPaused.store(false);
|
||||||
|
} else {
|
||||||
|
m_pauseButton->SetLabel("Run");
|
||||||
|
streamPaused.store(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoRefresh( wxTimerEvent& event ) {
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigitalConsole::DoRefresh( wxTimerEvent& event ) {
|
||||||
|
if (streamWritten.load()) {
|
||||||
|
stream_busy.lock();
|
||||||
|
m_dataView->AppendText(streamBuf.str());
|
||||||
|
streamBuf.str("");
|
||||||
|
streamWritten.store(false);
|
||||||
|
stream_busy.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigitalConsole::OnClear( wxCommandEvent& event ) {
|
||||||
|
m_dataView->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigitalConsole::write(std::string outp) {
|
||||||
|
if (streamPaused.load()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stream_busy.lock();
|
||||||
|
streamBuf << outp;
|
||||||
|
streamWritten.store(true);
|
||||||
|
stream_busy.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigitalConsole::write(char outc) {
|
||||||
|
if (streamPaused.load()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stream_busy.lock();
|
||||||
|
streamBuf << outc;
|
||||||
|
streamWritten.store(true);
|
||||||
|
stream_busy.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModemDigitalOutputConsole::ModemDigitalOutputConsole(): ModemDigitalOutput(), dialog(nullptr) {
|
||||||
|
streamWritten.store(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemDigitalOutputConsole::~ModemDigitalOutputConsole() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemDigitalOutputConsole::setDialog(DigitalConsole *dialog_in) {
|
||||||
|
dialog = dialog_in;
|
||||||
|
if (dialog && dialogTitle != "") {
|
||||||
|
dialog->SetTitle(dialogTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DigitalConsole *ModemDigitalOutputConsole::getDialog() {
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemDigitalOutputConsole::Show() {
|
||||||
|
if (!dialog) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dialog->IsShown()) {
|
||||||
|
dialog->Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ModemDigitalOutputConsole::Hide() {
|
||||||
|
if (!dialog) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dialog->IsShown()) {
|
||||||
|
dialog->Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemDigitalOutputConsole::Close() {
|
||||||
|
if (!dialog) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dialog->Hide();
|
||||||
|
dialog->Close();
|
||||||
|
dialog = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemDigitalOutputConsole::setTitle(std::string title) {
|
||||||
|
if (dialog) {
|
||||||
|
dialog->SetTitle(title);
|
||||||
|
}
|
||||||
|
dialogTitle = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemDigitalOutputConsole::write(std::string outp) {
|
||||||
|
if (!dialog) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dialog->write(outp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemDigitalOutputConsole::write(char outc) {
|
||||||
|
if (!dialog) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dialog->write(outc);
|
||||||
|
}
|
485
src/forms/DigitalConsole/DigitalConsole.fbp
Normal file
485
src/forms/DigitalConsole/DigitalConsole.fbp
Normal file
@ -0,0 +1,485 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<wxFormBuilder_Project>
|
||||||
|
<FileVersion major="1" minor="13" />
|
||||||
|
<object class="Project" expanded="1">
|
||||||
|
<property name="class_decoration"></property>
|
||||||
|
<property name="code_generation">C++</property>
|
||||||
|
<property name="disconnect_events">1</property>
|
||||||
|
<property name="disconnect_mode">source_name</property>
|
||||||
|
<property name="disconnect_php_events">0</property>
|
||||||
|
<property name="disconnect_python_events">0</property>
|
||||||
|
<property name="embedded_files_path">res</property>
|
||||||
|
<property name="encoding">UTF-8</property>
|
||||||
|
<property name="event_generation">connect</property>
|
||||||
|
<property name="file">DigitalConsoleFrame</property>
|
||||||
|
<property name="first_id">1000</property>
|
||||||
|
<property name="help_provider">none</property>
|
||||||
|
<property name="internationalize">0</property>
|
||||||
|
<property name="name">DigitalConsole</property>
|
||||||
|
<property name="namespace"></property>
|
||||||
|
<property name="path">.</property>
|
||||||
|
<property name="precompiled_header"></property>
|
||||||
|
<property name="relative_path">1</property>
|
||||||
|
<property name="skip_lua_events">1</property>
|
||||||
|
<property name="skip_php_events">1</property>
|
||||||
|
<property name="skip_python_events">1</property>
|
||||||
|
<property name="ui_table">UI</property>
|
||||||
|
<property name="use_enum">0</property>
|
||||||
|
<property name="use_microsoft_bom">0</property>
|
||||||
|
<object class="Frame" expanded="1">
|
||||||
|
<property name="aui_managed">0</property>
|
||||||
|
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="center">wxBOTH</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="event_handler">impl_virtual</property>
|
||||||
|
<property name="extra_style"></property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="name">DigitalConsoleFrame</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="size">441,394</property>
|
||||||
|
<property name="style">wxCAPTION|wxFRAME_FLOAT_ON_PARENT|wxMAXIMIZE|wxMAXIMIZE_BOX|wxMINIMIZE|wxMINIMIZE_BOX|wxRESIZE_BORDER</property>
|
||||||
|
<property name="subclass">; </property>
|
||||||
|
<property name="title">Digital Output</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="window_extra_style">wxWS_EX_PROCESS_UI_UPDATES</property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style">wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL</property>
|
||||||
|
<property name="xrc_skip_sizer">1</property>
|
||||||
|
<event name="OnActivate"></event>
|
||||||
|
<event name="OnActivateApp"></event>
|
||||||
|
<event name="OnAuiFindManager"></event>
|
||||||
|
<event name="OnAuiPaneButton"></event>
|
||||||
|
<event name="OnAuiPaneClose"></event>
|
||||||
|
<event name="OnAuiPaneMaximize"></event>
|
||||||
|
<event name="OnAuiPaneRestore"></event>
|
||||||
|
<event name="OnAuiRender"></event>
|
||||||
|
<event name="OnChar"></event>
|
||||||
|
<event name="OnClose">OnClose</event>
|
||||||
|
<event name="OnEnterWindow"></event>
|
||||||
|
<event name="OnEraseBackground"></event>
|
||||||
|
<event name="OnHibernate"></event>
|
||||||
|
<event name="OnIconize"></event>
|
||||||
|
<event name="OnIdle"></event>
|
||||||
|
<event name="OnKeyDown"></event>
|
||||||
|
<event name="OnKeyUp"></event>
|
||||||
|
<event name="OnKillFocus"></event>
|
||||||
|
<event name="OnLeaveWindow"></event>
|
||||||
|
<event name="OnLeftDClick"></event>
|
||||||
|
<event name="OnLeftDown"></event>
|
||||||
|
<event name="OnLeftUp"></event>
|
||||||
|
<event name="OnMiddleDClick"></event>
|
||||||
|
<event name="OnMiddleDown"></event>
|
||||||
|
<event name="OnMiddleUp"></event>
|
||||||
|
<event name="OnMotion"></event>
|
||||||
|
<event name="OnMouseEvents"></event>
|
||||||
|
<event name="OnMouseWheel"></event>
|
||||||
|
<event name="OnPaint"></event>
|
||||||
|
<event name="OnRightDClick"></event>
|
||||||
|
<event name="OnRightDown"></event>
|
||||||
|
<event name="OnRightUp"></event>
|
||||||
|
<event name="OnSetFocus"></event>
|
||||||
|
<event name="OnSize"></event>
|
||||||
|
<event name="OnUpdateUI"></event>
|
||||||
|
<object class="wxBoxSizer" expanded="1">
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="name">mainSizer</property>
|
||||||
|
<property name="orient">wxVERTICAL</property>
|
||||||
|
<property name="permission">none</property>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxEXPAND</property>
|
||||||
|
<property name="proportion">1</property>
|
||||||
|
<object class="wxBoxSizer" expanded="0">
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="name">dataViewSizer</property>
|
||||||
|
<property name="orient">wxVERTICAL</property>
|
||||||
|
<property name="permission">none</property>
|
||||||
|
<object class="sizeritem" expanded="0">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxEXPAND</property>
|
||||||
|
<property name="proportion">1</property>
|
||||||
|
<object class="wxTextCtrl" expanded="0">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font">,90,90,-1,76,0</property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="maxlength"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_dataView</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style">wxTE_CHARWRAP|wxTE_MULTILINE|wxTE_NOHIDESEL|wxTE_READONLY|wxTE_WORDWRAP</property>
|
||||||
|
<property name="subclass"></property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="validator_data_type"></property>
|
||||||
|
<property name="validator_style">wxFILTER_NONE</property>
|
||||||
|
<property name="validator_type">wxDefaultValidator</property>
|
||||||
|
<property name="validator_variable"></property>
|
||||||
|
<property name="value"></property>
|
||||||
|
<property name="window_extra_style">wxWS_EX_PROCESS_UI_UPDATES</property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style">wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE|wxNO_BORDER|wxSIMPLE_BORDER|wxVSCROLL</property>
|
||||||
|
<event name="OnChar"></event>
|
||||||
|
<event name="OnEnterWindow"></event>
|
||||||
|
<event name="OnEraseBackground"></event>
|
||||||
|
<event name="OnKeyDown"></event>
|
||||||
|
<event name="OnKeyUp"></event>
|
||||||
|
<event name="OnKillFocus"></event>
|
||||||
|
<event name="OnLeaveWindow"></event>
|
||||||
|
<event name="OnLeftDClick"></event>
|
||||||
|
<event name="OnLeftDown"></event>
|
||||||
|
<event name="OnLeftUp"></event>
|
||||||
|
<event name="OnMiddleDClick"></event>
|
||||||
|
<event name="OnMiddleDown"></event>
|
||||||
|
<event name="OnMiddleUp"></event>
|
||||||
|
<event name="OnMotion"></event>
|
||||||
|
<event name="OnMouseEvents"></event>
|
||||||
|
<event name="OnMouseWheel"></event>
|
||||||
|
<event name="OnPaint"></event>
|
||||||
|
<event name="OnRightDClick"></event>
|
||||||
|
<event name="OnRightDown"></event>
|
||||||
|
<event name="OnRightUp"></event>
|
||||||
|
<event name="OnSetFocus"></event>
|
||||||
|
<event name="OnSize"></event>
|
||||||
|
<event name="OnText"></event>
|
||||||
|
<event name="OnTextEnter"></event>
|
||||||
|
<event name="OnTextMaxLen"></event>
|
||||||
|
<event name="OnTextURL"></event>
|
||||||
|
<event name="OnUpdateUI"></event>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxALL|wxEXPAND</property>
|
||||||
|
<property name="proportion">0</property>
|
||||||
|
<object class="wxBoxSizer" expanded="0">
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="name">buttonSizer</property>
|
||||||
|
<property name="orient">wxHORIZONTAL</property>
|
||||||
|
<property name="permission">none</property>
|
||||||
|
<object class="sizeritem" expanded="0">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxEXPAND</property>
|
||||||
|
<property name="proportion">1</property>
|
||||||
|
<object class="wxButton" expanded="0">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default">0</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="label">Clear</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_clearButton</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style"></property>
|
||||||
|
<property name="subclass"></property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="validator_data_type"></property>
|
||||||
|
<property name="validator_style">wxFILTER_NONE</property>
|
||||||
|
<property name="validator_type">wxDefaultValidator</property>
|
||||||
|
<property name="validator_variable"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<event name="OnButtonClick">OnClear</event>
|
||||||
|
<event name="OnChar"></event>
|
||||||
|
<event name="OnEnterWindow"></event>
|
||||||
|
<event name="OnEraseBackground"></event>
|
||||||
|
<event name="OnKeyDown"></event>
|
||||||
|
<event name="OnKeyUp"></event>
|
||||||
|
<event name="OnKillFocus"></event>
|
||||||
|
<event name="OnLeaveWindow"></event>
|
||||||
|
<event name="OnLeftDClick"></event>
|
||||||
|
<event name="OnLeftDown"></event>
|
||||||
|
<event name="OnLeftUp"></event>
|
||||||
|
<event name="OnMiddleDClick"></event>
|
||||||
|
<event name="OnMiddleDown"></event>
|
||||||
|
<event name="OnMiddleUp"></event>
|
||||||
|
<event name="OnMotion"></event>
|
||||||
|
<event name="OnMouseEvents"></event>
|
||||||
|
<event name="OnMouseWheel"></event>
|
||||||
|
<event name="OnPaint"></event>
|
||||||
|
<event name="OnRightDClick"></event>
|
||||||
|
<event name="OnRightDown"></event>
|
||||||
|
<event name="OnRightUp"></event>
|
||||||
|
<event name="OnSetFocus"></event>
|
||||||
|
<event name="OnSize"></event>
|
||||||
|
<event name="OnUpdateUI"></event>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="0">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxEXPAND</property>
|
||||||
|
<property name="proportion">1</property>
|
||||||
|
<object class="wxButton" expanded="0">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default">0</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="label">Copy</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_copyButton</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style"></property>
|
||||||
|
<property name="subclass"></property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="validator_data_type"></property>
|
||||||
|
<property name="validator_style">wxFILTER_NONE</property>
|
||||||
|
<property name="validator_type">wxDefaultValidator</property>
|
||||||
|
<property name="validator_variable"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<event name="OnButtonClick">OnCopy</event>
|
||||||
|
<event name="OnChar"></event>
|
||||||
|
<event name="OnEnterWindow"></event>
|
||||||
|
<event name="OnEraseBackground"></event>
|
||||||
|
<event name="OnKeyDown"></event>
|
||||||
|
<event name="OnKeyUp"></event>
|
||||||
|
<event name="OnKillFocus"></event>
|
||||||
|
<event name="OnLeaveWindow"></event>
|
||||||
|
<event name="OnLeftDClick"></event>
|
||||||
|
<event name="OnLeftDown"></event>
|
||||||
|
<event name="OnLeftUp"></event>
|
||||||
|
<event name="OnMiddleDClick"></event>
|
||||||
|
<event name="OnMiddleDown"></event>
|
||||||
|
<event name="OnMiddleUp"></event>
|
||||||
|
<event name="OnMotion"></event>
|
||||||
|
<event name="OnMouseEvents"></event>
|
||||||
|
<event name="OnMouseWheel"></event>
|
||||||
|
<event name="OnPaint"></event>
|
||||||
|
<event name="OnRightDClick"></event>
|
||||||
|
<event name="OnRightDown"></event>
|
||||||
|
<event name="OnRightUp"></event>
|
||||||
|
<event name="OnSetFocus"></event>
|
||||||
|
<event name="OnSize"></event>
|
||||||
|
<event name="OnUpdateUI"></event>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="0">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxEXPAND</property>
|
||||||
|
<property name="proportion">1</property>
|
||||||
|
<object class="wxButton" expanded="0">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default">0</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="label">Stop</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_pauseButton</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style"></property>
|
||||||
|
<property name="subclass"></property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="validator_data_type"></property>
|
||||||
|
<property name="validator_style">wxFILTER_NONE</property>
|
||||||
|
<property name="validator_type">wxDefaultValidator</property>
|
||||||
|
<property name="validator_variable"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<event name="OnButtonClick">OnPause</event>
|
||||||
|
<event name="OnChar"></event>
|
||||||
|
<event name="OnEnterWindow"></event>
|
||||||
|
<event name="OnEraseBackground"></event>
|
||||||
|
<event name="OnKeyDown"></event>
|
||||||
|
<event name="OnKeyUp"></event>
|
||||||
|
<event name="OnKillFocus"></event>
|
||||||
|
<event name="OnLeaveWindow"></event>
|
||||||
|
<event name="OnLeftDClick"></event>
|
||||||
|
<event name="OnLeftDown"></event>
|
||||||
|
<event name="OnLeftUp"></event>
|
||||||
|
<event name="OnMiddleDClick"></event>
|
||||||
|
<event name="OnMiddleDown"></event>
|
||||||
|
<event name="OnMiddleUp"></event>
|
||||||
|
<event name="OnMotion"></event>
|
||||||
|
<event name="OnMouseEvents"></event>
|
||||||
|
<event name="OnMouseWheel"></event>
|
||||||
|
<event name="OnPaint"></event>
|
||||||
|
<event name="OnRightDClick"></event>
|
||||||
|
<event name="OnRightDown"></event>
|
||||||
|
<event name="OnRightUp"></event>
|
||||||
|
<event name="OnSetFocus"></event>
|
||||||
|
<event name="OnSize"></event>
|
||||||
|
<event name="OnUpdateUI"></event>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="wxTimer" expanded="1">
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="name">m_refreshTimer</property>
|
||||||
|
<property name="oneshot">0</property>
|
||||||
|
<property name="period">250</property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<event name="OnTimer">DoRefresh</event>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</wxFormBuilder_Project>
|
61
src/forms/DigitalConsole/DigitalConsole.h
Normal file
61
src/forms/DigitalConsole/DigitalConsole.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "DigitalConsoleFrame.h"
|
||||||
|
#include "ModemDigital.h"
|
||||||
|
|
||||||
|
class ModemDigitalOutputConsole;
|
||||||
|
class DigitalConsole: public DigitalConsoleFrame {
|
||||||
|
public:
|
||||||
|
DigitalConsole( wxWindow* parent, ModemDigitalOutputConsole *doParent );
|
||||||
|
~DigitalConsole();
|
||||||
|
|
||||||
|
|
||||||
|
void write(std::string outp);
|
||||||
|
void write(char outc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DoRefresh( wxTimerEvent& event );
|
||||||
|
void OnClose( wxCloseEvent& event );
|
||||||
|
void OnClear( wxCommandEvent& event );
|
||||||
|
|
||||||
|
void OnCopy( wxCommandEvent& event );
|
||||||
|
void OnPause( wxCommandEvent& event );
|
||||||
|
|
||||||
|
std::stringstream streamBuf;
|
||||||
|
std::mutex stream_busy;
|
||||||
|
std::atomic<bool> streamWritten;
|
||||||
|
std::atomic<bool> streamPaused;
|
||||||
|
ModemDigitalOutputConsole *doParent;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ModemDigitalOutputConsole: public ModemDigitalOutput {
|
||||||
|
public:
|
||||||
|
ModemDigitalOutputConsole();
|
||||||
|
~ModemDigitalOutputConsole();
|
||||||
|
|
||||||
|
void setDialog(DigitalConsole *dialog_in);
|
||||||
|
DigitalConsole *getDialog();
|
||||||
|
|
||||||
|
void setTitle(std::string title);
|
||||||
|
|
||||||
|
void write(std::string outp);
|
||||||
|
void write(char outc);
|
||||||
|
|
||||||
|
void Show();
|
||||||
|
void Hide();
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DigitalConsole *dialog;
|
||||||
|
std::stringstream streamBuf;
|
||||||
|
std::mutex stream_busy;
|
||||||
|
std::atomic<bool> streamWritten;
|
||||||
|
std::string dialogTitle;
|
||||||
|
};
|
||||||
|
|
73
src/forms/DigitalConsole/DigitalConsoleFrame.cpp
Normal file
73
src/forms/DigitalConsole/DigitalConsoleFrame.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// C++ code generated with wxFormBuilder (version Aug 23 2015)
|
||||||
|
// http://www.wxformbuilder.org/
|
||||||
|
//
|
||||||
|
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "DigitalConsoleFrame.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
DigitalConsoleFrame::DigitalConsoleFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
|
||||||
|
{
|
||||||
|
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
|
||||||
|
this->SetExtraStyle( wxWS_EX_PROCESS_UI_UPDATES );
|
||||||
|
|
||||||
|
wxBoxSizer* mainSizer;
|
||||||
|
mainSizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
wxBoxSizer* dataViewSizer;
|
||||||
|
dataViewSizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
m_dataView = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_CHARWRAP|wxTE_MULTILINE|wxTE_NOHIDESEL|wxTE_READONLY|wxTE_WORDWRAP|wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE|wxNO_BORDER|wxSIMPLE_BORDER|wxVSCROLL );
|
||||||
|
m_dataView->SetExtraStyle( wxWS_EX_PROCESS_UI_UPDATES );
|
||||||
|
m_dataView->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 76, 90, 90, false, wxEmptyString ) );
|
||||||
|
|
||||||
|
dataViewSizer->Add( m_dataView, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
mainSizer->Add( dataViewSizer, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
wxBoxSizer* buttonSizer;
|
||||||
|
buttonSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
m_clearButton = new wxButton( this, wxID_ANY, wxT("Clear"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
buttonSizer->Add( m_clearButton, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
m_copyButton = new wxButton( this, wxID_ANY, wxT("Copy"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
buttonSizer->Add( m_copyButton, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
m_pauseButton = new wxButton( this, wxID_ANY, wxT("Stop"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
buttonSizer->Add( m_pauseButton, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
mainSizer->Add( buttonSizer, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
this->SetSizer( mainSizer );
|
||||||
|
this->Layout();
|
||||||
|
m_refreshTimer.SetOwner( this, wxID_ANY );
|
||||||
|
m_refreshTimer.Start( 250 );
|
||||||
|
|
||||||
|
|
||||||
|
this->Centre( wxBOTH );
|
||||||
|
|
||||||
|
// Connect Events
|
||||||
|
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DigitalConsoleFrame::OnClose ) );
|
||||||
|
m_clearButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnClear ), NULL, this );
|
||||||
|
m_copyButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnCopy ), NULL, this );
|
||||||
|
m_pauseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnPause ), NULL, this );
|
||||||
|
this->Connect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( DigitalConsoleFrame::DoRefresh ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
DigitalConsoleFrame::~DigitalConsoleFrame()
|
||||||
|
{
|
||||||
|
// Disconnect Events
|
||||||
|
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DigitalConsoleFrame::OnClose ) );
|
||||||
|
m_clearButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnClear ), NULL, this );
|
||||||
|
m_copyButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnCopy ), NULL, this );
|
||||||
|
m_pauseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DigitalConsoleFrame::OnPause ), NULL, this );
|
||||||
|
this->Disconnect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( DigitalConsoleFrame::DoRefresh ) );
|
||||||
|
|
||||||
|
}
|
57
src/forms/DigitalConsole/DigitalConsoleFrame.h
Normal file
57
src/forms/DigitalConsole/DigitalConsoleFrame.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// C++ code generated with wxFormBuilder (version Aug 23 2015)
|
||||||
|
// http://www.wxformbuilder.org/
|
||||||
|
//
|
||||||
|
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef __DIGITALCONSOLEFRAME_H__
|
||||||
|
#define __DIGITALCONSOLEFRAME_H__
|
||||||
|
|
||||||
|
#include <wx/artprov.h>
|
||||||
|
#include <wx/xrc/xmlres.h>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <wx/textctrl.h>
|
||||||
|
#include <wx/gdicmn.h>
|
||||||
|
#include <wx/font.h>
|
||||||
|
#include <wx/colour.h>
|
||||||
|
#include <wx/settings.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/button.h>
|
||||||
|
#include <wx/timer.h>
|
||||||
|
#include <wx/frame.h>
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Class DigitalConsoleFrame
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
class DigitalConsoleFrame : public wxFrame
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxTextCtrl* m_dataView;
|
||||||
|
wxButton* m_clearButton;
|
||||||
|
wxButton* m_copyButton;
|
||||||
|
wxButton* m_pauseButton;
|
||||||
|
wxTimer m_refreshTimer;
|
||||||
|
|
||||||
|
// Virtual event handlers, overide them in your derived class
|
||||||
|
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
|
||||||
|
virtual void OnClear( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void OnCopy( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void OnPause( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void DoRefresh( wxTimerEvent& event ) { event.Skip(); }
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DigitalConsoleFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Digital Output"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 441,394 ), long style = wxCAPTION|wxFRAME_FLOAT_ON_PARENT|wxMAXIMIZE|wxMAXIMIZE_BOX|wxMINIMIZE|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL );
|
||||||
|
|
||||||
|
~DigitalConsoleFrame();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__DIGITALCONSOLEFRAME_H__
|
@ -3,7 +3,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "SDRDevices.h"
|
|
||||||
#include "SDRDevicesForm.h"
|
#include "SDRDevicesForm.h"
|
||||||
#include "SoapySDRThread.h"
|
#include "SoapySDRThread.h"
|
||||||
#include "SDREnumerator.h"
|
#include "SDREnumerator.h"
|
||||||
|
@ -1,21 +1,33 @@
|
|||||||
#include "Modem.h"
|
#include "Modem.h"
|
||||||
|
#include "CubicSDR.h"
|
||||||
|
|
||||||
|
|
||||||
ModemFactoryList Modem::modemFactories;
|
ModemFactoryList Modem::modemFactories;
|
||||||
|
|
||||||
void Modem::addModemFactory(Modem *factorySingle) {
|
//! Create an empty range (0.0, 0.0)
|
||||||
modemFactories[factorySingle->getName()] = factorySingle;
|
ModemRange::ModemRange(void) {
|
||||||
|
_min = 0;
|
||||||
|
_max = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModemFactoryList Modem::getFactories() {
|
//! Create a min/max range
|
||||||
return modemFactories;
|
ModemRange::ModemRange(const double minimum, const double maximum) {
|
||||||
|
_min = minimum;
|
||||||
|
_max = maximum;
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem *Modem::makeModem(std::string modemType) {
|
//! Get the range minimum
|
||||||
if (modemFactories.find(modemType) != modemFactories.end()) {
|
double ModemRange::minimum(void) const {
|
||||||
return modemFactories[modemType]->factory();
|
return _min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Get the range maximum
|
||||||
|
double ModemRange::maximum(void) const {
|
||||||
|
return _max;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemArgInfo::ModemArgInfo(void) {
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem::Modem() {
|
Modem::Modem() {
|
||||||
@ -25,3 +37,72 @@ Modem::Modem() {
|
|||||||
Modem::~Modem() {
|
Modem::~Modem() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Modem::addModemFactory(Modem *factorySingle) {
|
||||||
|
modemFactories[factorySingle->getName()] = factorySingle;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemFactoryList Modem::getFactories() {
|
||||||
|
return modemFactories;
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *Modem::makeModem(std::string modemName) {
|
||||||
|
if (modemFactories.find(modemName) != modemFactories.end()) {
|
||||||
|
return modemFactories[modemName]->factory();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Modem::getModemDefaultSampleRate(std::string modemName) {
|
||||||
|
if (modemFactories.find(modemName) != modemFactories.end()) {
|
||||||
|
return modemFactories[modemName]->getDefaultSampleRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList Modem::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Modem::getDefaultSampleRate() {
|
||||||
|
return 200000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modem::writeSetting(std::string setting, std::string value) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Modem::readSetting(std::string setting) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modem::writeSettings(ModemSettings settings) {
|
||||||
|
for (ModemSettings::const_iterator i = settings.begin(); i != settings.end(); i++) {
|
||||||
|
writeSetting(i->first, i->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemSettings Modem::readSettings() {
|
||||||
|
ModemArgInfoList args = getSettings();
|
||||||
|
ModemSettings rs;
|
||||||
|
for (ModemArgInfoList::const_iterator i = args.begin(); i != args.end(); i++) {
|
||||||
|
rs[i->key] = readSetting(i->key);
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Modem::shouldRebuildKit() {
|
||||||
|
return refreshKit.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modem::rebuildKit() {
|
||||||
|
refreshKit.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modem::clearRebuildKit() {
|
||||||
|
refreshKit.store(false);
|
||||||
|
}
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#include "IOThread.h"
|
#include "IOThread.h"
|
||||||
#include "AudioThread.h"
|
#include "AudioThread.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#define MIN_BANDWIDTH 500
|
||||||
|
|
||||||
class ModemKit {
|
class ModemKit {
|
||||||
public:
|
public:
|
||||||
@ -29,24 +32,118 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Copy of SoapySDR::Range, original comments
|
||||||
|
class ModemRange
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Create an empty range (0.0, 0.0)
|
||||||
|
ModemRange(void);
|
||||||
|
|
||||||
|
//! Create a min/max range
|
||||||
|
ModemRange(const double minimum, const double maximum);
|
||||||
|
|
||||||
|
//! Get the range minimum
|
||||||
|
double minimum(void) const;
|
||||||
|
|
||||||
|
//! Get the range maximum
|
||||||
|
double maximum(void) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double _min, _max;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modified version of SoapySDR::ArgInfo, original comments
|
||||||
|
class ModemArgInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Default constructor
|
||||||
|
ModemArgInfo(void);
|
||||||
|
|
||||||
|
//! The key used to identify the argument (required)
|
||||||
|
std::string key;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* The default value of the argument when not specified (required)
|
||||||
|
* Numbers should use standard floating point and integer formats.
|
||||||
|
* Boolean values should be represented as "true" and "false".
|
||||||
|
*/
|
||||||
|
std::string value;
|
||||||
|
|
||||||
|
//! The displayable name of the argument (optional, use key if empty)
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
//! A brief description about the argument (optional)
|
||||||
|
std::string description;
|
||||||
|
|
||||||
|
//! The units of the argument: dB, Hz, etc (optional)
|
||||||
|
std::string units;
|
||||||
|
|
||||||
|
//! The data type of the argument (required)
|
||||||
|
enum Type { BOOL, INT, FLOAT, STRING, PATH_DIR, PATH_FILE, COLOR } type;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* The range of possible numeric values (optional)
|
||||||
|
* When specified, the argument should be restricted to this range.
|
||||||
|
* The range is only applicable to numeric argument types.
|
||||||
|
*/
|
||||||
|
ModemRange range;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A discrete list of possible values (optional)
|
||||||
|
* When specified, the argument should be restricted to this options set.
|
||||||
|
*/
|
||||||
|
std::vector<std::string> options;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A discrete list of displayable names for the enumerated options (optional)
|
||||||
|
* When not specified, the option value itself can be used as a display name.
|
||||||
|
*/
|
||||||
|
std::vector<std::string> optionNames;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<ModemArgInfo> ModemArgInfoList;
|
||||||
|
|
||||||
class Modem;
|
class Modem;
|
||||||
typedef std::map<std::string,Modem *> ModemFactoryList;
|
typedef std::map<std::string,Modem *> ModemFactoryList;
|
||||||
|
|
||||||
|
typedef std::map<std::string, std::string> ModemSettings;
|
||||||
|
|
||||||
class Modem {
|
class Modem {
|
||||||
public:
|
public:
|
||||||
static void addModemFactory(Modem *factorySingle);
|
static void addModemFactory(Modem *factorySingle);
|
||||||
static ModemFactoryList getFactories();
|
static ModemFactoryList getFactories();
|
||||||
static Modem *makeModem(std::string modemType);
|
|
||||||
|
static Modem *makeModem(std::string modemName);
|
||||||
|
static int getModemDefaultSampleRate(std::string modemName);
|
||||||
|
|
||||||
virtual std::string getType() = 0;
|
virtual std::string getType() = 0;
|
||||||
virtual std::string getName() = 0;
|
virtual std::string getName() = 0;
|
||||||
|
|
||||||
virtual Modem *factory() = 0;
|
virtual Modem *factory() = 0;
|
||||||
|
|
||||||
Modem();
|
Modem();
|
||||||
virtual ~Modem();
|
virtual ~Modem();
|
||||||
|
|
||||||
|
virtual ModemArgInfoList getSettings();
|
||||||
|
virtual int getDefaultSampleRate();
|
||||||
|
virtual void writeSetting(std::string setting, std::string value);
|
||||||
|
virtual void writeSettings(ModemSettings settings);
|
||||||
|
virtual std::string readSetting(std::string setting);
|
||||||
|
virtual ModemSettings readSettings();
|
||||||
|
|
||||||
|
virtual int checkSampleRate(long long sampleRate, int audioSampleRate) = 0;
|
||||||
|
|
||||||
virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate) = 0;
|
virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate) = 0;
|
||||||
virtual void disposeKit(ModemKit *kit) = 0;
|
virtual void disposeKit(ModemKit *kit) = 0;
|
||||||
|
|
||||||
virtual void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) = 0;
|
virtual void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) = 0;
|
||||||
|
|
||||||
|
bool shouldRebuildKit();
|
||||||
|
void rebuildKit();
|
||||||
|
void clearRebuildKit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ModemFactoryList modemFactories;
|
static ModemFactoryList modemFactories;
|
||||||
|
std::atomic_bool refreshKit;
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,13 @@ std::string ModemAnalog::getType() {
|
|||||||
return "analog";
|
return "analog";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModemAnalog::checkSampleRate(long long sampleRate, int audioSampleRate) {
|
||||||
|
if (sampleRate < MIN_BANDWIDTH) {
|
||||||
|
return MIN_BANDWIDTH;
|
||||||
|
}
|
||||||
|
return sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
ModemKit *ModemAnalog::buildKit(long long sampleRate, int audioSampleRate) {
|
ModemKit *ModemAnalog::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
ModemKitAnalog *akit = new ModemKitAnalog;
|
ModemKitAnalog *akit = new ModemKitAnalog;
|
||||||
|
|
||||||
|
@ -16,12 +16,13 @@ class ModemAnalog : public Modem {
|
|||||||
public:
|
public:
|
||||||
ModemAnalog();
|
ModemAnalog();
|
||||||
std::string getType();
|
std::string getType();
|
||||||
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
virtual int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
void disposeKit(ModemKit *kit);
|
virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
void initOutputBuffers(ModemKitAnalog *akit, ModemIQData *input);
|
virtual void disposeKit(ModemKit *kit);
|
||||||
void buildAudioOutput(ModemKitAnalog *akit, AudioThreadInput *audioOut, bool autoGain);
|
virtual void initOutputBuffers(ModemKitAnalog *akit, ModemIQData *input);
|
||||||
std::vector<float> *getDemodOutputData();
|
virtual void buildAudioOutput(ModemKitAnalog *akit, AudioThreadInput *audioOut, bool autoGain);
|
||||||
std::vector<float> *getResampledOutputData();
|
virtual std::vector<float> *getDemodOutputData();
|
||||||
|
virtual std::vector<float> *getResampledOutputData();
|
||||||
protected:
|
protected:
|
||||||
int bufSize;
|
int bufSize;
|
||||||
std::vector<float> demodOutputData;
|
std::vector<float> demodOutputData;
|
||||||
|
@ -1,13 +1,31 @@
|
|||||||
#include "ModemDigital.h"
|
#include "ModemDigital.h"
|
||||||
|
|
||||||
ModemDigital::ModemDigital() {
|
|
||||||
|
|
||||||
|
ModemDigitalOutput::ModemDigitalOutput() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemDigital::ModemDigital() {
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
digitalOut = nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemDigitalOutput::~ModemDigitalOutput() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ModemDigital::getType() {
|
std::string ModemDigital::getType() {
|
||||||
return "digital";
|
return "digital";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModemDigital::checkSampleRate(long long sampleRate, int audioSampleRate) {
|
||||||
|
if (sampleRate < MIN_BANDWIDTH) {
|
||||||
|
return MIN_BANDWIDTH;
|
||||||
|
}
|
||||||
|
return sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
ModemKit *ModemDigital::buildKit(long long sampleRate, int audioSampleRate) {
|
ModemKit *ModemDigital::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
ModemKitDigital *dkit = new ModemKitDigital;
|
ModemKitDigital *dkit = new ModemKitDigital;
|
||||||
|
|
||||||
@ -31,24 +49,10 @@ int ModemDigital::getDemodulatorLock() {
|
|||||||
return currentDemodLock.load();
|
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) {
|
void ModemDigital::updateDemodulatorLock(modem mod, float sensitivity) {
|
||||||
setDemodulatorLock(modem_get_demodulator_evm(mod) <= 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) {
|
void ModemDigital::digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input) {
|
||||||
int bufSize = input->data.size();
|
int bufSize = input->data.size();
|
||||||
|
|
||||||
@ -58,14 +62,21 @@ void ModemDigital::digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *in
|
|||||||
}
|
}
|
||||||
demodOutputDataDigital.resize(bufSize);
|
demodOutputDataDigital.resize(bufSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demodulatorCons.load() != currentDemodCons.load()) {
|
|
||||||
updateDemodulatorCons(demodulatorCons.load());
|
|
||||||
currentDemodLock.store(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemDigital::digitalFinish(ModemKitDigital *kit, modem mod) {
|
void ModemDigital::digitalFinish(ModemKitDigital *kit, modem mod) {
|
||||||
demodOutputDataDigital.empty();
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
if (digitalOut && outStream.str().length()) {
|
||||||
|
digitalOut->write(outStream.str());
|
||||||
|
outStream.str("");
|
||||||
|
} else {
|
||||||
|
outStream.str("");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
void ModemDigital::setOutput(ModemDigitalOutput *modemDigitalOutput) {
|
||||||
|
digitalOut = modemDigitalOutput;
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,5 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Modem.h"
|
#include "Modem.h"
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class ModemKitDigital : public ModemKit {
|
class ModemKitDigital : public ModemKit {
|
||||||
public:
|
public:
|
||||||
@ -8,32 +13,49 @@ public:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ModemDigitalOutput {
|
||||||
|
public:
|
||||||
|
ModemDigitalOutput();
|
||||||
|
virtual ~ModemDigitalOutput();
|
||||||
|
|
||||||
|
virtual void write(std::string outp) = 0;
|
||||||
|
virtual void write(char outc) = 0;
|
||||||
|
|
||||||
|
virtual void Show() = 0;
|
||||||
|
virtual void Hide() = 0;
|
||||||
|
virtual void Close() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
class ModemDigital : public Modem {
|
class ModemDigital : public Modem {
|
||||||
public:
|
public:
|
||||||
ModemDigital();
|
ModemDigital();
|
||||||
|
|
||||||
std::string getType();
|
std::string getType();
|
||||||
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
|
||||||
void disposeKit(ModemKit *kit);
|
virtual int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
void digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input);
|
|
||||||
void digitalFinish(ModemKitDigital *kit, modem mod);
|
virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
|
virtual void disposeKit(ModemKit *kit);
|
||||||
|
|
||||||
|
virtual void digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input);
|
||||||
|
virtual void digitalFinish(ModemKitDigital *kit, modem mod);
|
||||||
|
|
||||||
virtual void setDemodulatorLock(bool demod_lock_in);
|
virtual void setDemodulatorLock(bool demod_lock_in);
|
||||||
virtual int getDemodulatorLock();
|
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);
|
virtual void updateDemodulatorLock(modem mod, float sensitivity);
|
||||||
|
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
void setOutput(ModemDigitalOutput *digitalOutput);
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<unsigned int> demodOutputDataDigital;
|
std::vector<unsigned int> demodOutputDataDigital;
|
||||||
std::atomic_int demodulatorCons;
|
|
||||||
std::atomic_bool currentDemodLock;
|
std::atomic_bool currentDemodLock;
|
||||||
std::atomic_int currentDemodCons;
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
ModemDigitalOutput *digitalOut;
|
||||||
// std::vector<unsigned int> demodOutputDataDigitalTest;
|
std::stringstream outStream;
|
||||||
// std::vector<unsigned char> demodOutputSoftbits;
|
#endif
|
||||||
// std::vector<unsigned char> demodOutputSoftbitsTest;
|
|
||||||
};
|
};
|
@ -1,9 +1,13 @@
|
|||||||
#include "ModemAM.h"
|
#include "ModemAM.h"
|
||||||
|
|
||||||
ModemAM::ModemAM() {
|
ModemAM::ModemAM() : ModemAnalog() {
|
||||||
demodAM = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
|
demodAM = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemAM::~ModemAM() {
|
||||||
|
ampmodem_destroy(demodAM);
|
||||||
|
}
|
||||||
|
|
||||||
Modem *ModemAM::factory() {
|
Modem *ModemAM::factory() {
|
||||||
return new ModemAM;
|
return new ModemAM;
|
||||||
}
|
}
|
||||||
@ -12,6 +16,10 @@ std::string ModemAM::getName() {
|
|||||||
return "AM";
|
return "AM";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModemAM::getDefaultSampleRate() {
|
||||||
|
return 6000;
|
||||||
|
}
|
||||||
|
|
||||||
void ModemAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
ModemKitAnalog *amkit = (ModemKitAnalog *)kit;
|
ModemKitAnalog *amkit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
@ -5,8 +5,14 @@
|
|||||||
class ModemAM : public ModemAnalog {
|
class ModemAM : public ModemAnalog {
|
||||||
public:
|
public:
|
||||||
ModemAM();
|
ModemAM();
|
||||||
|
~ModemAM();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
#include "ModemDSB.h"
|
#include "ModemDSB.h"
|
||||||
|
|
||||||
ModemDSB::ModemDSB() {
|
ModemDSB::ModemDSB() : ModemAnalog() {
|
||||||
demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1);
|
demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemDSB::~ModemDSB() {
|
||||||
|
ampmodem_destroy(demodAM_DSB);
|
||||||
|
}
|
||||||
|
|
||||||
Modem *ModemDSB::factory() {
|
Modem *ModemDSB::factory() {
|
||||||
return new ModemDSB;
|
return new ModemDSB;
|
||||||
}
|
}
|
||||||
@ -12,6 +16,10 @@ std::string ModemDSB::getName() {
|
|||||||
return "DSB";
|
return "DSB";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModemDSB::getDefaultSampleRate() {
|
||||||
|
return 5400;
|
||||||
|
}
|
||||||
|
|
||||||
void ModemDSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemDSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
ModemKitAnalog *amkit = (ModemKitAnalog *)kit;
|
ModemKitAnalog *amkit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
@ -5,8 +5,14 @@
|
|||||||
class ModemDSB : public ModemAnalog {
|
class ModemDSB : public ModemAnalog {
|
||||||
public:
|
public:
|
||||||
ModemDSB();
|
ModemDSB();
|
||||||
|
~ModemDSB();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
#include "ModemFM.h"
|
#include "ModemFM.h"
|
||||||
|
|
||||||
ModemFM::ModemFM() {
|
ModemFM::ModemFM() : ModemAnalog() {
|
||||||
demodFM = freqdem_create(0.5);
|
demodFM = freqdem_create(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemFM::~ModemFM() {
|
||||||
|
freqdem_destroy(demodFM);
|
||||||
|
}
|
||||||
|
|
||||||
Modem *ModemFM::factory() {
|
Modem *ModemFM::factory() {
|
||||||
return new ModemFM;
|
return new ModemFM;
|
||||||
}
|
}
|
||||||
@ -12,6 +16,10 @@ std::string ModemFM::getName() {
|
|||||||
return "FM";
|
return "FM";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModemFM::getDefaultSampleRate() {
|
||||||
|
return 200000;
|
||||||
|
}
|
||||||
|
|
||||||
void ModemFM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemFM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
ModemKitAnalog *fmkit = (ModemKitAnalog *)kit;
|
ModemKitAnalog *fmkit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
@ -5,11 +5,16 @@
|
|||||||
class ModemFM : public ModemAnalog {
|
class ModemFM : public ModemAnalog {
|
||||||
public:
|
public:
|
||||||
ModemFM();
|
ModemFM();
|
||||||
|
~ModemFM();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
freqdem demodFM;
|
freqdem demodFM;
|
||||||
};
|
};
|
@ -30,11 +30,27 @@ Modem *ModemFMStereo::factory() {
|
|||||||
return new ModemFMStereo;
|
return new ModemFMStereo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModemFMStereo::checkSampleRate(long long sampleRate, int audioSampleRate) {
|
||||||
|
if (sampleRate < 100000) {
|
||||||
|
return 100000;
|
||||||
|
} else if (sampleRate < 1500) {
|
||||||
|
return 1500;
|
||||||
|
} else {
|
||||||
|
return sampleRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModemFMStereo::getDefaultSampleRate() {
|
||||||
|
return 200000;
|
||||||
|
}
|
||||||
|
|
||||||
ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) {
|
ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
ModemKitFMStereo *kit = new ModemKitFMStereo;
|
ModemKitFMStereo *kit = new ModemKitFMStereo;
|
||||||
|
|
||||||
kit->audioResampleRatio = double(audioSampleRate) / double(sampleRate);
|
kit->audioResampleRatio = double(audioSampleRate) / double(sampleRate);
|
||||||
|
kit->sampleRate = sampleRate;
|
||||||
|
kit->audioSampleRate = audioSampleRate;
|
||||||
|
|
||||||
float As = 60.0f; // stop-band attenuation [dB]
|
float As = 60.0f; // stop-band attenuation [dB]
|
||||||
|
|
||||||
kit->audioResampler = msresamp_rrrf_create(kit->audioResampleRatio, As);
|
kit->audioResampler = msresamp_rrrf_create(kit->audioResampleRatio, As);
|
||||||
|
@ -20,11 +20,18 @@ class ModemFMStereo : public Modem {
|
|||||||
public:
|
public:
|
||||||
ModemFMStereo();
|
ModemFMStereo();
|
||||||
~ModemFMStereo();
|
~ModemFMStereo();
|
||||||
|
|
||||||
std::string getType();
|
std::string getType();
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
void disposeKit(ModemKit *kit);
|
void disposeKit(ModemKit *kit);
|
||||||
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -4,15 +4,6 @@ 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() {
|
std::string ModemIQ::getType() {
|
||||||
return "analog";
|
return "analog";
|
||||||
}
|
}
|
||||||
@ -21,10 +12,29 @@ std::string ModemIQ::getName() {
|
|||||||
return "I/Q";
|
return "I/Q";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Modem *ModemIQ::factory() {
|
||||||
|
return new ModemIQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemKit *ModemIQ::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
|
ModemKit *kit = new ModemKit;
|
||||||
|
kit->sampleRate = sampleRate;
|
||||||
|
kit->audioSampleRate = audioSampleRate;
|
||||||
|
return kit;
|
||||||
|
}
|
||||||
|
|
||||||
void ModemIQ::disposeKit(ModemKit *kit) {
|
void ModemIQ::disposeKit(ModemKit *kit) {
|
||||||
delete kit;
|
delete kit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModemIQ::checkSampleRate(long long sampleRate, int audioSampleRate) {
|
||||||
|
return audioSampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModemIQ::getDefaultSampleRate() {
|
||||||
|
return 48000;
|
||||||
|
}
|
||||||
|
|
||||||
void ModemIQ::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemIQ::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
int bufSize = input->data.size();
|
int bufSize = input->data.size();
|
||||||
|
|
||||||
|
@ -4,11 +4,19 @@
|
|||||||
class ModemIQ : public Modem {
|
class ModemIQ : public Modem {
|
||||||
public:
|
public:
|
||||||
ModemIQ();
|
ModemIQ();
|
||||||
|
|
||||||
std::string getType();
|
std::string getType();
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
|
|
||||||
void disposeKit(ModemKit *kit);
|
void disposeKit(ModemKit *kit);
|
||||||
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemLSB.h"
|
#include "ModemLSB.h"
|
||||||
|
|
||||||
ModemLSB::ModemLSB() {
|
ModemLSB::ModemLSB() : ModemAnalog() {
|
||||||
// half band filter used for side-band elimination
|
// half band filter used for side-band elimination
|
||||||
ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
||||||
demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1);
|
demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1);
|
||||||
@ -19,6 +19,20 @@ ModemLSB::~ModemLSB() {
|
|||||||
ampmodem_destroy(demodAM_LSB);
|
ampmodem_destroy(demodAM_LSB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModemLSB::checkSampleRate(long long sampleRate, int audioSampleRate) {
|
||||||
|
if (sampleRate < MIN_BANDWIDTH) {
|
||||||
|
return MIN_BANDWIDTH;
|
||||||
|
}
|
||||||
|
if (sampleRate % 2 == 0) {
|
||||||
|
return sampleRate;
|
||||||
|
}
|
||||||
|
return sampleRate+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModemLSB::getDefaultSampleRate() {
|
||||||
|
return 5400;
|
||||||
|
}
|
||||||
|
|
||||||
void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
|
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Modem.h"
|
|
||||||
#include "ModemAnalog.h"
|
#include "ModemAnalog.h"
|
||||||
|
|
||||||
class ModemLSB : public ModemAnalog {
|
class ModemLSB : public ModemAnalog {
|
||||||
public:
|
public:
|
||||||
ModemLSB();
|
ModemLSB();
|
||||||
~ModemLSB();
|
~ModemLSB();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemUSB.h"
|
#include "ModemUSB.h"
|
||||||
|
|
||||||
ModemUSB::ModemUSB() {
|
ModemUSB::ModemUSB() : ModemAnalog() {
|
||||||
// half band filter used for side-band elimination
|
// half band filter used for side-band elimination
|
||||||
ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
||||||
demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1);
|
demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1);
|
||||||
@ -19,6 +19,20 @@ ModemUSB::~ModemUSB() {
|
|||||||
ampmodem_destroy(demodAM_USB);
|
ampmodem_destroy(demodAM_USB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModemUSB::checkSampleRate(long long sampleRate, int audioSampleRate) {
|
||||||
|
if (sampleRate < MIN_BANDWIDTH) {
|
||||||
|
return MIN_BANDWIDTH;
|
||||||
|
}
|
||||||
|
if (sampleRate % 2 == 0) {
|
||||||
|
return sampleRate;
|
||||||
|
}
|
||||||
|
return sampleRate+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModemUSB::getDefaultSampleRate() {
|
||||||
|
return 5400;
|
||||||
|
}
|
||||||
|
|
||||||
void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
|
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
@ -5,8 +5,14 @@ class ModemUSB : public ModemAnalog {
|
|||||||
public:
|
public:
|
||||||
ModemUSB();
|
ModemUSB();
|
||||||
~ModemUSB();
|
~ModemUSB();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemAPSK.h"
|
#include "ModemAPSK.h"
|
||||||
|
|
||||||
ModemAPSK::ModemAPSK() {
|
ModemAPSK::ModemAPSK() : ModemDigital() {
|
||||||
demodAPSK4 = modem_create(LIQUID_MODEM_APSK4);
|
demodAPSK4 = modem_create(LIQUID_MODEM_APSK4);
|
||||||
demodAPSK8 = modem_create(LIQUID_MODEM_APSK8);
|
demodAPSK8 = modem_create(LIQUID_MODEM_APSK8);
|
||||||
demodAPSK16 = modem_create(LIQUID_MODEM_APSK16);
|
demodAPSK16 = modem_create(LIQUID_MODEM_APSK16);
|
||||||
@ -8,9 +8,8 @@ ModemAPSK::ModemAPSK() {
|
|||||||
demodAPSK64 = modem_create(LIQUID_MODEM_APSK64);
|
demodAPSK64 = modem_create(LIQUID_MODEM_APSK64);
|
||||||
demodAPSK128 = modem_create(LIQUID_MODEM_APSK128);
|
demodAPSK128 = modem_create(LIQUID_MODEM_APSK128);
|
||||||
demodAPSK256 = modem_create(LIQUID_MODEM_APSK256);
|
demodAPSK256 = modem_create(LIQUID_MODEM_APSK256);
|
||||||
demodulatorCons.store(4);
|
demodAPSK = demodAPSK4;
|
||||||
currentDemodCons.store(0);
|
cons = 4;
|
||||||
updateDemodulatorCons(4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem *ModemAPSK::factory() {
|
Modem *ModemAPSK::factory() {
|
||||||
@ -31,46 +30,67 @@ std::string ModemAPSK::getName() {
|
|||||||
return "APSK";
|
return "APSK";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList ModemAPSK::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
ModemArgInfo consArg;
|
||||||
|
consArg.key = "cons";
|
||||||
|
consArg.name = "Constellation";
|
||||||
|
consArg.description = "Modem Constellation Pattern";
|
||||||
|
consArg.value = std::to_string(cons);
|
||||||
|
consArg.type = ModemArgInfo::STRING;
|
||||||
|
std::vector<std::string> consOpts;
|
||||||
|
consOpts.push_back("4");
|
||||||
|
consOpts.push_back("8");
|
||||||
|
consOpts.push_back("16");
|
||||||
|
consOpts.push_back("32");
|
||||||
|
consOpts.push_back("64");
|
||||||
|
consOpts.push_back("128");
|
||||||
|
consOpts.push_back("256");
|
||||||
|
consArg.options = consOpts;
|
||||||
|
args.push_back(consArg);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemAPSK::writeSetting(std::string setting, std::string value) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
int newCons = std::stoi(value);
|
||||||
|
updateDemodulatorCons(newCons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemAPSK::readSetting(std::string setting) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
return std::to_string(cons);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void ModemAPSK::updateDemodulatorCons(int cons) {
|
void ModemAPSK::updateDemodulatorCons(int cons) {
|
||||||
if (currentDemodCons.load() != cons) {
|
this->cons = cons;
|
||||||
currentDemodCons = cons;
|
switch (cons) {
|
||||||
switch (demodulatorCons.load()) {
|
case 4:
|
||||||
case 2:
|
demodAPSK = demodAPSK4;
|
||||||
demodAPSK = demodAPSK4;
|
break;
|
||||||
updateDemodulatorCons(4);
|
case 8:
|
||||||
break;
|
demodAPSK = demodAPSK8;
|
||||||
case 4:
|
break;
|
||||||
demodAPSK = demodAPSK4;
|
case 16:
|
||||||
updateDemodulatorCons(4);
|
demodAPSK = demodAPSK16;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 32:
|
||||||
demodAPSK = demodAPSK8;
|
demodAPSK = demodAPSK32;
|
||||||
updateDemodulatorCons(8);
|
break;
|
||||||
break;
|
case 64:
|
||||||
case 16:
|
demodAPSK = demodAPSK64;
|
||||||
demodAPSK = demodAPSK16;
|
break;
|
||||||
updateDemodulatorCons(16);
|
case 128:
|
||||||
break;
|
demodAPSK = demodAPSK128;
|
||||||
case 32:
|
break;
|
||||||
demodAPSK = demodAPSK32;
|
case 256:
|
||||||
updateDemodulatorCons(32);
|
demodAPSK = demodAPSK256;
|
||||||
break;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,20 @@ class ModemAPSK : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemAPSK();
|
ModemAPSK();
|
||||||
~ModemAPSK();
|
~ModemAPSK();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
ModemArgInfoList getSettings();
|
||||||
|
void writeSetting(std::string setting, std::string value);
|
||||||
|
std::string readSetting(std::string setting);
|
||||||
|
|
||||||
void updateDemodulatorCons(int cons);
|
void updateDemodulatorCons(int cons);
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int cons;
|
||||||
modem demodAPSK;
|
modem demodAPSK;
|
||||||
modem demodAPSK4;
|
modem demodAPSK4;
|
||||||
modem demodAPSK8;
|
modem demodAPSK8;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemASK.h"
|
#include "ModemASK.h"
|
||||||
|
|
||||||
ModemASK::ModemASK() {
|
ModemASK::ModemASK() : ModemDigital() {
|
||||||
demodASK2 = modem_create(LIQUID_MODEM_ASK2);
|
demodASK2 = modem_create(LIQUID_MODEM_ASK2);
|
||||||
demodASK4 = modem_create(LIQUID_MODEM_ASK4);
|
demodASK4 = modem_create(LIQUID_MODEM_ASK4);
|
||||||
demodASK8 = modem_create(LIQUID_MODEM_ASK8);
|
demodASK8 = modem_create(LIQUID_MODEM_ASK8);
|
||||||
@ -10,9 +10,7 @@ ModemASK::ModemASK() {
|
|||||||
demodASK128 = modem_create(LIQUID_MODEM_ASK128);
|
demodASK128 = modem_create(LIQUID_MODEM_ASK128);
|
||||||
demodASK256 = modem_create(LIQUID_MODEM_ASK256);
|
demodASK256 = modem_create(LIQUID_MODEM_ASK256);
|
||||||
demodASK = demodASK2;
|
demodASK = demodASK2;
|
||||||
demodulatorCons.store(2);
|
cons = 2;
|
||||||
currentDemodCons.store(0);
|
|
||||||
updateDemodulatorCons(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem *ModemASK::factory() {
|
Modem *ModemASK::factory() {
|
||||||
@ -33,47 +31,71 @@ std::string ModemASK::getName() {
|
|||||||
return "ASK";
|
return "ASK";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList ModemASK::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
ModemArgInfo consArg;
|
||||||
|
consArg.key = "cons";
|
||||||
|
consArg.name = "Constellation";
|
||||||
|
consArg.description = "Modem Constellation Pattern";
|
||||||
|
consArg.value = std::to_string(cons);
|
||||||
|
consArg.type = ModemArgInfo::STRING;
|
||||||
|
std::vector<std::string> consOpts;
|
||||||
|
consOpts.push_back("2");
|
||||||
|
consOpts.push_back("4");
|
||||||
|
consOpts.push_back("8");
|
||||||
|
consOpts.push_back("16");
|
||||||
|
consOpts.push_back("32");
|
||||||
|
consOpts.push_back("64");
|
||||||
|
consOpts.push_back("128");
|
||||||
|
consOpts.push_back("256");
|
||||||
|
consArg.options = consOpts;
|
||||||
|
args.push_back(consArg);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemASK::writeSetting(std::string setting, std::string value) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
int newCons = std::stoi(value);
|
||||||
|
updateDemodulatorCons(newCons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemASK::readSetting(std::string setting) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
return std::to_string(cons);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void ModemASK::updateDemodulatorCons(int cons) {
|
void ModemASK::updateDemodulatorCons(int cons) {
|
||||||
if (currentDemodCons.load() != cons) {
|
this->cons = cons;
|
||||||
currentDemodCons = cons;
|
switch (cons) {
|
||||||
|
case 2:
|
||||||
switch (demodulatorCons.load()) {
|
demodASK = demodASK2;
|
||||||
case 2:
|
break;
|
||||||
demodASK = demodASK2;
|
case 4:
|
||||||
updateDemodulatorCons(2);
|
demodASK = demodASK4;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 8:
|
||||||
demodASK = demodASK4;
|
demodASK = demodASK8;
|
||||||
updateDemodulatorCons(4);
|
break;
|
||||||
break;
|
case 16:
|
||||||
case 8:
|
demodASK = demodASK16;
|
||||||
demodASK = demodASK8;
|
break;
|
||||||
updateDemodulatorCons(8);
|
case 32:
|
||||||
break;
|
demodASK = demodASK32;
|
||||||
case 16:
|
break;
|
||||||
demodASK = demodASK16;
|
case 64:
|
||||||
updateDemodulatorCons(16);
|
demodASK = demodASK64;
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 128:
|
||||||
demodASK = demodASK32;
|
demodASK = demodASK128;
|
||||||
updateDemodulatorCons(32);
|
break;
|
||||||
break;
|
case 256:
|
||||||
case 64:
|
demodASK = demodASK256;
|
||||||
demodASK = demodASK64;
|
break;
|
||||||
updateDemodulatorCons(64);
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
demodASK = demodASK128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
demodASK = demodASK256;
|
|
||||||
updateDemodulatorCons(256);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
demodASK = demodASK2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,20 @@ class ModemASK : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemASK();
|
ModemASK();
|
||||||
~ModemASK();
|
~ModemASK();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
ModemArgInfoList getSettings();
|
||||||
|
void writeSetting(std::string setting, std::string value);
|
||||||
|
std::string readSetting(std::string setting);
|
||||||
|
|
||||||
void updateDemodulatorCons(int cons);
|
void updateDemodulatorCons(int cons);
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int cons;
|
||||||
modem demodASK;
|
modem demodASK;
|
||||||
modem demodASK2;
|
modem demodASK2;
|
||||||
modem demodASK4;
|
modem demodASK4;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemBPSK.h"
|
#include "ModemBPSK.h"
|
||||||
|
|
||||||
ModemBPSK::ModemBPSK() {
|
ModemBPSK::ModemBPSK() : ModemDigital() {
|
||||||
demodBPSK = modem_create(LIQUID_MODEM_BPSK);
|
demodBPSK = modem_create(LIQUID_MODEM_BPSK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,12 +16,6 @@ std::string ModemBPSK::getName() {
|
|||||||
return "BPSK";
|
return "BPSK";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemBPSK::updateDemodulatorCons(int cons) {
|
|
||||||
if (currentDemodCons.load() != cons) {
|
|
||||||
currentDemodCons = cons;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModemBPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemBPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
ModemKitDigital *dkit = (ModemKitDigital *)kit;
|
ModemKitDigital *dkit = (ModemKitDigital *)kit;
|
||||||
digitalStart(dkit, demodBPSK, input);
|
digitalStart(dkit, demodBPSK, input);
|
||||||
|
@ -5,12 +5,13 @@ class ModemBPSK : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemBPSK();
|
ModemBPSK();
|
||||||
~ModemBPSK();
|
~ModemBPSK();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
void updateDemodulatorCons(int cons);
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
modem demodBPSK;
|
modem demodBPSK;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemDPSK.h"
|
#include "ModemDPSK.h"
|
||||||
|
|
||||||
ModemDPSK::ModemDPSK() {
|
ModemDPSK::ModemDPSK() : ModemDigital() {
|
||||||
demodDPSK2 = modem_create(LIQUID_MODEM_DPSK2);
|
demodDPSK2 = modem_create(LIQUID_MODEM_DPSK2);
|
||||||
demodDPSK4 = modem_create(LIQUID_MODEM_DPSK4);
|
demodDPSK4 = modem_create(LIQUID_MODEM_DPSK4);
|
||||||
demodDPSK8 = modem_create(LIQUID_MODEM_DPSK8);
|
demodDPSK8 = modem_create(LIQUID_MODEM_DPSK8);
|
||||||
@ -9,9 +9,8 @@ ModemDPSK::ModemDPSK() {
|
|||||||
demodDPSK64 = modem_create(LIQUID_MODEM_DPSK64);
|
demodDPSK64 = modem_create(LIQUID_MODEM_DPSK64);
|
||||||
demodDPSK128 = modem_create(LIQUID_MODEM_DPSK128);
|
demodDPSK128 = modem_create(LIQUID_MODEM_DPSK128);
|
||||||
demodDPSK256 = modem_create(LIQUID_MODEM_DPSK256);
|
demodDPSK256 = modem_create(LIQUID_MODEM_DPSK256);
|
||||||
demodulatorCons.store(2);
|
demodDPSK = demodDPSK2;
|
||||||
currentDemodCons.store(0);
|
cons = 2;
|
||||||
updateDemodulatorCons(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem *ModemDPSK::factory() {
|
Modem *ModemDPSK::factory() {
|
||||||
@ -33,47 +32,71 @@ ModemDPSK::~ModemDPSK() {
|
|||||||
modem_destroy(demodDPSK256);
|
modem_destroy(demodDPSK256);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList ModemDPSK::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
ModemArgInfo consArg;
|
||||||
|
consArg.key = "cons";
|
||||||
|
consArg.name = "Constellation";
|
||||||
|
consArg.description = "Modem Constellation Pattern";
|
||||||
|
consArg.value = std::to_string(cons);
|
||||||
|
consArg.type = ModemArgInfo::STRING;
|
||||||
|
std::vector<std::string> consOpts;
|
||||||
|
consOpts.push_back("2");
|
||||||
|
consOpts.push_back("4");
|
||||||
|
consOpts.push_back("8");
|
||||||
|
consOpts.push_back("16");
|
||||||
|
consOpts.push_back("32");
|
||||||
|
consOpts.push_back("64");
|
||||||
|
consOpts.push_back("128");
|
||||||
|
consOpts.push_back("256");
|
||||||
|
consArg.options = consOpts;
|
||||||
|
args.push_back(consArg);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemDPSK::writeSetting(std::string setting, std::string value) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
int newCons = std::stoi(value);
|
||||||
|
updateDemodulatorCons(newCons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemDPSK::readSetting(std::string setting) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
return std::to_string(cons);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void ModemDPSK::updateDemodulatorCons(int cons) {
|
void ModemDPSK::updateDemodulatorCons(int cons) {
|
||||||
if (currentDemodCons.load() != cons) {
|
this->cons = cons;
|
||||||
currentDemodCons = cons;
|
switch (cons) {
|
||||||
|
case 2:
|
||||||
switch (demodulatorCons.load()) {
|
demodDPSK = demodDPSK2;
|
||||||
case 2:
|
break;
|
||||||
demodDPSK = demodDPSK2;
|
case 4:
|
||||||
updateDemodulatorCons(2);
|
demodDPSK = demodDPSK4;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 8:
|
||||||
demodDPSK = demodDPSK4;
|
demodDPSK = demodDPSK8;
|
||||||
updateDemodulatorCons(4);
|
break;
|
||||||
break;
|
case 16:
|
||||||
case 8:
|
demodDPSK = demodDPSK16;
|
||||||
demodDPSK = demodDPSK8;
|
break;
|
||||||
updateDemodulatorCons(8);
|
case 32:
|
||||||
break;
|
demodDPSK = demodDPSK32;
|
||||||
case 16:
|
break;
|
||||||
demodDPSK = demodDPSK16;
|
case 64:
|
||||||
updateDemodulatorCons(16);
|
demodDPSK = demodDPSK64;
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 128:
|
||||||
demodDPSK = demodDPSK32;
|
demodDPSK = demodDPSK128;
|
||||||
updateDemodulatorCons(32);
|
break;
|
||||||
break;
|
case 256:
|
||||||
case 64:
|
demodDPSK = demodDPSK256;
|
||||||
demodDPSK = demodDPSK64;
|
break;
|
||||||
updateDemodulatorCons(64);
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
demodDPSK = demodDPSK128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
demodDPSK = demodDPSK256;
|
|
||||||
updateDemodulatorCons(256);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
demodDPSK = demodDPSK2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,20 @@ class ModemDPSK : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemDPSK();
|
ModemDPSK();
|
||||||
~ModemDPSK();
|
~ModemDPSK();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
ModemArgInfoList getSettings();
|
||||||
|
void writeSetting(std::string setting, std::string value);
|
||||||
|
std::string readSetting(std::string setting);
|
||||||
|
|
||||||
void updateDemodulatorCons(int cons);
|
void updateDemodulatorCons(int cons);
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int cons;
|
||||||
modem demodDPSK;
|
modem demodDPSK;
|
||||||
modem demodDPSK2;
|
modem demodDPSK2;
|
||||||
modem demodDPSK4;
|
modem demodDPSK4;
|
||||||
|
143
src/modules/modem/digital/ModemFSK.cpp
Normal file
143
src/modules/modem/digital/ModemFSK.cpp
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#include "ModemFSK.h"
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
ModemFSK::ModemFSK() : ModemDigital() {
|
||||||
|
// DMR defaults?
|
||||||
|
bps = 1;
|
||||||
|
sps = 9600;
|
||||||
|
bw = 0.45;
|
||||||
|
outStream << std::hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *ModemFSK::factory() {
|
||||||
|
return new ModemFSK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModemFSK::checkSampleRate(long long sampleRate, int audioSampleRate) {
|
||||||
|
float minSps = pow(2.0,bps);
|
||||||
|
float nextSps = (float(sampleRate) / float(sps));
|
||||||
|
if (nextSps < minSps) {
|
||||||
|
return 2 * bps * sps;
|
||||||
|
} else {
|
||||||
|
return sampleRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModemFSK::getDefaultSampleRate() {
|
||||||
|
return 19200;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList ModemFSK::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
ModemArgInfo bpsArg;
|
||||||
|
bpsArg.key = "bps";
|
||||||
|
bpsArg.name = "Bits/symbol";
|
||||||
|
bpsArg.value = std::to_string(bps);
|
||||||
|
bpsArg.description = "Modem bits-per-symbol";
|
||||||
|
bpsArg.type = ModemArgInfo::STRING;
|
||||||
|
bpsArg.units = "bits";
|
||||||
|
|
||||||
|
std::vector<std::string> bpsOpts;
|
||||||
|
bpsOpts.push_back("1");
|
||||||
|
bpsOpts.push_back("2");
|
||||||
|
bpsOpts.push_back("4");
|
||||||
|
bpsOpts.push_back("8");
|
||||||
|
bpsOpts.push_back("16");
|
||||||
|
bpsArg.options = bpsOpts;
|
||||||
|
|
||||||
|
args.push_back(bpsArg);
|
||||||
|
|
||||||
|
ModemArgInfo spsArg;
|
||||||
|
spsArg.key = "sps";
|
||||||
|
spsArg.name = "Symbols/second";
|
||||||
|
spsArg.value = std::to_string(sps);
|
||||||
|
spsArg.description = "Modem symbols-per-second";
|
||||||
|
spsArg.type = ModemArgInfo::INT;
|
||||||
|
spsArg.range = ModemRange(10,115200);
|
||||||
|
std::vector<std::string> spsOpts;
|
||||||
|
|
||||||
|
args.push_back(spsArg);
|
||||||
|
|
||||||
|
ModemArgInfo bwArg;
|
||||||
|
bwArg.key = "bw";
|
||||||
|
bwArg.name = "Signal bandwidth";
|
||||||
|
bwArg.value = std::to_string(bw);
|
||||||
|
bwArg.description = "Total signal bandwidth";
|
||||||
|
bwArg.type = ModemArgInfo::FLOAT;
|
||||||
|
bwArg.range = ModemRange(0.1,0.49);
|
||||||
|
args.push_back(bwArg);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemFSK::writeSetting(std::string setting, std::string value) {
|
||||||
|
if (setting == "bps") {
|
||||||
|
bps = std::stoi(value);
|
||||||
|
rebuildKit();
|
||||||
|
} else if (setting == "sps") {
|
||||||
|
sps = std::stoi(value);
|
||||||
|
rebuildKit();
|
||||||
|
} else if (setting == "bw") {
|
||||||
|
bw = std::stof(value);
|
||||||
|
rebuildKit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemFSK::readSetting(std::string setting) {
|
||||||
|
if (setting == "bps") {
|
||||||
|
return std::to_string(bps);
|
||||||
|
} else if (setting == "sps") {
|
||||||
|
return std::to_string(sps);
|
||||||
|
} else if (setting == "bw") {
|
||||||
|
return std::to_string(bw);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemKit *ModemFSK::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
|
ModemKitFSK *dkit = new ModemKitFSK;
|
||||||
|
dkit->m = bps;
|
||||||
|
dkit->k = sampleRate / sps;
|
||||||
|
dkit->bw = bw;
|
||||||
|
|
||||||
|
dkit->demodFSK = fskdem_create(dkit->m, dkit->k, dkit->bw);
|
||||||
|
|
||||||
|
dkit->sampleRate = sampleRate;
|
||||||
|
dkit->audioSampleRate = audioSampleRate;
|
||||||
|
|
||||||
|
return dkit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemFSK::disposeKit(ModemKit *kit) {
|
||||||
|
ModemKitFSK *dkit = (ModemKitFSK *)kit;
|
||||||
|
|
||||||
|
fskdem_destroy(dkit->demodFSK);
|
||||||
|
|
||||||
|
delete dkit;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemFSK::getName() {
|
||||||
|
return "FSK";
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemFSK::~ModemFSK() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemFSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
ModemKitFSK *dkit = (ModemKitFSK *)kit;
|
||||||
|
|
||||||
|
digitalStart(dkit, nullptr, input);
|
||||||
|
|
||||||
|
dkit->inputBuffer.insert(dkit->inputBuffer.end(),input->data.begin(),input->data.end());
|
||||||
|
|
||||||
|
while (dkit->inputBuffer.size() >= dkit->k) {
|
||||||
|
outStream << fskdem_demodulate(dkit->demodFSK, &dkit->inputBuffer[0]);
|
||||||
|
|
||||||
|
// float err = fskdem_get_frequency_error(dkit->demodFSK);
|
||||||
|
dkit->inputBuffer.erase(dkit->inputBuffer.begin(),dkit->inputBuffer.begin()+dkit->k);
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalFinish(dkit, nullptr);
|
||||||
|
}
|
40
src/modules/modem/digital/ModemFSK.h
Normal file
40
src/modules/modem/digital/ModemFSK.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ModemDigital.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
class ModemKitFSK : public ModemKitDigital {
|
||||||
|
public:
|
||||||
|
unsigned int m, k;
|
||||||
|
float bw;
|
||||||
|
|
||||||
|
fskdem demodFSK;
|
||||||
|
std::vector<liquid_float_complex> inputBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModemFSK : public ModemDigital {
|
||||||
|
public:
|
||||||
|
ModemFSK();
|
||||||
|
~ModemFSK();
|
||||||
|
|
||||||
|
std::string getName();
|
||||||
|
|
||||||
|
Modem *factory();
|
||||||
|
|
||||||
|
int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
|
ModemArgInfoList getSettings();
|
||||||
|
void writeSetting(std::string setting, std::string value);
|
||||||
|
std::string readSetting(std::string setting);
|
||||||
|
|
||||||
|
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
|
void disposeKit(ModemKit *kit);
|
||||||
|
|
||||||
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int sps, bps;
|
||||||
|
float bw;
|
||||||
|
};
|
||||||
|
|
133
src/modules/modem/digital/ModemGMSK.cpp
Normal file
133
src/modules/modem/digital/ModemGMSK.cpp
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#include "ModemGMSK.h"
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
ModemGMSK::ModemGMSK() : ModemDigital() {
|
||||||
|
_sps = 4;
|
||||||
|
_fdelay = 3;
|
||||||
|
_ebf = 0.3;
|
||||||
|
outStream << std::hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemGMSK::~ModemGMSK() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemGMSK::getName() {
|
||||||
|
return "GMSK";
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *ModemGMSK::factory() {
|
||||||
|
return new ModemGMSK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModemGMSK::checkSampleRate(long long sampleRate, int audioSampleRate) {
|
||||||
|
if (sampleRate < MIN_BANDWIDTH) {
|
||||||
|
return MIN_BANDWIDTH;
|
||||||
|
}
|
||||||
|
return sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModemGMSK::getDefaultSampleRate() {
|
||||||
|
return 19200;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList ModemGMSK::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
ModemArgInfo fdelayArg;
|
||||||
|
fdelayArg.key = "fdelay";
|
||||||
|
fdelayArg.name = "Filter delay";
|
||||||
|
fdelayArg.value = std::to_string(_fdelay);
|
||||||
|
fdelayArg.description = "Filter delay in samples";
|
||||||
|
fdelayArg.type = ModemArgInfo::INT;
|
||||||
|
fdelayArg.units = "samples";
|
||||||
|
fdelayArg.range = ModemRange(1,128);
|
||||||
|
args.push_back(fdelayArg);
|
||||||
|
|
||||||
|
ModemArgInfo spsArg;
|
||||||
|
spsArg.key = "sps";
|
||||||
|
spsArg.name = "Samples / symbol";
|
||||||
|
spsArg.value = std::to_string(_sps);
|
||||||
|
spsArg.description = "Modem samples-per-symbol";
|
||||||
|
spsArg.type = ModemArgInfo::INT;
|
||||||
|
spsArg.units = "samples/symbol";
|
||||||
|
spsArg.range = ModemRange(2,512);
|
||||||
|
args.push_back(spsArg);
|
||||||
|
|
||||||
|
ModemArgInfo ebfArg;
|
||||||
|
ebfArg.key = "ebf";
|
||||||
|
ebfArg.name = "Excess bandwidth";
|
||||||
|
ebfArg.value = std::to_string(_ebf);
|
||||||
|
ebfArg.description = "Modem excess bandwidth factor";
|
||||||
|
ebfArg.type = ModemArgInfo::FLOAT;
|
||||||
|
ebfArg.range = ModemRange(0.1,0.49);
|
||||||
|
args.push_back(ebfArg);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemGMSK::writeSetting(std::string setting, std::string value) {
|
||||||
|
if (setting == "fdelay") {
|
||||||
|
_fdelay = std::stoi(value);
|
||||||
|
rebuildKit();
|
||||||
|
} else if (setting == "sps") {
|
||||||
|
_sps = std::stoi(value);
|
||||||
|
rebuildKit();
|
||||||
|
} else if (setting == "ebf") {
|
||||||
|
_ebf = std::stof(value);
|
||||||
|
rebuildKit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemGMSK::readSetting(std::string setting) {
|
||||||
|
if (setting == "fdelay") {
|
||||||
|
return std::to_string(_fdelay);
|
||||||
|
} else if (setting == "sps") {
|
||||||
|
return std::to_string(_sps);
|
||||||
|
} else if (setting == "ebf") {
|
||||||
|
return std::to_string(_ebf);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemKit *ModemGMSK::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
|
ModemKitGMSK *dkit = new ModemKitGMSK;
|
||||||
|
dkit->sps = _sps;
|
||||||
|
dkit->fdelay = _fdelay;
|
||||||
|
dkit->ebf = _ebf;
|
||||||
|
|
||||||
|
dkit->demodGMSK = gmskdem_create(dkit->sps, dkit->fdelay, dkit->ebf);
|
||||||
|
|
||||||
|
dkit->sampleRate = sampleRate;
|
||||||
|
dkit->audioSampleRate = audioSampleRate;
|
||||||
|
|
||||||
|
return dkit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemGMSK::disposeKit(ModemKit *kit) {
|
||||||
|
ModemKitGMSK *dkit = (ModemKitGMSK *)kit;
|
||||||
|
|
||||||
|
gmskdem_destroy(dkit->demodGMSK);
|
||||||
|
|
||||||
|
delete dkit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemGMSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
ModemKitGMSK *dkit = (ModemKitGMSK *)kit;
|
||||||
|
unsigned int sym_out;
|
||||||
|
|
||||||
|
digitalStart(dkit, nullptr, input);
|
||||||
|
|
||||||
|
dkit->inputBuffer.insert(dkit->inputBuffer.end(),input->data.begin(),input->data.end());
|
||||||
|
|
||||||
|
int numProcessed = 0;
|
||||||
|
for (int i = 0, iMax = dkit->inputBuffer.size()/dkit->sps; i < iMax; i+= dkit->sps) {
|
||||||
|
gmskdem_demodulate(dkit->demodGMSK, &input->data[i],&sym_out);
|
||||||
|
outStream << sym_out;
|
||||||
|
numProcessed += dkit->sps;
|
||||||
|
}
|
||||||
|
|
||||||
|
dkit->inputBuffer.erase(dkit->inputBuffer.begin(),dkit->inputBuffer.begin()+numProcessed);
|
||||||
|
|
||||||
|
digitalFinish(dkit, nullptr);
|
||||||
|
}
|
41
src/modules/modem/digital/ModemGMSK.h
Normal file
41
src/modules/modem/digital/ModemGMSK.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ModemDigital.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
class ModemKitGMSK : public ModemKitDigital {
|
||||||
|
public:
|
||||||
|
unsigned int fdelay, sps;
|
||||||
|
float ebf;
|
||||||
|
|
||||||
|
gmskdem demodGMSK;
|
||||||
|
std::vector<liquid_float_complex> inputBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModemGMSK : public ModemDigital {
|
||||||
|
public:
|
||||||
|
ModemGMSK();
|
||||||
|
~ModemGMSK();
|
||||||
|
|
||||||
|
std::string getName();
|
||||||
|
|
||||||
|
Modem *factory();
|
||||||
|
|
||||||
|
int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
|
ModemArgInfoList getSettings();
|
||||||
|
void writeSetting(std::string setting, std::string value);
|
||||||
|
std::string readSetting(std::string setting);
|
||||||
|
|
||||||
|
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
|
void disposeKit(ModemKit *kit);
|
||||||
|
|
||||||
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _sps; // samples per symbol
|
||||||
|
int _fdelay; // filter delay
|
||||||
|
float _ebf;
|
||||||
|
};
|
||||||
|
|
@ -1,13 +1,9 @@
|
|||||||
#include "ModemOOK.h"
|
#include "ModemOOK.h"
|
||||||
|
|
||||||
ModemOOK::ModemOOK() {
|
ModemOOK::ModemOOK() : ModemDigital() {
|
||||||
demodOOK = modem_create(LIQUID_MODEM_OOK);
|
demodOOK = modem_create(LIQUID_MODEM_OOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem *ModemOOK::factory() {
|
|
||||||
return new ModemOOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModemOOK::~ModemOOK() {
|
ModemOOK::~ModemOOK() {
|
||||||
modem_destroy(demodOOK);
|
modem_destroy(demodOOK);
|
||||||
}
|
}
|
||||||
@ -16,10 +12,15 @@ std::string ModemOOK::getName() {
|
|||||||
return "OOK";
|
return "OOK";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemOOK::updateDemodulatorCons(int cons) {
|
Modem *ModemOOK::factory() {
|
||||||
if (currentDemodCons.load() != cons) {
|
return new ModemOOK;
|
||||||
currentDemodCons = cons;
|
}
|
||||||
|
|
||||||
|
int ModemOOK::checkSampleRate(long long sampleRate, int audioSampleRate) {
|
||||||
|
if (sampleRate < 100) {
|
||||||
|
return 100;
|
||||||
}
|
}
|
||||||
|
return sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemOOK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemOOK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
@ -5,12 +5,15 @@ class ModemOOK : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemOOK();
|
ModemOOK();
|
||||||
~ModemOOK();
|
~ModemOOK();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
void updateDemodulatorCons(int cons);
|
|
||||||
|
int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
modem demodOOK;
|
modem demodOOK;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemPSK.h"
|
#include "ModemPSK.h"
|
||||||
|
|
||||||
ModemPSK::ModemPSK() {
|
ModemPSK::ModemPSK() : ModemDigital() {
|
||||||
demodPSK2 = modem_create(LIQUID_MODEM_PSK2);
|
demodPSK2 = modem_create(LIQUID_MODEM_PSK2);
|
||||||
demodPSK4 = modem_create(LIQUID_MODEM_PSK4);
|
demodPSK4 = modem_create(LIQUID_MODEM_PSK4);
|
||||||
demodPSK8 = modem_create(LIQUID_MODEM_PSK8);
|
demodPSK8 = modem_create(LIQUID_MODEM_PSK8);
|
||||||
@ -9,9 +9,8 @@ ModemPSK::ModemPSK() {
|
|||||||
demodPSK64 = modem_create(LIQUID_MODEM_PSK64);
|
demodPSK64 = modem_create(LIQUID_MODEM_PSK64);
|
||||||
demodPSK128 = modem_create(LIQUID_MODEM_PSK128);
|
demodPSK128 = modem_create(LIQUID_MODEM_PSK128);
|
||||||
demodPSK256 = modem_create(LIQUID_MODEM_PSK256);
|
demodPSK256 = modem_create(LIQUID_MODEM_PSK256);
|
||||||
demodulatorCons.store(2);
|
demodPSK = demodPSK2;
|
||||||
currentDemodCons.store(0);
|
cons = 2;
|
||||||
updateDemodulatorCons(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem *ModemPSK::factory() {
|
Modem *ModemPSK::factory() {
|
||||||
@ -33,47 +32,72 @@ ModemPSK::~ModemPSK() {
|
|||||||
modem_destroy(demodPSK256);
|
modem_destroy(demodPSK256);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModemArgInfoList ModemPSK::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
ModemArgInfo consArg;
|
||||||
|
consArg.key = "cons";
|
||||||
|
consArg.name = "Constellation";
|
||||||
|
consArg.description = "Modem Constellation Pattern";
|
||||||
|
consArg.value = std::to_string(cons);
|
||||||
|
consArg.type = ModemArgInfo::STRING;
|
||||||
|
std::vector<std::string> consOpts;
|
||||||
|
consOpts.push_back("2");
|
||||||
|
consOpts.push_back("4");
|
||||||
|
consOpts.push_back("8");
|
||||||
|
consOpts.push_back("16");
|
||||||
|
consOpts.push_back("32");
|
||||||
|
consOpts.push_back("64");
|
||||||
|
consOpts.push_back("128");
|
||||||
|
consOpts.push_back("256");
|
||||||
|
consArg.options = consOpts;
|
||||||
|
args.push_back(consArg);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemPSK::writeSetting(std::string setting, std::string value) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
int newCons = std::stoi(value);
|
||||||
|
updateDemodulatorCons(newCons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemPSK::readSetting(std::string setting) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
return std::to_string(cons);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void ModemPSK::updateDemodulatorCons(int cons) {
|
void ModemPSK::updateDemodulatorCons(int cons) {
|
||||||
if (currentDemodCons.load() != cons) {
|
this->cons = cons;
|
||||||
currentDemodCons = cons;
|
switch (cons) {
|
||||||
|
case 2:
|
||||||
switch (demodulatorCons.load()) {
|
demodPSK = demodPSK2;
|
||||||
case 2:
|
break;
|
||||||
demodPSK = demodPSK2;
|
case 4:
|
||||||
updateDemodulatorCons(2);
|
demodPSK = demodPSK4;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 8:
|
||||||
demodPSK = demodPSK4;
|
demodPSK = demodPSK8;
|
||||||
updateDemodulatorCons(4);
|
break;
|
||||||
break;
|
case 16:
|
||||||
case 8:
|
demodPSK = demodPSK16;
|
||||||
demodPSK = demodPSK8;
|
break;
|
||||||
updateDemodulatorCons(8);
|
case 32:
|
||||||
break;
|
demodPSK = demodPSK32;
|
||||||
case 16:
|
break;
|
||||||
demodPSK = demodPSK16;
|
case 64:
|
||||||
updateDemodulatorCons(16);
|
demodPSK = demodPSK64;
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 128:
|
||||||
demodPSK = demodPSK32;
|
demodPSK = demodPSK128;
|
||||||
updateDemodulatorCons(32);
|
break;
|
||||||
break;
|
case 256:
|
||||||
case 64:
|
demodPSK = demodPSK256;
|
||||||
demodPSK = demodPSK64;
|
break;
|
||||||
updateDemodulatorCons(64);
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
demodPSK = demodPSK128;
|
|
||||||
updateDemodulatorCons(128);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
demodPSK = demodPSK256;
|
|
||||||
updateDemodulatorCons(256);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
demodPSK = demodPSK2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,20 @@ class ModemPSK : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemPSK();
|
ModemPSK();
|
||||||
~ModemPSK();
|
~ModemPSK();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
ModemArgInfoList getSettings();
|
||||||
|
void writeSetting(std::string setting, std::string value);
|
||||||
|
std::string readSetting(std::string setting);
|
||||||
|
|
||||||
void updateDemodulatorCons(int cons);
|
void updateDemodulatorCons(int cons);
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int cons;
|
||||||
modem demodPSK;
|
modem demodPSK;
|
||||||
modem demodPSK2;
|
modem demodPSK2;
|
||||||
modem demodPSK4;
|
modem demodPSK4;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemQAM.h"
|
#include "ModemQAM.h"
|
||||||
|
|
||||||
ModemQAM::ModemQAM() {
|
ModemQAM::ModemQAM() : ModemDigital() {
|
||||||
demodQAM4 = modem_create(LIQUID_MODEM_QAM4);
|
demodQAM4 = modem_create(LIQUID_MODEM_QAM4);
|
||||||
demodQAM8 = modem_create(LIQUID_MODEM_QAM8);
|
demodQAM8 = modem_create(LIQUID_MODEM_QAM8);
|
||||||
demodQAM16 = modem_create(LIQUID_MODEM_QAM16);
|
demodQAM16 = modem_create(LIQUID_MODEM_QAM16);
|
||||||
@ -8,9 +8,8 @@ ModemQAM::ModemQAM() {
|
|||||||
demodQAM64 = modem_create(LIQUID_MODEM_QAM64);
|
demodQAM64 = modem_create(LIQUID_MODEM_QAM64);
|
||||||
demodQAM128 = modem_create(LIQUID_MODEM_QAM128);
|
demodQAM128 = modem_create(LIQUID_MODEM_QAM128);
|
||||||
demodQAM256 = modem_create(LIQUID_MODEM_QAM256);
|
demodQAM256 = modem_create(LIQUID_MODEM_QAM256);
|
||||||
demodulatorCons.store(4);
|
demodQAM = demodQAM4;
|
||||||
currentDemodCons.store(0);
|
cons = 4;
|
||||||
updateDemodulatorCons(4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem *ModemQAM::factory() {
|
Modem *ModemQAM::factory() {
|
||||||
@ -31,47 +30,67 @@ ModemQAM::~ModemQAM() {
|
|||||||
modem_destroy(demodQAM256);
|
modem_destroy(demodQAM256);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList ModemQAM::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
ModemArgInfo consArg;
|
||||||
|
consArg.key = "cons";
|
||||||
|
consArg.name = "Constellation";
|
||||||
|
consArg.description = "Modem Constellation Pattern";
|
||||||
|
consArg.value = std::to_string(cons);
|
||||||
|
consArg.type = ModemArgInfo::STRING;
|
||||||
|
std::vector<std::string> consOpts;
|
||||||
|
consOpts.push_back("4");
|
||||||
|
consOpts.push_back("8");
|
||||||
|
consOpts.push_back("16");
|
||||||
|
consOpts.push_back("32");
|
||||||
|
consOpts.push_back("64");
|
||||||
|
consOpts.push_back("128");
|
||||||
|
consOpts.push_back("256");
|
||||||
|
consArg.options = consOpts;
|
||||||
|
args.push_back(consArg);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemQAM::writeSetting(std::string setting, std::string value) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
int newCons = std::stoi(value);
|
||||||
|
updateDemodulatorCons(newCons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemQAM::readSetting(std::string setting) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
return std::to_string(cons);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void ModemQAM::updateDemodulatorCons(int cons) {
|
void ModemQAM::updateDemodulatorCons(int cons) {
|
||||||
if (currentDemodCons.load() != cons) {
|
this->cons = cons;
|
||||||
currentDemodCons = cons;
|
switch (cons) {
|
||||||
|
case 4:
|
||||||
switch (demodulatorCons.load()) {
|
demodQAM = demodQAM4;
|
||||||
case 2:
|
break;
|
||||||
demodQAM = demodQAM4;
|
case 8:
|
||||||
updateDemodulatorCons(4);
|
demodQAM = demodQAM8;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 16:
|
||||||
demodQAM = demodQAM4;
|
demodQAM = demodQAM16;
|
||||||
updateDemodulatorCons(4);
|
break;
|
||||||
break;
|
case 32:
|
||||||
case 8:
|
demodQAM = demodQAM32;
|
||||||
demodQAM = demodQAM8;
|
break;
|
||||||
updateDemodulatorCons(8);
|
case 64:
|
||||||
break;
|
demodQAM = demodQAM64;
|
||||||
case 16:
|
break;
|
||||||
demodQAM = demodQAM16;
|
case 128:
|
||||||
updateDemodulatorCons(16);
|
demodQAM = demodQAM128;
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 256:
|
||||||
demodQAM = demodQAM32;
|
demodQAM = demodQAM256;
|
||||||
updateDemodulatorCons(32);
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,20 @@ class ModemQAM : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemQAM();
|
ModemQAM();
|
||||||
~ModemQAM();
|
~ModemQAM();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
ModemArgInfoList getSettings();
|
||||||
|
void writeSetting(std::string setting, std::string value);
|
||||||
|
std::string readSetting(std::string setting);
|
||||||
|
|
||||||
void updateDemodulatorCons(int cons);
|
void updateDemodulatorCons(int cons);
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int cons;
|
||||||
modem demodQAM;
|
modem demodQAM;
|
||||||
modem demodQAM4;
|
modem demodQAM4;
|
||||||
modem demodQAM8;
|
modem demodQAM8;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemQPSK.h"
|
#include "ModemQPSK.h"
|
||||||
|
|
||||||
ModemQPSK::ModemQPSK() {
|
ModemQPSK::ModemQPSK() : ModemDigital() {
|
||||||
demodQPSK = modem_create(LIQUID_MODEM_QPSK);
|
demodQPSK = modem_create(LIQUID_MODEM_QPSK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,12 +16,6 @@ std::string ModemQPSK::getName() {
|
|||||||
return "QPSK";
|
return "QPSK";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemQPSK::updateDemodulatorCons(int cons) {
|
|
||||||
if (currentDemodCons.load() != cons) {
|
|
||||||
currentDemodCons = cons;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModemQPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemQPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
ModemKitDigital *dkit = (ModemKitDigital *)kit;
|
ModemKitDigital *dkit = (ModemKitDigital *)kit;
|
||||||
digitalStart(dkit, demodQPSK, input);
|
digitalStart(dkit, demodQPSK, input);
|
||||||
|
@ -5,9 +5,11 @@ class ModemQPSK : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemQPSK();
|
ModemQPSK();
|
||||||
~ModemQPSK();
|
~ModemQPSK();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
void updateDemodulatorCons(int cons);
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
#include "ModemSQAM.h"
|
#include "ModemSQAM.h"
|
||||||
|
|
||||||
ModemSQAM::ModemSQAM() {
|
ModemSQAM::ModemSQAM() : ModemDigital() {
|
||||||
demodSQAM32 = modem_create(LIQUID_MODEM_SQAM32);
|
demodSQAM32 = modem_create(LIQUID_MODEM_SQAM32);
|
||||||
demodSQAM128 = modem_create(LIQUID_MODEM_SQAM128);
|
demodSQAM128 = modem_create(LIQUID_MODEM_SQAM128);
|
||||||
demodulatorCons.store(32);
|
demodSQAM = demodSQAM32;
|
||||||
currentDemodCons.store(0);
|
cons = 32;
|
||||||
updateDemodulatorCons(32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem *ModemSQAM::factory() {
|
Modem *ModemSQAM::factory() {
|
||||||
@ -21,47 +20,47 @@ std::string ModemSQAM::getName() {
|
|||||||
return "SQAM";
|
return "SQAM";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList ModemSQAM::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
ModemArgInfo consArg;
|
||||||
|
consArg.key = "cons";
|
||||||
|
consArg.name = "Constellation";
|
||||||
|
consArg.description = "Modem Constellation Pattern";
|
||||||
|
consArg.value = std::to_string(cons);
|
||||||
|
consArg.type = ModemArgInfo::STRING;
|
||||||
|
std::vector<std::string> consOpts;
|
||||||
|
consOpts.push_back("32");
|
||||||
|
consOpts.push_back("128");
|
||||||
|
consArg.options = consOpts;
|
||||||
|
args.push_back(consArg);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemSQAM::writeSetting(std::string setting, std::string value) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
int newCons = std::stoi(value);
|
||||||
|
updateDemodulatorCons(newCons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemSQAM::readSetting(std::string setting) {
|
||||||
|
if (setting == "cons") {
|
||||||
|
return std::to_string(cons);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void ModemSQAM::updateDemodulatorCons(int cons) {
|
void ModemSQAM::updateDemodulatorCons(int cons) {
|
||||||
if (currentDemodCons.load() != cons) {
|
this->cons = cons;
|
||||||
currentDemodCons = cons;
|
switch (cons) {
|
||||||
|
case 32:
|
||||||
switch (demodulatorCons.load()) {
|
demodSQAM = demodSQAM32;
|
||||||
case 2:
|
break;
|
||||||
demodSQAM = demodSQAM32;
|
case 128:
|
||||||
updateDemodulatorCons(32);
|
demodSQAM = demodSQAM128;
|
||||||
break;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,20 @@ class ModemSQAM : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemSQAM();
|
ModemSQAM();
|
||||||
~ModemSQAM();
|
~ModemSQAM();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
|
|
||||||
|
ModemArgInfoList getSettings();
|
||||||
|
void writeSetting(std::string setting, std::string value);
|
||||||
|
std::string readSetting(std::string setting);
|
||||||
|
|
||||||
void updateDemodulatorCons(int cons);
|
void updateDemodulatorCons(int cons);
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int cons;
|
||||||
modem demodSQAM;
|
modem demodSQAM;
|
||||||
modem demodSQAM32;
|
modem demodSQAM32;
|
||||||
modem demodSQAM128;
|
modem demodSQAM128;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ModemST.h"
|
#include "ModemST.h"
|
||||||
|
|
||||||
ModemST::ModemST() {
|
ModemST::ModemST() : ModemDigital() {
|
||||||
demodST = modem_create(LIQUID_MODEM_V29);
|
demodST = modem_create(LIQUID_MODEM_V29);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,12 +16,6 @@ ModemST::~ModemST() {
|
|||||||
modem_destroy(demodST);
|
modem_destroy(demodST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemST::updateDemodulatorCons(int cons) {
|
|
||||||
if (currentDemodCons.load() != cons) {
|
|
||||||
currentDemodCons = cons;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModemST::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
void ModemST::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
ModemKitDigital *dkit = (ModemKitDigital *)kit;
|
ModemKitDigital *dkit = (ModemKitDigital *)kit;
|
||||||
digitalStart(dkit, demodST, input);
|
digitalStart(dkit, demodST, input);
|
||||||
|
@ -5,9 +5,11 @@ class ModemST : public ModemDigital {
|
|||||||
public:
|
public:
|
||||||
ModemST();
|
ModemST();
|
||||||
~ModemST();
|
~ModemST();
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
Modem *factory();
|
Modem *factory();
|
||||||
void updateDemodulatorCons(int cons);
|
|
||||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -16,6 +16,9 @@ void ScopePanel::setMode(ScopeMode scopeMode) {
|
|||||||
this->scopeMode = scopeMode;
|
this->scopeMode = scopeMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScopePanel::ScopeMode ScopePanel::getMode() {
|
||||||
|
return this->scopeMode;
|
||||||
|
}
|
||||||
|
|
||||||
void ScopePanel::setPoints(std::vector<float> &points) {
|
void ScopePanel::setPoints(std::vector<float> &points) {
|
||||||
this->points.assign(points.begin(),points.end());
|
this->points.assign(points.begin(),points.end());
|
||||||
@ -61,14 +64,29 @@ void ScopePanel::drawPanelContents() {
|
|||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
} else if (scopeMode == SCOPE_MODE_XY) {
|
} else if (scopeMode == SCOPE_MODE_XY) {
|
||||||
// ...
|
RGBA4f bg1(ThemeMgr::mgr.currentTheme->scopeBackground), bg2(ThemeMgr::mgr.currentTheme->scopeBackground * 2.0);
|
||||||
|
bg1.a = 0.05;
|
||||||
|
bg2.a = 0.05;
|
||||||
|
bgPanel.setFillColor(bg1, bg2);
|
||||||
|
bgPanel.calcTransform(transform);
|
||||||
|
bgPanel.draw();
|
||||||
|
glLineWidth(1.0);
|
||||||
|
glEnable(GL_POINT_SMOOTH);
|
||||||
|
glPointSize(1.0);
|
||||||
|
glLoadMatrixf(transform);
|
||||||
|
glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r * 0.15, ThemeMgr::mgr.currentTheme->scopeLine.g * 0.15,
|
||||||
|
ThemeMgr::mgr.currentTheme->scopeLine.b * 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (points.size()) {
|
if (points.size()) {
|
||||||
glEnable (GL_BLEND);
|
glEnable (GL_BLEND);
|
||||||
glEnable (GL_LINE_SMOOTH);
|
glEnable (GL_LINE_SMOOTH);
|
||||||
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
if (scopeMode == SCOPE_MODE_XY) {
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
|
} else {
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
glColor4f(ThemeMgr::mgr.currentTheme->scopeLine.r, ThemeMgr::mgr.currentTheme->scopeLine.g, ThemeMgr::mgr.currentTheme->scopeLine.b, 1.0);
|
glColor4f(ThemeMgr::mgr.currentTheme->scopeLine.r, ThemeMgr::mgr.currentTheme->scopeLine.g, ThemeMgr::mgr.currentTheme->scopeLine.b, 1.0);
|
||||||
glEnableClientState (GL_VERTEX_ARRAY);
|
glEnableClientState (GL_VERTEX_ARRAY);
|
||||||
glVertexPointer(2, GL_FLOAT, 0, &points[0]);
|
glVertexPointer(2, GL_FLOAT, 0, &points[0]);
|
||||||
@ -83,7 +101,8 @@ void ScopePanel::drawPanelContents() {
|
|||||||
glLoadMatrixf(bgPanelStereo[1].transform);
|
glLoadMatrixf(bgPanelStereo[1].transform);
|
||||||
glDrawArrays(GL_LINE_STRIP, points.size() / 4, points.size() / 4);
|
glDrawArrays(GL_LINE_STRIP, points.size() / 4, points.size() / 4);
|
||||||
} else if (scopeMode == SCOPE_MODE_XY) {
|
} else if (scopeMode == SCOPE_MODE_XY) {
|
||||||
// ...
|
glLoadMatrixf(bgPanel.transform);
|
||||||
|
glDrawArrays(GL_POINTS, 0, points.size() / 2);
|
||||||
}
|
}
|
||||||
glLineWidth(1.0);
|
glLineWidth(1.0);
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
@ -10,6 +10,7 @@ public:
|
|||||||
ScopePanel();
|
ScopePanel();
|
||||||
|
|
||||||
void setMode(ScopeMode scopeMode);
|
void setMode(ScopeMode scopeMode);
|
||||||
|
ScopeMode getMode();
|
||||||
void setPoints(std::vector<float> &points);
|
void setPoints(std::vector<float> &points);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -95,7 +95,7 @@ void ScopeVisualProcessor::process() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioInputData->channels == 2) {
|
if (audioInputData->type == 1) {
|
||||||
iMax = audioInputData->data.size();
|
iMax = audioInputData->data.size();
|
||||||
if (renderData->waveform_points.size() != iMax * 2) {
|
if (renderData->waveform_points.size() != iMax * 2) {
|
||||||
renderData->waveform_points.resize(iMax * 2);
|
renderData->waveform_points.resize(iMax * 2);
|
||||||
@ -104,11 +104,23 @@ void ScopeVisualProcessor::process() {
|
|||||||
renderData->waveform_points[i * 2] = (((double) (i % (iMax/2)) / (double) iMax) * 2.0 - 0.5) * 2.0;
|
renderData->waveform_points[i * 2] = (((double) (i % (iMax/2)) / (double) iMax) * 2.0 - 0.5) * 2.0;
|
||||||
renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] / peak;
|
renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] / peak;
|
||||||
}
|
}
|
||||||
|
renderData->mode = ScopePanel::SCOPE_MODE_2Y;
|
||||||
|
} else if (audioInputData->type == 2) {
|
||||||
|
iMax = audioInputData->data.size();
|
||||||
|
if (renderData->waveform_points.size() != iMax) {
|
||||||
|
renderData->waveform_points.resize(iMax);
|
||||||
|
}
|
||||||
|
for (i = 0; i < iMax/2; i++) {
|
||||||
|
renderData->waveform_points[i * 2] = audioInputData->data[i * 2] / peak;
|
||||||
|
renderData->waveform_points[i * 2 + 1] = audioInputData->data[i * 2 + 1] / peak;
|
||||||
|
}
|
||||||
|
renderData->mode = ScopePanel::SCOPE_MODE_XY;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < iMax; i++) {
|
for (i = 0; i < iMax; i++) {
|
||||||
renderData->waveform_points[i * 2] = (((double) i / (double) iMax) - 0.5) * 2.0;
|
renderData->waveform_points[i * 2] = (((double) i / (double) iMax) - 0.5) * 2.0;
|
||||||
renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] / peak;
|
renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] / peak;
|
||||||
}
|
}
|
||||||
|
renderData->mode = ScopePanel::SCOPE_MODE_Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderData->spectrum = false;
|
renderData->spectrum = false;
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
#include "VisualProcessor.h"
|
#include "VisualProcessor.h"
|
||||||
#include "AudioThread.h"
|
#include "AudioThread.h"
|
||||||
#include "fftw3.h"
|
#include "fftw3.h"
|
||||||
|
#include "ScopePanel.h"
|
||||||
|
|
||||||
class ScopeRenderData: public ReferenceCounter {
|
class ScopeRenderData: public ReferenceCounter {
|
||||||
public:
|
public:
|
||||||
std::vector<float> waveform_points;
|
std::vector<float> waveform_points;
|
||||||
|
ScopePanel::ScopeMode mode;
|
||||||
int inputRate;
|
int inputRate;
|
||||||
int sampleRate;
|
int sampleRate;
|
||||||
int channels;
|
int channels;
|
||||||
|
@ -155,10 +155,16 @@ void ModeSelectorCanvas::addChoice(int value, std::string label) {
|
|||||||
numChoices = selections.size();
|
numChoices = selections.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModeSelectorCanvas::addChoice(std::string label) {
|
||||||
|
selections.push_back(ModeSelectorMode(selections.size()+1, label));
|
||||||
|
numChoices = selections.size();
|
||||||
|
}
|
||||||
|
|
||||||
void ModeSelectorCanvas::setSelection(std::string label) {
|
void ModeSelectorCanvas::setSelection(std::string label) {
|
||||||
for (int i = 0; i < numChoices; i++) {
|
for (int i = 0; i < numChoices; i++) {
|
||||||
if (selections[i].label == label) {
|
if (selections[i].label == label) {
|
||||||
currentSelection = i;
|
currentSelection = i;
|
||||||
|
Refresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ 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 addChoice(std::string label);
|
||||||
void setSelection(std::string label);
|
void setSelection(std::string label);
|
||||||
std::string getSelectionLabel();
|
std::string getSelectionLabel();
|
||||||
void setSelection(int value);
|
void setSelection(int value);
|
||||||
|
@ -230,9 +230,9 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBA4f color, long
|
|||||||
}
|
}
|
||||||
// advanced demodulators start here
|
// advanced demodulators start here
|
||||||
|
|
||||||
if (demod->getDemodulatorCons() > 0) {
|
// if (demod->getDemodulatorCons() > 0) {
|
||||||
demodStr = demodStr + std::to_string(demod->getDemodulatorCons());
|
// demodStr = demodStr + std::to_string(demod->getDemodulatorCons());
|
||||||
}
|
// }
|
||||||
|
|
||||||
// add lock to string if we have an lock
|
// add lock to string if we have an lock
|
||||||
if(demod->getDemodulatorLock()) {
|
if(demod->getDemodulatorLock()) {
|
||||||
|
@ -29,6 +29,5 @@ public:
|
|||||||
void setHoverAlpha(float hoverAlpha);
|
void setHoverAlpha(float hoverAlpha);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DemodulatorThreadParameters defaultDemodParams;
|
|
||||||
float hoverAlpha;
|
float hoverAlpha;
|
||||||
};
|
};
|
||||||
|
@ -28,7 +28,7 @@ EVT_LEAVE_WINDOW(ScopeCanvas::OnMouseLeftWindow)
|
|||||||
EVT_ENTER_WINDOW(ScopeCanvas::OnMouseEnterWindow)
|
EVT_ENTER_WINDOW(ScopeCanvas::OnMouseEnterWindow)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
ScopeCanvas::ScopeCanvas(wxWindow *parent, int *attribList) : InteractiveCanvas(parent, attribList), stereo(false), ppmMode(false), ctr(0), ctrTarget(0), dragAccel(0), helpTip("") {
|
ScopeCanvas::ScopeCanvas(wxWindow *parent, int *attribList) : InteractiveCanvas(parent, attribList), ppmMode(false), ctr(0), ctrTarget(0), dragAccel(0), helpTip("") {
|
||||||
|
|
||||||
glContext = new ScopeContext(this, &wxGetApp().GetContext(this));
|
glContext = new ScopeContext(this, &wxGetApp().GetContext(this));
|
||||||
inputData.set_max_num_items(2);
|
inputData.set_max_num_items(2);
|
||||||
@ -65,7 +65,7 @@ bool ScopeCanvas::spectrumVisible() {
|
|||||||
float panelInterval = (2.0 + panelSpacing);
|
float panelInterval = (2.0 + panelSpacing);
|
||||||
|
|
||||||
ctrTarget = abs(round(ctr / panelInterval));
|
ctrTarget = abs(round(ctr / panelInterval));
|
||||||
|
|
||||||
if (ctrTarget == 1 || dragAccel || (ctr != ctrTarget)) {
|
if (ctrTarget == 1 || dragAccel || (ctr != ctrTarget)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -73,10 +73,6 @@ bool ScopeCanvas::spectrumVisible() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScopeCanvas::setStereo(bool state) {
|
|
||||||
stereo = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScopeCanvas::setDeviceName(std::string device_name) {
|
void ScopeCanvas::setDeviceName(std::string device_name) {
|
||||||
deviceName = device_name;
|
deviceName = device_name;
|
||||||
deviceName.append(" ");
|
deviceName.append(" ");
|
||||||
@ -106,12 +102,12 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
ScopeRenderData *avData;
|
ScopeRenderData *avData;
|
||||||
inputData.pop(avData);
|
inputData.pop(avData);
|
||||||
|
|
||||||
|
|
||||||
if (!avData->spectrum) {
|
if (!avData->spectrum) {
|
||||||
|
scopePanel.setMode(avData->mode);
|
||||||
if (avData->waveform_points.size()) {
|
if (avData->waveform_points.size()) {
|
||||||
scopePanel.setPoints(avData->waveform_points);
|
scopePanel.setPoints(avData->waveform_points);
|
||||||
setStereo(avData->channels == 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
avData->decRefCount();
|
avData->decRefCount();
|
||||||
} else {
|
} else {
|
||||||
if (avData->waveform_points.size()) {
|
if (avData->waveform_points.size()) {
|
||||||
@ -133,14 +129,18 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
|
|
||||||
glViewport(0, 0, ClientSize.x, ClientSize.y);
|
glViewport(0, 0, ClientSize.x, ClientSize.y);
|
||||||
|
|
||||||
glContext->DrawBegin();
|
if (scopePanel.getMode() == ScopePanel::SCOPE_MODE_XY && !spectrumVisible()) {
|
||||||
|
glDrawBuffer(GL_FRONT);
|
||||||
|
glContext->DrawBegin(false);
|
||||||
|
} else {
|
||||||
|
glDrawBuffer(GL_BACK);
|
||||||
|
glContext->DrawBegin();
|
||||||
|
|
||||||
|
bgPanel.setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground * 3.0, RGBA4f(0,0,0,1));
|
||||||
|
bgPanel.calcTransform(CubicVR::mat4::identity());
|
||||||
|
bgPanel.draw();
|
||||||
|
}
|
||||||
|
|
||||||
bgPanel.setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground * 3.0, RGBA4f(0,0,0,0));
|
|
||||||
bgPanel.calcTransform(CubicVR::mat4::identity());
|
|
||||||
bgPanel.draw();
|
|
||||||
|
|
||||||
scopePanel.setMode(stereo?ScopePanel::SCOPE_MODE_2Y:ScopePanel::SCOPE_MODE_Y);
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glLoadMatrixf(CubicVR::mat4::perspective(45.0, 1.0, 1.0, 1000.0));
|
glLoadMatrixf(CubicVR::mat4::perspective(45.0, 1.0, 1.0, 1000.0));
|
||||||
@ -190,7 +190,7 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
|
|
||||||
spectrumPanel.setPosition(panelInterval+ctr, 0);
|
spectrumPanel.setPosition(panelInterval+ctr, 0);
|
||||||
if (spectrumVisible()) {
|
if (spectrumVisible()) {
|
||||||
spectrumPanel.setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground * 2.0, RGBA4f(0,0,0,0));
|
spectrumPanel.setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground * 2.0, RGBA4f(0,0,0,1));
|
||||||
spectrumPanel.contentsVisible = true;
|
spectrumPanel.contentsVisible = true;
|
||||||
roty = atan2(spectrumPanel.pos[0],1.2);
|
roty = atan2(spectrumPanel.pos[0],1.2);
|
||||||
spectrumPanel.rot[1] = -(roty * (180.0 / M_PI));
|
spectrumPanel.rot[1] = -(roty * (180.0 / M_PI));
|
||||||
@ -217,7 +217,9 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
glContext->DrawTunerTitles(ppmMode);
|
glContext->DrawTunerTitles(ppmMode);
|
||||||
glContext->DrawEnd();
|
glContext->DrawEnd();
|
||||||
|
|
||||||
SwapBuffers();
|
if (scopePanel.getMode() != ScopePanel::SCOPE_MODE_XY || spectrumVisible()) {
|
||||||
|
SwapBuffers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ public:
|
|||||||
ScopeCanvas(wxWindow *parent, int *attribList = NULL);
|
ScopeCanvas(wxWindow *parent, int *attribList = NULL);
|
||||||
~ScopeCanvas();
|
~ScopeCanvas();
|
||||||
|
|
||||||
void setStereo(bool state);
|
|
||||||
void setDeviceName(std::string device_name);
|
void setDeviceName(std::string device_name);
|
||||||
void setPPMMode(bool ppmMode);
|
void setPPMMode(bool ppmMode);
|
||||||
bool getPPMMode();
|
bool getPPMMode();
|
||||||
@ -50,7 +49,6 @@ private:
|
|||||||
GLPanel bgPanel;
|
GLPanel bgPanel;
|
||||||
ScopeContext *glContext;
|
ScopeContext *glContext;
|
||||||
std::string deviceName;
|
std::string deviceName;
|
||||||
bool stereo;
|
|
||||||
bool ppmMode;
|
bool ppmMode;
|
||||||
bool showDb;
|
bool showDb;
|
||||||
float panelSpacing;
|
float panelSpacing;
|
||||||
|
@ -12,10 +12,12 @@ ScopeContext::ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext) :
|
|||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScopeContext::DrawBegin() {
|
void ScopeContext::DrawBegin(bool clear) {
|
||||||
glClearColor(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g,
|
if (clear) {
|
||||||
ThemeMgr::mgr.currentTheme->scopeBackground.b, 1.0);
|
glClearColor(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g,
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
ThemeMgr::mgr.currentTheme->scopeBackground.b, 1.0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
glMatrixMode (GL_MODELVIEW);
|
glMatrixMode (GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
@ -11,7 +11,7 @@ class ScopeContext: public PrimaryGLContext {
|
|||||||
public:
|
public:
|
||||||
ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext);
|
ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext);
|
||||||
|
|
||||||
void DrawBegin();
|
void DrawBegin(bool clear=true);
|
||||||
void DrawTunerTitles(bool ppmMode=false);
|
void DrawTunerTitles(bool ppmMode=false);
|
||||||
void DrawDeviceName(std::string deviceName);
|
void DrawDeviceName(std::string deviceName);
|
||||||
void DrawDivider();
|
void DrawDivider();
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
#include <wx/numformatter.h>
|
#include <wx/numformatter.h>
|
||||||
|
|
||||||
#define MIN_BANDWIDTH 1500
|
|
||||||
|
|
||||||
wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas)
|
wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas)
|
||||||
EVT_PAINT(WaterfallCanvas::OnPaint)
|
EVT_PAINT(WaterfallCanvas::OnPaint)
|
||||||
EVT_KEY_DOWN(WaterfallCanvas::OnKeyDown)
|
EVT_KEY_DOWN(WaterfallCanvas::OnKeyDown)
|
||||||
@ -44,6 +42,7 @@ WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
|||||||
preBuf = false;
|
preBuf = false;
|
||||||
SetCursor(wxCURSOR_CROSS);
|
SetCursor(wxCURSOR_CROSS);
|
||||||
scaleMove = 0;
|
scaleMove = 0;
|
||||||
|
minBandwidth = 30000;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaterfallCanvas::~WaterfallCanvas() {
|
WaterfallCanvas::~WaterfallCanvas() {
|
||||||
@ -179,8 +178,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
|
|
||||||
if (currentZoom < 1) {
|
if (currentZoom < 1) {
|
||||||
bw = (long long) ceil((long double) bw * currentZoom);
|
bw = (long long) ceil((long double) bw * currentZoom);
|
||||||
if (bw < 30000) {
|
if (bw < minBandwidth) {
|
||||||
bw = 30000;
|
bw = minBandwidth;
|
||||||
}
|
}
|
||||||
if (mouseInView) {
|
if (mouseInView) {
|
||||||
long long mfreqA = getFrequencyAt(mpos);
|
long long mfreqA = getFrequencyAt(mpos);
|
||||||
@ -461,7 +460,7 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
|||||||
bwDiff = -bwDiff;
|
bwDiff = -bwDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentBW = demod->getBandwidth();
|
int currentBW = dragBW;
|
||||||
|
|
||||||
currentBW = currentBW + bwDiff;
|
currentBW = currentBW + bwDiff;
|
||||||
if (currentBW > CHANNELIZER_RATE_MAX) {
|
if (currentBW > CHANNELIZER_RATE_MAX) {
|
||||||
@ -472,6 +471,7 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
demod->setBandwidth(currentBW);
|
demod->setBandwidth(currentBW);
|
||||||
|
dragBW = currentBW;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dragState == WF_DRAG_FREQUENCY) {
|
if (dragState == WF_DRAG_FREQUENCY) {
|
||||||
@ -596,11 +596,13 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) {
|
|||||||
InteractiveCanvas::OnMouseDown(event);
|
InteractiveCanvas::OnMouseDown(event);
|
||||||
|
|
||||||
dragState = nextDragState;
|
dragState = nextDragState;
|
||||||
|
wxGetApp().getDemodMgr().updateLastState();
|
||||||
|
|
||||||
if (dragState && dragState != WF_DRAG_RANGE) {
|
if (dragState && dragState != WF_DRAG_RANGE) {
|
||||||
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
if (demod) {
|
if (demod) {
|
||||||
dragOfs = (long long) (mouseTracker.getMouseX() * (float) getBandwidth()) + getCenterFrequency() - (getBandwidth() / 2) - demod->getFrequency();
|
dragOfs = (long long) (mouseTracker.getMouseX() * (float) getBandwidth()) + getCenterFrequency() - (getBandwidth() / 2) - demod->getFrequency();
|
||||||
|
dragBW = demod->getBandwidth();
|
||||||
}
|
}
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getActiveDemodulator(), false);
|
wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getActiveDemodulator(), false);
|
||||||
}
|
}
|
||||||
@ -615,6 +617,7 @@ void WaterfallCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
|||||||
|
|
||||||
void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
||||||
InteractiveCanvas::OnMouseReleased(event);
|
InteractiveCanvas::OnMouseReleased(event);
|
||||||
|
wxGetApp().getDemodMgr().updateLastState();
|
||||||
|
|
||||||
bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL)
|
bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL)
|
||||||
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive());
|
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive());
|
||||||
@ -651,6 +654,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
|
|
||||||
if (dragState == WF_DRAG_NONE) {
|
if (dragState == WF_DRAG_NONE) {
|
||||||
if (!isNew && wxGetApp().getDemodMgr().getDemodulators().size()) {
|
if (!isNew && wxGetApp().getDemodMgr().getDemodulators().size()) {
|
||||||
|
mgr->updateLastState();
|
||||||
demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
} else {
|
} else {
|
||||||
isNew = true;
|
isNew = true;
|
||||||
@ -663,7 +667,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
|
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
|
||||||
demod->setGain(mgr->getLastGain());
|
demod->setGain(mgr->getLastGain());
|
||||||
demod->setMuted(mgr->isLastMuted());
|
demod->setMuted(mgr->isLastMuted());
|
||||||
|
demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType()));
|
||||||
demod->run();
|
demod->run();
|
||||||
|
|
||||||
wxGetApp().bindDemodulator(demod);
|
wxGetApp().bindDemodulator(demod);
|
||||||
@ -676,7 +680,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
|
|
||||||
demod->updateLabel(freq);
|
demod->updateLabel(freq);
|
||||||
demod->setFrequency(freq);
|
demod->setFrequency(freq);
|
||||||
|
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
setStatusText("New demodulator at frequency: %s", freq);
|
setStatusText("New demodulator at frequency: %s", freq);
|
||||||
} else {
|
} else {
|
||||||
@ -684,13 +688,14 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(demod, false);
|
wxGetApp().getDemodMgr().setActiveDemodulator(demod, false);
|
||||||
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);
|
||||||
} else {
|
} else {
|
||||||
if (activeDemod) {
|
if (activeDemod) {
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(activeDemod, false);
|
wxGetApp().getDemodMgr().setActiveDemodulator(activeDemod, false);
|
||||||
|
mgr->updateLastState();
|
||||||
activeDemod->setTracking(true);
|
activeDemod->setTracking(true);
|
||||||
nextDragState = WF_DRAG_FREQUENCY;
|
nextDragState = WF_DRAG_FREQUENCY;
|
||||||
} else {
|
} else {
|
||||||
@ -740,6 +745,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
|
|
||||||
|
|
||||||
if (!isNew && wxGetApp().getDemodMgr().getDemodulators().size()) {
|
if (!isNew && wxGetApp().getDemodMgr().getDemodulators().size()) {
|
||||||
|
mgr->updateLastState();
|
||||||
demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
} else {
|
} else {
|
||||||
demod = wxGetApp().getDemodMgr().newThread();
|
demod = wxGetApp().getDemodMgr().newThread();
|
||||||
@ -749,6 +755,8 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
demod->setSquelchLevel(mgr->getLastSquelchLevel());
|
demod->setSquelchLevel(mgr->getLastSquelchLevel());
|
||||||
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
|
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
|
||||||
demod->setGain(mgr->getLastGain());
|
demod->setGain(mgr->getLastGain());
|
||||||
|
demod->setMuted(mgr->isLastMuted());
|
||||||
|
demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType()));
|
||||||
|
|
||||||
demod->run();
|
demod->run();
|
||||||
|
|
||||||
@ -765,7 +773,8 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
demod->updateLabel(freq);
|
demod->updateLabel(freq);
|
||||||
demod->setFrequency(freq);
|
demod->setFrequency(freq);
|
||||||
demod->setBandwidth(bw);
|
demod->setBandwidth(bw);
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(demod, false);
|
mgr->setActiveDemodulator(demod, false);
|
||||||
|
mgr->updateLastState();
|
||||||
}
|
}
|
||||||
|
|
||||||
dragState = WF_DRAG_NONE;
|
dragState = WF_DRAG_NONE;
|
||||||
@ -842,4 +851,6 @@ void WaterfallCanvas::setLinesPerSecond(int lps) {
|
|||||||
tex_update.unlock();
|
tex_update.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WaterfallCanvas::setMinBandwidth(int min) {
|
||||||
|
minBandwidth = min;
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@ public:
|
|||||||
SpectrumVisualDataQueue *getVisualDataQueue();
|
SpectrumVisualDataQueue *getVisualDataQueue();
|
||||||
|
|
||||||
void setLinesPerSecond(int lps);
|
void setLinesPerSecond(int lps);
|
||||||
|
void setMinBandwidth(int min);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnPaint(wxPaintEvent& event);
|
void OnPaint(wxPaintEvent& event);
|
||||||
@ -68,12 +69,14 @@ private:
|
|||||||
float hoverAlpha;
|
float hoverAlpha;
|
||||||
int linesPerSecond;
|
int linesPerSecond;
|
||||||
float scaleMove;
|
float scaleMove;
|
||||||
|
int dragBW;
|
||||||
|
|
||||||
SpectrumVisualDataQueue visualDataQueue;
|
SpectrumVisualDataQueue visualDataQueue;
|
||||||
Timer gTimer;
|
Timer gTimer;
|
||||||
double lpsIndex;
|
double lpsIndex;
|
||||||
bool preBuf;
|
bool preBuf;
|
||||||
std::mutex tex_update;
|
std::mutex tex_update;
|
||||||
|
int minBandwidth;
|
||||||
// event table
|
// event table
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user