mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-11-06 10:47:34 +01:00
Added squelch to radio
This commit is contained in:
parent
2c729bf646
commit
774663d70d
@ -70,10 +70,50 @@ int sdrpp_main() {
|
||||
|
||||
spdlog::info("SDR++ v" VERSION_STR);
|
||||
|
||||
// ======== DEFAULT CONFIG ========
|
||||
json defConfig;
|
||||
defConfig["bandColors"]["amateur"] = "#FF0000FF";
|
||||
defConfig["bandColors"]["aviation"] = "#00FF00FF";
|
||||
defConfig["bandColors"]["broadcast"] = "#0000FFFF";
|
||||
defConfig["bandColors"]["marine"] = "#00FFFFFF";
|
||||
defConfig["bandColors"]["military"] = "#FFFF00FF";
|
||||
defConfig["bandPlan"] = "General";
|
||||
defConfig["bandPlanEnabled"] = true;
|
||||
defConfig["centerTuning"] = true;
|
||||
defConfig["fftHeight"] = 300;
|
||||
defConfig["frequency"] = 100000000.0;
|
||||
defConfig["max"] = 0.0;
|
||||
defConfig["maximized"] = false;
|
||||
defConfig["menuOrder"] = {
|
||||
"Source",
|
||||
"Radio",
|
||||
"Recorder",
|
||||
"Sinks",
|
||||
"Audio",
|
||||
"Scripting",
|
||||
"Band Plan",
|
||||
"Display"
|
||||
};
|
||||
defConfig["menuWidth"] = 300;
|
||||
defConfig["min"] = -70.0;
|
||||
defConfig["moduleInstances"]["Audio Sink"] = "audio_sink";
|
||||
defConfig["moduleInstances"]["PlutoSDR Source"] = "plutosdr_source";
|
||||
defConfig["moduleInstances"]["RTL-TCP Source"] = "rtl_tcp_source";
|
||||
defConfig["moduleInstances"]["Radio"] = "radio";
|
||||
defConfig["moduleInstances"]["Recorder"] = "recorder";
|
||||
defConfig["moduleInstances"]["SoapySDR Source"] = "soapy_source";
|
||||
defConfig["modules"] = json::array();
|
||||
defConfig["offset"] = 0.0;
|
||||
defConfig["showWaterfall"] = true;
|
||||
defConfig["source"] = "";
|
||||
defConfig["streams"] = json::object();
|
||||
defConfig["windowSize"]["h"] = 720;
|
||||
defConfig["windowSize"]["w"] = 1280;
|
||||
|
||||
// Load config
|
||||
spdlog::info("Loading config");
|
||||
core::configManager.setPath(ROOT_DIR "/config.json");
|
||||
core::configManager.load(json());
|
||||
core::configManager.load(defConfig);
|
||||
core::configManager.enableAutoSave();
|
||||
|
||||
// Setup window
|
||||
|
@ -219,4 +219,73 @@ namespace dsp {
|
||||
stream<T>* _in;
|
||||
|
||||
};
|
||||
|
||||
class Squelch : public generic_block<Squelch> {
|
||||
public:
|
||||
Squelch() {}
|
||||
|
||||
Squelch(stream<complex_t>* in, float level) { init(in, level); }
|
||||
|
||||
~Squelch() {
|
||||
generic_block<Squelch>::stop();
|
||||
delete[] normBuffer;
|
||||
}
|
||||
|
||||
void init(stream<complex_t>* in, float level) {
|
||||
_in = in;
|
||||
_level = level;
|
||||
normBuffer = new float[STREAM_BUFFER_SIZE];
|
||||
generic_block<Squelch>::registerInput(_in);
|
||||
generic_block<Squelch>::registerOutput(&out);
|
||||
}
|
||||
|
||||
void setInput(stream<complex_t>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<Squelch>::ctrlMtx);
|
||||
generic_block<Squelch>::tempStop();
|
||||
generic_block<Squelch>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<Squelch>::registerInput(_in);
|
||||
generic_block<Squelch>::tempStart();
|
||||
}
|
||||
|
||||
void setLevel(float level) {
|
||||
_level = level;
|
||||
}
|
||||
|
||||
float getLevel() {
|
||||
return _level;
|
||||
}
|
||||
|
||||
int run() {
|
||||
count = _in->read();
|
||||
if (count < 0) { return -1; }
|
||||
|
||||
if (out.aquire() < 0) { return -1; }
|
||||
float sum = 0.0f;
|
||||
volk_32fc_magnitude_32f(normBuffer, (lv_32fc_t*)_in->data, count);
|
||||
volk_32f_accumulator_s32f(&sum, normBuffer, count);
|
||||
sum /= (float)count;
|
||||
|
||||
if (10.0f * log10f(sum) >= _level) {
|
||||
memcpy(out.data, _in->data, count * sizeof(complex_t));
|
||||
}
|
||||
else {
|
||||
memset(out.data, 0, count * sizeof(complex_t));
|
||||
}
|
||||
|
||||
_in->flush();
|
||||
out.write(count);
|
||||
return count;
|
||||
}
|
||||
|
||||
stream<complex_t> out;
|
||||
|
||||
|
||||
private:
|
||||
int count;
|
||||
float* normBuffer;
|
||||
float _level = -50.0f;
|
||||
stream<complex_t>* _in;
|
||||
|
||||
};
|
||||
}
|
@ -35,7 +35,6 @@ std::thread worker;
|
||||
std::mutex fft_mtx;
|
||||
fftwf_complex *fft_in, *fft_out;
|
||||
fftwf_plan p;
|
||||
float* tempData;
|
||||
char buf[1024];
|
||||
|
||||
int fftSize = 8192 * 8;
|
||||
@ -83,6 +82,7 @@ int fftHeight = 300;
|
||||
bool showMenu = true;
|
||||
bool centerTuning = false;
|
||||
dsp::stream<dsp::complex_t> dummyStream;
|
||||
bool demoWindow = false;
|
||||
|
||||
void windowInit() {
|
||||
LoadingScreen::show("Initializing UI");
|
||||
@ -234,7 +234,7 @@ void setVFO(double freq) {
|
||||
gui::waterfall.setViewOffset((BW / 2.0) - (viewBW / 2.0));
|
||||
gui::waterfall.setCenterFrequency(freq);
|
||||
gui::waterfall.setViewOffset(0);
|
||||
sigpath::vfoManager.setCenterOffset(gui::waterfall.selectedVFO, 0);
|
||||
sigpath::vfoManager.setOffset(gui::waterfall.selectedVFO, 0);
|
||||
sigpath::sourceManager.tune(freq);
|
||||
return;
|
||||
}
|
||||
@ -500,6 +500,7 @@ void drawWindow() {
|
||||
if (ImGui::Checkbox("Test technique", &dcbias.val)) {
|
||||
//sigpath::signalPath.setDCBiasCorrection(dcbias.val);
|
||||
}
|
||||
ImGui::Checkbox("Show demo window", &demoWindow);
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
@ -575,6 +576,10 @@ void drawWindow() {
|
||||
if (showCredits) {
|
||||
credits::show();
|
||||
}
|
||||
|
||||
if (demoWindow) {
|
||||
ImGui::ShowDemoWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void setViewBandwidthSlider(float bandwidth) {
|
||||
|
@ -25,8 +25,8 @@ public:
|
||||
_config->aquire();
|
||||
if(_config->conf.contains(prefix)) {
|
||||
if(!_config->conf[prefix].contains("AM")) {
|
||||
_config->conf[prefix]["AM"]["bandwidth"] = bw;
|
||||
_config->conf[prefix]["AM"]["snapInterval"] = snapInterval;
|
||||
if (!_config->conf[prefix]["AM"].contains("bandwidth")) { _config->conf[prefix]["AM"]["bandwidth"] = bw; }
|
||||
if (!_config->conf[prefix]["AM"].contains("snapInterval")) { _config->conf[prefix]["AM"]["snapInterval"] = snapInterval; }
|
||||
}
|
||||
json conf = _config->conf[prefix]["AM"];
|
||||
bw = conf["bandwidth"];
|
||||
@ -37,8 +37,10 @@ public:
|
||||
_config->conf[prefix]["AM"]["snapInterval"] = snapInterval;
|
||||
}
|
||||
_config->release(true);
|
||||
|
||||
squelch.init(_vfo->output, squelchLevel);
|
||||
|
||||
demod.init(_vfo->output);
|
||||
demod.init(&squelch.out);
|
||||
|
||||
agc.init(&demod.out, 1.0f / 125.0f);
|
||||
|
||||
@ -52,6 +54,7 @@ public:
|
||||
}
|
||||
|
||||
void start() {
|
||||
squelch.start();
|
||||
demod.start();
|
||||
agc.start();
|
||||
resamp.start();
|
||||
@ -60,6 +63,7 @@ public:
|
||||
}
|
||||
|
||||
void stop() {
|
||||
squelch.stop();
|
||||
demod.stop();
|
||||
agc.stop();
|
||||
resamp.stop();
|
||||
@ -79,7 +83,7 @@ public:
|
||||
|
||||
void setVFO(VFOManager::VFO* vfo) {
|
||||
_vfo = vfo;
|
||||
demod.setInput(_vfo->output);
|
||||
squelch.setInput(_vfo->output);
|
||||
}
|
||||
|
||||
VFOManager::VFO* getVFO() {
|
||||
@ -131,6 +135,16 @@ public:
|
||||
_config->conf[uiPrefix]["AM"]["snapInterval"] = snapInterval;
|
||||
_config->release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Squelch");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloat(("##_radio_am_deemp_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
|
||||
squelch.setLevel(squelchLevel);
|
||||
_config->aquire();
|
||||
_config->conf[uiPrefix]["AM"]["squelchLevel"] = squelchLevel;
|
||||
_config->release(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -153,8 +167,10 @@ private:
|
||||
float audioSampRate = 48000;
|
||||
float bw = 12500;
|
||||
bool running = false;
|
||||
float squelchLevel = -100.0f;
|
||||
|
||||
VFOManager::VFO* _vfo;
|
||||
dsp::Squelch squelch;
|
||||
dsp::AMDemod demod;
|
||||
dsp::AGC agc;
|
||||
dsp::filter_window::BlackmanWindow win;
|
||||
|
@ -28,8 +28,8 @@ public:
|
||||
_config->aquire();
|
||||
if(_config->conf.contains(prefix)) {
|
||||
if(!_config->conf[prefix].contains("CW")) {
|
||||
_config->conf[prefix]["CW"]["bandwidth"] = bw;
|
||||
_config->conf[prefix]["CW"]["snapInterval"] = snapInterval;
|
||||
if (!_config->conf[prefix]["CW"].contains("bandwidth")) { _config->conf[prefix]["CW"]["bandwidth"] = bw; }
|
||||
if (!_config->conf[prefix]["CW"].contains("snapInterval")) { _config->conf[prefix]["CW"]["snapInterval"] = snapInterval; }
|
||||
}
|
||||
json conf = _config->conf[prefix]["CW"];
|
||||
bw = conf["bandwidth"];
|
||||
@ -40,10 +40,12 @@ public:
|
||||
_config->conf[prefix]["CW"]["snapInterval"] = snapInterval;
|
||||
}
|
||||
_config->release(true);
|
||||
|
||||
squelch.init(_vfo->output, squelchLevel);
|
||||
|
||||
float audioBW = std::min<float>(audioSampRate / 2.0f, bw / 2.0f);
|
||||
win.init(audioBW, audioBW, bbSampRate);
|
||||
resamp.init(vfo->output, &win, bbSampRate, audioSampRate);
|
||||
resamp.init(&squelch.out, &win, bbSampRate, audioSampRate);
|
||||
win.setSampleRate(bbSampRate * resamp.getInterpolation());
|
||||
resamp.updateWindow(&win);
|
||||
|
||||
@ -57,6 +59,7 @@ public:
|
||||
}
|
||||
|
||||
void start() {
|
||||
squelch.start();
|
||||
resamp.start();
|
||||
xlator.start();
|
||||
c2r.start();
|
||||
@ -66,6 +69,7 @@ public:
|
||||
}
|
||||
|
||||
void stop() {
|
||||
squelch.stop();
|
||||
resamp.stop();
|
||||
xlator.stop();
|
||||
c2r.stop();
|
||||
@ -86,7 +90,7 @@ public:
|
||||
|
||||
void setVFO(VFOManager::VFO* vfo) {
|
||||
_vfo = vfo;
|
||||
resamp.setInput(_vfo->output);
|
||||
squelch.setInput(_vfo->output);
|
||||
}
|
||||
|
||||
VFOManager::VFO* getVFO() {
|
||||
@ -141,6 +145,16 @@ public:
|
||||
_config->conf[uiPrefix]["CW"]["snapInterval"] = snapInterval;
|
||||
_config->release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Squelch");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloat(("##_radio_cw_deemp_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
|
||||
squelch.setLevel(squelchLevel);
|
||||
_config->aquire();
|
||||
_config->conf[uiPrefix]["CW"]["squelchLevel"] = squelchLevel;
|
||||
_config->release(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -163,8 +177,10 @@ private:
|
||||
float audioSampRate = 48000;
|
||||
float bw = 200;
|
||||
bool running = false;
|
||||
float squelchLevel = -100.0f;
|
||||
|
||||
VFOManager::VFO* _vfo;
|
||||
dsp::Squelch squelch;
|
||||
dsp::filter_window::BlackmanWindow win;
|
||||
dsp::PolyphaseResampler<dsp::complex_t> resamp;
|
||||
dsp::FrequencyXlator<dsp::complex_t> xlator;
|
||||
|
@ -25,8 +25,8 @@ public:
|
||||
_config->aquire();
|
||||
if(_config->conf.contains(prefix)) {
|
||||
if(!_config->conf[prefix].contains("DSB")) {
|
||||
_config->conf[prefix]["DSB"]["bandwidth"] = bw;
|
||||
_config->conf[prefix]["DSB"]["snapInterval"] = snapInterval;
|
||||
if (!_config->conf[prefix]["DSB"].contains("bandwidth")) { _config->conf[prefix]["DSB"]["bandwidth"] = bw; }
|
||||
if (!_config->conf[prefix]["DSB"].contains("snapInterval")) { _config->conf[prefix]["DSB"]["snapInterval"] = snapInterval; }
|
||||
}
|
||||
json conf = _config->conf[prefix]["DSB"];
|
||||
bw = conf["bandwidth"];
|
||||
@ -37,8 +37,10 @@ public:
|
||||
_config->conf[prefix]["DSB"]["snapInterval"] = snapInterval;
|
||||
}
|
||||
_config->release(true);
|
||||
|
||||
squelch.init(_vfo->output, squelchLevel);
|
||||
|
||||
demod.init(_vfo->output, bbSampRate, bandWidth, dsp::SSBDemod::MODE_DSB);
|
||||
demod.init(&squelch.out, bbSampRate, bandWidth, dsp::SSBDemod::MODE_DSB);
|
||||
|
||||
agc.init(&demod.out, 1.0f / 125.0f);
|
||||
|
||||
@ -52,6 +54,7 @@ public:
|
||||
}
|
||||
|
||||
void start() {
|
||||
squelch.start();
|
||||
demod.start();
|
||||
agc.start();
|
||||
resamp.start();
|
||||
@ -60,6 +63,7 @@ public:
|
||||
}
|
||||
|
||||
void stop() {
|
||||
squelch.stop();
|
||||
demod.stop();
|
||||
agc.stop();
|
||||
resamp.stop();
|
||||
@ -79,7 +83,7 @@ public:
|
||||
|
||||
void setVFO(VFOManager::VFO* vfo) {
|
||||
_vfo = vfo;
|
||||
demod.setInput(_vfo->output);
|
||||
squelch.setInput(_vfo->output);
|
||||
}
|
||||
|
||||
VFOManager::VFO* getVFO() {
|
||||
@ -131,6 +135,16 @@ public:
|
||||
_config->conf[uiPrefix]["DSB"]["snapInterval"] = snapInterval;
|
||||
_config->release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Squelch");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloat(("##_radio_dsb_deemp_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
|
||||
squelch.setLevel(squelchLevel);
|
||||
_config->aquire();
|
||||
_config->conf[uiPrefix]["DSB"]["squelchLevel"] = squelchLevel;
|
||||
_config->release(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -153,8 +167,10 @@ private:
|
||||
float audioSampRate = 48000;
|
||||
float bw = 6000;
|
||||
bool running = false;
|
||||
float squelchLevel = -100.0f;
|
||||
|
||||
VFOManager::VFO* _vfo;
|
||||
dsp::Squelch squelch;
|
||||
dsp::SSBDemod demod;
|
||||
dsp::AGC agc;
|
||||
dsp::filter_window::BlackmanWindow win;
|
||||
|
@ -25,8 +25,8 @@ public:
|
||||
_config->aquire();
|
||||
if(_config->conf.contains(prefix)) {
|
||||
if(!_config->conf[prefix].contains("FM")) {
|
||||
_config->conf[prefix]["FM"]["bandwidth"] = bw;
|
||||
_config->conf[prefix]["FM"]["snapInterval"] = snapInterval;
|
||||
if (!_config->conf[prefix]["FM"].contains("bandwidth")) { _config->conf[prefix]["FM"]["bandwidth"] = bw; }
|
||||
if (!_config->conf[prefix]["FM"].contains("snapInterval")) { _config->conf[prefix]["FM"]["snapInterval"] = snapInterval; }
|
||||
}
|
||||
json conf = _config->conf[prefix]["FM"];
|
||||
bw = conf["bandwidth"];
|
||||
@ -37,8 +37,10 @@ public:
|
||||
_config->conf[prefix]["FM"]["snapInterval"] = snapInterval;
|
||||
}
|
||||
_config->release(true);
|
||||
|
||||
squelch.init(_vfo->output, squelchLevel);
|
||||
|
||||
demod.init(_vfo->output, bbSampRate, bandWidth / 2.0f);
|
||||
demod.init(&squelch.out, bbSampRate, bandWidth / 2.0f);
|
||||
|
||||
float audioBW = std::min<float>(audioSampleRate / 2.0f, bw / 2.0f);
|
||||
win.init(audioBW, audioBW, bbSampRate);
|
||||
@ -50,6 +52,7 @@ public:
|
||||
}
|
||||
|
||||
void start() {
|
||||
squelch.start();
|
||||
demod.start();
|
||||
resamp.start();
|
||||
m2s.start();
|
||||
@ -57,6 +60,7 @@ public:
|
||||
}
|
||||
|
||||
void stop() {
|
||||
squelch.stop();
|
||||
demod.stop();
|
||||
resamp.stop();
|
||||
m2s.stop();
|
||||
@ -75,7 +79,7 @@ public:
|
||||
|
||||
void setVFO(VFOManager::VFO* vfo) {
|
||||
_vfo = vfo;
|
||||
demod.setInput(_vfo->output);
|
||||
squelch.setInput(_vfo->output);
|
||||
}
|
||||
|
||||
VFOManager::VFO* getVFO() {
|
||||
@ -127,6 +131,16 @@ public:
|
||||
_config->conf[uiPrefix]["FM"]["snapInterval"] = snapInterval;
|
||||
_config->release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Squelch");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloat(("##_radio_fm_deemp_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
|
||||
squelch.setLevel(squelchLevel);
|
||||
_config->aquire();
|
||||
_config->conf[uiPrefix]["FM"]["squelchLevel"] = squelchLevel;
|
||||
_config->release(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -150,8 +164,10 @@ private:
|
||||
float audioSampRate = 48000;
|
||||
float bw = 12500;
|
||||
bool running = false;
|
||||
float squelchLevel = -100.0f;
|
||||
|
||||
VFOManager::VFO* _vfo;
|
||||
dsp::Squelch squelch;
|
||||
dsp::FMDemod demod;
|
||||
dsp::filter_window::BlackmanWindow win;
|
||||
dsp::PolyphaseResampler<float> resamp;
|
||||
|
@ -25,8 +25,8 @@ public:
|
||||
_config->aquire();
|
||||
if(_config->conf.contains(prefix)) {
|
||||
if(!_config->conf[prefix].contains("LSB")) {
|
||||
_config->conf[prefix]["LSB"]["bandwidth"] = bw;
|
||||
_config->conf[prefix]["LSB"]["snapInterval"] = snapInterval;
|
||||
if (!_config->conf[prefix]["LSB"].contains("bandwidth")) { _config->conf[prefix]["LSB"]["bandwidth"] = bw; }
|
||||
if (!_config->conf[prefix]["LSB"].contains("snapInterval")) { _config->conf[prefix]["LSB"]["snapInterval"] = snapInterval; }
|
||||
}
|
||||
json conf = _config->conf[prefix]["LSB"];
|
||||
bw = conf["bandwidth"];
|
||||
@ -37,8 +37,10 @@ public:
|
||||
_config->conf[prefix]["LSB"]["snapInterval"] = snapInterval;
|
||||
}
|
||||
_config->release(true);
|
||||
|
||||
squelch.init(_vfo->output, squelchLevel);
|
||||
|
||||
demod.init(_vfo->output, bbSampRate, bandWidth, dsp::SSBDemod::MODE_LSB);
|
||||
demod.init(&squelch.out, bbSampRate, bandWidth, dsp::SSBDemod::MODE_LSB);
|
||||
|
||||
agc.init(&demod.out, 1.0f / 125.0f);
|
||||
|
||||
@ -52,6 +54,7 @@ public:
|
||||
}
|
||||
|
||||
void start() {
|
||||
squelch.start();
|
||||
demod.start();
|
||||
agc.start();
|
||||
resamp.start();
|
||||
@ -60,6 +63,7 @@ public:
|
||||
}
|
||||
|
||||
void stop() {
|
||||
squelch.stop();
|
||||
demod.stop();
|
||||
agc.stop();
|
||||
resamp.stop();
|
||||
@ -79,7 +83,7 @@ public:
|
||||
|
||||
void setVFO(VFOManager::VFO* vfo) {
|
||||
_vfo = vfo;
|
||||
demod.setInput(_vfo->output);
|
||||
squelch.setInput(_vfo->output);
|
||||
}
|
||||
|
||||
VFOManager::VFO* getVFO() {
|
||||
@ -131,6 +135,16 @@ public:
|
||||
_config->conf[uiPrefix]["LSB"]["snapInterval"] = snapInterval;
|
||||
_config->release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Squelch");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloat(("##_radio_lsb_deemp_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
|
||||
squelch.setLevel(squelchLevel);
|
||||
_config->aquire();
|
||||
_config->conf[uiPrefix]["LSB"]["squelchLevel"] = squelchLevel;
|
||||
_config->release(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -153,8 +167,10 @@ private:
|
||||
float audioSampRate = 48000;
|
||||
float bw = 3000;
|
||||
bool running = false;
|
||||
float squelchLevel = -100.0f;
|
||||
|
||||
VFOManager::VFO* _vfo;
|
||||
dsp::Squelch squelch;
|
||||
dsp::SSBDemod demod;
|
||||
dsp::AGC agc;
|
||||
dsp::filter_window::BlackmanWindow win;
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
_config->aquire();
|
||||
if(_config->conf.contains(prefix)) {
|
||||
if(!_config->conf[prefix].contains("RAW")) {
|
||||
_config->conf[prefix]["RAW"]["snapInterval"] = snapInterval;
|
||||
if (!_config->conf[prefix]["RAW"].contains("snapInterval")) { _config->conf[prefix]["RAW"]["snapInterval"] = snapInterval; }
|
||||
}
|
||||
json conf = _config->conf[prefix]["RAW"];
|
||||
snapInterval = conf["snapInterval"];
|
||||
@ -34,16 +34,20 @@ public:
|
||||
_config->conf[prefix]["RAW"]["snapInterval"] = snapInterval;
|
||||
}
|
||||
_config->release(true);
|
||||
|
||||
squelch.init(_vfo->output, squelchLevel);
|
||||
|
||||
c2s.init(_vfo->output);
|
||||
c2s.init(&squelch.out);
|
||||
}
|
||||
|
||||
void start() {
|
||||
squelch.start();
|
||||
c2s.start();
|
||||
running = true;
|
||||
}
|
||||
|
||||
void stop() {
|
||||
squelch.stop();
|
||||
c2s.stop();
|
||||
running = false;
|
||||
}
|
||||
@ -60,7 +64,7 @@ public:
|
||||
|
||||
void setVFO(VFOManager::VFO* vfo) {
|
||||
_vfo = vfo;
|
||||
c2s.setInput(_vfo->output);
|
||||
squelch.setInput(_vfo->output);
|
||||
}
|
||||
|
||||
VFOManager::VFO* getVFO() {
|
||||
@ -95,6 +99,16 @@ public:
|
||||
_config->release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Squelch");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloat(("##_radio_raw_deemp_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
|
||||
squelch.setLevel(squelchLevel);
|
||||
_config->aquire();
|
||||
_config->conf[uiPrefix]["RAW"]["squelchLevel"] = squelchLevel;
|
||||
_config->release(true);
|
||||
}
|
||||
|
||||
// TODO: Allow selection of the bandwidth
|
||||
}
|
||||
|
||||
@ -109,8 +123,10 @@ private:
|
||||
float audioSampRate = 48000;
|
||||
float bw = 12500;
|
||||
bool running = false;
|
||||
float squelchLevel = -100.0f;
|
||||
|
||||
VFOManager::VFO* _vfo;
|
||||
dsp::Squelch squelch;
|
||||
dsp::ComplexToStereo c2s;
|
||||
|
||||
ConfigManager* _config;
|
||||
|
@ -25,8 +25,8 @@ public:
|
||||
_config->aquire();
|
||||
if(_config->conf.contains(prefix)) {
|
||||
if(!_config->conf[prefix].contains("USB")) {
|
||||
_config->conf[prefix]["USB"]["bandwidth"] = bw;
|
||||
_config->conf[prefix]["USB"]["snapInterval"] = snapInterval;
|
||||
if (!_config->conf[prefix]["USB"].contains("bandwidth")) { _config->conf[prefix]["USB"]["bandwidth"] = bw; }
|
||||
if (!_config->conf[prefix]["USB"].contains("snapInterval")) { _config->conf[prefix]["USB"]["snapInterval"] = snapInterval; }
|
||||
}
|
||||
json conf = _config->conf[prefix]["USB"];
|
||||
bw = conf["bandwidth"];
|
||||
@ -37,8 +37,10 @@ public:
|
||||
_config->conf[prefix]["USB"]["snapInterval"] = snapInterval;
|
||||
}
|
||||
_config->release(true);
|
||||
|
||||
squelch.init(_vfo->output, squelchLevel);
|
||||
|
||||
demod.init(_vfo->output, bbSampRate, bandWidth, dsp::SSBDemod::MODE_USB);
|
||||
demod.init(&squelch.out, bbSampRate, bandWidth, dsp::SSBDemod::MODE_USB);
|
||||
|
||||
agc.init(&demod.out, 1.0f / 125.0f);
|
||||
|
||||
@ -52,6 +54,7 @@ public:
|
||||
}
|
||||
|
||||
void start() {
|
||||
squelch.start();
|
||||
demod.start();
|
||||
agc.start();
|
||||
resamp.start();
|
||||
@ -60,6 +63,7 @@ public:
|
||||
}
|
||||
|
||||
void stop() {
|
||||
squelch.stop();
|
||||
demod.stop();
|
||||
agc.stop();
|
||||
resamp.stop();
|
||||
@ -79,7 +83,7 @@ public:
|
||||
|
||||
void setVFO(VFOManager::VFO* vfo) {
|
||||
_vfo = vfo;
|
||||
demod.setInput(_vfo->output);
|
||||
squelch.setInput(_vfo->output);
|
||||
}
|
||||
|
||||
VFOManager::VFO* getVFO() {
|
||||
@ -131,6 +135,16 @@ public:
|
||||
_config->conf[uiPrefix]["USB"]["snapInterval"] = snapInterval;
|
||||
_config->release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Squelch");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloat(("##_radio_usb_deemp_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
|
||||
squelch.setLevel(squelchLevel);
|
||||
_config->aquire();
|
||||
_config->conf[uiPrefix]["USB"]["squelchLevel"] = squelchLevel;
|
||||
_config->release(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -153,8 +167,10 @@ private:
|
||||
float audioSampRate = 48000;
|
||||
float bw = 3000;
|
||||
bool running = false;
|
||||
float squelchLevel = -100.0f;
|
||||
|
||||
VFOManager::VFO* _vfo;
|
||||
dsp::Squelch squelch;
|
||||
dsp::SSBDemod demod;
|
||||
dsp::AGC agc;
|
||||
dsp::filter_window::BlackmanWindow win;
|
||||
|
@ -25,24 +25,28 @@ public:
|
||||
_config->aquire();
|
||||
if(_config->conf.contains(prefix)) {
|
||||
if(!_config->conf[prefix].contains("WFM")) {
|
||||
_config->conf[prefix]["WFM"]["bandwidth"] = bw;
|
||||
_config->conf[prefix]["WFM"]["snapInterval"] = snapInterval;
|
||||
_config->conf[prefix]["WFM"]["deempMode"] = deempId;
|
||||
if (!_config->conf[prefix]["WFM"].contains("bandwidth")) { _config->conf[prefix]["WFM"]["bandwidth"] = bw; }
|
||||
if (!_config->conf[prefix]["WFM"].contains("snapInterval")) { _config->conf[prefix]["WFM"]["snapInterval"] = snapInterval; }
|
||||
if (!_config->conf[prefix]["WFM"].contains("deempMode")) { _config->conf[prefix]["WFM"]["deempMode"] = deempId; }
|
||||
if (!_config->conf[prefix]["WFM"].contains("squelchLevel")) { _config->conf[prefix]["WFM"]["squelchLevel"] = squelchLevel; }
|
||||
}
|
||||
json conf = _config->conf[prefix]["WFM"];
|
||||
bw = conf["bandwidth"];
|
||||
snapInterval = conf["snapInterval"];
|
||||
deempId = conf["deempMode"];
|
||||
squelchLevel = conf["squelchLevel"];
|
||||
}
|
||||
else {
|
||||
_config->conf[prefix]["WFM"]["bandwidth"] = bw;
|
||||
_config->conf[prefix]["WFM"]["snapInterval"] = snapInterval;
|
||||
_config->conf[prefix]["WFM"]["deempMode"] = deempId;
|
||||
_config->conf[prefix]["WFM"]["squelchLevel"] = squelchLevel;
|
||||
}
|
||||
_config->release(true);
|
||||
|
||||
squelch.init(_vfo->output, squelchLevel);
|
||||
|
||||
demod.init(_vfo->output, bbSampRate, bandWidth / 2.0f);
|
||||
demod.init(&squelch.out, bbSampRate, bandWidth / 2.0f);
|
||||
|
||||
float audioBW = std::min<float>(audioSampleRate / 2.0f, 16000.0f);
|
||||
win.init(audioBW, audioBW, bbSampRate);
|
||||
@ -56,6 +60,7 @@ public:
|
||||
}
|
||||
|
||||
void start() {
|
||||
squelch.start();
|
||||
demod.start();
|
||||
resamp.start();
|
||||
deemp.start();
|
||||
@ -64,6 +69,7 @@ public:
|
||||
}
|
||||
|
||||
void stop() {
|
||||
squelch.stop();
|
||||
demod.stop();
|
||||
resamp.stop();
|
||||
deemp.stop();
|
||||
@ -83,7 +89,7 @@ public:
|
||||
|
||||
void setVFO(VFOManager::VFO* vfo) {
|
||||
_vfo = vfo;
|
||||
demod.setInput(_vfo->output);
|
||||
squelch.setInput(_vfo->output);
|
||||
}
|
||||
|
||||
VFOManager::VFO* getVFO() {
|
||||
@ -149,6 +155,16 @@ public:
|
||||
_config->conf[uiPrefix]["WFM"]["deempMode"] = deempId;
|
||||
_config->release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Squelch");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloat(("##_radio_wfm_deemp_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
|
||||
squelch.setLevel(squelchLevel);
|
||||
_config->aquire();
|
||||
_config->conf[uiPrefix]["WFM"]["squelchLevel"] = squelchLevel;
|
||||
_config->release(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -181,12 +197,14 @@ private:
|
||||
std::string uiPrefix;
|
||||
float snapInterval = 100000;
|
||||
float audioSampRate = 48000;
|
||||
float squelchLevel = -100.0f;
|
||||
float bw = 200000;
|
||||
int deempId = 0;
|
||||
float tau = 50e-6;
|
||||
bool running = false;
|
||||
|
||||
VFOManager::VFO* _vfo;
|
||||
dsp::Squelch squelch;
|
||||
dsp::FMDemod demod;
|
||||
dsp::filter_window::BlackmanWindow win;
|
||||
dsp::PolyphaseResampler<float> resamp;
|
||||
|
@ -3,7 +3,7 @@
|
||||
"bandPlanEnabled": true,
|
||||
"centerTuning": false,
|
||||
"fftHeight": 300,
|
||||
"frequency": 99716000,
|
||||
"frequency": 103600000,
|
||||
"max": 0.0,
|
||||
"maximized": false,
|
||||
"menuOrder": [
|
||||
@ -17,7 +17,7 @@
|
||||
"Display"
|
||||
],
|
||||
"menuWidth": 300,
|
||||
"min": -65.44117736816406,
|
||||
"min": -66.17647552490234,
|
||||
"moduleInstances": {
|
||||
"Audio Sink": "audio_sink",
|
||||
"PlutoSDR Source": "plutosdr_source",
|
||||
@ -27,12 +27,12 @@
|
||||
"SoapySDR Source": "soapy_source"
|
||||
},
|
||||
"modules": [
|
||||
"./radio/Release/radio.dll",
|
||||
"./recorder/Release/recorder.dll",
|
||||
"./soapy_source/Release/soapy_source.dll",
|
||||
"./rtl_tcp_source/Release/rtl_tcp_source.dll",
|
||||
"./audio_sink/Release/audio_sink.dll",
|
||||
"./plutosdr_source/Release/plutosdr_source.dll"
|
||||
"./radio/RelWithDebInfo/radio.dll",
|
||||
"./recorder/RelWithDebInfo/recorder.dll",
|
||||
"./soapy_source/RelWithDebInfo/soapy_source.dll",
|
||||
"./rtl_tcp_source/RelWithDebInfo/rtl_tcp_source.dll",
|
||||
"./audio_sink/RelWithDebInfo/audio_sink.dll",
|
||||
"./plutosdr_source/RelWithDebInfo/plutosdr_source.dll"
|
||||
],
|
||||
"offset": 0.0,
|
||||
"showWaterfall": true,
|
||||
@ -41,7 +41,7 @@
|
||||
"Radio": {
|
||||
"muted": false,
|
||||
"sink": "Audio",
|
||||
"volume": 0.4285714328289032
|
||||
"volume": 0.6785714030265808
|
||||
},
|
||||
"Radio 1": {
|
||||
"muted": false,
|
||||
|
@ -2,11 +2,13 @@
|
||||
"Radio": {
|
||||
"AM": {
|
||||
"bandwidth": 12500.0,
|
||||
"snapInterval": 1000.0
|
||||
"snapInterval": 1000.0,
|
||||
"squelchLevel": -100.0
|
||||
},
|
||||
"CW": {
|
||||
"bandwidth": 200.0,
|
||||
"snapInterval": 10.0
|
||||
"snapInterval": 10.0,
|
||||
"squelchLevel": -100.0
|
||||
},
|
||||
"DSB": {
|
||||
"bandwidth": 6000.0,
|
||||
@ -30,7 +32,8 @@
|
||||
"WFM": {
|
||||
"bandwidth": 200000.0,
|
||||
"deempMode": 0,
|
||||
"snapInterval": 100000.0
|
||||
"snapInterval": 100000.0,
|
||||
"squelchLevel": -100.0
|
||||
},
|
||||
"selectedDemodId": 1
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
{
|
||||
"device": "HackRF One #0 901868dc282c8f8b",
|
||||
"device": "AirSpy HF+ [c852435de0224af7]",
|
||||
"devices": {
|
||||
"": {
|
||||
"agc": false,
|
||||
"gains": {
|
||||
"PGA": 0.0
|
||||
},
|
||||
"sampleRate": 8000000.0
|
||||
"sampleRate": 4000000.0
|
||||
},
|
||||
"AirSpy HF+ [c852435de0224af7]": {
|
||||
"agc": false,
|
||||
"gains": {
|
||||
"LNA": 6.0,
|
||||
"RF": 0.0
|
||||
"RF": -48.0
|
||||
},
|
||||
"sampleRate": 768000.0
|
||||
},
|
||||
|
@ -143,6 +143,8 @@ private:
|
||||
|
||||
hasAgc = dev->hasGainMode(SOAPY_SDR_RX, channelId);
|
||||
|
||||
hasIQBalance = dev->hasIQBalanceMode(SOAPY_SDR_RX, channelId);
|
||||
|
||||
SoapySDR::Device::unmake(dev);
|
||||
|
||||
config.aquire();
|
||||
@ -163,6 +165,12 @@ private:
|
||||
else {
|
||||
agc = false;
|
||||
}
|
||||
if (hasIQBalance && config.conf["devices"][name].contains("iqBalance")) {
|
||||
iqBalance = config.conf["devices"][name]["iqBalance"];
|
||||
}
|
||||
else {
|
||||
iqBalance = false;
|
||||
}
|
||||
if (config.conf["devices"][name].contains("sampleRate")) {
|
||||
selectSampleRate(config.conf["devices"][name]["sampleRate"]);
|
||||
}
|
||||
@ -196,6 +204,9 @@ private:
|
||||
if (hasAgc) {
|
||||
conf["agc"] = agc;
|
||||
}
|
||||
if (hasIQBalance) {
|
||||
conf["iqBalance"] = iqBalance;
|
||||
}
|
||||
config.aquire();
|
||||
config.conf["devices"][devArgs["label"]] = conf;
|
||||
config.release(true);
|
||||
@ -231,6 +242,10 @@ private:
|
||||
_this->dev->setGainMode(SOAPY_SDR_RX, _this->channelId, _this->agc);
|
||||
}
|
||||
|
||||
if (_this->hasIQBalance) {
|
||||
_this->dev->setIQBalanceMode(SOAPY_SDR_RX, _this->channelId, _this->iqBalance);
|
||||
}
|
||||
|
||||
_this->dev->setFrequency(SOAPY_SDR_RX, _this->channelId, _this->freq);
|
||||
|
||||
_this->devStream = _this->dev->setupStream(SOAPY_SDR_RX, "CF32");
|
||||
@ -322,6 +337,13 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (_this->hasIQBalance) {
|
||||
if (ImGui::Checkbox((std::string("AGC##_iq_bal_sel_") + _this->name).c_str(), &_this->iqBalance)) {
|
||||
if (_this->running) { _this->dev->setIQBalanceMode(SOAPY_SDR_RX, _this->channelId, _this->iqBalance); }
|
||||
_this->saveCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (auto gain : _this->gainList) {
|
||||
ImGui::Text("%s gain", gain.c_str());
|
||||
@ -371,6 +393,8 @@ private:
|
||||
bool running = false;
|
||||
bool hasAgc = false;
|
||||
bool agc = false;
|
||||
bool hasIQBalance = false;
|
||||
bool iqBalance = false;
|
||||
std::vector<double> sampleRates;
|
||||
int srId = -1;
|
||||
float* uiGains;
|
||||
|
Loading…
Reference in New Issue
Block a user