Allow modems to limit/control input rate

- Modems can now over-ride user rate input and lock/step as needed
- Separate digital code defs a bit more so it’s not required when
disabled
- Testing FSK based on @andresv ’s example at
https://github.com/jgaeddert/liquid-dsp/issues/9
This commit is contained in:
Charles J. Cliffe 2015-11-22 19:56:25 -05:00
parent 724808d9ff
commit c0eca0b2f3
26 changed files with 242 additions and 105 deletions

View File

@ -237,16 +237,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 +286,23 @@ 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/modules/modem/digital/ModemASK.cpp
src/modules/modem/digital/ModemAPSK.cpp
src/modules/modem/digital/ModemBPSK.cpp
src/modules/modem/digital/ModemDPSK.cpp
src/modules/modem/digital/ModemFSK.cpp
src/modules/modem/digital/ModemPSK.cpp
src/modules/modem/digital/ModemOOK.cpp
src/modules/modem/digital/ModemST.cpp
src/modules/modem/digital/ModemSQAM.cpp
src/modules/modem/digital/ModemQAM.cpp
src/modules/modem/digital/ModemQPSK.cpp
)
ENDIF()
SET (cubicsdr_headers SET (cubicsdr_headers
src/CubicSDRDefs.h src/CubicSDRDefs.h
src/CubicSDR.h src/CubicSDR.h
@ -316,16 +323,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 +388,23 @@ SET (cubicsdr_headers
external/cubicvr2/math/vec4.h external/cubicvr2/math/vec4.h
) )
IF(ENABLE_DIGITAL_LAB)
SET(cubicsdr_headers
${cubicsdr_headers}
src/modules/modem/digital/ModemASK.h
src/modules/modem/digital/ModemAPSK.h
src/modules/modem/digital/ModemBPSK.h
src/modules/modem/digital/ModemDPSK.h
src/modules/modem/digital/ModemFSK.h
src/modules/modem/digital/ModemPSK.h
src/modules/modem/digital/ModemOOK.h
src/modules/modem/digital/ModemST.h
src/modules/modem/digital/ModemSQAM.h
src/modules/modem/digital/ModemQAM.h
src/modules/modem/digital/ModemQPSK.h
)
ENDIF()
SET (CUBICSDR_RESOURCES 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
@ -414,7 +428,9 @@ 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}")
IF(ENABLE_DIGITAL_LAB)
SOURCE_GROUP("Modem-Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}") SOURCE_GROUP("Modem-Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}")
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}")

View File

@ -85,11 +85,12 @@ AppFrame::AppFrame() :
demodModeSelectorAdv->addChoice(2, "BPSK"); demodModeSelectorAdv->addChoice(2, "BPSK");
demodModeSelectorAdv->addChoice(3, "DPSK"); demodModeSelectorAdv->addChoice(3, "DPSK");
demodModeSelectorAdv->addChoice(4, "PSK"); demodModeSelectorAdv->addChoice(4, "PSK");
demodModeSelectorAdv->addChoice(5, "OOK"); demodModeSelectorAdv->addChoice(5, "FSK");
demodModeSelectorAdv->addChoice(6, "ST"); demodModeSelectorAdv->addChoice(6, "OOK");
demodModeSelectorAdv->addChoice(7, "SQAM"); demodModeSelectorAdv->addChoice(7, "ST");
demodModeSelectorAdv->addChoice(8, "QAM"); demodModeSelectorAdv->addChoice(8, "SQAM");
demodModeSelectorAdv->addChoice(9, "QPSK"); demodModeSelectorAdv->addChoice(9, "QAM");
demodModeSelectorAdv->addChoice(10, "QPSK");
demodModeSelectorAdv->setHelpTip("Choose advanced modulation types."); demodModeSelectorAdv->setHelpTip("Choose advanced modulation types.");
demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0); demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0);

View File

@ -172,17 +172,20 @@ 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);
Modem::addModemFactory(new ModemFSK);
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;

View File

@ -37,16 +37,19 @@
#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"
#include "ModemFSK.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>

View File

