1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-28 18:58:48 -05:00

LimeSDR: handle clock source change in source and sink

This commit is contained in:
f4exb 2017-11-04 02:18:16 +01:00
parent 465416ee19
commit 2ec8270e99
10 changed files with 206 additions and 2 deletions

View File

@ -344,3 +344,33 @@ bool DeviceLimeSDR::setTxAntennaPath(lms_device_t *device, std::size_t chan, int
return true; return true;
} }
bool DeviceLimeSDR::setClockSource(lms_device_t *device, bool extClock, uint32_t extClockFrequency)
{
if (extClock)
{
if (LMS_SetClockFreq(device, LMS_CLOCK_EXTREF, (float) extClockFrequency) < 0)
{
fprintf(stderr, "DeviceLimeSDR::setClockSource: cannot set to external\n");
return false;
}
}
else
{
uint16_t vcoTrimValue;
if (LMS_VCTCXORead(device, &vcoTrimValue))
{
fprintf(stderr, "DeviceLimeSDR::setClockSource: cannot read VCTXO trim value\n");
return false;
}
if (LMS_VCTCXOWrite(device, vcoTrimValue))
{
fprintf(stderr, "DeviceLimeSDR::setClockSource: cannot write VCTXO trim value\n");
return false;
}
}
return true;
}

View File

@ -51,6 +51,8 @@ public:
static bool setRxAntennaPath(lms_device_t *device, std::size_t chan, int path); static bool setRxAntennaPath(lms_device_t *device, std::size_t chan, int path);
/** Set Tx antenna path **/ /** Set Tx antenna path **/
static bool setTxAntennaPath(lms_device_t *device, std::size_t chan, int path); static bool setTxAntennaPath(lms_device_t *device, std::size_t chan, int path);
/** Set clock source and external clock frequency if required */
static bool setClockSource(lms_device_t *device, bool extClock, uint32_t extClockFrequency);
}; };
#endif /* DEVICES_LIMESDR_DEVICELIMESDR_H_ */ #endif /* DEVICES_LIMESDR_DEVICELIMESDR_H_ */

View File

@ -17,6 +17,7 @@
#include "devicelimesdrshared.h" #include "devicelimesdrshared.h"
MESSAGE_CLASS_DEFINITION(DeviceLimeSDRShared::MsgReportBuddyChange, Message) MESSAGE_CLASS_DEFINITION(DeviceLimeSDRShared::MsgReportBuddyChange, Message)
MESSAGE_CLASS_DEFINITION(DeviceLimeSDRShared::MsgReportClockSourceChange, Message)
MESSAGE_CLASS_DEFINITION(DeviceLimeSDRShared::MsgReportDeviceInfo, Message) MESSAGE_CLASS_DEFINITION(DeviceLimeSDRShared::MsgReportDeviceInfo, Message)
const float DeviceLimeSDRShared::m_sampleFifoLengthInSeconds = 0.25; const float DeviceLimeSDRShared::m_sampleFifoLengthInSeconds = 0.25;

View File

