USRP: Add support for non-discoverable devices and user arguments.

Tweak UI so icons aren't squashed.
pull/1271/head
Jon Beniston 2022-06-01 15:37:50 +01:00
rodzic 2c7b8374d6
commit 49460a48df
16 zmienionych plików z 253 dodań i 131 usunięć

Wyświetl plik

@ -52,7 +52,7 @@ void DeviceUSRP::enumOriginDevices(const QString& hardwareId, PluginInterface::O
qDebug() << "DeviceUSRP::enumOriginDevices: found USRP device " << displayedName;
DeviceUSRPParams usrpParams;
usrpParams.open(id.toStdString().c_str(), true);
usrpParams.open(id, true);
usrpParams.close();
originDevices.append(PluginInterface::OriginDevice(

Wyświetl plik

@ -19,86 +19,98 @@
#include <QDebug>
#include "deviceusrpparam.h"
bool DeviceUSRPParams::open(const char *deviceStr, bool channelNumOnly)
bool DeviceUSRPParams::open(const QString &deviceStr, bool channelNumOnly)
{
qDebug("DeviceUSRPParams::open: %s", (const char *) deviceStr);
qDebug("DeviceUSRPParams::open: %s", qPrintable(deviceStr));
std::string device_args(deviceStr);
m_dev = uhd::usrp::multi_usrp::make(device_args);
// Save information about what the radio supports
m_nbRxChannels = m_dev->get_rx_num_channels();
m_nbTxChannels = m_dev->get_tx_num_channels();
// Speed up program initialisation, by not getting all properties
// If we could find out number of channles without ::make ing the device
// that would be even better
if (!channelNumOnly)
try
{
m_lpfRangeRx = m_dev->get_rx_bandwidth_range();
m_lpfRangeTx = m_dev->get_tx_bandwidth_range();
std::string device_args(qPrintable(deviceStr));
m_loRangeRx = m_dev->get_fe_rx_freq_range();
m_loRangeTx = m_dev->get_fe_tx_freq_range();
// For USB
// The recv_frame_size must be a multiple of 8 bytes and not a multiple of 1024 bytes.
// recv_frame_size max is 16360.
//m_dev = uhd::usrp::multi_usrp::make(device_args + ",recv_frame_size=16392");
m_dev = uhd::usrp::multi_usrp::make(device_args);
// For some devices (B210), rx/tx_rates vary with master_clock_rate
// Note master_clock_rate is rate between FPGA and RFIC
// tx/rx_rate is rate between PC and FPGA
uhd::meta_range_t clockRange = m_dev->get_master_clock_rate_range();
if (clockRange.start() == clockRange.stop())
// Save information about what the radio supports
m_nbRxChannels = m_dev->get_rx_num_channels();
m_nbTxChannels = m_dev->get_tx_num_channels();
// Speed up program initialisation, by not getting all properties
// If we could find out number of channles without ::make ing the device
// that would be even better
if (!channelNumOnly)
{
m_srRangeRx = m_dev->get_rx_rates();
m_srRangeTx = m_dev->get_tx_rates();
}
else
{
// Find max and min sample rate, for max and min master clock rates
m_dev->set_master_clock_rate(clockRange.start());
uhd::meta_range_t rxLow = m_dev->get_rx_rates();
uhd::meta_range_t txLow = m_dev->get_tx_rates();
m_lpfRangeRx = m_dev->get_rx_bandwidth_range();
m_lpfRangeTx = m_dev->get_tx_bandwidth_range();
m_dev->set_master_clock_rate(clockRange.stop());
uhd::meta_range_t rxHigh = m_dev->get_rx_rates();
uhd::meta_range_t txHigh = m_dev->get_tx_rates();
m_loRangeRx = m_dev->get_fe_rx_freq_range();
m_loRangeTx = m_dev->get_fe_tx_freq_range();
m_srRangeRx = uhd::meta_range_t(std::min(rxLow.start(), rxHigh.start()), std::max(rxLow.stop(), rxHigh.stop()));
m_srRangeTx = uhd::meta_range_t(std::min(txLow.start(), txHigh.start()), std::max(txLow.stop(), txHigh.stop()));
// Need to restore automatic clock rate
uhd::property_tree::sptr properties = m_dev->get_device()->get_tree();
if (properties->exists("/mboards/0/auto_tick_rate"))
// For some devices (B210), rx/tx_rates vary with master_clock_rate
// Note master_clock_rate is rate between FPGA and RFIC
// tx/rx_rate is rate between PC and FPGA
uhd::meta_range_t clockRange = m_dev->get_master_clock_rate_range();
if (clockRange.start() == clockRange.stop())
{
properties->access<bool>("/mboards/0/auto_tick_rate").set(true);
m_srRangeRx = m_dev->get_rx_rates();
m_srRangeTx = m_dev->get_tx_rates();
}
else
{
// Find max and min sample rate, for max and min master clock rates
m_dev->set_master_clock_rate(clockRange.start());
uhd::meta_range_t rxLow = m_dev->get_rx_rates();
uhd::meta_range_t txLow = m_dev->get_tx_rates();
m_dev->set_master_clock_rate(clockRange.stop());
uhd::meta_range_t rxHigh = m_dev->get_rx_rates();
uhd::meta_range_t txHigh = m_dev->get_tx_rates();
m_srRangeRx = uhd::meta_range_t(std::min(rxLow.start(), rxHigh.start()), std::max(rxLow.stop(), rxHigh.stop()));
m_srRangeTx = uhd::meta_range_t(std::min(txLow.start(), txHigh.start()), std::max(txLow.stop(), txHigh.stop()));
// Need to restore automatic clock rate
uhd::property_tree::sptr properties = m_dev->get_device()->get_tree();
if (properties->exists("/mboards/0/auto_tick_rate"))
{
properties->access<bool>("/mboards/0/auto_tick_rate").set(true);
}
}
m_gainRangeRx = m_dev->get_rx_gain_range();
m_gainRangeTx = m_dev->get_tx_gain_range();
std::vector<std::string> txAntennas = m_dev->get_tx_antennas();
m_txAntennas.reserve(txAntennas.size());
for(size_t i = 0, l = txAntennas.size(); i < l; ++i)
m_txAntennas << QString::fromStdString(txAntennas[i]);
std::vector<std::string> rxAntennas = m_dev->get_rx_antennas();
m_rxAntennas.reserve(rxAntennas.size());
for(size_t i = 0, l = rxAntennas.size(); i < l; ++i)
m_rxAntennas << QString::fromStdString(rxAntennas[i]);
std::vector<std::string> rxGainNames = m_dev->get_rx_gain_names();
m_rxGainNames.reserve(rxGainNames.size());
for(size_t i = 0, l = rxGainNames.size(); i < l; ++i)
m_rxGainNames << QString::fromStdString(rxGainNames[i]);
std::vector<std::string> clockSources = m_dev->get_clock_sources(0);
m_clockSources.reserve(clockSources.size());
for(size_t i = 0, l = clockSources.size(); i < l; ++i)
m_clockSources << QString::fromStdString(clockSources[i]);
}
m_gainRangeRx = m_dev->get_rx_gain_range();
m_gainRangeTx = m_dev->get_tx_gain_range();
std::vector<std::string> txAntennas = m_dev->get_tx_antennas();
m_txAntennas.reserve(txAntennas.size());
for(size_t i = 0, l = txAntennas.size(); i < l; ++i)
m_txAntennas << QString::fromStdString(txAntennas[i]);
std::vector<std::string> rxAntennas = m_dev->get_rx_antennas();
m_rxAntennas.reserve(rxAntennas.size());
for(size_t i = 0, l = rxAntennas.size(); i < l; ++i)
m_rxAntennas << QString::fromStdString(rxAntennas[i]);
std::vector<std::string> rxGainNames = m_dev->get_rx_gain_names();
m_rxGainNames.reserve(rxGainNames.size());
for(size_t i = 0, l = rxGainNames.size(); i < l; ++i)
m_rxGainNames << QString::fromStdString(rxGainNames[i]);
std::vector<std::string> clockSources = m_dev->get_clock_sources(0);
m_clockSources.reserve(clockSources.size());
for(size_t i = 0, l = clockSources.size(); i < l; ++i)
m_clockSources << QString::fromStdString(clockSources[i]);
return true;
}
catch (const std::exception& e)
{
qDebug() << "DeviceUSRPParams::open: exception: " << e.what();
return false;
}
return true;
}
void DeviceUSRPParams::close()

Wyświetl plik

@ -74,7 +74,7 @@ struct DEVICES_API DeviceUSRPParams
/**
* Opens and initialize the device and obtain information (# channels, ranges, ...)
*/
bool open(const char *deviceStr, bool channelNumOnly);
bool open(const QString &deviceStr, bool channelNumOnly);
void close();
uhd::usrp::multi_usrp::sptr getDevice() { return m_dev; }

Wyświetl plik

@ -4,6 +4,8 @@
This output sample sink plugin sends its samples to a [USRP device](https://www.ettus.com/products/).
When using a USRP device over a network, you have to create a non discoverable device reference in the [user arguments dialog](https://github.com/f4exb/sdrangel/blob/master/sdrgui/deviceuserargs.md) from the main window Preferences > Devices menu. You must use the USRP hardware ID then specify the device address with an addr parameter in the user arguments for example: addr=192.168.1.10. Note that this will become effective once SDRangel is restarted.
<h2>Interface</h2>
The top and bottom bars of the device window are described [here](../../../sdrgui/device/readme.md)

Wyświetl plik

@ -183,9 +183,24 @@ bool USRPOutput::openDevice()
qDebug("USRPOutput::openDevice: open device here");
m_deviceShared.m_deviceParams = new DeviceUSRPParams();
char serial[256];
strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
m_deviceShared.m_deviceParams->open(serial, false);
QString deviceStr;
// If a non-discoverable device, serial with be of the form USRP-N
if (m_deviceAPI->getSamplingDeviceSerial().startsWith("USRP"))
{
deviceStr = m_deviceAPI->getHardwareUserArguments();
}
else
{
deviceStr = m_deviceAPI->getSamplingDeviceSerial();
if (m_deviceAPI->getHardwareUserArguments().size() != 0) {
deviceStr = deviceStr + ',' + m_deviceAPI->getHardwareUserArguments();
}
}
if (!m_deviceShared.m_deviceParams->open(deviceStr, false))
{
qCritical("USRPOutput::openDevice: failed to open device");
return false;
}
m_deviceShared.m_channel = requestedChannel; // acknowledge the requested channel
}
@ -463,33 +478,69 @@ void USRPOutput::setCenterFrequency(qint64 centerFrequency)
}
}
std::size_t USRPOutput::getChannelIndex()
int USRPOutput::getChannelIndex()
{
return m_deviceShared.m_channel;
}
void USRPOutput::getLORange(float& minF, float& maxF) const
{
minF = m_deviceShared.m_deviceParams->m_loRangeTx.start();
maxF = m_deviceShared.m_deviceParams->m_loRangeTx.stop();
try
{
minF = m_deviceShared.m_deviceParams->m_loRangeTx.start();
maxF = m_deviceShared.m_deviceParams->m_loRangeTx.stop();
}
catch (std::exception& e)
{
qDebug() << "USRPOutput::getLORange: exception: " << e.what();
minF = 0.0f;
maxF = 0.0f;
}
}
void USRPOutput::getSRRange(float& minF, float& maxF) const
{
minF = m_deviceShared.m_deviceParams->m_srRangeTx.start();
maxF = m_deviceShared.m_deviceParams->m_srRangeTx.stop();
try
{
minF = m_deviceShared.m_deviceParams->m_srRangeTx.start();
maxF = m_deviceShared.m_deviceParams->m_srRangeTx.stop();
}
catch (std::exception& e)
{
qDebug() << "USRPOutput::getLORange: exception: " << e.what();
minF = 0.0f;
maxF = 0.0f;
}
}
void USRPOutput::getLPRange(float& minF, float& maxF) const
{
minF = m_deviceShared.m_deviceParams->m_lpfRangeTx.start();
maxF = m_deviceShared.m_deviceParams->m_lpfRangeTx.stop();
try
{
minF = m_deviceShared.m_deviceParams->m_lpfRangeTx.start();
maxF = m_deviceShared.m_deviceParams->m_lpfRangeTx.stop();
}
catch (std::exception& e)
{
qDebug() << "USRPOutput::getLORange: exception: " << e.what();
minF = 0.0f;
maxF = 0.0f;
}
}
void USRPOutput::getGainRange(float& minF, float& maxF) const
{
minF = m_deviceShared.m_deviceParams->m_gainRangeTx.start();
maxF = m_deviceShared.m_deviceParams->m_gainRangeTx.stop();
try
{
minF = m_deviceShared.m_deviceParams->m_gainRangeTx.start();
maxF = m_deviceShared.m_deviceParams->m_gainRangeTx.stop();
}
catch (std::exception& e)
{
qDebug() << "USRPOutput::getLORange: exception: " << e.what();
minF = 0.0f;
maxF = 0.0f;
}
}
QStringList USRPOutput::getTxAntennas() const

Wyświetl plik

@ -208,7 +208,7 @@ public:
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response);
std::size_t getChannelIndex();
int getChannelIndex();
void getLORange(float& minF, float& maxF) const;
void getSRRange(float& minF, float& maxF) const;
void getLPRange(float& minF, float& maxF) const;

Wyświetl plik

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>360</width>
<height>214</height>
<height>192</height>
</rect>
</property>
<property name="sizePolicy">
@ -19,13 +19,13 @@
<property name="minimumSize">
<size>
<width>360</width>
<height>163</height>
<height>192</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>380</width>
<height>214</height>
<height>192</height>
</size>
</property>
<property name="font">
@ -217,6 +217,13 @@
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">

Wyświetl plik

@ -35,7 +35,7 @@
const PluginDescriptor USRPOutputPlugin::m_pluginDescriptor = {
QStringLiteral("USRP"),
QStringLiteral("URSP Output"),
QStringLiteral("7.0.0"),
QStringLiteral("7.3.1"),
QStringLiteral("(c) Jon Beniston, M7RCE and Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,
@ -43,7 +43,7 @@ const PluginDescriptor USRPOutputPlugin::m_pluginDescriptor = {
};
static constexpr const char* const m_hardwareID = "USRP";
static constexpr const char* const m_deviceTypeID = USRPOUTPUT_DEVICE_TYPE_ID;
const char* const USRPOutputPlugin::m_deviceTypeID = USRPOUTPUT_DEVICE_TYPE_ID;
USRPOutputPlugin::USRPOutputPlugin(QObject* parent) :
QObject(parent)

Wyświetl plik

@ -45,6 +45,9 @@ public:
DeviceUISet *deviceUISet);
virtual DeviceSampleSink* createSampleSinkPluginInstance(const QString& sinkId, DeviceAPI *deviceAPI);
virtual DeviceWebAPIAdapter* createDeviceWebAPIAdapter() const;
virtual QString getDeviceTypeId() const { return m_deviceTypeID; }
static const char* const m_deviceTypeID;
private:
static const PluginDescriptor m_pluginDescriptor;

Wyświetl plik

@ -4,6 +4,8 @@
This input sample source plugin gets its samples from a [USRP device](https://www.ettus.com/product-categories/usrp-bus-series/).
When using a USRP device over a network, you have to create a non discoverable device reference in the [user arguments dialog](https://github.com/f4exb/sdrangel/blob/master/sdrgui/deviceuserargs.md) from the main window Preferences > Devices menu. You must use the USRP hardware ID then specify the device address with an addr parameter in the user arguments for example: addr=192.168.1.10. Note that this will become effective once SDRangel is restarted.
<h2>Interface</h2>
The top and bottom bars of the device window are described [here](../../../sdrgui/device/readme.md)

Wyświetl plik

@ -212,9 +212,24 @@ bool USRPInput::openDevice()
qDebug("USRPInput::openDevice: open device here");
m_deviceShared.m_deviceParams = new DeviceUSRPParams();
char serial[256];
strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
m_deviceShared.m_deviceParams->open(serial, false);
QString deviceStr;
// If a non-discoverable device, serial with be of the form USRP-N
if (m_deviceAPI->getSamplingDeviceSerial().startsWith("USRP"))
{
deviceStr = m_deviceAPI->getHardwareUserArguments();
}
else
{
deviceStr = m_deviceAPI->getSamplingDeviceSerial();
if (m_deviceAPI->getHardwareUserArguments().size() != 0) {
deviceStr = deviceStr + ',' + m_deviceAPI->getHardwareUserArguments();
}
}
if (!m_deviceShared.m_deviceParams->open(deviceStr, false))
{
qCritical("USRPInput::openDevice: failed to open device");
return false;
}
m_deviceShared.m_channel = requestedChannel; // acknowledge the requested channel
}
@ -499,33 +514,69 @@ void USRPInput::setCenterFrequency(qint64 centerFrequency)
}
}
std::size_t USRPInput::getChannelIndex()
int USRPInput::getChannelIndex()
{
return m_deviceShared.m_channel;
}
void USRPInput::getLORange(float& minF, float& maxF) const
{
minF = m_deviceShared.m_deviceParams->m_loRangeRx.start();
maxF = m_deviceShared.m_deviceParams->m_loRangeRx.stop();
try
{
minF = m_deviceShared.m_deviceParams->m_loRangeRx.start();
maxF = m_deviceShared.m_deviceParams->m_loRangeRx.stop();
}
catch (std::exception& e)
{
qDebug() << "USRPInput::getLORange: exception: " << e.what();
minF = 0.0f;
maxF = 0.0f;
}
}
void USRPInput::getSRRange(float& minF, float& maxF) const
{
minF = m_deviceShared.m_deviceParams->m_srRangeRx.start();
maxF = m_deviceShared.m_deviceParams->m_srRangeRx.stop();
try
{
minF = m_deviceShared.m_deviceParams->m_srRangeRx.start();
maxF = m_deviceShared.m_deviceParams->m_srRangeRx.stop();
}
catch (std::exception& e)
{
qDebug() << "USRPInput::getSRRange: exception: " << e.what();
minF = 0.0f;
maxF = 0.0f;
}
}
void USRPInput::getLPRange(float& minF, float& maxF) const
{
minF = m_deviceShared.m_deviceParams->m_lpfRangeRx.start();
maxF = m_deviceShared.m_deviceParams->m_lpfRangeRx.stop();
try
{
minF = m_deviceShared.m_deviceParams->m_lpfRangeRx.start();
maxF = m_deviceShared.m_deviceParams->m_lpfRangeRx.stop();
}
catch (std::exception& e)
{
qDebug() << "USRPInput::getLPRange: exception: " << e.what();
minF = 0.0f;
maxF = 0.0f;
}
}
void USRPInput::getGainRange(float& minF, float& maxF) const
{
minF = m_deviceShared.m_deviceParams->m_gainRangeRx.start();
maxF = m_deviceShared.m_deviceParams->m_gainRangeRx.stop();
try
{
minF = m_deviceShared.m_deviceParams->m_gainRangeRx.start();
maxF = m_deviceShared.m_deviceParams->m_gainRangeRx.stop();
}
catch (std::exception& e)
{
qDebug() << "USRPInput::getGainRange: exception: " << e.what();
minF = 0.0f;
maxF = 0.0f;
}
}
QStringList USRPInput::getRxAntennas() const

Wyświetl plik

@ -208,7 +208,7 @@ public:
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response);
std::size_t getChannelIndex();
int getChannelIndex();
void getLORange(float& minF, float& maxF) const;
void getSRRange(float& minF, float& maxF) const;
void getLPRange(float& minF, float& maxF) const;

