mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 21:20:31 -05: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()
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user