@ -14,7 +14,6 @@ DemodulatorInstance::DemodulatorInstance() :
follow.store(false); follow.store(false);
currentAudioSampleRate.store(0); currentAudioSampleRate.store(0);
currentFrequency.store(0); currentFrequency.store(0);
currentBandwidth.store(0);
currentOutputDevice.store(-1); currentOutputDevice.store(-1);
currentAudioGain.store(1.0); currentAudioGain.store(1.0);
@ -24,7 +23,7 @@ DemodulatorInstance::DemodulatorInstance() :
pipeDemodCommand = new DemodulatorThreadCommandQueue; pipeDemodCommand = new DemodulatorThreadCommandQueue;
pipeDemodNotify = new DemodulatorThreadCommandQueue; pipeDemodNotify = new DemodulatorThreadCommandQueue;
demodulatorPreThread = new DemodulatorPreThread(); 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);
@ -254,12 +253,6 @@ 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; currentDemodType = demod_type_in;
@ -274,7 +267,6 @@ void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) {
demodulatorPreThread->getParams().demodType = currentDemodType; demodulatorPreThread->getParams().demodType = currentDemodType;
if (!active) { if (!active) {
checkBandwidth();
demodulatorPreThread->setDemodType(currentDemodType); demodulatorPreThread->setDemodType(currentDemodType);
} else if (demodulatorThread && threadQueueControl) { } else if (demodulatorThread && threadQueueControl) {
demodulatorPreThread->setDemodType(currentDemodType); demodulatorPreThread->setDemodType(currentDemodType);
@ -318,32 +310,18 @@ int DemodulatorInstance::getDemodulatorCons() {
} }
void DemodulatorInstance::setBandwidth(int bw) { void DemodulatorInstance::setBandwidth(int bw) {
if (currentDemodType == "I/Q") {
if (currentAudioSampleRate) {
bw = currentAudioSampleRate;
} else {
bw = AudioThread::deviceSampleRate[getOutputDevice()];
}
}
if (!active && demodulatorPreThread != NULL) { if (!active && demodulatorPreThread != NULL) {
currentBandwidth = bw; demodulatorPreThread->getParams().bandwidth = bw;
checkBandwidth();
demodulatorPreThread->getParams().bandwidth = currentBandwidth;
} else if (demodulatorPreThread && pipeDemodCommand) { } else if (demodulatorPreThread && pipeDemodCommand) {
DemodulatorThreadCommand command; DemodulatorThreadCommand command;
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH; command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH;
currentBandwidth = bw; command.llong_value = bw;
checkBandwidth();
command.llong_value = currentBandwidth;
pipeDemodCommand->push(command); pipeDemodCommand->push(command);
} }
} }
int DemodulatorInstance::getBandwidth() { int DemodulatorInstance::getBandwidth() {
if (!currentBandwidth) { return demodulatorPreThread->getParams().bandwidth;
currentBandwidth = demodulatorPreThread->getParams().bandwidth;
}
return currentBandwidth;
} }
void DemodulatorInstance::setFrequency(long long freq) { void DemodulatorInstance::setFrequency(long long freq) {
@ -387,9 +365,9 @@ void DemodulatorInstance::setAudioSampleRate(int sampleRate) {
} }
int DemodulatorInstance::getAudioSampleRate() { int DemodulatorInstance::getAudioSampleRate() {
if (!currentAudioSampleRate) { currentAudioSampleRate = audioThread->getSampleRate();
currentAudioSampleRate = audioThread->getSampleRate(); demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate;
}
return currentAudioSampleRate; return currentAudioSampleRate;
} }

View File

@ -97,8 +97,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; //
@ -109,7 +107,6 @@ private:
std::atomic_bool muted; std::atomic_bool muted;
std::atomic_llong currentFrequency; std::atomic_llong currentFrequency;
std::atomic_int currentBandwidth;
std::string currentDemodType; std::string currentDemodType;
std::atomic_int currentOutputDevice; std::atomic_int currentOutputDevice;
std::atomic_int currentAudioSampleRate; std::atomic_int currentAudioSampleRate;

View File

@ -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), commandQueue(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;
@ -82,11 +84,7 @@ void DemodulatorPreThread::run() {
if (command.llong_value < 1500) { if (command.llong_value < 1500) {
command.llong_value = 1500; command.llong_value = 1500;
} }
if (command.llong_value > params.sampleRate) { tempParams.bandwidth = command.llong_value;
tempParams.bandwidth = params.sampleRate;
} else {
tempParams.bandwidth = command.llong_value;
}
bandwidthChanged = true; bandwidthChanged = true;
break; break;
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY: case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY:
@ -257,6 +255,7 @@ void DemodulatorPreThread::setParams(DemodulatorThreadParameters &params_in) {
void DemodulatorPreThread::setDemodType(std::string demodType) { void DemodulatorPreThread::setDemodType(std::string demodType) {
this->newDemodType = demodType; this->newDemodType = demodType;
DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD); DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD);
command.sampleRate = params.sampleRate;
command.demodType = demodType; command.demodType = demodType;
command.bandwidth = params.bandwidth; command.bandwidth = params.bandwidth;
command.audioSampleRate = params.audioSampleRate; command.audioSampleRate = params.audioSampleRate;

View File

@ -7,10 +7,12 @@
#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();
@ -28,6 +30,7 @@ public:
ModemKit *getModemKit(); ModemKit *getModemKit();
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;

View File

@ -26,62 +26,62 @@ 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; cModemType = demodCommand.demodType;
result.sampleRate = demodCommand.sampleRate;
} }
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;
} }
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;
resultQueue->push(result); resultQueue->push(result);

View File

@ -44,6 +44,7 @@ public:
Modem(); Modem();
virtual ~Modem(); virtual ~Modem();
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;

View File

@ -8,6 +8,10 @@ std::string ModemAnalog::getType() {
return "analog"; return "analog";
} }
int ModemAnalog::checkSampleRate(long long sampleRate, int audioSampleRate) {
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;

View File

@ -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;

View File

@ -8,6 +8,10 @@ std::string ModemDigital::getType() {
return "digital"; return "digital";
} }
int ModemDigital::checkSampleRate(long long sampleRate, int audioSampleRate) {
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;

View File

@ -13,10 +13,11 @@ class ModemDigital : public Modem {
public: public:
ModemDigital(); ModemDigital();
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 digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input); virtual void disposeKit(ModemKit *kit);
void digitalFinish(ModemKitDigital *kit, modem mod); 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();

View File

@ -30,6 +30,14 @@ Modem *ModemFMStereo::factory() {
return new ModemFMStereo; return new ModemFMStereo;
} }
int ModemFMStereo::checkSampleRate(long long sampleRate, int audioSampleRate) {
if (sampleRate < 100000) {
return 100000;
} else {
return sampleRate;
}
}
ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) { ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) {
ModemKitFMStereo *kit = new ModemKitFMStereo; ModemKitFMStereo *kit = new ModemKitFMStereo;

View File

@ -23,6 +23,7 @@ public:
std::string getType(); std::string getType();
std::string getName(); std::string getName();
Modem *factory(); Modem *factory();
int checkSampleRate(long long sampleRate, int audioSampleRate);
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);