Wyświetl plik

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>360</width>
<height>174</height>
<height>192</height>
</rect>
</property>
<property name="sizePolicy">
@ -19,13 +19,13 @@
<property name="minimumSize">
<size>
<width>360</width>
<height>174</height>
<height>192</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>380</width>
<height>221</height>
<height>192</height>
</size>
</property>
<property name="font">
@ -56,7 +56,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_freq">
<property name="topMargin">
<number>4</number>
<number>2</number>
</property>
<item>
<layout class="QVBoxLayout" name="freqLeftLayout">
@ -145,7 +145,6 @@
<font>
<family>Liberation Mono</family>
<pointsize>16</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
@ -162,12 +161,6 @@
</item>
<item>
<layout class="QVBoxLayout" name="freqRightLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" name="freqRightTopLayout">
<item>
@ -225,6 +218,13 @@
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
@ -359,7 +359,6 @@
<font>
<family>Liberation Mono</family>
<pointsize>12</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
@ -454,6 +453,13 @@
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="gainLayout">
<property name="topMargin">
@ -534,13 +540,6 @@
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
@ -554,13 +553,6 @@
</property>
</spacer>
</item>
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="dcOffset">
<property name="toolTip">
@ -623,7 +615,6 @@
<font>
<family>Liberation Mono</family>
<pointsize>12</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
@ -674,7 +665,6 @@
<font>
<family>Liberation Mono</family>
<pointsize>12</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
</property>