@ -68,6 +68,35 @@ public:
{ } { }
}; };
class MsgReportClockSourceChange : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool getExtClock() const { return m_extClock; }
uint32_t getExtClockFeq() const { return m_extClockFreq; }
static MsgReportClockSourceChange* create(
bool extClock,
uint32_t m_extClockFreq)
{
return new MsgReportClockSourceChange(
extClock,
m_extClockFreq);
}
private:
bool m_extClock; //!< True if external clock source
uint32_t m_extClockFreq; //!< Frequency (Hz) of external clock source
MsgReportClockSourceChange(
bool extClock,
uint32_t m_extClockFreq) :
Message(),
m_extClock(extClock),
m_extClockFreq(m_extClockFreq)
{ }
};
class MsgReportDeviceInfo : public Message { class MsgReportDeviceInfo : public Message {
MESSAGE_CLASS_DECLARATION MESSAGE_CLASS_DECLARATION

View File

@ -519,6 +519,19 @@ bool LimeSDROutput::handleMessage(const Message& message)
return true; return true;
} }
else if (DeviceLimeSDRShared::MsgReportClockSourceChange::match(message))
{
DeviceLimeSDRShared::MsgReportClockSourceChange& report = (DeviceLimeSDRShared::MsgReportClockSourceChange&) message;
m_settings.m_extClock = report.getExtClock();
m_settings.m_extClockFreq = report.getExtClockFeq();
DeviceLimeSDRShared::MsgReportClockSourceChange *reportToGUI = DeviceLimeSDRShared::MsgReportClockSourceChange::create(
m_settings.m_extClock, m_settings.m_extClockFreq);
getMessageQueueToGUI()->push(reportToGUI);
return true;
}
else if (MsgGetStreamInfo::match(message)) else if (MsgGetStreamInfo::match(message))
{ {
// qDebug() << "LimeSDROutput::handleMessage: MsgGetStreamInfo"; // qDebug() << "LimeSDROutput::handleMessage: MsgGetStreamInfo";
@ -621,6 +634,7 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo
bool forwardChangeOwnDSP = false; bool forwardChangeOwnDSP = false;
bool forwardChangeTxDSP = false; bool forwardChangeTxDSP = false;
bool forwardChangeAllDSP = false; bool forwardChangeAllDSP = false;
bool forwardClockSource = false;
bool ownThreadWasRunning = false; bool ownThreadWasRunning = false;
bool doCalibration = false; bool doCalibration = false;
double clockGenFreq = 0.0; double clockGenFreq = 0.0;
@ -820,6 +834,28 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo
} }
} }
if ((m_settings.m_extClock != settings.m_extClock) ||
(m_settings.m_extClockFreq != settings.m_extClockFreq) || force)
{
if (DeviceLimeSDR::setClockSource(m_deviceShared.m_deviceParams->getDevice(),
settings.m_extClock,
settings.m_extClockFreq))
{
forwardClockSource = true;
doCalibration = true;
qDebug("LimeSDRInput::applySettings: clock set to %s (Ext: %d Hz)",
settings.m_extClock ? "external" : "internal",
settings.m_extClockFreq);
}
else
{
qCritical("LimeSDRInput::applySettings: could not set clock to %s (Ext: %d Hz)",
settings.m_extClock ? "external" : "internal",
settings.m_extClockFreq);
}
}
m_settings = settings; m_settings = settings;
double clockGenFreqAfter; double clockGenFreqAfter;
@ -933,6 +969,31 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
} }
if (forwardClockSource)
{
// send to source buddies
const std::vector<DeviceSourceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
std::vector<DeviceSourceAPI*>::const_iterator itSource = sourceBuddies.begin();
for (; itSource != sourceBuddies.end(); ++itSource)
{
DeviceLimeSDRShared::MsgReportClockSourceChange *report = DeviceLimeSDRShared::MsgReportClockSourceChange::create(
m_settings.m_extClock, m_settings.m_extClockFreq);
(*itSource)->getSampleSourceInputMessageQueue()->push(report);
}
// send to sink buddies
const std::vector<DeviceSinkAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
std::vector<DeviceSinkAPI*>::const_iterator itSink = sinkBuddies.begin();
for (; itSink != sinkBuddies.end(); ++itSink)
{
DeviceLimeSDRShared::MsgReportClockSourceChange *report = DeviceLimeSDRShared::MsgReportClockSourceChange::create(
m_settings.m_extClock, m_settings.m_extClockFreq);
(*itSink)->getSampleSinkInputMessageQueue()->push(report);
}
}
qDebug() << "LimeSDROutput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz" qDebug() << "LimeSDROutput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz"
<< " device stream sample rate: " << m_settings.m_devSampleRate << "S/s" << " device stream sample rate: " << m_settings.m_devSampleRate << "S/s"
<< " sample rate with soft decimation: " << m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftInterp) << "S/s" << " sample rate with soft decimation: " << m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftInterp) << "S/s"
@ -942,7 +1003,9 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo
<< " m_lpfFIREnable: " << m_settings.m_lpfFIREnable << " m_lpfFIREnable: " << m_settings.m_lpfFIREnable
<< " m_ncoEnable: " << m_settings.m_ncoEnable << " m_ncoEnable: " << m_settings.m_ncoEnable
<< " m_ncoFrequency: " << m_settings.m_ncoFrequency << " m_ncoFrequency: " << m_settings.m_ncoFrequency
<< " m_antennaPath: " << m_settings.m_antennaPath; << " m_antennaPath: " << m_settings.m_antennaPath
<< " m_extClock: " << m_settings.m_extClock
<< " m_extClockFreq: " << m_settings.m_extClockFreq;
return true; return true;
} }

View File

