New radio module

pull/538/head
AlexandreRouma 2021-12-04 17:46:48 +01:00
rodzic 62d2dfafd7
commit fe285c71ff
11 zmienionych plików z 125 dodań i 47 usunięć

Wyświetl plik

@ -37,6 +37,7 @@ option(OPT_BUILD_FALCON9_DECODER "Build the falcon9 live decoder (Dependencies:
option(OPT_BUILD_M17_DECODER "Build the M17 decoder module (no dependencies required)" OFF)
option(OPT_BUILD_METEOR_DEMODULATOR "Build the meteor demodulator module (no dependencies required)" ON)
option(OPT_BUILD_RADIO "Main audio modulation decoder (AM, FM, SSB, etc...)" ON)
option(OPT_BUILD_NEW_RADIO "Beta Main audio modulation decoder (AM, FM, SSB, etc...)" ON)
option(OPT_BUILD_WEATHER_SAT_DECODER "Build the HRPT decoder module (no dependencies required)" OFF)
# Misc
@ -145,9 +146,12 @@ endif (OPT_BUILD_METEOR_DEMODULATOR)
if (OPT_BUILD_RADIO)
add_subdirectory("decoder_modules/radio")
add_subdirectory("decoder_modules/new_radio")
endif (OPT_BUILD_RADIO)
if (OPT_BUILD_NEW_RADIO)
add_subdirectory("decoder_modules/new_radio")
endif (OPT_BUILD_NEW_RADIO)
if (OPT_BUILD_WEATHER_SAT_DECODER)
add_subdirectory("decoder_modules/weather_sat_decoder")
endif (OPT_BUILD_WEATHER_SAT_DECODER)

Wyświetl plik

@ -16,12 +16,13 @@ namespace demod {
class Demodulator {
public:
virtual ~Demodulator() {}
virtual void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) = 0;
virtual void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) = 0;
virtual void start() = 0;
virtual void stop() = 0;
virtual void showMenu() = 0;
virtual void setBandwidth(double bandwidth) = 0;
virtual void setInput(dsp::stream<dsp::complex_t>* input) = 0;
virtual void AFSampRateChanged(double newSR) = 0;
virtual const char* getName() = 0;
virtual double getIFSampleRate() = 0;
virtual double getAFSampleRate() = 0;
@ -33,8 +34,10 @@ namespace demod {
virtual double getDefaultSnapInterval() = 0;
virtual int getVFOReference() = 0;
virtual bool getDeempAllowed() = 0;
virtual bool getPostProcEnabled() = 0;
virtual int getDefaultDeemphasisMode() = 0;
virtual double getAFBandwidth(double bandwidth) = 0;
virtual bool getDynamicAFBandwidth() = 0;
virtual dsp::stream<dsp::stereo_t>* getOutput() = 0;
};
@ -46,4 +49,5 @@ namespace demod {
#include "demodulators/usb.h"
#include "demodulators/lsb.h"
#include "demodulators/dsb.h"
#include "demodulators/cw.h"
#include "demodulators/cw.h"
#include "demodulators/raw.h"

Wyświetl plik

@ -8,15 +8,15 @@ namespace demod {
public:
AM() {}
AM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
init(name, config, input, bandwidth, outputChangeHandler);
AM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
}
~AM() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
this->name = name;
this->outputChangeHandler = outputChangeHandler;
@ -48,6 +48,8 @@ namespace demod {
demod.setInput(input);
}
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "AM"; }
@ -61,6 +63,7 @@ namespace demod {
double getDefaultSnapInterval() { return 1000.0; }
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
bool getDeempAllowed() { return false; }
bool getPostProcEnabled() { return true; }
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
double getAFBandwidth(double bandwidth) { return bandwidth / 2.0; }
bool getDynamicAFBandwidth() { return true; }

Wyświetl plik

@ -8,15 +8,15 @@ namespace demod {
public:
CW() {}
CW(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
init(name, config, input, bandwidth, outputChangeHandler);
CW(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
}
~CW() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
this->name = name;
this->outputChangeHandler = outputChangeHandler;
@ -49,6 +49,8 @@ namespace demod {
xlator.setInput(input);
}
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "CW"; }
@ -62,6 +64,7 @@ namespace demod {
double getDefaultSnapInterval() { return 10.0; }
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
bool getDeempAllowed() { return false; }
bool getPostProcEnabled() { return true; }
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
double getAFBandwidth(double bandwidth) { return (bandwidth / 2.0) + 1000.0; }
bool getDynamicAFBandwidth() { return true; }

Wyświetl plik

@ -8,15 +8,15 @@ namespace demod {
public:
DSB() {}
DSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
init(name, config, input, bandwidth, outputChangeHandler);
DSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
}
~DSB() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
this->name = name;
this->outputChangeHandler = outputChangeHandler;
@ -50,6 +50,8 @@ namespace demod {
demod.setInput(input);
}
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "DSB"; }
@ -63,6 +65,7 @@ namespace demod {
double getDefaultSnapInterval() { return 100.0; }
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
bool getDeempAllowed() { return false; }
bool getPostProcEnabled() { return true; }
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
double getAFBandwidth(double bandwidth) { return bandwidth / 2.0; }
bool getDynamicAFBandwidth() { return true; }

Wyświetl plik

@ -8,15 +8,15 @@ namespace demod {
public:
LSB() {}
LSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
init(name, config, input, bandwidth, outputChangeHandler);
LSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
}
~LSB() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
this->name = name;
this->outputChangeHandler = outputChangeHandler;
@ -50,6 +50,8 @@ namespace demod {
demod.setInput(input);
}
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "LSB"; }
@ -63,6 +65,7 @@ namespace demod {
double getDefaultSnapInterval() { return 100.0; }
int getVFOReference() { return ImGui::WaterfallVFO::REF_UPPER; }
bool getDeempAllowed() { return false; }
bool getPostProcEnabled() { return true; }
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
double getAFBandwidth(double bandwidth) { return bandwidth; }
bool getDynamicAFBandwidth() { return true; }

Wyświetl plik

@ -8,15 +8,15 @@ namespace demod {
public:
NFM() {}
NFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
init(name, config, input, bandwidth, outputChangeHandler);
NFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
}
~NFM() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
this->name = name;
this->outputChangeHandler = outputChangeHandler;
@ -42,6 +42,8 @@ namespace demod {
demod.setInput(input);
}
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "FM"; }
@ -55,6 +57,7 @@ namespace demod {
double getDefaultSnapInterval() { return 2500.0; }
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
bool getDeempAllowed() { return true; }
bool getPostProcEnabled() { return true; }
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
double getAFBandwidth(double bandwidth) { return bandwidth / 2.0; }
bool getDynamicAFBandwidth() { return true; }

Wyświetl plik

@ -8,15 +8,15 @@ namespace demod {
public:
USB() {}
USB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
init(name, config, input, bandwidth, outputChangeHandler);
USB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
}
~USB() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
this->name = name;
this->outputChangeHandler = outputChangeHandler;
@ -50,6 +50,8 @@ namespace demod {
demod.setInput(input);
}
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "USB"; }
@ -63,6 +65,7 @@ namespace demod {
double getDefaultSnapInterval() { return 100.0; }
int getVFOReference() { return ImGui::WaterfallVFO::REF_LOWER; }
bool getDeempAllowed() { return false; }
bool getPostProcEnabled() { return true; }
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
double getAFBandwidth(double bandwidth) { return bandwidth; }
bool getDynamicAFBandwidth() { return true; }

Wyświetl plik

@ -8,15 +8,15 @@ namespace demod {
public:
WFM() {}
WFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
init(name, config, input, bandwidth, outputChangeHandler);
WFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
}
~WFM() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
this->name = name;
this->outputChangeHandler = outputChangeHandler;
_config = config;
@ -66,6 +66,8 @@ namespace demod {
demodStereo.setInput(input);
}
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "WFM"; }
@ -79,6 +81,7 @@ namespace demod {
double getDefaultSnapInterval() { return 100000.0; }
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
bool getDeempAllowed() { return true; }
bool getPostProcEnabled() { return true; }
int getDefaultDeemphasisMode() { return DEEMP_MODE_50US; }
double getAFBandwidth(double bandwidth) { return 16000.0; }
bool getDynamicAFBandwidth() { return false; }

Wyświetl plik

@ -42,6 +42,7 @@ public:
demods[RADIO_DEMOD_LSB] = new demod::LSB();
demods[RADIO_DEMOD_DSB] = new demod::DSB();
demods[RADIO_DEMOD_CW] = new demod::CW();
demods[RADIO_DEMOD_RAW] = new demod::RAW();
// Initialize the VFO
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 200000, 200000, 50000, 200000, false);
@ -74,7 +75,7 @@ public:
bw = std::clamp<double>(bw, demod->getMinBandwidth(), demod->getMaxBandwidth());
// Initialize
demod->init(name, &config, &squelch.out, bw, _demodOutputChangeHandler);
demod->init(name, &config, &squelch.out, bw, _demodOutputChangeHandler, stream.getSampleRate());
}
// Initialize DSP
@ -87,13 +88,10 @@ public:
// Select the demodulator
selectDemodByID((DemodID)selectedDemodID);
// Start DSP
squelch.start();
resamp.start();
deemp.start();
// Start stream, the rest was started when selecting the demodulator
stream.start();
gui::menu.registerEntry(name, menuHandler, this, NULL);
gui::menu.registerEntry(name, menuHandler, this, this);
}
~RadioModule() {
@ -104,10 +102,20 @@ public:
void enable() {
enabled = true;
if (!vfo) {
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 200000, 200000, 50000, 200000, false);
}
selectDemodByID((DemodID)selectedDemodID);
}
void disable() {
enabled = false;
squelch.stop();
if (selectedDemod) { selectedDemod->stop(); }
resamp.stop();
deemp.stop();
if (vfo) { sigpath::vfoManager.deleteVFO(vfo); }
vfo = NULL;
}
bool isEnabled() {
@ -239,6 +247,9 @@ private:
if (selectedDemod) { selectedDemod->stop(); }
selectedDemod = demod;
// Give the demodulator the most recent audio SR
selectedDemod->AFSampRateChanged(audioSampleRate);
// Load config
bandwidth = selectedDemod->getDefaultBandwidth();
minBandwidth = selectedDemod->getMinBandwidth();
@ -246,6 +257,7 @@ private:
bandwidthLocked = selectedDemod->getBandwidthLocked();
snapInterval = selectedDemod->getDefaultSnapInterval();
squelchLevel = MIN_SQUELCH;
deempAllowed = selectedDemod->getDeempAllowed();
deempMode = DEEMP_MODE_NONE;
squelchEnabled = false;
if (config.conf[name][selectedDemod->getName()].contains("snapInterval")) {
@ -268,7 +280,7 @@ private:
// Configure VFO
if (vfo) {
vfo->setBandwidthLimits(minBandwidth, maxBandwidth, false);
vfo->setBandwidthLimits(minBandwidth, maxBandwidth, selectedDemod->getBandwidthLocked());
vfo->setReference(selectedDemod->getVFOReference());
vfo->setSnapInterval(snapInterval);
vfo->setSampleRate(selectedDemod->getIFSampleRate(), bandwidth);
@ -278,33 +290,38 @@ private:
squelch.setLevel(squelchLevel);
setSquelchEnabled(squelchEnabled);
// Configure resampler
resamp.stop();
resamp.setInput(selectedDemod->getOutput());
resamp.setInSampleRate(selectedDemod->getAFSampleRate());
setAudioSampleRate(audioSampleRate);
resamp.start();
// Enable or disable post processing entirely depending on the demodulator's options
setPostProcEnabled(selectedDemod->getPostProcEnabled());
// Configure deemphasis
deempAllowed = selectedDemod->getDeempAllowed();
if (deempAllowed) {
setDeemphasisMode(deempMode);
}
else {
setDeemphasisMode(DEEMP_MODE_NONE);
if (postProcEnabled) {
// Configure resampler
resamp.stop();
resamp.setInput(selectedDemod->getOutput());
resamp.setInSampleRate(selectedDemod->getAFSampleRate());
setAudioSampleRate(audioSampleRate);
// Configure deemphasis
if (deempAllowed) {
setDeemphasisMode(deempMode);
}
else {
setDeemphasisMode(DEEMP_MODE_NONE);
}
}
// Start new demodulator
selectedDemod->start();
}
void setBandwidth(double bw) {
bandwidth = bw;
if (!selectedDemod) { return; }
float audioBW = std::min<float>(selectedDemod->getMaxAFBandwidth(), selectedDemod->getAFBandwidth(bandwidth));
audioBW = std::min<float>(audioBW, audioSampleRate / 2.0);
vfo->setBandwidth(bandwidth);
selectedDemod->setBandwidth(bandwidth);
if (selectedDemod->getDynamicAFBandwidth()) {
if (selectedDemod->getDynamicAFBandwidth() && postProcEnabled) {
win.setCutoff(audioBW);
win.setTransWidth(audioBW);
resamp.updateWindow(&win);
@ -317,7 +334,17 @@ private:
void setAudioSampleRate(double sr) {
audioSampleRate = sr;
if (!selectedDemod) { return; }
selectedDemod->AFSampRateChanged(audioSampleRate);
if (!postProcEnabled) {
minBandwidth = selectedDemod->getMinBandwidth();
maxBandwidth = selectedDemod->getMaxBandwidth();
bandwidth = selectedDemod->getIFSampleRate();
vfo->setBandwidthLimits(minBandwidth, maxBandwidth, selectedDemod->getBandwidthLocked());
vfo->setSampleRate(selectedDemod->getIFSampleRate(), bandwidth);
return;
}
float audioBW = std::min<float>(selectedDemod->getMaxAFBandwidth(), selectedDemod->getAFBandwidth(bandwidth));
audioBW = std::min<float>(audioBW, audioSampleRate / 2.0);
resamp.stop();
deemp.stop();
deemp.setSampleRate(audioSampleRate);
@ -330,9 +357,23 @@ private:
if (deempMode != DEEMP_MODE_NONE) { deemp.start(); }
}
void setPostProcEnabled(bool enable) {
postProcEnabled = enable;
if (!selectedDemod) { return; }
if (postProcEnabled) {
setDeemphasisMode(deempMode);
}
else {
resamp.stop();
deemp.stop();
stream.setInput(selectedDemod->getOutput());
}
}
void setDeemphasisMode(int mode) {
deempMode = mode;
if (mode != DEEMP_MODE_NONE) {
if (!postProcEnabled) { return; }
if (deempMode != DEEMP_MODE_NONE) {
// TODO: Investigate why not stopping the deemp here causes the DSP to stall
deemp.stop();
stream.setInput(&deemp.out);
@ -349,6 +390,7 @@ private:
squelchEnabled = enable;
if (!selectedDemod) { return; }
if (squelchEnabled) {
squelch.setInput(vfo->output);
selectedDemod->setInput(&squelch.out);
squelch.start();
}
@ -370,7 +412,12 @@ private:
static void demodOutputChangeHandler(dsp::stream<dsp::stereo_t>* output, void* ctx) {
RadioModule* _this = (RadioModule*)ctx;
_this->resamp.setInput(output);
if (_this->postProcEnabled) {
_this->resamp.setInput(output);
}
else {
_this->stream.setInput(output);
}
}
EventHandler<double> onUserChangedBandwidthHandler;
@ -398,6 +445,7 @@ private:
int selectedDemodID = 1;
int deempMode = DEEMP_MODE_NONE;
bool deempAllowed;
bool postProcEnabled;
const double MIN_SQUELCH = -100.0;
const double MAX_SQUELCH = 0.0;

Wyświetl plik

@ -57,6 +57,7 @@ cp "C:/Program Files/codec2/lib/libcodec2.dll" sdrpp_windows_x64/
cp $build_dir/decoder_modules/meteor_demodulator/Release/meteor_demodulator.dll sdrpp_windows_x64/modules/
cp $build_dir/decoder_modules/radio/Release/radio.dll sdrpp_windows_x64/modules/
cp $build_dir/decoder_modules/radio/Release/new_radio.dll sdrpp_windows_x64/modules/
# Copy misc modules