Wyświetl plik

@ -35,7 +35,7 @@
const PluginDescriptor USRPInputPlugin::m_pluginDescriptor = {
QStringLiteral("USRP"),
QStringLiteral("USRP Input"),
QStringLiteral("7.0.0"),
QStringLiteral("7.3.1"),
QStringLiteral("(c) Jon Beniston, M7RCE and Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,
@ -43,7 +43,7 @@ const PluginDescriptor USRPInputPlugin::m_pluginDescriptor = {
};
static constexpr const char* const m_hardwareID = "USRP";
static constexpr const char* const m_deviceTypeID = USRP_DEVICE_TYPE_ID;
const char* const USRPInputPlugin::m_deviceTypeID = USRP_DEVICE_TYPE_ID;
USRPInputPlugin::USRPInputPlugin(QObject* parent) :
QObject(parent)

Wyświetl plik

@ -46,6 +46,10 @@ public:
virtual DeviceSampleSource* createSampleSourcePluginInstance(const QString& sourceId, DeviceAPI *deviceAPI);
virtual DeviceWebAPIAdapter* createDeviceWebAPIAdapter() const;
virtual QString getDeviceTypeId() const { return m_deviceTypeID; }
static const char* const m_deviceTypeID;
private:
static const PluginDescriptor m_pluginDescriptor;
};

Wyświetl plik

@ -22,7 +22,7 @@ Use this button to import the selected device in the panel above (1) to the pane
<h2>3 Non discoverable device hardware ID</h2>
Some devices cannot be discovered automatically. This is the case for networked devices in particular the PlutoSDR. In conjunctions with (4) and (5) you can define devices that can be added to the list of available devices for selection. Note that you will need to restart SDRangel for this to be effective.
Some devices cannot be discovered automatically. This is the case for networked devices in particular the PlutoSDR and some USRPs. In conjunctions with (4) and (5) you can define devices that can be added to the list of available devices for selection. Note that you will need to restart SDRangel for this to be effective.
Once the device is defined user arguments like the IP address can be specified for it.