@ -36,6 +36,8 @@ void LimeSDROutputSettings::resetToDefaults()
m_ncoEnable = false; m_ncoEnable = false;
m_ncoFrequency = 0; m_ncoFrequency = 0;
m_antennaPath = PATH_RFE_NONE; m_antennaPath = PATH_RFE_NONE;
m_extClock = false;
m_extClockFreq = 10000000; // 10 MHz
} }
QByteArray LimeSDROutputSettings::serialize() const QByteArray LimeSDROutputSettings::serialize() const
@ -52,6 +54,8 @@ QByteArray LimeSDROutputSettings::serialize() const
s.writeBool(11, m_ncoEnable); s.writeBool(11, m_ncoEnable);
s.writeS32(12, m_ncoFrequency); s.writeS32(12, m_ncoFrequency);
s.writeS32(13, (int) m_antennaPath); s.writeS32(13, (int) m_antennaPath);
s.writeBool(14, m_extClock);
s.writeU32(15, m_extClockFreq);
return s.final(); return s.final();
} }
@ -81,6 +85,8 @@ bool LimeSDROutputSettings::deserialize(const QByteArray& data)
d.readS32(12, &m_ncoFrequency, 0); d.readS32(12, &m_ncoFrequency, 0);
d.readS32(13, &intval, 0); d.readS32(13, &intval, 0);
m_antennaPath = (PathRFE) intval; m_antennaPath = (PathRFE) intval;
d.readBool(14, &m_extClock, false);
d.readU32(15, &m_extClockFreq, 10000000);
return true; return true;
} }

View File

@ -52,6 +52,8 @@ struct LimeSDROutputSettings
bool m_ncoEnable; //!< Enable TSP NCO and mixing bool m_ncoEnable; //!< Enable TSP NCO and mixing
int m_ncoFrequency; //!< Actual NCO frequency (the resulting frequency with mixing is displayed) int m_ncoFrequency; //!< Actual NCO frequency (the resulting frequency with mixing is displayed)
PathRFE m_antennaPath; PathRFE m_antennaPath;
bool m_extClock; //!< True if external clock source
uint32_t m_extClockFreq; //!< Frequency (Hz) of external clock source
LimeSDROutputSettings(); LimeSDROutputSettings();
void resetToDefaults(); void resetToDefaults();

View File

@ -538,6 +538,19 @@ bool LimeSDRInput::handleMessage(const Message& message)
return true; return true;
} }
else if (DeviceLimeSDRShared::MsgReportClockSourceChange::match(message))
{
DeviceLimeSDRShared::MsgReportClockSourceChange& report = (DeviceLimeSDRShared::MsgReportClockSourceChange&) message;
m_settings.m_extClock = report.getExtClock();
m_settings.m_extClockFreq = report.getExtClockFeq();
DeviceLimeSDRShared::MsgReportClockSourceChange *reportToGUI = DeviceLimeSDRShared::MsgReportClockSourceChange::create(
m_settings.m_extClock, m_settings.m_extClockFreq);
getMessageQueueToGUI()->push(reportToGUI);
return true;
}
else if (MsgGetStreamInfo::match(message)) else if (MsgGetStreamInfo::match(message))
{ {
// qDebug() << "LimeSDRInput::handleMessage: MsgGetStreamInfo"; // qDebug() << "LimeSDRInput::handleMessage: MsgGetStreamInfo";
@ -653,6 +666,7 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc
bool forwardChangeOwnDSP = false; bool forwardChangeOwnDSP = false;
bool forwardChangeRxDSP = false; bool forwardChangeRxDSP = false;
bool forwardChangeAllDSP = false; bool forwardChangeAllDSP = false;
bool forwardClockSource = false;
bool ownThreadWasRunning = false; bool ownThreadWasRunning = false;
bool doCalibration = false; bool doCalibration = false;
bool setAntennaAuto = false; bool setAntennaAuto = false;
@ -972,6 +986,28 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc
} }
} }
if ((m_settings.m_extClock != settings.m_extClock) ||
(m_settings.m_extClockFreq != settings.m_extClockFreq) || force)
{
if (DeviceLimeSDR::setClockSource(m_deviceShared.m_deviceParams->getDevice(),
settings.m_extClock,
settings.m_extClockFreq))
{
forwardClockSource = true;
doCalibration = true;
qDebug("LimeSDRInput::applySettings: clock set to %s (Ext: %d Hz)",
settings.m_extClock ? "external" : "internal",
settings.m_extClockFreq);
}
else
{
qCritical("LimeSDRInput::applySettings: could not set clock to %s (Ext: %d Hz)",
settings.m_extClock ? "external" : "internal",
settings.m_extClockFreq);
}
}
m_settings = settings; m_settings = settings;
double clockGenFreqAfter; double clockGenFreqAfter;
@ -1086,6 +1122,31 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
} }
if (forwardClockSource)
{
// send to source buddies
const std::vector<DeviceSourceAPI*>& sourceBuddies = m_deviceAPI->getSourceBuddies();
std::vector<DeviceSourceAPI*>::const_iterator itSource = sourceBuddies.begin();
for (; itSource != sourceBuddies.end(); ++itSource)
{
DeviceLimeSDRShared::MsgReportClockSourceChange *report = DeviceLimeSDRShared::MsgReportClockSourceChange::create(
m_settings.m_extClock, m_settings.m_extClockFreq);
(*itSource)->getSampleSourceInputMessageQueue()->push(report);
}
// send to sink buddies
const std::vector<DeviceSinkAPI*>& sinkBuddies = m_deviceAPI->getSinkBuddies();
std::vector<DeviceSinkAPI*>::const_iterator itSink = sinkBuddies.begin();
for (; itSink != sinkBuddies.end(); ++itSink)
{
DeviceLimeSDRShared::MsgReportClockSourceChange *report = DeviceLimeSDRShared::MsgReportClockSourceChange::create(
m_settings.m_extClock, m_settings.m_extClockFreq);
(*itSink)->getSampleSinkInputMessageQueue()->push(report);
}
}
qDebug() << "LimeSDRInput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz" qDebug() << "LimeSDRInput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz"
<< " device stream sample rate: " << m_settings.m_devSampleRate << "S/s" << " device stream sample rate: " << m_settings.m_devSampleRate << "S/s"
<< " sample rate with soft decimation: " << m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftDecim) << "S/s" << " sample rate with soft decimation: " << m_settings.m_devSampleRate/(1<<m_settings.m_log2SoftDecim) << "S/s"
@ -1095,7 +1156,9 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc
<< " m_lpfFIREnable: " << m_settings.m_lpfFIREnable << " m_lpfFIREnable: " << m_settings.m_lpfFIREnable
<< " m_ncoEnable: " << m_settings.m_ncoEnable << " m_ncoEnable: " << m_settings.m_ncoEnable
<< " m_ncoFrequency: " << m_settings.m_ncoFrequency << " m_ncoFrequency: " << m_settings.m_ncoFrequency
<< " m_antennaPath: " << m_settings.m_antennaPath; << " m_antennaPath: " << m_settings.m_antennaPath
<< " m_extClock: " << m_settings.m_extClock
<< " m_extClockFreq: " << m_settings.m_extClockFreq;
return true; return true;
} }

