Save calibration kit as json
This commit is contained in:
parent
1dab72238b
commit
68f660ff1c
@ -4,6 +4,7 @@ HEADERS += \
|
||||
Calibration/calibrationtracedialog.h \
|
||||
Calibration/calkit.h \
|
||||
Calibration/calkitdialog.h \
|
||||
Calibration/json.hpp \
|
||||
Calibration/measurementmodel.h \
|
||||
CustomWidgets/colorpickerbutton.h \
|
||||
CustomWidgets/siunitedit.h \
|
||||
@ -33,6 +34,7 @@ HEADERS += \
|
||||
Traces/tracewidget.h \
|
||||
Traces/tracexyplot.h \
|
||||
Traces/xyplotaxisdialog.h \
|
||||
Util/qpointervariant.h \
|
||||
VNA/portextension.h \
|
||||
VNA/vna.h \
|
||||
appwindow.h \
|
||||
|
@ -4,7 +4,10 @@
|
||||
#include <iomanip>
|
||||
#include "calkitdialog.h"
|
||||
#include <math.h>
|
||||
#include "json.hpp"
|
||||
#include <QMessageBox>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using namespace std;
|
||||
|
||||
Calkit::Calkit()
|
||||
@ -14,79 +17,50 @@ Calkit::Calkit()
|
||||
ts_through(nullptr),
|
||||
ts_cached(false)
|
||||
{
|
||||
open_Z0 = 50.0;
|
||||
open_delay = 0.0;
|
||||
open_loss = 0.0;
|
||||
open_C0 = 0.0;
|
||||
open_C1 = 0.0;
|
||||
open_C2 = 0.0;
|
||||
open_C3 = 0.0;
|
||||
|
||||
short_Z0 = 50.0;
|
||||
short_delay = 0.0;
|
||||
short_loss = 0.0;
|
||||
short_L0 = 0.0;
|
||||
short_L1 = 0.0;
|
||||
short_L2 = 0.0;
|
||||
short_L3 = 0.0;
|
||||
|
||||
load_Z0 = 50.0;
|
||||
|
||||
through_Z0 = 50.0;
|
||||
through_delay = 0.0;
|
||||
through_loss = 0.0;
|
||||
|
||||
open_measurements = false;
|
||||
short_measurements = false;
|
||||
load_measurements = false;
|
||||
through_measurements = false;
|
||||
|
||||
open_file = "";
|
||||
short_file = "";
|
||||
load_file = "";
|
||||
through_file = "";
|
||||
|
||||
open_Sparam = 0;
|
||||
short_Sparam = 0;
|
||||
load_Sparam = 0;
|
||||
through_Sparam1 = 0;
|
||||
through_Sparam2 = 1;
|
||||
|
||||
TRL_through_Z0 = 50.0;
|
||||
TRL_reflection_short = true;
|
||||
TRL_line_delay = 74;
|
||||
TRL_line_maxfreq = 6000000000;
|
||||
TRL_line_minfreq = 751000000;
|
||||
// set default values
|
||||
for(auto e : json_descr) {
|
||||
e.var.setValue(e.def);
|
||||
}
|
||||
}
|
||||
|
||||
Calkit::Calkit(const Calkit &c) :
|
||||
// only copy standard definitions, leave cache state and json_descr pointers at default values
|
||||
SOLT(c.SOLT),
|
||||
TRL(c.TRL)
|
||||
{
|
||||
|
||||
}
|
||||
#include <QDebug>
|
||||
void Calkit::toFile(std::string filename)
|
||||
{
|
||||
TransformPathsToRelative(QString::fromStdString(filename));
|
||||
|
||||
json j;
|
||||
for(auto e : json_descr) {
|
||||
auto list = e.name.split("/");
|
||||
auto *json_entry = &j;
|
||||
while(list.size() > 0) {
|
||||
json_entry = &(*json_entry)[list.takeFirst().toStdString()];
|
||||
}
|
||||
// json library does not now about QVariant, handle used cases
|
||||
auto val = e.var.value();
|
||||
qDebug() << val << endl;
|
||||
switch(static_cast<QMetaType::Type>(val.type())) {
|
||||
case QMetaType::Double: *json_entry = val.toDouble(); break;
|
||||
case QMetaType::Int: *json_entry = val.toInt(); break;
|
||||
case QMetaType::Bool: *json_entry = val.toBool(); break;
|
||||
case QMetaType::QString: *json_entry = val.toString().toStdString(); break;
|
||||
default:
|
||||
throw runtime_error("Unimplemented metatype");
|
||||
}
|
||||
}
|
||||
ofstream file;
|
||||
file.open(filename);
|
||||
file << std::fixed << std::setprecision(12);
|
||||
file << open_measurements << "\n" << short_measurements << "\n" << load_measurements << "\n" << through_measurements << "\n";
|
||||
file << open_Z0 << "\n" << open_delay << "\n" << open_loss << "\n" << open_C0 << "\n" << open_C1 << "\n" << open_C2 << "\n" << open_C3 << "\n";
|
||||
file << short_Z0 << "\n" << short_delay << "\n" << short_loss << "\n" << short_L0 << "\n" << short_L1 << "\n" << short_L2 << "\n" << short_L3 << "\n";
|
||||
file << load_Z0 << "\n";
|
||||
file << through_Z0 << "\n" << through_delay << "\n" << through_loss << "\n";
|
||||
if(open_measurements) {
|
||||
file << open_file << "\n" << open_Sparam << "\n";
|
||||
}
|
||||
if(short_measurements) {
|
||||
file << short_file << "\n" << short_Sparam << "\n";
|
||||
}
|
||||
if(load_measurements) {
|
||||
file << load_file << "\n" << load_Sparam << "\n";
|
||||
}
|
||||
if(through_measurements) {
|
||||
file << through_file << "\n" << through_Sparam1 << "\n" << through_Sparam2 << "\n";
|
||||
}
|
||||
file << TRL_through_Z0 << "\n";
|
||||
file << TRL_reflection_short << "\n";
|
||||
file << TRL_line_delay << "\n";
|
||||
file << TRL_line_minfreq << "\n";
|
||||
file << TRL_line_maxfreq << "\n";
|
||||
file << setw(4) << j << endl;
|
||||
file.close();
|
||||
|
||||
TransformPathsToAbsolute(QString::fromStdString(filename));
|
||||
}
|
||||
|
||||
static QString readLine(ifstream &file) {
|
||||
@ -97,57 +71,113 @@ static QString readLine(ifstream &file) {
|
||||
|
||||
Calkit Calkit::fromFile(std::string filename)
|
||||
{
|
||||
Calkit c;
|
||||
auto c = Calkit();
|
||||
ifstream file;
|
||||
file.open(filename);
|
||||
if(!file.is_open()) {
|
||||
throw runtime_error("Unable to open file");
|
||||
}
|
||||
c.open_measurements = readLine(file).toInt();
|
||||
c.short_measurements = readLine(file).toInt();
|
||||
c.load_measurements = readLine(file).toInt();
|
||||
c.through_measurements = readLine(file).toInt();
|
||||
c.open_Z0 = readLine(file).toDouble();
|
||||
c.open_delay = readLine(file).toDouble();
|
||||
c.open_loss = readLine(file).toDouble();
|
||||
c.open_C0 = readLine(file).toDouble();
|
||||
c.open_C1 = readLine(file).toDouble();
|
||||
c.open_C2 = readLine(file).toDouble();
|
||||
c.open_C3 = readLine(file).toDouble();
|
||||
c.short_Z0 = readLine(file).toDouble();
|
||||
c.short_delay = readLine(file).toDouble();
|
||||
c.short_loss = readLine(file).toDouble();
|
||||
c.short_L0 = readLine(file).toDouble();
|
||||
c.short_L1 = readLine(file).toDouble();
|
||||
c.short_L2 = readLine(file).toDouble();
|
||||
c.short_L3 = readLine(file).toDouble();
|
||||
c.load_Z0 = readLine(file).toDouble();
|
||||
c.through_Z0 = readLine(file).toDouble();
|
||||
c.through_delay = readLine(file).toDouble();
|
||||
c.through_loss = readLine(file).toDouble();
|
||||
if(c.open_measurements) {
|
||||
c.open_file = readLine(file).toStdString();
|
||||
c.open_Sparam = readLine(file).toInt();
|
||||
|
||||
json j;
|
||||
file >> j;
|
||||
if(j.contains("SOLT")) {
|
||||
// calkit file uses json format, parse
|
||||
for(auto e : c.json_descr) {
|
||||
auto list = e.name.split("/");
|
||||
auto *json_entry = &j;
|
||||
bool entry_exists = true;
|
||||
while(list.size() > 0) {
|
||||
auto key = list.takeFirst().toStdString();
|
||||
if((*json_entry).contains(key)) {
|
||||
json_entry = &(*json_entry)[key];
|
||||
} else {
|
||||
entry_exists = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!entry_exists) {
|
||||
// missing entry in json file, nothing to do (default values already set in constructor)
|
||||
continue;
|
||||
}
|
||||
// json library does not now about QVariant, handle used cases
|
||||
auto val = e.var.value();
|
||||
switch(static_cast<QMetaType::Type>(val.type())) {
|
||||
case QMetaType::Double: e.var.setValue((*json_entry).get<double>()); break;
|
||||
case QMetaType::Int: e.var.setValue((*json_entry).get<int>()); break;
|
||||
case QMetaType::Bool: e.var.setValue((*json_entry).get<bool>()); break;
|
||||
case QMetaType::QString: {
|
||||
auto s = QString::fromStdString((*json_entry).get<string>());
|
||||
qDebug() << s;
|
||||
e.var.setValue(s);
|
||||
qDebug() << e.var.value();
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw runtime_error("Unimplemented metatype");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// legacy file format, return to beginning of file
|
||||
file.clear();
|
||||
file.seekg(0);
|
||||
c.SOLT.Open.useMeasurements = readLine(file).toInt();
|
||||
c.SOLT.Short.useMeasurements = readLine(file).toInt();
|
||||
c.SOLT.Load.useMeasurements = readLine(file).toInt();
|
||||
c.SOLT.Through.useMeasurements = readLine(file).toInt();
|
||||
c.SOLT.Open.Z0 = readLine(file).toDouble();
|
||||
c.SOLT.Open.delay = readLine(file).toDouble();
|
||||
c.SOLT.Open.loss = readLine(file).toDouble();
|
||||
c.SOLT.Open.C0 = readLine(file).toDouble();
|
||||
c.SOLT.Open.C1 = readLine(file).toDouble();
|
||||
c.SOLT.Open.C2 = readLine(file).toDouble();
|
||||
c.SOLT.Open.C3 = readLine(file).toDouble();
|
||||
c.SOLT.Short.Z0 = readLine(file).toDouble();
|
||||
c.SOLT.Short.delay = readLine(file).toDouble();
|
||||
c.SOLT.Short.loss = readLine(file).toDouble();
|
||||
c.SOLT.Short.L0 = readLine(file).toDouble();
|
||||
c.SOLT.Short.L1 = readLine(file).toDouble();
|
||||
c.SOLT.Short.L2 = readLine(file).toDouble();
|
||||
c.SOLT.Short.L3 = readLine(file).toDouble();
|
||||
c.SOLT.Load.Z0 = 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.useMeasurements) {
|
||||
c.SOLT.Open.file = readLine(file);
|
||||
c.SOLT.Open.Sparam = readLine(file).toInt();
|
||||
}
|
||||
if(c.SOLT.Short.useMeasurements) {
|
||||
c.SOLT.Short.file = readLine(file);
|
||||
c.SOLT.Short.Sparam = readLine(file).toInt();
|
||||
}
|
||||
if(c.SOLT.Load.useMeasurements) {
|
||||
c.SOLT.Load.file = readLine(file);
|
||||
c.SOLT.Load.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();
|
||||
|
||||
auto msg = new QMessageBox();
|
||||
msg->setWindowTitle("Loading calkit file");
|
||||
msg->setText("The file \"" + QString::fromStdString(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");
|
||||
msg->setStandardButtons(QMessageBox::Ok);
|
||||
msg->exec();
|
||||
}
|
||||
if(c.short_measurements) {
|
||||
c.short_file = readLine(file).toStdString();
|
||||
c.short_Sparam = readLine(file).toInt();
|
||||
}
|
||||
if(c.load_measurements) {
|
||||
c.load_file = readLine(file).toStdString();
|
||||
c.load_Sparam = readLine(file).toInt();
|
||||
}
|
||||
if(c.through_measurements) {
|
||||
c.through_file = readLine(file).toStdString();
|
||||
c.through_Sparam1 = readLine(file).toInt();
|
||||
c.through_Sparam2 = readLine(file).toInt();
|
||||
}
|
||||
c.TRL_through_Z0 = readLine(file).toDouble();
|
||||
c.TRL_reflection_short = readLine(file).toDouble();
|
||||
c.TRL_line_delay = readLine(file).toDouble();
|
||||
c.TRL_line_minfreq = readLine(file).toDouble();
|
||||
c.TRL_line_maxfreq = readLine(file).toDouble();
|
||||
file.close();
|
||||
|
||||
c.TransformPathsToAbsolute(QString::fromStdString(filename));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -157,22 +187,22 @@ void Calkit::edit()
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
Calkit::SOLT Calkit::toSOLT(double frequency)
|
||||
class Calkit::SOLT Calkit::toSOLT(double frequency)
|
||||
{
|
||||
fillTouchstoneCache();
|
||||
SOLT ref;
|
||||
if(load_measurements) {
|
||||
class SOLT ref;
|
||||
if(SOLT.Load.useMeasurements) {
|
||||
ref.Load = ts_load->interpolate(frequency).S[0];
|
||||
} else {
|
||||
auto imp_load = complex<double>(load_Z0, 0);
|
||||
auto imp_load = complex<double>(SOLT.Load.Z0, 0);
|
||||
ref.Load = (imp_load - complex<double>(50.0)) / (imp_load + complex<double>(50.0));
|
||||
}
|
||||
|
||||
if(open_measurements) {
|
||||
if(SOLT.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);
|
||||
double Cfringing = SOLT.Open.C0 * 1e-15 + SOLT.Open.C1 * 1e-27 * frequency + SOLT.Open.C2 * 1e-36 * pow(frequency, 2) + SOLT.Open.C3 * 1e-45 * pow(frequency, 3);
|
||||
// convert to impedance
|
||||
if (Cfringing == 0) {
|
||||
// special case to avoid issues with infinity
|
||||
@ -182,30 +212,30 @@ Calkit::SOLT Calkit::toSOLT(double frequency)
|
||||
ref.Open = (imp_open - complex<double>(50.0)) / (imp_open + complex<double>(50.0));
|
||||
}
|
||||
// transform the delay into a phase shift for the given frequency
|
||||
double open_phaseshift = -2 * M_PI * frequency * 2 * open_delay * 1e-12;
|
||||
double open_att_db = open_loss * 1e9 * 4.3429 * 2 * open_delay * 1e-12 / open_Z0 * sqrt(frequency / 1e9);
|
||||
double open_phaseshift = -2 * M_PI * frequency * 2 * SOLT.Open.delay * 1e-12;
|
||||
double open_att_db = SOLT.Open.loss * 1e9 * 4.3429 * 2 * SOLT.Open.delay * 1e-12 / SOLT.Open.Z0 * sqrt(frequency / 1e9);
|
||||
double open_att = pow(10.0, -open_att_db / 10.0);
|
||||
auto open_correction = polar<double>(open_att, open_phaseshift);
|
||||
ref.Open *= open_correction;
|
||||
}
|
||||
|
||||
if(short_measurements) {
|
||||
if(SOLT.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);
|
||||
double Lseries = SOLT.Short.L0 * 1e-12 + SOLT.Short.L1 * 1e-24 * frequency + SOLT.Short.L2 * 1e-33 * pow(frequency, 2) + SOLT.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));
|
||||
// transform the delay into a phase shift for the given frequency
|
||||
double short_phaseshift = -2 * M_PI * frequency * 2 * short_delay * 1e-12;
|
||||
double short_att_db = short_loss * 1e9 * 4.3429 * 2 * short_delay * 1e-12 / short_Z0 * sqrt(frequency / 1e9);;
|
||||
double short_phaseshift = -2 * M_PI * frequency * 2 * SOLT.Short.delay * 1e-12;
|
||||
double short_att_db = SOLT.Short.loss * 1e9 * 4.3429 * 2 * SOLT.Short.delay * 1e-12 / SOLT.Short.Z0 * sqrt(frequency / 1e9);;
|
||||
double short_att = pow(10.0, -short_att_db / 10.0);
|
||||
auto short_correction = polar<double>(short_att, short_phaseshift);
|
||||
ref.Short *= short_correction;
|
||||
}
|
||||
|
||||
if(through_measurements) {
|
||||
if(SOLT.Through.useMeasurements) {
|
||||
auto interp = ts_through->interpolate(frequency);
|
||||
ref.ThroughS11 = interp.S[0];
|
||||
ref.ThroughS12 = interp.S[1];
|
||||
@ -213,8 +243,8 @@ Calkit::SOLT Calkit::toSOLT(double frequency)
|
||||
ref.ThroughS22 = interp.S[3];
|
||||
} else {
|
||||
// calculate effect of through
|
||||
double through_phaseshift = -2 * M_PI * frequency * through_delay * 1e-12;
|
||||
double through_att_db = through_loss * 1e9 * 4.3429 * through_delay * 1e-12 / through_Z0 * sqrt(frequency / 1e9);;
|
||||
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
|
||||
@ -226,11 +256,11 @@ Calkit::SOLT Calkit::toSOLT(double frequency)
|
||||
return ref;
|
||||
}
|
||||
|
||||
Calkit::TRL Calkit::toTRL(double)
|
||||
class Calkit::TRL Calkit::toTRL(double)
|
||||
{
|
||||
TRL trl;
|
||||
class TRL trl;
|
||||
// reflection coefficent sign depends on whether an open or short is used
|
||||
trl.reflectionIsNegative = TRL_reflection_short;
|
||||
trl.reflectionIsNegative = TRL.Reflection.isShort;
|
||||
// assume ideal through for now
|
||||
trl.ThroughS11 = 0.0;
|
||||
trl.ThroughS12 = 1.0;
|
||||
@ -239,10 +269,10 @@ Calkit::TRL Calkit::toTRL(double)
|
||||
return trl;
|
||||
}
|
||||
|
||||
double Calkit::minFreq(bool TRL)
|
||||
double Calkit::minFreq(bool trl)
|
||||
{
|
||||
if(TRL) {
|
||||
return TRL_line_minfreq;
|
||||
if(trl) {
|
||||
return TRL.Line.minFreq;
|
||||
} else {
|
||||
fillTouchstoneCache();
|
||||
double min = 0;
|
||||
@ -261,10 +291,10 @@ double Calkit::minFreq(bool TRL)
|
||||
}
|
||||
}
|
||||
|
||||
double Calkit::maxFreq(bool TRL)
|
||||
double Calkit::maxFreq(bool trl)
|
||||
{
|
||||
if(TRL) {
|
||||
return TRL_line_maxfreq;
|
||||
if(trl) {
|
||||
return TRL.Line.maxFreq;
|
||||
} else {
|
||||
fillTouchstoneCache();
|
||||
double max = std::numeric_limits<double>::max();
|
||||
@ -285,7 +315,34 @@ double Calkit::maxFreq(bool TRL)
|
||||
|
||||
bool Calkit::isTRLReflectionShort() const
|
||||
{
|
||||
return TRL_reflection_short;
|
||||
return TRL.Reflection.isShort;
|
||||
}
|
||||
|
||||
void Calkit::TransformPathsToRelative(QFileInfo d)
|
||||
{
|
||||
vector<QString*> filenames = {&SOLT.Short.file, &SOLT.Open.file, &SOLT.Load.file, &SOLT.Through.file};
|
||||
for(auto f : filenames) {
|
||||
if(f->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if(QFileInfo(*f).isAbsolute()) {
|
||||
*f = d.dir().relativeFilePath(*f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Calkit::TransformPathsToAbsolute(QFileInfo d)
|
||||
{
|
||||
vector<QString*> filenames = {&SOLT.Short.file, &SOLT.Open.file, &SOLT.Load.file, &SOLT.Through.file};
|
||||
for(auto f : filenames) {
|
||||
if(f->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if(QFileInfo(*f).isRelative()) {
|
||||
auto absDir = QDir(d.dir().path() + "/" + *f);
|
||||
*f = absDir.absolutePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Calkit::clearTouchstoneCache()
|
||||
@ -306,25 +363,25 @@ void Calkit::fillTouchstoneCache()
|
||||
if(ts_cached) {
|
||||
return;
|
||||
}
|
||||
if(open_measurements) {
|
||||
if(SOLT.Open.useMeasurements) {
|
||||
ts_open = new Touchstone(1);
|
||||
*ts_open = Touchstone::fromFile(open_file);
|
||||
ts_open->reduceTo1Port(open_Sparam);
|
||||
*ts_open = Touchstone::fromFile(SOLT.Open.file.toStdString());
|
||||
ts_open->reduceTo1Port(SOLT.Open.Sparam);
|
||||
}
|
||||
if(short_measurements) {
|
||||
if(SOLT.Short.useMeasurements) {
|
||||
ts_short = new Touchstone(1);
|
||||
*ts_short = Touchstone::fromFile(short_file);
|
||||
ts_open->reduceTo1Port(short_Sparam);
|
||||
*ts_short = Touchstone::fromFile(SOLT.Short.file.toStdString());
|
||||
ts_open->reduceTo1Port(SOLT.Short.Sparam);
|
||||
}
|
||||
if(load_measurements) {
|
||||
if(SOLT.Load.useMeasurements) {
|
||||
ts_load = new Touchstone(1);
|
||||
*ts_load = Touchstone::fromFile(load_file);
|
||||
ts_open->reduceTo1Port(load_Sparam);
|
||||
*ts_load = Touchstone::fromFile(SOLT.Load.file.toStdString());
|
||||
ts_open->reduceTo1Port(SOLT.Load.Sparam);
|
||||
}
|
||||
if(through_measurements) {
|
||||
if(SOLT.Through.useMeasurements) {
|
||||
ts_through = new Touchstone(2);
|
||||
*ts_through = Touchstone::fromFile(through_file);
|
||||
ts_through->reduceTo2Port(through_Sparam1, through_Sparam2);
|
||||
*ts_through = Touchstone::fromFile(SOLT.Through.file.toStdString());
|
||||
ts_through->reduceTo2Port(SOLT.Through.Sparam1, SOLT.Through.Sparam2);
|
||||
}
|
||||
ts_cached = true;
|
||||
}
|
||||
|
@ -4,12 +4,21 @@
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include "touchstone.h"
|
||||
#include "Util/qpointervariant.h"
|
||||
#include <QDir>
|
||||
|
||||
class Calkit
|
||||
{
|
||||
friend class CalkitDialog;
|
||||
public:
|
||||
Calkit();
|
||||
Calkit(const Calkit& c);
|
||||
Calkit& operator=(const Calkit& other)
|
||||
{
|
||||
this->SOLT = other.SOLT;
|
||||
this->TRL = other.TRL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
class SOLT {
|
||||
public:
|
||||
@ -30,36 +39,106 @@ public:
|
||||
void edit();
|
||||
SOLT toSOLT(double frequency);
|
||||
TRL toTRL(double frequency);
|
||||
double minFreq(bool TRL = false);
|
||||
double maxFreq(bool TRL = false);
|
||||
double minFreq(bool trl = false);
|
||||
double maxFreq(bool trl = false);
|
||||
bool isTRLReflectionShort() const;
|
||||
|
||||
private:
|
||||
void TransformPathsToRelative(QFileInfo d);
|
||||
void TransformPathsToAbsolute(QFileInfo d);
|
||||
// SOLT standard definitions
|
||||
double open_Z0, open_delay, open_loss, open_C0, open_C1, open_C2, open_C3;
|
||||
double short_Z0, short_delay, short_loss, short_L0, short_L1, short_L2, short_L3;
|
||||
double load_Z0;
|
||||
double through_Z0, through_delay, through_loss;
|
||||
|
||||
// coefficients/measurement file switch
|
||||
bool open_measurements;
|
||||
bool short_measurements;
|
||||
bool load_measurements;
|
||||
bool through_measurements;
|
||||
|
||||
// TRL standard definitions
|
||||
double TRL_through_Z0;
|
||||
bool TRL_reflection_short;
|
||||
double TRL_line_delay;
|
||||
double TRL_line_minfreq;
|
||||
double TRL_line_maxfreq;
|
||||
|
||||
std::string open_file, short_file, load_file, through_file;
|
||||
int open_Sparam, short_Sparam, load_Sparam, through_Sparam1, through_Sparam2;
|
||||
struct {
|
||||
struct {
|
||||
double Z0, delay, loss, C0, C1, C2, C3;
|
||||
QString file;
|
||||
bool useMeasurements;
|
||||
int Sparam;
|
||||
} Open;
|
||||
struct {
|
||||
double Z0, delay, loss, L0, L1, L2, L3;
|
||||
QString file;
|
||||
bool useMeasurements;
|
||||
int Sparam;
|
||||
} Short;
|
||||
struct {
|
||||
double Z0;
|
||||
QString file;
|
||||
bool useMeasurements;
|
||||
int Sparam;
|
||||
} Load;
|
||||
struct {
|
||||
double Z0, delay, loss;
|
||||
QString file;
|
||||
bool useMeasurements;
|
||||
int Sparam1, Sparam2;
|
||||
} Through;
|
||||
} SOLT;
|
||||
struct {
|
||||
struct {
|
||||
double Z0;
|
||||
} Through;
|
||||
struct {
|
||||
bool isShort;
|
||||
} Reflection;
|
||||
struct {
|
||||
double delay, minFreq, maxFreq;
|
||||
} Line;
|
||||
} TRL;
|
||||
bool startDialogWithSOLT;
|
||||
|
||||
Touchstone *ts_open, *ts_short, *ts_load, *ts_through;
|
||||
bool ts_cached;
|
||||
|
||||
using JSONDescription = struct _jsondescr {
|
||||
QPointerVariant var;
|
||||
QString name;
|
||||
QVariant def;
|
||||
};
|
||||
const std::array<JSONDescription, 37> json_descr = {{
|
||||
{&SOLT.Open.Z0, "SOLT/Open/Param/Z0", 50.0},
|
||||
{&SOLT.Open.delay, "SOLT/Open/Param/Delay", 0.0},
|
||||
{&SOLT.Open.loss, "SOLT/Open/Param/Loss", 0.0},
|
||||
{&SOLT.Open.C0, "SOLT/Open/Param/C0", 0.0},
|
||||
{&SOLT.Open.C1, "SOLT/Open/Param/C1", 0.0},
|
||||
{&SOLT.Open.C2, "SOLT/Open/Param/C2", 0.0},
|
||||
{&SOLT.Open.C3, "SOLT/Open/Param/C3", 0.0},
|
||||
{&SOLT.Open.useMeasurements, "SOLT/Open/Measurements/Use", false},
|
||||
{&SOLT.Open.file, "SOLT/Open/Measurements/File", ""},
|
||||
{&SOLT.Open.Sparam, "SOLT/Open/Measurements/Port", 0},
|
||||
|
||||
{&SOLT.Short.Z0, "SOLT/Short/Param/Z0", 50.0},
|
||||
{&SOLT.Short.delay, "SOLT/Short/Param/Delay", 0.0},
|
||||
{&SOLT.Short.loss, "SOLT/Short/Param/Loss", 0.0},
|
||||
{&SOLT.Short.L0, "SOLT/Short/Param/L0", 0.0},
|
||||
{&SOLT.Short.L1, "SOLT/Short/Param/L1", 0.0},
|
||||
{&SOLT.Short.L2, "SOLT/Short/Param/L2", 0.0},
|
||||
{&SOLT.Short.L3, "SOLT/Short/Param/L3", 0.0},
|
||||
{&SOLT.Short.useMeasurements, "SOLT/Short/Measurements/Use", false},
|
||||
{&SOLT.Short.file, "SOLT/Short/Measurements/File", ""},
|
||||
{&SOLT.Short.Sparam, "SOLT/Short/Measurements/Port", 0},
|
||||
|
||||
{&SOLT.Load.Z0, "SOLT/Load/Param/Z0", 50.0},
|
||||
{&SOLT.Load.useMeasurements, "SOLT/Load/Measurements/Use", false},
|
||||
{&SOLT.Load.file, "SOLT/Load/Measurements/File", ""},
|
||||
{&SOLT.Load.Sparam, "SOLT/Load/Measurements/Port", 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},
|
||||
|
||||
{&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();
|
||||
};
|
||||
|
@ -50,15 +50,15 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
||||
updateEntries();
|
||||
|
||||
connect(ui->TRL_line_min, &SIUnitEdit::valueChanged, [=](double newval){
|
||||
ownKit.TRL_line_minfreq = newval;
|
||||
ownKit.TRL.Line.minFreq = newval;
|
||||
updateEntries();
|
||||
});
|
||||
connect(ui->TRL_line_max, &SIUnitEdit::valueChanged, [=](double newval){
|
||||
ownKit.TRL_line_maxfreq = newval;
|
||||
ownKit.TRL.Line.maxFreq = newval;
|
||||
updateEntries();
|
||||
});
|
||||
connect(ui->TRL_line_delay, &QLineEdit::editingFinished, [=](){
|
||||
ownKit.TRL_line_delay = ui->TRL_line_delay->text().toDouble();
|
||||
ownKit.TRL.Line.delay = ui->TRL_line_delay->text().toDouble();
|
||||
updateEntries();
|
||||
});
|
||||
|
||||
@ -137,136 +137,144 @@ CalkitDialog::~CalkitDialog()
|
||||
void CalkitDialog::parseEntries()
|
||||
{
|
||||
// type
|
||||
ownKit.open_measurements = ui->open_measurement->isChecked();
|
||||
ownKit.short_measurements = ui->short_measurement->isChecked();
|
||||
ownKit.load_measurements = ui->load_measurement->isChecked();
|
||||
ownKit.through_measurements = ui->through_measurement->isChecked();
|
||||
ownKit.SOLT.Open.useMeasurements = ui->open_measurement->isChecked();
|
||||
ownKit.SOLT.Short.useMeasurements = ui->short_measurement->isChecked();
|
||||
ownKit.SOLT.Load.useMeasurements = ui->load_measurement->isChecked();
|
||||
ownKit.SOLT.Through.useMeasurements = ui->through_measurement->isChecked();
|
||||
|
||||
// coefficients
|
||||
ownKit.open_Z0 = ui->open_Z0->text().toDouble();
|
||||
ownKit.open_delay = ui->open_delay->text().toDouble();
|
||||
ownKit.open_loss = ui->open_loss->text().toDouble();
|
||||
ownKit.open_C0 = ui->open_C0->text().toDouble();
|
||||
ownKit.open_C1 = ui->open_C1->text().toDouble();
|
||||
ownKit.open_C2 = ui->open_C2->text().toDouble();
|
||||
ownKit.open_C3 = ui->open_C3->text().toDouble();
|
||||
ownKit.SOLT.Open.Z0 = ui->open_Z0->text().toDouble();
|
||||
ownKit.SOLT.Open.delay = ui->open_delay->text().toDouble();
|
||||
ownKit.SOLT.Open.loss = ui->open_loss->text().toDouble();
|
||||
ownKit.SOLT.Open.C0 = ui->open_C0->text().toDouble();
|
||||
ownKit.SOLT.Open.C1 = ui->open_C1->text().toDouble();
|
||||
ownKit.SOLT.Open.C2 = ui->open_C2->text().toDouble();
|
||||
ownKit.SOLT.Open.C3 = ui->open_C3->text().toDouble();
|
||||
|
||||
ownKit.short_Z0 = ui->short_Z0->text().toDouble();
|
||||
ownKit.short_delay = ui->short_delay->text().toDouble();
|
||||
ownKit.short_loss = ui->short_loss->text().toDouble();
|
||||
ownKit.short_L0 = ui->short_L0->text().toDouble();
|
||||
ownKit.short_L1 = ui->short_L1->text().toDouble();
|
||||
ownKit.short_L2 = ui->short_L2->text().toDouble();
|
||||
ownKit.short_L3 = ui->short_L3->text().toDouble();
|
||||
ownKit.SOLT.Short.Z0 = ui->short_Z0->text().toDouble();
|
||||
ownKit.SOLT.Short.delay = ui->short_delay->text().toDouble();
|
||||
ownKit.SOLT.Short.loss = ui->short_loss->text().toDouble();
|
||||
ownKit.SOLT.Short.L0 = ui->short_L0->text().toDouble();
|
||||
ownKit.SOLT.Short.L1 = ui->short_L1->text().toDouble();
|
||||
ownKit.SOLT.Short.L2 = ui->short_L2->text().toDouble();
|
||||
ownKit.SOLT.Short.L3 = ui->short_L3->text().toDouble();
|
||||
|
||||
ownKit.load_Z0 = ui->load_Z0->text().toDouble();
|
||||
ownKit.SOLT.Load.Z0 = ui->load_Z0->text().toDouble();
|
||||
|
||||
ownKit.through_Z0 = ui->through_Z0->text().toDouble();
|
||||
ownKit.through_delay = ui->through_delay->text().toDouble();
|
||||
ownKit.through_loss = ui->through_loss->text().toDouble();
|
||||
ownKit.SOLT.Through.Z0 = ui->through_Z0->text().toDouble();
|
||||
ownKit.SOLT.Through.delay = ui->through_delay->text().toDouble();
|
||||
ownKit.SOLT.Through.loss = ui->through_loss->text().toDouble();
|
||||
|
||||
// file
|
||||
ownKit.open_file = ui->open_touchstone->getFilename().toStdString();
|
||||
ownKit.short_file = ui->short_touchstone->getFilename().toStdString();
|
||||
ownKit.load_file = ui->load_touchstone->getFilename().toStdString();
|
||||
ownKit.through_file = ui->through_touchstone->getFilename().toStdString();
|
||||
ownKit.SOLT.Open.file = ui->open_touchstone->getFilename();
|
||||
ownKit.SOLT.Short.file = ui->short_touchstone->getFilename();
|
||||
ownKit.SOLT.Load.file = ui->load_touchstone->getFilename();
|
||||
ownKit.SOLT.Through.file = ui->through_touchstone->getFilename();
|
||||
|
||||
ownKit.open_Sparam = ui->open_touchstone->getPorts()[0];
|
||||
ownKit.short_Sparam = ui->short_touchstone->getPorts()[0];
|
||||
ownKit.load_Sparam = ui->load_touchstone->getPorts()[0];
|
||||
ownKit.through_Sparam1 = ui->through_touchstone->getPorts()[0];
|
||||
ownKit.through_Sparam2 = ui->through_touchstone->getPorts()[1];
|
||||
ownKit.SOLT.Open.Sparam = ui->open_touchstone->getPorts()[0];
|
||||
ownKit.SOLT.Short.Sparam = ui->short_touchstone->getPorts()[0];
|
||||
ownKit.SOLT.Load.Sparam = ui->load_touchstone->getPorts()[0];
|
||||
ownKit.SOLT.Through.Sparam1 = ui->through_touchstone->getPorts()[0];
|
||||
ownKit.SOLT.Through.Sparam2 = ui->through_touchstone->getPorts()[1];
|
||||
|
||||
// TRL
|
||||
ownKit.TRL_through_Z0 = ui->TRL_through_Z0->text().toDouble();
|
||||
ownKit.TRL_reflection_short = ui->TRL_R_short->isChecked();
|
||||
ownKit.TRL_line_delay = ui->TRL_line_delay->text().toDouble();
|
||||
ownKit.TRL_line_minfreq = ui->TRL_line_min->value();
|
||||
ownKit.TRL_line_maxfreq = ui->TRL_line_max->value();
|
||||
ownKit.TRL.Through.Z0 = ui->TRL_through_Z0->text().toDouble();
|
||||
ownKit.TRL.Reflection.isShort = ui->TRL_R_short->isChecked();
|
||||
ownKit.TRL.Line.delay = ui->TRL_line_delay->text().toDouble();
|
||||
ownKit.TRL.Line.minFreq = ui->TRL_line_min->value();
|
||||
ownKit.TRL.Line.maxFreq = ui->TRL_line_max->value();
|
||||
|
||||
ownKit.startDialogWithSOLT = ui->tabWidget->currentIndex() == 0;
|
||||
}
|
||||
|
||||
void CalkitDialog::updateEntries()
|
||||
{
|
||||
// Coefficients
|
||||
ui->open_Z0->setText(QString::number(ownKit.open_Z0));
|
||||
ui->open_delay->setText(QString::number(ownKit.open_delay));
|
||||
ui->open_loss->setText(QString::number(ownKit.open_loss));
|
||||
ui->open_C0->setText(QString::number(ownKit.open_C0));
|
||||
ui->open_C1->setText(QString::number(ownKit.open_C1));
|
||||
ui->open_C2->setText(QString::number(ownKit.open_C2));
|
||||
ui->open_C3->setText(QString::number(ownKit.open_C3));
|
||||
ui->open_Z0->setText(QString::number(ownKit.SOLT.Open.Z0));
|
||||
ui->open_delay->setText(QString::number(ownKit.SOLT.Open.delay));
|
||||
ui->open_loss->setText(QString::number(ownKit.SOLT.Open.loss));
|
||||
ui->open_C0->setText(QString::number(ownKit.SOLT.Open.C0));
|
||||
ui->open_C1->setText(QString::number(ownKit.SOLT.Open.C1));
|
||||
ui->open_C2->setText(QString::number(ownKit.SOLT.Open.C2));
|
||||
ui->open_C3->setText(QString::number(ownKit.SOLT.Open.C3));
|
||||
|
||||
ui->short_Z0->setText(QString::number(ownKit.short_Z0));
|
||||
ui->short_delay->setText(QString::number(ownKit.short_delay));
|
||||
ui->short_loss->setText(QString::number(ownKit.short_loss));
|
||||
ui->short_L0->setText(QString::number(ownKit.short_L0));
|
||||
ui->short_L1->setText(QString::number(ownKit.short_L1));
|
||||
ui->short_L2->setText(QString::number(ownKit.short_L2));
|
||||
ui->short_L3->setText(QString::number(ownKit.short_L3));
|
||||
ui->short_Z0->setText(QString::number(ownKit.SOLT.Short.Z0));
|
||||
ui->short_delay->setText(QString::number(ownKit.SOLT.Short.delay));
|
||||
ui->short_loss->setText(QString::number(ownKit.SOLT.Short.loss));
|
||||
ui->short_L0->setText(QString::number(ownKit.SOLT.Short.L0));
|
||||
ui->short_L1->setText(QString::number(ownKit.SOLT.Short.L1));
|
||||
ui->short_L2->setText(QString::number(ownKit.SOLT.Short.L2));
|
||||
ui->short_L3->setText(QString::number(ownKit.SOLT.Short.L3));
|
||||
|
||||
ui->load_Z0->setText(QString::number(ownKit.load_Z0));
|
||||
ui->load_Z0->setText(QString::number(ownKit.SOLT.Load.Z0));
|
||||
|
||||
ui->through_Z0->setText(QString::number(ownKit.through_Z0));
|
||||
ui->through_delay->setText(QString::number(ownKit.through_delay));
|
||||
ui->through_loss->setText(QString::number(ownKit.through_loss));
|
||||
ui->through_Z0->setText(QString::number(ownKit.SOLT.Through.Z0));
|
||||
ui->through_delay->setText(QString::number(ownKit.SOLT.Through.delay));
|
||||
ui->through_loss->setText(QString::number(ownKit.SOLT.Through.loss));
|
||||
|
||||
// Measurements
|
||||
ui->open_touchstone->setFile(QString::fromStdString(ownKit.open_file));
|
||||
ui->open_touchstone->selectPort(0, ownKit.open_Sparam);
|
||||
ui->open_touchstone->setFile(ownKit.SOLT.Open.file);
|
||||
ui->open_touchstone->selectPort(0, ownKit.SOLT.Open.Sparam);
|
||||
|
||||
ui->short_touchstone->setFile(QString::fromStdString(ownKit.short_file));
|
||||
ui->short_touchstone->selectPort(0, ownKit.short_Sparam);
|
||||
ui->short_touchstone->setFile(ownKit.SOLT.Short.file);
|
||||
ui->short_touchstone->selectPort(0, ownKit.SOLT.Short.Sparam);
|
||||
|
||||
ui->load_touchstone->setFile(QString::fromStdString(ownKit.load_file));
|
||||
ui->load_touchstone->selectPort(0, ownKit.load_Sparam);
|
||||
ui->load_touchstone->setFile(ownKit.SOLT.Load.file);
|
||||
ui->load_touchstone->selectPort(0, ownKit.SOLT.Load.Sparam);
|
||||
|
||||
ui->through_touchstone->setFile(QString::fromStdString(ownKit.through_file));
|
||||
ui->through_touchstone->selectPort(0, ownKit.through_Sparam1);
|
||||
ui->through_touchstone->selectPort(1, ownKit.through_Sparam2);
|
||||
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.open_measurements) {
|
||||
if (ownKit.SOLT.Open.useMeasurements) {
|
||||
ui->open_measurement->click();
|
||||
} else {
|
||||
ui->open_coefficients->click();
|
||||
}
|
||||
|
||||
if (ownKit.short_measurements) {
|
||||
if (ownKit.SOLT.Short.useMeasurements) {
|
||||
ui->short_measurement->click();
|
||||
} else {
|
||||
ui->short_coefficients->click();
|
||||
}
|
||||
|
||||
if (ownKit.load_measurements) {
|
||||
if (ownKit.SOLT.Load.useMeasurements) {
|
||||
ui->load_measurement->click();
|
||||
} else {
|
||||
ui->load_coefficients->click();
|
||||
}
|
||||
|
||||
if (ownKit.through_measurements) {
|
||||
if (ownKit.SOLT.Through.useMeasurements) {
|
||||
ui->through_measurement->click();
|
||||
} else {
|
||||
ui->through_coefficients->click();
|
||||
}
|
||||
|
||||
// TRL
|
||||
ui->TRL_through_Z0->setText(QString::number(ownKit.TRL_through_Z0));
|
||||
if(ownKit.TRL_reflection_short) {
|
||||
ui->TRL_through_Z0->setText(QString::number(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->setText(QString::number(ownKit.TRL_line_delay));
|
||||
ui->TRL_line_min->setValueQuiet(ownKit.TRL_line_minfreq);
|
||||
ui->TRL_line_max->setValueQuiet(ownKit.TRL_line_maxfreq);
|
||||
ui->TRL_line_delay->setText(QString::number(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) {
|
||||
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) {
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
25533
Software/PC_Application/Calibration/json.hpp
Normal file
25533
Software/PC_Application/Calibration/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
29
Software/PC_Application/Util/qpointervariant.h
Normal file
29
Software/PC_Application/Util/qpointervariant.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef QPOINTERVARIANT_H
|
||||
#define QPOINTERVARIANT_H
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
class QPointerVariant {
|
||||
public:
|
||||
template <typename T> QPointerVariant(T *ptr)
|
||||
: ptr(static_cast<void*>(ptr)),
|
||||
variant(QVariant(*ptr)){};
|
||||
void setValue(const QVariant &value) {
|
||||
auto destType = variant.type();
|
||||
if(!value.canConvert(destType)) {
|
||||
throw std::runtime_error("Unable to convert QVariant to requested type");
|
||||
}
|
||||
variant = value;
|
||||
variant.convert(destType);
|
||||
QMetaType mt(destType);
|
||||
mt.construct(ptr, variant.constData());
|
||||
}
|
||||
QVariant value() {
|
||||
return QVariant(variant.type(), ptr);
|
||||
}
|
||||
private:
|
||||
void *ptr;
|
||||
QVariant variant;
|
||||
};
|
||||
|
||||
#endif // QPOINTERVARIANT_H
|
@ -4,29 +4,7 @@
|
||||
#include <QDialog>
|
||||
#include <QVariant>
|
||||
#include <exception>
|
||||
|
||||
class QPointerVariant {
|
||||
public:
|
||||
template <typename T> QPointerVariant(T *ptr)
|
||||
: ptr(static_cast<void*>(ptr)),
|
||||
variant(QVariant(*ptr)){};
|
||||
void setValue(const QVariant &value) {
|
||||
auto destType = variant.type();
|
||||
if(!value.canConvert(destType)) {
|
||||
throw std::runtime_error("Unable to convert QVariant to requested type");
|
||||
}
|
||||
variant = value;
|
||||
variant.convert(destType);
|
||||
QMetaType mt(destType);
|
||||
mt.construct(ptr, variant.constData());
|
||||
}
|
||||
QVariant value() {
|
||||
return QVariant(variant.type(), ptr);
|
||||
}
|
||||
private:
|
||||
void *ptr;
|
||||
QVariant variant;
|
||||
};
|
||||
#include "Util/qpointervariant.h"
|
||||
|
||||
class Preferences {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user