7 Commits
1.0.0 ... 1.0.3

Author SHA1 Message Date
dcc17cdee7 Fixed LimeSDR + Fixed FFTSize bug + added ppm option to RTL-SDR & RTL-TCP + Fixed RTL-TCP not saving settings 2021-08-10 00:54:00 +02:00
9eb3ef0500 Fixed rigctl server not starting on AOS 2021-08-08 21:38:15 +02:00
ffc20f5fee Added new patron 2021-08-08 21:38:15 +02:00
6144f3a3f9 Update readme.md 2021-08-04 16:46:32 +02:00
a3bda1b8fd Bugfix 2 2021-08-04 00:16:14 +02:00
2a6c742a51 Bugfix 2021-08-04 00:15:05 +02:00
604a559b54 Update readme.md 2021-08-03 21:37:35 +02:00
17 changed files with 156 additions and 26 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ build/
root_dev/ root_dev/
Folder.DotSettings.user Folder.DotSettings.user
CMakeSettings.json CMakeSettings.json
poggers_decoder

View File

@ -32,9 +32,16 @@ void ConfigManager::load(json def, bool lock) {
return; return;
} }
std::ifstream file(path.c_str()); try {
file >> conf; std::ifstream file(path.c_str());
file.close(); file >> conf;
file.close();
}
catch (std::exception e) {
spdlog::error("Config file '{0}' is corrupted, resetting it", path);
conf = def;
save(false);
}
if (lock) { mtx.unlock(); } if (lock) { mtx.unlock(); }
} }

View File

@ -35,6 +35,7 @@ namespace sdrpp_credits {
const char* patrons[] = { const char* patrons[] = {
"Croccydile", "Croccydile",
"Daniele D'Agnelli", "Daniele D'Agnelli",
"EB3FRN",
"Eric Johnson", "Eric Johnson",
"W4IPA", "W4IPA",
"Lee Donaghy", "Lee Donaghy",

View File

@ -53,7 +53,7 @@ namespace dsp {
} }
_in->flush(); _in->flush();
if (!out.swap(outCount)) { return -1; } if (outCount > 0 && !out.swap(outCount)) { return -1; }
return count; return count;
} }
@ -217,7 +217,7 @@ namespace dsp {
memcpy(delay, &_in->readBuf[count - 7], 7 * sizeof(T)); memcpy(delay, &_in->readBuf[count - 7], 7 * sizeof(T));
_in->flush(); _in->flush();
if (!out.swap(outCount)) { return -1; } if (outCount > 0 && !out.swap(outCount)) { return -1; }
return count; return count;
} }

View File

@ -64,7 +64,7 @@ namespace dsp {
if (bitsRead >= _frameLen) { if (bitsRead >= _frameLen) {
if (!out.swap((bitsRead / 8) + ((bitsRead % 8) > 0))) { return -1; } if (!out.swap((bitsRead / 8) + ((bitsRead % 8) > 0))) { return -1; }
bitsRead = -1; bitsRead = -1;
nextBitIsStartOfFrame = true; if (allowSequential) { nextBitIsStartOfFrame = true; }
} }
continue; continue;
@ -100,12 +100,14 @@ namespace dsp {
memcpy(buffer, &_in->readBuf[count - _syncLen], _syncLen); memcpy(buffer, &_in->readBuf[count - _syncLen], _syncLen);
//printf("Block processed\n"); //printf("Block processed\n");
callcount++; callcount++;
_in->flush(); _in->flush();
return count; return count;
} }
bool allowSequential = true;
stream<uint8_t> out; stream<uint8_t> out;
private: private:

View File

