HackRF: 2 way Rx/Tx frequency synchronization

This commit is contained in:
f4exb 2019-03-31 00:40:42 +01:00
parent 64b198e507
commit 9c5c726b97
6 changed files with 210 additions and 48 deletions

View File

@ -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<<m_settings.m_log2Interp);
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, m_settings.m_centerFrequency);
m_deviceAPI->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<uint64_t>(freq_hz));
qint64 df = ((qint64)freq_hz * LOppmTenths) / 10000000LL;
hackrf_error rc = (hackrf_error) hackrf_set_freq(m_dev, static_cast<uint64_t>(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;
}

View File

@ -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);

View File

@ -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<<m_settings.m_log2Decim);
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, m_settings.m_centerFrequency);
m_fileSink->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<uint64_t>(freq_hz));
qint64 df = ((qint64)freq_hz * LOppmTenths) / 10000000LL;
hackrf_error rc = (hackrf_error) hackrf_set_freq(m_dev, static_cast<uint64_t>(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;
}

View File

@ -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<QString>& deviceSettingsKeys, const HackRFInputSettings& settings, bool force);
void webapiReverseSendStartStop(bool start);

View File

@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#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<<log2Interp) << "S/s"
<< " center freq position code: " << fcPos
<< " image frequency: " << f_img << "Hz";
return deviceCenterFrequency;
}
qint64 DeviceSampleSink::calculateCenterFrequency(
quint64 deviceCenterFrequency,
qint64 transverterDeltaFrequency,
int log2Interp,
fcPos_t fcPos,
quint32 devSampleRate,
bool transverterMode)
{
qint64 centerFrequency = deviceCenterFrequency;
centerFrequency += calculateFrequencyShift(log2Interp, fcPos, devSampleRate);
centerFrequency += transverterMode ? transverterDeltaFrequency : 0;
centerFrequency = centerFrequency < 0 ? 0 : centerFrequency;
qDebug() << "DeviceSampleSink::calculateCenterFrequency:"
<< " desired center freq: " << centerFrequency << " Hz"
<< " device center freq: " << deviceCenterFrequency << " Hz"
<< " device sample rate: " << devSampleRate << "S/s"
<< " Actual sample rate: " << devSampleRate/(1<<log2Interp) << "S/s"
<< " center freq position code: " << fcPos;
return centerFrequency;
}
/**
* log2Interp = 0: no shift
*
* n = log2Interp <= 2: fc = +/- 1/2^(n-1)
* center
* | ^ |
* | inf | sup |
* ^ ^
*
* n = log2Interp > 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;
}
}
}

View File

@ -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();