Reference control added

This commit is contained in:
Jan Käberich 2020-09-12 12:17:35 +02:00
parent 6960498fcb
commit e266d37b96
13 changed files with 272 additions and 143 deletions

Binary file not shown.

View File

@ -82,14 +82,11 @@ Device::~Device()
}
}
bool Device::Configure(Protocol::SweepSettings settings)
bool Device::SendPacket(Protocol::PacketInfo packet)
{
if(m_connected) {
unsigned char buffer[128];
Protocol::PacketInfo p;
p.type = Protocol::PacketType::SweepSettings;
p.settings = settings;
unsigned int length = Protocol::EncodePacket(p, buffer, sizeof(buffer));
unsigned char buffer[1024];
unsigned int length = Protocol::EncodePacket(packet, buffer, sizeof(buffer));
if(!length) {
qCritical() << "Failed to encode packet";
return false;
@ -107,78 +104,35 @@ bool Device::Configure(Protocol::SweepSettings settings)
}
}
bool Device::Configure(Protocol::SweepSettings settings)
{
Protocol::PacketInfo p;
p.type = Protocol::PacketType::SweepSettings;
p.settings = settings;
return SendPacket(p);
}
bool Device::SetManual(Protocol::ManualControl manual)
{
if(m_connected) {
unsigned char buffer[128];
Protocol::PacketInfo p;
p.type = Protocol::PacketType::ManualControl;
p.manual = manual;
unsigned int length = Protocol::EncodePacket(p, buffer, sizeof(buffer));
if(!length) {
qCritical() << "Failed to encode packet";
return false;
}
int actual_length;
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
if(ret < 0) {
qCritical() << "Error sending data: "
<< libusb_strerror((libusb_error) ret);
return false;
}
return true;
} else {
return false;
}
Protocol::PacketInfo p;
p.type = Protocol::PacketType::ManualControl;
p.manual = manual;
return SendPacket(p);
}
bool Device::SendFirmwareChunk(Protocol::FirmwarePacket &fw)
{
if(m_connected) {
unsigned char buffer[Protocol::FirmwareChunkSize + 4 + 8];
Protocol::PacketInfo p;
p.type = Protocol::PacketType::FirmwarePacket;
p.firmware = fw;
unsigned int length = Protocol::EncodePacket(p, buffer, sizeof(buffer));
if(!length) {
qCritical() << "Failed to encode packet";
return false;
}
int actual_length;
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
if(ret < 0) {
qCritical() << "Error sending data: "
<< libusb_strerror((libusb_error) ret);
return false;
}
return true;
} else {
return false;
}
Protocol::PacketInfo p;
p.type = Protocol::PacketType::FirmwarePacket;
p.firmware = fw;
return SendPacket(p);
}
bool Device::SendCommandWithoutPayload(Protocol::PacketType type)
{
if(m_connected) {
unsigned char buffer[32];
Protocol::PacketInfo p;
p.type = type;
unsigned int length = Protocol::EncodePacket(p, buffer, sizeof(buffer));
if(!length) {
qCritical() << "Failed to encode packet";
return false;
}
int actual_length;
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
if(ret < 0) {
qCritical() << "Error sending data: "
<< libusb_strerror((libusb_error) ret);
return false;
}
return true;
} else {
return false;
}
Protocol::PacketInfo p;
p.type = type;
return SendPacket(p);
}
std::set<QString> Device::GetDevices()

View File

@ -46,6 +46,7 @@ public:
// connect to a VNA device. If serial is specified only connecting to this device, otherwise to the first one found
Device(QString serial = QString());
~Device();
bool SendPacket(Protocol::PacketInfo packet);
bool Configure(Protocol::SweepSettings settings);
bool SetManual(Protocol::ManualControl manual);
bool SendFirmwareChunk(Protocol::FirmwarePacket &fw);

View File

@ -403,7 +403,6 @@ void VNA::ConnectToDevice(QString serial)
lConnectionStatus.setText("Connected to " + device->serial());
qInfo() << "Connected to " << device->serial();
lDeviceInfo.setText(device->getLastDeviceInfoString());
device->Configure(settings);
connect(device, &Device::DatapointReceived, this, &VNA::NewDatapoint);
connect(device, &Device::LogLineReceived, &deviceLog, &DeviceLog::addLine);
connect(device, &Device::ConnectionLost, this, &VNA::DeviceConnectionLost);
@ -414,21 +413,26 @@ void VNA::ConnectToDevice(QString serial)
ui->actionManual_Control->setEnabled(true);
ui->menuDefault_Calibration->setEnabled(true);
ui->actionFirmware_Update->setEnabled(true);
// Check if default calibration exists and attempt to load it
QSettings settings;
auto key = "DefaultCalibration"+device->serial();
if (settings.contains(key)) {
auto filename = settings.value(key).toString();
qDebug() << "Attempting to load default calibration file \"" << filename << "\"";
if(QFile::exists(filename)) {
cal.openFromFile(filename);
ApplyCalibration(cal.getType());
{
// Check if default calibration exists and attempt to load it
QSettings settings;
auto key = "DefaultCalibration"+device->serial();
if (settings.contains(key)) {
auto filename = settings.value(key).toString();
qDebug() << "Attempting to load default calibration file \"" << filename << "\"";
if(QFile::exists(filename)) {
cal.openFromFile(filename);
ApplyCalibration(cal.getType());
}
ui->actionRemoveDefaultCal->setEnabled(true);
} else {
qDebug() << "No default calibration file set for this device";
ui->actionRemoveDefaultCal->setEnabled(false);
}
ui->actionRemoveDefaultCal->setEnabled(true);
} else {
qDebug() << "No default calibration file set for this device";
ui->actionRemoveDefaultCal->setEnabled(false);
}
// Configure initial state of device
device->Configure(settings);
UpdateReference();
} catch (const runtime_error e) {
DisconnectDevice();
UpdateDeviceList();
@ -553,26 +557,28 @@ void VNA::CreateToolbars()
// Reference toolbar
auto tb_reference = new QToolBar("Reference", this);
tb_reference->addWidget(new QLabel("Ref:"));
toolbars.referenceType = new QComboBox();
toolbars.referenceType->addItem("Int");
toolbars.referenceType->addItem("Ext");
auto refInAuto = new QCheckBox("Auto");
refInAuto->setChecked(true);
toolbars.referenceType->setEnabled(false);
connect(refInAuto, &QCheckBox::clicked, [this](bool checked) {
// TODO change device settings
toolbars.referenceType->setEnabled(!checked);
toolbars.reference.type = new QComboBox();
toolbars.reference.type->addItem("Int");
toolbars.reference.type->addItem("Ext");
toolbars.reference.automatic = new QCheckBox("Auto");
connect(toolbars.reference.automatic, &QCheckBox::clicked, [this](bool checked) {
toolbars.reference.type->setEnabled(!checked);
UpdateReference();
});
tb_reference->addWidget(toolbars.referenceType);
tb_reference->addWidget(refInAuto);
// toolbars.reference.automatic->setChecked(true);
tb_reference->addWidget(toolbars.reference.type);
tb_reference->addWidget(toolbars.reference.automatic);
tb_reference->addSeparator();
tb_reference->addWidget(new QLabel("Ref out:"));
auto refOutEnabled = new QCheckBox();
auto refOutFreq = new QComboBox();
refOutFreq->addItem("10 MHz");
refOutFreq->addItem("100 MHz");
tb_reference->addWidget(refOutEnabled);
tb_reference->addWidget(refOutFreq);
toolbars.reference.outputEnabled = new QCheckBox();
toolbars.reference.outFreq = new QComboBox();
toolbars.reference.outFreq->addItem("10 MHz");
toolbars.reference.outFreq->addItem("100 MHz");
tb_reference->addWidget(toolbars.reference.outputEnabled);
tb_reference->addWidget(toolbars.reference.outFreq);
connect(toolbars.reference.type, qOverload<int>(&QComboBox::currentIndexChanged), this, &VNA::UpdateReference);
connect(toolbars.reference.outFreq, qOverload<int>(&QComboBox::currentIndexChanged), this, &VNA::UpdateReference);
connect(toolbars.reference.outputEnabled, &QCheckBox::clicked, this, &VNA::UpdateReference);
addToolBar(tb_reference);
@ -860,6 +866,35 @@ void VNA::StartCalibrationMeasurement(Calibration::Measurement m)
});
}
void VNA::UpdateReference()
{
if(!device) {
// can't update without a device connected
return;
}
Protocol::ReferenceSettings s = {};
if(toolbars.reference.automatic->isChecked()) {
s.AutomaticSwitch = 1;
}
if(toolbars.reference.type->currentText()=="Ext") {
s.UseExternalRef = 1;
}
if(toolbars.reference.outputEnabled->isChecked()) {
switch(toolbars.reference.outFreq->currentIndex()) {
case 0:
s.ExtRefOuputFreq = 10000000;
break;
case 1:
s.ExtRefOuputFreq = 100000000;
break;
}
}
Protocol::PacketInfo p;
p.type = Protocol::PacketType::Reference;
p.reference = s;
device->SendPacket(p);
}
void VNA::ConstrainAndUpdateFrequencies()
{
if(settings.f_stop > maxFreq) {

View File

@ -17,6 +17,7 @@
#include "Device/devicelog.h"
#include "preferences.h"
#include <QButtonGroup>
#include <QCheckBox>
namespace Ui {
class MainWindow;
@ -63,6 +64,7 @@ private slots:
void DisableCalibration(bool force = false);
void ApplyCalibration(Calibration::Type type);
void StartCalibrationMeasurement(Calibration::Measurement m);
void UpdateReference();
signals:
void CalibrationMeasurementComplete(Calibration::Measurement m);
@ -110,7 +112,12 @@ private:
QStackedWidget *central;
struct {
QComboBox *referenceType;
struct {
QComboBox *type;
QCheckBox *automatic;
QCheckBox *outputEnabled;
QComboBox *outFreq;
} reference;
} toolbars;
Preferences pref;

View File

@ -100,6 +100,7 @@ void App_Start() {
uint32_t lastNewPoint = HAL_GetTick();
bool sweepActive = false;
Protocol::ReferenceSettings reference;
while (1) {
uint32_t notification;
@ -113,39 +114,16 @@ void App_Start() {
lastNewPoint = HAL_GetTick();
if(result.pointNum == settings.points - 1) {
// end of sweep
// read PLL temperatures
uint8_t tempSource, tempLO;
VNA::GetTemps(&tempSource, &tempLO);
LOG_INFO("PLL temperatures: %u/%u", tempSource, tempLO);
// Read ADC min/max
auto limits = FPGA::GetADCLimits();
#define ADC_LIMIT 30000
VNA::Ref::applySettings(reference);
// Compile info packet
packet.type = Protocol::PacketType::DeviceInfo;
packet.info.FPGA_configured = 1;
if(limits.P1min < -ADC_LIMIT || limits.P1max > ADC_LIMIT
|| limits.P2min < -ADC_LIMIT || limits.P2max > ADC_LIMIT
|| limits.Rmin < -ADC_LIMIT || limits.Rmax > ADC_LIMIT) {
packet.info.ADC_overload = true;
} else {
packet.info.ADC_overload = false;
}
packet.info.FW_major = FW_MAJOR;
packet.info.FW_minor = FW_MINOR;
packet.info.HW_Revision = HW_REVISION;
auto status = FPGA::GetStatus();
packet.info.LO1_locked = (status & (int) FPGA::Interrupt::LO1Unlock) ? 0 : 1;
packet.info.source_locked = (status & (int) FPGA::Interrupt::SourceUnlock) ? 0 : 1;
packet.info.extRefAvailable = 0;
packet.info.extRefInUse = 0;
packet.info.temperatures.LO1 = tempLO;
packet.info.temperatures.source = tempSource;
packet.info.temperatures.MCU = 0;
VNA::fillDeviceInfo(&packet.info);
Communication::Send(packet);
FPGA::ResetADCLimits();
LOG_INFO("ADC limits: P1: %d/%d P2: %d/%d R: %d/%d",
limits.P1min, limits.P1max, limits.P2min, limits.P2max,
limits.Rmin, limits.Rmax);
// Start next sweep
FPGA::StartSweep();
}
@ -194,6 +172,13 @@ void App_Start() {
manual = packet.manual;
VNA::ConfigureManual(manual, VNAStatusCallback);
break;
case Protocol::PacketType::Reference:
reference = packet.reference;
if(!sweepActive) {
// can update right now
VNA::Ref::applySettings(reference);
}
break;
#ifdef HAS_FLASH
case Protocol::PacketType::ClearFlash:
FPGA::AbortSweep();
@ -238,7 +223,10 @@ void App_Start() {
if(sweepActive && HAL_GetTick() - lastNewPoint > 1000) {
LOG_WARN("Timed out waiting for point, last received point was %d", result.pointNum);
LOG_WARN("FPGA status: 0x%04x", FPGA::GetStatus());
FPGA::AbortSweep();
// restart the current sweep
VNA::Init();
VNA::Ref::applySettings(reference);
VNA::ConfigureSweep(settings, VNACallback);
sweepActive = true;
lastNewPoint = HAL_GetTick();

View File

@ -187,6 +187,23 @@ static int16_t EncodeSweepSettings(Protocol::SweepSettings d, uint8_t *buf,
return e.getSize();
}
static Protocol::ReferenceSettings DecodeReferenceSettings(uint8_t *buf) {
Protocol::ReferenceSettings d;
Decoder e(buf);
e.get<uint32_t>(d.ExtRefOuputFreq);
d.AutomaticSwitch = e.getBits(1);
d.UseExternalRef = e.getBits(1);
return d;
}
static int16_t EncodeReferenceSettings(Protocol::ReferenceSettings d, uint8_t *buf,
uint16_t bufSize) {
Encoder e(buf, bufSize);
e.add<uint32_t>(d.ExtRefOuputFreq);
e.addBits(d.AutomaticSwitch, 1);
e.addBits(d.UseExternalRef, 1);
return e.getSize();
}
static Protocol::DeviceInfo DecodeDeviceInfo(uint8_t *buf) {
Protocol::DeviceInfo d;
Decoder e(buf);
@ -388,6 +405,9 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
case PacketType::SweepSettings:
info->settings = DecodeSweepSettings(&data[4]);
break;
case PacketType::Reference:
info->reference = DecodeReferenceSettings(&data[4]);
break;
case PacketType::DeviceInfo:
info->info = DecodeDeviceInfo(&data[4]);
break;
@ -403,6 +423,7 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
case PacketType::Ack:
case PacketType::PerformFirmwareUpdate:
case PacketType::ClearFlash:
case PacketType::Nack:
// no payload, nothing to do
break;
case PacketType::None:
@ -421,6 +442,9 @@ uint16_t Protocol::EncodePacket(PacketInfo packet, uint8_t *dest, uint16_t dests
case PacketType::SweepSettings:
payload_size = EncodeSweepSettings(packet.settings, &dest[4], destsize - 8);
break;
case PacketType::Reference:
payload_size = EncodeReferenceSettings(packet.reference, &dest[4], destsize - 8);
break;
case PacketType::DeviceInfo:
payload_size = EncodeDeviceInfo(packet.info, &dest[4], destsize - 8);
break;
@ -436,6 +460,7 @@ uint16_t Protocol::EncodePacket(PacketInfo packet, uint8_t *dest, uint16_t dests
case PacketType::Ack:
case PacketType::PerformFirmwareUpdate:
case PacketType::ClearFlash:
case PacketType::Nack:
// no payload, nothing to do
break;
case PacketType::None:

View File

@ -23,6 +23,12 @@ using SweepSettings = struct _sweepSettings {
int16_t cdbm_excitation; // in 1/100 dbm
};
using ReferenceSettings = struct _referenceSettings {
uint32_t ExtRefOuputFreq;
uint8_t AutomaticSwitch:1;
uint8_t UseExternalRef:1;
};
using DeviceInfo = struct _deviceInfo {
uint16_t FW_major;
uint16_t FW_minor;
@ -102,6 +108,7 @@ enum class PacketType : uint8_t {
ClearFlash = 8,
PerformFirmwareUpdate = 9,
Nack = 10,
Reference = 11,
};
using PacketInfo = struct _packetinfo {
@ -109,6 +116,7 @@ using PacketInfo = struct _packetinfo {
union {
Datapoint datapoint;
SweepSettings settings;
ReferenceSettings reference;
DeviceInfo info;
ManualControl manual;
ManualStatus status;

View File

@ -63,6 +63,8 @@ bool FPGA::Configure(Flash *f, uint32_t start_address, uint32_t bitstream_size)
bool FPGA::Init(HaltedCallback cb) {
halted_cb = cb;
SysCtrlReg = 0;
ISRMaskReg = 0;
// Reset FPGA
High(FPGA_RESET);
SetMode(Mode::FPGA);

View File

@ -2,12 +2,32 @@
#include <cmath>
#define LOG_LEVEL LOG_LEVEL_INFO
#define LOG_LEVEL LOG_LEVEL_DEBUG
#define LOG_MODULE "SI5351"
#include "Log.h"
bool Si5351C::Init(uint32_t clkin_freq) {
bool success = true;
FreqCLKINDiv = 0;
// Disable OEB pin functionality
success &= WriteRegister(Reg::OEBPinMask, 0xFF);
// Disable all outputs
success &= WriteRegister(Reg::OutputEnableControl, 0xFF);
// Enable fanouts
success &= WriteRegister(Reg::FanoutEnable, 0xD0);
if(success) {
LOG_INFO("Initialized");
} else {
LOG_ERR("Initialization failed");
}
return success;
}
bool Si5351C::ConfigureCLKIn(uint32_t clkin_freq) {
bool success = true;
uint8_t clkinDiv = 0;
while (clkin_freq / (1 << clkinDiv) > 40000000) {
@ -26,19 +46,6 @@ bool Si5351C::Init(uint32_t clkin_freq) {
value |= clkinDiv << 6;
success &= WriteRegister(Reg::PLLInputSource, value);
// Disable OEB pin functionality
success &= WriteRegister(Reg::OEBPinMask, 0xFF);
// Disable all outputs
success &= WriteRegister(Reg::OutputEnableControl, 0xFF);
// Enable fanouts
success &= WriteRegister(Reg::FanoutEnable, 0xD0);
if(success) {
LOG_INFO("Initialized");
} else {
LOG_ERR("Initialization failed");
}
return success;
}
@ -278,6 +285,17 @@ bool Si5351C::WriteRegisterRange(Reg start, const uint8_t *data, uint8_t len) {
I2C_MEMADD_SIZE_8BIT, (uint8_t*) data, len, 100) == HAL_OK;
}
bool Si5351C::ExtCLKAvailable() {
uint8_t value;
ReadRegister(Reg::DeviceStatus, &value);
LOG_DEBUG("Device status: 0x%02x", value);
if (value & 0x10) {
return false;
} else {
return true;
}
}
bool Si5351C::ReadRegisterRange(Reg start, uint8_t *data, uint8_t len) {
return HAL_I2C_Mem_Read(i2c, address, (int) start,
I2C_MEMADD_SIZE_8BIT, data, len, 100) == HAL_OK;
@ -338,3 +356,5 @@ bool Si5351C::ReadRawCLKConfig(uint8_t clknum, uint8_t *config) {
auto reg = (Reg) ((int) Reg::MS0_CONFIG + 8 * clknum);
return ReadRegisterRange(reg, config, 8);
}

View File

@ -30,6 +30,7 @@ public:
FreqCLKINDiv(0) {
};
bool Init(uint32_t clkin_freq = 0);
bool ConfigureCLKIn(uint32_t clkin_freq);
bool SetPLL(PLL pll, uint32_t frequency, PLLSource src);
bool SetCLK(uint8_t clknum, uint32_t frequency, PLL source, DriveStrength strength = DriveStrength::mA2, uint32_t PLLFreqOverride = 0);
bool SetCLKtoXTAL(uint8_t clknum);
@ -38,6 +39,7 @@ public:
bool Disable(uint8_t clknum);
bool Locked(PLL pll);
bool ResetPLL(PLL pll);
bool ExtCLKAvailable();
// Direct register access of clk configuration registers
// config has to point to a buffer containing at least 8 bytes

View File

@ -36,6 +36,9 @@ static uint16_t IFTableIndexCnt = 0;
static constexpr uint32_t BandSwitchFrequency = 25000000;
static uint32_t extOutFreq = 0;
static bool extRefInUse = false;
using namespace VNAHAL;
static void HaltedCallback() {
@ -129,6 +132,10 @@ bool VNA::Init() {
Si5351.SetPLL(Si5351C::PLL::B, 800000000, Si5351C::PLLSource::XTAL);
while(!Si5351.Locked(Si5351C::PLL::B));
extRefInUse = 0;
extOutFreq = 0;
Si5351.Disable(SiChannel::ReferenceOut);
// Both MAX2871 get a 100MHz reference
Si5351.SetCLK(SiChannel::Source, 100000000, Si5351C::PLL::A, Si5351C::DriveStrength::mA2);
Si5351.Enable(SiChannel::Source);
@ -137,10 +144,6 @@ bool VNA::Init() {
// 16MHz FPGA clock
Si5351.SetCLK(SiChannel::FPGA, 16000000, Si5351C::PLL::A, Si5351C::DriveStrength::mA2);
Si5351.Enable(SiChannel::FPGA);
// TODO reference settings controllable through USB
// // 10 MHz external reference clock
// Si5351.SetCLK(6, 10000000, Si5351C::PLL::A, Si5351C::DriveStrength::mA8);
// Si5351.Enable(6);
// Generate second LO with Si5351
Si5351.SetCLK(SiChannel::Port1LO2, IF1 - IF2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
@ -410,3 +413,80 @@ bool VNA::GetTemps(uint8_t *source, uint8_t *lo) {
FPGA::SetMode(FPGA::Mode::FPGA);
return true;
}
void VNA::fillDeviceInfo(Protocol::DeviceInfo *info) {
// read PLL temperatures
uint8_t tempSource, tempLO;
VNA::GetTemps(&tempSource, &tempLO);
LOG_INFO("PLL temperatures: %u/%u", tempSource, tempLO);
// Read ADC min/max
auto limits = FPGA::GetADCLimits();
LOG_INFO("ADC limits: P1: %d/%d P2: %d/%d R: %d/%d",
limits.P1min, limits.P1max, limits.P2min, limits.P2max,
limits.Rmin, limits.Rmax);
#define ADC_LIMIT 30000
// Set VNA related member of info struct
if(limits.P1min < -ADC_LIMIT || limits.P1max > ADC_LIMIT
|| limits.P2min < -ADC_LIMIT || limits.P2max > ADC_LIMIT
|| limits.Rmin < -ADC_LIMIT || limits.Rmax > ADC_LIMIT) {
info->ADC_overload = true;
} else {
info->ADC_overload = false;
}
auto status = FPGA::GetStatus();
info->LO1_locked = (status & (int) FPGA::Interrupt::LO1Unlock) ? 0 : 1;
info->source_locked = (status & (int) FPGA::Interrupt::SourceUnlock) ? 0 : 1;
info->extRefAvailable = Ref::available();
info->extRefInUse = extRefInUse;
info->temperatures.LO1 = tempLO;
info->temperatures.source = tempSource;
info->temperatures.MCU = 0;
FPGA::ResetADCLimits();
}
bool VNA::Ref::available() {
return Si5351.ExtCLKAvailable();
}
bool VNA::Ref::applySettings(Protocol::ReferenceSettings s) {
if(extOutFreq != s.ExtRefOuputFreq) {
extOutFreq = s.ExtRefOuputFreq;
if(extOutFreq == 0) {
Si5351.Disable(SiChannel::ReferenceOut);
LOG_INFO("External reference output disabled");
} else {
Si5351.SetCLK(SiChannel::ReferenceOut, extOutFreq, Si5351C::PLL::A);
Si5351.Enable(SiChannel::ReferenceOut);
LOG_INFO("External reference output set to %luHz", extOutFreq);
}
}
bool useExternal = s.UseExternalRef || (s.AutomaticSwitch && Ref::available());
if(useExternal != extRefInUse) {
// switch between internal and external reference
extRefInUse = useExternal;
if(extRefInUse) {
if(!Ref::available()) {
LOG_WARN("Forced switch to external reference but no signal detected");
}
Si5351.ConfigureCLKIn(10000000);
Si5351.SetPLL(Si5351C::PLL::A, 800000000, Si5351C::PLLSource::CLKIN);
Si5351.SetPLL(Si5351C::PLL::B, 800000000, Si5351C::PLLSource::CLKIN);
LOG_INFO("Switched to external reference");
FPGA::Enable(FPGA::Periphery::ExtRefLED);
} else {
Si5351.SetPLL(Si5351C::PLL::A, 800000000, Si5351C::PLLSource::XTAL);
Si5351.SetPLL(Si5351C::PLL::B, 800000000, Si5351C::PLLSource::XTAL);
LOG_INFO("Switched to internal reference");
FPGA::Disable(FPGA::Periphery::ExtRefLED);
}
}
constexpr uint32_t lock_timeout = 10;
uint32_t start = HAL_GetTick();
while(!Si5351.Locked(Si5351C::PLL::A) || !Si5351.Locked(Si5351C::PLL::A)) {
if(HAL_GetTick() - start > lock_timeout) {
LOG_ERR("Clock distributor PLLs failed to lock");
return false;
}
}
return false;
}

View File

@ -12,7 +12,14 @@ using StatusCallback = void(*)(FPGA::SamplingResult);
bool Init();
bool ConfigureSweep(Protocol::SweepSettings s, SweepCallback cb);
bool ConfigureManual(Protocol::ManualControl m, StatusCallback cb);
// Only call the following function when the sweep is inactive
bool GetTemps(uint8_t *source, uint8_t *lo);
void fillDeviceInfo(Protocol::DeviceInfo *info);
namespace Ref {
bool available();
bool applySettings(Protocol::ReferenceSettings s);
}
}