mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-28 18:58:48 -05:00
SoapySDR support: fixes
This commit is contained in:
parent
6a9607c8fc
commit
564a99d14e
3
debian/changelog
vendored
3
debian/changelog
vendored
@ -1,8 +1,9 @@
|
||||
sdrangel (4.3.0-1) unstable; urgency=medium
|
||||
|
||||
* SoapySDR support
|
||||
* BladeRF2 corrections
|
||||
|
||||
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 04 Nov 2018 21:14:18 +0200
|
||||
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 18 Nov 2018 21:14:18 +0100
|
||||
|
||||
sdrangel (4.2.4-1) unstable; urgency=medium
|
||||
|
||||
|
@ -520,9 +520,9 @@ void BladeRF2Output::setCenterFrequency(qint64 centerFrequency)
|
||||
}
|
||||
}
|
||||
|
||||
bool BladeRF2Output::setDeviceCenterFrequency(struct bladerf *dev, int requestedChannel, quint64 freq_hz)
|
||||
bool BladeRF2Output::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_TX(requestedChannel), freq_hz);
|
||||
@ -789,7 +789,7 @@ bool BladeRF2Output::applySettings(const BladeRF2OutputSettings& settings, bool
|
||||
|
||||
if (dev != 0)
|
||||
{
|
||||
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency))
|
||||
if (setDeviceCenterFrequency(dev, requestedChannel, deviceCenterFrequency, settings.m_LOppmTenths))
|
||||
{
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
|
@ -153,7 +153,7 @@ private:
|
||||
void moveThreadToBuddy();
|
||||
bool applySettings(const BladeRF2OutputSettings& settings, bool force);
|
||||
int getNbChannels();
|
||||
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 BladeRF2OutputSettings& settings);
|
||||
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
const PluginDescriptor BladeRF2OutputPlugin::m_pluginDescriptor = {
|
||||
QString("BladeRF2 Output"),
|
||||
QString("4.2.1"),
|
||||
QString("4.3.0"),
|
||||
QString("(c) Edouard Griffiths, F4EXB"),
|
||||
QString("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
|
@ -14,6 +14,8 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "util/simpleserializer.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "dsp/dspengine.h"
|
||||
@ -77,6 +79,7 @@ bool SoapySDROutput::openDevice()
|
||||
}
|
||||
|
||||
m_deviceShared.m_device = device;
|
||||
m_deviceShared.m_deviceParams = deviceSoapySDRShared->m_deviceParams;
|
||||
}
|
||||
// look for Rx buddies and get reference to the device object
|
||||
else if (m_deviceAPI->getSourceBuddies().size() > 0) // then source
|
||||
@ -101,6 +104,7 @@ bool SoapySDROutput::openDevice()
|
||||
}
|
||||
|
||||
m_deviceShared.m_device = device;
|
||||
m_deviceShared.m_deviceParams = deviceSoapySDRShared->m_deviceParams;
|
||||
}
|
||||
// There are no buddies then create the first BladeRF2 device
|
||||
else
|
||||
@ -114,6 +118,8 @@ bool SoapySDROutput::openDevice()
|
||||
qCritical("SoapySDROutput::openDevice: cannot open SoapySDR device");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_deviceShared.m_deviceParams = new DeviceSoapySDRParams(m_deviceShared.m_device);
|
||||
}
|
||||
|
||||
m_deviceShared.m_channel = m_deviceAPI->getItemIndex(); // publicly allocate channel
|
||||
@ -341,11 +347,10 @@ bool SoapySDROutput::start()
|
||||
if (needsStart)
|
||||
{
|
||||
qDebug("SoapySDROutput::start: (re)sart buddy thread");
|
||||
soapySDROutputThread->setSampleRate(m_settings.m_devSampleRate);
|
||||
soapySDROutputThread->startWork();
|
||||
}
|
||||
|
||||
applySettings(m_settings, true); // re-apply forcibly to set sample rate with the new number of channels
|
||||
|
||||
qDebug("SoapySDROutput::start: started");
|
||||
m_running = true;
|
||||
|
||||
@ -518,10 +523,206 @@ void SoapySDROutput::setCenterFrequency(qint64 centerFrequency)
|
||||
}
|
||||
}
|
||||
|
||||
bool SoapySDROutput::handleMessage(const Message& message __attribute__((unused)))
|
||||
bool SoapySDROutput::setDeviceCenterFrequency(SoapySDR::Device *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths)
|
||||
{
|
||||
return false;
|
||||
qint64 df = ((qint64)freq_hz * loPpmTenths) / 10000000LL;
|
||||
freq_hz += df;
|
||||
|
||||
try
|
||||
{
|
||||
dev->setFrequency(SOAPY_SDR_TX,
|
||||
requestedChannel,
|
||||
m_deviceShared.m_deviceParams->getTxChannelMainTunableElementName(requestedChannel),
|
||||
freq_hz);
|
||||
qDebug("SoapySDROutput::setDeviceCenterFrequency: setFrequency(%llu)", freq_hz);
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
qCritical("SoapySDROutput::applySettings: could not set frequency: %llu: %s", freq_hz, ex.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SoapySDROutput::handleMessage(const Message& message)
|
||||
{
|
||||
if (MsgConfigureSoapySDROutput::match(message))
|
||||
{
|
||||
MsgConfigureSoapySDROutput& conf = (MsgConfigureSoapySDROutput&) message;
|
||||
qDebug() << "SoapySDROutput::handleMessage: MsgConfigureSoapySDROutput";
|
||||
|
||||
if (!applySettings(conf.getSettings(), conf.getForce())) {
|
||||
qDebug("SoapySDROutput::handleMessage: MsgConfigureSoapySDROutput config error");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgStartStop::match(message))
|
||||
{
|
||||
MsgStartStop& cmd = (MsgStartStop&) message;
|
||||
qDebug() << "SoapySDROutput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
|
||||
|
||||
if (cmd.getStartStop())
|
||||
{
|
||||
if (m_deviceAPI->initGeneration())
|
||||
{
|
||||
m_deviceAPI->startGeneration();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_deviceAPI->stopGeneration();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DeviceSoapySDRShared::MsgReportBuddyChange::match(message))
|
||||
{
|
||||
int requestedChannel = m_deviceAPI->getItemIndex();
|
||||
//DeviceSoapySDRShared::MsgReportBuddyChange& report = (DeviceSoapySDRShared::MsgReportBuddyChange&) message;
|
||||
SoapySDROutputSettings settings = m_settings;
|
||||
//bool fromRxBuddy = report.getRxElseTx();
|
||||
|
||||
settings.m_centerFrequency = m_deviceShared.m_device->getFrequency(
|
||||
SOAPY_SDR_TX,
|
||||
requestedChannel,
|
||||
m_deviceShared.m_deviceParams->getTxChannelMainTunableElementName(requestedChannel));
|
||||
|
||||
settings.m_devSampleRate = m_deviceShared.m_device->getSampleRate(SOAPY_SDR_TX, requestedChannel);
|
||||
|
||||
//SoapySDROutputThread *outputThread = findThread();
|
||||
|
||||
m_settings = settings;
|
||||
|
||||
// propagate settings to GUI if any
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgConfigureSoapySDROutput *reportToGUI = MsgConfigureSoapySDROutput::create(m_settings, false);
|
||||
getMessageQueueToGUI()->push(reportToGUI);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool force)
|
||||
{
|
||||
bool forwardChangeOwnDSP = false;
|
||||
bool forwardChangeToBuddies = false;
|
||||
|
||||
SoapySDR::Device *dev = m_deviceShared.m_device;
|
||||
SoapySDROutputThread *outputThread = 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_devSampleRate != settings.m_devSampleRate) || force)
|
||||
{
|
||||
forwardChangeOwnDSP = true;
|
||||
forwardChangeToBuddies = true;
|
||||
|
||||
if (dev != 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
dev->setSampleRate(SOAPY_SDR_TX, requestedChannel, settings.m_devSampleRate);
|
||||
qDebug() << "SoapySDROutput::applySettings: setSampleRate OK: " << settings.m_devSampleRate;
|
||||
|
||||
if (outputThread)
|
||||
{
|
||||
bool wasRunning = outputThread->isRunning();
|
||||
outputThread->stopWork();
|
||||
outputThread->setSampleRate(settings.m_devSampleRate);
|
||||
|
||||
if (wasRunning) {
|
||||
outputThread->startWork();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
qCritical("SoapySDROutput::applySettings: could not set sample rate: %d: %s",
|
||||
settings.m_devSampleRate, ex.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_settings.m_log2Interp != settings.m_log2Interp) || force)
|
||||
{
|
||||
forwardChangeOwnDSP = true;
|
||||
|
||||
if (outputThread != 0)
|
||||
{
|
||||
outputThread->setLog2Interpolation(requestedChannel, settings.m_log2Interp);
|
||||
qDebug() << "SoapySDROutput::applySettings: set decimation to " << (1<<settings.m_log2Interp);
|
||||
}
|
||||
}
|
||||
|
||||
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_log2Interp != settings.m_log2Interp) || force)
|
||||
{
|
||||
forwardChangeOwnDSP = true;
|
||||
forwardChangeToBuddies = true;
|
||||
|
||||
if (dev != 0) {
|
||||
setDeviceCenterFrequency(dev, requestedChannel, settings.m_centerFrequency, settings.m_LOppmTenths);
|
||||
}
|
||||
}
|
||||
|
||||
if (forwardChangeOwnDSP)
|
||||
{
|
||||
int sampleRate = settings.m_devSampleRate/(1<<settings.m_log2Interp);
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, settings.m_centerFrequency);
|
||||
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,
|
||||
2,
|
||||
settings.m_devSampleRate,
|
||||
false);
|
||||
itSource->getSampleSourceInputMessageQueue()->push(report);
|
||||
}
|
||||
|
||||
for (const auto &itSink : sinkBuddies)
|
||||
{
|
||||
DeviceSoapySDRShared::MsgReportBuddyChange *report = DeviceSoapySDRShared::MsgReportBuddyChange::create(
|
||||
settings.m_centerFrequency,
|
||||
settings.m_LOppmTenths,
|
||||
2,
|
||||
settings.m_devSampleRate,
|
||||
false);
|
||||
itSink->getSampleSinkInputMessageQueue()->push(report);
|
||||
}
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
|
||||
qDebug() << "SoapySDROutput::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_log2Interp: " << m_settings.m_log2Interp
|
||||
<< " m_devSampleRate: " << m_settings.m_devSampleRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ void SoapySDROutputThread::run()
|
||||
std::iota(channels.begin(), channels.end(), 0); // Fill with 0, 1, ..., m_nbChannels-1.
|
||||
|
||||
//initialize the sample rate for all channels
|
||||
qDebug("SoapySDROutputThread::run: m_sampleRate: %u", m_sampleRate);
|
||||
for (const auto &it : channels) {
|
||||
m_dev->setSampleRate(SOAPY_SDR_TX, it, m_sampleRate);
|
||||
}
|
||||
@ -144,20 +145,20 @@ void SoapySDROutputThread::run()
|
||||
|
||||
if (m_nbChannels > 1)
|
||||
{
|
||||
callbackMO(buffs, numElems*2); // size given in number of I or Q samples (2 items per sample)
|
||||
callbackMO(buffs, numElems); // size given in number of samples (1 item per sample)
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_interpolatorType)
|
||||
{
|
||||
case Interpolator8:
|
||||
callbackSO8((qint8*) buffs[0], numElems*2);
|
||||
callbackSO8((qint8*) buffs[0], numElems);
|
||||
break;
|
||||
case Interpolator12:
|
||||
callbackSO12((qint16*) buffs[0], numElems*2);
|
||||
callbackSO12((qint16*) buffs[0], numElems);
|
||||
break;
|
||||
case Interpolator16:
|
||||
callbackSO16((qint16*) buffs[0], numElems*2);
|
||||
callbackSO16((qint16*) buffs[0], numElems);
|
||||
break;
|
||||
case InterpolatorFloat:
|
||||
default:
|
||||
@ -230,21 +231,41 @@ void SoapySDROutputThread::callbackMO(std::vector<void *>& buffs, qint32 samples
|
||||
{
|
||||
for(unsigned int ichan = 0; ichan < m_nbChannels; ichan++)
|
||||
{
|
||||
switch (m_interpolatorType)
|
||||
if (m_channels[ichan].m_sampleFifo)
|
||||
{
|
||||
case Interpolator8:
|
||||
callbackSO8((qint8*) buffs[ichan], samplesPerChannel, ichan);
|
||||
break;
|
||||
case Interpolator12:
|
||||
callbackSO12((qint16*) buffs[ichan], samplesPerChannel, ichan);
|
||||
break;
|
||||
case Interpolator16:
|
||||
callbackSO16((qint16*) buffs[ichan], samplesPerChannel, ichan);
|
||||
break;
|
||||
case InterpolatorFloat:
|
||||
default:
|
||||
// TODO
|
||||
break;
|
||||
switch (m_interpolatorType)
|
||||
{
|
||||
case Interpolator8:
|
||||
callbackSO8((qint8*) buffs[ichan], samplesPerChannel, ichan);
|
||||
break;
|
||||
case Interpolator12:
|
||||
callbackSO12((qint16*) buffs[ichan], samplesPerChannel, ichan);
|
||||
break;
|
||||
case Interpolator16:
|
||||
callbackSO16((qint16*) buffs[ichan], samplesPerChannel, ichan);
|
||||
break;
|
||||
case InterpolatorFloat:
|
||||
default:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // no FIFO for this channel means channel is unused: fill with zeros
|
||||
{
|
||||
switch (m_interpolatorType)
|
||||
{
|
||||
case Interpolator8:
|
||||
std::fill((qint8*) buffs[ichan], (qint8*) buffs[ichan] + 2*samplesPerChannel, 0);
|
||||
break;
|
||||
case Interpolator12:
|
||||
case Interpolator16:
|
||||
std::fill((qint16*) buffs[ichan], (qint16*) buffs[ichan] + 2*samplesPerChannel, 0);
|
||||
break;
|
||||
case InterpolatorFloat:
|
||||
default:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
unsigned int getNbChannels() const { return m_nbChannels; }
|
||||
void setLog2Interpolation(unsigned int channel, unsigned int log2_interp);
|
||||
unsigned int getLog2Interpolation(unsigned int channel) const;
|
||||
void setSampleRate(unsigned int sampleRate) { m_sampleRate = sampleRate; }
|
||||
unsigned int getSampleRate() const { return m_sampleRate; }
|
||||
void setFifo(unsigned int channel, SampleSourceFifo *sampleFifo);
|
||||
SampleSourceFifo *getFifo(unsigned int channel);
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
const PluginDescriptor Blderf2InputPlugin::m_pluginDescriptor = {
|
||||
QString("BladeRF2 Input"),
|
||||
QString("4.2.1"),
|
||||
QString("4.3.0"),
|
||||
QString("(c) Edouard Griffiths, F4EXB"),
|
||||
QString("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
|
@ -372,11 +372,10 @@ bool SoapySDRInput::start()
|
||||
if (needsStart)
|
||||
{
|
||||
qDebug("SoapySDRInput::start: (re)sart buddy thread");
|
||||
soapySDRInputThread->setSampleRate(m_settings.m_devSampleRate);
|
||||
soapySDRInputThread->startWork();
|
||||
}
|
||||
|
||||
applySettings(m_settings, true);
|
||||
|
||||
qDebug("SoapySDRInput::start: started");
|
||||
m_running = true;
|
||||
|
||||
@ -514,16 +513,28 @@ const QString& SoapySDRInput::getDeviceDescription() const
|
||||
|
||||
int SoapySDRInput::getSampleRate() const
|
||||
{
|
||||
return 0;
|
||||
int rate = m_settings.m_devSampleRate;
|
||||
return (rate / (1<<m_settings.m_log2Decim));
|
||||
}
|
||||
|
||||
quint64 SoapySDRInput::getCenterFrequency() const
|
||||
{
|
||||
return 0;
|
||||
return m_settings.m_centerFrequency;
|
||||
}
|
||||
|
||||
void SoapySDRInput::setCenterFrequency(qint64 centerFrequency __attribute__((unused)))
|
||||
{
|
||||
SoapySDRInputSettings settings = m_settings;
|
||||
settings.m_centerFrequency = centerFrequency;
|
||||
|
||||
MsgConfigureSoapySDRInput *message = MsgConfigureSoapySDRInput::create(settings, false);
|
||||
m_inputMessageQueue.push(message);
|
||||
|
||||
if (m_guiMessageQueue)
|
||||
{
|
||||
MsgConfigureSoapySDRInput* messageToGUI = MsgConfigureSoapySDRInput::create(settings, false);
|
||||
m_guiMessageQueue->push(messageToGUI);
|
||||
}
|
||||
}
|
||||
|
||||
bool SoapySDRInput::setDeviceCenterFrequency(SoapySDR::Device *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths)
|
||||
@ -607,6 +618,7 @@ bool SoapySDRInput::handleMessage(const Message& message __attribute__((unused))
|
||||
DeviceSoapySDRShared::MsgReportBuddyChange& report = (DeviceSoapySDRShared::MsgReportBuddyChange&) message;
|
||||
SoapySDRInputSettings settings = m_settings;
|
||||
settings.m_fcPos = (SoapySDRInputSettings::fcPos_t) report.getFcPos();
|
||||
//bool fromRxBuddy = report.getRxElseTx();
|
||||
|
||||
settings.m_centerFrequency = m_deviceShared.m_device->getFrequency(
|
||||
SOAPY_SDR_RX,
|
||||
@ -624,6 +636,13 @@ bool SoapySDRInput::handleMessage(const Message& message __attribute__((unused))
|
||||
|
||||
m_settings = settings;
|
||||
|
||||
// propagate settings to GUI if any
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgConfigureSoapySDRInput *reportToGUI = MsgConfigureSoapySDRInput::create(m_settings, false);
|
||||
getMessageQueueToGUI()->push(reportToGUI);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -683,8 +702,6 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo
|
||||
|
||||
if ((m_settings.m_fcPos != settings.m_fcPos) || force)
|
||||
{
|
||||
SoapySDRInputThread *inputThread = findThread();
|
||||
|
||||
if (inputThread != 0)
|
||||
{
|
||||
inputThread->setFcPos(requestedChannel, (int) settings.m_fcPos);
|
||||
|
Loading…
Reference in New Issue
Block a user