mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-08-15 04:02:25 -04:00
SoapySDR support: input: center frequency and sample rate handling
This commit is contained in:
parent
5acac7b9fa
commit
ea98f2e1c9
@ -31,6 +31,42 @@ DeviceSoapySDRParams::DeviceSoapySDRParams(SoapySDR::Device *device) :
|
|||||||
DeviceSoapySDRParams::~DeviceSoapySDRParams()
|
DeviceSoapySDRParams::~DeviceSoapySDRParams()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
std::string DeviceSoapySDRParams::getRxChannelMainTunableElementName(uint32_t index)
|
||||||
|
{
|
||||||
|
if (index < m_nbRx)
|
||||||
|
{
|
||||||
|
return std::string("RF");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ChannelSettings& channelSettings = m_RxChannelsSettings[index];
|
||||||
|
|
||||||
|
if (channelSettings.m_frequencySettings.size() > 0) {
|
||||||
|
return channelSettings.m_frequencySettings.front().m_name;
|
||||||
|
} else {
|
||||||
|
return std::string("RF");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DeviceSoapySDRParams::getTxChannelMainTunableElementName(uint32_t index)
|
||||||
|
{
|
||||||
|
if (index < m_nbRx)
|
||||||
|
{
|
||||||
|
return std::string("RF");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ChannelSettings& channelSettings = m_RxChannelsSettings[index];
|
||||||
|
|
||||||
|
if (channelSettings.m_frequencySettings.size() > 0) {
|
||||||
|
return channelSettings.m_frequencySettings.front().m_name;
|
||||||
|
} else {
|
||||||
|
return std::string("RF");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceSoapySDRParams::fillParams()
|
void DeviceSoapySDRParams::fillParams()
|
||||||
{
|
{
|
||||||
m_deviceSettingsArgs = m_device->getSettingInfo();
|
m_deviceSettingsArgs = m_device->getSettingInfo();
|
||||||
|
@ -86,6 +86,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getRxChannelMainTunableElementName(uint32_t index);
|
||||||
|
std::string getTxChannelMainTunableElementName(uint32_t index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void fillParams();
|
void fillParams();
|
||||||
void fillChannelParams(std::vector<ChannelSettings>& channelSettings, int direction, unsigned int ichan);
|
void fillChannelParams(std::vector<ChannelSettings>& channelSettings, int direction, unsigned int ichan);
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#include "devicesoapysdrshared.h"
|
#include "devicesoapysdrshared.h"
|
||||||
|
|
||||||
|
MESSAGE_CLASS_DEFINITION(DeviceSoapySDRShared::MsgReportBuddyChange, Message)
|
||||||
|
|
||||||
DeviceSoapySDRShared::DeviceSoapySDRShared() :
|
DeviceSoapySDRShared::DeviceSoapySDRShared() :
|
||||||
m_device(0),
|
m_device(0),
|
||||||
m_channel(-1),
|
m_channel(-1),
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <SoapySDR/Device.hpp>
|
#include <SoapySDR/Device.hpp>
|
||||||
|
|
||||||
|
#include "util/message.h"
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
#include "devicesoapysdrparams.h"
|
#include "devicesoapysdrparams.h"
|
||||||
|
|
||||||
@ -31,6 +32,53 @@ class SoapySDROutput;
|
|||||||
class DEVICES_API DeviceSoapySDRShared
|
class DEVICES_API DeviceSoapySDRShared
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
class MsgReportBuddyChange : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint64_t getCenterFrequency() const { return m_centerFrequency; }
|
||||||
|
int getLOppmTenths() const { return m_LOppmTenths; }
|
||||||
|
int getFcPos() const { return m_fcPos; }
|
||||||
|
int getDevSampleRate() const { return m_devSampleRate; }
|
||||||
|
bool getRxElseTx() const { return m_rxElseTx; }
|
||||||
|
|
||||||
|
static MsgReportBuddyChange* create(
|
||||||
|
uint64_t centerFrequency,
|
||||||
|
int LOppmTenths,
|
||||||
|
int fcPos,
|
||||||
|
int devSampleRate,
|
||||||
|
bool rxElseTx)
|
||||||
|
{
|
||||||
|
return new MsgReportBuddyChange(
|
||||||
|
centerFrequency,
|
||||||
|
LOppmTenths,
|
||||||
|
fcPos,
|
||||||
|
devSampleRate,
|
||||||
|
rxElseTx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t m_centerFrequency; //!< Center frequency
|
||||||
|
int m_LOppmTenths; //!< LO soft correction in tenths of ppm
|
||||||
|
int m_fcPos; //!< Center frequency position
|
||||||
|
int m_devSampleRate; //!< device/host sample rate
|
||||||
|
bool m_rxElseTx; //!< tells which side initiated the message
|
||||||
|
|
||||||
|
MsgReportBuddyChange(
|
||||||
|
uint64_t centerFrequency,
|
||||||
|
int LOppmTenths,
|
||||||
|
int fcPos,
|
||||||
|
int devSampleRate,
|
||||||
|
bool rxElseTx) :
|
||||||
|
Message(),
|
||||||
|
m_centerFrequency(centerFrequency),
|
||||||
|
m_LOppmTenths(LOppmTenths),
|
||||||
|
m_fcPos(fcPos),
|
||||||
|
m_devSampleRate(devSampleRate),
|
||||||
|
m_rxElseTx(rxElseTx)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
DeviceSoapySDRShared();
|
DeviceSoapySDRShared();
|
||||||
~DeviceSoapySDRShared();
|
~DeviceSoapySDRShared();
|
||||||
|
|
||||||
|
@ -538,9 +538,9 @@ void BladeRF2Input::setCenterFrequency(qint64 centerFrequency)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BladeRF2Input::setDeviceCenterFrequency(struct bladerf *dev, int requestedChannel, quint64 freq_hz)
|
bool BladeRF2Input::setDeviceCenterFrequency(struct bladerf *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths)
|
||||||
{
|
{
|
||||||
qint64 df = ((qint64)freq_hz * m_settings.m_LOppmTenths) / 10000000LL;
|
qint64 df = ((qint64)freq_hz * loPpmTenths) / 10000000LL;
|
||||||
freq_hz += df;
|
freq_hz += df;
|
||||||
|
|
||||||
int status = bladerf_set_frequency(dev, BLADERF_CHANNEL_RX(requestedChannel), freq_hz);
|
int status = bladerf_set_frequency(dev, BLADERF_CHANNEL_RX(requestedChannel), freq_hz);
|
||||||
@ -661,7 +661,7 @@ bool BladeRF2Input::handleMessage(const Message& message)
|
|||||||
(DeviceSampleSource::fcPos_t) settings.m_fcPos,
|
(DeviceSampleSource::fcPos_t) settings.m_fcPos,
|
||||||
settings.m_devSampleRate);
|
settings.m_devSampleRate);
|
||||||
|
|
||||||
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency))
|
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency, settings.m_LOppmTenths))
|
||||||
{
|
{
|
||||||
if (getMessageQueueToGUI())
|
if (getMessageQueueToGUI())
|
||||||
{
|
{
|
||||||
@ -846,7 +846,7 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo
|
|||||||
|
|
||||||
if (dev != 0)
|
if (dev != 0)
|
||||||
{
|
{
|
||||||
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency))
|
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency, settings.m_LOppmTenths))
|
||||||
{
|
{
|
||||||
if (getMessageQueueToGUI())
|
if (getMessageQueueToGUI())
|
||||||
{
|
{
|
||||||
|
@ -192,7 +192,7 @@ private:
|
|||||||
BladeRF2InputThread *findThread();
|
BladeRF2InputThread *findThread();
|
||||||
void moveThreadToBuddy();
|
void moveThreadToBuddy();
|
||||||
bool applySettings(const BladeRF2InputSettings& settings, bool force = false);
|
bool applySettings(const BladeRF2InputSettings& settings, bool force = false);
|
||||||
bool setDeviceCenterFrequency(struct bladerf *dev, int requestedChannel, quint64 freq_hz);
|
bool setDeviceCenterFrequency(struct bladerf *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths);
|
||||||
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const BladeRF2InputSettings& settings);
|
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const BladeRF2InputSettings& settings);
|
||||||
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
||||||
};
|
};
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "util/simpleserializer.h"
|
#include "util/simpleserializer.h"
|
||||||
|
|
||||||
#include "device/devicesourceapi.h"
|
#include "device/devicesourceapi.h"
|
||||||
@ -26,17 +28,27 @@
|
|||||||
#include "soapysdrinputthread.h"
|
#include "soapysdrinputthread.h"
|
||||||
#include "soapysdrinput.h"
|
#include "soapysdrinput.h"
|
||||||
|
|
||||||
|
MESSAGE_CLASS_DEFINITION(SoapySDRInput::MsgConfigureSoapySDRInput, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(SoapySDRInput::MsgFileRecord, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(SoapySDRInput::MsgStartStop, Message)
|
||||||
|
|
||||||
SoapySDRInput::SoapySDRInput(DeviceSourceAPI *deviceAPI) :
|
SoapySDRInput::SoapySDRInput(DeviceSourceAPI *deviceAPI) :
|
||||||
m_deviceAPI(deviceAPI),
|
m_deviceAPI(deviceAPI),
|
||||||
m_thread(0),
|
m_settings(),
|
||||||
m_deviceDescription("SoapySDRInput"),
|
m_deviceDescription("SoapySDRInput"),
|
||||||
m_running(false)
|
m_running(false),
|
||||||
|
m_thread(0)
|
||||||
{
|
{
|
||||||
openDevice();
|
openDevice();
|
||||||
|
|
||||||
|
m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
|
||||||
|
m_deviceAPI->addSink(m_fileSink);
|
||||||
}
|
}
|
||||||
|
|
||||||
SoapySDRInput::~SoapySDRInput()
|
SoapySDRInput::~SoapySDRInput()
|
||||||
{
|
{
|
||||||
|
m_deviceAPI->removeSink(m_fileSink);
|
||||||
|
delete m_fileSink;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoapySDRInput::destroy()
|
void SoapySDRInput::destroy()
|
||||||
@ -195,6 +207,38 @@ void SoapySDRInput::init()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SoapySDRInputThread *SoapySDRInput::findThread()
|
||||||
|
{
|
||||||
|
if (m_thread == 0) // this does not own the thread
|
||||||
|
{
|
||||||
|
SoapySDRInputThread *soapySDRInputThread = 0;
|
||||||
|
|
||||||
|
// find a buddy that has allocated the thread
|
||||||
|
const std::vector<DeviceSourceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
|
||||||
|
std::vector<DeviceSourceAPI*>::const_iterator it = sourceBuddies.begin();
|
||||||
|
|
||||||
|
for (; it != sourceBuddies.end(); ++it)
|
||||||
|
{
|
||||||
|
SoapySDRInput *buddySource = ((DeviceSoapySDRShared*) (*it)->getBuddySharedPtr())->m_source;
|
||||||
|
|
||||||
|
if (buddySource)
|
||||||
|
{
|
||||||
|
soapySDRInputThread = buddySource->getThread();
|
||||||
|
|
||||||
|
if (soapySDRInputThread) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return soapySDRInputThread;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_thread; // own thread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SoapySDRInput::moveThreadToBuddy()
|
void SoapySDRInput::moveThreadToBuddy()
|
||||||
{
|
{
|
||||||
const std::vector<DeviceSourceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
|
const std::vector<DeviceSourceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
|
||||||
@ -251,7 +295,256 @@ void SoapySDRInput::setCenterFrequency(qint64 centerFrequency __attribute__((unu
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SoapySDRInput::setDeviceCenterFrequency(SoapySDR::Device *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths)
|
||||||
|
{
|
||||||
|
qint64 df = ((qint64)freq_hz * loPpmTenths) / 10000000LL;
|
||||||
|
freq_hz += df;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dev->setFrequency(SOAPY_SDR_RX,
|
||||||
|
requestedChannel,
|
||||||
|
m_deviceShared.m_deviceParams->getRxChannelMainTunableElementName(requestedChannel),
|
||||||
|
freq_hz);
|
||||||
|
qDebug("SoapySDRInput::setDeviceCenterFrequency: setFrequency(%llu)", freq_hz);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (const std::exception &ex)
|
||||||
|
{
|
||||||
|
qCritical("SoapySDRInput::applySettings: could not set frequency: %llu: %s", freq_hz, ex.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool SoapySDRInput::handleMessage(const Message& message __attribute__((unused)))
|
bool SoapySDRInput::handleMessage(const Message& message __attribute__((unused)))
|
||||||
{
|
{
|
||||||
return false;
|
if (MsgConfigureSoapySDRInput::match(message))
|
||||||
|
{
|
||||||
|
MsgConfigureSoapySDRInput& conf = (MsgConfigureSoapySDRInput&) message;
|
||||||
|
qDebug() << "SoapySDRInput::handleMessage: MsgConfigureSoapySDRInput";
|
||||||
|
|
||||||
|
if (!applySettings(conf.getSettings(), conf.getForce())) {
|
||||||
|
qDebug("SoapySDRInput::handleMessage: MsgConfigureSoapySDRInput config error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (MsgFileRecord::match(message))
|
||||||
|
{
|
||||||
|
MsgFileRecord& conf = (MsgFileRecord&) message;
|
||||||
|
qDebug() << "SoapySDRInput::handleMessage: MsgFileRecord: " << conf.getStartStop();
|
||||||
|
|
||||||
|
if (conf.getStartStop())
|
||||||
|
{
|
||||||
|
if (m_settings.m_fileRecordName.size() != 0) {
|
||||||
|
m_fileSink->setFileName(m_settings.m_fileRecordName);
|
||||||
|
} else {
|
||||||
|
m_fileSink->genUniqueFileName(m_deviceAPI->getDeviceUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fileSink->startRecording();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_fileSink->stopRecording();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (MsgStartStop::match(message))
|
||||||
|
{
|
||||||
|
MsgStartStop& cmd = (MsgStartStop&) message;
|
||||||
|
qDebug() << "SoapySDRInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
|
||||||
|
|
||||||
|
if (cmd.getStartStop())
|
||||||
|
{
|
||||||
|
if (m_deviceAPI->initAcquisition())
|
||||||
|
{
|
||||||
|
m_deviceAPI->startAcquisition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_deviceAPI->stopAcquisition();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (DeviceSoapySDRShared::MsgReportBuddyChange::match(message))
|
||||||
|
{
|
||||||
|
int requestedChannel = m_deviceAPI->getItemIndex();
|
||||||
|
DeviceSoapySDRShared::MsgReportBuddyChange& report = (DeviceSoapySDRShared::MsgReportBuddyChange&) message;
|
||||||
|
SoapySDRInputSettings settings = m_settings;
|
||||||
|
settings.m_fcPos = (SoapySDRInputSettings::fcPos_t) report.getFcPos();
|
||||||
|
|
||||||
|
settings.m_centerFrequency = m_deviceShared.m_device->getFrequency(
|
||||||
|
SOAPY_SDR_RX,
|
||||||
|
requestedChannel,
|
||||||
|
m_deviceShared.m_deviceParams->getRxChannelMainTunableElementName(requestedChannel));
|
||||||
|
|
||||||
|
settings.m_devSampleRate = m_deviceShared.m_device->getSampleRate(SOAPY_SDR_RX, requestedChannel);
|
||||||
|
|
||||||
|
SoapySDRInputThread *inputThread = findThread();
|
||||||
|
|
||||||
|
if (inputThread)
|
||||||
|
{
|
||||||
|
inputThread->setFcPos(requestedChannel, (int) settings.m_fcPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_settings = settings;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool force)
|
||||||
|
{
|
||||||
|
bool forwardChangeOwnDSP = false;
|
||||||
|
bool forwardChangeToBuddies = false;
|
||||||
|
|
||||||
|
SoapySDR::Device *dev = m_deviceShared.m_device;
|
||||||
|
SoapySDRInputThread *inputThread = findThread();
|
||||||
|
int requestedChannel = m_deviceAPI->getItemIndex();
|
||||||
|
qint64 xlatedDeviceCenterFrequency = settings.m_centerFrequency;
|
||||||
|
xlatedDeviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0;
|
||||||
|
xlatedDeviceCenterFrequency = xlatedDeviceCenterFrequency < 0 ? 0 : xlatedDeviceCenterFrequency;
|
||||||
|
|
||||||
|
if ((m_settings.m_dcBlock != settings.m_dcBlock) ||
|
||||||
|
(m_settings.m_iqCorrection != settings.m_iqCorrection) || force)
|
||||||
|
{
|
||||||
|
m_deviceAPI->configureCorrections(settings.m_dcBlock, settings.m_iqCorrection);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force)
|
||||||
|
{
|
||||||
|
forwardChangeOwnDSP = true;
|
||||||
|
forwardChangeToBuddies = true;
|
||||||
|
|
||||||
|
if (dev != 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dev->setSampleRate(SOAPY_SDR_RX, requestedChannel, settings.m_devSampleRate);
|
||||||
|
qDebug() << "SoapySDRInput::applySettings: setSampleRate OK: " << settings.m_devSampleRate;
|
||||||
|
|
||||||
|
if (inputThread)
|
||||||
|
{
|
||||||
|
bool wasRunning = inputThread->isRunning();
|
||||||
|
inputThread->stopWork();
|
||||||
|
inputThread->setSampleRate(settings.m_devSampleRate);
|
||||||
|
|
||||||
|
if (wasRunning) {
|
||||||
|
inputThread->startWork();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &ex)
|
||||||
|
{
|
||||||
|
qCritical("SoapySDRInput::applySettings: could not set sample rate: %d: %s",
|
||||||
|
settings.m_devSampleRate, ex.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.m_fcPos != settings.m_fcPos) || force)
|
||||||
|
{
|
||||||
|
SoapySDRInputThread *inputThread = findThread();
|
||||||
|
|
||||||
|
if (inputThread != 0)
|
||||||
|
{
|
||||||
|
inputThread->setFcPos(requestedChannel, (int) settings.m_fcPos);
|
||||||
|
qDebug() << "SoapySDRInput::applySettings: set fc pos (enum) to " << (int) settings.m_fcPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.m_log2Decim != settings.m_log2Decim) || force)
|
||||||
|
{
|
||||||
|
forwardChangeOwnDSP = true;
|
||||||
|
SoapySDRInputThread *inputThread = findThread();
|
||||||
|
|
||||||
|
if (inputThread != 0)
|
||||||
|
{
|
||||||
|
inputThread->setLog2Decimation(requestedChannel, settings.m_log2Decim);
|
||||||
|
qDebug() << "SoapySDRInput::applySettings: set decimation to " << (1<<settings.m_log2Decim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.m_centerFrequency != settings.m_centerFrequency)
|
||||||
|
|| (m_settings.m_transverterMode != settings.m_transverterMode)
|
||||||
|
|| (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency)
|
||||||
|
|| (m_settings.m_LOppmTenths != settings.m_LOppmTenths)
|
||||||
|
|| (m_settings.m_devSampleRate != settings.m_devSampleRate)
|
||||||
|
|| (m_settings.m_fcPos != settings.m_fcPos)
|
||||||
|
|| (m_settings.m_log2Decim != settings.m_log2Decim) || force)
|
||||||
|
{
|
||||||
|
qint64 deviceCenterFrequency = DeviceSampleSource::calculateDeviceCenterFrequency(
|
||||||
|
xlatedDeviceCenterFrequency,
|
||||||
|
0,
|
||||||
|
settings.m_log2Decim,
|
||||||
|
(DeviceSampleSource::fcPos_t) settings.m_fcPos,
|
||||||
|
settings.m_devSampleRate);
|
||||||
|
|
||||||
|
forwardChangeOwnDSP = true;
|
||||||
|
forwardChangeToBuddies = true;
|
||||||
|
|
||||||
|
if (dev != 0) {
|
||||||
|
setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency, settings.m_LOppmTenths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forwardChangeOwnDSP)
|
||||||
|
{
|
||||||
|
int sampleRate = settings.m_devSampleRate/(1<<settings.m_log2Decim);
|
||||||
|
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, settings.m_centerFrequency);
|
||||||
|
m_fileSink->handleMessage(*notif); // forward to file sink
|
||||||
|
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forwardChangeToBuddies)
|
||||||
|
{
|
||||||
|
// send to source buddies
|
||||||
|
const std::vector<DeviceSourceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
|
||||||
|
const std::vector<DeviceSinkAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
|
||||||
|
|
||||||
|
for (const auto &itSource : sourceBuddies)
|
||||||
|
{
|
||||||
|
DeviceSoapySDRShared::MsgReportBuddyChange *report = DeviceSoapySDRShared::MsgReportBuddyChange::create(
|
||||||
|
settings.m_centerFrequency,
|
||||||
|
settings.m_LOppmTenths,
|
||||||
|
(int) settings.m_fcPos,
|
||||||
|
settings.m_devSampleRate,
|
||||||
|
true);
|
||||||
|
itSource->getSampleSourceInputMessageQueue()->push(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &itSink : sinkBuddies)
|
||||||
|
{
|
||||||
|
DeviceSoapySDRShared::MsgReportBuddyChange *report = DeviceSoapySDRShared::MsgReportBuddyChange::create(
|
||||||
|
settings.m_centerFrequency,
|
||||||
|
settings.m_LOppmTenths,
|
||||||
|
(int) settings.m_fcPos,
|
||||||
|
settings.m_devSampleRate,
|
||||||
|
true);
|
||||||
|
itSink->getSampleSinkInputMessageQueue()->push(report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_settings = settings;
|
||||||
|
|
||||||
|
qDebug() << "SoapySDRInput::applySettings: "
|
||||||
|
<< " m_transverterMode: " << m_settings.m_transverterMode
|
||||||
|
<< " m_transverterDeltaFrequency: " << m_settings.m_transverterDeltaFrequency
|
||||||
|
<< " m_centerFrequency: " << m_settings.m_centerFrequency << " Hz"
|
||||||
|
<< " m_LOppmTenths: " << m_settings.m_LOppmTenths
|
||||||
|
<< " m_log2Decim: " << m_settings.m_log2Decim
|
||||||
|
<< " m_fcPos: " << m_settings.m_fcPos
|
||||||
|
<< " m_devSampleRate: " << m_settings.m_devSampleRate
|
||||||
|
<< " m_dcBlock: " << m_settings.m_dcBlock
|
||||||
|
<< " m_iqCorrection: " << m_settings.m_iqCorrection;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,12 @@
|
|||||||
|
|
||||||
class DeviceSourceAPI;
|
class DeviceSourceAPI;
|
||||||
class SoapySDRInputThread;
|
class SoapySDRInputThread;
|
||||||
|
class FileRecord;
|
||||||
|
|
||||||
|
namespace SoapySDR
|
||||||
|
{
|
||||||
|
class Device;
|
||||||
|
}
|
||||||
|
|
||||||
class SoapySDRInput : public DeviceSampleSource
|
class SoapySDRInput : public DeviceSampleSource
|
||||||
{
|
{
|
||||||
@ -119,14 +125,20 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceSourceAPI *m_deviceAPI;
|
DeviceSourceAPI *m_deviceAPI;
|
||||||
DeviceSoapySDRShared m_deviceShared;
|
QMutex m_mutex;
|
||||||
SoapySDRInputThread *m_thread;
|
SoapySDRInputSettings m_settings;
|
||||||
QString m_deviceDescription;
|
QString m_deviceDescription;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
|
SoapySDRInputThread *m_thread;
|
||||||
|
DeviceSoapySDRShared m_deviceShared;
|
||||||
|
FileRecord *m_fileSink; //!< File sink to record device I/Q output
|
||||||
|
|
||||||
bool openDevice();
|
bool openDevice();
|
||||||
void closeDevice();
|
void closeDevice();
|
||||||
|
SoapySDRInputThread *findThread();
|
||||||
void moveThreadToBuddy();
|
void moveThreadToBuddy();
|
||||||
|
bool applySettings(const SoapySDRInputSettings& settings, bool force = false);
|
||||||
|
bool setDeviceCenterFrequency(SoapySDR::Device *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,6 +49,17 @@ SoapySDRInputGui::SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
|||||||
ui->centerFrequency->setValueRange(7, f_min/1000, f_max/1000);
|
ui->centerFrequency->setValueRange(7, f_min/1000, f_max/1000);
|
||||||
|
|
||||||
createRangesControl(m_sampleSource->getRateRanges(), "SR", "kS/s");
|
createRangesControl(m_sampleSource->getRateRanges(), "SR", "kS/s");
|
||||||
|
|
||||||
|
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
||||||
|
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||||
|
m_statusTimer.start(500);
|
||||||
|
|
||||||
|
displaySettings();
|
||||||
|
|
||||||
|
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
|
||||||
|
m_sampleSource->setMessageQueueToGUI(&m_inputMessageQueue);
|
||||||
|
|
||||||
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
SoapySDRInputGui::~SoapySDRInputGui()
|
SoapySDRInputGui::~SoapySDRInputGui()
|
||||||
@ -170,17 +181,59 @@ bool SoapySDRInputGui::deserialize(const QByteArray& data __attribute__((unused)
|
|||||||
|
|
||||||
bool SoapySDRInputGui::handleMessage(const Message& message __attribute__((unused)))
|
bool SoapySDRInputGui::handleMessage(const Message& message __attribute__((unused)))
|
||||||
{
|
{
|
||||||
return false;
|
if (SoapySDRInput::MsgStartStop::match(message))
|
||||||
|
{
|
||||||
|
SoapySDRInput::MsgStartStop& notif = (SoapySDRInput::MsgStartStop&) message;
|
||||||
|
blockApplySettings(true);
|
||||||
|
ui->startStop->setChecked(notif.getStartStop());
|
||||||
|
blockApplySettings(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoapySDRInputGui::handleInputMessages()
|
||||||
|
{
|
||||||
|
Message* message;
|
||||||
|
|
||||||
|
while ((message = m_inputMessageQueue.pop()) != 0)
|
||||||
|
{
|
||||||
|
qDebug("SoapySDRInputGui::handleInputMessages: message: %s", message->getIdentifier());
|
||||||
|
|
||||||
|
if (DSPSignalNotification::match(*message))
|
||||||
|
{
|
||||||
|
DSPSignalNotification* notif = (DSPSignalNotification*) message;
|
||||||
|
m_sampleRate = notif->getSampleRate();
|
||||||
|
m_deviceCenterFrequency = notif->getCenterFrequency();
|
||||||
|
qDebug("SoapySDRInputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
|
||||||
|
updateSampleRateAndFrequency();
|
||||||
|
|
||||||
|
delete message;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (handleMessage(*message))
|
||||||
|
{
|
||||||
|
delete message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoapySDRInputGui::sampleRateChanged(double sampleRate)
|
void SoapySDRInputGui::sampleRateChanged(double sampleRate)
|
||||||
{
|
{
|
||||||
qDebug("SoapySDRInputGui::sampleRateChanged: %lf", sampleRate);
|
m_settings.m_devSampleRate = sampleRate;
|
||||||
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoapySDRInputGui::on_centerFrequency_changed(quint64 value)
|
void SoapySDRInputGui::on_centerFrequency_changed(quint64 value)
|
||||||
{
|
{
|
||||||
qDebug("SoapySDRInputGui::on_centerFrequency_changed: %llu", value);
|
m_settings.m_centerFrequency = value * 1000;
|
||||||
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoapySDRInputGui::on_dcOffset_toggled(bool checked)
|
void SoapySDRInputGui::on_dcOffset_toggled(bool checked)
|
||||||
@ -227,6 +280,13 @@ void SoapySDRInputGui::on_transverter_clicked()
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoapySDRInputGui::on_LOppm_valueChanged(int value)
|
||||||
|
{
|
||||||
|
ui->LOppmText->setText(QString("%1").arg(QString::number(value/10.0, 'f', 1)));
|
||||||
|
m_settings.m_LOppmTenths = value;
|
||||||
|
sendSettings();
|
||||||
|
}
|
||||||
|
|
||||||
void SoapySDRInputGui::on_startStop_toggled(bool checked)
|
void SoapySDRInputGui::on_startStop_toggled(bool checked)
|
||||||
{
|
{
|
||||||
if (m_doApplySettings)
|
if (m_doApplySettings)
|
||||||
@ -261,6 +321,9 @@ void SoapySDRInputGui::displaySettings()
|
|||||||
ui->decim->setCurrentIndex(m_settings.m_log2Decim);
|
ui->decim->setCurrentIndex(m_settings.m_log2Decim);
|
||||||
ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos);
|
ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos);
|
||||||
|
|
||||||
|
ui->LOppm->setValue(m_settings.m_LOppmTenths);
|
||||||
|
ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1)));
|
||||||
|
|
||||||
blockApplySettings(false);
|
blockApplySettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,9 @@ private:
|
|||||||
void blockApplySettings(bool block);
|
void blockApplySettings(bool block);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void handleInputMessages();
|
||||||
void on_centerFrequency_changed(quint64 value);
|
void on_centerFrequency_changed(quint64 value);
|
||||||
|
void on_LOppm_valueChanged(int value);
|
||||||
void sampleRateChanged(double sampleRate);
|
void sampleRateChanged(double sampleRate);
|
||||||
void on_dcOffset_toggled(bool checked);
|
void on_dcOffset_toggled(bool checked);
|
||||||
void on_iqImbalance_toggled(bool checked);
|
void on_iqImbalance_toggled(bool checked);
|
||||||
|
@ -167,7 +167,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<layout class="QHBoxLayout" name="horizontalLayout_common">
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
@ -319,6 +319,52 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_ppm">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="LOppmLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>LO ppm</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="LOppm">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Local Oscillator software ppm correction</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-1000</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="LOppmText">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>-100.0</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_freq">
|
<widget class="Line" name="line_freq">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -57,6 +57,10 @@ SoapySDRInputThread::~SoapySDRInputThread()
|
|||||||
|
|
||||||
void SoapySDRInputThread::startWork()
|
void SoapySDRInputThread::startWork()
|
||||||
{
|
{
|
||||||
|
if (m_running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_startWaitMutex.lock();
|
m_startWaitMutex.lock();
|
||||||
start();
|
start();
|
||||||
|
|
||||||
@ -69,6 +73,10 @@ void SoapySDRInputThread::startWork()
|
|||||||
|
|
||||||
void SoapySDRInputThread::stopWork()
|
void SoapySDRInputThread::stopWork()
|
||||||
{
|
{
|
||||||
|
if (!m_running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_running = false;
|
m_running = false;
|
||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user