mirror of
https://github.com/jankae/LibreVNA.git
synced 2025-12-06 07:12:10 +01:00
Compare commits
4 commits
5947584e63
...
5d00d4786b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d00d4786b | ||
|
|
3e327e7e6b | ||
|
|
b2fd49d800 | ||
|
|
f327a4b4a0 |
|
|
@ -6,6 +6,7 @@
|
|||
#include "Util/util.h"
|
||||
#include "LibreCAL/librecaldialog.h"
|
||||
#include "preferences.h"
|
||||
#include "Traces/sparamtraceselectordialog.h"
|
||||
|
||||
#include "Tools/Eigen/Dense"
|
||||
|
||||
|
|
@ -303,6 +304,7 @@ QString Calibration::TypeToString(Calibration::Type type)
|
|||
case Type::None: return "None";
|
||||
case Type::OSL: return "OSL";
|
||||
case Type::SOLT: return "SOLT";
|
||||
case Type::SOLTwithoutRxMatch: return "SOLTwithoutRxMatch";
|
||||
case Type::ThroughNormalization: return "ThroughNormalization";
|
||||
case Type::TRL: return "TRL";
|
||||
case Type::Last: return "Invalid";
|
||||
|
|
@ -408,7 +410,7 @@ void Calibration::correctTraces(std::map<QString, Trace *> traceSet)
|
|||
}
|
||||
}
|
||||
|
||||
void Calibration::edit()
|
||||
void Calibration::edit(TraceModel *traceModel)
|
||||
{
|
||||
auto d = new QDialog();
|
||||
d->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
|
@ -510,6 +512,10 @@ void Calibration::edit()
|
|||
ui->bDelete->setEnabled(ui->table->currentRow() >= 0);
|
||||
ui->bMoveUp->setEnabled(ui->table->currentRow() >= 1);
|
||||
ui->bMoveDown->setEnabled(ui->table->currentRow() >= 0 && ui->table->currentRow() < ui->table->rowCount() - 1);
|
||||
auto selected = ui->table->selectionModel()->selectedRows();
|
||||
ui->measure->setEnabled(selected.size() > 0);
|
||||
ui->selectMeasurement->setEnabled(traceModel && selected.size() == 1);
|
||||
ui->clearMeasurement->setEnabled(selected.size() > 0);
|
||||
};
|
||||
|
||||
auto updateMeasurementTable = [=](){
|
||||
|
|
@ -619,6 +625,35 @@ void Calibration::edit()
|
|||
emit startMeasurements(m);
|
||||
});
|
||||
|
||||
connect(ui->selectMeasurement, &QPushButton::clicked, [=](){
|
||||
auto selected = ui->table->selectionModel()->selectedRows();
|
||||
if(selected.size() != 1) {
|
||||
InformationBox::ShowError("Unable to select measurement", "Exactly one measurement must be selected");
|
||||
return;
|
||||
}
|
||||
// figure out which S parameters we need
|
||||
auto meas = measurements[selected[0].row()];
|
||||
auto ports = meas->getPorts();
|
||||
if(ports.size() == 0) {
|
||||
InformationBox::ShowError("Unable to select measurement", "Selecting measurements for this type of calibration measurement is not supported");
|
||||
return;
|
||||
}
|
||||
auto selector = new SParamTraceSelectorDialog(*traceModel, ports);
|
||||
connect(selector, &SParamTraceSelectorDialog::tracesSelected, d, [=](std::vector<DeviceDriver::VNAMeasurement> traceMeasurements){
|
||||
clearMeasurements({meas});
|
||||
for(const auto &tm : traceMeasurements) {
|
||||
addMeasurements({meas}, tm);
|
||||
}
|
||||
updateMeasurementTable();
|
||||
updateCalibrationList();
|
||||
});
|
||||
selector->show();
|
||||
});
|
||||
if(!traceModel) {
|
||||
// can not select a measurement if no trace model is supplied
|
||||
ui->selectMeasurement->setEnabled(false);
|
||||
}
|
||||
|
||||
connect(this, &Calibration::measurementsUpdated, d, [=](){
|
||||
updateMeasurementTable();
|
||||
updateCalibrationList();
|
||||
|
|
@ -665,7 +700,7 @@ void Calibration::edit()
|
|||
});
|
||||
});
|
||||
|
||||
QObject::connect(ui->table, &QTableWidget::currentCellChanged, updateTableEditButtons);
|
||||
QObject::connect(ui->table, &QTableWidget::itemSelectionChanged, updateTableEditButtons);
|
||||
|
||||
auto addMenu = new QMenu();
|
||||
for(auto t : CalibrationMeasurement::Base::availableTypes()) {
|
||||
|
|
@ -809,6 +844,17 @@ Calibration::Point Calibration::computeSOLT(double f)
|
|||
return point;
|
||||
}
|
||||
|
||||
Calibration::Point Calibration::computeSOLTwithoutRxMatch(double f) {
|
||||
// This is very similar to SOLT but it assumes that receiver matching at the VNA is perfect.
|
||||
// It can be used if the through calibration standard is very lossy which would result in
|
||||
// very noisy values for the receiver match
|
||||
auto p = computeSOLT(f);
|
||||
for(auto &l : p.L) {
|
||||
fill(l.begin(), l.end(), 0.0);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
Calibration::Point Calibration::computeThroughNormalization(double f)
|
||||
{
|
||||
Point point = createInitializedPoint(f);
|
||||
|
|
@ -1736,6 +1782,7 @@ bool Calibration::canCompute(Calibration::CalType type, double *startFreq, doubl
|
|||
case Type::None:
|
||||
return true; // Always possible to reset the calibration
|
||||
case Type::SOLT:
|
||||
case Type::SOLTwithoutRxMatch:
|
||||
// through measurements between all ports
|
||||
for(unsigned int i=1;i<=type.usedPorts.size();i++) {
|
||||
for(unsigned int j=i+1;j<=type.usedPorts.size();j++) {
|
||||
|
|
@ -1829,6 +1876,7 @@ bool Calibration::compute(Calibration::CalType type)
|
|||
switch(type.type) {
|
||||
case Type::OSL: p = computeOSL(f); break;
|
||||
case Type::SOLT: p = computeSOLT(f); break;
|
||||
case Type::SOLTwithoutRxMatch: p = computeSOLTwithoutRxMatch(f); break;
|
||||
case Type::ThroughNormalization: p = computeThroughNormalization(f); break;
|
||||
case Type::TRL: p = computeTRL(f); break;
|
||||
case Type::None:
|
||||
|
|
@ -1858,6 +1906,7 @@ int Calibration::minimumPorts(Calibration::Type type)
|
|||
switch(type) {
|
||||
case Type::OSL: return 1;
|
||||
case Type::SOLT: return 1;
|
||||
case Type::SOLTwithoutRxMatch: return 2;
|
||||
case Type::ThroughNormalization: return 2;
|
||||
case Type::TRL: return 2;
|
||||
case Type::None:
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public:
|
|||
None,
|
||||
OSL,
|
||||
SOLT,
|
||||
SOLTwithoutRxMatch,
|
||||
ThroughNormalization,
|
||||
TRL,
|
||||
Last,
|
||||
|
|
@ -46,7 +47,7 @@ public:
|
|||
void correctTraces(std::map<QString, Trace*> traceSet);
|
||||
|
||||
// Starts the calibration edit dialog, allowing the user to make/delete measurements
|
||||
void edit();
|
||||
void edit(TraceModel *traceModel = nullptr);
|
||||
|
||||
Calkit& getKit();
|
||||
|
||||
|
|
@ -163,6 +164,7 @@ private:
|
|||
Point createInitializedPoint(double f);
|
||||
Point computeOSL(double f);
|
||||
Point computeSOLT(double f);
|
||||
Point computeSOLTwithoutRxMatch(double f);
|
||||
Point computeThroughNormalization(double f);
|
||||
Point computeTRL(double f);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
<item>
|
||||
<widget class="QTableWidget" name="table">
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
<enum>QAbstractItemView::SelectionBehavior::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
|
|
@ -148,6 +148,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectMeasurement">
|
||||
<property name="text">
|
||||
<string>Select
|
||||
Measurement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearMeasurement">
|
||||
<property name="text">
|
||||
|
|
@ -185,7 +193,7 @@ Kit</string>
|
|||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -287,7 +295,7 @@ Kit</string>
|
|||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
virtual std::vector<unsigned int> getPorts() = 0;
|
||||
|
||||
static bool canMeasureSimultaneously(std::set<Base *> measurements);
|
||||
QDateTime getTimestamp() const;
|
||||
|
||||
|
|
@ -102,6 +104,8 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
virtual std::vector<unsigned int> getPorts() override {return {port};}
|
||||
|
||||
class Point {
|
||||
public:
|
||||
double frequency;
|
||||
|
|
@ -222,6 +226,8 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
virtual std::vector<unsigned int> getPorts() override {return {port1, port2};}
|
||||
|
||||
class Point {
|
||||
public:
|
||||
double frequency;
|
||||
|
|
@ -298,6 +304,8 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
virtual std::vector<unsigned int> getPorts() override {return {};}
|
||||
|
||||
class Point {
|
||||
public:
|
||||
double frequency;
|
||||
|
|
|
|||
|
|
@ -794,6 +794,7 @@ QString LibreVNADriver::getFirmwareMagicString()
|
|||
{
|
||||
switch(hardwareVersion) {
|
||||
case 0x01: return "VNA!";
|
||||
case 0xE0: return "VNS1";
|
||||
case 0xFE: return "VNP2";
|
||||
case 0xFF: return "VNPT";
|
||||
default: return "XXXX";
|
||||
|
|
|
|||
|
|
@ -131,8 +131,8 @@ void ManualControlDialogVE0::NewStatus(Protocol::ManualStatus status)
|
|||
auto port1db = Util::SparamTodB(port1referenced);
|
||||
auto port2db = Util::SparamTodB(port2referenced);
|
||||
|
||||
ui->port1referenced->setText(QString::number(port1db, 'f', 1) + "db@" + QString::number(arg(port1referenced)*180/M_PI, 'f', 0) + "°");
|
||||
ui->port2referenced->setText(QString::number(port2db, 'f', 1) + "db@" + QString::number(arg(port2referenced)*180/M_PI, 'f', 0) + "°");
|
||||
ui->port1referenced->setText(QString::number(port1db, 'f', 2) + "db@" + QString::number(arg(port1referenced)*180/M_PI, 'f', 2) + "°");
|
||||
ui->port2referenced->setText(QString::number(port2db, 'f', 2) + "db@" + QString::number(arg(port2referenced)*180/M_PI, 'f', 2) + "°");
|
||||
}
|
||||
|
||||
void ManualControlDialogVE0::UpdateDevice()
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ HEADERS += \
|
|||
Traces/eyediagramplot.h \
|
||||
Traces/fftcomplex.h \
|
||||
Traces/sparamtraceselector.h \
|
||||
Traces/sparamtraceselectordialog.h \
|
||||
Traces/trace.h \
|
||||
Traces/traceaxis.h \
|
||||
Traces/tracecsvexport.h \
|
||||
|
|
@ -271,6 +272,7 @@ SOURCES += \
|
|||
Traces/eyediagramplot.cpp \
|
||||
Traces/fftcomplex.cpp \
|
||||
Traces/sparamtraceselector.cpp \
|
||||
Traces/sparamtraceselectordialog.cpp \
|
||||
Traces/trace.cpp \
|
||||
Traces/traceaxis.cpp \
|
||||
Traces/tracecsvexport.cpp \
|
||||
|
|
@ -389,6 +391,7 @@ FORMS += \
|
|||
Traces/eyediagrameditdialog.ui \
|
||||
Traces/smithchartdialog.ui \
|
||||
Traces/polarchartdialog.ui \
|
||||
Traces/sparamtraceselectordialog.ui \
|
||||
Traces/tracecsvexport.ui \
|
||||
Traces/traceeditdialog.ui \
|
||||
Traces/traceimportdialog.ui \
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ SparamTraceSelector::SparamTraceSelector(const TraceModel &model, std::vector<un
|
|||
: model(model),
|
||||
empty_allowed(empty_allowed),
|
||||
used_ports(used_ports),
|
||||
editablePorts(editablePorts)
|
||||
editablePorts(editablePorts),
|
||||
valid(false)
|
||||
{
|
||||
createGUI();
|
||||
setInitialChoices();
|
||||
|
|
@ -140,6 +141,7 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
|
|||
|
||||
} else if(cb->currentIndex() == 0 && points > 0) {
|
||||
if(!empty_allowed) {
|
||||
valid = false;
|
||||
emit selectionValid(false);
|
||||
}
|
||||
// Check if all trace selections are set for none
|
||||
|
|
@ -161,7 +163,8 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
|
|||
}
|
||||
if(empty_allowed) {
|
||||
// always valid as soon as at least one trace is selected
|
||||
emit selectionValid(points > 0);
|
||||
valid = points > 0;
|
||||
emit selectionValid(valid);
|
||||
} else {
|
||||
// actually need to check
|
||||
valid = true;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public:
|
|||
SparamTraceSelector(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed = false, unsigned int editablePorts = 0);
|
||||
SparamTraceSelector(const TraceModel &model, std::set<unsigned int> used_ports, bool empty_allowed = false, unsigned int editablePorts = 0);
|
||||
|
||||
bool isValid();
|
||||
bool isValid() {return valid;}
|
||||
|
||||
std::map<QString, Trace*> getTraces();
|
||||
unsigned int getPoints() { return points;}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
#include "sparamtraceselectordialog.h"
|
||||
#include "ui_sparamtraceselectordialog.h"
|
||||
|
||||
#include "sparamtraceselector.h"
|
||||
#include <QPushButton>
|
||||
|
||||
SParamTraceSelectorDialog::SParamTraceSelectorDialog(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed)
|
||||
: QDialog(nullptr)
|
||||
, ui(new Ui::SParamTraceSelectorDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
auto selector = new SparamTraceSelector(model, used_ports, empty_allowed);
|
||||
ui->verticalLayout->replaceWidget(ui->placeholder, selector);
|
||||
|
||||
auto okButton = ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok);
|
||||
connect(selector, &SparamTraceSelector::selectionValid, okButton, &QPushButton::setEnabled);
|
||||
okButton->setEnabled(selector->isValid());
|
||||
|
||||
connect(okButton, &QPushButton::clicked, [=](){
|
||||
auto traces = selector->getTraces();
|
||||
if(traces.size() == 0) {
|
||||
// should not happen
|
||||
reject();
|
||||
}
|
||||
emit tracesSelected(Trace::assembleDatapoints(traces));
|
||||
accept();
|
||||
});
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &SParamTraceSelectorDialog::reject);
|
||||
}
|
||||
|
||||
SParamTraceSelectorDialog::~SParamTraceSelectorDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef SPARAMTRACESELECTORDIALOG_H
|
||||
#define SPARAMTRACESELECTORDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "tracemodel.h"
|
||||
|
||||
namespace Ui {
|
||||
class SParamTraceSelectorDialog;
|
||||
}
|
||||
|
||||
class SParamTraceSelectorDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SParamTraceSelectorDialog(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed = false);
|
||||
~SParamTraceSelectorDialog();
|
||||
|
||||
signals:
|
||||
void tracesSelected(std::vector<DeviceDriver::VNAMeasurement> traceMeasurements);
|
||||
|
||||
private:
|
||||
Ui::SParamTraceSelectorDialog *ui;
|
||||
};
|
||||
|
||||
#endif // SPARAMTRACESELECTORDIALOG_H
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SParamTraceSelectorDialog</class>
|
||||
<widget class="QDialog" name="SParamTraceSelectorDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModality::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>494</width>
|
||||
<height>222</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>S-Paramter Trace Selector Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="placeholder" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -110,7 +110,7 @@ VNA::VNA(AppWindow *window, QString name)
|
|||
|
||||
auto calData = calMenu->addAction("Calibration Measurements");
|
||||
connect(calData, &QAction::triggered, [=](){
|
||||
cal.edit();
|
||||
cal.edit(&traceModel);
|
||||
});
|
||||
|
||||
auto calEditKit = calMenu->addAction("Edit Calibration Kit");
|
||||
|
|
@ -1375,7 +1375,7 @@ void VNA::ApplyCalibration(Calibration::CalType type)
|
|||
// Not all required traces available
|
||||
InformationBox::ShowMessageBlocking("Missing calibration measurements", "Not all calibration measurements for this type of calibration have been taken. The calibration can be enabled after the missing measurements have been acquired.");
|
||||
DisableCalibration();
|
||||
cal.edit();
|
||||
cal.edit(&traceModel);
|
||||
} else {
|
||||
// Not all required traces available
|
||||
InformationBox::ShowMessageBlocking("Missing calibration measurements", "Not all calibration measurements for this type of calibration have been taken. Please switch to frequency sweep to take these measurements.");
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ SOURCES += \
|
|||
../LibreVNA-GUI/Traces/eyediagramplot.cpp \
|
||||
../LibreVNA-GUI/Traces/fftcomplex.cpp \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselector.cpp \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselectordialog.cpp \
|
||||
../LibreVNA-GUI/Traces/trace.cpp \
|
||||
../LibreVNA-GUI/Traces/traceaxis.cpp \
|
||||
../LibreVNA-GUI/Traces/tracecsvexport.cpp \
|
||||
|
|
@ -310,6 +311,7 @@ HEADERS += \
|
|||
../LibreVNA-GUI/Traces/eyediagramplot.h \
|
||||
../LibreVNA-GUI/Traces/fftcomplex.h \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselector.h \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselectordialog.h \
|
||||
../LibreVNA-GUI/Traces/trace.h \
|
||||
../LibreVNA-GUI/Traces/traceaxis.h \
|
||||
../LibreVNA-GUI/Traces/tracecsvexport.h \
|
||||
|
|
@ -425,6 +427,7 @@ FORMS += \
|
|||
../LibreVNA-GUI/Traces/eyediagrameditdialog.ui \
|
||||
../LibreVNA-GUI/Traces/polarchartdialog.ui \
|
||||
../LibreVNA-GUI/Traces/smithchartdialog.ui \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselectordialog.ui \
|
||||
../LibreVNA-GUI/Traces/tracecsvexport.ui \
|
||||
../LibreVNA-GUI/Traces/traceeditdialog.ui \
|
||||
../LibreVNA-GUI/Traces/traceimportdialog.ui \
|
||||
|
|
|
|||
Loading…
Reference in a new issue