1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-09-27 15:26:33 -04:00

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; return false;
} }
if (m_running) stop(); if (m_running) {
stop();
}
m_hackRFThread = new HackRFOutputThread(m_dev, &m_sampleSourceFifo); m_hackRFThread = new HackRFOutputThread(m_dev, &m_sampleSourceFifo);
@ -269,6 +271,32 @@ bool HackRFOutput::handleMessage(const Message& message)
return true; 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 else
{ {
return false; return false;
@ -277,19 +305,18 @@ bool HackRFOutput::handleMessage(const Message& message)
void HackRFOutput::setDeviceCenterFrequency(quint64 freq_hz, qint32 LOppmTenths) void HackRFOutput::setDeviceCenterFrequency(quint64 freq_hz, qint32 LOppmTenths)
{ {
qint64 df = ((qint64)freq_hz * LOppmTenths) / 10000000LL; if (!m_dev) {
freq_hz += df; 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) if (rc != HACKRF_SUCCESS) {
{ qWarning("HackRFOutput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz + df);
qWarning("HackRFOutput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz); } else {
} qDebug("HackRFOutput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz + df);
else }
{
qWarning("HackRFOutput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz);
}
} }
bool HackRFOutput::applySettings(const HackRFOutputSettings& settings, bool force) 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"); 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) { if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) {
reverseAPIKeys.append("LOppmTenths"); reverseAPIKeys.append("LOppmTenths");
@ -397,11 +416,20 @@ bool HackRFOutput::applySettings(const HackRFOutputSettings& settings, bool forc
if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) || if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency) ||
(m_settings.m_LOppmTenths != settings.m_LOppmTenths)) (m_settings.m_LOppmTenths != settings.m_LOppmTenths))
{ {
if (m_dev != 0) qint64 deviceCenterFrequency = DeviceSampleSink::calculateDeviceCenterFrequency(
{ settings.m_centerFrequency,
setDeviceCenterFrequency(settings.m_centerFrequency, settings.m_LOppmTenths); 0,
qDebug() << "HackRFOutput::applySettings: center freq: " << settings.m_centerFrequency << " Hz LOppm: " << settings.m_LOppmTenths; 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; forwardChange = true;
} }

View File

@ -142,8 +142,8 @@ private:
DeviceHackRFParams m_sharedParams; DeviceHackRFParams m_sharedParams;
QNetworkAccessManager *m_networkManager; QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest; QNetworkRequest m_networkRequest;
bool m_running; bool m_running;
bool openDevice(); bool openDevice();
void closeDevice(); void closeDevice();
bool applySettings(const HackRFOutputSettings& settings, bool force); bool applySettings(const HackRFOutputSettings& settings, bool force);

View File

@ -139,7 +139,9 @@ bool HackRFInput::start()
return false; return false;
} }
if (m_running) stop(); if (m_running) {
stop();
}
m_hackRFThread = new HackRFInputThread(m_dev, &m_sampleFifo); 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, (DeviceSampleSource::fcPos_t) m_settings.m_fcPos,
m_settings.m_devSampleRate); m_settings.m_devSampleRate);
qDebug("HackRFInput::handleMessage: MsgSynchronizeFrequency: centerFrequency: %lld Hz", centerFrequency); 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; 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; if (!m_dev) {
freq_hz += df; 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) if (rc != HACKRF_SUCCESS) {
{ qWarning("HackRFInput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz + df);
qWarning("HackRFInput::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz); } else {
} qDebug("HackRFInput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz + df);
else
{
qWarning("HackRFInput::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz);
} }
} }
@ -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"); reverseAPIKeys.append("centerFrequency");
} }
@ -429,10 +442,14 @@ bool HackRFInput::applySettings(const HackRFInputSettings& settings, bool force)
settings.m_log2Decim, settings.m_log2Decim,
(DeviceSampleSource::fcPos_t) settings.m_fcPos, (DeviceSampleSource::fcPos_t) settings.m_fcPos,
settings.m_devSampleRate); settings.m_devSampleRate);
setDeviceCenterFrequency(deviceCenterFrequency, settings.m_LOppmTenths);
if (m_dev != 0) { if (m_deviceAPI->getSinkBuddies().size() > 0) // forward to buddy if necessary
setDeviceCenterFrequency(deviceCenterFrequency); {
} DeviceSinkAPI *buddy = m_deviceAPI->getSinkBuddies()[0];
DeviceHackRFShared::MsgSynchronizeFrequency *freqMsg = DeviceHackRFShared::MsgSynchronizeFrequency::create(deviceCenterFrequency);
buddy->getSampleSinkInputMessageQueue()->push(freqMsg);
}
forwardChange = true; forwardChange = true;
} }

View File

@ -170,7 +170,7 @@ private:
bool openDevice(); bool openDevice();
void closeDevice(); void closeDevice();
bool applySettings(const HackRFInputSettings& settings, bool force); 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 webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const HackRFInputSettings& settings);
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const HackRFInputSettings& settings, bool force); void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const HackRFInputSettings& settings, bool force);
void webapiReverseSendStartStop(bool start); void webapiReverseSendStartStop(bool start);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 F4EXB // // Copyright (C) 2016-2019 F4EXB //
// written by Edouard Griffiths // // written by Edouard Griffiths //
// // // //
// This program is free software; you can redistribute it and/or modify // // 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/>. // // along with this program. If not, see <http://www.gnu.org/licenses/>. //
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include "dsp/devicesamplesink.h" #include "dsp/devicesamplesink.h"
DeviceSampleSink::DeviceSampleSink() : 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 // // written by Edouard Griffiths //
// // // //
// This program is free software; you can redistribute it and/or modify // // This program is free software; you can redistribute it and/or modify //
@ -35,6 +35,12 @@ namespace SWGSDRangel
class SDRBASE_API DeviceSampleSink : public QObject { class SDRBASE_API DeviceSampleSink : public QObject {
Q_OBJECT Q_OBJECT
public: public:
typedef enum {
FC_POS_INFRA = 0,
FC_POS_SUPRA,
FC_POS_CENTER
} fcPos_t;
DeviceSampleSink(); DeviceSampleSink();
virtual ~DeviceSampleSink(); virtual ~DeviceSampleSink();
virtual void destroy() = 0; virtual void destroy() = 0;
@ -108,6 +114,27 @@ public:
MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; } MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; }
SampleSourceFifo* getSampleFifo() { return &m_sampleSourceFifo; } 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: protected slots:
void handleInputMessages(); void handleInputMessages();