From 31c9e5767e43b26bb085c62379906ca67f5ed3a6 Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Sun, 28 Jan 2024 00:03:04 +0100 Subject: [PATCH 1/7] beginning of PlutoSDR context enumeration --- source_modules/plutosdr_source/src/main.cpp | 75 +++++++++++++++++---- 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/source_modules/plutosdr_source/src/main.cpp b/source_modules/plutosdr_source/src/main.cpp index d0684758..206ce84a 100644 --- a/source_modules/plutosdr_source/src/main.cpp +++ b/source_modules/plutosdr_source/src/main.cpp @@ -28,10 +28,6 @@ public: // Load configuration config.acquire(); - if (config.conf.contains("IP")) { - std::string _ip = config.conf["IP"]; - strcpy(&ip[3], _ip.c_str()); - } if (config.conf.contains("sampleRate")) { sampleRate = config.conf["sampleRate"]; } @@ -82,6 +78,12 @@ public: gainModes.define(2, "Slow Attack", "slow_attack"); gainModes.define(3, "Hybrid", "hybrid"); + // Enumerate devices + refresh(); + + // Select device + // TODO + // Register source handler.ctx = this; handler.selectHandler = menuSelected; @@ -128,6 +130,41 @@ private: return std::string(buf); } + void refresh() { + // Clear device list + devices.clear(); + + // Create scan context + iio_scan_context* sctx = iio_create_scan_context(NULL, 0); + if (!sctx) { + flog::error("Failed get scan context"); + return; + } + + // Enumerate devices + iio_context_info** ctxInfoList; + ssize_t count = iio_scan_context_get_info_list(sctx, &ctxInfoList); + if (count < 0) { + flog::error("Failed to enumerate contexts"); + return; + } + for (ssize_t i = 0; i < count; i++) { + iio_context_info* info = ctxInfoList[i]; + std::string desc = iio_context_info_get_description(info); + std::string uri = iio_context_info_get_uri(info); + + devices.define(uri, name, uri); + } + iio_context_info_list_free(ctxInfoList); + + // Destroy scan context + iio_scan_context_destroy(sctx); + } + + void select(const std::string& nuri) { + uri = nuri; + } + static void menuSelected(void* ctx) { PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx; core::setInputSampleRate(_this->sampleRate); @@ -144,9 +181,9 @@ private: if (_this->running) { return; } // Open context - _this->ctx = iio_create_context_from_uri(_this->ip); + _this->ctx = iio_create_context_from_uri(_this->uri.c_str()); if (_this->ctx == NULL) { - flog::error("Could not open pluto"); + flog::error("Could not open pluto ({})", _this->uri); return; } @@ -223,16 +260,13 @@ private: PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx; if (_this->running) { SmGui::BeginDisabled(); } - SmGui::LeftLabel("IP"); SmGui::FillWidth(); - if (SmGui::InputText(CONCAT("##_pluto_ip_", _this->name), &_this->ip[3], 16)) { - config.acquire(); - config.conf["IP"] = &_this->ip[3]; - config.release(true); + SmGui::ForceSync(); + if (SmGui::Combo("##plutosdr_dev_sel", &_this->devId, _this->devices.txt)) { + _this->select(_this->devices.value(_this->devId)); + // TODO: Save } - SmGui::LeftLabel("Samplerate"); - SmGui::FillWidth(); if (SmGui::Combo(CONCAT("##_pluto_sr_", _this->name), &_this->srId, _this->samplerates.txt)) { _this->sampleRate = _this->samplerates.value(_this->srId); core::setInputSampleRate(_this->sampleRate); @@ -240,6 +274,16 @@ private: config.conf["sampleRate"] = _this->sampleRate; config.release(true); } + + // Refresh button + SmGui::SameLine(); + SmGui::FillWidth(); + SmGui::ForceSync(); + if (SmGui::Button(CONCAT("Refresh##_pluto_refr_", _this->name))) { + _this->refresh(); + _this->select(_this->uri); + + } if (_this->running) { SmGui::EndDisabled(); } SmGui::LeftLabel("Bandwidth"); @@ -343,16 +387,19 @@ private: iio_channel* rxChan = NULL; bool running = false; + std::string uri = ""; + double freq; - char ip[1024] = "ip:192.168.2.1"; float sampleRate = 4000000; int bandwidth = 0; int gainMode = 0; float gain = 0; + int devId = 0; int srId = 0; int bwId = 0; + OptionList devices; OptionList samplerates; OptionList bandwidths; OptionList gainModes; From 175992b08109a98f44455b87b6d49e464cba68ee Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Sun, 28 Jan 2024 00:25:46 +0100 Subject: [PATCH 2/7] add android workaround --- source_modules/plutosdr_source/src/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source_modules/plutosdr_source/src/main.cpp b/source_modules/plutosdr_source/src/main.cpp index 206ce84a..2a79f73f 100644 --- a/source_modules/plutosdr_source/src/main.cpp +++ b/source_modules/plutosdr_source/src/main.cpp @@ -153,12 +153,18 @@ private: std::string desc = iio_context_info_get_description(info); std::string uri = iio_context_info_get_uri(info); - devices.define(uri, name, uri); + devices.define(uri, desc, uri); } iio_context_info_list_free(ctxInfoList); // Destroy scan context iio_scan_context_destroy(sctx); + +#ifdef __ANDROID__ + // On Android, a default IP entry must be made (TODO: This is not ideal since the IP cannot be changed) + const char* androidURI = "ip:192.168.2.1"; + devices.define(androidURI, "Default (192.168.2.1)", androidURI); +#endif } void select(const std::string& nuri) { From 32cbd726fd19bc27ebdeffe5216a646a6c0e9453 Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Sun, 28 Jan 2024 02:16:20 +0100 Subject: [PATCH 3/7] implement enumeration and settings for plutosdr source --- source_modules/plutosdr_source/src/main.cpp | 196 ++++++++++++-------- 1 file changed, 121 insertions(+), 75 deletions(-) diff --git a/source_modules/plutosdr_source/src/main.cpp b/source_modules/plutosdr_source/src/main.cpp index 2a79f73f..868a4333 100644 --- a/source_modules/plutosdr_source/src/main.cpp +++ b/source_modules/plutosdr_source/src/main.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #define CONCAT(a, b) ((std::string(a) + b).c_str()) @@ -26,63 +27,32 @@ public: PlutoSDRSourceModule(std::string name) { this->name = name; - // Load configuration - config.acquire(); - if (config.conf.contains("sampleRate")) { - sampleRate = config.conf["sampleRate"]; - } - if (config.conf.contains("bandwidth")) { - bandwidth = config.conf["bandwidth"]; - } - if (config.conf.contains("gainMode")) { - gainMode = config.conf["gainMode"]; - } - if (config.conf.contains("gain")) { - gain = config.conf["gain"]; - } - config.release(); - // Define valid samplerates for (int sr = 1000000; sr <= 61440000; sr += 500000) { samplerates.define(sr, getBandwdithScaled(sr), sr); } samplerates.define(61440000, getBandwdithScaled(61440000.0), 61440000.0); - // Set samplerate ID - if (samplerates.keyExists(sampleRate)) { - srId = samplerates.keyId(sampleRate); - } - else { - srId = 0; - sampleRate = samplerates.value(srId); - } - // Define valid bandwidths bandwidths.define(0, "Auto", 0); for (int bw = 1000000.0; bw <= 52000000; bw += 500000) { bandwidths.define(bw, getBandwdithScaled(bw), bw); } - // Set bandwidth ID - if (bandwidths.keyExists(bandwidth)) { - bwId = bandwidths.keyId(bandwidth); - } - else { - bwId = 0; - bandwidth = bandwidths.value(bwId); - } - // Define gain modes - gainModes.define(0, "Manual", "manual"); - gainModes.define(1, "Fast Attack", "fast_attack"); - gainModes.define(2, "Slow Attack", "slow_attack"); - gainModes.define(3, "Hybrid", "hybrid"); + gainModes.define("manual", "Manual", "manual"); + gainModes.define("fast_attack", "Fast Attack", "fast_attack"); + gainModes.define("slow_attack", "Slow Attack", "slow_attack"); + gainModes.define("hybrid", "Hybrid", "hybrid"); // Enumerate devices refresh(); // Select device - // TODO + config.acquire(); + uri = config.conf["device"]; + config.release(); + select(uri); // Register source handler.ctx = this; @@ -168,12 +138,66 @@ private: } void select(const std::string& nuri) { + // If no device is available, give up + if (devices.empty()) { + uri.clear(); + return; + } + + // If the device is not available, select the first one + if (!devices.keyExists(nuri)) { + select(devices.key(0)); + } + + // Update URI uri = nuri; + + // TODO: Enumerate capabilities + + // Load device config + config.acquire(); + if (config.conf["devices"][uri.c_str()].contains("samplerate")) { + // Select given samplerate or default if invalid + samplerate = config.conf["devices"][uri]["samplerate"]; + if (samplerates.keyExists(samplerate)) { + srId = samplerates.keyId(samplerate); + } + else { + srId = 0; + samplerate = samplerates.value(srId); + } + } + if (config.conf["devices"][uri].contains("bandwidth")) { + // Select given bandwidth or default if invalid + bandwidth = config.conf["devices"][uri]["bandwidth"]; + if (bandwidths.keyExists(bandwidth)) { + bwId = bandwidths.keyId(bandwidth); + } + else { + bwId = 0; + bandwidth = bandwidths.value(bwId); + } + } + if (config.conf["devices"][uri].contains("gainMode")) { + // Select given gain mode or default if invalid + std::string gm = config.conf["devices"][uri]["gainMode"]; + if (gainModes.keyExists(gm)) { + gmId = gainModes.keyId(gm); + } + else { + gmId = 0; + } + } + if (config.conf["devices"][uri].contains("gain")) { + gain = config.conf["devices"][uri]["gain"]; + gain = std::clamp(gain, -1.0f, 73.0f); + } + config.release(); } static void menuSelected(void* ctx) { PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx; - core::setInputSampleRate(_this->sampleRate); + core::setInputSampleRate(_this->samplerate); flog::info("PlutoSDRSourceModule '{0}': Menu Select!", _this->name); } @@ -217,15 +241,15 @@ private: // Configure RX channel iio_channel_attr_write(_this->rxChan, "rf_port_select", "A_BALANCED"); - iio_channel_attr_write_longlong(_this->rxLO, "frequency", round(_this->freq)); // Freq - iio_channel_attr_write_bool(_this->rxChan, "filter_fir_en", true); // Digital filter - iio_channel_attr_write_longlong(_this->rxChan, "sampling_frequency", round(_this->sampleRate)); // Sample rate - iio_channel_attr_write_longlong(_this->rxChan, "hardwaregain", round(_this->gain)); // Gain - iio_channel_attr_write(_this->rxChan, "gain_control_mode", _this->gainModes.value(_this->gainMode).c_str()); // Gain mode + iio_channel_attr_write_longlong(_this->rxLO, "frequency", round(_this->freq)); // Freq + iio_channel_attr_write_bool(_this->rxChan, "filter_fir_en", true); // Digital filter + iio_channel_attr_write_longlong(_this->rxChan, "sampling_frequency", round(_this->samplerate)); // Sample rate + iio_channel_attr_write_double(_this->rxChan, "hardwaregain", _this->gain); // Gain + iio_channel_attr_write(_this->rxChan, "gain_control_mode", _this->gainModes.value(_this->gmId).c_str()); // Gain mode _this->setBandwidth(_this->bandwidth); // Configure the ADC filters - ad9361_set_bb_rate(_this->phy, round(_this->sampleRate)); + ad9361_set_bb_rate(_this->phy, round(_this->samplerate)); // Start worker thread _this->running = true; @@ -257,7 +281,7 @@ private: _this->freq = freq; if (_this->running) { // Tune device - iio_channel_attr_write_longlong(iio_device_find_channel(_this->phy, "altvoltage0", true), "frequency", round(freq)); + iio_channel_attr_write_longlong(_this->rxLO, "frequency", round(freq)); } flog::info("PlutoSDRSourceModule '{0}': Tune: {1}!", _this->name, freq); } @@ -270,15 +294,19 @@ private: SmGui::ForceSync(); if (SmGui::Combo("##plutosdr_dev_sel", &_this->devId, _this->devices.txt)) { _this->select(_this->devices.value(_this->devId)); - // TODO: Save + config.acquire(); + config.conf["device"] = _this->devices.key(_this->devId); + config.release(true); } if (SmGui::Combo(CONCAT("##_pluto_sr_", _this->name), &_this->srId, _this->samplerates.txt)) { - _this->sampleRate = _this->samplerates.value(_this->srId); - core::setInputSampleRate(_this->sampleRate); - config.acquire(); - config.conf["sampleRate"] = _this->sampleRate; - config.release(true); + _this->samplerate = _this->samplerates.value(_this->srId); + core::setInputSampleRate(_this->samplerate); + if (!_this->uri.empty()) { + config.acquire(); + config.conf["devices"][_this->uri]["samplerate"] = _this->samplerate; + config.release(true); + } } // Refresh button @@ -299,35 +327,41 @@ private: if (_this->running) { _this->setBandwidth(_this->bandwidth); } - config.acquire(); - config.conf["bandwidth"] = _this->bandwidth; - config.release(true); + if (!_this->uri.empty()) { + config.acquire(); + config.conf["devices"][_this->uri]["bandwidth"] = _this->bandwidth; + config.release(true); + } } SmGui::LeftLabel("Gain Mode"); SmGui::FillWidth(); SmGui::ForceSync(); - if (SmGui::Combo(CONCAT("##_gainmode_select_", _this->name), &_this->gainMode, _this->gainModes.txt)) { + if (SmGui::Combo(CONCAT("##_pluto_gainmode_select_", _this->name), &_this->gmId, _this->gainModes.txt)) { if (_this->running) { - iio_channel_attr_write(_this->rxChan, "gain_control_mode", _this->gainModes.value(_this->gainMode).c_str()); + iio_channel_attr_write(_this->rxChan, "gain_control_mode", _this->gainModes.value(_this->gmId).c_str()); + } + if (!_this->uri.empty()) { + config.acquire(); + config.conf["devices"][_this->uri]["gainMode"] = _this->gainModes.key(_this->gmId); + config.release(true); } - config.acquire(); - config.conf["gainMode"] = _this->gainMode; - config.release(true); } - SmGui::LeftLabel("PGA Gain"); - if (_this->gainMode) { SmGui::BeginDisabled(); } + SmGui::LeftLabel("Gain"); + if (_this->gmId) { SmGui::BeginDisabled(); } SmGui::FillWidth(); - if (SmGui::SliderFloat(CONCAT("##_gain_select_", _this->name), &_this->gain, 0, 76)) { + if (SmGui::SliderFloatWithSteps(CONCAT("##_pluto_gain__", _this->name), &_this->gain, -1.0f, 73.0f, 1.0f, SmGui::FMT_STR_FLOAT_DB_NO_DECIMAL)) { if (_this->running) { - iio_channel_attr_write_longlong(_this->rxChan, "hardwaregain", round(_this->gain)); + iio_channel_attr_write_double(_this->rxChan, "hardwaregain", _this->gain); + } + if (!_this->uri.empty()) { + config.acquire(); + config.conf["devices"][_this->uri]["gain"] = _this->gain; + config.release(true); } - config.acquire(); - config.conf["gain"] = _this->gain; - config.release(true); } - if (_this->gainMode) { SmGui::EndDisabled(); } + if (_this->gmId) { SmGui::EndDisabled(); } } void setBandwidth(int bw) { @@ -335,13 +369,13 @@ private: iio_channel_attr_write_longlong(rxChan, "rf_bandwidth", bw); } else { - iio_channel_attr_write_longlong(rxChan, "rf_bandwidth", std::min(sampleRate, 52000000)); + iio_channel_attr_write_longlong(rxChan, "rf_bandwidth", std::min(samplerate, 52000000)); } } static void worker(void* ctx) { PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx; - int blockSize = _this->sampleRate / 200.0f; + int blockSize = _this->samplerate / 200.0f; // Acquire channels iio_channel* rx0_i = iio_device_find_channel(_this->dev, "voltage0", 0); @@ -396,26 +430,38 @@ private: std::string uri = ""; double freq; - float sampleRate = 4000000; + int samplerate = 4000000; int bandwidth = 0; - int gainMode = 0; - float gain = 0; + float gain = -1; int devId = 0; int srId = 0; int bwId = 0; + int gmId = 0; OptionList devices; OptionList samplerates; OptionList bandwidths; - OptionList gainModes; + OptionList gainModes; }; MOD_EXPORT void _INIT_() { json defConf = {}; + defConf["device"] = ""; + defConf["devices"] = {}; config.setPath(core::args["root"].s() + "/plutosdr_source_config.json"); config.load(defConf); config.enableAutoSave(); + + // Reset the configuration if the old format is still used + config.acquire(); + if (!config.conf.contains("device") || !config.conf.contains("devices")) { + config.conf = defConf; + config.release(true); + } + else { + config.release(); + } } MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) { From 1cd8c2510a1634fea65f0672478e2ef26cc6ef7f Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Sun, 28 Jan 2024 14:38:36 +0100 Subject: [PATCH 4/7] fix plutosdr source error checking --- source_modules/plutosdr_source/src/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source_modules/plutosdr_source/src/main.cpp b/source_modules/plutosdr_source/src/main.cpp index 868a4333..3a9a019a 100644 --- a/source_modules/plutosdr_source/src/main.cpp +++ b/source_modules/plutosdr_source/src/main.cpp @@ -380,6 +380,10 @@ private: // Acquire channels iio_channel* rx0_i = iio_device_find_channel(_this->dev, "voltage0", 0); iio_channel* rx0_q = iio_device_find_channel(_this->dev, "voltage1", 0); + if (!rx0_i || !rx0_q) { + flog::error("Failed to acquire RX channels"); + return; + } // Start streaming iio_channel_enable(rx0_i); @@ -399,6 +403,7 @@ private: // Get buffer pointer int16_t* buf = (int16_t*)iio_buffer_first(rxbuf, rx0_i); + if (!buf) { break; } // Convert samples to CF32 volk_16i_s32f_convert_32f((float*)_this->stream.writeBuf, buf, 32768.0f, blockSize * 2); From 6b5de78e80bc6a61bee6470a7767a9fc89bd3af9 Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Sun, 28 Jan 2024 14:39:01 +0100 Subject: [PATCH 5/7] fix plutosdr source not updating samplerate on select --- source_modules/plutosdr_source/src/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source_modules/plutosdr_source/src/main.cpp b/source_modules/plutosdr_source/src/main.cpp index 3a9a019a..265ffc17 100644 --- a/source_modules/plutosdr_source/src/main.cpp +++ b/source_modules/plutosdr_source/src/main.cpp @@ -193,6 +193,9 @@ private: gain = std::clamp(gain, -1.0f, 73.0f); } config.release(); + + // Update core samplerate + core::setInputSampleRate(samplerate); } static void menuSelected(void* ctx) { From 97d0a07ec7566c80c5eb59da3a060d098762a2d6 Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Sun, 28 Jan 2024 15:26:34 +0100 Subject: [PATCH 6/7] fix plutosdr commit persistence --- source_modules/plutosdr_source/src/main.cpp | 100 +++++++++++--------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/source_modules/plutosdr_source/src/main.cpp b/source_modules/plutosdr_source/src/main.cpp index 265ffc17..8ed917a0 100644 --- a/source_modules/plutosdr_source/src/main.cpp +++ b/source_modules/plutosdr_source/src/main.cpp @@ -50,9 +50,9 @@ public: // Select device config.acquire(); - uri = config.conf["device"]; + devName = config.conf["device"]; config.release(); - select(uri); + select(devName); // Register source handler.ctx = this; @@ -121,9 +121,9 @@ private: for (ssize_t i = 0; i < count; i++) { iio_context_info* info = ctxInfoList[i]; std::string desc = iio_context_info_get_description(info); - std::string uri = iio_context_info_get_uri(info); + std::string duri = iio_context_info_get_uri(info); - devices.define(uri, desc, uri); + devices.define(desc, desc, duri); } iio_context_info_list_free(ctxInfoList); @@ -133,54 +133,46 @@ private: #ifdef __ANDROID__ // On Android, a default IP entry must be made (TODO: This is not ideal since the IP cannot be changed) const char* androidURI = "ip:192.168.2.1"; - devices.define(androidURI, "Default (192.168.2.1)", androidURI); + const char* androidName = "Default (192.168.2.1)"; + devices.define(androidName, androidName, androidURI); #endif } - void select(const std::string& nuri) { + void select(const std::string& name) { // If no device is available, give up if (devices.empty()) { - uri.clear(); + devName.clear(); return; } // If the device is not available, select the first one - if (!devices.keyExists(nuri)) { + if (!devices.keyExists(name)) { select(devices.key(0)); } // Update URI - uri = nuri; + devName = name; + uri = devices.value(devices.keyId(name)); // TODO: Enumerate capabilities + // Load defaults + samplerate = 4000000; + bandwidth = 0; + gmId = 0; + gain = -1.0f; + // Load device config config.acquire(); - if (config.conf["devices"][uri.c_str()].contains("samplerate")) { - // Select given samplerate or default if invalid - samplerate = config.conf["devices"][uri]["samplerate"]; - if (samplerates.keyExists(samplerate)) { - srId = samplerates.keyId(samplerate); - } - else { - srId = 0; - samplerate = samplerates.value(srId); - } + if (config.conf["devices"][devName].contains("samplerate")) { + samplerate = config.conf["devices"][devName]["samplerate"]; } - if (config.conf["devices"][uri].contains("bandwidth")) { - // Select given bandwidth or default if invalid - bandwidth = config.conf["devices"][uri]["bandwidth"]; - if (bandwidths.keyExists(bandwidth)) { - bwId = bandwidths.keyId(bandwidth); - } - else { - bwId = 0; - bandwidth = bandwidths.value(bwId); - } + if (config.conf["devices"][devName].contains("bandwidth")) { + bandwidth = config.conf["devices"][devName]["bandwidth"]; } - if (config.conf["devices"][uri].contains("gainMode")) { + if (config.conf["devices"][devName].contains("gainMode")) { // Select given gain mode or default if invalid - std::string gm = config.conf["devices"][uri]["gainMode"]; + std::string gm = config.conf["devices"][devName]["gainMode"]; if (gainModes.keyExists(gm)) { gmId = gainModes.keyId(gm); } @@ -188,11 +180,29 @@ private: gmId = 0; } } - if (config.conf["devices"][uri].contains("gain")) { - gain = config.conf["devices"][uri]["gain"]; + if (config.conf["devices"][devName].contains("gain")) { + gain = config.conf["devices"][devName]["gain"]; gain = std::clamp(gain, -1.0f, 73.0f); } config.release(); + + // Update samplerate ID + if (samplerates.keyExists(samplerate)) { + srId = samplerates.keyId(samplerate); + } + else { + srId = 0; + samplerate = samplerates.value(srId); + } + + // Update bandwidth ID + if (bandwidths.keyExists(bandwidth)) { + bwId = bandwidths.keyId(bandwidth); + } + else { + bwId = 0; + bandwidth = bandwidths.value(bwId); + } // Update core samplerate core::setInputSampleRate(samplerate); @@ -213,6 +223,9 @@ private: PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx; if (_this->running) { return; } + // If no device is selected, give up + if (_this->devName.empty() || _this->uri.empty()) { return; } + // Open context _this->ctx = iio_create_context_from_uri(_this->uri.c_str()); if (_this->ctx == NULL) { @@ -296,7 +309,7 @@ private: SmGui::FillWidth(); SmGui::ForceSync(); if (SmGui::Combo("##plutosdr_dev_sel", &_this->devId, _this->devices.txt)) { - _this->select(_this->devices.value(_this->devId)); + _this->select(_this->devices.key(_this->devId)); config.acquire(); config.conf["device"] = _this->devices.key(_this->devId); config.release(true); @@ -305,9 +318,9 @@ private: if (SmGui::Combo(CONCAT("##_pluto_sr_", _this->name), &_this->srId, _this->samplerates.txt)) { _this->samplerate = _this->samplerates.value(_this->srId); core::setInputSampleRate(_this->samplerate); - if (!_this->uri.empty()) { + if (!_this->devName.empty()) { config.acquire(); - config.conf["devices"][_this->uri]["samplerate"] = _this->samplerate; + config.conf["devices"][_this->devName]["samplerate"] = _this->samplerate; config.release(true); } } @@ -318,7 +331,7 @@ private: SmGui::ForceSync(); if (SmGui::Button(CONCAT("Refresh##_pluto_refr_", _this->name))) { _this->refresh(); - _this->select(_this->uri); + _this->select(_this->devName); } if (_this->running) { SmGui::EndDisabled(); } @@ -330,9 +343,9 @@ private: if (_this->running) { _this->setBandwidth(_this->bandwidth); } - if (!_this->uri.empty()) { + if (!_this->devName.empty()) { config.acquire(); - config.conf["devices"][_this->uri]["bandwidth"] = _this->bandwidth; + config.conf["devices"][_this->devName]["bandwidth"] = _this->bandwidth; config.release(true); } } @@ -344,9 +357,9 @@ private: if (_this->running) { iio_channel_attr_write(_this->rxChan, "gain_control_mode", _this->gainModes.value(_this->gmId).c_str()); } - if (!_this->uri.empty()) { + if (!_this->devName.empty()) { config.acquire(); - config.conf["devices"][_this->uri]["gainMode"] = _this->gainModes.key(_this->gmId); + config.conf["devices"][_this->devName]["gainMode"] = _this->gainModes.key(_this->gmId); config.release(true); } } @@ -358,9 +371,9 @@ private: if (_this->running) { iio_channel_attr_write_double(_this->rxChan, "hardwaregain", _this->gain); } - if (!_this->uri.empty()) { + if (!_this->devName.empty()) { config.acquire(); - config.conf["devices"][_this->uri]["gain"] = _this->gain; + config.conf["devices"][_this->devName]["gain"] = _this->gain; config.release(true); } } @@ -435,6 +448,7 @@ private: iio_channel* rxChan = NULL; bool running = false; + std::string devName = ""; std::string uri = ""; double freq; From bc77bab45fdfa6935dad671ddbcd18f675d6b8a1 Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Sun, 28 Jan 2024 17:23:18 +0100 Subject: [PATCH 7/7] improved plutosdr device naming --- source_modules/plutosdr_source/src/main.cpp | 95 +++++++++++++++------ 1 file changed, 68 insertions(+), 27 deletions(-) diff --git a/source_modules/plutosdr_source/src/main.cpp b/source_modules/plutosdr_source/src/main.cpp index 8ed917a0..c0af537c 100644 --- a/source_modules/plutosdr_source/src/main.cpp +++ b/source_modules/plutosdr_source/src/main.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #define CONCAT(a, b) ((std::string(a) + b).c_str()) @@ -50,9 +51,9 @@ public: // Select device config.acquire(); - devName = config.conf["device"]; + devDesc = config.conf["device"]; config.release(); - select(devName); + select(devDesc); // Register source handler.ctx = this; @@ -111,6 +112,11 @@ private: return; } + // Create parsing regexes + std::regex backendRgx(".+(?=:)", std::regex::ECMAScript); + std::regex modelRgx("\\(.+(?=\\),)", std::regex::ECMAScript); + std::regex serialRgx("serial=[0-9A-Za-z]+", std::regex::ECMAScript); + // Enumerate devices iio_context_info** ctxInfoList; ssize_t count = iio_scan_context_get_info_list(sctx, &ctxInfoList); @@ -123,7 +129,42 @@ private: std::string desc = iio_context_info_get_description(info); std::string duri = iio_context_info_get_uri(info); - devices.define(desc, desc, duri); + // If the device is not a plutosdr, don't include it + if (desc.find("PlutoSDR") == std::string::npos) { + flog::warn("Ignored IIO device: [{}] {}", duri, desc); + continue; + } + + // Extract the backend + std::string backend = "unknown"; + std::smatch backendMatch; + if (std::regex_search(duri, backendMatch, backendRgx)) { + backend = backendMatch[0]; + } + + // Extract the model + std::string model = "Unknown"; + std::smatch modelMatch; + if (std::regex_search(desc, modelMatch, modelRgx)) { + model = modelMatch[0]; + int parenthPos = model.find('('); + if (parenthPos != std::string::npos) { + model = model.substr(parenthPos+1); + } + } + + // Extract the serial + std::string serial = "unknown"; + std::smatch serialMatch; + if (std::regex_search(desc, serialMatch, serialRgx)) { + serial = serialMatch[0].str().substr(7); + } + + // Construct the device name + std::string devName = '(' + backend + ") " + model + " [" + serial + ']'; + + // Save device + devices.define(desc, devName, duri); } iio_context_info_list_free(ctxInfoList); @@ -138,21 +179,21 @@ private: #endif } - void select(const std::string& name) { + void select(const std::string& desc) { // If no device is available, give up if (devices.empty()) { - devName.clear(); + devDesc.clear(); return; } // If the device is not available, select the first one - if (!devices.keyExists(name)) { + if (!devices.keyExists(desc)) { select(devices.key(0)); } // Update URI - devName = name; - uri = devices.value(devices.keyId(name)); + devDesc = desc; + uri = devices.value(devices.keyId(desc)); // TODO: Enumerate capabilities @@ -164,15 +205,15 @@ private: // Load device config config.acquire(); - if (config.conf["devices"][devName].contains("samplerate")) { - samplerate = config.conf["devices"][devName]["samplerate"]; + if (config.conf["devices"][devDesc].contains("samplerate")) { + samplerate = config.conf["devices"][devDesc]["samplerate"]; } - if (config.conf["devices"][devName].contains("bandwidth")) { - bandwidth = config.conf["devices"][devName]["bandwidth"]; + if (config.conf["devices"][devDesc].contains("bandwidth")) { + bandwidth = config.conf["devices"][devDesc]["bandwidth"]; } - if (config.conf["devices"][devName].contains("gainMode")) { + if (config.conf["devices"][devDesc].contains("gainMode")) { // Select given gain mode or default if invalid - std::string gm = config.conf["devices"][devName]["gainMode"]; + std::string gm = config.conf["devices"][devDesc]["gainMode"]; if (gainModes.keyExists(gm)) { gmId = gainModes.keyId(gm); } @@ -180,8 +221,8 @@ private: gmId = 0; } } - if (config.conf["devices"][devName].contains("gain")) { - gain = config.conf["devices"][devName]["gain"]; + if (config.conf["devices"][devDesc].contains("gain")) { + gain = config.conf["devices"][devDesc]["gain"]; gain = std::clamp(gain, -1.0f, 73.0f); } config.release(); @@ -224,7 +265,7 @@ private: if (_this->running) { return; } // If no device is selected, give up - if (_this->devName.empty() || _this->uri.empty()) { return; } + if (_this->devDesc.empty() || _this->uri.empty()) { return; } // Open context _this->ctx = iio_create_context_from_uri(_this->uri.c_str()); @@ -318,9 +359,9 @@ private: if (SmGui::Combo(CONCAT("##_pluto_sr_", _this->name), &_this->srId, _this->samplerates.txt)) { _this->samplerate = _this->samplerates.value(_this->srId); core::setInputSampleRate(_this->samplerate); - if (!_this->devName.empty()) { + if (!_this->devDesc.empty()) { config.acquire(); - config.conf["devices"][_this->devName]["samplerate"] = _this->samplerate; + config.conf["devices"][_this->devDesc]["samplerate"] = _this->samplerate; config.release(true); } } @@ -331,7 +372,7 @@ private: SmGui::ForceSync(); if (SmGui::Button(CONCAT("Refresh##_pluto_refr_", _this->name))) { _this->refresh(); - _this->select(_this->devName); + _this->select(_this->devDesc); } if (_this->running) { SmGui::EndDisabled(); } @@ -343,9 +384,9 @@ private: if (_this->running) { _this->setBandwidth(_this->bandwidth); } - if (!_this->devName.empty()) { + if (!_this->devDesc.empty()) { config.acquire(); - config.conf["devices"][_this->devName]["bandwidth"] = _this->bandwidth; + config.conf["devices"][_this->devDesc]["bandwidth"] = _this->bandwidth; config.release(true); } } @@ -357,9 +398,9 @@ private: if (_this->running) { iio_channel_attr_write(_this->rxChan, "gain_control_mode", _this->gainModes.value(_this->gmId).c_str()); } - if (!_this->devName.empty()) { + if (!_this->devDesc.empty()) { config.acquire(); - config.conf["devices"][_this->devName]["gainMode"] = _this->gainModes.key(_this->gmId); + config.conf["devices"][_this->devDesc]["gainMode"] = _this->gainModes.key(_this->gmId); config.release(true); } } @@ -371,9 +412,9 @@ private: if (_this->running) { iio_channel_attr_write_double(_this->rxChan, "hardwaregain", _this->gain); } - if (!_this->devName.empty()) { + if (!_this->devDesc.empty()) { config.acquire(); - config.conf["devices"][_this->devName]["gain"] = _this->gain; + config.conf["devices"][_this->devDesc]["gain"] = _this->gain; config.release(true); } } @@ -448,7 +489,7 @@ private: iio_channel* rxChan = NULL; bool running = false; - std::string devName = ""; + std::string devDesc = ""; std::string uri = ""; double freq;