Take automatic calibration measurements
This commit is contained in:
parent
cb0e553a17
commit
8301448343
@ -218,14 +218,203 @@ void LibreCALDialog::updateDeviceStatus()
|
||||
}
|
||||
|
||||
void LibreCALDialog::startCalibration()
|
||||
{
|
||||
disableUI();
|
||||
|
||||
ui->progressCal->setValue(0);
|
||||
ui->lCalibrationStatus->setText("Creating calibration kit from coefficients...");
|
||||
ui->lCalibrationStatus->setStyleSheet("QLabel { color : black; }");
|
||||
auto& kit = cal->getKit();
|
||||
kit.clearStandards();
|
||||
kit.manufacturer = "LibreCAL ("+coeffSet.name+")";
|
||||
kit.serialnumber = device->serial();
|
||||
kit.description = "Automatically created from LibreCAL module";
|
||||
std::vector<CalStandard::Virtual*> openStandards;
|
||||
std::vector<CalStandard::Virtual*> shortStandards;
|
||||
std::vector<CalStandard::Virtual*> loadStandards;
|
||||
std::vector<CalStandard::Virtual*> throughStandards;
|
||||
for(int i=1;i<=device->getNumPorts();i++) {
|
||||
if(coeffSet.opens[i-1]->t.points() > 0) {
|
||||
auto o = new CalStandard::Open();
|
||||
o->setName("Port "+QString::number(i));
|
||||
o->setMeasurement(coeffSet.opens[i-1]->t);
|
||||
openStandards.push_back(o);
|
||||
kit.standards.push_back(o);
|
||||
}
|
||||
if(coeffSet.shorts[i-1]->t.points() > 0) {
|
||||
auto o = new CalStandard::Short();
|
||||
o->setName("Port "+QString::number(i));
|
||||
o->setMeasurement(coeffSet.shorts[i-1]->t);
|
||||
shortStandards.push_back(o);
|
||||
kit.standards.push_back(o);
|
||||
}
|
||||
if(coeffSet.loads[i-1]->t.points() > 0) {
|
||||
auto o = new CalStandard::Load();
|
||||
o->setName("Port "+QString::number(i));
|
||||
o->setMeasurement(coeffSet.loads[i-1]->t);
|
||||
loadStandards.push_back(o);
|
||||
kit.standards.push_back(o);
|
||||
}
|
||||
for(int j=i+1;j<=device->getNumPorts();j++) {
|
||||
auto c = coeffSet.getThrough(i,j);
|
||||
if(!c) {
|
||||
continue;
|
||||
}
|
||||
if(c->t.points() > 0) {
|
||||
auto o = new CalStandard::Through();
|
||||
o->setName("Port "+QString::number(i)+" to "+QString::number(j));
|
||||
o->setMeasurement(c->t);
|
||||
throughStandards.push_back(o);
|
||||
kit.standards.push_back(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
ui->lCalibrationStatus->setText("Creating calibration measurements...");
|
||||
cal->reset();
|
||||
auto vnaPorts = VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;
|
||||
set<CalibrationMeasurement::Base*> openMeasurements;
|
||||
set<CalibrationMeasurement::Base*> shortMeasurements;
|
||||
set<CalibrationMeasurement::Base*> loadMeasurements;
|
||||
vector<CalibrationMeasurement::TwoPort*> throughMeasurements;
|
||||
for(int p=0;p<vnaPorts;p++) {
|
||||
if(portAssignment[p] == 0) {
|
||||
continue;
|
||||
}
|
||||
// Create SOL measurements with correct port of calkit
|
||||
auto open = new CalibrationMeasurement::Open(cal);
|
||||
open->setPort(p+1);
|
||||
open->setStandard(openStandards[portAssignment[p]-1]);
|
||||
openMeasurements.insert(open);
|
||||
cal->measurements.push_back(open);
|
||||
|
||||
auto _short = new CalibrationMeasurement::Short(cal);
|
||||
_short->setPort(p+1);
|
||||
_short->setStandard(shortStandards[portAssignment[p]-1]);
|
||||
shortMeasurements.insert(_short);
|
||||
cal->measurements.push_back(_short);
|
||||
|
||||
auto load = new CalibrationMeasurement::Load(cal);
|
||||
load->setPort(p+1);
|
||||
load->setStandard(loadStandards[portAssignment[p]-1]);
|
||||
loadMeasurements.insert(load);
|
||||
cal->measurements.push_back(load);
|
||||
for(int p2=p+1;p2<vnaPorts;p2++) {
|
||||
if(portAssignment[p2] == 0) {
|
||||
continue;
|
||||
}
|
||||
auto through = new CalibrationMeasurement::Through(cal);
|
||||
through->setPort1(p+1);
|
||||
through->setPort2(p2+1);
|
||||
// find correct through standard
|
||||
int libreCALp1 = portAssignment[p];
|
||||
int libreCALp2 = portAssignment[p2];
|
||||
QString forwardName = "Port "+QString::number(libreCALp1)+" to "+QString::number(libreCALp2);
|
||||
QString reverseName = "Port "+QString::number(libreCALp2)+" to "+QString::number(libreCALp1);
|
||||
for(auto ts : throughStandards) {
|
||||
if(ts->getName() == forwardName) {
|
||||
through->setStandard(ts);
|
||||
through->setReverseStandard(false);
|
||||
} else if(ts->getName() == reverseName) {
|
||||
through->setStandard(ts);
|
||||
through->setReverseStandard(true);
|
||||
}
|
||||
}
|
||||
throughMeasurements.push_back(through);
|
||||
cal->measurements.push_back(through);
|
||||
}
|
||||
}
|
||||
|
||||
ui->lCalibrationStatus->setText("Taking calibration measurements...");
|
||||
|
||||
measurementsTaken = 0;
|
||||
|
||||
auto setTerminationOnAllUsedPorts = [=](CalDevice::Standard s) {
|
||||
for(auto p : portAssignment) {
|
||||
if(p > 0) {
|
||||
device->setStandard(p, s);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto startNextCalibrationStep = [=]() {
|
||||
// indicate calibration percentage
|
||||
auto totalMeasurements = 3 + throughMeasurements.size();
|
||||
ui->progressCal->setValue(measurementsTaken * 100 / totalMeasurements);
|
||||
switch(measurementsTaken) {
|
||||
case 0:
|
||||
setTerminationOnAllUsedPorts(CalDevice::Standard::Open);
|
||||
emit cal->startMeasurements(openMeasurements);
|
||||
break;
|
||||
case 1:
|
||||
setTerminationOnAllUsedPorts(CalDevice::Standard::Short);
|
||||
emit cal->startMeasurements(shortMeasurements);
|
||||
break;
|
||||
case 2:
|
||||
setTerminationOnAllUsedPorts(CalDevice::Standard::Load);
|
||||
emit cal->startMeasurements(loadMeasurements);
|
||||
break;
|
||||
default: {
|
||||
// into through measurements now
|
||||
int throughIndex = measurementsTaken - 3;
|
||||
if(throughIndex >= throughMeasurements.size()) {
|
||||
// this was the last measurement
|
||||
// Try to apply the calibration
|
||||
Calibration::CalType type;
|
||||
type.type = Calibration::Type::SOLT;
|
||||
for(int i=0;i<vnaPorts;i++) {
|
||||
if(portAssignment[i] > 0) {
|
||||
// this VNA port was used in the calibration
|
||||
type.usedPorts.push_back(i+1);
|
||||
}
|
||||
}
|
||||
auto res = cal->compute(type);
|
||||
if(res) {
|
||||
ui->progressCal->setValue(100);
|
||||
ui->lCalibrationStatus->setText("Calibration activated.");
|
||||
} else {
|
||||
ui->progressCal->setValue(0);
|
||||
ui->lCalibrationStatus->setText("Failed to activate calibration.");
|
||||
ui->lCalibrationStatus->setStyleSheet("QLabel { color : red; }");
|
||||
}
|
||||
// severe connection to this function
|
||||
disconnect(cal, &Calibration::measurementsUpdated, this, nullptr);
|
||||
enableUI();
|
||||
break;
|
||||
}
|
||||
setTerminationOnAllUsedPorts(CalDevice::Standard::None);
|
||||
auto m = throughMeasurements[throughIndex];
|
||||
device->setStandard(m->getPort1(), CalDevice::Standard::Through);
|
||||
device->setStandard(m->getPort2(), CalDevice::Standard::Through);
|
||||
emit cal->startMeasurements({m});
|
||||
}
|
||||
break;
|
||||
}
|
||||
measurementsTaken++;
|
||||
};
|
||||
|
||||
connect(cal, &Calibration::measurementsUpdated, this, startNextCalibrationStep);
|
||||
|
||||
startNextCalibrationStep();
|
||||
}
|
||||
|
||||
void LibreCALDialog::disableUI()
|
||||
{
|
||||
ui->cbDevice->setEnabled(false);
|
||||
ui->cbCoefficients->setEnabled(false);
|
||||
ui->start->setEnabled(false);
|
||||
for(auto cb : portAssignmentComboBoxes) {
|
||||
cb->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
ui->lCalibrationStatus->setText("Creating calibration kit from coefficients...");
|
||||
auto& kit = cal->getKit();
|
||||
kit = Calkit::fromLibreCAL(device, coeffSet);
|
||||
void LibreCALDialog::enableUI()
|
||||
{
|
||||
ui->cbDevice->setEnabled(true);
|
||||
ui->cbCoefficients->setEnabled(true);
|
||||
ui->start->setEnabled(true);
|
||||
for(auto cb : portAssignmentComboBoxes) {
|
||||
cb->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LibreCALDialog::createPortAssignmentUI()
|
||||
@ -233,6 +422,7 @@ void LibreCALDialog::createPortAssignmentUI()
|
||||
auto layout = static_cast<QFormLayout*>(ui->assignmentBox->layout());
|
||||
// Clear any possible previous elements
|
||||
portAssignment.clear();
|
||||
portAssignmentComboBoxes.clear();
|
||||
while(layout->rowCount() > 1) {
|
||||
layout->removeRow(1);
|
||||
}
|
||||
@ -255,7 +445,13 @@ void LibreCALDialog::createPortAssignmentUI()
|
||||
emit portAssignmentChanged();
|
||||
});
|
||||
// try to set the default
|
||||
if(comboBox->count() > p) {
|
||||
comboBox->setCurrentIndex(p);
|
||||
} else {
|
||||
// port not available, set to unused
|
||||
comboBox->setCurrentIndex(0);
|
||||
}
|
||||
layout->addRow(label, comboBox);
|
||||
portAssignmentComboBoxes.push_back(comboBox);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include <QTimer>
|
||||
#include <QComboBox>
|
||||
|
||||
namespace Ui {
|
||||
class LibreCALDialog;
|
||||
@ -27,6 +28,8 @@ private slots:
|
||||
void updateDeviceStatus();
|
||||
void startCalibration();
|
||||
private:
|
||||
void disableUI();
|
||||
void enableUI();
|
||||
void createPortAssignmentUI();
|
||||
Ui::LibreCALDialog *ui;
|
||||
Calibration *cal;
|
||||
@ -35,6 +38,9 @@ private:
|
||||
QTimer updateTimer;
|
||||
bool busy;
|
||||
std::vector<int> portAssignment;
|
||||
std::vector<QComboBox*> portAssignmentComboBoxes;
|
||||
|
||||
int measurementsTaken;
|
||||
};
|
||||
|
||||
#endif // LIBRECALDIALOG_H
|
||||
|
@ -209,22 +209,25 @@ void Calibration::edit()
|
||||
updateCalButtons();
|
||||
});
|
||||
|
||||
connect(ui->activate, &QPushButton::clicked, [=](){
|
||||
auto cal = availableCals[ui->calibrationList->currentRow()];
|
||||
if(compute(cal)) {
|
||||
connect(this, &Calibration::activated, d, [=](){
|
||||
updateCalibrationList();
|
||||
updateCalStatistics();
|
||||
updateCalButtons();
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->deactivate, &QPushButton::clicked, [=](){
|
||||
deactivate();
|
||||
connect(this, &Calibration::deactivated, d, [=](){
|
||||
updateCalibrationList();
|
||||
updateCalStatistics();
|
||||
updateCalButtons();
|
||||
});
|
||||
|
||||
connect(ui->activate, &QPushButton::clicked, [=](){
|
||||
auto cal = availableCals[ui->calibrationList->currentRow()];
|
||||
compute(cal);
|
||||
});
|
||||
|
||||
connect(ui->deactivate, &QPushButton::clicked, this, &Calibration::deactivate);
|
||||
|
||||
ui->table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
auto updateTableEditButtons = [=](){
|
||||
@ -263,6 +266,9 @@ void Calibration::edit()
|
||||
if(measurements.size() > 0) {
|
||||
if(!InformationBox::AskQuestion("Create default entries?", "Do you want to remove all existing entries and create default calibration measurements instead?", true)) {
|
||||
// user aborted
|
||||
ui->createDefault->blockSignals(true);
|
||||
ui->createDefault->setCurrentIndex(0);
|
||||
ui->createDefault->blockSignals(false);
|
||||
return;
|
||||
}
|
||||
measurements.clear();
|
||||
@ -345,6 +351,10 @@ void Calibration::edit()
|
||||
d->show();
|
||||
});
|
||||
|
||||
connect(ui->editCalkit, &QPushButton::clicked, [=](){
|
||||
kit.edit();
|
||||
});
|
||||
|
||||
QObject::connect(ui->table, &QTableWidget::currentCellChanged, updateTableEditButtons);
|
||||
|
||||
auto addMenu = new QMenu();
|
||||
|
@ -9,6 +9,8 @@
|
||||
class Calibration : public QObject, public Savable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class LibreCALDialog;
|
||||
public:
|
||||
Calibration();
|
||||
|
||||
@ -20,7 +22,7 @@ public:
|
||||
class CalType {
|
||||
public:
|
||||
Type type;
|
||||
std::vector<int> usedPorts;
|
||||
std::vector<int> usedPorts; // port count starts at 1
|
||||
QString getReadableDescription();
|
||||
QString getShortString();
|
||||
|
||||
|
@ -167,6 +167,21 @@ Calibration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="editCalkit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit
|
||||
Calibration
|
||||
Kit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QComboBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QCheckBox>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -366,6 +367,8 @@ QWidget *CalibrationMeasurement::TwoPort::createSettingsWidget()
|
||||
auto cbPort1 = new QComboBox();
|
||||
auto label2 = new QLabel(" to ");
|
||||
auto cbPort2 = new QComboBox();
|
||||
auto cbReverse = new QCheckBox("Reversed");
|
||||
cbReverse->setToolTip("Enable this option if the calibration standard is defined with the port order swapped");
|
||||
auto dev = VirtualDevice::getConnected();
|
||||
if(dev) {
|
||||
for(int i=1;i<=dev->getInfo().ports;i++) {
|
||||
@ -389,12 +392,16 @@ QWidget *CalibrationMeasurement::TwoPort::createSettingsWidget()
|
||||
cbPort2->addItem(QString::number(port2));
|
||||
cbPort2->setCurrentText(QString::number(port2));
|
||||
}
|
||||
cbReverse->setChecked(reverseStandard);
|
||||
connect(cbPort1, qOverload<int>(&QComboBox::currentIndexChanged), [=](){
|
||||
setPort1(cbPort1->currentText().toInt());
|
||||
});
|
||||
connect(cbPort2, qOverload<int>(&QComboBox::currentIndexChanged), [=](){
|
||||
setPort2(cbPort2->currentText().toInt());
|
||||
});
|
||||
connect(cbReverse, &QCheckBox::toggled, [=](){
|
||||
setReverseStandard(cbReverse->isChecked());
|
||||
});
|
||||
connect(this, &TwoPort::port1Changed, cbPort1, [=](){
|
||||
auto string = QString::number(port1);
|
||||
if(cbPort1->findText(string) < 0) {
|
||||
@ -411,6 +418,9 @@ QWidget *CalibrationMeasurement::TwoPort::createSettingsWidget()
|
||||
}
|
||||
cbPort2->setCurrentText(string);
|
||||
});
|
||||
connect(this, &TwoPort::reverseStandardChanged, cbReverse, [=](){
|
||||
cbReverse->setChecked(reverseStandard);
|
||||
});
|
||||
auto ret = new QWidget();
|
||||
auto layout = new QHBoxLayout;
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
@ -418,6 +428,7 @@ QWidget *CalibrationMeasurement::TwoPort::createSettingsWidget()
|
||||
layout->addWidget(cbPort1);
|
||||
layout->addWidget(label2);
|
||||
layout->addWidget(cbPort2);
|
||||
layout->addWidget(cbReverse);
|
||||
layout->setStretch(1, 1);
|
||||
layout->setStretch(3, 1);
|
||||
ret->setLayout(layout);
|
||||
@ -429,6 +440,7 @@ nlohmann::json CalibrationMeasurement::TwoPort::toJSON()
|
||||
auto j = Base::toJSON();
|
||||
j["port1"] = port1;
|
||||
j["port2"] = port2;
|
||||
j["reverseStandard"] = reverseStandard;
|
||||
nlohmann::json jpoints;
|
||||
for(auto &p : points) {
|
||||
nlohmann::json jpoint;
|
||||
@ -446,6 +458,7 @@ void CalibrationMeasurement::TwoPort::fromJSON(nlohmann::json j)
|
||||
Base::fromJSON(j);
|
||||
port1 = j.value("port1", 0);
|
||||
port2 = j.value("port2", 0);
|
||||
reverseStandard = j.value("reverseStandard", false);
|
||||
if(j.contains("points")) {
|
||||
for(auto jpoint : j["points"]) {
|
||||
Point p;
|
||||
@ -479,7 +492,12 @@ Sparam CalibrationMeasurement::TwoPort::getMeasured(double frequency)
|
||||
|
||||
Sparam CalibrationMeasurement::TwoPort::getActual(double frequency)
|
||||
{
|
||||
return static_cast<CalStandard::TwoPort*>(standard)->toSparam(frequency);
|
||||
auto param = static_cast<CalStandard::TwoPort*>(standard)->toSparam(frequency);
|
||||
if(reverseStandard) {
|
||||
swap(param.m11, param.m22);
|
||||
swap(param.m12, param.m21);
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
int CalibrationMeasurement::TwoPort::getPort2() const
|
||||
@ -503,6 +521,14 @@ void CalibrationMeasurement::TwoPort::setPort2(int p)
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationMeasurement::TwoPort::setReverseStandard(bool reverse)
|
||||
{
|
||||
if(reverseStandard != reverse) {
|
||||
reverseStandard = reverse;
|
||||
emit reverseStandardChanged(reverse);
|
||||
}
|
||||
}
|
||||
|
||||
int CalibrationMeasurement::TwoPort::getPort1() const
|
||||
{
|
||||
return port1;
|
||||
|
@ -141,7 +141,8 @@ public:
|
||||
TwoPort(Calibration *cal) :
|
||||
Base(cal),
|
||||
port1(0),
|
||||
port2(0){}
|
||||
port2(0),
|
||||
reverseStandard(false){}
|
||||
|
||||
virtual double minFreq() override;
|
||||
virtual double maxFreq() override;
|
||||
@ -164,12 +165,15 @@ public:
|
||||
public slots:
|
||||
void setPort1(int p);
|
||||
void setPort2(int p);
|
||||
void setReverseStandard(bool reverse);
|
||||
protected:
|
||||
signals:
|
||||
void port1Changed(int p);
|
||||
void port2Changed(int p);
|
||||
void reverseStandardChanged(bool r);
|
||||
protected:
|
||||
int port1, port2;
|
||||
bool reverseStandard; // Set to true if standard is defined with ports swapped
|
||||
class Point {
|
||||
public:
|
||||
double frequency;
|
||||
|
@ -328,47 +328,6 @@ Calkit Calkit::fromFile(QString filename)
|
||||
return c;
|
||||
}
|
||||
|
||||
Calkit Calkit::fromLibreCAL(CalDevice *device, CalDevice::CoefficientSet s)
|
||||
{
|
||||
Calkit ret;
|
||||
ret.manufacturer = "LibreCAL ("+s.name+")";
|
||||
ret.serialnumber = device->serial();
|
||||
ret.description = "Automatically created from LibreCAL module";
|
||||
for(int i=1;i<=device->getNumPorts();i++) {
|
||||
if(s.opens[i-1]->t.points() > 0) {
|
||||
auto o = new CalStandard::Open();
|
||||
o->setName("Port "+QString::number(i)+" Open");
|
||||
o->setMeasurement(s.opens[i-1]->t);
|
||||
ret.standards.push_back(o);
|
||||
}
|
||||
if(s.shorts[i-1]->t.points() > 0) {
|
||||
auto o = new CalStandard::Short();
|
||||
o->setName("Port "+QString::number(i)+" Short");
|
||||
o->setMeasurement(s.shorts[i-1]->t);
|
||||
ret.standards.push_back(o);
|
||||
}
|
||||
if(s.loads[i-1]->t.points() > 0) {
|
||||
auto o = new CalStandard::Load();
|
||||
o->setName("Port "+QString::number(i)+" Load");
|
||||
o->setMeasurement(s.loads[i-1]->t);
|
||||
ret.standards.push_back(o);
|
||||
}
|
||||
for(int j=i+1;j<=device->getNumPorts();j++) {
|
||||
auto c = s.getThrough(i,j);
|
||||
if(!c) {
|
||||
continue;
|
||||
}
|
||||
if(c->t.points() > 0) {
|
||||
auto o = new CalStandard::Through();
|
||||
o->setName("Port "+QString::number(i)+" to "+QString::number(j)+" Through");
|
||||
o->setMeasurement(c->t);
|
||||
ret.standards.push_back(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Calkit::edit(std::function<void (void)> updateCal)
|
||||
{
|
||||
auto dialog = new CalkitDialog(*this);
|
||||
|
@ -15,6 +15,7 @@
|
||||
class Calkit : public Savable
|
||||
{
|
||||
friend class CalkitDialog;
|
||||
friend class LibreCALDialog;
|
||||
public:
|
||||
Calkit();
|
||||
Calkit(const Calkit&) = default;
|
||||
@ -43,7 +44,6 @@ public:
|
||||
|
||||
void toFile(QString filename);
|
||||
static Calkit fromFile(QString filename);
|
||||
static Calkit fromLibreCAL(CalDevice *device, CalDevice::CoefficientSet s);
|
||||
void edit(std::function<void(void)> updateCal = nullptr);
|
||||
|
||||
std::vector<CalStandard::Virtual *> getStandards() const;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "CustomWidgets/informationbox.h"
|
||||
#include "Deembedding/manualdeembeddingdialog.h"
|
||||
#include "Calibration/manualcalibrationdialog.h"
|
||||
#include "Calibration/LibreCAL/librecaldialog.h"
|
||||
#include "Util/util.h"
|
||||
#include "Tools/parameters.h"
|
||||
|
||||
@ -111,6 +112,12 @@ VNA::VNA(AppWindow *window, QString name)
|
||||
// });
|
||||
});
|
||||
|
||||
auto calElectronic = calMenu->addAction("Electronic Calibration");
|
||||
connect(calElectronic, &QAction::triggered, [=](){
|
||||
auto d = new LibreCALDialog(&cal);
|
||||
d->show();
|
||||
});
|
||||
|
||||
calMenu->addSeparator();
|
||||
|
||||
auto calImportTerms = calMenu->addAction("Import error terms as traces");
|
||||
|
Loading…
Reference in New Issue
Block a user