From 679fb49743ae50aec28d947f84200a9133941114 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Tue, 27 Jul 2021 23:50:48 +0200 Subject: [PATCH 01/11] Added IQ correction --- core/src/core.cpp | 1 + core/src/gui/menus/source.cpp | 10 ++++++++++ core/src/signal_path/dsp.cpp | 19 ++++++++++++++++--- core/src/signal_path/dsp.h | 3 +++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/core/src/core.cpp b/core/src/core.cpp index 8d601657..8c21dbb8 100644 --- a/core/src/core.cpp +++ b/core/src/core.cpp @@ -206,6 +206,7 @@ int sdrpp_main(int argc, char *argv[]) { defConfig["showWaterfall"] = true; defConfig["source"] = ""; defConfig["decimationPower"] = 0; + defConfig["iqCorrection"] = false; defConfig["streams"]["Radio"]["muted"] = false; defConfig["streams"]["Radio"]["sink"] = "Audio"; diff --git a/core/src/gui/menus/source.cpp b/core/src/gui/menus/source.cpp index 1afe0e07..43c8b957 100644 --- a/core/src/gui/menus/source.cpp +++ b/core/src/gui/menus/source.cpp @@ -12,6 +12,7 @@ namespace sourecmenu { double customOffset = 0.0; double effectiveOffset = 0.0; int decimationPower = 0; + bool iqCorrection = false; EventHandler sourceRegisteredHandler; EventHandler sourceUnregisterHandler; @@ -124,6 +125,8 @@ namespace sourecmenu { customOffset = core::configManager.conf["offset"]; offsetMode = core::configManager.conf["offsetMode"]; decimationPower = core::configManager.conf["decimationPower"]; + iqCorrection = core::configManager.conf["iqCorrection"]; + sigpath::signalPath.setIQCorrection(iqCorrection); updateOffset(); refreshSources(); @@ -158,6 +161,13 @@ namespace sourecmenu { sigpath::sourceManager.showSelectedMenu(); + if (ImGui::Checkbox("IQ Correction##_sdrpp_iq_corr", &iqCorrection)) { + sigpath::signalPath.setIQCorrection(iqCorrection); + core::configManager.acquire(); + core::configManager.conf["iqCorrection"] = iqCorrection; + core::configManager.release(true); + } + ImGui::Text("Offset mode"); ImGui::SameLine(); ImGui::SetNextItemWidth(itemWidth - ImGui::GetCursorPosX()); diff --git a/core/src/signal_path/dsp.cpp b/core/src/signal_path/dsp.cpp index 37f385e0..15a30781 100644 --- a/core/src/signal_path/dsp.cpp +++ b/core/src/signal_path/dsp.cpp @@ -16,7 +16,8 @@ void SignalPath::init(uint64_t sampleRate, int fftRate, int fftSize, dsp::stream // split.init(input); inputBuffer.init(input); - split.init(&inputBuffer.out); + corrector.init(&inputBuffer.out, 100.0f / sampleRate); + split.init(&corrector.out); reshape.init(&fftStream, fftSize, (sampleRate / fftRate) - fftSize); split.bindStream(&fftStream); @@ -43,6 +44,8 @@ void SignalPath::setSampleRate(double sampleRate) { vfo.vfo->start(); } + corrector.setCorrectionRate(100.0f / sampleRate); + split.start(); } @@ -55,6 +58,7 @@ void SignalPath::start() { decimator->start(); } inputBuffer.start(); + corrector.start(); split.start(); reshape.start(); fftHandlerSink.start(); @@ -66,6 +70,7 @@ void SignalPath::stop() { decimator->stop(); } inputBuffer.stop(); + corrector.stop(); split.stop(); reshape.stop(); fftHandlerSink.stop(); @@ -159,7 +164,7 @@ void SignalPath::setDecimation(int dec) { // If no decimation, reconnect if (!dec) { - split.setInput(&inputBuffer.out); + split.setInput(&corrector.out); if (running) { split.start(); } core::setInputSampleRate(sourceSampleRate); return; @@ -167,7 +172,7 @@ void SignalPath::setDecimation(int dec) { // Create new decimators for (int i = 0; i < dec; i++) { - dsp::HalfDecimator* decimator = new dsp::HalfDecimator((i == 0) ? &inputBuffer.out : &decimators[i-1]->out, &halfBandWindow); + dsp::HalfDecimator* decimator = new dsp::HalfDecimator((i == 0) ? &corrector.out : &decimators[i-1]->out, &halfBandWindow); if (running) { decimator->start(); } decimators.push_back(decimator); } @@ -176,4 +181,12 @@ void SignalPath::setDecimation(int dec) { // Update the DSP sample rate core::setInputSampleRate(sourceSampleRate); +} + +void SignalPath::setIQCorrection(bool enabled) { + corrector.bypass = !enabled; + if (!enabled) { + corrector.offset.re = 0; + corrector.offset.im = 0; + } } \ No newline at end of file diff --git a/core/src/signal_path/dsp.h b/core/src/signal_path/dsp.h index a644850c..cf6f2afc 100644 --- a/core/src/signal_path/dsp.h +++ b/core/src/signal_path/dsp.h @@ -4,6 +4,7 @@ #include #include #include +#include class SignalPath { public: @@ -24,6 +25,7 @@ public: void stopFFT(); void setBuffering(bool enabled); void setDecimation(int dec); + void setIQCorrection(bool enabled); dsp::SampleFrameBuffer inputBuffer; double sourceSampleRate = 0; @@ -36,6 +38,7 @@ private: }; dsp::Splitter split; + dsp::IQCorrector corrector; // FFT dsp::stream fftStream; From b9e35e65589f139b456ad14359b8df9e5ef82dea Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Tue, 27 Jul 2021 23:51:06 +0200 Subject: [PATCH 02/11] Added IQ correction --- core/src/dsp/correction.h | 76 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 core/src/dsp/correction.h diff --git a/core/src/dsp/correction.h b/core/src/dsp/correction.h new file mode 100644 index 00000000..3c50458c --- /dev/null +++ b/core/src/dsp/correction.h @@ -0,0 +1,76 @@ +#pragma once +#include +#include +#include +#include + +namespace dsp { + class IQCorrector : public generic_block { + public: + IQCorrector() {} + + IQCorrector(stream* in, float rate) { init(in, rate); } + + void init(stream* in, float rate) { + _in = in; + correctionRate = rate; + offset.re = 0; + offset.im = 0; + generic_block::registerInput(_in); + generic_block::registerOutput(&out); + generic_block::_block_init = true; + } + + void setInput(stream* in) { + assert(generic_block::_block_init); + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in); + _in = in; + generic_block::registerInput(_in); + generic_block::tempStart(); + } + + void setCorrectionRate(float rate) { + correctionRate = rate; + } + + int run() { + int count = _in->read(); + if (count < 0) { return -1; } + + if (bypass) { + memcpy(out.writeBuf, _in->readBuf, count * sizeof(complex_t)); + + _in->flush(); + + if (!out.swap(count)) { return -1; } + + return count; + } + + for (int i = 0; i < count; i++) { + out.writeBuf[i] = _in->readBuf[i] - offset; + offset = offset + (out.writeBuf[i] * correctionRate); + } + + _in->flush(); + + if (!out.swap(count)) { return -1; } + + return count; + } + + stream out; + + // TEMPORARY FOR DEBUG PURPOSES + bool bypass = true; + complex_t offset; + + private: + stream* _in; + float correctionRate = 0.00001; + + + }; +} \ No newline at end of file From 82902845862f0dc8a32549c05d671115d7d59ff8 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Wed, 28 Jul 2021 02:18:54 +0200 Subject: [PATCH 03/11] Improved performance of DC correction --- core/src/dsp/correction.h | 2 +- core/src/gui/menus/display.cpp | 2 +- core/src/gui/widgets/waterfall.cpp | 2 +- core/src/signal_path/dsp.cpp | 53 +++++++++++++++++++++++++----- core/src/signal_path/dsp.h | 1 + 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/core/src/dsp/correction.h b/core/src/dsp/correction.h index 3c50458c..d785a320 100644 --- a/core/src/dsp/correction.h +++ b/core/src/dsp/correction.h @@ -64,7 +64,7 @@ namespace dsp { stream out; // TEMPORARY FOR DEBUG PURPOSES - bool bypass = true; + bool bypass = false; complex_t offset; private: diff --git a/core/src/gui/menus/display.cpp b/core/src/gui/menus/display.cpp index e42cd5b0..1e03e7bc 100644 --- a/core/src/gui/menus/display.cpp +++ b/core/src/gui/menus/display.cpp @@ -108,7 +108,7 @@ namespace displaymenu { ImGui::SameLine(); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); if (ImGui::InputInt("##sdrpp_fft_rate", &fftRate, 1, 10)) { - std::clamp(fftRate, 1, 200); + fftRate = std::max(1, fftRate); sigpath::signalPath.setFFTRate(fftRate); core::configManager.acquire(); core::configManager.conf["fftRate"] = fftRate; diff --git a/core/src/gui/widgets/waterfall.cpp b/core/src/gui/widgets/waterfall.cpp index f33c12db..7d3e6d41 100644 --- a/core/src/gui/widgets/waterfall.cpp +++ b/core/src/gui/widgets/waterfall.cpp @@ -362,7 +362,7 @@ namespace ImGui { // If the mouse wheel is moved on the frequency scale if (mouseWheel != 0 && mouseInFreq) { - viewOffset -= (double)mouseWheel * viewBandwidth / 20.0; + viewOffset -= (double)mouseWheel * viewBandwidth / 20.0; if (viewOffset + (viewBandwidth / 2.0) > wholeBandwidth / 2.0) { double freqOffset = (viewOffset + (viewBandwidth / 2.0)) - (wholeBandwidth / 2.0); diff --git a/core/src/signal_path/dsp.cpp b/core/src/signal_path/dsp.cpp index 15a30781..269a4f0d 100644 --- a/core/src/signal_path/dsp.cpp +++ b/core/src/signal_path/dsp.cpp @@ -16,8 +16,8 @@ void SignalPath::init(uint64_t sampleRate, int fftRate, int fftSize, dsp::stream // split.init(input); inputBuffer.init(input); - corrector.init(&inputBuffer.out, 100.0f / sampleRate); - split.init(&corrector.out); + corrector.init(&inputBuffer.out, 50.0f / sampleRate); + split.init(&inputBuffer.out); reshape.init(&fftStream, fftSize, (sampleRate / fftRate) - fftSize); split.bindStream(&fftStream); @@ -44,7 +44,7 @@ void SignalPath::setSampleRate(double sampleRate) { vfo.vfo->start(); } - corrector.setCorrectionRate(100.0f / sampleRate); + corrector.setCorrectionRate(50.0f / sampleRate); split.start(); } @@ -58,7 +58,7 @@ void SignalPath::start() { decimator->start(); } inputBuffer.start(); - corrector.start(); + if (iqCorrection) { corrector.start(); } split.start(); reshape.start(); fftHandlerSink.start(); @@ -70,7 +70,7 @@ void SignalPath::stop() { decimator->stop(); } inputBuffer.stop(); - corrector.stop(); + if (iqCorrection) { corrector.stop(); } split.stop(); reshape.stop(); fftHandlerSink.stop(); @@ -164,7 +164,13 @@ void SignalPath::setDecimation(int dec) { // If no decimation, reconnect if (!dec) { - split.setInput(&corrector.out); + if (iqCorrection) { + split.setInput(&corrector.out); + } + else { + split.setInput(&inputBuffer.out); + } + if (running) { split.start(); } core::setInputSampleRate(sourceSampleRate); return; @@ -172,7 +178,17 @@ void SignalPath::setDecimation(int dec) { // Create new decimators for (int i = 0; i < dec; i++) { - dsp::HalfDecimator* decimator = new dsp::HalfDecimator((i == 0) ? &corrector.out : &decimators[i-1]->out, &halfBandWindow); + dsp::HalfDecimator* decimator; + if (iqCorrection && i == 0) { + decimator = new dsp::HalfDecimator(&corrector.out, &halfBandWindow); + } + else if (i == 0) { + decimator = new dsp::HalfDecimator(&inputBuffer.out, &halfBandWindow); + } + else { + decimator = new dsp::HalfDecimator(&decimators[i-1]->out, &halfBandWindow); + } + if (running) { decimator->start(); } decimators.push_back(decimator); } @@ -184,7 +200,28 @@ void SignalPath::setDecimation(int dec) { } void SignalPath::setIQCorrection(bool enabled) { - corrector.bypass = !enabled; + if (iqCorrection == enabled) { return; } + + if (!iqCorrection && enabled) { + if (decimation) { + decimators[0]->setInput(&corrector.out); + } + else { + split.setInput(&corrector.out); + } + if (running) { corrector.start(); } + } + else if (iqCorrection && !enabled) { + if (running) { corrector.stop(); } + if (decimation) { + decimators[0]->setInput(&inputBuffer.out); + } + else { + split.setInput(&inputBuffer.out); + } + } + + iqCorrection = enabled; if (!enabled) { corrector.offset.re = 0; corrector.offset.im = 0; diff --git a/core/src/signal_path/dsp.h b/core/src/signal_path/dsp.h index cf6f2afc..5f122213 100644 --- a/core/src/signal_path/dsp.h +++ b/core/src/signal_path/dsp.h @@ -56,4 +56,5 @@ private: int inputBlockSize; bool bufferingEnabled = false; bool running = false; + bool iqCorrection = false; }; \ No newline at end of file From 003ff37ab800b7ef5e883ef63cdb637a0fea1592 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Wed, 28 Jul 2021 04:21:51 +0200 Subject: [PATCH 04/11] Added support for compound commands and long commands to the rigctl server --- rigctl_server/CMakeLists.txt | 1 + rigctl_server/src/main.cpp | 149 ++++++++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 3 deletions(-) diff --git a/rigctl_server/CMakeLists.txt b/rigctl_server/CMakeLists.txt index cb7ff5ef..c80eca00 100644 --- a/rigctl_server/CMakeLists.txt +++ b/rigctl_server/CMakeLists.txt @@ -14,6 +14,7 @@ file(GLOB SRC "src/*.cpp") include_directories("src/") include_directories("../recorder/src") include_directories("../meteor_demodulator/src") +include_directories("../radio/src") add_library(rigctl_server SHARED ${SRC}) target_link_libraries(rigctl_server PRIVATE sdrpp_core) diff --git a/rigctl_server/src/main.cpp b/rigctl_server/src/main.cpp index b7bb2ab8..a7fac981 100644 --- a/rigctl_server/src/main.cpp +++ b/rigctl_server/src/main.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #define CONCAT(a, b) ((std::string(a) + b).c_str()) #define MAX_COMMAND_LENGTH 8192 @@ -359,9 +361,23 @@ private: // NOTE: THIS STUFF ISN'T THREADSAFE AND WILL LIKELY BREAK. - // Execute commands + // If the command is empty, do nothing if (parts.size() == 0) { return; } - else if (parts[0] == "F") { + + // If the command is a compound command, execute each one separately + if (parts[0].size() > 1 && parts[0][0] != '\\') { + std::string arguments; + if (parts.size() > 1) { arguments = cmd.substr(parts[0].size()); } + for (char c : parts[0]) { + commandHandler(c + arguments); + } + return; + } + + spdlog::info("Rigctl command: '{0}'", cmd); + + // Otherwise, execute the command + if (parts[0] == "F" || parts[0] == "\\set_freq") { std::lock_guard lck(vfoMtx); // if number of arguments isn't correct, return error @@ -384,7 +400,7 @@ private: resp = "RPRT 0\n"; client->write(resp.size(), (uint8_t*)resp.c_str()); } - else if (parts[0] == "f") { + else if (parts[0] == "f" || parts[0] == "\\get_freq") { std::lock_guard lck(vfoMtx); // Get center frequency of the SDR @@ -400,6 +416,133 @@ private: sprintf(buf, "%" PRIu64 "\n", (uint64_t)freq); client->write(strlen(buf), (uint8_t*)buf); } + else if (parts[0] == "M" || parts[0] == "\\set_mode") { + std::lock_guard lck(vfoMtx); + resp = "RPRT 0\n"; + + if (parts.size() >= 2 && parts[1] == "?") { + resp = "FM WFM AM DSB USB CW LSB RAW\n"; + client->write(resp.size(), (uint8_t*)resp.c_str()); + return; + } + + // if number of arguments isn't correct or the VFO is not "VFO", return error + if (parts.size() != 3) { + resp = "RPRT 1\n"; + client->write(resp.size(), (uint8_t*)resp.c_str()); + return; + } + + // Check that the bandwidth is an integer + for (char c : parts[2]) { + if (!std::isdigit(c)) { + resp = "RPRT 1\n"; + client->write(resp.size(), (uint8_t*)resp.c_str()); + return; + } + } + + float newBandwidth = std::atoi(parts[2].c_str()); + + int newMode; + if (parts[1] == "FM") { + newMode = RADIO_IFACE_MODE_NFM; + } + else if (parts[1] == "WFM") { + newMode = RADIO_IFACE_MODE_WFM; + } + else if (parts[1] == "AM") { + newMode = RADIO_IFACE_MODE_AM; + } + else if (parts[1] == "DSB") { + newMode = RADIO_IFACE_MODE_DSB; + } + else if (parts[1] == "USB") { + newMode = RADIO_IFACE_MODE_USB; + } + else if (parts[1] == "CW") { + newMode = RADIO_IFACE_MODE_CW; + } + else if (parts[1] == "LSB") { + newMode = RADIO_IFACE_MODE_LSB; + } + else if (parts[1] == "RAW") { + newMode = RADIO_IFACE_MODE_RAW; + } + else { + resp = "RPRT 1\n"; + client->write(resp.size(), (uint8_t*)resp.c_str()); + return; + } + + // If tuning is enabled, set the mode and optionally the bandwidth + if (!selectedVfo.empty() && core::modComManager.getModuleName(selectedVfo) == "radio" && tuningEnabled) { + core::modComManager.callInterface(selectedVfo, RADIO_IFACE_CMD_SET_MODE, &newMode, NULL); + if (newBandwidth) { + core::modComManager.callInterface(selectedVfo, RADIO_IFACE_CMD_SET_BANDWIDTH, &newBandwidth, NULL); + } + } + + client->write(resp.size(), (uint8_t*)resp.c_str()); + } + else if (parts[0] == "m" || parts[0] == "\\get_mode") { + std::lock_guard lck(vfoMtx); + resp = "RAW\n"; + + if (!selectedVfo.empty() && core::modComManager.getModuleName(selectedVfo) == "radio") { + int mode; + core::modComManager.callInterface(selectedVfo, RADIO_IFACE_CMD_GET_MODE, NULL, &mode); + + if (mode == RADIO_IFACE_MODE_NFM) { + resp = "FM\n"; + } + else if (mode == RADIO_IFACE_MODE_WFM) { + resp = "WFM\n"; + } + else if (mode == RADIO_IFACE_MODE_AM) { + resp = "AM\n"; + } + else if (mode == RADIO_IFACE_MODE_DSB) { + resp = "DSB\n"; + } + else if (mode == RADIO_IFACE_MODE_USB) { + resp = "USB\n"; + } + else if (mode == RADIO_IFACE_MODE_CW) { + resp = "CW\n"; + } + else if (mode == RADIO_IFACE_MODE_LSB) { + resp = "LSB\n"; + } + } + + client->write(resp.size(), (uint8_t*)resp.c_str()); + } + else if (parts[0] == "V" || parts[0] == "\\set_vfo") { + std::lock_guard lck(vfoMtx); + resp = "RPRT 0\n"; + + // if number of arguments isn't correct or the VFO is not "VFO", return error + if (parts.size() != 2) { + resp = "RPRT 1\n"; + client->write(resp.size(), (uint8_t*)resp.c_str()); + return; + } + + if (parts[1] == "?") { + resp = "VFO\n"; + } + else if (parts[1] != "VFO") { + resp = "RPRT 1\n"; + } + + client->write(resp.size(), (uint8_t*)resp.c_str()); + } + else if (parts[0] == "v" || parts[0] == "\\get_vfo") { + std::lock_guard lck(vfoMtx); + resp = "VFO\n"; + client->write(resp.size(), (uint8_t*)resp.c_str()); + } else if (parts[0] == "AOS") { std::lock_guard lck(recorderMtx); // If not controlling the recorder, return From fc30287bed1e160cccc57cb837f01491568a5617 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Wed, 28 Jul 2021 04:34:44 +0200 Subject: [PATCH 05/11] Fixed wrong response for get_mode rigctl command --- rigctl_server/src/main.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/rigctl_server/src/main.cpp b/rigctl_server/src/main.cpp index a7fac981..a78feea6 100644 --- a/rigctl_server/src/main.cpp +++ b/rigctl_server/src/main.cpp @@ -487,35 +487,42 @@ private: } else if (parts[0] == "m" || parts[0] == "\\get_mode") { std::lock_guard lck(vfoMtx); - resp = "RAW\n"; + resp = "RAW "; if (!selectedVfo.empty() && core::modComManager.getModuleName(selectedVfo) == "radio") { int mode; core::modComManager.callInterface(selectedVfo, RADIO_IFACE_CMD_GET_MODE, NULL, &mode); if (mode == RADIO_IFACE_MODE_NFM) { - resp = "FM\n"; + resp = "FM "; } else if (mode == RADIO_IFACE_MODE_WFM) { - resp = "WFM\n"; + resp = "WFM "; } else if (mode == RADIO_IFACE_MODE_AM) { - resp = "AM\n"; + resp = "AM "; } else if (mode == RADIO_IFACE_MODE_DSB) { - resp = "DSB\n"; + resp = "DSB "; } else if (mode == RADIO_IFACE_MODE_USB) { - resp = "USB\n"; + resp = "USB "; } else if (mode == RADIO_IFACE_MODE_CW) { - resp = "CW\n"; + resp = "CW "; } else if (mode == RADIO_IFACE_MODE_LSB) { - resp = "LSB\n"; + resp = "LSB "; } } + if (!selectedVfo.empty()) { + resp += std::to_string((int)sigpath::vfoManager.getBandwidth(selectedVfo)) + "\n"; + } + else { + resp += "0\n"; + } + client->write(resp.size(), (uint8_t*)resp.c_str()); } else if (parts[0] == "V" || parts[0] == "\\set_vfo") { From 2f61b190ca74294490b17cec256b4894d88a9dd7 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Wed, 28 Jul 2021 19:35:25 +0200 Subject: [PATCH 06/11] Fixed RTL-TCP bug --- rtl_tcp_source/src/main.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/rtl_tcp_source/src/main.cpp b/rtl_tcp_source/src/main.cpp index cc0d889e..745f93d2 100644 --- a/rtl_tcp_source/src/main.cpp +++ b/rtl_tcp_source/src/main.cpp @@ -68,7 +68,7 @@ public: directSamplingMode = config.conf["directSamplingMode"]; rtlAGC = config.conf["rtlAGC"]; tunerAGC = config.conf["tunerAGC"]; - gain = config.conf["gainIndex"]; + gain = std::clamp(config.conf["gainIndex"], 0, 28); biasTee = config.conf["biasTee"]; offsetTuning = config.conf["offsetTuning"]; hostStr = hostStr.substr(0, 1023); @@ -127,12 +127,20 @@ private: spdlog::warn("Setting sample rate to {0}", _this->sampleRate); _this->client.setFrequency(_this->freq); _this->client.setSampleRate(_this->sampleRate); - _this->client.setGainMode(!_this->tunerAGC); _this->client.setDirectSampling(_this->directSamplingMode); _this->client.setAGCMode(_this->rtlAGC); - _this->client.setGainIndex(_this->gain); _this->client.setBiasTee(_this->biasTee); _this->client.setOffsetTuning(_this->offsetTuning); + if (_this->tunerAGC) { + _this->client.setGainMode(0); + } + else { + _this->client.setGainMode(1); + + // Setting it twice because for some reason it refuses to do it on the first time + _this->client.setGainIndex(_this->gain); + } + _this->running = true; _this->workerThread = std::thread(worker, _this); spdlog::info("RTLTCPSourceModule '{0}': Start!", _this->name); @@ -229,7 +237,7 @@ private: if (_this->tunerAGC) { style::beginDisabled(); } ImGui::SetNextItemWidth(menuWidth); - if (ImGui::SliderInt(CONCAT("##_gain_select_", _this->name), &_this->gain, 0, 29, "")) { + if (ImGui::SliderInt(CONCAT("##_gain_select_", _this->name), &_this->gain, 0, 28, "")) { if (_this->running) { _this->client.setGainIndex(_this->gain); } From 0741f265d79c3d7c5279171bbbbdbd36fe389850 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Wed, 28 Jul 2021 20:16:31 +0200 Subject: [PATCH 07/11] Fixed bugs with the frequency manager --- core/src/version.h | 2 +- frequency_manager/src/main.cpp | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/core/src/version.h b/core/src/version.h index 7a2ed301..e9d9683a 100644 --- a/core/src/version.h +++ b/core/src/version.h @@ -1,3 +1,3 @@ #pragma once -#define VERSION_STR "1.0.0_rc1" \ No newline at end of file +#define VERSION_STR "1.0.0_rc2" \ No newline at end of file diff --git a/frequency_manager/src/main.cpp b/frequency_manager/src/main.cpp index 7868ab04..d65fc519 100644 --- a/frequency_manager/src/main.cpp +++ b/frequency_manager/src/main.cpp @@ -198,19 +198,20 @@ private: ImGui::EndTable(); - if (strlen(nameBuf) == 0) { style::beginDisabled(); } + bool applyDisabled = (strlen(nameBuf) == 0) || (bookmarks.find(editedBookmarkName) != bookmarks.end() && editedBookmarkName != firstEditedBookmarkName); + if (applyDisabled) { style::beginDisabled(); } if (ImGui::Button("Apply")) { open = false; // If editing, delete the original one if (editOpen) { - bookmarks.erase(firstEeditedBookmarkName); + bookmarks.erase(firstEditedBookmarkName); } - bookmarks[nameBuf] = editedBookmark; + bookmarks[editedBookmarkName] = editedBookmark; saveByName(selectedListName); } - if (strlen(nameBuf) == 0) { style::endDisabled(); } + if (applyDisabled) { style::endDisabled(); } ImGui::SameLine(); if (ImGui::Button("Cancel")) { open = false; @@ -463,7 +464,7 @@ private: _this->editedBookmark.selected = false; - _this->editOpen = true; + _this->createOpen = true; // Find new unique default name if (_this->bookmarks.find("New Bookmark") == _this->bookmarks.end()) { @@ -492,7 +493,7 @@ private: _this->editOpen = true; _this->editedBookmark = _this->bookmarks[selectedNames[0]]; _this->editedBookmarkName = selectedNames[0]; - _this->firstEeditedBookmarkName = selectedNames[0]; + _this->firstEditedBookmarkName = selectedNames[0]; } if (selectedNames.size() != 1 && _this->selectedListName != "") { style::endDisabled(); } @@ -808,7 +809,7 @@ private: std::map bookmarks; std::string editedBookmarkName = ""; - std::string firstEeditedBookmarkName = ""; + std::string firstEditedBookmarkName = ""; FrequencyBookmark editedBookmark; std::vector listNames; From e744520d50707e67eefac87abacc6be82a53de80 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Wed, 28 Jul 2021 22:53:38 +0200 Subject: [PATCH 08/11] Fixed setFFTSize visual bug --- core/src/gui/widgets/waterfall.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/core/src/gui/widgets/waterfall.cpp b/core/src/gui/widgets/waterfall.cpp index 7d3e6d41..d325bc00 100644 --- a/core/src/gui/widgets/waterfall.cpp +++ b/core/src/gui/widgets/waterfall.cpp @@ -520,7 +520,7 @@ namespace ImGui { float pixel; float dataRange = waterfallMax - waterfallMin; int count = std::min(waterfallHeight, fftLines); - if (rawFFTs != NULL) { + if (rawFFTs != NULL && fftLines >= 0) { for (int i = 0; i < count; i++) { drawDataSize = (viewBandwidth / wholeBandwidth) * rawFFTSize; drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2); @@ -530,6 +530,12 @@ namespace ImGui { waterfallFb[(i * dataWidth) + j] = waterfallPallet[(int)(pixel * (WATERFALL_RESOLUTION - 1))]; } } + + for (int i = count; i < waterfallHeight; i++) { + for (int j = 0; j < dataWidth; j++) { + waterfallFb[(i * dataWidth) + j] = (uint32_t)255 << 24; + } + } } delete[] tempData; waterfallUpdate = true; @@ -1028,15 +1034,16 @@ namespace ImGui { void WaterFall::setRawFFTSize(int size, bool lock) { std::lock_guard lck(buf_mtx); rawFFTSize = size; + int wfSize = std::max(1, waterfallHeight); if (rawFFTs != NULL) { - int wfSize = std::max(1, waterfallHeight); rawFFTs = (float*)realloc(rawFFTs, rawFFTSize * wfSize * sizeof(float)); } else { - int wfSize = std::max(1, waterfallHeight); rawFFTs = (float*)malloc(rawFFTSize * wfSize * sizeof(float)); } + fftLines = 0; memset(rawFFTs, 0, rawFFTSize * waterfallHeight * sizeof(float)); + updateWaterfallFb(); } void WaterFall::setBandPlanPos(int pos) { From 7079ddb74ec81d69b2cd8feb7757daf70f2c9ede Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Thu, 29 Jul 2021 02:50:51 +0200 Subject: [PATCH 09/11] Fixes to the UI --- core/src/credits.cpp | 5 +++-- core/src/gui/dialogs/credits.cpp | 11 ++++++----- frequency_manager/src/main.cpp | 8 ++++++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/src/credits.cpp b/core/src/credits.cpp index 4fc3b947..2a65d9f0 100644 --- a/core/src/credits.cpp +++ b/core/src/credits.cpp @@ -24,9 +24,10 @@ namespace sdrpp_credits { const char* libraries[] = { "Dear ImGui (ocornut)", + "fftw3 (fftw.org)", + "glew (Nigel Stewart)", + "glfw (Camilla Löwy)", "json (nlohmann)", - "RtAudio", - "SoapySDR (PothosWare)", "spdlog (gabime)", "Portable File Dialogs" }; diff --git a/core/src/gui/dialogs/credits.cpp b/core/src/gui/dialogs/credits.cpp index 3fb47316..4368346f 100644 --- a/core/src/gui/dialogs/credits.cpp +++ b/core/src/gui/dialogs/credits.cpp @@ -15,6 +15,10 @@ namespace credits { void show() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20.0f, 20.0f)); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0,0,0,0)); + ImVec2 dispSize = ImGui::GetIO().DisplaySize; + ImVec2 center = ImVec2(dispSize.x/2.0f, dispSize.y/2.0f); + ImGui::SetNextWindowPos(center, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::OpenPopup("Credits"); ImGui::BeginPopupModal("Credits", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove); @@ -55,11 +59,8 @@ namespace credits { ImGui::Spacing(); ImGui::Text("SDR++ v" VERSION_STR " (Built at " __TIME__ ", " __DATE__ ")"); - ImVec2 dispSize = ImGui::GetIO().DisplaySize; - ImVec2 winSize = ImGui::GetWindowSize(); - ImGui::SetWindowPos(ImVec2(std::round((dispSize.x/2) - (winSize.x/2)), std::round((dispSize.y/2) - (winSize.y/2)))); - ImGui::EndPopup(); - ImGui::PopStyleVar(1); + ImGui::PopStyleColor(); + ImGui::PopStyleVar(); } } \ No newline at end of file diff --git a/frequency_manager/src/main.cpp b/frequency_manager/src/main.cpp index d65fc519..c7dd08ab 100644 --- a/frequency_manager/src/main.cpp +++ b/frequency_manager/src/main.cpp @@ -680,7 +680,9 @@ private: std::string hoveredBookmarkName; if (_this->bookmarkDisplayMode == BOOKMARK_DISP_MODE_TOP) { - for (auto const bm : _this->waterfallBookmarks) { + int count = _this->waterfallBookmarks.size(); + for (int i = count-1; i >= 0; i--) { + auto& bm = _this->waterfallBookmarks[i]; double centerXpos = args.fftRectMin.x + std::round((bm.bookmark.frequency - args.lowFreq) * args.freqToPixelRatio); ImVec2 nameSize = ImGui::CalcTextSize(bm.bookmarkName.c_str()); ImVec2 rectMin = ImVec2(centerXpos-(nameSize.x/2)-5, args.fftRectMin.y); @@ -697,7 +699,9 @@ private: } } else if (_this->bookmarkDisplayMode == BOOKMARK_DISP_MODE_BOTTOM) { - for (auto const bm : _this->waterfallBookmarks) { + int count = _this->waterfallBookmarks.size(); + for (int i = count-1; i >= 0; i--) { + auto& bm = _this->waterfallBookmarks[i]; double centerXpos = args.fftRectMin.x + std::round((bm.bookmark.frequency - args.lowFreq) * args.freqToPixelRatio); ImVec2 nameSize = ImGui::CalcTextSize(bm.bookmarkName.c_str()); ImVec2 rectMin = ImVec2(centerXpos-(nameSize.x/2)-5, args.fftRectMax.y-nameSize.y); From b7a0f849cfd479729066cbecbf1328db8e75d990 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Thu, 29 Jul 2021 15:07:22 +0200 Subject: [PATCH 10/11] potential fix for Windows 7 freeze on exit --- core/src/config.cpp | 46 ++++++++++++++++------------------ core/src/config.h | 11 ++++---- core/src/core.cpp | 8 ++++++ frequency_manager/src/main.cpp | 3 ++- 4 files changed, 38 insertions(+), 30 deletions(-) diff --git a/core/src/config.cpp b/core/src/config.cpp index 83a6fe1c..a638dbdc 100644 --- a/core/src/config.cpp +++ b/core/src/config.cpp @@ -47,51 +47,49 @@ void ConfigManager::save(bool lock) { } void ConfigManager::enableAutoSave() { - if (!autoSaveEnabled) { - autoSaveEnabled = true; - termFlag = false; - autoSaveThread = std::thread(autoSaveWorker, this); - } + if (autoSaveEnabled) { return; } + autoSaveEnabled = true; + termFlag = false; + autoSaveThread = std::thread(&ConfigManager::autoSaveWorker, this); } void ConfigManager::disableAutoSave() { - if (autoSaveEnabled) { - { - std::lock_guard lock(termMtx); - autoSaveEnabled = false; - termFlag = true; - } - termCond.notify_one(); - if (autoSaveThread.joinable()) { autoSaveThread.join(); } + if (!autoSaveEnabled) { return; } + { + std::lock_guard lock(termMtx); + autoSaveEnabled = false; + termFlag = true; } + termCond.notify_one(); + if (autoSaveThread.joinable()) { autoSaveThread.join(); } } void ConfigManager::acquire() { mtx.lock(); } -void ConfigManager::release(bool changed) { - this->changed |= changed; +void ConfigManager::release(bool modified) { + changed |= modified; mtx.unlock(); } -void ConfigManager::autoSaveWorker(ConfigManager* _this) { - while (_this->autoSaveEnabled) { - if (!_this->mtx.try_lock()) { +void ConfigManager::autoSaveWorker() { + while (autoSaveEnabled) { + if (!mtx.try_lock()) { spdlog::warn("ConfigManager locked, waiting..."); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); continue; } - if (_this->changed) { - _this->changed = false; - _this->save(false); + if (changed) { + changed = false; + save(false); } - _this->mtx.unlock(); + mtx.unlock(); // Sleep but listen for wakeup call { - std::unique_lock lock(_this->termMtx); - _this->termCond.wait_for(lock, std::chrono::milliseconds(1000), [_this]() { return _this->termFlag; } ); + std::unique_lock lock(termMtx); + termCond.wait_for(lock, std::chrono::milliseconds(1000), [this]() { return termFlag; } ); } } } \ No newline at end of file diff --git a/core/src/config.h b/core/src/config.h index 0ebf6fc7..c1bec251 100644 --- a/core/src/config.h +++ b/core/src/config.h @@ -4,6 +4,7 @@ #include #include #include +#include using nlohmann::json; @@ -17,21 +18,21 @@ public: void enableAutoSave(); void disableAutoSave(); void acquire(); - void release(bool changed = false); + void release(bool modified = false); json conf; private: - static void autoSaveWorker(ConfigManager* _this); + void autoSaveWorker(); std::string path = ""; - bool changed = false; - bool autoSaveEnabled = false; + volatile bool changed = false; + volatile bool autoSaveEnabled = false; std::thread autoSaveThread; std::mutex mtx; std::mutex termMtx; std::condition_variable termCond; - bool termFlag = false; + volatile bool termFlag = false; }; \ No newline at end of file diff --git a/core/src/core.cpp b/core/src/core.cpp index 8c21dbb8..1553a480 100644 --- a/core/src/core.cpp +++ b/core/src/core.cpp @@ -463,6 +463,11 @@ int sdrpp_main(int argc, char *argv[]) { glfwSwapBuffers(core::window); } + // Shut down all modules + for (auto& [name, mod] : core::moduleManager.modules) { + mod.end(); + } + // Cleanup ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); @@ -473,5 +478,8 @@ int sdrpp_main(int argc, char *argv[]) { sigpath::signalPath.stop(); + core::configManager.disableAutoSave(); + core::configManager.save(); + return 0; } diff --git a/frequency_manager/src/main.cpp b/frequency_manager/src/main.cpp index c7dd08ab..1c7880c8 100644 --- a/frequency_manager/src/main.cpp +++ b/frequency_manager/src/main.cpp @@ -866,5 +866,6 @@ MOD_EXPORT void _DELETE_INSTANCE_(void* instance) { } MOD_EXPORT void _END_() { - // Nothing here + config.disableAutoSave(); + config.save(); } \ No newline at end of file From 5d08f1018d0e02324610afe25848f9afd763f2fd Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Thu, 29 Jul 2021 17:58:23 +0200 Subject: [PATCH 11/11] Partial fix for the SNR meter not being the right size --- core/src/config.h | 1 - core/src/gui/main_window.cpp | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/config.h b/core/src/config.h index c1bec251..e6bf10a2 100644 --- a/core/src/config.h +++ b/core/src/config.h @@ -4,7 +4,6 @@ #include #include #include -#include using nlohmann::json; diff --git a/core/src/gui/main_window.cpp b/core/src/gui/main_window.cpp index 513a6468..a7c9b61c 100644 --- a/core/src/gui/main_window.cpp +++ b/core/src/gui/main_window.cpp @@ -404,9 +404,11 @@ void MainWindow::draw() { ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetWindowSize().x - 387); + int snrWidth = std::min(300, ImGui::GetWindowSize().x - ImGui::GetCursorPosX() - 87); + + ImGui::SetCursorPosX(ImGui::GetWindowSize().x - (snrWidth+87)); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5); - ImGui::SetNextItemWidth(300); + ImGui::SetNextItemWidth(snrWidth); ImGui::SNRMeter((vfo != NULL) ? gui::waterfall.selectedVFOSNR : 0); ImGui::SameLine();