View File

@ -41,6 +41,8 @@ void LimeSDRInputSettings::resetToDefaults()
m_lnaGain = 15; m_lnaGain = 15;
m_tiaGain = 2; m_tiaGain = 2;
m_pgaGain = 16; m_pgaGain = 16;
m_extClock = false;
m_extClockFreq = 10000000; // 10 MHz
} }
QByteArray LimeSDRInputSettings::serialize() const QByteArray LimeSDRInputSettings::serialize() const
@ -63,6 +65,8 @@ QByteArray LimeSDRInputSettings::serialize() const
s.writeU32(15, m_lnaGain); s.writeU32(15, m_lnaGain);
s.writeU32(16, m_tiaGain); s.writeU32(16, m_tiaGain);
s.writeU32(17, m_pgaGain); s.writeU32(17, m_pgaGain);
s.writeBool(18, m_extClock);
s.writeU32(19, m_extClockFreq);
return s.final(); return s.final();
} }
@ -99,6 +103,8 @@ bool LimeSDRInputSettings::deserialize(const QByteArray& data)
d.readU32(15, &m_lnaGain, 15); d.readU32(15, &m_lnaGain, 15);
d.readU32(16, &m_tiaGain, 2); d.readU32(16, &m_tiaGain, 2);
d.readU32(17, &m_pgaGain, 16); d.readU32(17, &m_pgaGain, 16);
d.readBool(18, &m_extClock, false);
d.readU32(19, &m_extClockFreq, 10000000);
return true; return true;
} }

View File

@ -66,6 +66,8 @@ struct LimeSDRInputSettings
uint32_t m_lnaGain; //!< Manual LAN gain uint32_t m_lnaGain; //!< Manual LAN gain
uint32_t m_tiaGain; //!< Manual TIA gain uint32_t m_tiaGain; //!< Manual TIA gain
uint32_t m_pgaGain; //!< Manual PGA gain uint32_t m_pgaGain; //!< Manual PGA gain
bool m_extClock; //!< True if external clock source
uint32_t m_extClockFreq; //!< Frequency (Hz) of external clock source
LimeSDRInputSettings(); LimeSDRInputSettings();
void resetToDefaults(); void resetToDefaults();