kopia lustrzana https://github.com/f4exb/sdrangel
SoapySDR support: input: center frequency and sample rate handling
rodzic
5acac7b9fa
commit
ea98f2e1c9
|
@ -31,6 +31,42 @@ DeviceSoapySDRParams::DeviceSoapySDRParams(SoapySDR::Device *device) :
|
|||
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()
|
||||
{
|
||||
m_deviceSettingsArgs = m_device->getSettingInfo();
|
||||
|
|
|
@ -86,6 +86,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
std::string getRxChannelMainTunableElementName(uint32_t index);
|
||||
std::string getTxChannelMainTunableElementName(uint32_t index);
|
||||
|
||||
private:
|
||||
void fillParams();
|
||||
void fillChannelParams(std::vector<ChannelSettings>& channelSettings, int direction, unsigned int ichan);
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include "devicesoapysdrshared.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(DeviceSoapySDRShared::MsgReportBuddyChange, Message)
|
||||
|
||||
DeviceSoapySDRShared::DeviceSoapySDRShared() :
|
||||
m_device(0),
|
||||
m_channel(-1),
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <SoapySDR/Device.hpp>
|
||||
|
||||
#include "util/message.h"
|
||||
#include "export.h"
|
||||
#include "devicesoapysdrparams.h"
|
||||
|
||||
|
@ -31,6 +32,53 @@ class SoapySDROutput;
|
|||
class DEVICES_API DeviceSoapySDRShared
|
||||
{
|
||||
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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
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,
|
||||
settings.m_devSampleRate);
|
||||
|
||||
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency))
|
||||
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency, settings.m_LOppmTenths))
|
||||
{
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
|
@ -846,7 +846,7 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo
|
|||
|
||||
if (dev != 0)
|
||||
{
|
||||
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency))
|
||||
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency, settings.m_LOppmTenths))
|
||||
{
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
|
|
|
@ -192,7 +192,7 @@ private:
|
|||
BladeRF2InputThread *findThread();
|
||||
void moveThreadToBuddy();
|
||||
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 webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
||||
};
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "util/simpleserializer.h"
|
||||
|
||||
#include "device/devicesourceapi.h"
|
||||
|
@ -26,17 +28,27 @@
|
|||
#include "soapysdrinputthread.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) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_thread(0),
|
||||
m_settings(),
|
||||
m_deviceDescription("SoapySDRInput"),
|
||||
m_running(false)
|
||||
m_running(false),
|
||||
m_thread(0)
|
||||
{
|
||||
openDevice();
|
||||
|
||||
m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
|
||||
m_deviceAPI->addSink(m_fileSink);
|
||||
}
|
||||
|
||||
SoapySDRInput::~SoapySDRInput()
|
||||
{
|
||||
m_deviceAPI->removeSink(m_fileSink);
|
||||
delete m_fileSink;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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)))
|
||||
{
|
||||
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 SoapySDRInputThread;
|
||||
class FileRecord;
|
||||
|
||||
namespace SoapySDR
|
||||
{
|
||||
class Device;
|
||||
}
|
||||
|
||||
class SoapySDRInput : public DeviceSampleSource
|
||||
{
|
||||
|
@ -119,14 +125,20 @@ public:
|
|||
|
||||
private:
|
||||
DeviceSourceAPI *m_deviceAPI;
|
||||
DeviceSoapySDRShared m_deviceShared;
|
||||
SoapySDRInputThread *m_thread;
|
||||
QMutex m_mutex;
|
||||
SoapySDRInputSettings m_settings;
|
||||
QString m_deviceDescription;
|
||||
bool m_running;
|
||||
SoapySDRInputThread *m_thread;
|
||||
DeviceSoapySDRShared m_deviceShared;
|
||||
FileRecord *m_fileSink; //!< File sink to record device I/Q output
|
||||
|
||||
bool openDevice();
|
||||
void closeDevice();
|
||||
SoapySDRInputThread *findThread();
|
||||
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);
|
||||
|
||||
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()
|
||||
|
@ -170,17 +181,59 @@ bool SoapySDRInputGui::deserialize(const QByteArray& data __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)
|
||||
{
|
||||
qDebug("SoapySDRInputGui::sampleRateChanged: %lf", sampleRate);
|
||||
m_settings.m_devSampleRate = sampleRate;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -227,6 +280,13 @@ void SoapySDRInputGui::on_transverter_clicked()
|
|||
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)
|
||||
{
|
||||
if (m_doApplySettings)
|
||||
|
@ -261,6 +321,9 @@ void SoapySDRInputGui::displaySettings()
|
|||
ui->decim->setCurrentIndex(m_settings.m_log2Decim);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,9 @@ private:
|
|||
void blockApplySettings(bool block);
|
||||
|
||||
private slots:
|
||||
void handleInputMessages();
|
||||
void on_centerFrequency_changed(quint64 value);
|
||||
void on_LOppm_valueChanged(int value);
|
||||
void sampleRateChanged(double sampleRate);
|
||||
void on_dcOffset_toggled(bool checked);
|
||||
void on_iqImbalance_toggled(bool checked);
|
||||
|
|
|
@ -167,7 +167,7 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_common">
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
|
@ -319,6 +319,52 @@
|
|||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
<widget class="Line" name="line_freq">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -57,6 +57,10 @@ SoapySDRInputThread::~SoapySDRInputThread()
|
|||
|
||||
void SoapySDRInputThread::startWork()
|
||||
{
|
||||
if (m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_startWaitMutex.lock();
|
||||
start();
|
||||
|
||||
|
@ -69,6 +73,10 @@ void SoapySDRInputThread::startWork()
|
|||
|
||||
void SoapySDRInputThread::stopWork()
|
||||
{
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_running = false;
|
||||
wait();
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue