diff --git a/devices/soapysdr/devicesoapysdrparams.cpp b/devices/soapysdr/devicesoapysdrparams.cpp index 482567b30..4baf11e3a 100644 --- a/devices/soapysdr/devicesoapysdrparams.cpp +++ b/devices/soapysdr/devicesoapysdrparams.cpp @@ -14,12 +14,18 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include +#include + +#include + #include "devicesoapysdrparams.h" DeviceSoapySDRParams::DeviceSoapySDRParams(SoapySDR::Device *device) : m_device(device) { fillParams(); + printParams(); } DeviceSoapySDRParams::~DeviceSoapySDRParams() @@ -85,3 +91,172 @@ void DeviceSoapySDRParams::fillChannelParams(std::vector& channe channelSettings.back().m_bandwidthsRanges = m_device->getBandwidthRange(direction, ichan); } + +void DeviceSoapySDRParams::printParams() +{ + qDebug() << "DeviceSoapySDRParams::printParams: m_deviceSettingsArgs:\n" << argInfoListToString(m_deviceSettingsArgs).c_str(); + int ichan = 0; + + for (const auto &it : m_RxChannelsSettings) + { + qDebug() << "DeviceSoapySDRParams::printParams: Rx channel " << ichan; + printChannelParams(it); + ichan++; + } + + ichan = 0; + + for (const auto &it : m_TxChannelsSettings) + { + qDebug() << "DeviceSoapySDRParams::printParams: Tx channel " << ichan; + printChannelParams(it); + ichan++; + } +} + +void DeviceSoapySDRParams::printChannelParams(const ChannelSetting& channelSetting) +{ + qDebug() << "DeviceSoapySDRParams::printParams: m_streamSettingsArgs:\n" << argInfoListToString(channelSetting.m_streamSettingsArgs).c_str(); + qDebug() << "DeviceSoapySDRParams::printParams:" + << " m_hasDCAutoCorrection: " << channelSetting.m_hasDCAutoCorrection + << " m_hasDCOffsetValue: " << channelSetting.m_hasDCOffsetValue + << " m_hasIQBalanceValue: " << channelSetting.m_hasIQBalanceValue + << " m_hasFrequencyCorrectionValue: " << channelSetting.m_hasFrequencyCorrectionValue + << " m_hasAGC: " << channelSetting.m_hasAGC; + qDebug() << "DeviceSoapySDRParams::printParams: m_antennas: " << vectorToString(channelSetting.m_antennas).c_str(); + qDebug() << "DeviceSoapySDRParams::printParams: m_gainRange: " << rangeToString(channelSetting.m_gainRange).c_str(); + + qDebug() << "DeviceSoapySDRParams::printParams: individual gains..."; + + for (const auto &gainIt : channelSetting.m_gainSettings) + { + qDebug() << "DeviceSoapySDRParams::printParams: m_name: " << gainIt.m_name.c_str(); + qDebug() << "DeviceSoapySDRParams::printParams: m_range: " << rangeToString(gainIt.m_range).c_str(); + } + + qDebug() << "DeviceSoapySDRParams::printParams: tunable elements..."; + + for (const auto &freqIt : channelSetting.m_frequencySettings) + { + qDebug() << "DeviceSoapySDRParams::printParams: m_name: " << freqIt.m_name.c_str(); + qDebug() << "DeviceSoapySDRParams::printParams: m_range (kHz): " << rangeListToString(freqIt.m_ranges, 1e3).c_str(); + } + + qDebug() << "DeviceSoapySDRParams::printParams: m_frequencySettingsArgs:\n" << argInfoListToString(channelSetting.m_frequencySettingsArgs).c_str(); + qDebug() << "DeviceSoapySDRParams::printParams: m_ratesRanges (kHz): " << rangeListToString(channelSetting.m_ratesRanges, 1e3).c_str(); + qDebug() << "DeviceSoapySDRParams::printParams: m_bandwidthsRanges (kHz): " << rangeListToString(channelSetting.m_bandwidthsRanges, 1e3).c_str(); +} + +std::string DeviceSoapySDRParams::argInfoToString(const SoapySDR::ArgInfo &argInfo, const std::string indent) +{ + std::stringstream ss; + + //name, or use key if missing + std::string name = argInfo.name; + if (argInfo.name.empty()) name = argInfo.key; + ss << indent << " * " << name; + + //optional description + std::string desc = argInfo.description; + const std::string replace("\n"+indent+" "); + + for (std::size_t pos = 0; (pos=desc.find("\n", pos)) != std::string::npos; pos+=replace.size()) { + desc.replace(pos, 1, replace); + } + + if (not desc.empty()) { + ss << " - " << desc << std::endl << indent << " "; + } + + //other fields + ss << " [key=" << argInfo.key; + + if (not argInfo.units.empty()) { + ss << ", units=" << argInfo.units; + } + + if (not argInfo.value.empty()) { + ss << ", default=" << argInfo.value; + } + + //type + switch (argInfo.type) + { + case SoapySDR::ArgInfo::BOOL: + ss << ", type=bool"; + break; + case SoapySDR::ArgInfo::INT: + ss << ", type=int"; + break; + case SoapySDR::ArgInfo::FLOAT: + ss << ", type=float"; + break; + case SoapySDR::ArgInfo::STRING: + ss << ", type=string"; + break; + } + + //optional range/enumeration + if (argInfo.range.minimum() < argInfo.range.maximum()) { + ss << ", range=" << rangeToString(argInfo.range); + } + + if (not argInfo.options.empty()) { + ss << ", options=(" << vectorToString(argInfo.options) << ")"; + } + + ss << "]"; + + return ss.str(); +} + +std::string DeviceSoapySDRParams::argInfoListToString(const SoapySDR::ArgInfoList &argInfos) +{ + std::stringstream ss; + + for (std::size_t i = 0; i < argInfos.size(); i++) { + ss << argInfoToString(argInfos[i]) << std::endl; + } + + return ss.str(); +} + +std::string DeviceSoapySDRParams::rangeToString(const SoapySDR::Range &range) +{ + std::stringstream ss; + ss << "[" << range.minimum() << ", " << range.maximum(); + + if (range.step() != 0.0) { + ss << ", " << range.step(); + } + + ss << "]"; + return ss.str(); +} + +std::string DeviceSoapySDRParams::rangeListToString(const SoapySDR::RangeList &range, const double scale) +{ + const std::size_t MAXRLEN = 10; //for abbreviating long lists + std::stringstream ss; + + for (std::size_t i = 0; i < range.size(); i++) + { + if (range.size() >= MAXRLEN and i >= MAXRLEN/2 and i < (range.size()-MAXRLEN/2)) + { + if (i == MAXRLEN) ss << ", ..."; + continue; + } + + if (not ss.str().empty()) { + ss << ", "; + } + + if (range[i].minimum() == range[i].maximum()) { + ss << (range[i].minimum()/scale); + } else { + ss << "[" << (range[i].minimum()/scale) << ", " << (range[i].maximum()/scale) << "]"; + } + } + + return ss.str(); +} diff --git a/devices/soapysdr/devicesoapysdrparams.h b/devices/soapysdr/devicesoapysdrparams.h index 447736ac8..09d5c4846 100644 --- a/devices/soapysdr/devicesoapysdrparams.h +++ b/devices/soapysdr/devicesoapysdrparams.h @@ -18,6 +18,9 @@ #define DEVICES_SOAPYSDR_DEVICESOAPYSDRPARAMS_H_ #include +#include +#include + #include #include "export.h" @@ -68,6 +71,36 @@ public: private: void fillParams(); void fillChannelParams(std::vector& channelSettings, int direction, unsigned int ichan); + void printParams(); + void printChannelParams(const ChannelSetting& channelSetting); + + // Printing functions copied from SoapySDR's SoapySDRProbe.cpp + std::string argInfoToString(const SoapySDR::ArgInfo &argInfo, const std::string indent = " "); + std::string argInfoListToString(const SoapySDR::ArgInfoList &argInfos); + std::string rangeToString(const SoapySDR::Range &range); + std::string rangeListToString(const SoapySDR::RangeList &range, const double scale); + + template + std::string vectorToString(const std::vector &options) + { + std::stringstream ss; + + if (options.empty()) { + return ""; + } + + for (std::size_t i = 0; i < options.size(); i++) + { + if (not ss.str().empty()) { + ss << ", "; + } + + ss << options[i]; + } + + return ss.str(); + } + SoapySDR::Device *m_device; SoapySDR::ArgInfoList m_deviceSettingsArgs; //!< list (vector) of device settings arguments uint32_t m_nbRx; //!< number of Rx channels diff --git a/devices/soapysdr/devicesoapysdrshared.h b/devices/soapysdr/devicesoapysdrshared.h index 4fce21a2b..8ab019ba1 100644 --- a/devices/soapysdr/devicesoapysdrshared.h +++ b/devices/soapysdr/devicesoapysdrshared.h @@ -20,6 +20,7 @@ #include #include "export.h" +#include "devicesoapysdrparams.h" class SoapySDRInput; class SoapySDROutput; @@ -34,6 +35,7 @@ public: ~DeviceSoapySDRShared(); SoapySDR::Device *m_device; + DeviceSoapySDRParams *m_deviceParams; int m_channel; //!< allocated channel (-1 if none) SoapySDRInput *m_source; SoapySDROutput *m_sink; diff --git a/plugins/samplesource/soapysdrinput/CMakeLists.txt b/plugins/samplesource/soapysdrinput/CMakeLists.txt index a6606a303..b87a6567f 100644 --- a/plugins/samplesource/soapysdrinput/CMakeLists.txt +++ b/plugins/samplesource/soapysdrinput/CMakeLists.txt @@ -19,7 +19,7 @@ set(soapysdrinput_HEADERS ) set(soapysdrinput_FORMS -# soapysdrinputgui.ui + soapysdrinputgui.ui ) if (BUILD_DEBIAN) diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 6c0575e0a..8622b31c9 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -32,6 +32,7 @@ SoapySDRInput::SoapySDRInput(DeviceSourceAPI *deviceAPI) : m_deviceDescription("SoapySDRInput"), m_running(false) { + openDevice(); } SoapySDRInput::~SoapySDRInput() @@ -78,6 +79,7 @@ bool SoapySDRInput::openDevice() } m_deviceShared.m_device = device; + m_deviceShared.m_deviceParams = deviceSoapySDRShared->m_deviceParams; } // look for Tx buddies and get reference to the device object else if (m_deviceAPI->getSinkBuddies().size() > 0) // then sink @@ -102,6 +104,7 @@ bool SoapySDRInput::openDevice() } m_deviceShared.m_device = device; + m_deviceShared.m_deviceParams = deviceSoapySDRShared->m_deviceParams; } // There are no buddies then create the first SoapySDR device else @@ -115,6 +118,8 @@ bool SoapySDRInput::openDevice() qCritical("BladeRF2Input::openDevice: cannot open BladeRF2 device"); return false; } + + m_deviceShared.m_deviceParams = new DeviceSoapySDRParams(m_deviceShared.m_device); } m_deviceShared.m_channel = m_deviceAPI->getItemIndex(); // publicly allocate channel @@ -140,10 +145,12 @@ void SoapySDRInput::closeDevice() m_deviceShared.m_channel = -1; // publicly release channel m_deviceShared.m_source = 0; - // No buddies so effectively close the device + // No buddies so effectively close the device and delete parameters if ((m_deviceAPI->getSinkBuddies().size() == 0) && (m_deviceAPI->getSourceBuddies().size() == 0)) { + delete m_deviceShared.m_deviceParams; + m_deviceShared.m_deviceParams = 0; DeviceSoapySDR& deviceSoapySDR = DeviceSoapySDR::instance(); deviceSoapySDR.closeSoapySdr(m_deviceShared.m_device); m_deviceShared.m_device = 0; diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp index fe29fb4d0..ec07b97f3 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -20,22 +20,28 @@ #include "device/deviceuiset.h" #include "util/simpleserializer.h" +#include "ui_soapysdrinputgui.h" #include "soapysdrinputgui.h" SoapySDRInputGui::SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) : QWidget(parent), - ui(0), + ui(new Ui::SoapySDRInputGui), m_deviceUISet(deviceUISet), m_forceSettings(true), m_doApplySettings(true), m_sampleSource(0), m_sampleRate(0), + m_deviceCenterFrequency(0), m_lastEngineState(DSPDeviceSourceEngine::StNotStarted) { + m_sampleSource = (SoapySDRInput*) m_deviceUISet->m_deviceSourceAPI->getSampleSource(); + ui->setupUi(this); + ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); } SoapySDRInputGui::~SoapySDRInputGui() { + delete ui; } void SoapySDRInputGui::destroy() diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui b/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui new file mode 100644 index 000000000..30049db37 --- /dev/null +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui @@ -0,0 +1,411 @@ + + + SoapySDRInputGui + + + + 0 + 0 + 324 + 276 + + + + + 0 + 0 + + + + + 320 + 132 + + + + + Liberation Sans + 9 + + + + SoapySDR + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 4 + + + + + + + + + start/stop acquisition + + + + + + + :/play.png + :/stop.png:/play.png + + + + + + + Toggle record I/Q samples from device + + + + + + + :/record_off.png:/record_off.png + + + + + + + + + + + I/Q sample rate kS/s + + + 00000k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 20 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Tuner center frequency in kHz + + + + + + + kHz + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + + true + + + + + 0 + 0 + 304 + 128 + + + + + 0 + 0 + + + + + 3 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Data1 + + + + + + + + 0 + + + + + 1 + + + + + 2 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Kiki + + + + + + + Qt::Horizontal + + + + + + + 0.0 + + + + + + + + + + + TextLabel + + + + + + + ... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Zozo + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Didi + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + ValueDial + QWidget +
gui/valuedial.h
+ 1 +
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+
+ + + + +