From 9c5c726b97fa72ecdae5e30f9bb8a14091c56ebf Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 31 Mar 2019 00:40:42 +0100 Subject: [PATCH] HackRF: 2 way Rx/Tx frequency synchronization --- .../samplesink/hackrfoutput/hackrfoutput.cpp | 80 ++++++++++------ .../samplesink/hackrfoutput/hackrfoutput.h | 2 +- .../samplesource/hackrfinput/hackrfinput.cpp | 53 +++++++---- .../samplesource/hackrfinput/hackrfinput.h | 2 +- sdrbase/dsp/devicesamplesink.cpp | 92 ++++++++++++++++++- sdrbase/dsp/devicesamplesink.h | 29 +++++- 6 files changed, 210 insertions(+), 48 deletions(-) diff --git a/plugins/samplesink/hackrfoutput/hackrfoutput.cpp b/plugins/samplesink/hackrfoutput/hackrfoutput.cpp index e90c19b23..b1df37d39 100644 --- a/plugins/samplesink/hackrfoutput/hackrfoutput.cpp +++ b/plugins/samplesink/hackrfoutput/hackrfoutput.cpp @@ -123,7 +123,9 @@ bool HackRFOutput::start() return false; } - if (m_running) stop(); + if (m_running) { + stop(); + } m_hackRFThread = new HackRFOutputThread(m_dev, &m_sampleSourceFifo); @@ -269,6 +271,32 @@ bool HackRFOutput::handleMessage(const Message& message) return true; } + else if (DeviceHackRFShared::MsgSynchronizeFrequency::match(message)) + { + DeviceHackRFShared::MsgSynchronizeFrequency& freqMsg = (DeviceHackRFShared::MsgSynchronizeFrequency&) message; + qint64 centerFrequency = DeviceSampleSink::calculateCenterFrequency( + freqMsg.getFrequency(), + 0, + m_settings.m_log2Interp, + DeviceSampleSink::FC_POS_CENTER, + m_settings.m_devSampleRate); + qDebug("HackRFOutput::handleMessage: MsgSynchronizeFrequency: centerFrequency: %lld Hz", centerFrequency); + HackRFOutputSettings settings = m_settings; + settings.m_centerFrequency = centerFrequency; + + if (m_guiMessageQueue) + { + MsgConfigureHackRF* messageToGUI = MsgConfigureHackRF::create(settings, false); + m_guiMessageQueue->push(messageToGUI); + } + + m_settings.m_centerFrequency = settings.m_centerFrequency; + int sampleRate = m_settings.m_devSampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif); + + return true; + } else { return false; @@ -277,19 +305,18 @@ bool HackRFOutput::handleMessage(const Message& message) void HackRFOutput::setDeviceCenterFrequency(quint64 freq_hz, qint32 LOppmTenths) { - qint64 df = ((qint64)freq_hz * LOppmTenths) / 10000000LL; - freq_hz += df; + if (!m_dev) { + return; + } - hackrf_error rc = (hackrf_error) hackrf_set_freq(m_dev, static_cast(freq_hz)); + qint64 df = ((qint64)freq_hz * LOppmTenths) / 10000000LL; + hackrf_error rc = (hackrf_error) hackrf_set_freq(m_dev, static_cast(freq_hz + df)); - if (rc != HACKRF_SUCCESS) - { - qWarning("HackRFOutput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz); - } - else - { - qWarning("HackRFOutput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz); - } + if (rc != HACKRF_SUCCESS) { + qWarning("HackRFOutput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz + df); + } else { + qDebug("HackRFOutput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz + df); + } } bool HackRFOutput::applySettings(const HackRFOutputSettings& settings, bool force) @@ -379,16 +406,8 @@ bool HackRFOutput::applySettings(const HackRFOutputSettings& settings, bool forc } } - if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) - { + if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) { reverseAPIKeys.append("centerFrequency"); - - if (m_deviceAPI->getSourceBuddies().size() > 0) - { - DeviceSourceAPI *buddy = m_deviceAPI->getSourceBuddies()[0]; - DeviceHackRFShared::MsgSynchronizeFrequency *freqMsg = DeviceHackRFShared::MsgSynchronizeFrequency::create(settings.m_centerFrequency); - buddy->getSampleSourceInputMessageQueue()->push(freqMsg); - } } if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) { reverseAPIKeys.append("LOppmTenths"); @@ -397,11 +416,20 @@ bool HackRFOutput::applySettings(const HackRFOutputSettings& settings, bool forc if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) || (m_settings.m_LOppmTenths != settings.m_LOppmTenths)) { - if (m_dev != 0) - { - setDeviceCenterFrequency(settings.m_centerFrequency, settings.m_LOppmTenths); - qDebug() << "HackRFOutput::applySettings: center freq: " << settings.m_centerFrequency << " Hz LOppm: " << settings.m_LOppmTenths; - } + qint64 deviceCenterFrequency = DeviceSampleSink::calculateDeviceCenterFrequency( + settings.m_centerFrequency, + 0, + settings.m_log2Interp, + DeviceSampleSink::FC_POS_CENTER, + settings.m_devSampleRate); + setDeviceCenterFrequency(deviceCenterFrequency, settings.m_LOppmTenths); + + if (m_deviceAPI->getSourceBuddies().size() > 0) + { + DeviceSourceAPI *buddy = m_deviceAPI->getSourceBuddies()[0]; + DeviceHackRFShared::MsgSynchronizeFrequency *freqMsg = DeviceHackRFShared::MsgSynchronizeFrequency::create(deviceCenterFrequency); + buddy->getSampleSourceInputMessageQueue()->push(freqMsg); + } forwardChange = true; } diff --git a/plugins/samplesink/hackrfoutput/hackrfoutput.h b/plugins/samplesink/hackrfoutput/hackrfoutput.h index b234a08fd..42494b4ed 100644 --- a/plugins/samplesink/hackrfoutput/hackrfoutput.h +++ b/plugins/samplesink/hackrfoutput/hackrfoutput.h @@ -142,8 +142,8 @@ private: DeviceHackRFParams m_sharedParams; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; - bool m_running; + bool openDevice(); void closeDevice(); bool applySettings(const HackRFOutputSettings& settings, bool force); diff --git a/plugins/samplesource/hackrfinput/hackrfinput.cpp b/plugins/samplesource/hackrfinput/hackrfinput.cpp index d789c620b..1868a62f4 100644 --- a/plugins/samplesource/hackrfinput/hackrfinput.cpp +++ b/plugins/samplesource/hackrfinput/hackrfinput.cpp @@ -139,7 +139,9 @@ bool HackRFInput::start() return false; } - if (m_running) stop(); + if (m_running) { + stop(); + } m_hackRFThread = new HackRFInputThread(m_dev, &m_sampleFifo); @@ -319,7 +321,20 @@ bool HackRFInput::handleMessage(const Message& message) (DeviceSampleSource::fcPos_t) m_settings.m_fcPos, m_settings.m_devSampleRate); qDebug("HackRFInput::handleMessage: MsgSynchronizeFrequency: centerFrequency: %lld Hz", centerFrequency); - setCenterFrequency(centerFrequency); + HackRFInputSettings settings = m_settings; + settings.m_centerFrequency = centerFrequency; + + if (m_guiMessageQueue) + { + MsgConfigureHackRF* messageToGUI = MsgConfigureHackRF::create(settings, false); + m_guiMessageQueue->push(messageToGUI); + } + + m_settings.m_centerFrequency = settings.m_centerFrequency; + int sampleRate = m_settings.m_devSampleRate/(1<handleMessage(*notif); // forward to file sink + m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); return true; } @@ -329,20 +344,19 @@ bool HackRFInput::handleMessage(const Message& message) } } -void HackRFInput::setDeviceCenterFrequency(quint64 freq_hz) +void HackRFInput::setDeviceCenterFrequency(quint64 freq_hz, qint32 LOppmTenths) { - qint64 df = ((qint64)freq_hz * m_settings.m_LOppmTenths) / 10000000LL; - freq_hz += df; + if (!m_dev) { + return; + } - hackrf_error rc = (hackrf_error) hackrf_set_freq(m_dev, static_cast(freq_hz)); + qint64 df = ((qint64)freq_hz * LOppmTenths) / 10000000LL; + hackrf_error rc = (hackrf_error) hackrf_set_freq(m_dev, static_cast(freq_hz + df)); - if (rc != HACKRF_SUCCESS) - { - qWarning("HackRFInput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz); - } - else - { - qWarning("HackRFInput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz); + if (rc != HACKRF_SUCCESS) { + qWarning("HackRFInput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz + df); + } else { + qDebug("HackRFInput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz + df); } } @@ -405,8 +419,7 @@ bool HackRFInput::applySettings(const HackRFInputSettings& settings, bool force) } } - if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency)) // forward delta to buddy if necessary - { + if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency)) { reverseAPIKeys.append("centerFrequency"); } @@ -429,10 +442,14 @@ bool HackRFInput::applySettings(const HackRFInputSettings& settings, bool force) settings.m_log2Decim, (DeviceSampleSource::fcPos_t) settings.m_fcPos, settings.m_devSampleRate); + setDeviceCenterFrequency(deviceCenterFrequency, settings.m_LOppmTenths); - if (m_dev != 0) { - setDeviceCenterFrequency(deviceCenterFrequency); - } + if (m_deviceAPI->getSinkBuddies().size() > 0) // forward to buddy if necessary + { + DeviceSinkAPI *buddy = m_deviceAPI->getSinkBuddies()[0]; + DeviceHackRFShared::MsgSynchronizeFrequency *freqMsg = DeviceHackRFShared::MsgSynchronizeFrequency::create(deviceCenterFrequency); + buddy->getSampleSinkInputMessageQueue()->push(freqMsg); + } forwardChange = true; } diff --git a/plugins/samplesource/hackrfinput/hackrfinput.h b/plugins/samplesource/hackrfinput/hackrfinput.h index 4204d4d9a..36de99688 100644 --- a/plugins/samplesource/hackrfinput/hackrfinput.h +++ b/plugins/samplesource/hackrfinput/hackrfinput.h @@ -170,7 +170,7 @@ private: bool openDevice(); void closeDevice(); bool applySettings(const HackRFInputSettings& settings, bool force); - void setDeviceCenterFrequency(quint64 freq); + void setDeviceCenterFrequency(quint64 freq, qint32 LOppmTenths); void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const HackRFInputSettings& settings); void webapiReverseSendSettings(QList& deviceSettingsKeys, const HackRFInputSettings& settings, bool force); void webapiReverseSendStartStop(bool start); diff --git a/sdrbase/dsp/devicesamplesink.cpp b/sdrbase/dsp/devicesamplesink.cpp index 9d35b7412..d26237946 100644 --- a/sdrbase/dsp/devicesamplesink.cpp +++ b/sdrbase/dsp/devicesamplesink.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 F4EXB // +// Copyright (C) 2016-2019 F4EXB // // written by Edouard Griffiths // // // // This program is free software; you can redistribute it and/or modify // @@ -15,6 +15,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include + #include "dsp/devicesamplesink.h" DeviceSampleSink::DeviceSampleSink() : @@ -41,6 +43,94 @@ void DeviceSampleSink::handleInputMessages() } } +qint64 DeviceSampleSink::calculateDeviceCenterFrequency( + quint64 centerFrequency, + qint64 transverterDeltaFrequency, + int log2Interp, + fcPos_t fcPos, + quint32 devSampleRate, + bool transverterMode) +{ + qint64 deviceCenterFrequency = centerFrequency; + deviceCenterFrequency -= transverterMode ? transverterDeltaFrequency : 0; + deviceCenterFrequency = deviceCenterFrequency < 0 ? 0 : deviceCenterFrequency; + qint64 f_img = deviceCenterFrequency; + deviceCenterFrequency -= calculateFrequencyShift(log2Interp, fcPos, devSampleRate); + f_img -= 2*calculateFrequencyShift(log2Interp, fcPos, devSampleRate); + qDebug() << "DeviceSampleSink::calculateDeviceCenterFrequency:" + << " desired center freq: " << centerFrequency << " Hz" + << " device center freq: " << deviceCenterFrequency << " Hz" + << " device sample rate: " << devSampleRate << "S/s" + << " Actual sample rate: " << devSampleRate/(1< 2: fc = +/- 1/2^n + * center + * | ^ | + * | |inf| | |sup| | + * ^ ^ + */ +qint32 DeviceSampleSink::calculateFrequencyShift( + int log2Interp, + fcPos_t fcPos, + quint32 devSampleRate) +{ + if (log2Interp == 0) { // no shift at all + return 0; + } else if (log2Interp < 3) { + if (fcPos == FC_POS_INFRA) { // shift in the square next to center frequency + return -(devSampleRate / (1<<(log2Interp+1))); + } else if (fcPos == FC_POS_SUPRA) { + return devSampleRate / (1<<(log2Interp+1)); + } else { + return 0; + } + } else { + if (fcPos == FC_POS_INFRA) { // shift centered in the square next to center frequency + return -(devSampleRate / (1<<(log2Interp))); + } else if (fcPos == FC_POS_SUPRA) { + return devSampleRate / (1<<(log2Interp)); + } else { + return 0; + } + } +} diff --git a/sdrbase/dsp/devicesamplesink.h b/sdrbase/dsp/devicesamplesink.h index 8ecb74d20..d52371fa5 100644 --- a/sdrbase/dsp/devicesamplesink.h +++ b/sdrbase/dsp/devicesamplesink.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 F4EXB // +// Copyright (C) 2016-2019 F4EXB // // written by Edouard Griffiths // // // // This program is free software; you can redistribute it and/or modify // @@ -35,6 +35,12 @@ namespace SWGSDRangel class SDRBASE_API DeviceSampleSink : public QObject { Q_OBJECT public: + typedef enum { + FC_POS_INFRA = 0, + FC_POS_SUPRA, + FC_POS_CENTER + } fcPos_t; + DeviceSampleSink(); virtual ~DeviceSampleSink(); virtual void destroy() = 0; @@ -108,6 +114,27 @@ public: MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; } SampleSourceFifo* getSampleFifo() { return &m_sampleSourceFifo; } + static qint64 calculateDeviceCenterFrequency( + quint64 centerFrequency, + qint64 transverterDeltaFrequency, + int log2Interp, + fcPos_t fcPos, + quint32 devSampleRate, + bool transverterMode = false); + + static qint64 calculateCenterFrequency( + quint64 deviceCenterFrequency, + qint64 transverterDeltaFrequency, + int log2Interp, + fcPos_t fcPos, + quint32 devSampleRate, + bool transverterMode = false); + + static qint32 calculateFrequencyShift( + int log2Interp, + fcPos_t fcPos, + quint32 devSampleRate); + protected slots: void handleInputMessages();