TCXO offset calibration
This commit is contained in:
parent
4f4b2db549
commit
938f444c73
39
Software/PC_Application/Calibration/frequencycaldialog.cpp
Normal file
39
Software/PC_Application/Calibration/frequencycaldialog.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "frequencycaldialog.h"
|
||||||
|
#include "ui_frequencycaldialog.h"
|
||||||
|
|
||||||
|
FrequencyCalDialog::FrequencyCalDialog(Device *dev, QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::FrequencyCalDialog),
|
||||||
|
dev(dev)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->ppm->setUnit("ppm");
|
||||||
|
ui->ppm->setPrefixes(" ");
|
||||||
|
ui->ppm->setPrecision(4);
|
||||||
|
ui->ppm->setValue(0.0);
|
||||||
|
|
||||||
|
connect(dev, &Device::FrequencyCorrectionReceived, ui->ppm, &SIUnitEdit::setValueQuiet);
|
||||||
|
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
connect(ui->buttonBox, &QDialogButtonBox::accepted, [=](){
|
||||||
|
// get value and transfer to device
|
||||||
|
Protocol::PacketInfo p;
|
||||||
|
p.type = Protocol::PacketType::FrequencyCorrection;
|
||||||
|
p.frequencyCorrection.ppm = ui->ppm->value();
|
||||||
|
dev->SendPacket(p);
|
||||||
|
// force restart of current mode for setting to take effect
|
||||||
|
auto activeMode = Mode::getActiveMode();
|
||||||
|
activeMode->deactivate();
|
||||||
|
activeMode->activate();
|
||||||
|
accept();
|
||||||
|
delete this;
|
||||||
|
});
|
||||||
|
|
||||||
|
// request setting from device
|
||||||
|
dev->SendCommandWithoutPayload(Protocol::PacketType::RequestFrequencyCorrection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FrequencyCalDialog::~FrequencyCalDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
25
Software/PC_Application/Calibration/frequencycaldialog.h
Normal file
25
Software/PC_Application/Calibration/frequencycaldialog.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef FREQUENCYCALDIALOG_H
|
||||||
|
#define FREQUENCYCALDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "Device/device.h"
|
||||||
|
#include "mode.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class FrequencyCalDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FrequencyCalDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FrequencyCalDialog(Device *dev, QWidget *parent = nullptr);
|
||||||
|
~FrequencyCalDialog();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::FrequencyCalDialog *ui;
|
||||||
|
Device *dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FREQUENCYCALDIALOG_H
|
124
Software/PC_Application/Calibration/frequencycaldialog.ui
Normal file
124
Software/PC_Application/Calibration/frequencycaldialog.ui
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>FrequencyCalDialog</class>
|
||||||
|
<widget class="QDialog" name="FrequencyCalDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>363</width>
|
||||||
|
<height>178</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Frequency Calibration</string>
|
||||||
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Specify the error of the internal TCXO to correct for it during measurements and signal generation. This setting has no effect when an external reference is used.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TCXO offset:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="SIUnitEdit" name="ppm"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>SIUnitEdit</class>
|
||||||
|
<extends>QLineEdit</extends>
|
||||||
|
<header>CustomWidgets/siunitedit.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>FrequencyCalDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>FrequencyCalDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
@ -459,6 +459,9 @@ void Device::ReceivedData()
|
|||||||
emit NackReceived();
|
emit NackReceived();
|
||||||
emit receivedAnswer(TransmissionResult::Nack);
|
emit receivedAnswer(TransmissionResult::Nack);
|
||||||
break;
|
break;
|
||||||
|
case Protocol::PacketType::FrequencyCorrection:
|
||||||
|
emit FrequencyCorrectionReceived(packet.frequencyCorrection.ppm);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,7 @@ signals:
|
|||||||
void ManualStatusReceived(Protocol::ManualStatus);
|
void ManualStatusReceived(Protocol::ManualStatus);
|
||||||
void SpectrumResultReceived(Protocol::SpectrumAnalyzerResult);
|
void SpectrumResultReceived(Protocol::SpectrumAnalyzerResult);
|
||||||
void AmplitudeCorrectionPointReceived(Protocol::AmplitudeCorrectionPoint);
|
void AmplitudeCorrectionPointReceived(Protocol::AmplitudeCorrectionPoint);
|
||||||
|
void FrequencyCorrectionReceived(float ppm);
|
||||||
void DeviceInfoUpdated();
|
void DeviceInfoUpdated();
|
||||||
void ConnectionLost();
|
void ConnectionLost();
|
||||||
void AckReceived();
|
void AckReceived();
|
||||||
|
@ -5,6 +5,7 @@ HEADERS += \
|
|||||||
Calibration/calibrationtracedialog.h \
|
Calibration/calibrationtracedialog.h \
|
||||||
Calibration/calkit.h \
|
Calibration/calkit.h \
|
||||||
Calibration/calkitdialog.h \
|
Calibration/calkitdialog.h \
|
||||||
|
Calibration/frequencycaldialog.h \
|
||||||
Calibration/manualcalibrationdialog.h \
|
Calibration/manualcalibrationdialog.h \
|
||||||
Calibration/measurementmodel.h \
|
Calibration/measurementmodel.h \
|
||||||
Calibration/receivercaldialog.h \
|
Calibration/receivercaldialog.h \
|
||||||
@ -128,6 +129,7 @@ SOURCES += \
|
|||||||
Calibration/calibrationtracedialog.cpp \
|
Calibration/calibrationtracedialog.cpp \
|
||||||
Calibration/calkit.cpp \
|
Calibration/calkit.cpp \
|
||||||
Calibration/calkitdialog.cpp \
|
Calibration/calkitdialog.cpp \
|
||||||
|
Calibration/frequencycaldialog.cpp \
|
||||||
Calibration/manualcalibrationdialog.cpp \
|
Calibration/manualcalibrationdialog.cpp \
|
||||||
Calibration/measurementmodel.cpp \
|
Calibration/measurementmodel.cpp \
|
||||||
Calibration/receivercaldialog.cpp \
|
Calibration/receivercaldialog.cpp \
|
||||||
@ -244,6 +246,7 @@ FORMS += \
|
|||||||
Calibration/automaticamplitudedialog.ui \
|
Calibration/automaticamplitudedialog.ui \
|
||||||
Calibration/calibrationtracedialog.ui \
|
Calibration/calibrationtracedialog.ui \
|
||||||
Calibration/calkitdialog.ui \
|
Calibration/calkitdialog.ui \
|
||||||
|
Calibration/frequencycaldialog.ui \
|
||||||
Calibration/manualcalibrationdialog.ui \
|
Calibration/manualcalibrationdialog.ui \
|
||||||
CustomWidgets/jsonpickerdialog.ui \
|
CustomWidgets/jsonpickerdialog.ui \
|
||||||
CustomWidgets/tilewidget.ui \
|
CustomWidgets/tilewidget.ui \
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "SpectrumAnalyzer/spectrumanalyzer.h"
|
#include "SpectrumAnalyzer/spectrumanalyzer.h"
|
||||||
#include "Calibration/sourcecaldialog.h"
|
#include "Calibration/sourcecaldialog.h"
|
||||||
#include "Calibration/receivercaldialog.h"
|
#include "Calibration/receivercaldialog.h"
|
||||||
|
#include "Calibration/frequencycaldialog.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "CustomWidgets/jsonpickerdialog.h"
|
#include "CustomWidgets/jsonpickerdialog.h"
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
@ -185,6 +186,7 @@ AppWindow::AppWindow(QWidget *parent)
|
|||||||
connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
|
connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
|
||||||
connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
|
connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
|
||||||
connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog);
|
connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog);
|
||||||
|
connect(ui->actionFrequency_Calibration, &QAction::triggered, this, &AppWindow::FrequencyCalibrationDialog);
|
||||||
connect(ui->actionPreferences, &QAction::triggered, [=](){
|
connect(ui->actionPreferences, &QAction::triggered, [=](){
|
||||||
// save previous SCPI settings in case they change
|
// save previous SCPI settings in case they change
|
||||||
auto &p = Preferences::getInstance();
|
auto &p = Preferences::getInstance();
|
||||||
@ -291,6 +293,7 @@ bool AppWindow::ConnectToDevice(QString serial)
|
|||||||
ui->actionFirmware_Update->setEnabled(true);
|
ui->actionFirmware_Update->setEnabled(true);
|
||||||
ui->actionSource_Calibration->setEnabled(true);
|
ui->actionSource_Calibration->setEnabled(true);
|
||||||
ui->actionReceiver_Calibration->setEnabled(true);
|
ui->actionReceiver_Calibration->setEnabled(true);
|
||||||
|
ui->actionFrequency_Calibration->setEnabled(true);
|
||||||
|
|
||||||
Mode::getActiveMode()->initializeDevice();
|
Mode::getActiveMode()->initializeDevice();
|
||||||
UpdateReference();
|
UpdateReference();
|
||||||
@ -321,6 +324,7 @@ void AppWindow::DisconnectDevice()
|
|||||||
ui->actionFirmware_Update->setEnabled(false);
|
ui->actionFirmware_Update->setEnabled(false);
|
||||||
ui->actionSource_Calibration->setEnabled(false);
|
ui->actionSource_Calibration->setEnabled(false);
|
||||||
ui->actionReceiver_Calibration->setEnabled(false);
|
ui->actionReceiver_Calibration->setEnabled(false);
|
||||||
|
ui->actionFrequency_Calibration->setEnabled(false);
|
||||||
for(auto a : deviceActionGroup->actions()) {
|
for(auto a : deviceActionGroup->actions()) {
|
||||||
a->setChecked(false);
|
a->setChecked(false);
|
||||||
}
|
}
|
||||||
@ -654,6 +658,12 @@ void AppWindow::ReceiverCalibrationDialog()
|
|||||||
d->exec();
|
d->exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppWindow::FrequencyCalibrationDialog()
|
||||||
|
{
|
||||||
|
auto d = new FrequencyCalDialog(device);
|
||||||
|
d->exec();
|
||||||
|
}
|
||||||
|
|
||||||
nlohmann::json AppWindow::SaveSetup()
|
nlohmann::json AppWindow::SaveSetup()
|
||||||
{
|
{
|
||||||
nlohmann::json j;
|
nlohmann::json j;
|
||||||
|
@ -53,6 +53,7 @@ private slots:
|
|||||||
void DeviceNeedsUpdate(int reported, int expected);
|
void DeviceNeedsUpdate(int reported, int expected);
|
||||||
void SourceCalibrationDialog();
|
void SourceCalibrationDialog();
|
||||||
void ReceiverCalibrationDialog();
|
void ReceiverCalibrationDialog();
|
||||||
|
void FrequencyCalibrationDialog();
|
||||||
nlohmann::json SaveSetup();
|
nlohmann::json SaveSetup();
|
||||||
void LoadSetup(nlohmann::json j);
|
void LoadSetup(nlohmann::json j);
|
||||||
private:
|
private:
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionSource_Calibration"/>
|
<addaction name="actionSource_Calibration"/>
|
||||||
<addaction name="actionReceiver_Calibration"/>
|
<addaction name="actionReceiver_Calibration"/>
|
||||||
|
<addaction name="actionFrequency_Calibration"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuWindow">
|
<widget class="QMenu" name="menuWindow">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -193,12 +194,21 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionSave_image">
|
<action name="actionSave_image">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="camera-photo"/>
|
<iconset theme="camera-photo">
|
||||||
|
<normaloff>.</normaloff>.</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save image...</string>
|
<string>Save image...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionFrequency_Calibration">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Frequency Calibration</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="icons.qrc"/>
|
<include location="icons.qrc"/>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <Cal.hpp>
|
||||||
#include <VNA.hpp>
|
#include <VNA.hpp>
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
|
|
||||||
@ -18,7 +19,6 @@
|
|||||||
#include "Generator.hpp"
|
#include "Generator.hpp"
|
||||||
#include "SpectrumAnalyzer.hpp"
|
#include "SpectrumAnalyzer.hpp"
|
||||||
#include "HW_HAL.hpp"
|
#include "HW_HAL.hpp"
|
||||||
#include "AmplitudeCal.hpp"
|
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||||
#define LOG_MODULE "App"
|
#define LOG_MODULE "App"
|
||||||
@ -86,7 +86,7 @@ void App_Start() {
|
|||||||
EN_6V_GPIO_Port->BSRR = EN_6V_Pin;
|
EN_6V_GPIO_Port->BSRR = EN_6V_Pin;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AmplitudeCal::Load();
|
Cal::Load();
|
||||||
|
|
||||||
if (!HW::Init()) {
|
if (!HW::Init()) {
|
||||||
LOG_CRIT("Initialization failed, unable to start");
|
LOG_CRIT("Initialization failed, unable to start");
|
||||||
@ -191,18 +191,31 @@ void App_Start() {
|
|||||||
#endif
|
#endif
|
||||||
case Protocol::PacketType::RequestSourceCal:
|
case Protocol::PacketType::RequestSourceCal:
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
AmplitudeCal::SendSource();
|
Cal::SendSource();
|
||||||
break;
|
break;
|
||||||
case Protocol::PacketType::RequestReceiverCal:
|
case Protocol::PacketType::RequestReceiverCal:
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
AmplitudeCal::SendReceiver();
|
Cal::SendReceiver();
|
||||||
break;
|
break;
|
||||||
case Protocol::PacketType::SourceCalPoint:
|
case Protocol::PacketType::SourceCalPoint:
|
||||||
AmplitudeCal::AddSourcePoint(recv_packet.amplitudePoint);
|
Cal::AddSourcePoint(recv_packet.amplitudePoint);
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
break;
|
break;
|
||||||
case Protocol::PacketType::ReceiverCalPoint:
|
case Protocol::PacketType::ReceiverCalPoint:
|
||||||
AmplitudeCal::AddReceiverPoint(recv_packet.amplitudePoint);
|
Cal::AddReceiverPoint(recv_packet.amplitudePoint);
|
||||||
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::RequestFrequencyCorrection:
|
||||||
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
|
{
|
||||||
|
Protocol::PacketInfo send;
|
||||||
|
send.type = Protocol::PacketType::FrequencyCorrection;
|
||||||
|
send.frequencyCorrection.ppm = Cal::getFrequencyCal();
|
||||||
|
Communication::Send(send);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::FrequencyCorrection:
|
||||||
|
Cal::setFrequencyCal(recv_packet.frequencyCorrection.ppm);
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "AmplitudeCal.hpp"
|
#include <Cal.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "Communication.h"
|
#include "Communication.h"
|
||||||
#include "HW_HAL.hpp"
|
#include "HW_HAL.hpp"
|
||||||
|
#include "Hardware.hpp"
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||||
#define LOG_MODULE "CAL"
|
#define LOG_MODULE "CAL"
|
||||||
@ -9,26 +10,27 @@
|
|||||||
|
|
||||||
|
|
||||||
// increment when Calibration struct format changed. If a wrong version is found in flash, it will revert to default values
|
// increment when Calibration struct format changed. If a wrong version is found in flash, it will revert to default values
|
||||||
static constexpr uint16_t version = 0x0000;
|
static constexpr uint16_t version = 0x0001;
|
||||||
|
|
||||||
using CorrectionTable = struct {
|
using CorrectionTable = struct {
|
||||||
uint8_t usedPoints;
|
uint8_t usedPoints;
|
||||||
uint32_t freq[AmplitudeCal::maxPoints]; // LSB = 10Hz
|
uint32_t freq[Cal::maxPoints]; // LSB = 10Hz
|
||||||
int16_t port1Correction[AmplitudeCal::maxPoints]; // LSB = 0.01db
|
int16_t port1Correction[Cal::maxPoints]; // LSB = 0.01db
|
||||||
int16_t port2Correction[AmplitudeCal::maxPoints]; // LSB = 0.01db
|
int16_t port2Correction[Cal::maxPoints]; // LSB = 0.01db
|
||||||
};
|
};
|
||||||
|
|
||||||
using Calibration = struct _calibration {
|
using Calibration = struct _calibration {
|
||||||
uint16_t version;
|
uint16_t version;
|
||||||
CorrectionTable Source;
|
CorrectionTable Source;
|
||||||
CorrectionTable Receiver;
|
CorrectionTable Receiver;
|
||||||
|
float TCXO_PPM_correction;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Calibration cal;
|
static Calibration cal;
|
||||||
|
|
||||||
static_assert(sizeof(cal) <= AmplitudeCal::flash_size, "Reserved flash size is too small");
|
static_assert(sizeof(cal) <= Cal::flash_size, "Reserved flash size is too small");
|
||||||
|
|
||||||
bool AmplitudeCal::Load() {
|
bool Cal::Load() {
|
||||||
HWHAL::flash.read(flash_address, sizeof(cal), &cal);
|
HWHAL::flash.read(flash_address, sizeof(cal), &cal);
|
||||||
if(cal.version != version) {
|
if(cal.version != version) {
|
||||||
LOG_WARN("Invalid version in flash, expected %u, got %u", version, cal.version);
|
LOG_WARN("Invalid version in flash, expected %u, got %u", version, cal.version);
|
||||||
@ -44,7 +46,7 @@ bool AmplitudeCal::Load() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmplitudeCal::Save() {
|
bool Cal::Save() {
|
||||||
if(!HWHAL::flash.eraseRange(flash_address, flash_size)) {
|
if(!HWHAL::flash.eraseRange(flash_address, flash_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -56,7 +58,7 @@ bool AmplitudeCal::Save() {
|
|||||||
return HWHAL::flash.write(flash_address, write_size, &cal);
|
return HWHAL::flash.write(flash_address, write_size, &cal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmplitudeCal::SetDefault() {
|
void Cal::SetDefault() {
|
||||||
memset(&cal, 0, sizeof(cal));
|
memset(&cal, 0, sizeof(cal));
|
||||||
cal.version = version;
|
cal.version = version;
|
||||||
cal.Source.usedPoints = 1;
|
cal.Source.usedPoints = 1;
|
||||||
@ -66,10 +68,10 @@ void AmplitudeCal::SetDefault() {
|
|||||||
LOG_INFO("Set to default");
|
LOG_INFO("Set to default");
|
||||||
}
|
}
|
||||||
|
|
||||||
static AmplitudeCal::Correction InterpolateCorrection(const CorrectionTable& table, uint64_t freq) {
|
static Cal::Correction InterpolateCorrection(const CorrectionTable& table, uint64_t freq) {
|
||||||
// adjust LSB to match table
|
// adjust LSB to match table
|
||||||
freq /= 10;
|
freq /= 10;
|
||||||
AmplitudeCal::Correction ret;
|
Cal::Correction ret;
|
||||||
// find first valid index that is higher than the given frequency
|
// find first valid index that is higher than the given frequency
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
for (; i < table.usedPoints; i++) {
|
for (; i < table.usedPoints; i++) {
|
||||||
@ -94,11 +96,11 @@ static AmplitudeCal::Correction InterpolateCorrection(const CorrectionTable& tab
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
AmplitudeCal::Correction AmplitudeCal::SourceCorrection(uint64_t freq) {
|
Cal::Correction Cal::SourceCorrection(uint64_t freq) {
|
||||||
return InterpolateCorrection(cal.Source, freq);
|
return InterpolateCorrection(cal.Source, freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
AmplitudeCal::Correction AmplitudeCal::ReceiverCorrection(uint64_t freq) {
|
Cal::Correction Cal::ReceiverCorrection(uint64_t freq) {
|
||||||
return InterpolateCorrection(cal.Receiver, freq);
|
return InterpolateCorrection(cal.Receiver, freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,34 +118,64 @@ static void SendCorrectionTable(const CorrectionTable& table, Protocol::PacketTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmplitudeCal::SendSource() {
|
void Cal::SendSource() {
|
||||||
SendCorrectionTable(cal.Source, Protocol::PacketType::SourceCalPoint);
|
SendCorrectionTable(cal.Source, Protocol::PacketType::SourceCalPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmplitudeCal::SendReceiver() {
|
void Cal::SendReceiver() {
|
||||||
SendCorrectionTable(cal.Receiver, Protocol::PacketType::ReceiverCalPoint);
|
SendCorrectionTable(cal.Receiver, Protocol::PacketType::ReceiverCalPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addPoint(CorrectionTable& table, const Protocol::AmplitudeCorrectionPoint& p) {
|
static void addPoint(CorrectionTable& table, const Protocol::AmplitudeCorrectionPoint& p) {
|
||||||
if(p.pointNum >= AmplitudeCal::maxPoints) {
|
if(p.pointNum >= Cal::maxPoints) {
|
||||||
// ignore out-of-bounds point
|
// ignore out-of-bounds point
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
table.freq[p.pointNum] = p.freq;
|
table.freq[p.pointNum] = p.freq;
|
||||||
table.port1Correction[p.pointNum] = p.port1;
|
table.port1Correction[p.pointNum] = p.port1;
|
||||||
table.port2Correction[p.pointNum] = p.port2;
|
table.port2Correction[p.pointNum] = p.port2;
|
||||||
if(p.pointNum == p.totalPoints - 1 || p.pointNum == AmplitudeCal::maxPoints - 1) {
|
if(p.pointNum == p.totalPoints - 1 || p.pointNum == Cal::maxPoints - 1) {
|
||||||
// this was the last point, update used points and save
|
// this was the last point, update used points and save
|
||||||
table.usedPoints = p.totalPoints;
|
table.usedPoints = p.totalPoints;
|
||||||
LOG_INFO("Last point received, saving to flash");
|
LOG_INFO("Last point received, saving to flash");
|
||||||
AmplitudeCal::Save();
|
Cal::Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmplitudeCal::AddSourcePoint(const Protocol::AmplitudeCorrectionPoint& p) {
|
void Cal::AddSourcePoint(const Protocol::AmplitudeCorrectionPoint& p) {
|
||||||
addPoint(cal.Source, p);
|
addPoint(cal.Source, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmplitudeCal::AddReceiverPoint(const Protocol::AmplitudeCorrectionPoint& p) {
|
void Cal::AddReceiverPoint(const Protocol::AmplitudeCorrectionPoint& p) {
|
||||||
addPoint(cal.Receiver, p);
|
addPoint(cal.Receiver, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t Cal::FrequencyCorrectionToDevice(uint64_t freq) {
|
||||||
|
// The frequency calibration is only used when the internal reference is active.
|
||||||
|
// If an external reference is in use, it is assumed to already be at the correct frequency
|
||||||
|
if(!HW::Ref::usingExternal()) {
|
||||||
|
freq -= freq * cal.TCXO_PPM_correction * 1e-6f;
|
||||||
|
}
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Cal::FrequencyCorrectionFromDevice(uint64_t freq) {
|
||||||
|
if(!HW::Ref::usingExternal()) {
|
||||||
|
// this formula is not exactly correct, it should actually be
|
||||||
|
// freq *= (1+PPM*10^-6). However, this can not be used directly
|
||||||
|
// due to floating point limitation. But the error of this approximation
|
||||||
|
// is so small that is doesn't make a difference (as the result only has
|
||||||
|
// 1Hz resolution anyway)
|
||||||
|
freq += freq * cal.TCXO_PPM_correction * 1e-6f;
|
||||||
|
}
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Cal::getFrequencyCal() {
|
||||||
|
return cal.TCXO_PPM_correction;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Cal::setFrequencyCal(float ppm) {
|
||||||
|
cal.TCXO_PPM_correction = ppm;
|
||||||
|
return Save();
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
#include "Firmware.hpp"
|
#include "Firmware.hpp"
|
||||||
#include "Protocol.hpp"
|
#include "Protocol.hpp"
|
||||||
|
|
||||||
namespace AmplitudeCal {
|
namespace Cal {
|
||||||
|
|
||||||
constexpr uint8_t maxPoints = 64;
|
constexpr uint8_t maxPoints = 64;
|
||||||
constexpr uint32_t flash_address = Firmware::maxSize; // stored directly behind firmware in flash
|
constexpr uint32_t flash_address = Firmware::maxSize; // stored directly behind firmware in flash
|
||||||
@ -22,9 +22,16 @@ using Correction = struct _correction {
|
|||||||
|
|
||||||
Correction SourceCorrection(uint64_t freq);
|
Correction SourceCorrection(uint64_t freq);
|
||||||
Correction ReceiverCorrection(uint64_t freq);
|
Correction ReceiverCorrection(uint64_t freq);
|
||||||
|
// converts a frequency as received from the GUI to a calibrated value that should be used for the PLLs etc.
|
||||||
|
uint64_t FrequencyCorrectionToDevice(uint64_t freq);
|
||||||
|
// corrects a measured frequency to its calibrated value for transfer to the GUI
|
||||||
|
uint64_t FrequencyCorrectionFromDevice(uint64_t freq);
|
||||||
void SendSource();
|
void SendSource();
|
||||||
void SendReceiver();
|
void SendReceiver();
|
||||||
void AddSourcePoint(const Protocol::AmplitudeCorrectionPoint& p);
|
void AddSourcePoint(const Protocol::AmplitudeCorrectionPoint& p);
|
||||||
void AddReceiverPoint(const Protocol::AmplitudeCorrectionPoint& p);
|
void AddReceiverPoint(const Protocol::AmplitudeCorrectionPoint& p);
|
||||||
|
|
||||||
|
float getFrequencyCal();
|
||||||
|
bool setFrequencyCal(float ppm);
|
||||||
|
|
||||||
}
|
}
|
@ -99,6 +99,7 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
|
|||||||
case PacketType::SpectrumAnalyzerResult: payload_size = sizeof(packet.spectrumResult); break;
|
case PacketType::SpectrumAnalyzerResult: payload_size = sizeof(packet.spectrumResult); break;
|
||||||
case PacketType::SourceCalPoint:
|
case PacketType::SourceCalPoint:
|
||||||
case PacketType::ReceiverCalPoint: payload_size = sizeof(packet.amplitudePoint); break;
|
case PacketType::ReceiverCalPoint: payload_size = sizeof(packet.amplitudePoint); break;
|
||||||
|
case PacketType::FrequencyCorrection: payload_size = sizeof(packet.frequencyCorrection); break;
|
||||||
case PacketType::Ack:
|
case PacketType::Ack:
|
||||||
case PacketType::PerformFirmwareUpdate:
|
case PacketType::PerformFirmwareUpdate:
|
||||||
case PacketType::ClearFlash:
|
case PacketType::ClearFlash:
|
||||||
@ -107,6 +108,7 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
|
|||||||
case PacketType::RequestSourceCal:
|
case PacketType::RequestSourceCal:
|
||||||
case PacketType::RequestReceiverCal:
|
case PacketType::RequestReceiverCal:
|
||||||
case PacketType::SetIdle:
|
case PacketType::SetIdle:
|
||||||
|
case PacketType::RequestFrequencyCorrection:
|
||||||
// no payload
|
// no payload
|
||||||
break;
|
break;
|
||||||
case PacketType::None:
|
case PacketType::None:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
namespace Protocol {
|
namespace Protocol {
|
||||||
|
|
||||||
static constexpr uint16_t Version = 4;
|
static constexpr uint16_t Version = 5;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
@ -152,6 +152,10 @@ using AmplitudeCorrectionPoint = struct _amplitudecorrectionpoint {
|
|||||||
int16_t port2;
|
int16_t port2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using FrequencyCorrection = struct _frequencycorrection {
|
||||||
|
float ppm;
|
||||||
|
};
|
||||||
|
|
||||||
enum class PacketType : uint8_t {
|
enum class PacketType : uint8_t {
|
||||||
None = 0,
|
None = 0,
|
||||||
Datapoint = 1,
|
Datapoint = 1,
|
||||||
@ -174,6 +178,8 @@ enum class PacketType : uint8_t {
|
|||||||
SourceCalPoint = 18,
|
SourceCalPoint = 18,
|
||||||
ReceiverCalPoint = 19,
|
ReceiverCalPoint = 19,
|
||||||
SetIdle = 20,
|
SetIdle = 20,
|
||||||
|
RequestFrequencyCorrection = 21,
|
||||||
|
FrequencyCorrection = 22,
|
||||||
};
|
};
|
||||||
|
|
||||||
using PacketInfo = struct _packetinfo {
|
using PacketInfo = struct _packetinfo {
|
||||||
@ -190,6 +196,7 @@ using PacketInfo = struct _packetinfo {
|
|||||||
SpectrumAnalyzerSettings spectrumSettings;
|
SpectrumAnalyzerSettings spectrumSettings;
|
||||||
SpectrumAnalyzerResult spectrumResult;
|
SpectrumAnalyzerResult spectrumResult;
|
||||||
AmplitudeCorrectionPoint amplitudePoint;
|
AmplitudeCorrectionPoint amplitudePoint;
|
||||||
|
FrequencyCorrection frequencyCorrection;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
#include <Cal.hpp>
|
||||||
#include "Generator.hpp"
|
#include "Generator.hpp"
|
||||||
#include "Manual.hpp"
|
#include "Manual.hpp"
|
||||||
#include "Hardware.hpp"
|
#include "Hardware.hpp"
|
||||||
#include "max2871.hpp"
|
#include "max2871.hpp"
|
||||||
#include "Si5351C.hpp"
|
#include "Si5351C.hpp"
|
||||||
#include "AmplitudeCal.hpp"
|
|
||||||
|
|
||||||
void Generator::Setup(Protocol::GeneratorSettings g) {
|
void Generator::Setup(Protocol::GeneratorSettings g) {
|
||||||
if(g.activePort == 0) {
|
if(g.activePort == 0) {
|
||||||
@ -35,6 +35,7 @@ void Generator::Setup(Protocol::GeneratorSettings g) {
|
|||||||
m.PortSwitch = 1;
|
m.PortSwitch = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
g.frequency = Cal::FrequencyCorrectionToDevice(g.frequency);
|
||||||
auto amplitude = HW::GetAmplitudeSettings(g.cdbm_level, g.frequency, g.applyAmplitudeCorrection, g.activePort == 2);
|
auto amplitude = HW::GetAmplitudeSettings(g.cdbm_level, g.frequency, g.applyAmplitudeCorrection, g.activePort == 2);
|
||||||
// Select correct source
|
// Select correct source
|
||||||
if(g.frequency < HW::BandSwitchFrequency) {
|
if(g.frequency < HW::BandSwitchFrequency) {
|
||||||
|
@ -235,7 +235,7 @@ void HW::SetIdle() {
|
|||||||
|
|
||||||
HW::AmplitudeSettings HW::GetAmplitudeSettings(int16_t cdbm, uint64_t freq, bool applyCorrections, bool port2) {
|
HW::AmplitudeSettings HW::GetAmplitudeSettings(int16_t cdbm, uint64_t freq, bool applyCorrections, bool port2) {
|
||||||
if (applyCorrections) {
|
if (applyCorrections) {
|
||||||
auto correction = AmplitudeCal::SourceCorrection(freq);
|
auto correction = Cal::SourceCorrection(freq);
|
||||||
if (port2) {
|
if (port2) {
|
||||||
cdbm += correction.port2;
|
cdbm += correction.port2;
|
||||||
} else {
|
} else {
|
||||||
@ -336,6 +336,10 @@ void HW::Ref::set(Protocol::ReferenceSettings s) {
|
|||||||
ref = s;
|
ref = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HW::Ref::usingExternal() {
|
||||||
|
return extRefInUse;
|
||||||
|
}
|
||||||
|
|
||||||
void HW::Ref::update() {
|
void HW::Ref::update() {
|
||||||
if(extOutFreq != ref.ExtRefOuputFreq) {
|
if(extOutFreq != ref.ExtRefOuputFreq) {
|
||||||
extOutFreq = ref.ExtRefOuputFreq;
|
extOutFreq = ref.ExtRefOuputFreq;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Cal.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "Protocol.hpp"
|
#include "Protocol.hpp"
|
||||||
#include "FPGA/FPGA.hpp"
|
#include "FPGA/FPGA.hpp"
|
||||||
#include "AmplitudeCal.hpp"
|
|
||||||
#include "max2871.hpp"
|
#include "max2871.hpp"
|
||||||
#include "Si5351C.hpp"
|
#include "Si5351C.hpp"
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ static constexpr Protocol::DeviceInfo Info = {
|
|||||||
.limits_cdbm_max = 0,
|
.limits_cdbm_max = 0,
|
||||||
.limits_minRBW = (uint32_t) (ADCSamplerate * 2.23f / MaxSamples),
|
.limits_minRBW = (uint32_t) (ADCSamplerate * 2.23f / MaxSamples),
|
||||||
.limits_maxRBW = (uint32_t) (ADCSamplerate * 2.23f / MinSamples),
|
.limits_maxRBW = (uint32_t) (ADCSamplerate * 2.23f / MinSamples),
|
||||||
.limits_maxAmplitudePoints = AmplitudeCal::maxPoints,
|
.limits_maxAmplitudePoints = Cal::maxPoints,
|
||||||
.limits_maxFreqHarmonic = 18000000000,
|
.limits_maxFreqHarmonic = 18000000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,6 +106,7 @@ bool GetTemps(uint8_t *source, uint8_t *lo);
|
|||||||
void fillDeviceInfo(Protocol::DeviceInfo *info, bool updateEvenWhenBusy = false);
|
void fillDeviceInfo(Protocol::DeviceInfo *info, bool updateEvenWhenBusy = false);
|
||||||
namespace Ref {
|
namespace Ref {
|
||||||
bool available();
|
bool available();
|
||||||
|
bool usingExternal();
|
||||||
// reference won't change until update is called
|
// reference won't change until update is called
|
||||||
void set(Protocol::ReferenceSettings s);
|
void set(Protocol::ReferenceSettings s);
|
||||||
void update();
|
void update();
|
||||||
|
@ -38,6 +38,7 @@ static bool trackingLowband;
|
|||||||
|
|
||||||
static void StartNextSample() {
|
static void StartNextSample() {
|
||||||
uint64_t freq = s.f_start + (s.f_stop - s.f_start) * pointCnt / (points - 1);
|
uint64_t freq = s.f_start + (s.f_stop - s.f_start) * pointCnt / (points - 1);
|
||||||
|
freq = Cal::FrequencyCorrectionToDevice(freq);
|
||||||
uint64_t LO1freq;
|
uint64_t LO1freq;
|
||||||
uint32_t LO2freq;
|
uint32_t LO2freq;
|
||||||
switch(signalIDstep) {
|
switch(signalIDstep) {
|
||||||
@ -364,7 +365,7 @@ void SA::Work() {
|
|||||||
p.spectrumResult.port1 /= 253000000.0;
|
p.spectrumResult.port1 /= 253000000.0;
|
||||||
p.spectrumResult.port2 /= 253000000.0;
|
p.spectrumResult.port2 /= 253000000.0;
|
||||||
if (s.applyReceiverCorrection) {
|
if (s.applyReceiverCorrection) {
|
||||||
auto correction = AmplitudeCal::ReceiverCorrection(p.spectrumResult.frequency);
|
auto correction = Cal::ReceiverCorrection(p.spectrumResult.frequency);
|
||||||
p.spectrumResult.port1 *= powf(10.0f, (float) correction.port1 / 100.0f / 20.0f);
|
p.spectrumResult.port1 *= powf(10.0f, (float) correction.port1 / 100.0f / 20.0f);
|
||||||
p.spectrumResult.port2 *= powf(10.0f, (float) correction.port2 / 100.0f / 20.0f);
|
p.spectrumResult.port2 *= powf(10.0f, (float) correction.port2 / 100.0f / 20.0f);
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,7 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||||||
for (uint16_t i = 0; i < points; i++) {
|
for (uint16_t i = 0; i < points; i++) {
|
||||||
bool harmonic_mixing = false;
|
bool harmonic_mixing = false;
|
||||||
uint64_t freq = s.f_start + (s.f_stop - s.f_start) * i / (points - 1);
|
uint64_t freq = s.f_start + (s.f_stop - s.f_start) * i / (points - 1);
|
||||||
|
freq = Cal::FrequencyCorrectionToDevice(freq);
|
||||||
|
|
||||||
if(freq > 6000000000ULL) {
|
if(freq > 6000000000ULL) {
|
||||||
harmonic_mixing = true;
|
harmonic_mixing = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user