diff --git a/devices/soapysdr/devicesoapysdrparams.cpp b/devices/soapysdr/devicesoapysdrparams.cpp index 4baf11e3a..133f7efee 100644 --- a/devices/soapysdr/devicesoapysdrparams.cpp +++ b/devices/soapysdr/devicesoapysdrparams.cpp @@ -46,9 +46,9 @@ void DeviceSoapySDRParams::fillParams() } } -void DeviceSoapySDRParams::fillChannelParams(std::vector& channelSettings, int direction, unsigned int ichan) +void DeviceSoapySDRParams::fillChannelParams(std::vector& channelSettings, int direction, unsigned int ichan) { - channelSettings.push_back(ChannelSetting()); + channelSettings.push_back(ChannelSettings()); channelSettings.back().m_streamSettingsArgs = m_device->getStreamArgsInfo(direction, ichan); channelSettings.back().m_antennas = m_device->listAntennas(direction, ichan); @@ -114,7 +114,7 @@ void DeviceSoapySDRParams::printParams() } } -void DeviceSoapySDRParams::printChannelParams(const ChannelSetting& channelSetting) +void DeviceSoapySDRParams::printChannelParams(const ChannelSettings& channelSetting) { qDebug() << "DeviceSoapySDRParams::printParams: m_streamSettingsArgs:\n" << argInfoListToString(channelSetting.m_streamSettingsArgs).c_str(); qDebug() << "DeviceSoapySDRParams::printParams:" @@ -236,25 +236,27 @@ std::string DeviceSoapySDRParams::rangeToString(const SoapySDR::Range &range) 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()) { + if (range[i].minimum() == range[i].maximum()) + { ss << (range[i].minimum()/scale); - } else { - ss << "[" << (range[i].minimum()/scale) << ", " << (range[i].maximum()/scale) << "]"; + } + else + { + ss << "[" << (range[i].minimum()/scale) << ", " << (range[i].maximum()/scale); + + if (range[i].step() != 0.0) { + ss << ", " << (range[i].step()/scale); + } + + ss << "]"; } } diff --git a/devices/soapysdr/devicesoapysdrparams.h b/devices/soapysdr/devicesoapysdrparams.h index 09d5c4846..67baf5cac 100644 --- a/devices/soapysdr/devicesoapysdrparams.h +++ b/devices/soapysdr/devicesoapysdrparams.h @@ -48,7 +48,7 @@ public: SoapySDR::RangeList m_ranges; //!< List of ranges of the tunable element }; - struct ChannelSetting + struct ChannelSettings { SoapySDR::ArgInfoList m_streamSettingsArgs; //!< common stream parameters bool m_hasDCAutoCorrection; //!< DC offset auto correction flag @@ -68,11 +68,29 @@ public: DeviceSoapySDRParams(SoapySDR::Device *device); ~DeviceSoapySDRParams(); + const ChannelSettings* getRxChannelSettings(uint32_t index) + { + if (index < m_nbRx) { + return &m_RxChannelsSettings[index]; + } else { + return 0; + } + } + + const ChannelSettings* getTxChannelSettings(uint32_t index) + { + if (index < m_nbTx) { + return &m_TxChannelsSettings[index]; + } else { + return 0; + } + } + private: void fillParams(); - void fillChannelParams(std::vector& channelSettings, int direction, unsigned int ichan); + void fillChannelParams(std::vector& channelSettings, int direction, unsigned int ichan); void printParams(); - void printChannelParams(const ChannelSetting& channelSetting); + void printChannelParams(const ChannelSettings& channelSetting); // Printing functions copied from SoapySDR's SoapySDRProbe.cpp std::string argInfoToString(const SoapySDR::ArgInfo &argInfo, const std::string indent = " "); @@ -105,8 +123,8 @@ private: SoapySDR::ArgInfoList m_deviceSettingsArgs; //!< list (vector) of device settings arguments uint32_t m_nbRx; //!< number of Rx channels uint32_t m_nbTx; //!< number of Tx channels - std::vector m_RxChannelsSettings; - std::vector m_TxChannelsSettings; + std::vector m_RxChannelsSettings; + std::vector m_TxChannelsSettings; }; diff --git a/plugins/samplesource/soapysdrinput/CMakeLists.txt b/plugins/samplesource/soapysdrinput/CMakeLists.txt index b87a6567f..ec5f14670 100644 --- a/plugins/samplesource/soapysdrinput/CMakeLists.txt +++ b/plugins/samplesource/soapysdrinput/CMakeLists.txt @@ -8,6 +8,7 @@ set(soapysdrinput_SOURCES soapysdrinputplugin.cpp soapysdrinputsettings.cpp soapysdrinputthread.cpp + discreterangegui.cpp ) set(soapysdrinput_HEADERS @@ -16,10 +17,12 @@ set(soapysdrinput_HEADERS soapysdrinputplugin.h soapysdrinputsettings.h soapysdrinputthread.h + discreterangegui.h ) set(soapysdrinput_FORMS soapysdrinputgui.ui + discreterangegui.ui ) if (BUILD_DEBIAN) diff --git a/plugins/samplesource/soapysdrinput/discreterangegui.cpp b/plugins/samplesource/soapysdrinput/discreterangegui.cpp new file mode 100644 index 000000000..654b3aea0 --- /dev/null +++ b/plugins/samplesource/soapysdrinput/discreterangegui.cpp @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "ui_discreterangegui.h" +#include "discreterangegui.h" + +DiscreteRangeGUI::DiscreteRangeGUI(QWidget* parent) : + QWidget(parent), + ui(new Ui::DiscreteRangeGUI) +{ + ui->setupUi(this); +} + +DiscreteRangeGUI::~DiscreteRangeGUI() +{ + delete ui; +} + +void DiscreteRangeGUI::setLabel(const QString& text) +{ + ui->rangeLabel->setText(text); +} + +void DiscreteRangeGUI::setUnits(const QString& units) +{ + ui->rangeUnits->setText(units); +} + +void DiscreteRangeGUI::addItem(const QString& itemStr, double itemValue) +{ + ui->rangeCombo->blockSignals(true); + ui->rangeCombo->addItem(itemStr); + itemValues.push_back(itemValue); + ui->rangeCombo->blockSignals(false); +} + +double DiscreteRangeGUI::getCurrentValue() +{ + return itemValues[ui->rangeCombo->currentIndex()]; +} + +void DiscreteRangeGUI::on_rangeCombo_currentIndexChanged(int index) +{ + double newRange = itemValues[index]; + emit rangeChanged(newRange); +} diff --git a/plugins/samplesource/soapysdrinput/discreterangegui.h b/plugins/samplesource/soapysdrinput/discreterangegui.h new file mode 100644 index 000000000..291d195d4 --- /dev/null +++ b/plugins/samplesource/soapysdrinput/discreterangegui.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_DISCRETERANGEGUI_H_ +#define PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_DISCRETERANGEGUI_H_ + +#include +#include + +namespace Ui { + class DiscreteRangeGUI; +} + +class DiscreteRangeGUI : public QWidget +{ + Q_OBJECT +public: + explicit DiscreteRangeGUI(QWidget* parent = 0); + ~DiscreteRangeGUI(); + + void setLabel(const QString& text); + void setUnits(const QString& units); + void addItem(const QString& itemStr, double itemValue); + double getCurrentValue(); + +signals: + void rangeChanged(double value); + +private slots: + void on_rangeCombo_currentIndexChanged(int index); + +private: + Ui::DiscreteRangeGUI* ui; + std::vector itemValues; +}; + + + +#endif /* PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_DISCRETERANGEGUI_H_ */ diff --git a/plugins/samplesource/soapysdrinput/discreterangegui.ui b/plugins/samplesource/soapysdrinput/discreterangegui.ui new file mode 100644 index 000000000..b8f36aff0 --- /dev/null +++ b/plugins/samplesource/soapysdrinput/discreterangegui.ui @@ -0,0 +1,48 @@ + + + DiscreteRangeGUI + + + + 0 + 0 + 203 + 30 + + + + Form + + + + + 0 + 0 + 172 + 29 + + + + + + + Label + + + + + + + + + + Unit + + + + + + + + + diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 8622b31c9..a765e340a 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -157,6 +157,40 @@ void SoapySDRInput::closeDevice() } } +void SoapySDRInput::getFrequencyRange(uint64_t& min, uint64_t& max) +{ + const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(m_deviceShared.m_channel); + + if (channelSettings && (channelSettings->m_frequencySettings.size() > 0)) + { + DeviceSoapySDRParams::FrequencySetting freqSettings = channelSettings->m_frequencySettings[0]; + SoapySDR::RangeList rangeList = freqSettings.m_ranges; + + if (rangeList.size() > 0) // TODO: handle multiple ranges + { + SoapySDR::Range range = rangeList[0]; + min = range.minimum(); + max = range.maximum(); + } + else + { + min = 0; + max = 0; + } + } + else + { + min = 0; + max = 0; + } +} + +const SoapySDR::RangeList& SoapySDRInput::getRateRanges() +{ + const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(m_deviceShared.m_channel); + return channelSettings->m_ratesRanges; +} + void SoapySDRInput::init() { } diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.h b/plugins/samplesource/soapysdrinput/soapysdrinput.h index 830aa0ebd..7bde0a771 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.h @@ -24,12 +24,37 @@ #include "soapysdr/devicesoapysdrshared.h" #include "dsp/devicesamplesource.h" +#include "soapysdrinputsettings.h" + class DeviceSourceAPI; class SoapySDRInputThread; class SoapySDRInput : public DeviceSampleSource { public: + class MsgConfigureSoapySDR : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const SoapySDRInputSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureSoapySDR* create(const SoapySDRInputSettings& settings, bool force) + { + return new MsgConfigureSoapySDR(settings, force); + } + + private: + SoapySDRInputSettings m_settings; + bool m_force; + + MsgConfigureSoapySDR(const SoapySDRInputSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + SoapySDRInput(DeviceSourceAPI *deviceAPI); virtual ~SoapySDRInput(); virtual void destroy(); @@ -51,6 +76,9 @@ public: virtual bool handleMessage(const Message& message); + void getFrequencyRange(uint64_t& min, uint64_t& max); + const SoapySDR::RangeList& getRateRanges(); + private: DeviceSourceAPI *m_deviceAPI; DeviceSoapySDRShared m_deviceShared; diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp index ec07b97f3..7049039d5 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -21,6 +21,7 @@ #include "util/simpleserializer.h" #include "ui_soapysdrinputgui.h" +#include "discreterangegui.h" #include "soapysdrinputgui.h" SoapySDRInputGui::SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) : @@ -36,7 +37,13 @@ SoapySDRInputGui::SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) : { m_sampleSource = (SoapySDRInput*) m_deviceUISet->m_deviceSourceAPI->getSampleSource(); ui->setupUi(this); + ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + uint64_t f_min, f_max; + m_sampleSource->getFrequencyRange(f_min, f_max); + ui->centerFrequency->setValueRange(7, f_min/1000, f_max/1000); + + createRangesControl(m_sampleSource->getRateRanges(), "Sample Rate", "kS/s"); } SoapySDRInputGui::~SoapySDRInputGui() @@ -49,6 +56,61 @@ void SoapySDRInputGui::destroy() delete this; } +void SoapySDRInputGui::createRangesControl(const SoapySDR::RangeList& rangeList, const QString& text, const QString& unit) +{ + if (rangeList.size() == 0) { // return early if the range list is empty + return; + } + + bool rangeDiscrete = true; // discretes values + bool rangeInterval = true; // intervals + + for (const auto &it : rangeList) + { + if (it.minimum() != it.maximum()) { + rangeDiscrete = false; + } else { + rangeInterval = false; + } + } + + if (rangeDiscrete) + { + DiscreteRangeGUI *rangeGUI = new DiscreteRangeGUI(ui->scrollAreaWidgetContents); + rangeGUI->setLabel(text); + rangeGUI->setUnits(unit); + + for (const auto &it : rangeList) { + rangeGUI->addItem(QString("%1").arg(QString::number(it.minimum()/1000.0, 'f', 0)), it.minimum()); + } + +// QHBoxLayout *layout = new QHBoxLayout(); +// QLabel *rangeLabel = new QLabel(); +// rangeLabel->setText(text); +// QLabel *rangeUnit = new QLabel(); +// rangeUnit->setText(unit); +// QComboBox *rangeCombo = new QComboBox(); +// +// for (const auto &it : rangeList) { +// rangeCombo->addItem(QString("%1").arg(QString::number(it.minimum()/1000.0, 'f', 0))); +// } +// +// layout->addWidget(rangeLabel); +// layout->addWidget(rangeCombo); +// layout->addWidget(rangeUnit); +// layout->setMargin(0); +// layout->setSpacing(6); +// rangeLabel->show(); +// rangeCombo->show(); +// QWidget *window = new QWidget(ui->scrollAreaWidgetContents); +// window->setFixedWidth(300); +// window->setFixedHeight(30); +// window->setContentsMargins(0,0,0,0); +// //window->setStyleSheet("background-color:black;"); +// window->setLayout(layout); + } +} + void SoapySDRInputGui::setName(const QString& name) { setObjectName(name); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.h b/plugins/samplesource/soapysdrinput/soapysdrinputgui.h index 970b72d7a..0210c5c49 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.h @@ -20,6 +20,8 @@ #include #include +#include + #include "plugin/plugininstancegui.h" #include "util/messagequeue.h" @@ -51,6 +53,7 @@ public: virtual bool handleMessage(const Message& message); private: + void createRangesControl(const SoapySDR::RangeList& rangeList, const QString& text, const QString& unit); Ui::SoapySDRInputGui* ui; DeviceUISet* m_deviceUISet; diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui b/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui index 30049db37..0da6bc007 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui @@ -7,15 +7,9 @@ 0 0 324 - 276 + 176 - - - 0 - 0 - - 320 @@ -190,15 +184,9 @@ 0 0 304 - 128 + 120 - - - 0 - 0 - - 3 @@ -314,6 +302,17 @@ + + + + + + Tata + + + + + @@ -341,54 +340,10 @@ - - - - - - Didi - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - -