Calkit with flexible number of standards
This commit is contained in:
parent
1c607d2c42
commit
623aa2b29a
@ -0,0 +1,190 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CalStandardThroughEditDialog</class>
|
||||
<widget class="QDialog" name="CalStandardThroughEditDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>358</width>
|
||||
<height>342</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Edit Through Standard</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="name"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="coefficients">
|
||||
<property name="text">
|
||||
<string>Coefficients</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="measurement">
|
||||
<property name="text">
|
||||
<string>Measurement file</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_35">
|
||||
<property name="text">
|
||||
<string>Z0:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="SIUnitEdit" name="Z0">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Delay [ps]:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="delay"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Loss [GΩ/s]: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="SIUnitEdit" name="loss"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1">
|
||||
<item>
|
||||
<widget class="QLabel" name="measurementLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="updateFile">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update from file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="TouchstoneImport" name="touchstoneImport" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</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>
|
||||
<customwidget>
|
||||
<class>TouchstoneImport</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>CustomWidgets/touchstoneimport.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>CalStandardThroughEditDialog</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>CalStandardThroughEditDialog</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>
|
||||
<buttongroups>
|
||||
<buttongroup name="buttonGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
@ -15,14 +15,6 @@ using json = nlohmann::json;
|
||||
using namespace std;
|
||||
|
||||
Calkit::Calkit()
|
||||
: ts_open_m(nullptr),
|
||||
ts_short_m(nullptr),
|
||||
ts_load_m(nullptr),
|
||||
ts_open_f(nullptr),
|
||||
ts_short_f(nullptr),
|
||||
ts_load_f(nullptr),
|
||||
ts_through(nullptr),
|
||||
ts_cached(false)
|
||||
{
|
||||
|
||||
// set default values
|
||||
@ -39,15 +31,11 @@ void Calkit::toFile(QString filename)
|
||||
|
||||
qDebug() << "Saving calkit to file" << filename;
|
||||
|
||||
TransformPathsToRelative(filename);
|
||||
|
||||
json j = Savable::createJSON(descr);
|
||||
ofstream file;
|
||||
file.open(filename.toStdString());
|
||||
file << setw(4) << j << endl;
|
||||
file.close();
|
||||
|
||||
TransformPathsToAbsolute(filename);
|
||||
}
|
||||
|
||||
static QString readLine(ifstream &file) {
|
||||
@ -74,93 +62,87 @@ Calkit Calkit::fromFile(QString filename)
|
||||
throw runtime_error("JSON parsing error: " + string(e.what()));
|
||||
}
|
||||
if(j.contains("SOLT")) {
|
||||
// older file versions specify Z0 for resistance. Set resistance to Nan to detect missing values later
|
||||
c.SOLT.load_m.resistance = std::numeric_limits<double>::quiet_NaN();
|
||||
c.SOLT.load_f.resistance = std::numeric_limits<double>::quiet_NaN();
|
||||
// // older file versions specify Z0 for resistance. Set resistance to Nan to detect missing values later
|
||||
// c.SOLT.load_m.resistance = std::numeric_limits<double>::quiet_NaN();
|
||||
// c.SOLT.load_f.resistance = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
qDebug() << "JSON format detected";
|
||||
// calkit file uses json format, parse
|
||||
Savable::parseJSON(j, c.descr);
|
||||
auto jSOLT = j["SOLT"];
|
||||
if (!jSOLT.contains("loadModelCFirst")) {
|
||||
// older version which did not allow the user to choose the load model. CFirst seems to be the more
|
||||
// used standard so it is the default for newer calkits. However, old calkits used LFirst so we need
|
||||
// to keep that to not mess with older calkit files
|
||||
c.SOLT.loadModelCFirst = false;
|
||||
}
|
||||
// adjust Z0/resistance in case of older calkit file version with missing resistance entries
|
||||
if(isnan(c.SOLT.load_f.resistance)) {
|
||||
c.SOLT.load_f.resistance = c.SOLT.load_f.Z0;
|
||||
c.SOLT.load_f.Z0 = 50.0;
|
||||
}
|
||||
if(isnan(c.SOLT.load_m.resistance)) {
|
||||
c.SOLT.load_m.resistance = c.SOLT.load_m.Z0;
|
||||
c.SOLT.load_m.Z0 = 50.0;
|
||||
}
|
||||
// qDebug() << "JSON format detected";
|
||||
// // calkit file uses json format, parse
|
||||
// Savable::parseJSON(j, c.descr);
|
||||
// auto jSOLT = j["SOLT"];
|
||||
// if (!jSOLT.contains("loadModelCFirst")) {
|
||||
// // older version which did not allow the user to choose the load model. CFirst seems to be the more
|
||||
// // used standard so it is the default for newer calkits. However, old calkits used LFirst so we need
|
||||
// // to keep that to not mess with older calkit files
|
||||
// c.SOLT.loadModelCFirst = false;
|
||||
// }
|
||||
// // adjust Z0/resistance in case of older calkit file version with missing resistance entries
|
||||
// if(isnan(c.SOLT.load_f.resistance)) {
|
||||
// c.SOLT.load_f.resistance = c.SOLT.load_f.Z0;
|
||||
// c.SOLT.load_f.Z0 = 50.0;
|
||||
// }
|
||||
// if(isnan(c.SOLT.load_m.resistance)) {
|
||||
// c.SOLT.load_m.resistance = c.SOLT.load_m.Z0;
|
||||
// c.SOLT.load_m.Z0 = 50.0;
|
||||
// }
|
||||
} else {
|
||||
qDebug() << "Legacy format detected";
|
||||
// legacy file format, return to beginning of file
|
||||
file.clear();
|
||||
file.seekg(0);
|
||||
c.SOLT.open_m.useMeasurements = readLine(file).toInt();
|
||||
c.SOLT.short_m.useMeasurements = readLine(file).toInt();
|
||||
c.SOLT.load_m.useMeasurements = readLine(file).toInt();
|
||||
c.SOLT.Through.useMeasurements = readLine(file).toInt();
|
||||
c.SOLT.open_m.Z0 = readLine(file).toDouble();
|
||||
c.SOLT.open_m.delay = readLine(file).toDouble();
|
||||
c.SOLT.open_m.loss = readLine(file).toDouble();
|
||||
c.SOLT.open_m.C0 = readLine(file).toDouble();
|
||||
c.SOLT.open_m.C1 = readLine(file).toDouble();
|
||||
c.SOLT.open_m.C2 = readLine(file).toDouble();
|
||||
c.SOLT.open_m.C3 = readLine(file).toDouble();
|
||||
c.SOLT.short_m.Z0 = readLine(file).toDouble();
|
||||
c.SOLT.short_m.delay = readLine(file).toDouble();
|
||||
c.SOLT.short_m.loss = readLine(file).toDouble();
|
||||
c.SOLT.short_m.L0 = readLine(file).toDouble();
|
||||
c.SOLT.short_m.L1 = readLine(file).toDouble();
|
||||
c.SOLT.short_m.L2 = readLine(file).toDouble();
|
||||
c.SOLT.short_m.L3 = readLine(file).toDouble();
|
||||
c.SOLT.load_m.resistance = readLine(file).toDouble();
|
||||
c.SOLT.Through.Z0 = readLine(file).toDouble();
|
||||
c.SOLT.Through.delay = readLine(file).toDouble();
|
||||
c.SOLT.Through.loss = readLine(file).toDouble();
|
||||
if(c.SOLT.open_m.useMeasurements) {
|
||||
c.SOLT.open_m.file = readLine(file);
|
||||
c.SOLT.open_m.Sparam = readLine(file).toInt();
|
||||
}
|
||||
if(c.SOLT.short_m.useMeasurements) {
|
||||
c.SOLT.short_m.file = readLine(file);
|
||||
c.SOLT.short_m.Sparam = readLine(file).toInt();
|
||||
}
|
||||
if(c.SOLT.load_m.useMeasurements) {
|
||||
c.SOLT.load_m.file = readLine(file);
|
||||
c.SOLT.load_m.Sparam = readLine(file).toInt();
|
||||
}
|
||||
if(c.SOLT.Through.useMeasurements) {
|
||||
c.SOLT.Through.file = readLine(file);
|
||||
c.SOLT.Through.Sparam1 = readLine(file).toInt();
|
||||
c.SOLT.Through.Sparam2 = readLine(file).toInt();
|
||||
}
|
||||
c.TRL.Through.Z0 = readLine(file).toDouble();
|
||||
c.TRL.Reflection.isShort = readLine(file).toDouble();
|
||||
c.TRL.Line.delay = readLine(file).toDouble();
|
||||
c.TRL.Line.minFreq = readLine(file).toDouble();
|
||||
c.TRL.Line.maxFreq = readLine(file).toDouble();
|
||||
// qDebug() << "Legacy format detected";
|
||||
// // legacy file format, return to beginning of file
|
||||
// file.clear();
|
||||
// file.seekg(0);
|
||||
// c.SOLT.open_m.useMeasurements = readLine(file).toInt();
|
||||
// c.SOLT.short_m.useMeasurements = readLine(file).toInt();
|
||||
// c.SOLT.load_m.useMeasurements = readLine(file).toInt();
|
||||
// c.SOLT.Through.useMeasurements = readLine(file).toInt();
|
||||
// c.SOLT.open_m.Z0 = readLine(file).toDouble();
|
||||
// c.SOLT.open_m.delay = readLine(file).toDouble();
|
||||
// c.SOLT.open_m.loss = readLine(file).toDouble();
|
||||
// c.SOLT.open_m.C0 = readLine(file).toDouble();
|
||||
// c.SOLT.open_m.C1 = readLine(file).toDouble();
|
||||
// c.SOLT.open_m.C2 = readLine(file).toDouble();
|
||||
// c.SOLT.open_m.C3 = readLine(file).toDouble();
|
||||
// c.SOLT.short_m.Z0 = readLine(file).toDouble();
|
||||
// c.SOLT.short_m.delay = readLine(file).toDouble();
|
||||
// c.SOLT.short_m.loss = readLine(file).toDouble();
|
||||
// c.SOLT.short_m.L0 = readLine(file).toDouble();
|
||||
// c.SOLT.short_m.L1 = readLine(file).toDouble();
|
||||
// c.SOLT.short_m.L2 = readLine(file).toDouble();
|
||||
// c.SOLT.short_m.L3 = readLine(file).toDouble();
|
||||
// c.SOLT.load_m.resistance = readLine(file).toDouble();
|
||||
// c.SOLT.Through.Z0 = readLine(file).toDouble();
|
||||
// c.SOLT.Through.delay = readLine(file).toDouble();
|
||||
// c.SOLT.Through.loss = readLine(file).toDouble();
|
||||
// if(c.SOLT.open_m.useMeasurements) {
|
||||
// c.SOLT.open_m.file = readLine(file);
|
||||
// c.SOLT.open_m.Sparam = readLine(file).toInt();
|
||||
// }
|
||||
// if(c.SOLT.short_m.useMeasurements) {
|
||||
// c.SOLT.short_m.file = readLine(file);
|
||||
// c.SOLT.short_m.Sparam = readLine(file).toInt();
|
||||
// }
|
||||
// if(c.SOLT.load_m.useMeasurements) {
|
||||
// c.SOLT.load_m.file = readLine(file);
|
||||
// c.SOLT.load_m.Sparam = readLine(file).toInt();
|
||||
// }
|
||||
// if(c.SOLT.Through.useMeasurements) {
|
||||
// c.SOLT.Through.file = readLine(file);
|
||||
// c.SOLT.Through.Sparam1 = readLine(file).toInt();
|
||||
// c.SOLT.Through.Sparam2 = readLine(file).toInt();
|
||||
// }
|
||||
// c.TRL.Through.Z0 = readLine(file).toDouble();
|
||||
// c.TRL.Reflection.isShort = readLine(file).toDouble();
|
||||
// c.TRL.Line.delay = readLine(file).toDouble();
|
||||
// c.TRL.Line.minFreq = readLine(file).toDouble();
|
||||
// c.TRL.Line.maxFreq = readLine(file).toDouble();
|
||||
|
||||
c.SOLT.separate_male_female = false;
|
||||
// c.SOLT.separate_male_female = false;
|
||||
|
||||
InformationBox::ShowMessage("Loading calkit file", "The file \"" + filename + "\" is stored in a deprecated"
|
||||
" calibration kit format. Future versions of this application might not support"
|
||||
" it anymore. Please save the calibration kit to update to the new format");
|
||||
// InformationBox::ShowMessage("Loading calkit file", "The file \"" + filename + "\" is stored in a deprecated"
|
||||
// " calibration kit format. Future versions of this application might not support"
|
||||
// " it anymore. Please save the calibration kit to update to the new format");
|
||||
}
|
||||
file.close();
|
||||
|
||||
c.TransformPathsToAbsolute(filename);
|
||||
|
||||
// set default values for non-editable items (for now)
|
||||
c.TRL.Through.Z0 = 50.0;
|
||||
c.SOLT.Through.Z0 = 50.0;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -179,305 +161,45 @@ void Calkit::edit(std::function<void (void)> updateCal)
|
||||
|
||||
bool Calkit::hasSeparateMaleFemaleStandards()
|
||||
{
|
||||
return SOLT.separate_male_female;
|
||||
return true; // TODO delete function
|
||||
}
|
||||
|
||||
class Calkit::SOLT Calkit::toSOLT(double frequency, bool male_standards)
|
||||
{
|
||||
auto addTransmissionLine = [](complex<double> termination_reflection, double offset_impedance, double offset_delay, double offset_loss, double frequency) -> complex<double> {
|
||||
// nomenclature and formulas from https://loco.lab.asu.edu/loco-memos/edges_reports/report_20130807.pdf
|
||||
auto Gamma_T = termination_reflection;
|
||||
auto f = frequency;
|
||||
auto w = 2.0 * M_PI * frequency;
|
||||
auto f_sqrt = sqrt(f / 1e9);
|
||||
|
||||
auto Z_c = complex<double>(offset_impedance + (offset_loss / (2*w)) * f_sqrt, -(offset_loss / (2*w)) * f_sqrt);
|
||||
auto gamma_l = complex<double>(offset_loss*offset_delay/(2*offset_impedance)*f_sqrt, w*offset_delay+offset_loss*offset_delay/(2*offset_impedance)*f_sqrt);
|
||||
|
||||
auto Z_r = complex<double>(50.0);
|
||||
|
||||
auto Gamma_1 = (Z_c - Z_r) / (Z_c + Z_r);
|
||||
|
||||
auto Gamma_i = (Gamma_1*(1.0-exp(-2.0*gamma_l)-Gamma_1*Gamma_T)+exp(-2.0*gamma_l)*Gamma_T)
|
||||
/ (1.0-Gamma_1*(exp(-2.0*gamma_l)*Gamma_1+Gamma_T*(1.0-exp(-2.0*gamma_l))));
|
||||
|
||||
return Gamma_i;
|
||||
};
|
||||
|
||||
auto Load = male_standards ? SOLT.load_m : SOLT.load_f;
|
||||
auto Short = male_standards ? SOLT.short_m : SOLT.short_f;
|
||||
auto Open = male_standards ? SOLT.open_m : SOLT.open_f;
|
||||
auto ts_load = male_standards ? ts_load_m : ts_load_f;
|
||||
auto ts_short = male_standards ? ts_short_m : ts_short_f;
|
||||
auto ts_open = male_standards ? ts_open_m : ts_open_f;
|
||||
|
||||
fillTouchstoneCache();
|
||||
class SOLT ref;
|
||||
if(Load.useMeasurements) {
|
||||
ref.Load = ts_load->interpolate(frequency).S[0];
|
||||
} else {
|
||||
auto imp_load = complex<double>(Load.resistance, 0);
|
||||
if (SOLT.loadModelCFirst) {
|
||||
// C is the first parameter starting from the VNA port. But the load is modeled here starting from
|
||||
// the other end, so we need to start with the inductor
|
||||
imp_load += complex<double>(0, frequency * 2 * M_PI * Load.Lseries);
|
||||
}
|
||||
// Add parallel capacitor to impedance
|
||||
if(Load.Cparallel > 0) {
|
||||
auto imp_C = complex<double>(0, -1.0 / (frequency * 2 * M_PI * Load.Cparallel));
|
||||
imp_load = (imp_load * imp_C) / (imp_load + imp_C);
|
||||
}
|
||||
if (!SOLT.loadModelCFirst) {
|
||||
// inductor not added yet, do so now
|
||||
imp_load += complex<double>(0, frequency * 2 * M_PI * Load.Lseries);
|
||||
}
|
||||
ref.Load = (imp_load - complex<double>(50.0)) / (imp_load + complex<double>(50.0));
|
||||
ref.Load = addTransmissionLine(ref.Load, Load.Z0, Load.delay*1e-12, 0, frequency);
|
||||
}
|
||||
|
||||
if(Open.useMeasurements) {
|
||||
ref.Open = ts_open->interpolate(frequency).S[0];
|
||||
} else {
|
||||
// calculate fringing capacitance for open
|
||||
double Cfringing = Open.C0 * 1e-15 + Open.C1 * 1e-27 * frequency + Open.C2 * 1e-36 * pow(frequency, 2) + Open.C3 * 1e-45 * pow(frequency, 3);
|
||||
// convert to impedance
|
||||
if (Cfringing == 0) {
|
||||
// special case to avoid issues with infinity
|
||||
ref.Open = complex<double>(1.0, 0);
|
||||
} else {
|
||||
auto imp_open = complex<double>(0, -1.0 / (frequency * 2 * M_PI * Cfringing));
|
||||
ref.Open = (imp_open - complex<double>(50.0)) / (imp_open + complex<double>(50.0));
|
||||
}
|
||||
ref.Open = addTransmissionLine(ref.Open, Open.Z0, Open.delay*1e-12, Open.loss*1e9, frequency);
|
||||
}
|
||||
|
||||
if(Short.useMeasurements) {
|
||||
ref.Short = ts_short->interpolate(frequency).S[0];
|
||||
} else {
|
||||
// calculate inductance for short
|
||||
double Lseries = Short.L0 * 1e-12 + Short.L1 * 1e-24 * frequency + Short.L2 * 1e-33 * pow(frequency, 2) + Short.L3 * 1e-42 * pow(frequency, 3);
|
||||
// convert to impedance
|
||||
auto imp_short = complex<double>(0, frequency * 2 * M_PI * Lseries);
|
||||
ref.Short = (imp_short - complex<double>(50.0)) / (imp_short + complex<double>(50.0));
|
||||
ref.Short = addTransmissionLine(ref.Short, Short.Z0, Short.delay*1e-12, Short.loss*1e9, frequency);
|
||||
}
|
||||
|
||||
if(SOLT.Through.useMeasurements) {
|
||||
auto interp = ts_through->interpolate(frequency);
|
||||
ref.ThroughS11 = interp.S[0];
|
||||
ref.ThroughS12 = interp.S[1];
|
||||
ref.ThroughS21 = interp.S[2];
|
||||
ref.ThroughS22 = interp.S[3];
|
||||
} else {
|
||||
// calculate effect of through
|
||||
double through_phaseshift = -2 * M_PI * frequency * SOLT.Through.delay * 1e-12;
|
||||
double through_att_db = SOLT.Through.loss * 1e9 * 4.3429 * SOLT.Through.delay * 1e-12 / SOLT.Through.Z0 * sqrt(frequency / 1e9);;
|
||||
double through_att = pow(10.0, -through_att_db / 10.0);
|
||||
ref.ThroughS12 = polar<double>(through_att, through_phaseshift);
|
||||
// Assume symmetric and perfectly matched through for other parameters
|
||||
ref.ThroughS21 = ref.ThroughS12;
|
||||
ref.ThroughS11 = 0.0;
|
||||
ref.ThroughS22 = 0.0;
|
||||
}
|
||||
|
||||
return ref;
|
||||
return SOLT(); // TODO delete function
|
||||
}
|
||||
|
||||
class Calkit::TRL Calkit::toTRL(double)
|
||||
{
|
||||
class TRL trl;
|
||||
// reflection coefficent sign depends on whether an open or short is used
|
||||
trl.reflectionIsNegative = TRL.Reflection.isShort;
|
||||
// assume ideal through for now
|
||||
trl.ThroughS11 = 0.0;
|
||||
trl.ThroughS12 = 1.0;
|
||||
trl.ThroughS21 = 1.0;
|
||||
trl.ThroughS22 = 0.0;
|
||||
return trl;
|
||||
return TRL(); // TODO delete function
|
||||
}
|
||||
|
||||
double Calkit::minFreqTRL()
|
||||
{
|
||||
return TRL.Line.minFreq;
|
||||
return 0; // TODO delete function
|
||||
}
|
||||
|
||||
double Calkit::maxFreqTRL()
|
||||
{
|
||||
return TRL.Line.maxFreq;
|
||||
return std::numeric_limits<double>::max(); // TODO delete function
|
||||
}
|
||||
|
||||
double Calkit::minFreqSOLT(bool male_standards)
|
||||
{
|
||||
fillTouchstoneCache();
|
||||
double min = 0;
|
||||
auto ts_load = male_standards ? ts_load_m : ts_load_f;
|
||||
auto ts_short = male_standards ? ts_short_m : ts_short_f;
|
||||
auto ts_open = male_standards ? ts_open_m : ts_open_f;
|
||||
array<Touchstone*, 4> ts_list = {ts_open, ts_short, ts_load, ts_through};
|
||||
// find the highest minimum frequency in all measurement files
|
||||
for(auto ts : ts_list) {
|
||||
if(!ts) {
|
||||
// this calibration standard is defined by coefficients, no minimum frequency
|
||||
continue;
|
||||
}
|
||||
if(ts->minFreq() > min) {
|
||||
min = ts->minFreq();
|
||||
}
|
||||
}
|
||||
return min;
|
||||
return 0; // TODO delete function
|
||||
}
|
||||
|
||||
double Calkit::maxFreqSOLT(bool male_standards)
|
||||
{
|
||||
fillTouchstoneCache();
|
||||
double max = std::numeric_limits<double>::max();
|
||||
auto ts_load = male_standards ? ts_load_m : ts_load_f;
|
||||
auto ts_short = male_standards ? ts_short_m : ts_short_f;
|
||||
auto ts_open = male_standards ? ts_open_m : ts_open_f;
|
||||
array<Touchstone*, 4> ts_list = {ts_open, ts_short, ts_load, ts_through};
|
||||
// find the highest minimum frequency in all measurement files
|
||||
for(auto ts : ts_list) {
|
||||
if(!ts) {
|
||||
// this calibration standard is defined by coefficients, no minimum frequency
|
||||
continue;
|
||||
}
|
||||
if(ts->maxFreq() < max) {
|
||||
max = ts->maxFreq();
|
||||
}
|
||||
}
|
||||
return max;
|
||||
return std::numeric_limits<double>::max(); // TODO delete function
|
||||
}
|
||||
|
||||
bool Calkit::checkIfValid(double min_freq, double max_freq, bool isTRL, bool include_male, bool include_female)
|
||||
{
|
||||
auto min_supported = std::numeric_limits<double>::min();
|
||||
auto max_supported = std::numeric_limits<double>::max();
|
||||
if(isTRL) {
|
||||
min_supported = TRL.Line.minFreq;
|
||||
max_supported = TRL.Line.maxFreq;
|
||||
} else {
|
||||
if(include_male) {
|
||||
auto min_male = minFreqSOLT(true);
|
||||
auto max_male = maxFreqSOLT(true);
|
||||
if(min_male > min_supported) {
|
||||
min_supported = min_male;
|
||||
}
|
||||
if(max_male > max_supported) {
|
||||
max_supported = max_male;
|
||||
}
|
||||
}
|
||||
if(include_female) {
|
||||
auto min_female = minFreqSOLT(false);
|
||||
auto max_female = maxFreqSOLT(false);
|
||||
if(min_female > min_supported) {
|
||||
min_supported = min_female;
|
||||
}
|
||||
if(max_female > max_supported) {
|
||||
max_supported = max_female;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(min_supported <= min_freq && max_supported >= max_freq) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true; // TODO delete function
|
||||
}
|
||||
|
||||
bool Calkit::isTRLReflectionShort() const
|
||||
{
|
||||
return TRL.Reflection.isShort;
|
||||
}
|
||||
|
||||
void Calkit::TransformPathsToRelative(QFileInfo d)
|
||||
{
|
||||
vector<QString*> filenames = {&SOLT.short_m.file, &SOLT.open_m.file, &SOLT.load_m.file, &SOLT.short_f.file, &SOLT.open_f.file, &SOLT.load_f.file, &SOLT.Through.file};
|
||||
for(auto f : filenames) {
|
||||
if(f->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if(QFileInfo(*f).isAbsolute()) {
|
||||
QString buf = *f;
|
||||
*f = d.dir().relativeFilePath(*f);
|
||||
qDebug() << "Transformed" << buf << "to" << *f << "(to relative)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Calkit::TransformPathsToAbsolute(QFileInfo d)
|
||||
{
|
||||
vector<QString*> filenames = {&SOLT.short_m.file, &SOLT.open_m.file, &SOLT.load_m.file, &SOLT.short_f.file, &SOLT.open_f.file, &SOLT.load_f.file, &SOLT.Through.file};
|
||||
for(auto f : filenames) {
|
||||
if(f->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if(QFileInfo(*f).isRelative()) {
|
||||
auto absDir = QDir(d.dir().path() + "/" + *f);
|
||||
QString buf = *f;
|
||||
*f = absDir.absolutePath();
|
||||
qDebug() << "Transformed" << buf << "to" << *f << "(to absolute)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Calkit::clearTouchstoneCache()
|
||||
{
|
||||
delete ts_open_m;
|
||||
ts_open_m = nullptr;
|
||||
delete ts_short_m;
|
||||
ts_short_m = nullptr;
|
||||
delete ts_load_m;
|
||||
ts_load_m = nullptr;
|
||||
delete ts_open_f;
|
||||
ts_open_f = nullptr;
|
||||
delete ts_short_f;
|
||||
ts_short_f = nullptr;
|
||||
delete ts_load_f;
|
||||
ts_load_f = nullptr;
|
||||
delete ts_through;
|
||||
ts_through = nullptr;
|
||||
ts_cached = false;
|
||||
}
|
||||
|
||||
void Calkit::fillTouchstoneCache()
|
||||
{
|
||||
if(ts_cached) {
|
||||
return;
|
||||
}
|
||||
if(SOLT.open_m.useMeasurements) {
|
||||
ts_open_m = new Touchstone(1);
|
||||
*ts_open_m = Touchstone::fromFile(SOLT.open_m.file.toStdString());
|
||||
ts_open_m->reduceTo1Port(SOLT.open_m.Sparam);
|
||||
}
|
||||
if(SOLT.short_m.useMeasurements) {
|
||||
ts_short_m = new Touchstone(1);
|
||||
*ts_short_m = Touchstone::fromFile(SOLT.short_m.file.toStdString());
|
||||
ts_short_m->reduceTo1Port(SOLT.short_m.Sparam);
|
||||
}
|
||||
if(SOLT.load_m.useMeasurements) {
|
||||
ts_load_m = new Touchstone(1);
|
||||
*ts_load_m = Touchstone::fromFile(SOLT.load_m.file.toStdString());
|
||||
ts_load_m->reduceTo1Port(SOLT.load_m.Sparam);
|
||||
}
|
||||
if(SOLT.open_f.useMeasurements) {
|
||||
ts_open_f = new Touchstone(1);
|
||||
*ts_open_f = Touchstone::fromFile(SOLT.open_f.file.toStdString());
|
||||
ts_open_f->reduceTo1Port(SOLT.open_f.Sparam);
|
||||
}
|
||||
if(SOLT.short_f.useMeasurements) {
|
||||
ts_short_f = new Touchstone(1);
|
||||
*ts_short_f = Touchstone::fromFile(SOLT.short_f.file.toStdString());
|
||||
ts_short_f->reduceTo1Port(SOLT.short_f.Sparam);
|
||||
}
|
||||
if(SOLT.load_f.useMeasurements) {
|
||||
ts_load_f = new Touchstone(1);
|
||||
*ts_load_f = Touchstone::fromFile(SOLT.load_f.file.toStdString());
|
||||
ts_load_f->reduceTo1Port(SOLT.load_f.Sparam);
|
||||
}
|
||||
if(SOLT.Through.useMeasurements) {
|
||||
ts_through = new Touchstone(2);
|
||||
*ts_through = Touchstone::fromFile(SOLT.Through.file.toStdString());
|
||||
ts_through->reduceTo2Port(SOLT.Through.Sparam1, SOLT.Through.Sparam2);
|
||||
}
|
||||
ts_cached = true;
|
||||
return true; // TODO delete function
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "touchstone.h"
|
||||
#include "Util/qpointervariant.h"
|
||||
#include "calstandard.h"
|
||||
|
||||
#include <string>
|
||||
#include <complex>
|
||||
@ -19,9 +20,7 @@ public:
|
||||
this->manufacturer = other.manufacturer;
|
||||
this->serialnumber = other.serialnumber;
|
||||
this->description = other.description;
|
||||
this->SOLT = other.SOLT;
|
||||
this->TRL = other.TRL;
|
||||
this->startDialogWithSOLT = other.startDialogWithSOLT;
|
||||
this->standards = other.standards;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -53,146 +52,14 @@ public:
|
||||
bool isTRLReflectionShort() const;
|
||||
|
||||
private:
|
||||
void TransformPathsToRelative(QFileInfo d);
|
||||
void TransformPathsToAbsolute(QFileInfo d);
|
||||
|
||||
QString manufacturer, serialnumber, description;
|
||||
// SOLT standard definitions
|
||||
struct {
|
||||
using Open = struct {
|
||||
double Z0, delay, loss, C0, C1, C2, C3;
|
||||
QString file;
|
||||
bool useMeasurements;
|
||||
int Sparam;
|
||||
};
|
||||
Open open_m, open_f;
|
||||
using Short = struct {
|
||||
double Z0, delay, loss, L0, L1, L2, L3;
|
||||
QString file;
|
||||
bool useMeasurements;
|
||||
int Sparam;
|
||||
};
|
||||
Short short_m, short_f;
|
||||
using Load = struct {
|
||||
double resistance, Z0, delay, Cparallel, Lseries;
|
||||
QString file;
|
||||
bool useMeasurements;
|
||||
int Sparam;
|
||||
};
|
||||
Load load_m, load_f;
|
||||
bool loadModelCFirst;
|
||||
struct {
|
||||
double Z0, delay, loss;
|
||||
QString file;
|
||||
bool useMeasurements;
|
||||
int Sparam1, Sparam2;
|
||||
} Through;
|
||||
bool separate_male_female;
|
||||
} SOLT;
|
||||
struct {
|
||||
struct {
|
||||
double Z0;
|
||||
} Through;
|
||||
struct {
|
||||
bool isShort;
|
||||
} Reflection;
|
||||
struct {
|
||||
double delay, minFreq, maxFreq;
|
||||
} Line;
|
||||
} TRL;
|
||||
bool startDialogWithSOLT;
|
||||
|
||||
Touchstone *ts_open_m, *ts_short_m, *ts_load_m;
|
||||
Touchstone *ts_open_f, *ts_short_f, *ts_load_f;
|
||||
Touchstone *ts_through;
|
||||
bool ts_cached;
|
||||
std::vector<CalStandard::Virtual*> standards;
|
||||
|
||||
const std::vector<Savable::SettingDescription> descr = {{
|
||||
{&manufacturer, "Manufacturer", ""},
|
||||
{&serialnumber, "Serialnumber", ""},
|
||||
{&description, "Description", ""},
|
||||
|
||||
{&SOLT.open_m.Z0, "SOLT.Open.Param.Z0", 50.0},
|
||||
{&SOLT.open_m.delay, "SOLT.Open.Param.Delay", 0.0},
|
||||
{&SOLT.open_m.loss, "SOLT.Open.Param.Loss", 0.0},
|
||||
{&SOLT.open_m.C0, "SOLT.Open.Param.C0", 0.0},
|
||||
{&SOLT.open_m.C1, "SOLT.Open.Param.C1", 0.0},
|
||||
{&SOLT.open_m.C2, "SOLT.Open.Param.C2", 0.0},
|
||||
{&SOLT.open_m.C3, "SOLT.Open.Param.C3", 0.0},
|
||||
{&SOLT.open_m.useMeasurements, "SOLT.Open.Measurements.Use", false},
|
||||
{&SOLT.open_m.file, "SOLT.Open.Measurements.File", ""},
|
||||
{&SOLT.open_m.Sparam, "SOLT.Open.Measurements.Port", 0},
|
||||
{&SOLT.open_f.Z0, "SOLT.Open.Param.Z0_Female", 50.0},
|
||||
{&SOLT.open_f.delay, "SOLT.Open.Param.Delay_Female", 0.0},
|
||||
{&SOLT.open_f.loss, "SOLT.Open.Param.Loss_Female", 0.0},
|
||||
{&SOLT.open_f.C0, "SOLT.Open.Param.C0_Female", 0.0},
|
||||
{&SOLT.open_f.C1, "SOLT.Open.Param.C1_Female", 0.0},
|
||||
{&SOLT.open_f.C2, "SOLT.Open.Param.C2_Female", 0.0},
|
||||
{&SOLT.open_f.C3, "SOLT.Open.Param.C3_Female", 0.0},
|
||||
{&SOLT.open_f.useMeasurements, "SOLT.Open.Measurements.Use_Female", false},
|
||||
{&SOLT.open_f.file, "SOLT.Open.Measurements.File_Female", ""},
|
||||
{&SOLT.open_f.Sparam, "SOLT.Open.Measurements.Port_Female", 0},
|
||||
|
||||
{&SOLT.short_m.Z0, "SOLT.Short.Param.Z0", 50.0},
|
||||
{&SOLT.short_m.delay, "SOLT.Short.Param.Delay", 0.0},
|
||||
{&SOLT.short_m.loss, "SOLT.Short.Param.Loss", 0.0},
|
||||
{&SOLT.short_m.L0, "SOLT.Short.Param.L0", 0.0},
|
||||
{&SOLT.short_m.L1, "SOLT.Short.Param.L1", 0.0},
|
||||
{&SOLT.short_m.L2, "SOLT.Short.Param.L2", 0.0},
|
||||
{&SOLT.short_m.L3, "SOLT.Short.Param.L3", 0.0},
|
||||
{&SOLT.short_m.useMeasurements, "SOLT.Short.Measurements.Use", false},
|
||||
{&SOLT.short_m.file, "SOLT.Short.Measurements.File", ""},
|
||||
{&SOLT.short_m.Sparam, "SOLT.Short.Measurements.Port", 0},
|
||||
{&SOLT.short_f.Z0, "SOLT.Short.Param.Z0_Female", 50.0},
|
||||
{&SOLT.short_f.delay, "SOLT.Short.Param.Delay_Female", 0.0},
|
||||
{&SOLT.short_f.loss, "SOLT.Short.Param.Loss_Female", 0.0},
|
||||
{&SOLT.short_f.L0, "SOLT.Short.Param.L0_Female", 0.0},
|
||||
{&SOLT.short_f.L1, "SOLT.Short.Param.L1_Female", 0.0},
|
||||
{&SOLT.short_f.L2, "SOLT.Short.Param.L2_Female", 0.0},
|
||||
{&SOLT.short_f.L3, "SOLT.Short.Param.L3_Female", 0.0},
|
||||
{&SOLT.short_f.useMeasurements, "SOLT.Short.Measurements.Use_Female", false},
|
||||
{&SOLT.short_f.file, "SOLT.Short.Measurements.File_Female", ""},
|
||||
{&SOLT.short_f.Sparam, "SOLT.Short.Measurements.Port_Female", 0},
|
||||
|
||||
{&SOLT.loadModelCFirst, "SOLT.loadModelCFirst", true},
|
||||
{&SOLT.load_m.resistance, "SOLT.Load.Param.Resistance", 50.0},
|
||||
{&SOLT.load_m.Z0, "SOLT.Load.Param.Z0", 50.0},
|
||||
{&SOLT.load_m.delay, "SOLT.Load.Param.Delay", 0.0},
|
||||
{&SOLT.load_m.Cparallel, "SOLT.Load.Param.C", 0.0},
|
||||
{&SOLT.load_m.Lseries, "SOLT.Load.Param.L", 0.0},
|
||||
{&SOLT.load_m.useMeasurements, "SOLT.Load.Measurements.Use", false},
|
||||
{&SOLT.load_m.file, "SOLT.Load.Measurements.File", ""},
|
||||
{&SOLT.load_m.Sparam, "SOLT.Load.Measurements.Port", 0},
|
||||
{&SOLT.load_f.resistance, "SOLT.Load.Param.Resistance_Female", 50.0},
|
||||
{&SOLT.load_f.Z0, "SOLT.Load.Param.Z0_Female", 50.0},
|
||||
{&SOLT.load_f.delay, "SOLT.Load.Param.Delay_Female", 0.0},
|
||||
{&SOLT.load_f.Cparallel, "SOLT.Load.Param.C_Female", 0.0},
|
||||
{&SOLT.load_f.Lseries, "SOLT.Load.Param.L_Female", 0.0},
|
||||
{&SOLT.load_f.useMeasurements, "SOLT.Load.Measurements.Use_Female", false},
|
||||
{&SOLT.load_f.file, "SOLT.Load.Measurements.File_Female", ""},
|
||||
{&SOLT.load_f.Sparam, "SOLT.Load.Measurements.Port_Female", 0},
|
||||
|
||||
{&SOLT.Through.Z0, "SOLT.Through.Param.Z0", 50.0},
|
||||
{&SOLT.Through.delay, "SOLT.Through.Param.Delay", 0.0},
|
||||
{&SOLT.Through.loss, "SOLT.Through.Param.Loss", 0.0},
|
||||
{&SOLT.Through.useMeasurements, "SOLT.Through.Measurements.Use", false},
|
||||
{&SOLT.Through.file, "SOLT.Through.Measurements.File", ""},
|
||||
{&SOLT.Through.Sparam1, "SOLT.Through.Measurements.Port1", 0},
|
||||
{&SOLT.Through.Sparam2, "SOLT.Through.Measurements.Port2", 1},
|
||||
|
||||
{&SOLT.separate_male_female, "SOLT.SeparateMaleFemale", false},
|
||||
|
||||
{&TRL.Through.Z0, "TRL.Through.Z0", 50.0},
|
||||
{&TRL.Reflection.isShort, "TRL.Reflect.isShort", false},
|
||||
{&TRL.Line.delay, "TRL.Line.Delay", 74.0},
|
||||
{&TRL.Line.minFreq, "TRL.Line.minFreq", 751000000.0},
|
||||
{&TRL.Line.maxFreq, "TRL.Line.maxFreq", 6000000000.0},
|
||||
|
||||
{&startDialogWithSOLT, "StartDialogWithSOLT", true}
|
||||
}};
|
||||
|
||||
void clearTouchstoneCache();
|
||||
void fillTouchstoneCache();
|
||||
};
|
||||
|
||||
#endif // CALKIT_H
|
||||
|
@ -9,192 +9,87 @@
|
||||
#include <fstream>
|
||||
#include <touchstone.h>
|
||||
#include <QtGlobal>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
||||
using namespace std;
|
||||
|
||||
CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::CalkitDialog),
|
||||
open_ok(true),
|
||||
short_ok(true),
|
||||
load_ok(true),
|
||||
through_ok(true),
|
||||
editKit(c)
|
||||
kit(c)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->OpenType->setId(ui->open_coefficients, 0);
|
||||
ui->OpenType->setId(ui->open_measurement, 1);
|
||||
|
||||
ui->ShortType->setId(ui->short_coefficients, 0);
|
||||
ui->ShortType->setId(ui->short_measurement, 1);
|
||||
|
||||
ui->LoadType->setId(ui->load_coefficients, 0);
|
||||
ui->LoadType->setId(ui->load_measurement, 1);
|
||||
|
||||
ui->ThroughType->setId(ui->through_coefficients, 0);
|
||||
ui->ThroughType->setId(ui->through_measurement, 1);
|
||||
|
||||
ui->open_touchstone->setPorts(1);
|
||||
ui->short_touchstone->setPorts(1);
|
||||
ui->load_touchstone->setPorts(1);
|
||||
ui->through_touchstone->setPorts(2);
|
||||
|
||||
ui->short_Z0->setUnit("Ω");
|
||||
ui->open_Z0->setUnit("Ω");
|
||||
ui->load_resistance->setUnit("Ω");
|
||||
ui->load_Z0->setUnit("Ω");
|
||||
ui->load_parC->setUnit("F");
|
||||
ui->load_parC->setPrefixes("fpnum ");
|
||||
ui->load_serL->setUnit("H");
|
||||
ui->load_serL->setPrefixes("fpnum ");
|
||||
|
||||
// Same setup for female standards
|
||||
ui->OpenType_f->setId(ui->open_coefficients_f, 0);
|
||||
ui->OpenType_f->setId(ui->open_measurement_f, 1);
|
||||
|
||||
ui->ShortType_f->setId(ui->short_coefficients_f, 0);
|
||||
ui->ShortType_f->setId(ui->short_measurement_f, 1);
|
||||
|
||||
ui->LoadType_f->setId(ui->load_coefficients_f, 0);
|
||||
ui->LoadType_f->setId(ui->load_measurement_f, 1);
|
||||
|
||||
ui->open_touchstone_f->setPorts(1);
|
||||
ui->short_touchstone_f->setPorts(1);
|
||||
ui->load_touchstone_f->setPorts(1);
|
||||
|
||||
ui->short_Z0_f->setUnit("Ω");
|
||||
ui->open_Z0_f->setUnit("Ω");
|
||||
ui->load_resistance_f->setUnit("Ω");
|
||||
ui->load_Z0_f->setUnit("Ω");
|
||||
ui->load_parC_f->setUnit("F");
|
||||
ui->load_parC_f->setPrefixes("fpnum ");
|
||||
ui->load_serL_f->setUnit("H");
|
||||
ui->load_serL_f->setPrefixes("fpnum ");
|
||||
|
||||
ui->through_Z0->setUnit("Ω");
|
||||
|
||||
ui->TRL_through_Z0->setUnit("Ω");
|
||||
ui->TRL_line_max->setUnit("Hz");
|
||||
ui->TRL_line_max->setPrecision(4);
|
||||
ui->TRL_line_max->setPrefixes(" kMG");
|
||||
ui->TRL_line_min->setUnit("Hz");
|
||||
ui->TRL_line_min->setPrecision(4);
|
||||
ui->TRL_line_min->setPrefixes(" kMG");
|
||||
|
||||
editKit.clearTouchstoneCache();
|
||||
ownKit = editKit;
|
||||
|
||||
connect(ui->cbStandardDefinition, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index){
|
||||
if (index == 0) {
|
||||
// common definition, hide tab bars, set all to male tab
|
||||
ui->mf_short->setCurrentIndex(0);
|
||||
ui->mf_short->tabBar()->hide();
|
||||
ui->mf_open->setCurrentIndex(0);
|
||||
ui->mf_open->tabBar()->hide();
|
||||
ui->mf_load->setCurrentIndex(0);
|
||||
ui->mf_load->tabBar()->hide();
|
||||
} else {
|
||||
// separate definitions for male/female standards
|
||||
ui->mf_short->tabBar()->show();
|
||||
ui->mf_open->tabBar()->show();
|
||||
ui->mf_load->tabBar()->show();
|
||||
}
|
||||
});
|
||||
|
||||
updateEntries();
|
||||
|
||||
connect(ui->TRL_line_min, &SIUnitEdit::valueChanged, [=](double newval){
|
||||
ownKit.TRL.Line.minFreq = newval;
|
||||
updateEntries();
|
||||
});
|
||||
connect(ui->TRL_line_max, &SIUnitEdit::valueChanged, [=](double newval){
|
||||
ownKit.TRL.Line.maxFreq = newval;
|
||||
updateEntries();
|
||||
});
|
||||
connect(ui->TRL_line_delay, &QLineEdit::editingFinished, [=](){
|
||||
ownKit.TRL.Line.delay = ui->TRL_line_delay->value();
|
||||
updateEntries();
|
||||
connect(ui->bDelete, &QPushButton::clicked, [=](){
|
||||
auto row = ui->list->currentRow();
|
||||
if(row >= 0) {
|
||||
delete kit.standards[row];
|
||||
kit.standards.erase(kit.standards.begin() + row);
|
||||
updateStandardList();
|
||||
}
|
||||
});
|
||||
|
||||
auto UpdateStatus = [=]() {
|
||||
bool ok = true;
|
||||
if(ui->open_measurement->isChecked() && !ui->open_touchstone->getStatus()) {
|
||||
ok = false;
|
||||
connect(ui->bMoveUp, &QPushButton::clicked, [=](){
|
||||
auto row = ui->list->currentRow();
|
||||
if(row >= 1) {
|
||||
swap(kit.standards[row], kit.standards[row-1]);
|
||||
ui->list->setCurrentRow(row-1);
|
||||
updateStandardList();
|
||||
}
|
||||
if(ui->short_measurement->isChecked() && !ui->short_touchstone->getStatus()) {
|
||||
ok = false;
|
||||
}
|
||||
if(ui->load_measurement->isChecked() && !ui->load_touchstone->getStatus()) {
|
||||
ok = false;
|
||||
}
|
||||
if(ui->open_measurement_f->isChecked() && !ui->open_touchstone_f->getStatus()) {
|
||||
ok = false;
|
||||
}
|
||||
if(ui->short_measurement_f->isChecked() && !ui->short_touchstone_f->getStatus()) {
|
||||
ok = false;
|
||||
}
|
||||
if(ui->load_measurement_f->isChecked() && !ui->load_touchstone_f->getStatus()) {
|
||||
ok = false;
|
||||
}
|
||||
if(ui->through_measurement->isChecked() && !ui->through_touchstone->getStatus()) {
|
||||
ok = false;
|
||||
}
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok);
|
||||
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(ok);
|
||||
};
|
||||
});
|
||||
|
||||
connect(ui->open_touchstone, &TouchstoneImport::statusChanged, UpdateStatus);
|
||||
connect(ui->short_touchstone, &TouchstoneImport::statusChanged, UpdateStatus);
|
||||
connect(ui->load_touchstone, &TouchstoneImport::statusChanged, UpdateStatus);
|
||||
connect(ui->open_touchstone_f, &TouchstoneImport::statusChanged, UpdateStatus);
|
||||
connect(ui->short_touchstone_f, &TouchstoneImport::statusChanged, UpdateStatus);
|
||||
connect(ui->load_touchstone_f, &TouchstoneImport::statusChanged, UpdateStatus);
|
||||
connect(ui->through_touchstone, &TouchstoneImport::statusChanged, UpdateStatus);
|
||||
connect(ui->bMoveDown, &QPushButton::clicked, [=](){
|
||||
auto row = ui->list->currentRow();
|
||||
if(row < ui->list->count() - 1) {
|
||||
swap(kit.standards[row], kit.standards[row+1]);
|
||||
ui->list->setCurrentRow(row+1);
|
||||
updateStandardList();
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->OpenType, qOverload<int>(&QButtonGroup::buttonClicked), [=](int) {
|
||||
UpdateStatus();
|
||||
});
|
||||
connect(ui->ShortType, qOverload<int>(&QButtonGroup::buttonClicked), [=](int) {
|
||||
UpdateStatus();
|
||||
});
|
||||
connect(ui->LoadType, qOverload<int>(&QButtonGroup::buttonClicked), [=](int) {
|
||||
UpdateStatus();
|
||||
});
|
||||
connect(ui->OpenType_f, qOverload<int>(&QButtonGroup::buttonClicked), [=](int) {
|
||||
UpdateStatus();
|
||||
});
|
||||
connect(ui->ShortType_f, qOverload<int>(&QButtonGroup::buttonClicked), [=](int) {
|
||||
UpdateStatus();
|
||||
});
|
||||
connect(ui->LoadType_f, qOverload<int>(&QButtonGroup::buttonClicked), [=](int) {
|
||||
UpdateStatus();
|
||||
});
|
||||
connect(ui->ThroughType, qOverload<int>(&QButtonGroup::buttonClicked), [=](int) {
|
||||
UpdateStatus();
|
||||
connect(ui->list, &QListWidget::currentRowChanged, this, &CalkitDialog::updateListEditButtons);
|
||||
|
||||
auto addMenu = new QMenu();
|
||||
for(auto t : CalStandard::Virtual::availableTypes()) {
|
||||
auto action = new QAction(CalStandard::Virtual::TypeToString(t));
|
||||
connect(action, &QAction::triggered, [=](){
|
||||
auto newStandard = CalStandard::Virtual::create(t);
|
||||
if(newStandard) {
|
||||
kit.standards.push_back(newStandard);
|
||||
updateStandardList();
|
||||
// start the edit dialog of the newly created standard
|
||||
kit.standards.back()->edit(bind(&CalkitDialog::updateStandardList, this));
|
||||
}
|
||||
});
|
||||
addMenu->addAction(action);
|
||||
}
|
||||
|
||||
ui->bAdd->setMenu(addMenu);
|
||||
|
||||
connect(ui->list, &QListWidget::doubleClicked, [=](const QModelIndex &index){
|
||||
if(!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
kit.standards[index.row()]->edit(bind(&CalkitDialog::updateStandardList, this));
|
||||
});
|
||||
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, [this]() {
|
||||
parseEntries();
|
||||
editKit = ownKit;
|
||||
editKit.clearTouchstoneCache();
|
||||
emit settingsChanged();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, [this]() {
|
||||
parseEntries();
|
||||
editKit = ownKit;
|
||||
editKit.clearTouchstoneCache();
|
||||
emit settingsChanged();
|
||||
accept();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, [this]() {
|
||||
reject();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Open), &QPushButton::clicked, [=](){
|
||||
auto filename = QFileDialog::getOpenFileName(this, "Open calibration kit coefficients", "", "Calibration kit files (*.calkit)", nullptr, QFileDialog::DontUseNativeDialog);
|
||||
if(filename.length() > 0) {
|
||||
try {
|
||||
ownKit = Calkit::fromFile(filename);
|
||||
kit = Calkit::fromFile(filename);
|
||||
} catch (runtime_error &e) {
|
||||
InformationBox::ShowError("Error", "The calibration kit file could not be parsed (" + QString(e.what()) + ")");
|
||||
qWarning() << "Parsing of calibration kit failed while opening calibration file: " << e.what();
|
||||
@ -207,7 +102,7 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Save calibration kit coefficients", "", "Calibration kit files (*.calkit)", nullptr, QFileDialog::DontUseNativeDialog);
|
||||
if(filename.length() > 0) {
|
||||
parseEntries();
|
||||
ownKit.toFile(filename);
|
||||
kit.toFile(filename);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -217,256 +112,40 @@ CalkitDialog::~CalkitDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CalkitDialog::updateListEditButtons()
|
||||
{
|
||||
ui->bDelete->setEnabled(ui->list->currentRow() >= 0);
|
||||
ui->bMoveUp->setEnabled(ui->list->currentRow() >= 1);
|
||||
ui->bMoveDown->setEnabled(ui->list->currentRow() >= 0 && ui->list->currentRow() < ui->list->count() - 1);
|
||||
}
|
||||
|
||||
void CalkitDialog::parseEntries()
|
||||
{
|
||||
ownKit.manufacturer = ui->manufacturer->text();
|
||||
ownKit.serialnumber = ui->serialnumber->text();
|
||||
ownKit.description = ui->description->toPlainText();
|
||||
|
||||
// type
|
||||
ownKit.SOLT.open_m.useMeasurements = ui->open_measurement->isChecked();
|
||||
ownKit.SOLT.short_m.useMeasurements = ui->short_measurement->isChecked();
|
||||
ownKit.SOLT.load_m.useMeasurements = ui->load_measurement->isChecked();
|
||||
ownKit.SOLT.open_f.useMeasurements = ui->open_measurement_f->isChecked();
|
||||
ownKit.SOLT.short_f.useMeasurements = ui->short_measurement_f->isChecked();
|
||||
ownKit.SOLT.load_f.useMeasurements = ui->load_measurement_f->isChecked();
|
||||
ownKit.SOLT.Through.useMeasurements = ui->through_measurement->isChecked();
|
||||
|
||||
// coefficients
|
||||
ownKit.SOLT.open_m.Z0 = ui->open_Z0->value();
|
||||
ownKit.SOLT.open_m.delay = ui->open_delay->value();
|
||||
ownKit.SOLT.open_m.loss = ui->open_loss->value();
|
||||
ownKit.SOLT.open_m.C0 = ui->open_C0->value();
|
||||
ownKit.SOLT.open_m.C1 = ui->open_C1->value();
|
||||
ownKit.SOLT.open_m.C2 = ui->open_C2->value();
|
||||
ownKit.SOLT.open_m.C3 = ui->open_C3->value();
|
||||
|
||||
ownKit.SOLT.short_m.Z0 = ui->short_Z0->value();
|
||||
ownKit.SOLT.short_m.delay = ui->short_delay->value();
|
||||
ownKit.SOLT.short_m.loss = ui->short_loss->value();
|
||||
ownKit.SOLT.short_m.L0 = ui->short_L0->value();
|
||||
ownKit.SOLT.short_m.L1 = ui->short_L1->value();
|
||||
ownKit.SOLT.short_m.L2 = ui->short_L2->value();
|
||||
ownKit.SOLT.short_m.L3 = ui->short_L3->value();
|
||||
|
||||
ownKit.SOLT.loadModelCFirst = ui->load_C_first->isChecked();
|
||||
ownKit.SOLT.load_m.resistance = ui->load_resistance->value();
|
||||
ownKit.SOLT.load_m.Z0 = ui->load_Z0->value();
|
||||
ownKit.SOLT.load_m.delay = ui->load_delay->value();
|
||||
ownKit.SOLT.load_m.Cparallel = ui->load_parC->value();
|
||||
ownKit.SOLT.load_m.Lseries = ui->load_serL->value();
|
||||
|
||||
ownKit.SOLT.open_f.Z0 = ui->open_Z0_f->value();
|
||||
ownKit.SOLT.open_f.delay = ui->open_delay_f->value();
|
||||
ownKit.SOLT.open_f.loss = ui->open_loss_f->value();
|
||||
ownKit.SOLT.open_f.C0 = ui->open_C0_f->value();
|
||||
ownKit.SOLT.open_f.C1 = ui->open_C1_f->value();
|
||||
ownKit.SOLT.open_f.C2 = ui->open_C2_f->value();
|
||||
ownKit.SOLT.open_f.C3 = ui->open_C3_f->value();
|
||||
|
||||
ownKit.SOLT.short_f.Z0 = ui->short_Z0_f->value();
|
||||
ownKit.SOLT.short_f.delay = ui->short_delay_f->value();
|
||||
ownKit.SOLT.short_f.loss = ui->short_loss_f->value();
|
||||
ownKit.SOLT.short_f.L0 = ui->short_L0_f->value();
|
||||
ownKit.SOLT.short_f.L1 = ui->short_L1_f->value();
|
||||
ownKit.SOLT.short_f.L2 = ui->short_L2_f->value();
|
||||
ownKit.SOLT.short_f.L3 = ui->short_L3_f->value();
|
||||
|
||||
ownKit.SOLT.load_f.resistance = ui->load_resistance_f->value();
|
||||
ownKit.SOLT.load_f.Z0 = ui->load_Z0_f->value();
|
||||
ownKit.SOLT.load_f.delay = ui->load_delay_f->value();
|
||||
ownKit.SOLT.load_f.Cparallel = ui->load_parC_f->value();
|
||||
ownKit.SOLT.load_f.Lseries = ui->load_serL_f->value();
|
||||
|
||||
ownKit.SOLT.Through.Z0 = ui->through_Z0->value();
|
||||
ownKit.SOLT.Through.delay = ui->through_delay->value();
|
||||
ownKit.SOLT.Through.loss = ui->through_loss->value();
|
||||
|
||||
ownKit.SOLT.separate_male_female = ui->cbStandardDefinition->currentIndex() == 1;
|
||||
|
||||
// file
|
||||
ownKit.SOLT.open_m.file = ui->open_touchstone->getFilename();
|
||||
ownKit.SOLT.short_m.file = ui->short_touchstone->getFilename();
|
||||
ownKit.SOLT.load_m.file = ui->load_touchstone->getFilename();
|
||||
ownKit.SOLT.Through.file = ui->through_touchstone->getFilename();
|
||||
|
||||
ownKit.SOLT.open_m.Sparam = ui->open_touchstone->getPorts()[0];
|
||||
ownKit.SOLT.short_m.Sparam = ui->short_touchstone->getPorts()[0];
|
||||
ownKit.SOLT.load_m.Sparam = ui->load_touchstone->getPorts()[0];
|
||||
ownKit.SOLT.Through.Sparam1 = ui->through_touchstone->getPorts()[0];
|
||||
ownKit.SOLT.Through.Sparam2 = ui->through_touchstone->getPorts()[1];
|
||||
|
||||
ownKit.SOLT.open_f.file = ui->open_touchstone_f->getFilename();
|
||||
ownKit.SOLT.short_f.file = ui->short_touchstone_f->getFilename();
|
||||
ownKit.SOLT.load_f.file = ui->load_touchstone_f->getFilename();
|
||||
|
||||
ownKit.SOLT.open_f.Sparam = ui->open_touchstone_f->getPorts()[0];
|
||||
ownKit.SOLT.short_f.Sparam = ui->short_touchstone_f->getPorts()[0];
|
||||
ownKit.SOLT.load_f.Sparam = ui->load_touchstone_f->getPorts()[0];
|
||||
|
||||
// TRL
|
||||
ownKit.TRL.Through.Z0 = ui->TRL_through_Z0->value();
|
||||
ownKit.TRL.Reflection.isShort = ui->TRL_R_short->isChecked();
|
||||
ownKit.TRL.Line.delay = ui->TRL_line_delay->value();
|
||||
ownKit.TRL.Line.minFreq = ui->TRL_line_min->value();
|
||||
ownKit.TRL.Line.maxFreq = ui->TRL_line_max->value();
|
||||
|
||||
ownKit.startDialogWithSOLT = ui->tabWidget->currentIndex() == 0;
|
||||
kit.manufacturer = ui->manufacturer->text();
|
||||
kit.serialnumber = ui->serialnumber->text();
|
||||
kit.description = ui->description->toPlainText();
|
||||
}
|
||||
|
||||
void CalkitDialog::updateEntries()
|
||||
{
|
||||
ui->manufacturer->setText(ownKit.manufacturer);
|
||||
ui->serialnumber->setText(ownKit.serialnumber);
|
||||
ui->description->setPlainText(ownKit.description);
|
||||
|
||||
// Coefficients
|
||||
ui->open_Z0->setValueQuiet(ownKit.SOLT.open_m.Z0);
|
||||
ui->open_delay->setValueQuiet(ownKit.SOLT.open_m.delay);
|
||||
ui->open_loss->setValueQuiet(ownKit.SOLT.open_m.loss);
|
||||
ui->open_C0->setValueQuiet(ownKit.SOLT.open_m.C0);
|
||||
ui->open_C1->setValueQuiet(ownKit.SOLT.open_m.C1);
|
||||
ui->open_C2->setValueQuiet(ownKit.SOLT.open_m.C2);
|
||||
ui->open_C3->setValueQuiet(ownKit.SOLT.open_m.C3);
|
||||
|
||||
ui->short_Z0->setValueQuiet(ownKit.SOLT.short_m.Z0);
|
||||
ui->short_delay->setValueQuiet(ownKit.SOLT.short_m.delay);
|
||||
ui->short_loss->setValueQuiet(ownKit.SOLT.short_m.loss);
|
||||
ui->short_L0->setValueQuiet(ownKit.SOLT.short_m.L0);
|
||||
ui->short_L1->setValueQuiet(ownKit.SOLT.short_m.L1);
|
||||
ui->short_L2->setValueQuiet(ownKit.SOLT.short_m.L2);
|
||||
ui->short_L3->setValueQuiet(ownKit.SOLT.short_m.L3);
|
||||
|
||||
ui->load_C_first->setChecked(ownKit.SOLT.loadModelCFirst);
|
||||
ui->load_L_first->setChecked(!ownKit.SOLT.loadModelCFirst);
|
||||
ui->load_resistance->setValueQuiet(ownKit.SOLT.load_m.resistance);
|
||||
ui->load_Z0->setValueQuiet(ownKit.SOLT.load_m.Z0);
|
||||
ui->load_delay->setValueQuiet(ownKit.SOLT.load_m.delay);
|
||||
ui->load_parC->setValueQuiet(ownKit.SOLT.load_m.Cparallel);
|
||||
ui->load_serL->setValueQuiet(ownKit.SOLT.load_m.Lseries);
|
||||
|
||||
ui->open_Z0_f->setValueQuiet(ownKit.SOLT.open_f.Z0);
|
||||
ui->open_delay_f->setValueQuiet(ownKit.SOLT.open_f.delay);
|
||||
ui->open_loss_f->setValueQuiet(ownKit.SOLT.open_f.loss);
|
||||
ui->open_C0_f->setValueQuiet(ownKit.SOLT.open_f.C0);
|
||||
ui->open_C1_f->setValueQuiet(ownKit.SOLT.open_f.C1);
|
||||
ui->open_C2_f->setValueQuiet(ownKit.SOLT.open_f.C2);
|
||||
ui->open_C3_f->setValueQuiet(ownKit.SOLT.open_f.C3);
|
||||
|
||||
ui->short_Z0_f->setValueQuiet(ownKit.SOLT.short_f.Z0);
|
||||
ui->short_delay_f->setValueQuiet(ownKit.SOLT.short_f.delay);
|
||||
ui->short_loss_f->setValueQuiet(ownKit.SOLT.short_f.loss);
|
||||
ui->short_L0_f->setValueQuiet(ownKit.SOLT.short_f.L0);
|
||||
ui->short_L1_f->setValueQuiet(ownKit.SOLT.short_f.L1);
|
||||
ui->short_L2_f->setValueQuiet(ownKit.SOLT.short_f.L2);
|
||||
ui->short_L3_f->setValueQuiet(ownKit.SOLT.short_f.L3);
|
||||
|
||||
ui->load_resistance_f->setValueQuiet(ownKit.SOLT.load_f.resistance);
|
||||
ui->load_Z0_f->setValueQuiet(ownKit.SOLT.load_f.Z0);
|
||||
ui->load_delay_f->setValueQuiet(ownKit.SOLT.load_f.delay);
|
||||
ui->load_parC_f->setValueQuiet(ownKit.SOLT.load_f.Cparallel);
|
||||
ui->load_serL_f->setValueQuiet(ownKit.SOLT.load_f.Lseries);
|
||||
|
||||
ui->through_Z0->setValueQuiet(ownKit.SOLT.Through.Z0);
|
||||
ui->through_delay->setValueQuiet(ownKit.SOLT.Through.delay);
|
||||
ui->through_loss->setValueQuiet(ownKit.SOLT.Through.loss);
|
||||
|
||||
// Measurements
|
||||
ui->open_touchstone->setFile(ownKit.SOLT.open_m.file);
|
||||
ui->open_touchstone->selectPort(0, ownKit.SOLT.open_m.Sparam);
|
||||
|
||||
ui->short_touchstone->setFile(ownKit.SOLT.short_m.file);
|
||||
ui->short_touchstone->selectPort(0, ownKit.SOLT.short_m.Sparam);
|
||||
|
||||
ui->load_touchstone->setFile(ownKit.SOLT.load_m.file);
|
||||
ui->load_touchstone->selectPort(0, ownKit.SOLT.load_m.Sparam);
|
||||
|
||||
ui->open_touchstone_f->setFile(ownKit.SOLT.open_f.file);
|
||||
ui->open_touchstone_f->selectPort(0, ownKit.SOLT.open_f.Sparam);
|
||||
|
||||
ui->short_touchstone_f->setFile(ownKit.SOLT.short_f.file);
|
||||
ui->short_touchstone_f->selectPort(0, ownKit.SOLT.short_f.Sparam);
|
||||
|
||||
ui->load_touchstone_f->setFile(ownKit.SOLT.load_f.file);
|
||||
ui->load_touchstone_f->selectPort(0, ownKit.SOLT.load_f.Sparam);
|
||||
|
||||
ui->through_touchstone->setFile(ownKit.SOLT.Through.file);
|
||||
ui->through_touchstone->selectPort(0, ownKit.SOLT.Through.Sparam1);
|
||||
ui->through_touchstone->selectPort(1, ownKit.SOLT.Through.Sparam2);
|
||||
|
||||
// Type
|
||||
if (ownKit.SOLT.open_m.useMeasurements) {
|
||||
ui->open_measurement->click();
|
||||
} else {
|
||||
ui->open_coefficients->click();
|
||||
}
|
||||
|
||||
if (ownKit.SOLT.short_m.useMeasurements) {
|
||||
ui->short_measurement->click();
|
||||
} else {
|
||||
ui->short_coefficients->click();
|
||||
}
|
||||
|
||||
if (ownKit.SOLT.load_m.useMeasurements) {
|
||||
ui->load_measurement->click();
|
||||
} else {
|
||||
ui->load_coefficients->click();
|
||||
}
|
||||
|
||||
if (ownKit.SOLT.open_f.useMeasurements) {
|
||||
ui->open_measurement_f->click();
|
||||
} else {
|
||||
ui->open_coefficients_f->click();
|
||||
}
|
||||
|
||||
if (ownKit.SOLT.short_f.useMeasurements) {
|
||||
ui->short_measurement_f->click();
|
||||
} else {
|
||||
ui->short_coefficients_f->click();
|
||||
}
|
||||
|
||||
if (ownKit.SOLT.load_f.useMeasurements) {
|
||||
ui->load_measurement_f->click();
|
||||
} else {
|
||||
ui->load_coefficients_f->click();
|
||||
}
|
||||
|
||||
if (ownKit.SOLT.Through.useMeasurements) {
|
||||
ui->through_measurement->click();
|
||||
} else {
|
||||
ui->through_coefficients->click();
|
||||
}
|
||||
|
||||
if (ownKit.SOLT.separate_male_female) {
|
||||
ui->cbStandardDefinition->setCurrentIndex(1);
|
||||
} else {
|
||||
ui->cbStandardDefinition->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
// TRL
|
||||
ui->TRL_through_Z0->setValueQuiet(ownKit.TRL.Through.Z0);
|
||||
if(ownKit.TRL.Reflection.isShort) {
|
||||
ui->TRL_R_short->setChecked(true);
|
||||
} else {
|
||||
ui->TRL_R_open->setChecked(true);
|
||||
}
|
||||
ui->TRL_line_delay->setValueQuiet(ownKit.TRL.Line.delay);
|
||||
ui->TRL_line_min->setValueQuiet(ownKit.TRL.Line.minFreq);
|
||||
ui->TRL_line_max->setValueQuiet(ownKit.TRL.Line.maxFreq);
|
||||
// Check if line length is appropriate for frequencies
|
||||
auto minDelay = 20.0/(ownKit.TRL.Line.minFreq * 360.0) * 1e12;
|
||||
auto maxDelay = 160.0/(ownKit.TRL.Line.maxFreq * 360.0) * 1e12;
|
||||
if(ownKit.TRL.Line.delay < minDelay) {
|
||||
ui->TRL_line_warning->setText("Line too short, minimum required delay is "+QString::number(minDelay, 'g', 3) + "ps");
|
||||
} else if(ownKit.TRL.Line.delay > maxDelay) {
|
||||
ui->TRL_line_warning->setText("Line too long, maximum allowed delay is "+QString::number(maxDelay, 'g', 3) + "ps");
|
||||
} else {
|
||||
ui->TRL_line_warning->clear();
|
||||
}
|
||||
|
||||
if (ownKit.startDialogWithSOLT) {
|
||||
ui->tabWidget->setCurrentIndex(0);
|
||||
} else {
|
||||
ui->tabWidget->setCurrentIndex(1);
|
||||
}
|
||||
ui->manufacturer->setText(kit.manufacturer);
|
||||
ui->serialnumber->setText(kit.serialnumber);
|
||||
ui->description->setPlainText(kit.description);
|
||||
}
|
||||
|
||||
void CalkitDialog::updateStandardList()
|
||||
{
|
||||
auto row = ui->list->currentRow();
|
||||
ui->list->clear();
|
||||
for(auto s : kit.standards) {
|
||||
ui->list->addItem(s->getDescription());
|
||||
}
|
||||
if(row >= 0) {
|
||||
if(row < ui->list->count()) {
|
||||
ui->list->setCurrentRow(row);
|
||||
} else if(ui->list->count() > 0) {
|
||||
ui->list->setCurrentRow(ui->list->count() - 1);
|
||||
}
|
||||
}
|
||||
updateListEditButtons();
|
||||
}
|
||||
|
@ -22,15 +22,15 @@ public:
|
||||
|
||||
signals:
|
||||
void settingsChanged();
|
||||
private:
|
||||
private slots:
|
||||
void updateListEditButtons();
|
||||
private:
|
||||
void parseEntries();
|
||||
void updateEntries();
|
||||
void updateStandardList();
|
||||
Ui::CalkitDialog *ui;
|
||||
|
||||
bool open_ok, short_ok, load_ok, through_ok;
|
||||
|
||||
Calkit ownKit;
|
||||
Calkit &editKit;
|
||||
Calkit &kit;
|
||||
};
|
||||
|
||||
#endif // CALKITDIALOG_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,11 +2,33 @@
|
||||
#include "ui_CalStandardOpenEditDialog.h"
|
||||
#include "ui_CalStandardShortEditDialog.h"
|
||||
#include "ui_CalStandardLoadEditDialog.h"
|
||||
#include "ui_CalStandardThroughEditDialog.h"
|
||||
#include "unit.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace CalStandard;
|
||||
|
||||
Virtual *Virtual::create(Virtual::Type type)
|
||||
{
|
||||
Virtual *ret = nullptr;
|
||||
switch(type) {
|
||||
case Type::Open: ret = new Open; break;
|
||||
case Type::Short: ret = new Short; break;
|
||||
case Type::Load: ret = new Load; break;
|
||||
case Type::Through: ret = new Through; break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Virtual::Type> Virtual::availableTypes()
|
||||
{
|
||||
std::vector<Type> ret;
|
||||
for(int i=0;i<(int) Type::Last;i++) {
|
||||
ret.push_back((Type) i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString Virtual::TypeToString(Virtual::Type type)
|
||||
{
|
||||
switch(type) {
|
||||
@ -134,7 +156,7 @@ std::complex<double> Open::toS11(double freq)
|
||||
}
|
||||
}
|
||||
|
||||
void Open::edit()
|
||||
void Open::edit(std::function<void(void)> finishedCallback)
|
||||
{
|
||||
auto d = new QDialog;
|
||||
auto ui = new Ui::CalStandardOpenEditDialog;
|
||||
@ -196,6 +218,9 @@ void Open::edit()
|
||||
C1 = ui->C1->value();
|
||||
C2 = ui->C2->value();
|
||||
C3 = ui->C3->value();
|
||||
if(finishedCallback) {
|
||||
finishedCallback();
|
||||
}
|
||||
});
|
||||
|
||||
d->show();
|
||||
@ -246,7 +271,7 @@ std::complex<double> Short::toS11(double freq)
|
||||
}
|
||||
}
|
||||
|
||||
void Short::edit()
|
||||
void Short::edit(std::function<void(void)> finishedCallback)
|
||||
{
|
||||
auto d = new QDialog;
|
||||
auto ui = new Ui::CalStandardShortEditDialog;
|
||||
@ -308,6 +333,9 @@ void Short::edit()
|
||||
L1 = ui->L1->value();
|
||||
L2 = ui->L2->value();
|
||||
L3 = ui->L3->value();
|
||||
if(finishedCallback) {
|
||||
finishedCallback();
|
||||
}
|
||||
});
|
||||
|
||||
d->show();
|
||||
@ -371,7 +399,7 @@ std::complex<double> Load::toS11(double freq)
|
||||
}
|
||||
}
|
||||
|
||||
void Load::edit()
|
||||
void Load::edit(std::function<void(void)> finishedCallback)
|
||||
{
|
||||
auto d = new QDialog;
|
||||
auto ui = new Ui::CalStandardLoadEditDialog;
|
||||
@ -444,6 +472,9 @@ void Load::edit()
|
||||
Cparallel = ui->parC->value();
|
||||
Lseries = ui->serL->value();
|
||||
Cfirst = ui->C_first->isChecked();
|
||||
if(finishedCallback) {
|
||||
finishedCallback();
|
||||
}
|
||||
});
|
||||
|
||||
d->show();
|
||||
@ -513,6 +544,13 @@ void TwoPort::fromJSON(nlohmann::json j)
|
||||
}
|
||||
}
|
||||
|
||||
Through::Through()
|
||||
{
|
||||
Z0 = 50.0;
|
||||
delay = 0.0;
|
||||
loss = 0.0;
|
||||
}
|
||||
|
||||
Sparam Through::toSparam(double freq)
|
||||
{
|
||||
if(touchstone) {
|
||||
@ -529,12 +567,81 @@ Sparam Through::toSparam(double freq)
|
||||
}
|
||||
}
|
||||
|
||||
void Through::edit(std::function<void(void)> finishedCallback)
|
||||
{
|
||||
auto d = new QDialog;
|
||||
auto ui = new Ui::CalStandardThroughEditDialog;
|
||||
ui->setupUi(d);
|
||||
|
||||
ui->name->setText(name);
|
||||
ui->Z0->setUnit("Ω");
|
||||
ui->Z0->setPrecision(2);
|
||||
ui->Z0->setValue(Z0);
|
||||
ui->delay->setValue(delay);
|
||||
ui->loss->setValue(loss);
|
||||
|
||||
auto updateMeasurementLabel = [=](){
|
||||
QString label;
|
||||
if(touchstone) {
|
||||
label = QString::number(touchstone->points())+" points from "+Unit::ToString(touchstone->minFreq(), "Hz", " kMG")+" to "+Unit::ToString(touchstone->maxFreq(), "Hz", " kMG");
|
||||
} else {
|
||||
label = "No measurements stored yet";
|
||||
}
|
||||
ui->measurementLabel->setText(label);
|
||||
};
|
||||
|
||||
QObject::connect(ui->coefficients, &QRadioButton::toggled, [=](bool checked) {
|
||||
if(checked) {
|
||||
clearMeasurement();
|
||||
}
|
||||
ui->stackedWidget->setCurrentIndex(checked ? 0 : 1);
|
||||
});
|
||||
QObject::connect(ui->measurement, &QRadioButton::toggled, [=](bool checked) {
|
||||
updateMeasurementLabel();
|
||||
ui->stackedWidget->setCurrentIndex(checked ? 1 : 0);
|
||||
});
|
||||
|
||||
QObject::connect(ui->touchstoneImport, &TouchstoneImport::statusChanged, ui->updateFile, &QPushButton::setEnabled);
|
||||
|
||||
ui->touchstoneImport->setPorts(1);
|
||||
if(touchstone) {
|
||||
ui->measurement->setChecked(true);
|
||||
ui->touchstoneImport->setFile(touchstone->getFilename());
|
||||
} else {
|
||||
ui->coefficients->setChecked(true);
|
||||
}
|
||||
|
||||
QObject::connect(ui->updateFile, &QPushButton::clicked, [=](){
|
||||
setMeasurement(ui->touchstoneImport->getTouchstone(), ui->touchstoneImport->getPorts()[0]);
|
||||
updateMeasurementLabel();
|
||||
});
|
||||
|
||||
QObject::connect(d, &QDialog::accepted, [=](){
|
||||
name = ui->name->text();
|
||||
Z0 = ui->Z0->value();
|
||||
delay = ui->delay->value();
|
||||
loss = ui->loss->value();
|
||||
if(finishedCallback) {
|
||||
finishedCallback();
|
||||
}
|
||||
});
|
||||
|
||||
d->show();
|
||||
}
|
||||
|
||||
nlohmann::json Through::toJSON()
|
||||
{
|
||||
|
||||
auto j = TwoPort::toJSON();
|
||||
j["Z0"] = Z0;
|
||||
j["delay"] = delay;
|
||||
j["loss"] = loss;
|
||||
return j;
|
||||
}
|
||||
|
||||
void Through::fromJSON(nlohmann::json j)
|
||||
{
|
||||
|
||||
TwoPort::fromJSON(j);
|
||||
Z0 = j.value("Z0", 50.0);
|
||||
delay = j.value("delay", 0.0);
|
||||
loss = j.value("loss", 0.0);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Tools/parameters.h"
|
||||
|
||||
#include <complex>
|
||||
#include <functional>
|
||||
|
||||
namespace CalStandard
|
||||
{
|
||||
@ -28,6 +29,7 @@ public:
|
||||
|
||||
static Virtual* create(Type type);
|
||||
|
||||
static std::vector<Type> availableTypes();
|
||||
static QString TypeToString(Type type);
|
||||
static Type TypeFromString(QString s);
|
||||
|
||||
@ -35,7 +37,7 @@ public:
|
||||
double minFrequency() {return minFreq;}
|
||||
double maxFrequency() {return maxFreq;}
|
||||
|
||||
virtual void edit() = 0;
|
||||
virtual void edit(std::function<void(void)> finishedCallback) = 0;
|
||||
virtual QString getDescription();
|
||||
|
||||
virtual nlohmann::json toJSON() override;
|
||||
@ -74,7 +76,7 @@ public:
|
||||
Open();
|
||||
|
||||
virtual std::complex<double> toS11(double freq) override;
|
||||
virtual void edit() override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
virtual Type getType() override {return Type::Open;}
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
@ -88,7 +90,7 @@ public:
|
||||
Short();
|
||||
|
||||
virtual std::complex<double> toS11(double freq) override;
|
||||
virtual void edit() override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
virtual Type getType() override {return Type::Short;}
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
@ -102,7 +104,7 @@ public:
|
||||
Load();
|
||||
|
||||
virtual std::complex<double> toS11(double freq) override;
|
||||
virtual void edit() override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
virtual Type getType() override {return Type::Load;}
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
@ -135,6 +137,7 @@ public:
|
||||
Through();
|
||||
|
||||
virtual Sparam toSparam(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
virtual Type getType() override {return Type::Through;}
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
@ -277,6 +277,7 @@ FORMS += \
|
||||
Calibration/CalStandardLoadEditDialog.ui \
|
||||
Calibration/CalStandardOpenEditDialog.ui \
|
||||
Calibration/CalStandardShortEditDialog.ui \
|
||||
Calibration/CalStandardThroughEditDialog.ui \
|
||||
Calibration/addamplitudepointsdialog.ui \
|
||||
Calibration/amplitudecaldialog.ui \
|
||||
Calibration/automaticamplitudedialog.ui \
|
||||
|
Loading…
Reference in New Issue
Block a user