mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-05 08:21:16 -05:00
Merge USRP updates
This commit is contained in:
commit
91f204a74d
@ -22,6 +22,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <uhd/types/device_addr.hpp>
|
#include <uhd/types/device_addr.hpp>
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ void DeviceUSRP::enumOriginDevices(const QString& hardwareId, PluginInterface::O
|
|||||||
qDebug() << "DeviceUSRP::enumOriginDevices: found USRP device " << displayedName;
|
qDebug() << "DeviceUSRP::enumOriginDevices: found USRP device " << displayedName;
|
||||||
|
|
||||||
DeviceUSRPParams usrpParams;
|
DeviceUSRPParams usrpParams;
|
||||||
usrpParams.open(id.toStdString().c_str());
|
usrpParams.open(id.toStdString().c_str(), true);
|
||||||
usrpParams.close();
|
usrpParams.close();
|
||||||
|
|
||||||
originDevices.append(PluginInterface::OriginDevice(
|
originDevices.append(PluginInterface::OriginDevice(
|
||||||
@ -69,3 +70,31 @@ void DeviceUSRP::enumOriginDevices(const QString& hardwareId, PluginInterface::O
|
|||||||
qDebug() << "DeviceUSRP::enumOriginDevices: exception: " << e.what();
|
qDebug() << "DeviceUSRP::enumOriginDevices: exception: " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceUSRP::waitForLock(uhd::usrp::multi_usrp::sptr usrp, const QString& clockSource, int channel)
|
||||||
|
{
|
||||||
|
int tries;
|
||||||
|
const int maxTries = 100;
|
||||||
|
|
||||||
|
// Wait for Ref lock
|
||||||
|
std::vector<std::string> sensor_names;
|
||||||
|
sensor_names = usrp->get_tx_sensor_names(channel);
|
||||||
|
if (clockSource == "external")
|
||||||
|
{
|
||||||
|
if (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end())
|
||||||
|
{
|
||||||
|
for (tries = 0; !usrp->get_mboard_sensor("ref_locked", 0).to_bool() && (tries < maxTries); tries++)
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
if (tries == maxTries)
|
||||||
|
qCritical("USRPInput::acquireChannel: Failed to lock ref");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Wait for LO lock
|
||||||
|
if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end())
|
||||||
|
{
|
||||||
|
for (tries = 0; !usrp->get_tx_sensor("lo_locked", channel).to_bool() && (tries < maxTries); tries++)
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
if (tries == maxTries)
|
||||||
|
qCritical("USRPInput::acquireChannel: Failed to lock LO");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -33,8 +33,8 @@ public:
|
|||||||
/** Enumeration of USRP hardware devices */
|
/** Enumeration of USRP hardware devices */
|
||||||
static void enumOriginDevices(const QString& hardwareId, PluginInterface::OriginDevices& originDevices);
|
static void enumOriginDevices(const QString& hardwareId, PluginInterface::OriginDevices& originDevices);
|
||||||
|
|
||||||
/** Block size used for transferring IQ samples to and from the device. This perhaps needs tuning. */
|
/** Wait for ref clock and LO to lock */
|
||||||
static const unsigned int blockSize = (1<<15);
|
static void waitForLock(uhd::usrp::multi_usrp::sptr usrp, const QString& clockSource, int channel);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DEVICES_USRP_DEVICEUSRP_H_ */
|
#endif /* DEVICES_USRP_DEVICEUSRP_H_ */
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "deviceusrpparam.h"
|
#include "deviceusrpparam.h"
|
||||||
|
|
||||||
bool DeviceUSRPParams::open(const char *deviceStr)
|
bool DeviceUSRPParams::open(const char *deviceStr, bool channelNumOnly)
|
||||||
{
|
{
|
||||||
qDebug("DeviceUSRPParams::open: %s", (const char *) deviceStr);
|
qDebug("DeviceUSRPParams::open: %s", (const char *) deviceStr);
|
||||||
|
|
||||||
@ -32,14 +32,47 @@ bool DeviceUSRPParams::open(const char *deviceStr)
|
|||||||
m_nbRxChannels = m_dev->get_rx_num_channels();
|
m_nbRxChannels = m_dev->get_rx_num_channels();
|
||||||
m_nbTxChannels = m_dev->get_tx_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_lpfRangeRx = m_dev->get_rx_bandwidth_range();
|
m_lpfRangeRx = m_dev->get_rx_bandwidth_range();
|
||||||
m_lpfRangeTx = m_dev->get_tx_bandwidth_range();
|
m_lpfRangeTx = m_dev->get_tx_bandwidth_range();
|
||||||
|
|
||||||
m_loRangeRx = m_dev->get_fe_rx_freq_range();
|
m_loRangeRx = m_dev->get_fe_rx_freq_range();
|
||||||
m_loRangeTx = m_dev->get_fe_tx_freq_range();
|
m_loRangeTx = m_dev->get_fe_tx_freq_range();
|
||||||
|
|
||||||
|
// 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())
|
||||||
|
{
|
||||||
m_srRangeRx = m_dev->get_rx_rates();
|
m_srRangeRx = m_dev->get_rx_rates();
|
||||||
m_srRangeTx = m_dev->get_tx_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_gainRangeRx = m_dev->get_rx_gain_range();
|
||||||
m_gainRangeTx = m_dev->get_tx_gain_range();
|
m_gainRangeTx = m_dev->get_tx_gain_range();
|
||||||
@ -63,6 +96,7 @@ bool DeviceUSRPParams::open(const char *deviceStr)
|
|||||||
m_clockSources.reserve(clockSources.size());
|
m_clockSources.reserve(clockSources.size());
|
||||||
for(size_t i = 0, l = clockSources.size(); i < l; ++i)
|
for(size_t i = 0, l = clockSources.size(); i < l; ++i)
|
||||||
m_clockSources << QString::fromStdString(clockSources[i]);
|
m_clockSources << QString::fromStdString(clockSources[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -47,11 +47,6 @@ struct DEVICES_API DeviceUSRPParams
|
|||||||
uhd::meta_range_t m_srRangeTx; //!< Sample rate range
|
uhd::meta_range_t m_srRangeTx; //!< Sample rate range
|
||||||
uhd::gain_range_t m_gainRangeRx; //!< Gain range for Rx
|
uhd::gain_range_t m_gainRangeRx; //!< Gain range for Rx
|
||||||
uhd::gain_range_t m_gainRangeTx; //!< Gain range for Tx
|
uhd::gain_range_t m_gainRangeTx; //!< Gain range for Tx
|
||||||
float m_sampleRate; //!< Sample rate between host and device
|
|
||||||
int m_log2OvSRRx; //!< log2 of Rx oversampling (0..5)
|
|
||||||
int m_log2OvSRTx; //!< log2 of Tx oversampling (0..5)
|
|
||||||
float m_rxFrequency; //!< Rx frequency
|
|
||||||
float m_txFrequency; //!< Tx frequency
|
|
||||||
QStringList m_txAntennas; //!< List of Tx antenna names
|
QStringList m_txAntennas; //!< List of Tx antenna names
|
||||||
QStringList m_rxAntennas; //!< List of Rx antenna names
|
QStringList m_rxAntennas; //!< List of Rx antenna names
|
||||||
QStringList m_rxGainNames; //!< List of Rx gain stages - Currently this seems limited to "PGA"
|
QStringList m_rxGainNames; //!< List of Rx gain stages - Currently this seems limited to "PGA"
|
||||||
@ -61,11 +56,6 @@ struct DEVICES_API DeviceUSRPParams
|
|||||||
m_dev(),
|
m_dev(),
|
||||||
m_nbRxChannels(0),
|
m_nbRxChannels(0),
|
||||||
m_nbTxChannels(0),
|
m_nbTxChannels(0),
|
||||||
m_sampleRate(1e6),
|
|
||||||
m_log2OvSRRx(0),
|
|
||||||
m_log2OvSRTx(0),
|
|
||||||
m_rxFrequency(1e6),
|
|
||||||
m_txFrequency(1e6),
|
|
||||||
m_lpfRangeRx(),
|
m_lpfRangeRx(),
|
||||||
m_lpfRangeTx(),
|
m_lpfRangeTx(),
|
||||||
m_loRangeRx(),
|
m_loRangeRx(),
|
||||||
@ -84,7 +74,7 @@ struct DEVICES_API DeviceUSRPParams
|
|||||||
/**
|
/**
|
||||||
* Opens and initialize the device and obtain information (# channels, ranges, ...)
|
* Opens and initialize the device and obtain information (# channels, ranges, ...)
|
||||||
*/
|
*/
|
||||||
bool open(const char *deviceStr);
|
bool open(const char *deviceStr, bool channelNumOnly);
|
||||||
void close();
|
void close();
|
||||||
uhd::usrp::multi_usrp::sptr getDevice() { return m_dev; }
|
uhd::usrp::multi_usrp::sptr getDevice() { return m_dev; }
|
||||||
|
|
||||||
|
@ -36,31 +36,43 @@ public:
|
|||||||
public:
|
public:
|
||||||
int getDevSampleRate() const { return m_devSampleRate; }
|
int getDevSampleRate() const { return m_devSampleRate; }
|
||||||
uint64_t getCenterFrequency() const { return m_centerFrequency; }
|
uint64_t getCenterFrequency() const { return m_centerFrequency; }
|
||||||
|
int getLOOffset() const { return m_loOffset; }
|
||||||
|
int getMasterClockRate() const { return m_masterClockRate; }
|
||||||
bool getRxElseTx() const { return m_rxElseTx; }
|
bool getRxElseTx() const { return m_rxElseTx; }
|
||||||
|
|
||||||
static MsgReportBuddyChange* create(
|
static MsgReportBuddyChange* create(
|
||||||
int devSampleRate,
|
int devSampleRate,
|
||||||
uint64_t centerFrequency,
|
uint64_t centerFrequency,
|
||||||
|
int loOffset,
|
||||||
|
int masterClockRate,
|
||||||
bool rxElseTx)
|
bool rxElseTx)
|
||||||
{
|
{
|
||||||
return new MsgReportBuddyChange(
|
return new MsgReportBuddyChange(
|
||||||
devSampleRate,
|
devSampleRate,
|
||||||
centerFrequency,
|
centerFrequency,
|
||||||
|
loOffset,
|
||||||
|
masterClockRate,
|
||||||
rxElseTx);
|
rxElseTx);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_devSampleRate; //!< device/host sample rate
|
int m_devSampleRate; //!< device/host sample rate
|
||||||
uint64_t m_centerFrequency; //!< Center frequency
|
uint64_t m_centerFrequency; //!< Center frequency
|
||||||
|
int m_loOffset; //!< LO offset
|
||||||
|
int m_masterClockRate; //!< FPGA/RFIC sample rate
|
||||||
bool m_rxElseTx; //!< tells which side initiated the message
|
bool m_rxElseTx; //!< tells which side initiated the message
|
||||||
|
|
||||||
MsgReportBuddyChange(
|
MsgReportBuddyChange(
|
||||||
int devSampleRate,
|
int devSampleRate,
|
||||||
uint64_t centerFrequency,
|
uint64_t centerFrequency,
|
||||||
|
int loOffset,
|
||||||
|
int masterClockRate,
|
||||||
bool rxElseTx) :
|
bool rxElseTx) :
|
||||||
Message(),
|
Message(),
|
||||||
m_devSampleRate(devSampleRate),
|
m_devSampleRate(devSampleRate),
|
||||||
m_centerFrequency(centerFrequency),
|
m_centerFrequency(centerFrequency),
|
||||||
|
m_loOffset(loOffset),
|
||||||
|
m_masterClockRate(masterClockRate),
|
||||||
m_rxElseTx(rxElseTx)
|
m_rxElseTx(rxElseTx)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
@ -105,6 +105,10 @@ Use this slider to adjust the global gain of the Tx chain. The allowable values
|
|||||||
|
|
||||||
This is the Tx hardware filter bandwidth in kHz in the AD936x device for the given channel. Use the wheels to adjust the value. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2.
|
This is the Tx hardware filter bandwidth in kHz in the AD936x device for the given channel. Use the wheels to adjust the value. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2.
|
||||||
|
|
||||||
|
<h3>Tx LO offset</h3>
|
||||||
|
|
||||||
|
This adjusts the Tx local oscillator (LO) frequency from the centre frequency by the given amount in kHz, and the NCOs are used to digitally shift the signal to the set centre frequency. This can be used to push the Tx LO leakage (which for the AD396x is -50dBc) out of band. The shift should be less than half of the sample rate.
|
||||||
|
|
||||||
<h3>12: Stream status indicator</h3>
|
<h3>12: Stream status indicator</h3>
|
||||||
|
|
||||||
This label turns green when data has been transmitted to the device.
|
This label turns green when data has been transmitted to the device.
|
||||||
|
@ -51,6 +51,7 @@ USRPOutput::USRPOutput(DeviceAPI *deviceAPI) :
|
|||||||
m_deviceAPI(deviceAPI),
|
m_deviceAPI(deviceAPI),
|
||||||
m_settings(),
|
m_settings(),
|
||||||
m_usrpOutputThread(nullptr),
|
m_usrpOutputThread(nullptr),
|
||||||
|
m_bufSamples(0),
|
||||||
m_deviceDescription("USRPOutput"),
|
m_deviceDescription("USRPOutput"),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_channelAcquired(false)
|
m_channelAcquired(false)
|
||||||
@ -174,7 +175,7 @@ bool USRPOutput::openDevice()
|
|||||||
m_deviceShared.m_deviceParams = new DeviceUSRPParams();
|
m_deviceShared.m_deviceParams = new DeviceUSRPParams();
|
||||||
char serial[256];
|
char serial[256];
|
||||||
strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
|
strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
|
||||||
m_deviceShared.m_deviceParams->open(serial);
|
m_deviceShared.m_deviceParams->open(serial, false);
|
||||||
m_deviceShared.m_channel = requestedChannel; // acknowledge the requested channel
|
m_deviceShared.m_channel = requestedChannel; // acknowledge the requested channel
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,8 +289,17 @@ bool USRPOutput::acquireChannel()
|
|||||||
suspendRxBuddies();
|
suspendRxBuddies();
|
||||||
suspendTxBuddies();
|
suspendTxBuddies();
|
||||||
|
|
||||||
|
if (m_streamId == nullptr)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
uhd::usrp::multi_usrp::sptr usrp = m_deviceShared.m_deviceParams->getDevice();
|
||||||
|
|
||||||
|
// Apply settings before creating stream
|
||||||
|
// However, don't set LPF to <10MHz at this stage, otherwise there is massive TX LO leakage
|
||||||
|
applySettings(m_settings, true, true);
|
||||||
|
usrp->set_tx_bandwidth(56000000, m_deviceShared.m_channel);
|
||||||
|
|
||||||
// set up the stream
|
// set up the stream
|
||||||
std::string cpu_format("sc16");
|
std::string cpu_format("sc16");
|
||||||
std::string wire_format("sc16");
|
std::string wire_format("sc16");
|
||||||
@ -299,12 +309,22 @@ bool USRPOutput::acquireChannel()
|
|||||||
uhd::stream_args_t stream_args(cpu_format, wire_format);
|
uhd::stream_args_t stream_args(cpu_format, wire_format);
|
||||||
stream_args.channels = channel_nums;
|
stream_args.channels = channel_nums;
|
||||||
|
|
||||||
m_streamId = m_deviceShared.m_deviceParams->getDevice()->get_tx_stream(stream_args);
|
m_streamId = usrp->get_tx_stream(stream_args);
|
||||||
|
|
||||||
|
// Match our transmit buffer size to what UHD uses
|
||||||
|
m_bufSamples = m_streamId->get_max_num_samps();
|
||||||
|
|
||||||
|
// Wait for reference and LO to lock
|
||||||
|
DeviceUSRP::waitForLock(usrp, m_settings.m_clockSource, m_deviceShared.m_channel);
|
||||||
|
|
||||||
|
// Now we can set desired bandwidth
|
||||||
|
usrp->set_tx_bandwidth(m_settings.m_lpfBW, m_deviceShared.m_channel);
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
qDebug() << "USRPOutput::acquireChannel: exception: " << e.what();
|
qDebug() << "USRPOutput::acquireChannel: exception: " << e.what();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resumeTxBuddies();
|
resumeTxBuddies();
|
||||||
resumeRxBuddies();
|
resumeRxBuddies();
|
||||||
@ -319,7 +339,7 @@ void USRPOutput::releaseChannel()
|
|||||||
suspendRxBuddies();
|
suspendRxBuddies();
|
||||||
suspendTxBuddies();
|
suspendTxBuddies();
|
||||||
|
|
||||||
// destroy the stream - FIXME: Better way to do this?
|
// destroy the stream
|
||||||
m_streamId = nullptr;
|
m_streamId = nullptr;
|
||||||
|
|
||||||
resumeTxBuddies();
|
resumeTxBuddies();
|
||||||
@ -330,7 +350,7 @@ void USRPOutput::releaseChannel()
|
|||||||
|
|
||||||
void USRPOutput::init()
|
void USRPOutput::init()
|
||||||
{
|
{
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USRPOutput::start()
|
bool USRPOutput::start()
|
||||||
@ -346,13 +366,9 @@ bool USRPOutput::start()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start / stop streaming is done in the thread.
|
m_usrpOutputThread = new USRPOutputThread(m_streamId, m_bufSamples, &m_sampleSourceFifo);
|
||||||
|
|
||||||
m_usrpOutputThread = new USRPOutputThread(m_streamId, &m_sampleSourceFifo);
|
|
||||||
qDebug("USRPOutput::start: thread created");
|
qDebug("USRPOutput::start: thread created");
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
|
||||||
|
|
||||||
m_usrpOutputThread->setLog2Interpolation(m_settings.m_log2SoftInterp);
|
m_usrpOutputThread->setLog2Interpolation(m_settings.m_log2SoftInterp);
|
||||||
m_usrpOutputThread->startWork();
|
m_usrpOutputThread->startWork();
|
||||||
|
|
||||||
@ -483,7 +499,7 @@ bool USRPOutput::handleMessage(const Message& message)
|
|||||||
MsgConfigureUSRP& conf = (MsgConfigureUSRP&) message;
|
MsgConfigureUSRP& conf = (MsgConfigureUSRP&) message;
|
||||||
qDebug() << "USRPOutput::handleMessage: MsgConfigureUSRP";
|
qDebug() << "USRPOutput::handleMessage: MsgConfigureUSRP";
|
||||||
|
|
||||||
if (!applySettings(conf.getSettings(), conf.getForce()))
|
if (!applySettings(conf.getSettings(), false, conf.getForce()))
|
||||||
{
|
{
|
||||||
qDebug("USRPOutput::handleMessage config error");
|
qDebug("USRPOutput::handleMessage config error");
|
||||||
}
|
}
|
||||||
@ -517,30 +533,31 @@ bool USRPOutput::handleMessage(const Message& message)
|
|||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange& report = (DeviceUSRPShared::MsgReportBuddyChange&) message;
|
DeviceUSRPShared::MsgReportBuddyChange& report = (DeviceUSRPShared::MsgReportBuddyChange&) message;
|
||||||
|
|
||||||
if (report.getRxElseTx() && m_running)
|
if (!report.getRxElseTx())
|
||||||
{
|
|
||||||
double host_Hz;
|
|
||||||
|
|
||||||
host_Hz = m_deviceShared.m_deviceParams->getDevice()->get_tx_rate(m_deviceShared.m_channel);
|
|
||||||
m_settings.m_devSampleRate = roundf(host_Hz);
|
|
||||||
|
|
||||||
qDebug() << "USRPOutput::handleMessage: MsgReportBuddyChange:"
|
|
||||||
<< " m_devSampleRate: " << m_settings.m_devSampleRate;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
// Tx buddy changed settings, we need to copy
|
||||||
m_settings.m_devSampleRate = report.getDevSampleRate();
|
m_settings.m_devSampleRate = report.getDevSampleRate();
|
||||||
m_settings.m_centerFrequency = report.getCenterFrequency();
|
m_settings.m_centerFrequency = report.getCenterFrequency();
|
||||||
|
m_settings.m_loOffset = report.getLOOffset();
|
||||||
}
|
}
|
||||||
|
// Master clock rate is common between all buddies
|
||||||
|
int masterClockRate = report.getMasterClockRate();
|
||||||
|
if (masterClockRate > 0)
|
||||||
|
m_settings.m_masterClockRate = masterClockRate;
|
||||||
|
qDebug() << "USRPOutput::handleMessage MsgReportBuddyChange";
|
||||||
|
qDebug() << "m_masterClockRate " << m_settings.m_masterClockRate;
|
||||||
|
|
||||||
DSPSignalNotification *notif = new DSPSignalNotification(
|
DSPSignalNotification *notif = new DSPSignalNotification(
|
||||||
m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftInterp),
|
m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftInterp),
|
||||||
m_settings.m_centerFrequency);
|
m_settings.m_centerFrequency);
|
||||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||||
|
|
||||||
|
if (getMessageQueueToGUI())
|
||||||
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange *reportToGUI = DeviceUSRPShared::MsgReportBuddyChange::create(
|
DeviceUSRPShared::MsgReportBuddyChange *reportToGUI = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
m_settings.m_devSampleRate, m_settings.m_centerFrequency, false);
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, false);
|
||||||
getMessageQueueToGUI()->push(reportToGUI);
|
getMessageQueueToGUI()->push(reportToGUI);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -563,7 +580,7 @@ bool USRPOutput::handleMessage(const Message& message)
|
|||||||
{
|
{
|
||||||
if (m_deviceAPI->getSamplingDeviceGUIMessageQueue())
|
if (m_deviceAPI->getSamplingDeviceGUIMessageQueue())
|
||||||
{
|
{
|
||||||
if (m_streamId != nullptr)
|
if ((m_streamId != nullptr) && m_channelAcquired)
|
||||||
{
|
{
|
||||||
bool active;
|
bool active;
|
||||||
quint32 underflows;
|
quint32 underflows;
|
||||||
@ -593,13 +610,14 @@ bool USRPOutput::handleMessage(const Message& message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool preGetStream, bool force)
|
||||||
{
|
{
|
||||||
bool forwardChangeOwnDSP = false;
|
bool forwardChangeOwnDSP = false;
|
||||||
bool forwardChangeTxDSP = false;
|
bool forwardChangeTxDSP = false;
|
||||||
bool forwardChangeAllDSP = false;
|
bool forwardChangeAllDSP = false;
|
||||||
bool forwardClockSource = false;
|
bool forwardClockSource = false;
|
||||||
bool ownThreadWasRunning = false;
|
bool ownThreadWasRunning = false;
|
||||||
|
bool checkRates = false;
|
||||||
QList<QString> reverseAPIKeys;
|
QList<QString> reverseAPIKeys;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -615,7 +633,7 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("clockSource");
|
reverseAPIKeys.append("clockSource");
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice())
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -645,17 +663,16 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
reverseAPIKeys.append("devSampleRate");
|
reverseAPIKeys.append("devSampleRate");
|
||||||
forwardChangeAllDSP = true;
|
forwardChangeAllDSP = true;
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
{
|
{
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_tx_rate(settings.m_devSampleRate, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_tx_rate(settings.m_devSampleRate, m_deviceShared.m_channel);
|
||||||
double actualSampleRate = m_deviceShared.m_deviceParams->getDevice()->get_tx_rate(m_deviceShared.m_channel);
|
qDebug("USRPOutput::applySettings: set sample rate set to %d", settings.m_devSampleRate);
|
||||||
qDebug("USRPOutput::applySettings: set sample rate set to %d - actual rate %f", settings.m_devSampleRate,
|
checkRates = true;
|
||||||
actualSampleRate);
|
|
||||||
m_deviceShared.m_deviceParams->m_sampleRate = m_settings.m_devSampleRate;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_centerFrequency != settings.m_centerFrequency)
|
if ((m_settings.m_centerFrequency != settings.m_centerFrequency)
|
||||||
|
|| (m_settings.m_loOffset != settings.m_loOffset)
|
||||||
|| (m_settings.m_transverterMode != settings.m_transverterMode)
|
|| (m_settings.m_transverterMode != settings.m_transverterMode)
|
||||||
|| (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)
|
|| (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)
|
||||||
|| force)
|
|| force)
|
||||||
@ -665,12 +682,20 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
reverseAPIKeys.append("transverterDeltaFrequency");
|
reverseAPIKeys.append("transverterDeltaFrequency");
|
||||||
forwardChangeTxDSP = true;
|
forwardChangeTxDSP = true;
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
|
{
|
||||||
|
if (settings.m_loOffset != 0)
|
||||||
|
{
|
||||||
|
uhd::tune_request_t tune_request(deviceCenterFrequency, settings.m_loOffset);
|
||||||
|
m_deviceShared.m_deviceParams->getDevice()->set_tx_freq(tune_request, m_deviceShared.m_channel);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
uhd::tune_request_t tune_request(deviceCenterFrequency);
|
uhd::tune_request_t tune_request(deviceCenterFrequency);
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_tx_freq(tune_request, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_tx_freq(tune_request, m_deviceShared.m_channel);
|
||||||
|
}
|
||||||
m_deviceShared.m_centerFrequency = deviceCenterFrequency; // for buddies
|
m_deviceShared.m_centerFrequency = deviceCenterFrequency; // for buddies
|
||||||
qDebug("USRPOutput::applySettings: frequency set to %lld", deviceCenterFrequency);
|
qDebug("USRPOutput::applySettings: frequency set to %lld with LO offset %d", deviceCenterFrequency, settings.m_loOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,7 +721,7 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("gain");
|
reverseAPIKeys.append("gain");
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
{
|
{
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_tx_gain(settings.m_gain, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_tx_gain(settings.m_gain, m_deviceShared.m_channel);
|
||||||
qDebug() << "USRPOutput::applySettings: Gain set to " << settings.m_gain;
|
qDebug() << "USRPOutput::applySettings: Gain set to " << settings.m_gain;
|
||||||
@ -707,6 +732,7 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("lpfBW");
|
reverseAPIKeys.append("lpfBW");
|
||||||
|
|
||||||
|
// Don't set bandwidth before get_tx_stream (See above)
|
||||||
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
||||||
{
|
{
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_tx_bandwidth(settings.m_lpfBW, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_tx_bandwidth(settings.m_lpfBW, m_deviceShared.m_channel);
|
||||||
@ -731,7 +757,7 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("antennaPath");
|
reverseAPIKeys.append("antennaPath");
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
{
|
{
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_tx_antenna(settings.m_antennaPath.toStdString(), m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_tx_antenna(settings.m_antennaPath.toStdString(), m_deviceShared.m_channel);
|
||||||
qDebug("USRPOutput::applySettings: set antenna path to %s on channel %d", qPrintable(settings.m_antennaPath), m_deviceShared.m_channel);
|
qDebug("USRPOutput::applySettings: set antenna path to %s on channel %d", qPrintable(settings.m_antennaPath), m_deviceShared.m_channel);
|
||||||
@ -749,6 +775,17 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
|
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
|
|
||||||
|
if (checkRates)
|
||||||
|
{
|
||||||
|
// Check if requested rate could actually be met and what master clock rate we ended up with
|
||||||
|
double actualSampleRate = m_deviceShared.m_deviceParams->getDevice()->get_tx_rate(m_deviceShared.m_channel);
|
||||||
|
qDebug("USRPOutput::applySettings: actual sample rate %f", actualSampleRate);
|
||||||
|
double masterClockRate = m_deviceShared.m_deviceParams->getDevice()->get_master_clock_rate();
|
||||||
|
qDebug("USRPOutput::applySettings: master_clock_rate %f", masterClockRate);
|
||||||
|
m_settings.m_devSampleRate = actualSampleRate;
|
||||||
|
m_settings.m_masterClockRate = masterClockRate;
|
||||||
|
}
|
||||||
|
|
||||||
// forward changes to buddies or oneself
|
// forward changes to buddies or oneself
|
||||||
|
|
||||||
if (forwardChangeAllDSP)
|
if (forwardChangeAllDSP)
|
||||||
@ -768,7 +805,7 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
for (; itSink != sinkBuddies.end(); ++itSink)
|
for (; itSink != sinkBuddies.end(); ++itSink)
|
||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
m_settings.m_devSampleRate, m_settings.m_centerFrequency, false);
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, false);
|
||||||
(*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
|
(*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,9 +816,17 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
for (; itSource != sourceBuddies.end(); ++itSource)
|
for (; itSource != sourceBuddies.end(); ++itSource)
|
||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
m_settings.m_devSampleRate, m_settings.m_centerFrequency, false);
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, false);
|
||||||
(*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
|
(*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send to GUI so it can see master clock rate and if actual rate differs
|
||||||
|
if (m_deviceAPI->getSamplingDeviceGUIMessageQueue())
|
||||||
|
{
|
||||||
|
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, false);
|
||||||
|
m_deviceAPI->getSamplingDeviceGUIMessageQueue()->push(report);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (forwardChangeTxDSP)
|
else if (forwardChangeTxDSP)
|
||||||
{
|
{
|
||||||
@ -800,7 +845,7 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
for (; itSink != sinkBuddies.end(); ++itSink)
|
for (; itSink != sinkBuddies.end(); ++itSink)
|
||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
m_settings.m_devSampleRate, m_settings.m_centerFrequency, false);
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, false);
|
||||||
(*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
|
(*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -829,6 +874,14 @@ bool USRPOutput::applySettings(const USRPOutputSettings& settings, bool force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send to GUI in case requested clock isn't detected
|
||||||
|
if (m_deviceAPI->getSamplingDeviceGUIMessageQueue())
|
||||||
|
{
|
||||||
|
DeviceUSRPShared::MsgReportClockSourceChange *report = DeviceUSRPShared::MsgReportClockSourceChange::create(
|
||||||
|
m_settings.m_clockSource);
|
||||||
|
m_deviceAPI->getSamplingDeviceGUIMessageQueue()->push(report);
|
||||||
|
}
|
||||||
|
|
||||||
// send to source buddies
|
// send to source buddies
|
||||||
const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
|
const std::vector<DeviceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
|
||||||
std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
|
std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
|
||||||
@ -924,6 +977,9 @@ void USRPOutput::webapiUpdateDeviceSettings(
|
|||||||
if (deviceSettingsKeys.contains("devSampleRate")) {
|
if (deviceSettingsKeys.contains("devSampleRate")) {
|
||||||
settings.m_devSampleRate = response.getUsrpOutputSettings()->getDevSampleRate();
|
settings.m_devSampleRate = response.getUsrpOutputSettings()->getDevSampleRate();
|
||||||
}
|
}
|
||||||
|
if (deviceSettingsKeys.contains("loOffset")) {
|
||||||
|
settings.m_loOffset = response.getUsrpOutputSettings()->getLoOffset();
|
||||||
|
}
|
||||||
if (deviceSettingsKeys.contains("clockSource")) {
|
if (deviceSettingsKeys.contains("clockSource")) {
|
||||||
settings.m_clockSource = *response.getUsrpOutputSettings()->getClockSource();
|
settings.m_clockSource = *response.getUsrpOutputSettings()->getClockSource();
|
||||||
}
|
}
|
||||||
@ -971,6 +1027,7 @@ void USRPOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& resp
|
|||||||
response.getUsrpOutputSettings()->setAntennaPath(new QString(settings.m_antennaPath));
|
response.getUsrpOutputSettings()->setAntennaPath(new QString(settings.m_antennaPath));
|
||||||
response.getUsrpOutputSettings()->setCenterFrequency(settings.m_centerFrequency);
|
response.getUsrpOutputSettings()->setCenterFrequency(settings.m_centerFrequency);
|
||||||
response.getUsrpOutputSettings()->setDevSampleRate(settings.m_devSampleRate);
|
response.getUsrpOutputSettings()->setDevSampleRate(settings.m_devSampleRate);
|
||||||
|
response.getUsrpOutputSettings()->setLoOffset(settings.m_loOffset);
|
||||||
response.getUsrpOutputSettings()->setClockSource(new QString(settings.m_clockSource));
|
response.getUsrpOutputSettings()->setClockSource(new QString(settings.m_clockSource));
|
||||||
response.getUsrpOutputSettings()->setGain(settings.m_gain);
|
response.getUsrpOutputSettings()->setGain(settings.m_gain);
|
||||||
response.getUsrpOutputSettings()->setLog2SoftInterp(settings.m_log2SoftInterp);
|
response.getUsrpOutputSettings()->setLog2SoftInterp(settings.m_log2SoftInterp);
|
||||||
@ -1024,7 +1081,7 @@ void USRPOutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response
|
|||||||
quint32 underflows = 0;
|
quint32 underflows = 0;
|
||||||
quint32 droppedPackets = 0;
|
quint32 droppedPackets = 0;
|
||||||
|
|
||||||
if (m_streamId != nullptr)
|
if ((m_streamId != nullptr) && (m_usrpOutputThread != nullptr) && m_channelAcquired)
|
||||||
{
|
{
|
||||||
m_usrpOutputThread->getStreamStatus(active, underflows, droppedPackets);
|
m_usrpOutputThread->getStreamStatus(active, underflows, droppedPackets);
|
||||||
success = true;
|
success = true;
|
||||||
@ -1056,6 +1113,9 @@ void USRPOutput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, c
|
|||||||
if (deviceSettingsKeys.contains("devSampleRate") || force) {
|
if (deviceSettingsKeys.contains("devSampleRate") || force) {
|
||||||
swgUsrpOutputSettings->setDevSampleRate(settings.m_devSampleRate);
|
swgUsrpOutputSettings->setDevSampleRate(settings.m_devSampleRate);
|
||||||
}
|
}
|
||||||
|
if (deviceSettingsKeys.contains("loOffset") || force) {
|
||||||
|
swgUsrpOutputSettings->setLoOffset(settings.m_loOffset);
|
||||||
|
}
|
||||||
if (deviceSettingsKeys.contains("clockSource") || force) {
|
if (deviceSettingsKeys.contains("clockSource") || force) {
|
||||||
swgUsrpOutputSettings->setClockSource(new QString(settings.m_clockSource));
|
swgUsrpOutputSettings->setClockSource(new QString(settings.m_clockSource));
|
||||||
}
|
}
|
||||||
|
@ -226,6 +226,7 @@ private:
|
|||||||
DeviceUSRPShared m_deviceShared;
|
DeviceUSRPShared m_deviceShared;
|
||||||
bool m_channelAcquired;
|
bool m_channelAcquired;
|
||||||
uhd::tx_streamer::sptr m_streamId;
|
uhd::tx_streamer::sptr m_streamId;
|
||||||
|
size_t m_bufSamples;
|
||||||
QNetworkAccessManager *m_networkManager;
|
QNetworkAccessManager *m_networkManager;
|
||||||
QNetworkRequest m_networkRequest;
|
QNetworkRequest m_networkRequest;
|
||||||
|
|
||||||
@ -237,7 +238,7 @@ private:
|
|||||||
void resumeRxBuddies();
|
void resumeRxBuddies();
|
||||||
void suspendTxBuddies();
|
void suspendTxBuddies();
|
||||||
void resumeTxBuddies();
|
void resumeTxBuddies();
|
||||||
bool applySettings(const USRPOutputSettings& settings, bool force = false);
|
bool applySettings(const USRPOutputSettings& settings, bool preGetStream, bool force = false);
|
||||||
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
||||||
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const USRPOutputSettings& settings, bool force);
|
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const USRPOutputSettings& settings, bool force);
|
||||||
void webapiReverseSendStartStop(bool start);
|
void webapiReverseSendStartStop(bool start);
|
||||||
|
@ -57,6 +57,9 @@ USRPOutputGUI::USRPOutputGUI(DeviceUISet *deviceUISet, QWidget* parent) :
|
|||||||
ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
|
ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
|
||||||
ui->sampleRate->setValueRange(8, (uint32_t) minF, (uint32_t) maxF);
|
ui->sampleRate->setValueRange(8, (uint32_t) minF, (uint32_t) maxF);
|
||||||
|
|
||||||
|
ui->loOffset->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
|
||||||
|
ui->loOffset->setValueRange(false, 5, (int32_t)-maxF/2/1000, (int32_t)maxF/2/1000); // LO offset shouldn't be greater than half the sample rate
|
||||||
|
|
||||||
m_usrpOutput->getLPRange(minF, maxF);
|
m_usrpOutput->getLPRange(minF, maxF);
|
||||||
ui->lpf->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
|
ui->lpf->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
|
||||||
ui->lpf->setValueRange(5, (minF/1000)+1, maxF/1000);
|
ui->lpf->setValueRange(5, (minF/1000)+1, maxF/1000);
|
||||||
@ -177,10 +180,12 @@ bool USRPOutputGUI::handleMessage(const Message& message)
|
|||||||
else if (DeviceUSRPShared::MsgReportBuddyChange::match(message))
|
else if (DeviceUSRPShared::MsgReportBuddyChange::match(message))
|
||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange& report = (DeviceUSRPShared::MsgReportBuddyChange&) message;
|
DeviceUSRPShared::MsgReportBuddyChange& report = (DeviceUSRPShared::MsgReportBuddyChange&) message;
|
||||||
m_settings.m_devSampleRate = report.getDevSampleRate();
|
m_settings.m_masterClockRate = report.getMasterClockRate();
|
||||||
|
|
||||||
if (!report.getRxElseTx()) {
|
if (!report.getRxElseTx()) {
|
||||||
|
m_settings.m_devSampleRate = report.getDevSampleRate();
|
||||||
m_settings.m_centerFrequency = report.getCenterFrequency();
|
m_settings.m_centerFrequency = report.getCenterFrequency();
|
||||||
|
m_settings.m_loOffset = report.getLOOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
@ -287,12 +292,22 @@ void USRPOutputGUI::updateSampleRateAndFrequency()
|
|||||||
void USRPOutputGUI::updateSampleRate()
|
void USRPOutputGUI::updateSampleRate()
|
||||||
{
|
{
|
||||||
uint32_t sr = m_settings.m_devSampleRate;
|
uint32_t sr = m_settings.m_devSampleRate;
|
||||||
|
int cr = m_settings.m_masterClockRate;
|
||||||
|
|
||||||
if (sr < 100000000) {
|
if (sr < 100000000) {
|
||||||
ui->sampleRateLabel->setText(tr("%1k").arg(QString::number(sr / 1000.0f, 'g', 5)));
|
ui->sampleRateLabel->setText(tr("%1k").arg(QString::number(sr / 1000.0f, 'g', 5)));
|
||||||
} else {
|
} else {
|
||||||
ui->sampleRateLabel->setText(tr("%1M").arg(QString::number(sr / 1000000.0f, 'g', 5)));
|
ui->sampleRateLabel->setText(tr("%1M").arg(QString::number(sr / 1000000.0f, 'g', 5)));
|
||||||
}
|
}
|
||||||
|
if (cr < 0) {
|
||||||
|
ui->masterClockRateLabel->setText("-");
|
||||||
|
} else if (cr < 100000000) {
|
||||||
|
ui->masterClockRateLabel->setText(tr("%1k").arg(QString::number(cr / 1000.0f, 'g', 5)));
|
||||||
|
} else {
|
||||||
|
ui->masterClockRateLabel->setText(tr("%1M").arg(QString::number(cr / 1000000.0f, 'g', 5)));
|
||||||
|
}
|
||||||
|
// LO offset shouldn't be greater than half the sample rate
|
||||||
|
ui->loOffset->setValueRange(false, 5, -(int32_t)sr/2/1000, (int32_t)sr/2/1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void USRPOutputGUI::displaySampleRate()
|
void USRPOutputGUI::displaySampleRate()
|
||||||
@ -343,6 +358,7 @@ void USRPOutputGUI::displaySettings()
|
|||||||
updateSampleRate();
|
updateSampleRate();
|
||||||
|
|
||||||
ui->lpf->setValue(m_settings.m_lpfBW / 1000);
|
ui->lpf->setValue(m_settings.m_lpfBW / 1000);
|
||||||
|
ui->loOffset->setValue(m_settings.m_loOffset / 1000);
|
||||||
|
|
||||||
ui->gain->setValue(m_settings.m_gain);
|
ui->gain->setValue(m_settings.m_gain);
|
||||||
ui->gainText->setText(tr("%1dB").arg(m_settings.m_gain));
|
ui->gainText->setText(tr("%1dB").arg(m_settings.m_gain));
|
||||||
@ -497,6 +513,12 @@ void USRPOutputGUI::on_lpf_changed(quint64 value)
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void USRPOutputGUI::on_loOffset_changed(qint64 value)
|
||||||
|
{
|
||||||
|
m_settings.m_loOffset = value * 1000;
|
||||||
|
sendSettings();
|
||||||
|
}
|
||||||
|
|
||||||
void USRPOutputGUI::on_gain_valueChanged(int value)
|
void USRPOutputGUI::on_gain_valueChanged(int value)
|
||||||
{
|
{
|
||||||
m_settings.m_gain = value;
|
m_settings.m_gain = value;
|
||||||
|
@ -88,6 +88,7 @@ private slots:
|
|||||||
void on_sampleRate_changed(quint64 value);
|
void on_sampleRate_changed(quint64 value);
|
||||||
void on_swInterp_currentIndexChanged(int index);
|
void on_swInterp_currentIndexChanged(int index);
|
||||||
void on_lpf_changed(quint64 value);
|
void on_lpf_changed(quint64 value);
|
||||||
|
void on_loOffset_changed(qint64 value);
|
||||||
void on_gain_valueChanged(int value);
|
void on_gain_valueChanged(int value);
|
||||||
void on_antenna_currentIndexChanged(int index);
|
void on_antenna_currentIndexChanged(int index);
|
||||||
void on_clockSource_currentIndexChanged(int index);
|
void on_clockSource_currentIndexChanged(int index);
|
||||||
|
@ -75,6 +75,16 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="freqLeftBotLayout">
|
<layout class="QHBoxLayout" name="freqLeftBotLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="masterClockRateLabel">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Master clock rate (sample rate between FPGA and RFIC) (k or MS/s)</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>00000k</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="sampleRateLabel">
|
<widget class="QLabel" name="sampleRateLabel">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@ -220,7 +230,7 @@
|
|||||||
<widget class="QComboBox" name="antenna">
|
<widget class="QComboBox" name="antenna">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>60</width>
|
<width>70</width>
|
||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
@ -562,6 +572,55 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="loOffsetLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>LO</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="ValueDialZ" name="loOffset" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Liberation Mono</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>PointingHandCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>LO frequency offset. This should not be greater than half the sample rate.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="loOffsetUnits">
|
||||||
|
<property name="text">
|
||||||
|
<string>kHz</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -684,6 +743,12 @@
|
|||||||
<header>gui/valuedial.h</header>
|
<header>gui/valuedial.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>ValueDialZ</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>gui/valuedialz.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>TransverterButton</class>
|
<class>TransverterButton</class>
|
||||||
<extends>QPushButton</extends>
|
<extends>QPushButton</extends>
|
||||||
|
@ -27,10 +27,12 @@ USRPOutputSettings::USRPOutputSettings()
|
|||||||
|
|
||||||
void USRPOutputSettings::resetToDefaults()
|
void USRPOutputSettings::resetToDefaults()
|
||||||
{
|
{
|
||||||
|
m_masterClockRate = -1; // Calculated by UHD
|
||||||
m_centerFrequency = 435000*1000;
|
m_centerFrequency = 435000*1000;
|
||||||
m_devSampleRate = 3000000;
|
m_devSampleRate = 3000000;
|
||||||
|
m_loOffset = 0;
|
||||||
m_log2SoftInterp = 0;
|
m_log2SoftInterp = 0;
|
||||||
m_lpfBW = 5.5e6f;
|
m_lpfBW = 10e6f;
|
||||||
m_gain = 50;
|
m_gain = 50;
|
||||||
m_antennaPath = "TX/RX";
|
m_antennaPath = "TX/RX";
|
||||||
m_clockSource = "internal";
|
m_clockSource = "internal";
|
||||||
@ -58,6 +60,7 @@ QByteArray USRPOutputSettings::serialize() const
|
|||||||
s.writeString(10, m_reverseAPIAddress);
|
s.writeString(10, m_reverseAPIAddress);
|
||||||
s.writeU32(11, m_reverseAPIPort);
|
s.writeU32(11, m_reverseAPIPort);
|
||||||
s.writeU32(12, m_reverseAPIDeviceIndex);
|
s.writeU32(12, m_reverseAPIDeviceIndex);
|
||||||
|
s.writeS32(13, m_loOffset);
|
||||||
|
|
||||||
return s.final();
|
return s.final();
|
||||||
}
|
}
|
||||||
@ -97,6 +100,7 @@ bool USRPOutputSettings::deserialize(const QByteArray& data)
|
|||||||
|
|
||||||
d.readU32(12, &uintval, 0);
|
d.readU32(12, &uintval, 0);
|
||||||
m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval;
|
m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval;
|
||||||
|
d.readS32(13, &m_loOffset, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,11 @@
|
|||||||
*/
|
*/
|
||||||
struct USRPOutputSettings
|
struct USRPOutputSettings
|
||||||
{
|
{
|
||||||
|
int m_masterClockRate;
|
||||||
// global settings to be saved
|
// global settings to be saved
|
||||||
uint64_t m_centerFrequency;
|
uint64_t m_centerFrequency;
|
||||||
int m_devSampleRate;
|
int m_devSampleRate;
|
||||||
|
int m_loOffset;
|
||||||
// channel settings
|
// channel settings
|
||||||
uint32_t m_log2SoftInterp;
|
uint32_t m_log2SoftInterp;
|
||||||
float m_lpfBW; //!< Analog lowpass filter bandwidth (Hz)
|
float m_lpfBW; //!< Analog lowpass filter bandwidth (Hz)
|
||||||
|
@ -26,19 +26,23 @@
|
|||||||
#include "usrpoutputthread.h"
|
#include "usrpoutputthread.h"
|
||||||
#include "usrpoutputsettings.h"
|
#include "usrpoutputsettings.h"
|
||||||
|
|
||||||
USRPOutputThread::USRPOutputThread(uhd::tx_streamer::sptr stream, SampleSourceFifo* sampleFifo, QObject* parent) :
|
USRPOutputThread::USRPOutputThread(uhd::tx_streamer::sptr stream, size_t bufSamples, SampleSourceFifo* sampleFifo, QObject* parent) :
|
||||||
QThread(parent),
|
QThread(parent),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_stream(stream),
|
m_stream(stream),
|
||||||
|
m_bufSamples(bufSamples),
|
||||||
m_sampleFifo(sampleFifo),
|
m_sampleFifo(sampleFifo),
|
||||||
m_log2Interp(0)
|
m_log2Interp(0)
|
||||||
{
|
{
|
||||||
std::fill(m_buf, m_buf + 2*DeviceUSRP::blockSize, 0);
|
// *2 as samples are I+Q
|
||||||
|
m_buf = new qint16[2*bufSamples];
|
||||||
|
std::fill(m_buf, m_buf + 2*bufSamples, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
USRPOutputThread::~USRPOutputThread()
|
USRPOutputThread::~USRPOutputThread()
|
||||||
{
|
{
|
||||||
stopWork();
|
stopWork();
|
||||||
|
delete m_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void USRPOutputThread::startWork()
|
void USRPOutputThread::startWork()
|
||||||
@ -66,8 +70,15 @@ void USRPOutputThread::stopWork()
|
|||||||
m_running = false;
|
m_running = false;
|
||||||
wait();
|
wait();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
// Get message indicating underflow, so it doesn't appear if we restart
|
// Get message indicating underflow, so it doesn't appear if we restart
|
||||||
m_stream->recv_async_msg(md);
|
m_stream->recv_async_msg(md);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
qDebug() << "USRPOutputThread::stopWork: exception: " << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
qDebug("USRPOutputThread::stopWork: stream stopped");
|
qDebug("USRPOutputThread::stopWork: stream stopped");
|
||||||
}
|
}
|
||||||
@ -90,15 +101,15 @@ void USRPOutputThread::run()
|
|||||||
|
|
||||||
while (m_running)
|
while (m_running)
|
||||||
{
|
{
|
||||||
callback(m_buf, DeviceUSRP::blockSize);
|
callback(m_buf, m_bufSamples);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const size_t samples_sent = m_stream->send(m_buf, DeviceUSRP::blockSize, md);
|
const size_t samples_sent = m_stream->send(m_buf, m_bufSamples, md);
|
||||||
m_packets++;
|
m_packets++;
|
||||||
if (samples_sent != DeviceUSRP::blockSize)
|
if (samples_sent != m_bufSamples)
|
||||||
{
|
{
|
||||||
qDebug("USRPOutputThread::run written %ld/%d samples", samples_sent, DeviceUSRP::blockSize);
|
qDebug("USRPOutputThread::run written %ld/%ld samples", samples_sent, m_bufSamples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
@ -37,7 +37,7 @@ class USRPOutputThread : public QThread, public DeviceUSRPShared::ThreadInterfac
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
USRPOutputThread(uhd::tx_streamer::sptr stream, SampleSourceFifo* sampleFifo, QObject* parent = 0);
|
USRPOutputThread(uhd::tx_streamer::sptr stream, size_t bufSamples, SampleSourceFifo* sampleFifo, QObject* parent = 0);
|
||||||
~USRPOutputThread();
|
~USRPOutputThread();
|
||||||
|
|
||||||
virtual void startWork();
|
virtual void startWork();
|
||||||
@ -57,7 +57,8 @@ private:
|
|||||||
quint32 m_droppedPackets;
|
quint32 m_droppedPackets;
|
||||||
|
|
||||||
uhd::tx_streamer::sptr m_stream;
|
uhd::tx_streamer::sptr m_stream;
|
||||||
qint16 m_buf[2*DeviceUSRP::blockSize]; //must hold I+Q values of each sample hence 2xcomplex size
|
qint16 *m_buf;
|
||||||
|
size_t m_bufSamples;
|
||||||
SampleSourceFifo* m_sampleFifo;
|
SampleSourceFifo* m_sampleFifo;
|
||||||
|
|
||||||
unsigned int m_log2Interp; // soft decimation
|
unsigned int m_log2Interp; // soft decimation
|
||||||
|
@ -118,6 +118,10 @@ Check this button to enable IQ imbalance correction.
|
|||||||
|
|
||||||
This is the Rx hardware IF filter bandwidth in kHz for the given channel. Use the wheels to adjust the value. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2.
|
This is the Rx hardware IF filter bandwidth in kHz for the given channel. Use the wheels to adjust the value. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2.
|
||||||
|
|
||||||
|
<h3>Rx LO offset</h3>
|
||||||
|
|
||||||
|
This adjusts the Rx local oscillator (LO) frequency from the centre frequency by the given amount in kHz, and the NCOs are used to digitally shift the signal to compensate. The shift should be less than half of the sample rate.
|
||||||
|
|
||||||
<h3>15: Stream status indicator</h3>
|
<h3>15: Stream status indicator</h3>
|
||||||
|
|
||||||
This label turns green when data is being received from the device.
|
This label turns green when data is being received from the device.
|
||||||
@ -128,3 +132,10 @@ This label turns green when data is being received from the device.
|
|||||||
- **T**: turns red if stream experiences timeouts
|
- **T**: turns red if stream experiences timeouts
|
||||||
|
|
||||||
The stream warning indicators are reset when the acqusition is started.
|
The stream warning indicators are reset when the acqusition is started.
|
||||||
|
|
||||||
|
<h2>Dependendices</h2>
|
||||||
|
|
||||||
|
On Ubuntu 20, the libuhd-dev package should be installed. The FPGA images then need to be downloaded with:
|
||||||
|
|
||||||
|
sudo /usr/lib/uhd/utils/uhd_images_downloader.py
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ USRPInput::USRPInput(DeviceAPI *deviceAPI) :
|
|||||||
m_deviceAPI(deviceAPI),
|
m_deviceAPI(deviceAPI),
|
||||||
m_settings(),
|
m_settings(),
|
||||||
m_usrpInputThread(nullptr),
|
m_usrpInputThread(nullptr),
|
||||||
|
m_bufSamples(0),
|
||||||
m_deviceDescription("USRPInput"),
|
m_deviceDescription("USRPInput"),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_channelAcquired(false)
|
m_channelAcquired(false)
|
||||||
@ -91,7 +92,9 @@ void USRPInput::destroy()
|
|||||||
|
|
||||||
bool USRPInput::openDevice()
|
bool USRPInput::openDevice()
|
||||||
{
|
{
|
||||||
if (!m_sampleFifo.setSize(96000 * 4))
|
// B210 supports up to 50MSa/s, so a fairly large FIFO is probably a good idea
|
||||||
|
// Should it be bigger still?
|
||||||
|
if (!m_sampleFifo.setSize(2000000))
|
||||||
{
|
{
|
||||||
qCritical("USRPInput::openDevice: could not allocate SampleFifo");
|
qCritical("USRPInput::openDevice: could not allocate SampleFifo");
|
||||||
return false;
|
return false;
|
||||||
@ -199,7 +202,7 @@ bool USRPInput::openDevice()
|
|||||||
m_deviceShared.m_deviceParams = new DeviceUSRPParams();
|
m_deviceShared.m_deviceParams = new DeviceUSRPParams();
|
||||||
char serial[256];
|
char serial[256];
|
||||||
strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
|
strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial()));
|
||||||
m_deviceShared.m_deviceParams->open(serial);
|
m_deviceShared.m_deviceParams->open(serial, false);
|
||||||
m_deviceShared.m_channel = requestedChannel; // acknowledge the requested channel
|
m_deviceShared.m_channel = requestedChannel; // acknowledge the requested channel
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,8 +316,17 @@ bool USRPInput::acquireChannel()
|
|||||||
suspendRxBuddies();
|
suspendRxBuddies();
|
||||||
suspendTxBuddies();
|
suspendTxBuddies();
|
||||||
|
|
||||||
|
if (m_streamId == nullptr)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
uhd::usrp::multi_usrp::sptr usrp = m_deviceShared.m_deviceParams->getDevice();
|
||||||
|
|
||||||
|
// Apply settings before creating stream
|
||||||
|
// However, don't set LPF to <10MHz at this stage, otherwise there is massive TX LO leakage
|
||||||
|
applySettings(m_settings, true, true);
|
||||||
|
usrp->set_rx_bandwidth(56000000, m_deviceShared.m_channel);
|
||||||
|
|
||||||
// set up the stream
|
// set up the stream
|
||||||
std::string cpu_format("sc16");
|
std::string cpu_format("sc16");
|
||||||
std::string wire_format("sc16");
|
std::string wire_format("sc16");
|
||||||
@ -325,11 +337,21 @@ bool USRPInput::acquireChannel()
|
|||||||
stream_args.channels = channel_nums;
|
stream_args.channels = channel_nums;
|
||||||
|
|
||||||
m_streamId = m_deviceShared.m_deviceParams->getDevice()->get_rx_stream(stream_args);
|
m_streamId = m_deviceShared.m_deviceParams->getDevice()->get_rx_stream(stream_args);
|
||||||
|
|
||||||
|
// Match our receive buffer size to what UHD uses
|
||||||
|
m_bufSamples = m_streamId->get_max_num_samps();
|
||||||
|
|
||||||
|
// Wait for reference and LO to lock
|
||||||
|
DeviceUSRP::waitForLock(usrp, m_settings.m_clockSource, m_deviceShared.m_channel);
|
||||||
|
|
||||||
|
// Now we can set desired bandwidth
|
||||||
|
usrp->set_rx_bandwidth(m_settings.m_lpfBW, m_deviceShared.m_channel);
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
qDebug() << "USRPInput::acquireChannel: exception: " << e.what();
|
qDebug() << "USRPInput::acquireChannel: exception: " << e.what();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resumeTxBuddies();
|
resumeTxBuddies();
|
||||||
resumeRxBuddies();
|
resumeRxBuddies();
|
||||||
@ -344,7 +366,7 @@ void USRPInput::releaseChannel()
|
|||||||
suspendRxBuddies();
|
suspendRxBuddies();
|
||||||
suspendTxBuddies();
|
suspendTxBuddies();
|
||||||
|
|
||||||
// destroy the stream - FIXME: Better way to do this?
|
// destroy the stream
|
||||||
m_streamId = nullptr;
|
m_streamId = nullptr;
|
||||||
|
|
||||||
resumeTxBuddies();
|
resumeTxBuddies();
|
||||||
@ -357,7 +379,7 @@ void USRPInput::releaseChannel()
|
|||||||
|
|
||||||
void USRPInput::init()
|
void USRPInput::init()
|
||||||
{
|
{
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USRPInput::start()
|
bool USRPInput::start()
|
||||||
@ -375,11 +397,9 @@ bool USRPInput::start()
|
|||||||
|
|
||||||
// start / stop streaming is done in the thread.
|
// start / stop streaming is done in the thread.
|
||||||
|
|
||||||
m_usrpInputThread = new USRPInputThread(m_streamId, &m_sampleFifo);
|
m_usrpInputThread = new USRPInputThread(m_streamId, m_bufSamples, &m_sampleFifo);
|
||||||
qDebug("USRPInput::start: thread created");
|
qDebug("USRPInput::start: thread created");
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
|
||||||
|
|
||||||
m_usrpInputThread->setLog2Decimation(m_settings.m_log2SoftDecim);
|
m_usrpInputThread->setLog2Decimation(m_settings.m_log2SoftDecim);
|
||||||
m_usrpInputThread->startWork();
|
m_usrpInputThread->startWork();
|
||||||
|
|
||||||
@ -515,7 +535,7 @@ bool USRPInput::handleMessage(const Message& message)
|
|||||||
MsgConfigureUSRP& conf = (MsgConfigureUSRP&) message;
|
MsgConfigureUSRP& conf = (MsgConfigureUSRP&) message;
|
||||||
qDebug() << "USRPInput::handleMessage: MsgConfigureUSRP";
|
qDebug() << "USRPInput::handleMessage: MsgConfigureUSRP";
|
||||||
|
|
||||||
if (!applySettings(conf.getSettings(), conf.getForce()))
|
if (!applySettings(conf.getSettings(), false, conf.getForce()))
|
||||||
{
|
{
|
||||||
qDebug("USRPInput::handleMessage config error");
|
qDebug("USRPInput::handleMessage config error");
|
||||||
}
|
}
|
||||||
@ -528,19 +548,17 @@ bool USRPInput::handleMessage(const Message& message)
|
|||||||
|
|
||||||
if (report.getRxElseTx())
|
if (report.getRxElseTx())
|
||||||
{
|
{
|
||||||
|
// Rx buddy changed settings, we need to copy
|
||||||
m_settings.m_devSampleRate = report.getDevSampleRate();
|
m_settings.m_devSampleRate = report.getDevSampleRate();
|
||||||
m_settings.m_centerFrequency = report.getCenterFrequency();
|
m_settings.m_centerFrequency = report.getCenterFrequency();
|
||||||
|
m_settings.m_loOffset = report.getLOOffset();
|
||||||
}
|
}
|
||||||
else if (m_running)
|
// Master clock rate is common between all buddies
|
||||||
{
|
int masterClockRate = report.getMasterClockRate();
|
||||||
double host_Hz;
|
if (masterClockRate > 0)
|
||||||
|
m_settings.m_masterClockRate = masterClockRate;
|
||||||
host_Hz = m_deviceShared.m_deviceParams->getDevice()->get_rx_rate(m_deviceShared.m_channel);
|
qDebug() << "USRPInput::handleMessage MsgReportBuddyChange";
|
||||||
m_settings.m_devSampleRate = roundf(host_Hz);
|
qDebug() << "m_masterClockRate " << m_settings.m_masterClockRate;
|
||||||
|
|
||||||
qDebug() << "USRPInput::handleMessage: MsgReportBuddyChange:"
|
|
||||||
<< " m_devSampleRate: " << m_settings.m_devSampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
DSPSignalNotification *notif = new DSPSignalNotification(
|
DSPSignalNotification *notif = new DSPSignalNotification(
|
||||||
m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftDecim),
|
m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftDecim),
|
||||||
@ -550,7 +568,7 @@ bool USRPInput::handleMessage(const Message& message)
|
|||||||
if (getMessageQueueToGUI())
|
if (getMessageQueueToGUI())
|
||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange *reportToGUI = DeviceUSRPShared::MsgReportBuddyChange::create(
|
DeviceUSRPShared::MsgReportBuddyChange *reportToGUI = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
m_settings.m_devSampleRate, m_settings.m_centerFrequency, true);
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, true);
|
||||||
getMessageQueueToGUI()->push(reportToGUI);
|
getMessageQueueToGUI()->push(reportToGUI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,7 +645,7 @@ bool USRPInput::handleMessage(const Message& message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
bool USRPInput::applySettings(const USRPInputSettings& settings, bool preGetStream, bool force)
|
||||||
{
|
{
|
||||||
bool forwardChangeOwnDSP = false;
|
bool forwardChangeOwnDSP = false;
|
||||||
bool forwardChangeRxDSP = false;
|
bool forwardChangeRxDSP = false;
|
||||||
@ -635,6 +653,7 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
bool forwardClockSource = false;
|
bool forwardClockSource = false;
|
||||||
bool ownThreadWasRunning = false;
|
bool ownThreadWasRunning = false;
|
||||||
bool reapplySomeSettings = false;
|
bool reapplySomeSettings = false;
|
||||||
|
bool checkRates = false;
|
||||||
QList<QString> reverseAPIKeys;
|
QList<QString> reverseAPIKeys;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -649,7 +668,7 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("clockSource");
|
reverseAPIKeys.append("clockSource");
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice())
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -680,18 +699,17 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
reverseAPIKeys.append("devSampleRate");
|
reverseAPIKeys.append("devSampleRate");
|
||||||
forwardChangeAllDSP = true;
|
forwardChangeAllDSP = true;
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
{
|
{
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_rx_rate(settings.m_devSampleRate, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_rx_rate(settings.m_devSampleRate, m_deviceShared.m_channel);
|
||||||
double actualSampleRate = m_deviceShared.m_deviceParams->getDevice()->get_rx_rate(m_deviceShared.m_channel);
|
qDebug("USRPInput::applySettings: set sample rate set to %d", settings.m_devSampleRate);
|
||||||
qDebug("USRPInput::applySettings: set sample rate set to %d - actual rate %f", settings.m_devSampleRate,
|
checkRates = true;
|
||||||
actualSampleRate);
|
|
||||||
m_deviceShared.m_deviceParams->m_sampleRate = m_settings.m_devSampleRate;
|
|
||||||
reapplySomeSettings = true;
|
reapplySomeSettings = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_centerFrequency != settings.m_centerFrequency)
|
if ((m_settings.m_centerFrequency != settings.m_centerFrequency)
|
||||||
|
|| (m_settings.m_loOffset != settings.m_loOffset)
|
||||||
|| (m_settings.m_transverterMode != settings.m_transverterMode)
|
|| (m_settings.m_transverterMode != settings.m_transverterMode)
|
||||||
|| (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)
|
|| (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)
|
||||||
|| force)
|
|| force)
|
||||||
@ -701,26 +719,34 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
reverseAPIKeys.append("transverterDeltaFrequency");
|
reverseAPIKeys.append("transverterDeltaFrequency");
|
||||||
forwardChangeRxDSP = true;
|
forwardChangeRxDSP = true;
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
|
{
|
||||||
|
if (settings.m_loOffset != 0)
|
||||||
|
{
|
||||||
|
uhd::tune_request_t tune_request(deviceCenterFrequency, settings.m_loOffset);
|
||||||
|
m_deviceShared.m_deviceParams->getDevice()->set_rx_freq(tune_request, m_deviceShared.m_channel);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
uhd::tune_request_t tune_request(deviceCenterFrequency);
|
uhd::tune_request_t tune_request(deviceCenterFrequency);
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_rx_freq(tune_request, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_rx_freq(tune_request, m_deviceShared.m_channel);
|
||||||
|
}
|
||||||
m_deviceShared.m_centerFrequency = deviceCenterFrequency; // for buddies
|
m_deviceShared.m_centerFrequency = deviceCenterFrequency; // for buddies
|
||||||
qDebug("USRPInput::applySettings: frequency set to %lld", deviceCenterFrequency);
|
qDebug("USRPInput::applySettings: frequency set to %lld with LO offset %d", deviceCenterFrequency, settings.m_loOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_dcBlock != settings.m_dcBlock) || force)
|
if ((m_settings.m_dcBlock != settings.m_dcBlock) || force)
|
||||||
{
|
{
|
||||||
reverseAPIKeys.append("dcBlock");
|
reverseAPIKeys.append("dcBlock");
|
||||||
if (m_deviceShared.m_deviceParams->getDevice())
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_rx_dc_offset(settings.m_dcBlock, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_rx_dc_offset(settings.m_dcBlock, m_deviceShared.m_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force)
|
if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force)
|
||||||
{
|
{
|
||||||
reverseAPIKeys.append("iqCorrection");
|
reverseAPIKeys.append("iqCorrection");
|
||||||
if (m_deviceShared.m_deviceParams->getDevice())
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_rx_iq_balance(settings.m_iqCorrection, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_rx_iq_balance(settings.m_iqCorrection, m_deviceShared.m_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,7 +754,7 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("gainMode");
|
reverseAPIKeys.append("gainMode");
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
{
|
{
|
||||||
if (settings.m_gainMode == USRPInputSettings::GAIN_AUTO)
|
if (settings.m_gainMode == USRPInputSettings::GAIN_AUTO)
|
||||||
{
|
{
|
||||||
@ -748,7 +774,7 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("gain");
|
reverseAPIKeys.append("gain");
|
||||||
|
|
||||||
if ((settings.m_gainMode != USRPInputSettings::GAIN_AUTO) && m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if ((settings.m_gainMode != USRPInputSettings::GAIN_AUTO) && m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
{
|
{
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_rx_gain(settings.m_gain, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_rx_gain(settings.m_gain, m_deviceShared.m_channel);
|
||||||
qDebug() << "USRPInput::applySettings: Gain set to " << settings.m_gain << " for channel " << m_deviceShared.m_channel;
|
qDebug() << "USRPInput::applySettings: Gain set to " << settings.m_gain << " for channel " << m_deviceShared.m_channel;
|
||||||
@ -758,8 +784,13 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
if ((m_settings.m_lpfBW != settings.m_lpfBW) || force)
|
if ((m_settings.m_lpfBW != settings.m_lpfBW) || force)
|
||||||
{
|
{
|
||||||
reverseAPIKeys.append("lpfBW");
|
reverseAPIKeys.append("lpfBW");
|
||||||
|
|
||||||
|
// Don't set bandwidth before get_rx_stream (See above)
|
||||||
|
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
||||||
|
{
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_rx_bandwidth(settings.m_lpfBW, m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_rx_bandwidth(settings.m_lpfBW, m_deviceShared.m_channel);
|
||||||
qDebug("USRPOutput::applySettings: LPF BW: %f for channel %d", settings.m_lpfBW, m_deviceShared.m_channel);
|
qDebug("USRPInput::applySettings: LPF BW: %f for channel %d", settings.m_lpfBW, m_deviceShared.m_channel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_log2SoftDecim != settings.m_log2SoftDecim) || force)
|
if ((m_settings.m_log2SoftDecim != settings.m_log2SoftDecim) || force)
|
||||||
@ -779,7 +810,7 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("antennaPath");
|
reverseAPIKeys.append("antennaPath");
|
||||||
|
|
||||||
if (m_deviceShared.m_deviceParams->getDevice() && m_channelAcquired)
|
if (m_deviceShared.m_deviceParams->getDevice() && (m_channelAcquired || preGetStream))
|
||||||
{
|
{
|
||||||
m_deviceShared.m_deviceParams->getDevice()->set_rx_antenna(settings.m_antennaPath.toStdString(), m_deviceShared.m_channel);
|
m_deviceShared.m_deviceParams->getDevice()->set_rx_antenna(settings.m_antennaPath.toStdString(), m_deviceShared.m_channel);
|
||||||
qDebug("USRPInput::applySettings: set antenna path to %s on channel %d", qPrintable(settings.m_antennaPath), m_deviceShared.m_channel);
|
qDebug("USRPInput::applySettings: set antenna path to %s on channel %d", qPrintable(settings.m_antennaPath), m_deviceShared.m_channel);
|
||||||
@ -810,6 +841,17 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
|
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
|
|
||||||
|
if (checkRates)
|
||||||
|
{
|
||||||
|
// Check if requested rate could actually be met and what master clock rate we ended up with
|
||||||
|
double actualSampleRate = m_deviceShared.m_deviceParams->getDevice()->get_rx_rate(m_deviceShared.m_channel);
|
||||||
|
qDebug("USRPInput::applySettings: actual sample rate %f", actualSampleRate);
|
||||||
|
double masterClockRate = m_deviceShared.m_deviceParams->getDevice()->get_master_clock_rate();
|
||||||
|
qDebug("USRPInput::applySettings: master_clock_rate %f", masterClockRate);
|
||||||
|
m_settings.m_devSampleRate = actualSampleRate;
|
||||||
|
m_settings.m_masterClockRate = masterClockRate;
|
||||||
|
}
|
||||||
|
|
||||||
// forward changes to buddies or oneself
|
// forward changes to buddies or oneself
|
||||||
|
|
||||||
if (forwardChangeAllDSP)
|
if (forwardChangeAllDSP)
|
||||||
@ -829,7 +871,7 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
for (; itSource != sourceBuddies.end(); ++itSource)
|
for (; itSource != sourceBuddies.end(); ++itSource)
|
||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
m_settings.m_devSampleRate, m_settings.m_centerFrequency, true);
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, true);
|
||||||
(*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
|
(*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -840,9 +882,17 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
for (; itSink != sinkBuddies.end(); ++itSink)
|
for (; itSink != sinkBuddies.end(); ++itSink)
|
||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
m_settings.m_devSampleRate, m_settings.m_centerFrequency, true);
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, true);
|
||||||
(*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
|
(*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send to GUI so it can see master clock rate and if actual rate differs
|
||||||
|
if (m_deviceAPI->getSamplingDeviceGUIMessageQueue())
|
||||||
|
{
|
||||||
|
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, true);
|
||||||
|
m_deviceAPI->getSamplingDeviceGUIMessageQueue()->push(report);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (forwardChangeRxDSP)
|
else if (forwardChangeRxDSP)
|
||||||
{
|
{
|
||||||
@ -861,7 +911,7 @@ bool USRPInput::applySettings(const USRPInputSettings& settings, bool force)
|
|||||||
for (; itSource != sourceBuddies.end(); ++itSource)
|
for (; itSource != sourceBuddies.end(); ++itSource)
|
||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
DeviceUSRPShared::MsgReportBuddyChange *report = DeviceUSRPShared::MsgReportBuddyChange::create(
|
||||||
m_settings.m_devSampleRate, m_settings.m_centerFrequency, true);
|
m_settings.m_devSampleRate, m_settings.m_centerFrequency, m_settings.m_loOffset, m_settings.m_masterClockRate, true);
|
||||||
(*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
|
(*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -990,6 +1040,9 @@ void USRPInput::webapiUpdateDeviceSettings(
|
|||||||
if (deviceSettingsKeys.contains("centerFrequency")) {
|
if (deviceSettingsKeys.contains("centerFrequency")) {
|
||||||
settings.m_centerFrequency = response.getUsrpInputSettings()->getCenterFrequency();
|
settings.m_centerFrequency = response.getUsrpInputSettings()->getCenterFrequency();
|
||||||
}
|
}
|
||||||
|
if (deviceSettingsKeys.contains("loOffset")) {
|
||||||
|
settings.m_loOffset = response.getUsrpInputSettings()->getLoOffset();
|
||||||
|
}
|
||||||
if (deviceSettingsKeys.contains("dcBlock")) {
|
if (deviceSettingsKeys.contains("dcBlock")) {
|
||||||
settings.m_dcBlock = response.getUsrpInputSettings()->getDcBlock() != 0;
|
settings.m_dcBlock = response.getUsrpInputSettings()->getDcBlock() != 0;
|
||||||
}
|
}
|
||||||
@ -1040,6 +1093,7 @@ void USRPInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& respo
|
|||||||
response.getUsrpInputSettings()->setCenterFrequency(settings.m_centerFrequency);
|
response.getUsrpInputSettings()->setCenterFrequency(settings.m_centerFrequency);
|
||||||
response.getUsrpInputSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
|
response.getUsrpInputSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
|
||||||
response.getUsrpInputSettings()->setDevSampleRate(settings.m_devSampleRate);
|
response.getUsrpInputSettings()->setDevSampleRate(settings.m_devSampleRate);
|
||||||
|
response.getUsrpInputSettings()->setLoOffset(settings.m_loOffset);
|
||||||
response.getUsrpInputSettings()->setClockSource(new QString(settings.m_clockSource));
|
response.getUsrpInputSettings()->setClockSource(new QString(settings.m_clockSource));
|
||||||
response.getUsrpInputSettings()->setGain(settings.m_gain);
|
response.getUsrpInputSettings()->setGain(settings.m_gain);
|
||||||
response.getUsrpInputSettings()->setGainMode((int) settings.m_gainMode);
|
response.getUsrpInputSettings()->setGainMode((int) settings.m_gainMode);
|
||||||
@ -1136,6 +1190,9 @@ void USRPInput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, co
|
|||||||
if (deviceSettingsKeys.contains("centerFrequency") || force) {
|
if (deviceSettingsKeys.contains("centerFrequency") || force) {
|
||||||
swgUsrpInputSettings->setCenterFrequency(settings.m_centerFrequency);
|
swgUsrpInputSettings->setCenterFrequency(settings.m_centerFrequency);
|
||||||
}
|
}
|
||||||
|
if (deviceSettingsKeys.contains("loOffset") || force) {
|
||||||
|
swgUsrpInputSettings->setLoOffset(settings.m_loOffset);
|
||||||
|
}
|
||||||
if (deviceSettingsKeys.contains("dcBlock") || force) {
|
if (deviceSettingsKeys.contains("dcBlock") || force) {
|
||||||
swgUsrpInputSettings->setDcBlock(settings.m_dcBlock ? 1 : 0);
|
swgUsrpInputSettings->setDcBlock(settings.m_dcBlock ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
@ -227,6 +227,7 @@ private:
|
|||||||
DeviceUSRPShared m_deviceShared;
|
DeviceUSRPShared m_deviceShared;
|
||||||
bool m_channelAcquired;
|
bool m_channelAcquired;
|
||||||
uhd::rx_streamer::sptr m_streamId;
|
uhd::rx_streamer::sptr m_streamId;
|
||||||
|
size_t m_bufSamples;
|
||||||
QNetworkAccessManager *m_networkManager;
|
QNetworkAccessManager *m_networkManager;
|
||||||
QNetworkRequest m_networkRequest;
|
QNetworkRequest m_networkRequest;
|
||||||
|
|
||||||
@ -238,7 +239,7 @@ private:
|
|||||||
void resumeRxBuddies();
|
void resumeRxBuddies();
|
||||||
void suspendTxBuddies();
|
void suspendTxBuddies();
|
||||||
void resumeTxBuddies();
|
void resumeTxBuddies();
|
||||||
bool applySettings(const USRPInputSettings& settings, bool force = false);
|
bool applySettings(const USRPInputSettings& settings, bool preGetStream, bool force = false);
|
||||||
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
||||||
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const USRPInputSettings& settings, bool force);
|
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const USRPInputSettings& settings, bool force);
|
||||||
void webapiReverseSendStartStop(bool start);
|
void webapiReverseSendStartStop(bool start);
|
||||||
|
@ -61,6 +61,9 @@ USRPInputGUI::USRPInputGUI(DeviceUISet *deviceUISet, QWidget* parent) :
|
|||||||
ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
|
ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
|
||||||
ui->sampleRate->setValueRange(8, (uint32_t) minF, (uint32_t) maxF);
|
ui->sampleRate->setValueRange(8, (uint32_t) minF, (uint32_t) maxF);
|
||||||
|
|
||||||
|
ui->loOffset->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
|
||||||
|
ui->loOffset->setValueRange(false, 5, (int32_t)-maxF/2/1000, (int32_t)maxF/2/1000); // LO offset shouldn't be greater than half the sample rate
|
||||||
|
|
||||||
m_usrpInput->getLPRange(minF, maxF);
|
m_usrpInput->getLPRange(minF, maxF);
|
||||||
ui->lpf->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
|
ui->lpf->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
|
||||||
ui->lpf->setValueRange(5, (minF/1000)+1, maxF/1000);
|
ui->lpf->setValueRange(5, (minF/1000)+1, maxF/1000);
|
||||||
@ -160,10 +163,12 @@ bool USRPInputGUI::handleMessage(const Message& message)
|
|||||||
else if (DeviceUSRPShared::MsgReportBuddyChange::match(message))
|
else if (DeviceUSRPShared::MsgReportBuddyChange::match(message))
|
||||||
{
|
{
|
||||||
DeviceUSRPShared::MsgReportBuddyChange& report = (DeviceUSRPShared::MsgReportBuddyChange&) message;
|
DeviceUSRPShared::MsgReportBuddyChange& report = (DeviceUSRPShared::MsgReportBuddyChange&) message;
|
||||||
m_settings.m_devSampleRate = report.getDevSampleRate();
|
m_settings.m_masterClockRate = report.getMasterClockRate();
|
||||||
|
|
||||||
if (report.getRxElseTx()) {
|
if (report.getRxElseTx()) {
|
||||||
|
m_settings.m_devSampleRate = report.getDevSampleRate();
|
||||||
m_settings.m_centerFrequency = report.getCenterFrequency();
|
m_settings.m_centerFrequency = report.getCenterFrequency();
|
||||||
|
m_settings.m_loOffset = report.getLOOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
@ -283,12 +288,22 @@ void USRPInputGUI::handleInputMessages()
|
|||||||
void USRPInputGUI::updateSampleRate()
|
void USRPInputGUI::updateSampleRate()
|
||||||
{
|
{
|
||||||
uint32_t sr = m_settings.m_devSampleRate;
|
uint32_t sr = m_settings.m_devSampleRate;
|
||||||
|
int cr = m_settings.m_masterClockRate;
|
||||||
|
|
||||||
if (sr < 100000000) {
|
if (sr < 100000000) {
|
||||||
ui->sampleRateLabel->setText(tr("%1k").arg(QString::number(sr / 1000.0f, 'g', 5)));
|
ui->sampleRateLabel->setText(tr("%1k").arg(QString::number(sr / 1000.0f, 'g', 5)));
|
||||||
} else {
|
} else {
|
||||||
ui->sampleRateLabel->setText(tr("%1M").arg(QString::number(sr / 1000000.0f, 'g', 5)));
|
ui->sampleRateLabel->setText(tr("%1M").arg(QString::number(sr / 1000000.0f, 'g', 5)));
|
||||||
}
|
}
|
||||||
|
if (cr < 0) {
|
||||||
|
ui->masterClockRateLabel->setText("-");
|
||||||
|
} else if (cr < 100000000) {
|
||||||
|
ui->masterClockRateLabel->setText(tr("%1k").arg(QString::number(cr / 1000.0f, 'g', 5)));
|
||||||
|
} else {
|
||||||
|
ui->masterClockRateLabel->setText(tr("%1M").arg(QString::number(cr / 1000000.0f, 'g', 5)));
|
||||||
|
}
|
||||||
|
// LO offset shouldn't be greater than half the sample rate
|
||||||
|
ui->loOffset->setValueRange(false, 5, -(int32_t)sr/2/1000, (int32_t)sr/2/1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void USRPInputGUI::updateSampleRateAndFrequency()
|
void USRPInputGUI::updateSampleRateAndFrequency()
|
||||||
@ -350,6 +365,7 @@ void USRPInputGUI::displaySettings()
|
|||||||
updateSampleRate();
|
updateSampleRate();
|
||||||
|
|
||||||
ui->lpf->setValue(m_settings.m_lpfBW / 1000);
|
ui->lpf->setValue(m_settings.m_lpfBW / 1000);
|
||||||
|
ui->loOffset->setValue(m_settings.m_loOffset / 1000);
|
||||||
|
|
||||||
ui->gain->setValue(m_settings.m_gain);
|
ui->gain->setValue(m_settings.m_gain);
|
||||||
ui->gainText->setText(tr("%1").arg(m_settings.m_gain));
|
ui->gainText->setText(tr("%1").arg(m_settings.m_gain));
|
||||||
@ -527,6 +543,12 @@ void USRPInputGUI::on_lpf_changed(quint64 value)
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void USRPInputGUI::on_loOffset_changed(qint64 value)
|
||||||
|
{
|
||||||
|
m_settings.m_loOffset = value * 1000;
|
||||||
|
sendSettings();
|
||||||
|
}
|
||||||
|
|
||||||
void USRPInputGUI::on_gainMode_currentIndexChanged(int index)
|
void USRPInputGUI::on_gainMode_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
m_settings.m_gainMode = (USRPInputSettings::GainMode) index;
|
m_settings.m_gainMode = (USRPInputSettings::GainMode) index;
|
||||||
|
@ -89,6 +89,7 @@ private slots:
|
|||||||
void on_sampleRate_changed(quint64 value);
|
void on_sampleRate_changed(quint64 value);
|
||||||
void on_swDecim_currentIndexChanged(int index);
|
void on_swDecim_currentIndexChanged(int index);
|
||||||
void on_lpf_changed(quint64 value);
|
void on_lpf_changed(quint64 value);
|
||||||
|
void on_loOffset_changed(qint64 value);
|
||||||
void on_gainMode_currentIndexChanged(int index);
|
void on_gainMode_currentIndexChanged(int index);
|
||||||
void on_gain_valueChanged(int value);
|
void on_gain_valueChanged(int value);
|
||||||
void on_antenna_currentIndexChanged(int index);
|
void on_antenna_currentIndexChanged(int index);
|
||||||
|
@ -75,6 +75,16 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="freqLeftBotLayout">
|
<layout class="QHBoxLayout" name="freqLeftBotLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="masterClockRateLabel">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Master clock rate (sample rate between FPGA and RFIC) (k or MS/s)</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>00000k</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="sampleRateLabel">
|
<widget class="QLabel" name="sampleRateLabel">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@ -626,6 +636,57 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="loOffsetLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>LO</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="ValueDialZ" name="loOffset" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Liberation Mono</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>PointingHandCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>LO offset (kHz)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="loOffsetUnits">
|
||||||
|
<property name="text">
|
||||||
|
<string>kHz</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -748,6 +809,12 @@
|
|||||||
<header>gui/valuedial.h</header>
|
<header>gui/valuedial.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>ValueDialZ</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>gui/valuedialz.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>TransverterButton</class>
|
<class>TransverterButton</class>
|
||||||
<extends>QPushButton</extends>
|
<extends>QPushButton</extends>
|
||||||
|
@ -26,12 +26,14 @@ USRPInputSettings::USRPInputSettings()
|
|||||||
|
|
||||||
void USRPInputSettings::resetToDefaults()
|
void USRPInputSettings::resetToDefaults()
|
||||||
{
|
{
|
||||||
|
m_masterClockRate = -1; // Calculated by UHD
|
||||||
m_centerFrequency = 435000*1000;
|
m_centerFrequency = 435000*1000;
|
||||||
m_devSampleRate = 3000000;
|
m_devSampleRate = 3000000;
|
||||||
|
m_loOffset = 0;
|
||||||
m_dcBlock = false;
|
m_dcBlock = false;
|
||||||
m_iqCorrection = false;
|
m_iqCorrection = false;
|
||||||
m_log2SoftDecim = 0;
|
m_log2SoftDecim = 0;
|
||||||
m_lpfBW = 5.5e6f;
|
m_lpfBW = 10e6f;
|
||||||
m_gain = 50;
|
m_gain = 50;
|
||||||
m_antennaPath = "TX/RX";
|
m_antennaPath = "TX/RX";
|
||||||
m_gainMode = GAIN_AUTO;
|
m_gainMode = GAIN_AUTO;
|
||||||
@ -63,6 +65,7 @@ QByteArray USRPInputSettings::serialize() const
|
|||||||
s.writeString(13, m_reverseAPIAddress);
|
s.writeString(13, m_reverseAPIAddress);
|
||||||
s.writeU32(14, m_reverseAPIPort);
|
s.writeU32(14, m_reverseAPIPort);
|
||||||
s.writeU32(15, m_reverseAPIDeviceIndex);
|
s.writeU32(15, m_reverseAPIDeviceIndex);
|
||||||
|
s.writeS32(16, m_loOffset);
|
||||||
return s.final();
|
return s.final();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +108,7 @@ bool USRPInputSettings::deserialize(const QByteArray& data)
|
|||||||
|
|
||||||
d.readU32(15, &uintval, 0);
|
d.readU32(15, &uintval, 0);
|
||||||
m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval;
|
m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval;
|
||||||
|
d.readS32(16, &m_loOffset, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,11 @@ struct USRPInputSettings
|
|||||||
GAIN_MANUAL
|
GAIN_MANUAL
|
||||||
} GainMode;
|
} GainMode;
|
||||||
|
|
||||||
|
int m_masterClockRate;
|
||||||
// global settings to be saved
|
// global settings to be saved
|
||||||
uint64_t m_centerFrequency;
|
uint64_t m_centerFrequency;
|
||||||
int m_devSampleRate;
|
int m_devSampleRate;
|
||||||
|
int m_loOffset;
|
||||||
// channel settings
|
// channel settings
|
||||||
bool m_dcBlock;
|
bool m_dcBlock;
|
||||||
bool m_iqCorrection;
|
bool m_iqCorrection;
|
||||||
|
@ -26,20 +26,35 @@
|
|||||||
#include "usrpinputsettings.h"
|
#include "usrpinputsettings.h"
|
||||||
#include "usrpinputthread.h"
|
#include "usrpinputthread.h"
|
||||||
|
|
||||||
USRPInputThread::USRPInputThread(uhd::rx_streamer::sptr stream, SampleSinkFifo* sampleFifo, QObject* parent) :
|
USRPInputThread::USRPInputThread(uhd::rx_streamer::sptr stream, size_t bufSamples, SampleSinkFifo* sampleFifo, QObject* parent) :
|
||||||
QThread(parent),
|
QThread(parent),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_stream(stream),
|
m_stream(stream),
|
||||||
m_convertBuffer(DeviceUSRP::blockSize),
|
m_bufSamples(bufSamples),
|
||||||
|
m_convertBuffer(bufSamples),
|
||||||
m_sampleFifo(sampleFifo),
|
m_sampleFifo(sampleFifo),
|
||||||
m_log2Decim(0)
|
m_log2Decim(0)
|
||||||
{
|
{
|
||||||
std::fill(m_buf, m_buf + 2*DeviceUSRP::blockSize, 0);
|
// *2 as samples are I+Q
|
||||||
|
m_buf = new qint16[2*bufSamples];
|
||||||
|
std::fill(m_buf, m_buf + 2*bufSamples, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
USRPInputThread::~USRPInputThread()
|
USRPInputThread::~USRPInputThread()
|
||||||
{
|
{
|
||||||
stopWork();
|
stopWork();
|
||||||
|
delete m_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USRPInputThread::issueStreamCmd(bool start)
|
||||||
|
{
|
||||||
|
uhd::stream_cmd_t stream_cmd(start ? uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS : uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
|
||||||
|
stream_cmd.num_samps = size_t(0);
|
||||||
|
stream_cmd.stream_now = true;
|
||||||
|
stream_cmd.time_spec = uhd::time_spec_t();
|
||||||
|
|
||||||
|
m_stream->issue_stream_cmd(stream_cmd);
|
||||||
|
qDebug() << "USRPInputThread::issueStreamCmd " << (start ? "start" : "stop");
|
||||||
}
|
}
|
||||||
|
|
||||||
void USRPInputThread::startWork()
|
void USRPInputThread::startWork()
|
||||||
@ -48,12 +63,8 @@ void USRPInputThread::startWork()
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
|
// Start streaming
|
||||||
stream_cmd.num_samps = size_t(0);
|
issueStreamCmd(true);
|
||||||
stream_cmd.stream_now = true;
|
|
||||||
stream_cmd.time_spec = uhd::time_spec_t();
|
|
||||||
|
|
||||||
m_stream->issue_stream_cmd(stream_cmd);
|
|
||||||
|
|
||||||
// Reset stats
|
// Reset stats
|
||||||
m_packets = 0;
|
m_packets = 0;
|
||||||
@ -84,18 +95,20 @@ void USRPInputThread::stopWork()
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
uhd::rx_metadata_t md;
|
uhd::rx_metadata_t md;
|
||||||
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
|
|
||||||
stream_cmd.stream_now = true;
|
// Stop streaming
|
||||||
m_stream->issue_stream_cmd(stream_cmd);
|
issueStreamCmd(false);
|
||||||
|
|
||||||
// Clear out any data left in the stream, otherwise we'll get an
|
// Clear out any data left in the stream, otherwise we'll get an
|
||||||
// exception 'recv buffer smaller than vrt packet offset' when restarting
|
// exception 'recv buffer smaller than vrt packet offset' when restarting
|
||||||
while (!md.end_of_burst)
|
md.end_of_burst = false;
|
||||||
|
md.error_code = uhd::rx_metadata_t::ERROR_CODE_NONE;
|
||||||
|
while (!md.end_of_burst && (md.error_code != uhd::rx_metadata_t::ERROR_CODE_TIMEOUT))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//qDebug() << "USRPInputThread::stopWork: recing until end of burst";
|
md.reset();
|
||||||
m_stream->recv(m_buf, DeviceUSRP::blockSize, md);
|
m_stream->recv(m_buf, m_bufSamples, md);
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
@ -127,26 +140,38 @@ void USRPInputThread::run()
|
|||||||
{
|
{
|
||||||
while (m_running)
|
while (m_running)
|
||||||
{
|
{
|
||||||
const size_t samples_received = m_stream->recv(m_buf, DeviceUSRP::blockSize, md);
|
md.reset();
|
||||||
|
const size_t samples_received = m_stream->recv(m_buf, m_bufSamples, md);
|
||||||
|
|
||||||
m_packets++;
|
m_packets++;
|
||||||
if (samples_received != DeviceUSRP::blockSize)
|
if (samples_received != m_bufSamples)
|
||||||
{
|
{
|
||||||
qDebug("USRPInputThread::run - received %ld/%d samples", samples_received, DeviceUSRP::blockSize);
|
qDebug("USRPInputThread::run - received %ld/%ld samples", samples_received, m_bufSamples);
|
||||||
}
|
}
|
||||||
if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT)
|
if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT)
|
||||||
{
|
{
|
||||||
qDebug("USRPInputThread::run - timeout - ending thread");
|
qDebug("USRPInputThread::run - timeout - ending thread");
|
||||||
m_timeouts++;
|
m_timeouts++;
|
||||||
// It seems we can't recover after a timeout, so stop thread
|
// Restart streaming
|
||||||
m_running = false;
|
issueStreamCmd(false);
|
||||||
|
issueStreamCmd(true);
|
||||||
|
qDebug("USRPInputThread::run - timeout - restarting");
|
||||||
}
|
}
|
||||||
else if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW)
|
else if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW)
|
||||||
{
|
{
|
||||||
qDebug("USRPInputThread::run - overflow");
|
qDebug("USRPInputThread::run - overflow");
|
||||||
m_overflows++;
|
m_overflows++;
|
||||||
}
|
}
|
||||||
|
else if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND)
|
||||||
|
qDebug("USRPInputThread::run - late command error");
|
||||||
|
else if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_BROKEN_CHAIN)
|
||||||
|
qDebug("USRPInputThread::run - broken chain error");
|
||||||
|
else if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_ALIGNMENT)
|
||||||
|
qDebug("USRPInputThread::run - alignment error");
|
||||||
|
else if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET)
|
||||||
|
qDebug("USRPInputThread::run - bad packet error");
|
||||||
|
|
||||||
|
if (samples_received > 0)
|
||||||
callbackIQ(m_buf, 2 * samples_received);
|
callbackIQ(m_buf, 2 * samples_received);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ class USRPInputThread : public QThread, public DeviceUSRPShared::ThreadInterface
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
USRPInputThread(uhd::rx_streamer::sptr stream, SampleSinkFifo* sampleFifo, QObject* parent = 0);
|
USRPInputThread(uhd::rx_streamer::sptr stream, size_t bufSamples, SampleSinkFifo* sampleFifo, QObject* parent = 0);
|
||||||
~USRPInputThread();
|
~USRPInputThread();
|
||||||
|
|
||||||
virtual void startWork();
|
virtual void startWork();
|
||||||
@ -45,6 +45,7 @@ public:
|
|||||||
virtual bool isRunning() { return m_running; }
|
virtual bool isRunning() { return m_running; }
|
||||||
void setLog2Decimation(unsigned int log2_decim);
|
void setLog2Decimation(unsigned int log2_decim);
|
||||||
void getStreamStatus(bool& active, quint32& overflows, quint32& m_timeouts);
|
void getStreamStatus(bool& active, quint32& overflows, quint32& m_timeouts);
|
||||||
|
void issueStreamCmd(bool start);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMutex m_startWaitMutex;
|
QMutex m_startWaitMutex;
|
||||||
@ -56,13 +57,14 @@ private:
|
|||||||
quint32 m_timeouts;
|
quint32 m_timeouts;
|
||||||
|
|
||||||
uhd::rx_streamer::sptr m_stream;
|
uhd::rx_streamer::sptr m_stream;
|
||||||
qint16 m_buf[2*DeviceUSRP::blockSize]; //must hold I+Q values of each sample hence 2xcomplex size
|
qint16 *m_buf;
|
||||||
|
size_t m_bufSamples;
|
||||||
SampleVector m_convertBuffer;
|
SampleVector m_convertBuffer;
|
||||||
SampleSinkFifo* m_sampleFifo;
|
SampleSinkFifo* m_sampleFifo;
|
||||||
|
|
||||||
unsigned int m_log2Decim; // soft decimation
|
unsigned int m_log2Decim; // soft decimation
|
||||||
|
|
||||||
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12, true> m_decimatorsIQ;
|
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 16, true> m_decimatorsIQ;
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
void callbackIQ(const qint16* buf, qint32 len);
|
void callbackIQ(const qint16* buf, qint32 len);
|
||||||
|
@ -7725,6 +7725,9 @@ margin-bottom: 20px;
|
|||||||
"devSampleRate" : {
|
"devSampleRate" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
|
"loOffset" : {
|
||||||
|
"type" : "integer"
|
||||||
|
},
|
||||||
"dcBlock" : {
|
"dcBlock" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
@ -7801,6 +7804,9 @@ margin-bottom: 20px;
|
|||||||
"devSampleRate" : {
|
"devSampleRate" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
|
"loOffset" : {
|
||||||
|
"type" : "integer"
|
||||||
|
},
|
||||||
"log2SoftInterp" : {
|
"log2SoftInterp" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
@ -40111,7 +40117,7 @@ except ApiException as e:
|
|||||||
</div>
|
</div>
|
||||||
<div id="generator">
|
<div id="generator">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Generated 2020-10-27T16:45:08.746+01:00
|
Generated 2020-10-27T19:23:34.436+01:00
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,6 +6,8 @@ USRPInputSettings:
|
|||||||
format: int64
|
format: int64
|
||||||
devSampleRate:
|
devSampleRate:
|
||||||
type: integer
|
type: integer
|
||||||
|
loOffset:
|
||||||
|
type: integer
|
||||||
dcBlock:
|
dcBlock:
|
||||||
type: integer
|
type: integer
|
||||||
iqCorrection:
|
iqCorrection:
|
||||||
@ -46,6 +48,8 @@ USRPOutputSettings:
|
|||||||
format: int64
|
format: int64
|
||||||
devSampleRate:
|
devSampleRate:
|
||||||
type: integer
|
type: integer
|
||||||
|
loOffset:
|
||||||
|
type: integer
|
||||||
log2SoftInterp:
|
log2SoftInterp:
|
||||||
type: integer
|
type: integer
|
||||||
lpfBW:
|
lpfBW:
|
||||||
|
@ -7725,6 +7725,9 @@ margin-bottom: 20px;
|
|||||||
"devSampleRate" : {
|
"devSampleRate" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
|
"loOffset" : {
|
||||||
|
"type" : "integer"
|
||||||
|
},
|
||||||
"dcBlock" : {
|
"dcBlock" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
@ -7801,6 +7804,9 @@ margin-bottom: 20px;
|
|||||||
"devSampleRate" : {
|
"devSampleRate" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
|
"loOffset" : {
|
||||||
|
"type" : "integer"
|
||||||
|
},
|
||||||
"log2SoftInterp" : {
|
"log2SoftInterp" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
@ -40111,7 +40117,7 @@ except ApiException as e:
|
|||||||
</div>
|
</div>
|
||||||
<div id="generator">
|
<div id="generator">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Generated 2020-10-27T16:45:08.746+01:00
|
Generated 2020-10-27T19:23:34.436+01:00
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,6 +32,8 @@ SWGUSRPInputSettings::SWGUSRPInputSettings() {
|
|||||||
m_center_frequency_isSet = false;
|
m_center_frequency_isSet = false;
|
||||||
dev_sample_rate = 0;
|
dev_sample_rate = 0;
|
||||||
m_dev_sample_rate_isSet = false;
|
m_dev_sample_rate_isSet = false;
|
||||||
|
lo_offset = 0;
|
||||||
|
m_lo_offset_isSet = false;
|
||||||
dc_block = 0;
|
dc_block = 0;
|
||||||
m_dc_block_isSet = false;
|
m_dc_block_isSet = false;
|
||||||
iq_correction = 0;
|
iq_correction = 0;
|
||||||
@ -72,6 +74,8 @@ SWGUSRPInputSettings::init() {
|
|||||||
m_center_frequency_isSet = false;
|
m_center_frequency_isSet = false;
|
||||||
dev_sample_rate = 0;
|
dev_sample_rate = 0;
|
||||||
m_dev_sample_rate_isSet = false;
|
m_dev_sample_rate_isSet = false;
|
||||||
|
lo_offset = 0;
|
||||||
|
m_lo_offset_isSet = false;
|
||||||
dc_block = 0;
|
dc_block = 0;
|
||||||
m_dc_block_isSet = false;
|
m_dc_block_isSet = false;
|
||||||
iq_correction = 0;
|
iq_correction = 0;
|
||||||
@ -110,6 +114,7 @@ SWGUSRPInputSettings::cleanup() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(antenna_path != nullptr) {
|
if(antenna_path != nullptr) {
|
||||||
delete antenna_path;
|
delete antenna_path;
|
||||||
}
|
}
|
||||||
@ -143,6 +148,8 @@ SWGUSRPInputSettings::fromJsonObject(QJsonObject &pJson) {
|
|||||||
|
|
||||||
::SWGSDRangel::setValue(&dev_sample_rate, pJson["devSampleRate"], "qint32", "");
|
::SWGSDRangel::setValue(&dev_sample_rate, pJson["devSampleRate"], "qint32", "");
|
||||||
|
|
||||||
|
::SWGSDRangel::setValue(&lo_offset, pJson["loOffset"], "qint32", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&dc_block, pJson["dcBlock"], "qint32", "");
|
::SWGSDRangel::setValue(&dc_block, pJson["dcBlock"], "qint32", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "qint32", "");
|
::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "qint32", "");
|
||||||
@ -193,6 +200,9 @@ SWGUSRPInputSettings::asJsonObject() {
|
|||||||
if(m_dev_sample_rate_isSet){
|
if(m_dev_sample_rate_isSet){
|
||||||
obj->insert("devSampleRate", QJsonValue(dev_sample_rate));
|
obj->insert("devSampleRate", QJsonValue(dev_sample_rate));
|
||||||
}
|
}
|
||||||
|
if(m_lo_offset_isSet){
|
||||||
|
obj->insert("loOffset", QJsonValue(lo_offset));
|
||||||
|
}
|
||||||
if(m_dc_block_isSet){
|
if(m_dc_block_isSet){
|
||||||
obj->insert("dcBlock", QJsonValue(dc_block));
|
obj->insert("dcBlock", QJsonValue(dc_block));
|
||||||
}
|
}
|
||||||
@ -259,6 +269,16 @@ SWGUSRPInputSettings::setDevSampleRate(qint32 dev_sample_rate) {
|
|||||||
this->m_dev_sample_rate_isSet = true;
|
this->m_dev_sample_rate_isSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint32
|
||||||
|
SWGUSRPInputSettings::getLoOffset() {
|
||||||
|
return lo_offset;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWGUSRPInputSettings::setLoOffset(qint32 lo_offset) {
|
||||||
|
this->lo_offset = lo_offset;
|
||||||
|
this->m_lo_offset_isSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
qint32
|
qint32
|
||||||
SWGUSRPInputSettings::getDcBlock() {
|
SWGUSRPInputSettings::getDcBlock() {
|
||||||
return dc_block;
|
return dc_block;
|
||||||
@ -410,6 +430,9 @@ SWGUSRPInputSettings::isSet(){
|
|||||||
if(m_dev_sample_rate_isSet){
|
if(m_dev_sample_rate_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
if(m_lo_offset_isSet){
|
||||||
|
isObjectUpdated = true; break;
|
||||||
|
}
|
||||||
if(m_dc_block_isSet){
|
if(m_dc_block_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,9 @@ public:
|
|||||||
qint32 getDevSampleRate();
|
qint32 getDevSampleRate();
|
||||||
void setDevSampleRate(qint32 dev_sample_rate);
|
void setDevSampleRate(qint32 dev_sample_rate);
|
||||||
|
|
||||||
|
qint32 getLoOffset();
|
||||||
|
void setLoOffset(qint32 lo_offset);
|
||||||
|
|
||||||
qint32 getDcBlock();
|
qint32 getDcBlock();
|
||||||
void setDcBlock(qint32 dc_block);
|
void setDcBlock(qint32 dc_block);
|
||||||
|
|
||||||
@ -100,6 +103,9 @@ private:
|
|||||||
qint32 dev_sample_rate;
|
qint32 dev_sample_rate;
|
||||||
bool m_dev_sample_rate_isSet;
|
bool m_dev_sample_rate_isSet;
|
||||||
|
|
||||||
|
qint32 lo_offset;
|
||||||
|
bool m_lo_offset_isSet;
|
||||||
|
|
||||||
qint32 dc_block;
|
qint32 dc_block;
|
||||||
bool m_dc_block_isSet;
|
bool m_dc_block_isSet;
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ SWGUSRPOutputSettings::SWGUSRPOutputSettings() {
|
|||||||
m_center_frequency_isSet = false;
|
m_center_frequency_isSet = false;
|
||||||
dev_sample_rate = 0;
|
dev_sample_rate = 0;
|
||||||
m_dev_sample_rate_isSet = false;
|
m_dev_sample_rate_isSet = false;
|
||||||
|
lo_offset = 0;
|
||||||
|
m_lo_offset_isSet = false;
|
||||||
log2_soft_interp = 0;
|
log2_soft_interp = 0;
|
||||||
m_log2_soft_interp_isSet = false;
|
m_log2_soft_interp_isSet = false;
|
||||||
lpf_bw = 0;
|
lpf_bw = 0;
|
||||||
@ -66,6 +68,8 @@ SWGUSRPOutputSettings::init() {
|
|||||||
m_center_frequency_isSet = false;
|
m_center_frequency_isSet = false;
|
||||||
dev_sample_rate = 0;
|
dev_sample_rate = 0;
|
||||||
m_dev_sample_rate_isSet = false;
|
m_dev_sample_rate_isSet = false;
|
||||||
|
lo_offset = 0;
|
||||||
|
m_lo_offset_isSet = false;
|
||||||
log2_soft_interp = 0;
|
log2_soft_interp = 0;
|
||||||
m_log2_soft_interp_isSet = false;
|
m_log2_soft_interp_isSet = false;
|
||||||
lpf_bw = 0;
|
lpf_bw = 0;
|
||||||
@ -97,6 +101,7 @@ SWGUSRPOutputSettings::cleanup() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(antenna_path != nullptr) {
|
if(antenna_path != nullptr) {
|
||||||
delete antenna_path;
|
delete antenna_path;
|
||||||
}
|
}
|
||||||
@ -128,6 +133,8 @@ SWGUSRPOutputSettings::fromJsonObject(QJsonObject &pJson) {
|
|||||||
|
|
||||||
::SWGSDRangel::setValue(&dev_sample_rate, pJson["devSampleRate"], "qint32", "");
|
::SWGSDRangel::setValue(&dev_sample_rate, pJson["devSampleRate"], "qint32", "");
|
||||||
|
|
||||||
|
::SWGSDRangel::setValue(&lo_offset, pJson["loOffset"], "qint32", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&log2_soft_interp, pJson["log2SoftInterp"], "qint32", "");
|
::SWGSDRangel::setValue(&log2_soft_interp, pJson["log2SoftInterp"], "qint32", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&lpf_bw, pJson["lpfBW"], "qint32", "");
|
::SWGSDRangel::setValue(&lpf_bw, pJson["lpfBW"], "qint32", "");
|
||||||
@ -172,6 +179,9 @@ SWGUSRPOutputSettings::asJsonObject() {
|
|||||||
if(m_dev_sample_rate_isSet){
|
if(m_dev_sample_rate_isSet){
|
||||||
obj->insert("devSampleRate", QJsonValue(dev_sample_rate));
|
obj->insert("devSampleRate", QJsonValue(dev_sample_rate));
|
||||||
}
|
}
|
||||||
|
if(m_lo_offset_isSet){
|
||||||
|
obj->insert("loOffset", QJsonValue(lo_offset));
|
||||||
|
}
|
||||||
if(m_log2_soft_interp_isSet){
|
if(m_log2_soft_interp_isSet){
|
||||||
obj->insert("log2SoftInterp", QJsonValue(log2_soft_interp));
|
obj->insert("log2SoftInterp", QJsonValue(log2_soft_interp));
|
||||||
}
|
}
|
||||||
@ -229,6 +239,16 @@ SWGUSRPOutputSettings::setDevSampleRate(qint32 dev_sample_rate) {
|
|||||||
this->m_dev_sample_rate_isSet = true;
|
this->m_dev_sample_rate_isSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint32
|
||||||
|
SWGUSRPOutputSettings::getLoOffset() {
|
||||||
|
return lo_offset;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWGUSRPOutputSettings::setLoOffset(qint32 lo_offset) {
|
||||||
|
this->lo_offset = lo_offset;
|
||||||
|
this->m_lo_offset_isSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
qint32
|
qint32
|
||||||
SWGUSRPOutputSettings::getLog2SoftInterp() {
|
SWGUSRPOutputSettings::getLog2SoftInterp() {
|
||||||
return log2_soft_interp;
|
return log2_soft_interp;
|
||||||
@ -350,6 +370,9 @@ SWGUSRPOutputSettings::isSet(){
|
|||||||
if(m_dev_sample_rate_isSet){
|
if(m_dev_sample_rate_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
if(m_lo_offset_isSet){
|
||||||
|
isObjectUpdated = true; break;
|
||||||
|
}
|
||||||
if(m_log2_soft_interp_isSet){
|
if(m_log2_soft_interp_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,9 @@ public:
|
|||||||
qint32 getDevSampleRate();
|
qint32 getDevSampleRate();
|
||||||
void setDevSampleRate(qint32 dev_sample_rate);
|
void setDevSampleRate(qint32 dev_sample_rate);
|
||||||
|
|
||||||
|
qint32 getLoOffset();
|
||||||
|
void setLoOffset(qint32 lo_offset);
|
||||||
|
|
||||||
qint32 getLog2SoftInterp();
|
qint32 getLog2SoftInterp();
|
||||||
void setLog2SoftInterp(qint32 log2_soft_interp);
|
void setLog2SoftInterp(qint32 log2_soft_interp);
|
||||||
|
|
||||||
@ -91,6 +94,9 @@ private:
|
|||||||
qint32 dev_sample_rate;
|
qint32 dev_sample_rate;
|
||||||
bool m_dev_sample_rate_isSet;
|
bool m_dev_sample_rate_isSet;
|
||||||
|
|
||||||
|
qint32 lo_offset;
|
||||||
|
bool m_lo_offset_isSet;
|
||||||
|
|
||||||
qint32 log2_soft_interp;
|
qint32 log2_soft_interp;
|
||||||
bool m_log2_soft_interp_isSet;
|
bool m_log2_soft_interp_isSet;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user