View File

@ -10,6 +10,8 @@ Modem *ModemIQ::factory() {
ModemKit *ModemIQ::buildKit(long long sampleRate, int audioSampleRate) { ModemKit *ModemIQ::buildKit(long long sampleRate, int audioSampleRate) {
ModemKit *kit = new ModemKit; ModemKit *kit = new ModemKit;
kit->sampleRate = sampleRate;
kit->audioSampleRate = audioSampleRate;
return kit; return kit;
} }
@ -25,6 +27,10 @@ void ModemIQ::disposeKit(ModemKit *kit) {
delete kit; delete kit;
} }
int ModemIQ::checkSampleRate(long long sampleRate, int audioSampleRate) {
return audioSampleRate;
}
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();

View File

@ -8,6 +8,7 @@ public:
std::string getName(); std::string getName();
Modem *factory(); Modem *factory();
ModemKit *buildKit(long long sampleRate, int audioSampleRate); ModemKit *buildKit(long long sampleRate, int audioSampleRate);
int checkSampleRate(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);

View File

@ -19,6 +19,13 @@ ModemLSB::~ModemLSB() {
ampmodem_destroy(demodAM_LSB); ampmodem_destroy(demodAM_LSB);
} }
int ModemLSB::checkSampleRate(long long sampleRate, int audioSampleRate) {
if (sampleRate % 2 == 0) {
return sampleRate;
}
return sampleRate+1;
}
void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitAnalog *akit = (ModemKitAnalog *)kit; ModemKitAnalog *akit = (ModemKitAnalog *)kit;