@ -396,6 +396,11 @@ namespace dsp {
generic_hier_block<MSKDemod>::_block_init = true; generic_hier_block<MSKDemod>::_block_init = true;
} }
void setInput(stream<complex_t>* input) {
assert((generic_hier_block<MSKDemod>::_block_init));
demod.setInput(input);
}
void setSampleRate(float sampleRate) { void setSampleRate(float sampleRate) {
assert(generic_hier_block<MSKDemod>::_block_init); assert(generic_hier_block<MSKDemod>::_block_init);
generic_hier_block<MSKDemod>::tempStop(); generic_hier_block<MSKDemod>::tempStop();

View File

@ -213,6 +213,11 @@ void MainWindow::fftHandler(dsp::complex_t* samples, int count, void* ctx) {
MainWindow* _this = (MainWindow*)ctx; MainWindow* _this = (MainWindow*)ctx;
std::lock_guard<std::mutex> lck(_this->fft_mtx); std::lock_guard<std::mutex> lck(_this->fft_mtx);
// Check if the count is valid
if (count > _this->fftSize) {
return;
}
// Apply window // Apply window
volk_32fc_32f_multiply_32fc((lv_32fc_t*)_this->fft_in, (lv_32fc_t*)samples, sigpath::signalPath.fftTaps, count); volk_32fc_32f_multiply_32fc((lv_32fc_t*)_this->fft_in, (lv_32fc_t*)samples, sigpath::signalPath.fftTaps, count);
@ -657,9 +662,9 @@ void MainWindow::setFFTSize(int size) {
gui::waterfall.setRawFFTSize(fftSize); gui::waterfall.setRawFFTSize(fftSize);
sigpath::signalPath.setFFTSize(fftSize); sigpath::signalPath.setFFTSize(fftSize);
fftwf_destroy_plan(fftwPlan);
fftwf_free(fft_in); fftwf_free(fft_in);
fftwf_free(fft_out); fftwf_free(fft_out);
fftwf_destroy_plan(fftwPlan);
fft_in = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize); fft_in = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
fft_out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize); fft_out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);

View File

@ -1,9 +1,17 @@
#include <gui/widgets/symbol_diagram.h> #include <gui/widgets/symbol_diagram.h>
namespace ImGui { namespace ImGui {
SymbolDiagram::SymbolDiagram(float scale) { SymbolDiagram::SymbolDiagram(float scale, int count) {
_scale = scale; _scale = scale;
memset(buffer, 0, 1024 * sizeof(float)); sampleCount = count;
buffer = new float[count];
memset(buffer, 0, sampleCount * sizeof(float));
}
SymbolDiagram::~SymbolDiagram() {
delete[] buffer;
} }
void SymbolDiagram::draw(const ImVec2& size_arg) { void SymbolDiagram::draw(const ImVec2& size_arg) {
@ -23,9 +31,9 @@ namespace ImGui {
window->DrawList->AddRectFilled(min, ImVec2(min.x+size.x, min.y+size.y), IM_COL32(0,0,0,255)); window->DrawList->AddRectFilled(min, ImVec2(min.x+size.x, min.y+size.y), IM_COL32(0,0,0,255));
ImU32 col = ImGui::GetColorU32(ImGuiCol_CheckMark, 0.7f); ImU32 col = ImGui::GetColorU32(ImGuiCol_CheckMark, 0.7f);
float increment = size.x / 1024.0f; float increment = size.x / (float)sampleCount;
float val; float val;
for (int i = 0; i < 1024; i++) { for (int i = 0; i < sampleCount; i++) {
val = buffer[i] * _scale; val = buffer[i] * _scale;
if (val > 1.0f || val < -1.0f) { continue; } if (val > 1.0f || val < -1.0f) { continue; }
window->DrawList->AddCircleFilled(ImVec2(((float)i * increment) + min.x, ((val + 1) * (size.y*0.5f)) + min.y), 2, col); window->DrawList->AddCircleFilled(ImVec2(((float)i * increment) + min.x, ((val + 1) * (size.y*0.5f)) + min.y), 2, col);

View File

@ -8,7 +8,8 @@
namespace ImGui { namespace ImGui {
class SymbolDiagram { class SymbolDiagram {
public: public:
SymbolDiagram(float _scale = 1.0f); SymbolDiagram(float _scale = 1.0f, int count = 1024);
~SymbolDiagram();
void draw(const ImVec2& size_arg = ImVec2(0, 0)); void draw(const ImVec2& size_arg = ImVec2(0, 0));
@ -18,8 +19,9 @@ namespace ImGui {
private: private:
std::mutex bufferMtx; std::mutex bufferMtx;
float buffer[1024]; float* buffer;
float _scale; float _scale;
int sampleCount = 0;
}; };
} }

View File

@ -682,6 +682,7 @@ namespace ImGui {
if (waterfallVisible) { if (waterfallVisible) {
FFTAreaHeight = std::min<int>(FFTAreaHeight, widgetSize.y - 50); FFTAreaHeight = std::min<int>(FFTAreaHeight, widgetSize.y - 50);
newFFTAreaHeight = FFTAreaHeight;
fftHeight = FFTAreaHeight - 50; fftHeight = FFTAreaHeight - 50;
waterfallHeight = widgetSize.y - fftHeight - 52; waterfallHeight = widgetSize.y - fftHeight - 52;
} }

View File

@ -1,3 +1,3 @@
#pragma once #pragma once
#define VERSION_STR "1.0.0" #define VERSION_STR "1.0.3"

View File

@ -335,7 +335,7 @@ private:
// Setup and start stream // Setup and start stream
int sampCount = _this->sampleRate / 200; int sampCount = _this->sampleRate / 200;
_this->devStream.isTx = false; _this->devStream.isTx = false;
_this->devStream.channel = 0; _this->devStream.channel = _this->chanId;
_this->devStream.fifoSize = sampCount; // TODO: Check what it's actually supposed to be _this->devStream.fifoSize = sampCount; // TODO: Check what it's actually supposed to be
_this->devStream.throughputVsLatency = 0.5f; _this->devStream.throughputVsLatency = 0.5f;
_this->devStream.dataFmt = _this->devStream.LMS_FMT_F32; _this->devStream.dataFmt = _this->devStream.LMS_FMT_F32;

View File

@ -270,16 +270,16 @@ Modules in beta are still included in releases for the most part but not enabled
|------------------|------------|-------------------|----------------------------|:---------------:|:-----------------------:|:---------------------------:| |------------------|------------|-------------------|----------------------------|:---------------:|:-----------------------:|:---------------------------:|
| airspy_source | Working | libairspy | OPT_BUILD_AIRSPY_SOURCE | ✅ | ✅ | ✅ | | airspy_source | Working | libairspy | OPT_BUILD_AIRSPY_SOURCE | ✅ | ✅ | ✅ |
| airspyhf_source | Working | libairspyhf | OPT_BUILD_AIRSPYHF_SOURCE | ✅ | ✅ | ✅ | | airspyhf_source | Working | libairspyhf | OPT_BUILD_AIRSPYHF_SOURCE | ✅ | ✅ | ✅ |
| bladerf_source | Beta | libbladeRF | OPT_BUILD_BLADERF_SOURCE | ⛔ | ⚠️ (not Debian Buster) | ✅ | | bladerf_source | Working | libbladeRF | OPT_BUILD_BLADERF_SOURCE | ⛔ | ⚠️ (not Debian Buster) | ✅ |
| file_source | Working | - | OPT_BUILD_FILE_SOURCE | ✅ | ✅ | ✅ | | file_source | Working | - | OPT_BUILD_FILE_SOURCE | ✅ | ✅ | ✅ |
| hackrf_source | Working | libhackrf | OPT_BUILD_HACKRF_SOURCE | ✅ | ✅ | ✅ | | hackrf_source | Working | libhackrf | OPT_BUILD_HACKRF_SOURCE | ✅ | ✅ | ✅ |
| limesdr_source | Beta | liblimesuite | OPT_BUILD_LIMESDR_SOURCE | ⛔ | ✅ | ✅ | | limesdr_source | Working | liblimesuite | OPT_BUILD_LIMESDR_SOURCE | ⛔ | ✅ | ✅ |
| sddc_source | Unfinished | - | OPT_BUILD_SDDC_SOURCE | ⛔ | ⛔ | ⛔ | | sddc_source | Unfinished | - | OPT_BUILD_SDDC_SOURCE | ⛔ | ⛔ | ⛔ |
| rtl_sdr_source | Working | librtlsdr | OPT_BUILD_RTL_SDR_SOURCE | ✅ | ✅ | ✅ | | rtl_sdr_source | Working | librtlsdr | OPT_BUILD_RTL_SDR_SOURCE | ✅ | ✅ | ✅ |
| rtl_tcp_source | Working | - | OPT_BUILD_RTL_TCP_SOURCE | ✅ | ✅ | ✅ | | rtl_tcp_source | Working | - | OPT_BUILD_RTL_TCP_SOURCE | ✅ | ✅ | ✅ |
| sdrplay_source | Working | SDRplay API | OPT_BUILD_SDRPLAY_SOURCE | ⛔ | ✅ | ✅ | | sdrplay_source | Working | SDRplay API | OPT_BUILD_SDRPLAY_SOURCE | ⛔ | ✅ | ✅ |
| soapy_source | Working | soapysdr | OPT_BUILD_SOAPY_SOURCE | ✅ | ✅ | ✅ | | soapy_source | Working | soapysdr | OPT_BUILD_SOAPY_SOURCE | ✅ | ✅ | ✅ |
| spyserver_source | Beta | - | OPT_BUILD_SPYSERVER_SOURCE | ✅ | ✅ | ✅ | | spyserver_source | Working | - | OPT_BUILD_SPYSERVER_SOURCE | ✅ | ✅ | ✅ |
| plutosdr_source | Working | libiio, libad9361 | OPT_BUILD_PLUTOSDR_SOURCE | ✅ | ✅ | ✅ | | plutosdr_source | Working | libiio, libad9361 | OPT_BUILD_PLUTOSDR_SOURCE | ✅ | ✅ | ✅ |
## Sinks ## Sinks
@ -287,14 +287,14 @@ Modules in beta are still included in releases for the most part but not enabled
| Name | Stage | Dependencies | Option | Built by default| Built in Release | Enabled in SDR++ by default | | Name | Stage | Dependencies | Option | Built by default| Built in Release | Enabled in SDR++ by default |
|--------------------|------------|--------------|------------------------------|:---------------:|:----------------:|:---------------------------:| |--------------------|------------|--------------|------------------------------|:---------------:|:----------------:|:---------------------------:|
| audio_sink | Working | rtaudio | OPT_BUILD_AUDIO_SINK | ✅ | ✅ | ✅ | | audio_sink | Working | rtaudio | OPT_BUILD_AUDIO_SINK | ✅ | ✅ | ✅ |
| network_sink | Beta | - | OPT_BUILD_NETWORK_SINK | ✅ | ✅ | ✅ | | network_sink | Working | - | OPT_BUILD_NETWORK_SINK | ✅ | ✅ | ✅ |
| new_portaudio_sink | Beta | portaudio | OPT_BUILD_NEW_PORTAUDIO_SINK | ⛔ | ✅ | ⛔ | | new_portaudio_sink | Beta | portaudio | OPT_BUILD_NEW_PORTAUDIO_SINK | ⛔ | ✅ | ⛔ |
## Decoders ## Decoders
| Name | Stage | Dependencies | Option | Built by default| Built in Release | Enabled in SDR++ by default | | Name | Stage | Dependencies | Option | Built by default| Built in Release | Enabled in SDR++ by default |
|---------------------|------------|--------------|-------------------------------|:---------------:|:----------------:|:---------------------------:| |---------------------|------------|--------------|-------------------------------|:---------------:|:----------------:|:---------------------------:|
| falcon9_decoder | Beta | ffplay | OPT_BUILD_FALCON9_DECODER | ⛔ | ⛔ | ⛔ | | falcon9_decoder | Unfinished | ffplay | OPT_BUILD_FALCON9_DECODER | ⛔ | ⛔ | ⛔ |
| meteor_demodulator | Working | - | OPT_BUILD_METEOR_DEMODULATOR | ✅ | ✅ | ⛔ | | meteor_demodulator | Working | - | OPT_BUILD_METEOR_DEMODULATOR | ✅ | ✅ | ⛔ |
| radio | Working | - | OPT_BUILD_RADIO | ✅ | ✅ | ✅ | | radio | Working | - | OPT_BUILD_RADIO | ✅ | ✅ | ✅ |
| weather_sat_decoder | Unfinished | - | OPT_BUILD_WEATHER_SAT_DECODER | ⛔ | ⛔ | ⛔ | | weather_sat_decoder | Unfinished | - | OPT_BUILD_WEATHER_SAT_DECODER | ⛔ | ⛔ | ⛔ |
@ -304,14 +304,22 @@ Modules in beta are still included in releases for the most part but not enabled
| Name | Stage | Dependencies | Option | Built by default | Built in Release | Enabled in SDR++ by default | | Name | Stage | Dependencies | Option | Built by default | Built in Release | Enabled in SDR++ by default |
|---------------------|------------|--------------|-----------------------------|:----------------:|:----------------:|:---------------------------:| |---------------------|------------|--------------|-----------------------------|:----------------:|:----------------:|:---------------------------:|
| discord_integration | Working | - | OPT_BUILD_DISCORD_PRESENCE | ✅ | ✅ | ⛔ | | discord_integration | Working | - | OPT_BUILD_DISCORD_PRESENCE | ✅ | ✅ | ⛔ |
| frequency_manager | Beta | - | OPT_BUILD_FREQUENCY_MANAGER | ✅ | ✅ | ✅ | | frequency_manager | Working | - | OPT_BUILD_FREQUENCY_MANAGER | ✅ | ✅ | ✅ |
| recorder | Working | - | OPT_BUILD_RECORDER | ✅ | ✅ | ✅ | | recorder | Working | - | OPT_BUILD_RECORDER | ✅ | ✅ | ✅ |
| rigctl_server | Unfinished | - | OPT_BUILD_RIGCTL_SERVER | ✅ | ✅ | ⛔ | | rigctl_server | Working | - | OPT_BUILD_RIGCTL_SERVER | ✅ | ✅ | ⛔ |
# Troubleshooting # Troubleshooting
First, please make sure you're running the latest automated build. If your issue is linked to a bug it is likely that is has already been fixed in later releases First, please make sure you're running the latest automated build. If your issue is linked to a bug it is likely that is has already been fixed in later releases
## SDR++ crashes then it won't start again no matter what
This is a bug in 1.0.0 that was fixed in 1.0.1
In some cases, if a crash happened while the config was being saved, the config file woul be corrupted and SDR++ would refuse to start because of it.
This has now been fixed. If a config file is corrupted it'll just reset it to its default state.
## "hash collision" error when starting ## "hash collision" error when starting
You likely installed the `soapysdr-module-all` package on Ubuntu/Debian. If not it's still a SoapySDR bug caused by multiple soapy modules coming in conflict. Uninstall anything related to SoapySDR then install soapysdr itself and only the soapy modules you actually need. You likely installed the `soapysdr-module-all` package on Ubuntu/Debian. If not it's still a SoapySDR bug caused by multiple soapy modules coming in conflict. Uninstall anything related to SoapySDR then install soapysdr itself and only the soapy modules you actually need.
@ -347,6 +355,7 @@ I will soon publish a contributing.md listing the code style to use.
* [Croccydile](https://example.com/) * [Croccydile](https://example.com/)
* [Daniele D'Agnelli](https://linkedin.com/in/dagnelli) * [Daniele D'Agnelli](https://linkedin.com/in/dagnelli)
* [EB3FRN](https://www.eb3frn.net/)
* [Eric Johnson](https://example.com/) * [Eric Johnson](https://example.com/)
* [W4IPA](https://twitter.com/W4IPAstroke5) * [W4IPA](https://twitter.com/W4IPAstroke5)
* [Lee Donaghy](https://github.com/github) * [Lee Donaghy](https://github.com/github)

View File

@ -365,7 +365,7 @@ private:
if (parts.size() == 0) { return; } if (parts.size() == 0) { return; }
// If the command is a compound command, execute each one separately // If the command is a compound command, execute each one separately
if (parts[0].size() > 1 && parts[0][0] != '\\') { if (parts[0].size() > 1 && parts[0][0] != '\\' && parts[0] != "AOS" && parts[0] != "LOS") {
std::string arguments; std::string arguments;
if (parts.size() > 1) { arguments = cmd.substr(parts[0].size()); } if (parts.size() > 1) { arguments = cmd.substr(parts[0].size()); }
for (char c : parts[0]) { for (char c : parts[0]) {

View File

@ -162,6 +162,7 @@ public:
created = true; created = true;
config.conf["devices"][selectedDevName]["sampleRate"] = 2400000.0; config.conf["devices"][selectedDevName]["sampleRate"] = 2400000.0;
config.conf["devices"][selectedDevName]["directSampling"] = directSamplingMode; config.conf["devices"][selectedDevName]["directSampling"] = directSamplingMode;
config.conf["devices"][selectedDevName]["ppm"] = 0;
config.conf["devices"][selectedDevName]["biasT"] = biasT; config.conf["devices"][selectedDevName]["biasT"] = biasT;
config.conf["devices"][selectedDevName]["offsetTuning"] = offsetTuning; config.conf["devices"][selectedDevName]["offsetTuning"] = offsetTuning;
config.conf["devices"][selectedDevName]["rtlAgc"] = rtlAgc; config.conf["devices"][selectedDevName]["rtlAgc"] = rtlAgc;
@ -187,6 +188,10 @@ public:
directSamplingMode = config.conf["devices"][selectedDevName]["directSampling"]; directSamplingMode = config.conf["devices"][selectedDevName]["directSampling"];
} }
if (config.conf["devices"][selectedDevName].contains("ppm")) {
ppm = config.conf["devices"][selectedDevName]["ppm"];
}
if (config.conf["devices"][selectedDevName].contains("biasT")) { if (config.conf["devices"][selectedDevName].contains("biasT")) {
biasT = config.conf["devices"][selectedDevName]["biasT"]; biasT = config.conf["devices"][selectedDevName]["biasT"];
} }
@ -256,6 +261,7 @@ private:
rtlsdr_set_sample_rate(_this->openDev, _this->sampleRate); rtlsdr_set_sample_rate(_this->openDev, _this->sampleRate);
rtlsdr_set_center_freq(_this->openDev, _this->freq); rtlsdr_set_center_freq(_this->openDev, _this->freq);
rtlsdr_set_freq_correction(_this->openDev, _this->ppm);
rtlsdr_set_tuner_bandwidth(_this->openDev, 0); rtlsdr_set_tuner_bandwidth(_this->openDev, 0);
rtlsdr_set_direct_sampling(_this->openDev, _this->directSamplingMode); rtlsdr_set_direct_sampling(_this->openDev, _this->directSamplingMode);
rtlsdr_set_bias_tee(_this->openDev, _this->biasT); rtlsdr_set_bias_tee(_this->openDev, _this->biasT);
@ -372,6 +378,21 @@ private:
} }
} }
ImGui::Text("PPM Correction");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputInt(CONCAT("##_rtlsdr_ppm_", _this->name), &_this->ppm, 1, 10)) {
_this->ppm = std::clamp<int>(_this->ppm, -1000000, 1000000);
if (_this->running) {
rtlsdr_set_freq_correction(_this->openDev, _this->ppm);
}
if (_this->selectedDevName != "") {
config.acquire();
config.conf["devices"][_this->selectedDevName]["ppm"] = _this->ppm;
config.release(true);
}
}
if (ImGui::Checkbox(CONCAT("Bias T##_rtlsdr_rtl_biast_", _this->name), &_this->biasT)) { if (ImGui::Checkbox(CONCAT("Bias T##_rtlsdr_rtl_biast_", _this->name), &_this->biasT)) {
if (_this->running) { if (_this->running) {
rtlsdr_set_bias_tee(_this->openDev, _this->biasT); rtlsdr_set_bias_tee(_this->openDev, _this->biasT);
@ -471,6 +492,8 @@ private:
int devCount = 0; int devCount = 0;
std::thread workerThread; std::thread workerThread;
int ppm = 0;
bool biasT = false; bool biasT = false;
int gainId = 0; int gainId = 0;

View File

@ -48,6 +48,8 @@ const char* sampleRatesTxt[] = {
"3.2MHz" "3.2MHz"
}; };
#define SAMPLE_RATE_COUNT (sizeof(sampleRates) / sizeof(double))
class RTLTCPSourceModule : public ModuleManager::Instance { class RTLTCPSourceModule : public ModuleManager::Instance {
public: public:
RTLTCPSourceModule(std::string name) { RTLTCPSourceModule(std::string name) {
@ -55,8 +57,9 @@ public:
sampleRate = 2400000.0; sampleRate = 2400000.0;
int srCount = sizeof(sampleRatesTxt) / sizeof(char*); int _24id = 0;
for (int i = 0; i < srCount; i++) { for (int i = 0; i < SAMPLE_RATE_COUNT; i++) {
if (sampleRates[i] == 2400000) { _24id = i; }
srTxt += sampleRatesTxt[i]; srTxt += sampleRatesTxt[i];
srTxt += '\0'; srTxt += '\0';
} }
@ -65,7 +68,9 @@ public:
config.acquire(); config.acquire();
std::string hostStr = config.conf["host"]; std::string hostStr = config.conf["host"];
port = config.conf["port"]; port = config.conf["port"];
double wantedSr = config.conf["sampleRate"];
directSamplingMode = config.conf["directSamplingMode"]; directSamplingMode = config.conf["directSamplingMode"];
ppm = config.conf["ppm"];
rtlAGC = config.conf["rtlAGC"]; rtlAGC = config.conf["rtlAGC"];
tunerAGC = config.conf["tunerAGC"]; tunerAGC = config.conf["tunerAGC"];
gain = std::clamp<int>(config.conf["gainIndex"], 0, 28); gain = std::clamp<int>(config.conf["gainIndex"], 0, 28);
@ -75,6 +80,20 @@ public:
strcpy(ip, hostStr.c_str()); strcpy(ip, hostStr.c_str());
config.release(); config.release();
bool found = false;
for (int i = 0; i < SAMPLE_RATE_COUNT; i++) {
if (sampleRates[i] == wantedSr) {
found = true;
srId = i;
sampleRate = sampleRates[i];
break;
}
}
if (!found) {
srId = _24id;
sampleRate = sampleRates[_24id];
}
handler.ctx = this; handler.ctx = this;
handler.selectHandler = menuSelected; handler.selectHandler = menuSelected;
handler.deselectHandler = menuDeselected; handler.deselectHandler = menuDeselected;
@ -127,6 +146,7 @@ private:
spdlog::warn("Setting sample rate to {0}", _this->sampleRate); spdlog::warn("Setting sample rate to {0}", _this->sampleRate);
_this->client.setFrequency(_this->freq); _this->client.setFrequency(_this->freq);
_this->client.setSampleRate(_this->sampleRate); _this->client.setSampleRate(_this->sampleRate);
_this->client.setPPM(_this->ppm);
_this->client.setDirectSampling(_this->directSamplingMode); _this->client.setDirectSampling(_this->directSamplingMode);
_this->client.setAGCMode(_this->rtlAGC); _this->client.setAGCMode(_this->rtlAGC);
_this->client.setBiasTee(_this->biasTee); _this->client.setBiasTee(_this->biasTee);
@ -191,6 +211,9 @@ private:
if (ImGui::Combo(CONCAT("##_rtltcp_sr_", _this->name), &_this->srId, _this->srTxt.c_str())) { if (ImGui::Combo(CONCAT("##_rtltcp_sr_", _this->name), &_this->srId, _this->srTxt.c_str())) {
_this->sampleRate = sampleRates[_this->srId]; _this->sampleRate = sampleRates[_this->srId];
core::setInputSampleRate(_this->sampleRate); core::setInputSampleRate(_this->sampleRate);
config.acquire();
config.conf["sampleRate"] = _this->sampleRate;
config.release(true);
} }
if (_this->running) { style::endDisabled(); } if (_this->running) { style::endDisabled(); }
@ -203,18 +226,39 @@ private:
_this->client.setDirectSampling(_this->directSamplingMode); _this->client.setDirectSampling(_this->directSamplingMode);
_this->client.setGainIndex(_this->gain); _this->client.setGainIndex(_this->gain);
} }
config.acquire();
config.conf["directSamplingMode"] = _this->directSamplingMode;
config.release(true);
}
ImGui::Text("PPM Correction");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputInt(CONCAT("##_rtltcp_ppm_", _this->name), &_this->ppm, 1, 10)) {
if (_this->running) {
_this->client.setPPM(_this->ppm);
}
config.acquire();
config.conf["ppm"] = _this->ppm;
config.release(true);
} }
if (ImGui::Checkbox(CONCAT("Bias-T##_biast_select_", _this->name), &_this->biasTee)) { if (ImGui::Checkbox(CONCAT("Bias-T##_biast_select_", _this->name), &_this->biasTee)) {
if (_this->running) { if (_this->running) {
_this->client.setBiasTee(_this->biasTee); _this->client.setBiasTee(_this->biasTee);
} }
config.acquire();
config.conf["biasTee"] = _this->biasTee;
config.release(true);
} }
if (ImGui::Checkbox(CONCAT("Offset Tuning##_biast_select_", _this->name), &_this->offsetTuning)) { if (ImGui::Checkbox(CONCAT("Offset Tuning##_biast_select_", _this->name), &_this->offsetTuning)) {
if (_this->running) { if (_this->running) {
_this->client.setOffsetTuning(_this->offsetTuning); _this->client.setOffsetTuning(_this->offsetTuning);
} }
config.acquire();
config.conf["offsetTuning"] = _this->offsetTuning;
config.release(true);
} }
if (ImGui::Checkbox("RTL AGC", &_this->rtlAGC)) { if (ImGui::Checkbox("RTL AGC", &_this->rtlAGC)) {
@ -224,6 +268,9 @@ private:
_this->client.setGainIndex(_this->gain); _this->client.setGainIndex(_this->gain);
} }
} }
config.acquire();
config.conf["rtlAGC"] = _this->rtlAGC;
config.release(true);
} }
if (ImGui::Checkbox("Tuner AGC", &_this->tunerAGC)) { if (ImGui::Checkbox("Tuner AGC", &_this->tunerAGC)) {
@ -233,6 +280,9 @@ private:
_this->client.setGainIndex(_this->gain); _this->client.setGainIndex(_this->gain);
} }
} }
config.acquire();
config.conf["tunerAGC"] = _this->tunerAGC;
config.release(true);
} }
if (_this->tunerAGC) { style::beginDisabled(); } if (_this->tunerAGC) { style::beginDisabled(); }
@ -241,6 +291,9 @@ private:
if (_this->running) { if (_this->running) {
_this->client.setGainIndex(_this->gain); _this->client.setGainIndex(_this->gain);
} }
config.acquire();
config.conf["gainIndex"] = _this->gain;
config.release(true);
} }
if (_this->tunerAGC) { style::endDisabled(); } if (_this->tunerAGC) { style::endDisabled(); }
} }
@ -275,6 +328,7 @@ private:
char ip[1024] = "localhost"; char ip[1024] = "localhost";
int port = 1234; int port = 1234;
int gain = 0; int gain = 0;
int ppm = 0;
bool rtlAGC = false; bool rtlAGC = false;
bool tunerAGC = false; bool tunerAGC = false;
int directSamplingMode = 0; int directSamplingMode = 0;
@ -290,7 +344,9 @@ MOD_EXPORT void _INIT_() {
json defConf; json defConf;
defConf["host"] = "localhost"; defConf["host"] = "localhost";
defConf["port"] = 1234; defConf["port"] = 1234;
defConf["sampleRate"] = 2400000.0;
defConf["directSamplingMode"] = 0; defConf["directSamplingMode"] = 0;
defConf["ppm"] = 0;
defConf["rtlAGC"] = false; defConf["rtlAGC"] = false;
defConf["tunerAGC"] = false; defConf["tunerAGC"] = false;
defConf["gainIndex"] = 0; defConf["gainIndex"] = 0;
@ -306,6 +362,12 @@ MOD_EXPORT void _INIT_() {
if (!config.conf.contains("offsetTuning")) { if (!config.conf.contains("offsetTuning")) {
config.conf["offsetTuning"] = false; config.conf["offsetTuning"] = false;
} }
if (!config.conf.contains("ppm")) {
config.conf["ppm"] = 0;
}
if (!config.conf.contains("sampleRate")) {
config.conf["sampleRate"] = 2400000.0;
}
config.release(true); config.release(true);
} }

View File

@ -166,6 +166,10 @@ public:
sendCommand(4, gain); sendCommand(4, gain);
} }
void setPPM(int ppm) {
sendCommand(5, (uint32_t)ppm);
}
void setAGCMode(int mode) { void setAGCMode(int mode) {
sendCommand(8, mode); sendCommand(8, mode);
} }