View File

@ -8,6 +8,7 @@ public:
~ModemLSB(); ~ModemLSB();
std::string getName(); std::string getName();
Modem *factory(); Modem *factory();
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:

View File

@ -19,6 +19,13 @@ ModemUSB::~ModemUSB() {
ampmodem_destroy(demodAM_USB); ampmodem_destroy(demodAM_USB);
} }
int ModemUSB::checkSampleRate(long long sampleRate, int audioSampleRate) {
if (sampleRate % 2 == 0) {
return sampleRate;
}
return sampleRate+1;
}
void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitAnalog *akit = (ModemKitAnalog *)kit; ModemKitAnalog *akit = (ModemKitAnalog *)kit;

View File

@ -7,6 +7,7 @@ public:
~ModemUSB(); ~ModemUSB();
std::string getName(); std::string getName();
Modem *factory(); Modem *factory();
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:

View File

@ -0,0 +1,62 @@
#include "ModemFSK.h"
ModemFSK::ModemFSK() {
demodulatorCons.store(2);
currentDemodCons.store(0);
updateDemodulatorCons(2);
}
Modem *ModemFSK::factory() {
return new ModemFSK;
}
ModemKit *ModemFSK::buildKit(long long sampleRate, int audioSampleRate) {
ModemKitFSK *dkit = new ModemKitFSK;
dkit->m = 1;
dkit->k = sampleRate / 9600;
dkit->bandwidth = 7000.0 / sampleRate;
dkit->demodFSK = fskdem_create(dkit->m, dkit->k, dkit->bandwidth);
dkit->sampleRate = sampleRate;
dkit->audioSampleRate = audioSampleRate;
return dkit;
}
void ModemFSK::disposeKit(ModemKit *kit) {
ModemKitFSK *dkit = (ModemKitFSK *)kit;
delete dkit;
}
std::string ModemFSK::getName() {
return "FSK";
}
ModemFSK::~ModemFSK() {
}
void ModemFSK::updateDemodulatorCons(int cons) {
}
void ModemFSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitFSK *dkit = (ModemKitFSK *)kit;
digitalStart(dkit, nullptr, input);
dkit->inputBuffer.insert(dkit->inputBuffer.end(),input->data.begin(),input->data.end());
while (dkit->inputBuffer.size() >= dkit->k) {
unsigned int sym_out;
sym_out = fskdem_demodulate(dkit->demodFSK, &dkit->inputBuffer[0]);
// std::cout << "ferror: " << fskdem_get_frequency_error(dkit->demodFSK) << std::endl;
printf("%01X", sym_out);
dkit->inputBuffer.erase(dkit->inputBuffer.begin(),dkit->inputBuffer.begin()+dkit->k);
}
digitalFinish(dkit, nullptr);
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "ModemDigital.h"
class ModemKitFSK : public ModemKitDigital {
public:
float sps, spacing, bandwidth;
unsigned int m, k;
fskdem demodFSK;
std::vector<liquid_float_complex> inputBuffer;
};
class ModemFSK : public ModemDigital {
public:
ModemFSK();
~ModemFSK();
std::string getName();
Modem *factory();
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
void disposeKit(ModemKit *kit);
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
fskdem dem;
};

View File

@ -461,7 +461,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 +472,7 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
} }
demod->setBandwidth(currentBW); demod->setBandwidth(currentBW);
dragBW = currentBW;
} }
if (dragState == WF_DRAG_FREQUENCY) { if (dragState == WF_DRAG_FREQUENCY) {
@ -601,6 +602,7 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) {
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);
} }

View File

@ -68,6 +68,7 @@ private:
float hoverAlpha; float hoverAlpha;
int linesPerSecond; int linesPerSecond;
float scaleMove; float scaleMove;
int dragBW;
SpectrumVisualDataQueue visualDataQueue; SpectrumVisualDataQueue visualDataQueue;
Timer gTimer; Timer gTimer;