diff --git a/Documentation/UserManual/ProgrammingGuide.pdf b/Documentation/UserManual/ProgrammingGuide.pdf index b9a5163..6710618 100644 Binary files a/Documentation/UserManual/ProgrammingGuide.pdf and b/Documentation/UserManual/ProgrammingGuide.pdf differ diff --git a/Documentation/UserManual/ProgrammingGuide.tex b/Documentation/UserManual/ProgrammingGuide.tex index d17b05e..b4b27a1 100644 --- a/Documentation/UserManual/ProgrammingGuide.tex +++ b/Documentation/UserManual/ProgrammingGuide.tex @@ -687,6 +687,208 @@ Important points when saving/loading calibration kit files through SCPI commands \subsubsection{VNA:CALibration:KIT:LOAD} \query{Loads a calibration kit file}{VNA:CALibration:KIT:LOAD?}{}{TRUE or FALSE} +\subsubsection{Common calibration kit standards commands} +The calibration kit supports an arbitrary amount of standards. This requires a flexible SCPI API which adjusts to the currently configured standards. + +A few calibration kit standard commands are always available and they can be used to create and delete calibration standards. Every created calibration standard adds their own commands. They can be accessed by including the calibration standard number in the command (shown as ``x'' in the following commands). + +\subsubsubsection{VNA:CALibration:KIT:STAndard:CLEAR} +\event{Resets the calibration kit to default values (ideal standards)}{VNA:CALibration:KIT:STAndard:CLEAR}{None} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:NUMber} +\query{Returns the number of configured calibration standards}{VNA:CALibration:KIT:STAndard:NUMber?}{None}{} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:TYPE} +\query{Returns the type of a created calibration standard}{VNA:CALibration:KIT:STAndard:TYPE?}{ Number of calibration standard}{Type of standard, one of:\\ +\hspace{1cm}Open\\ +\hspace{1cm}Short\\ +\hspace{1cm}Load\\ +\hspace{1cm}Reflect\\ +\hspace{1cm}Through\\ +\hspace{1cm}Line\\} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:NEW} +\event{Adds a new calibration standard}{VNA:CALibration:KIT:STAndard:NEW}{ Type of calibration standard, one of:\\ +\hspace{1cm}Open\\ +\hspace{1cm}Short\\ +\hspace{1cm}Load\\ +\hspace{1cm}Reflect\\ +\hspace{1cm}Through\\ +\hspace{1cm}Line\\ + User selectable name of new standard} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:DELete} +\event{Removes a calibration standard}{VNA:CALibration:KIT:STAndard:DELete}{ Number of standard to delete} + +\subsubsection{OPEN standard commands} +The following commands are only valid for a calibration standard of type ``Open''. The ``x'' in the command names must be replaced with the calibration standard number. + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME} +\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{ User selectable name} +\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{ User selectable name} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0} +\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{ Characteristic impedance in Ohm} +\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{ Characteristic impedance in Ohm} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY} +\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{ Delay in \unit{\pico\second}} +\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{ Delay in \unit{\pico\second}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LOSS} +\event{Sets the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS}{ Loss in \unit{\giga\ohm\per\second}} +\query{Queries the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS?}{None}{ Loss in \unit{\giga\ohm\per\second}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:C0} +\event{Sets the fringing capacitance polynom term 0 of the standard}{VNA:CALibration:KIT:STAndard:x:C0}{ in \num{d-15}\unit{\farad}} +\query{Queries the fringing capacitance polynom term 0 of the standard}{VNA:CALibration:KIT:STAndard:x:C0?}{None}{ in \num{d-15}\unit{\farad}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:C1} +\event{Sets the fringing capacitance polynom term 1 of the standard}{VNA:CALibration:KIT:STAndard:x:C1}{ in \num{d-27}\unit{\farad\per\hertz}} +\query{Queries the fringing capacitance polynom term 1 of the standard}{VNA:CALibration:KIT:STAndard:x:C1?}{None}{ in \num{d-27}\unit{\farad\per\hertz}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:C2} +\event{Sets the fringing capacitance polynom term 2 of the standard}{VNA:CALibration:KIT:STAndard:x:C2}{ in \num{d-36}\unit{\farad\per\hertz\squared}} +\query{Queries the fringing capacitance polynom term 2 of the standard}{VNA:CALibration:KIT:STAndard:x:C2?}{None}{ in \num{d-36}\unit{\farad\per\hertz\squared}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:C3} +\event{Sets the fringing capacitance polynom term 3 of the standard}{VNA:CALibration:KIT:STAndard:x:C3}{ in \num{d-45}\unit{\farad\per\hertz\cubed}} +\query{Queries the fringing capacitance polynom term 3 of the standard}{VNA:CALibration:KIT:STAndard:x:C3?}{None}{ in \num{d-45}\unit{\farad\per\hertz\cubed}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE} +\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{\\ sets the port from the file which is used to define the standard, optional} + +\subsubsection{SHORT standard commands} +The following commands are only valid for a calibration standard of type ``Short''. The ``x'' in the command names must be replaced with the calibration standard number. + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME} +\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{ User selectable name} +\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{ User selectable name} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0} +\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{ Characteristic impedance in Ohm} +\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{ Characteristic impedance in Ohm} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY} +\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{ Delay in \unit{\pico\second}} +\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{ Delay in \unit{\pico\second}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LOSS} +\event{Sets the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS}{ Loss in \unit{\giga\ohm\per\second}} +\query{Queries the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS?}{None}{ Loss in \unit{\giga\ohm\per\second}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:L0} +\event{Sets the residual inductance polynom term 0 of the standard}{VNA:CALibration:KIT:STAndard:x:L0}{ in \num{d-12}\unit{\henry}} +\query{Queries the residual inductance polynom term 0 of the standard}{VNA:CALibration:KIT:STAndard:x:L0?}{None}{ in \num{d-12}\unit{\henry}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:L1} +\event{Sets the residual inductance polynom term 1 of the standard}{VNA:CALibration:KIT:STAndard:x:L1}{ in \num{d-24}\unit{\henry\per\hertz}} +\query{Queries the residual inductance polynom term 1 of the standard}{VNA:CALibration:KIT:STAndard:x:L1?}{None}{ in \num{d-24}\unit{\henry\per\hertz}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:L2} +\event{Sets the residual inductance polynom term 2 of the standard}{VNA:CALibration:KIT:STAndard:x:L2}{ in \num{d-33}\unit{\henry\per\hertz\squared}} +\query{Queries the residual inductance polynom term 2 of the standard}{VNA:CALibration:KIT:STAndard:x:L2?}{None}{ in \num{d-33}\unit{\henry\per\hertz\squared}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:L3} +\event{Sets the residual inductance polynom term 3 of the standard}{VNA:CALibration:KIT:STAndard:x:L3}{ in \num{d-42}\unit{\henry\per\hertz\cubed}} +\query{Queries the residual inductance polynom term 3 of the standard}{VNA:CALibration:KIT:STAndard:x:L3?}{None}{ in \num{d-42}\unit{\henry\per\hertz\cubed}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE} +\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{\\ sets the port from the file which is used to define the standard, optional} + +\subsubsection{LOAD standard commands} +The following commands are only valid for a calibration standard of type ``Load''. The ``x'' in the command names must be replaced with the calibration standard number. + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME} +\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{ User selectable name} +\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{ User selectable name} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:RESistance} +\event{Sets the resistance of the standard}{VNA:CALibration:KIT:STAndard:x:RESistance}{ in \unit{\ohm}} +\query{Queries the resistance of the standard}{VNA:CALibration:KIT:STAndard:x:RESistance?}{None}{ in \unit{\ohm}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0} +\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{ Characteristic impedance in Ohm} +\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{ Characteristic impedance in Ohm} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY} +\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{ Delay in \unit{\pico\second}} +\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{ Delay in \unit{\pico\second}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LOSS} +\event{Sets the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS}{ Loss in \unit{\giga\ohm\per\second}} +\query{Queries the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS?}{None}{ Loss in \unit{\giga\ohm\per\second}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:CARallel} +\event{Sets the residual capacitance polynom of the standard}{VNA:CALibration:KIT:STAndard:x:CARallel}{ in \unit{\farad}} +\query{Queries the residual capacitance of the standard}{VNA:CALibration:KIT:STAndard:x:CARallel?}{None}{ in \unit{\farad}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LSERies} +\event{Sets the residual inductance of the standard}{VNA:CALibration:KIT:STAndard:x:LSERies}{ in \unit{\henry}} +\query{Queries the residual inductance of the standard}{VNA:CALibration:KIT:STAndard:x:LSERies?}{None}{ in \unit{\henry}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:CFIRST} +\event{Sets the order of residual capacitance/inductance}{VNA:CALibration:KIT:STAndard:x:CFIRST}{TRUE or FALSE} +\query{Queries the order of residual capacitance/inductance}{VNA:CALibration:KIT:STAndard:x:CFIRST?}{None}{TRUE or FALSE} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE} +\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{\\ sets the port from the file which is used to define the standard, optional} + +\subsubsection{REFLECT standard commands} +The following commands are only valid for a calibration standard of type ``Reflect''. The ``x'' in the command names must be replaced with the calibration standard number. + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME} +\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{ User selectable name} +\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{ User selectable name} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:SHORT} +\event{Sets the type of reflection standard}{VNA:CALibration:KIT:STAndard:x:SHORT}{TRUE for short standard or FALSE for open standard} +\query{Queries the type of reflection standard}{VNA:CALibration:KIT:STAndard:x:SHORT?}{None}{TRUE for short standard or FALSE for open standard} + +\subsubsection{THROUGH standard commands} +The following commands are only valid for a calibration standard of type ``Through''. The ``x'' in the command names must be replaced with the calibration standard number. + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME} +\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{ User selectable name} +\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{ User selectable name} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0} +\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{ Characteristic impedance in Ohm} +\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{ Characteristic impedance in Ohm} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY} +\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{ Delay in \unit{\pico\second}} +\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{ Delay in \unit{\pico\second}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LOSS} +\event{Sets the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS}{ Loss in \unit{\giga\ohm\per\second}} +\query{Queries the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS?}{None}{ Loss in \unit{\giga\ohm\per\second}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE} +\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{\\ + selects the first port from the file which is used to define the standard\\ + selects the second port from the file which is used to define the standard} + +\subsubsection{LINE standard commands} +The following commands are only valid for a calibration standard of type ``Line''. The ``x'' in the command names must be replaced with the calibration standard number. + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME} +\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{ User selectable name} +\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{ User selectable name} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0} +\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{ Characteristic impedance in Ohm} +\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{ Characteristic impedance in Ohm} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY} +\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{ Delay in \unit{\pico\second}} +\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{ Delay in \unit{\pico\second}} + +\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE} +\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{\\ + selects the first port from the file which is used to define the standard\\ + selects the second port from the file which is used to define the standard} + \subsubsection{Common Deembedding Commands} The VNA supports various deembedding options which can also be configured through the SCPI API. Because the deembedding system is flexible and supports any number of deembedding options at the same time, the SCPI API is also flexible. Instead of fixed commands, the available commands change depending on the configured deembedding options. @@ -754,7 +956,8 @@ Similarly to the deembedding options, the matching network itself is also flexib \query{Queries the port at which the matching network is added}{VNA:DEEMBedding:x:PORT?}{None}{, 1...n} \subsubsubsection{VNA:DEEMBedding:x:ADD} -\event{Selects whether the network is added or removed during the deembedding}{VNA:DEEMBedding:x:ADD}{TRUE if the effect of the network should be added. FALSE if the effect of the network should be subtracted} +\event{Selects whether the network is added or removed during the deembedding}{VNA:DEEMBedding:x:ADD}{TRUE if the effect of the network should be added. FALSE if the effect of the\\ +\hspace{1cm}network should be subtracted} \query{Queries whether the network is added or removed during the deembedding}{VNA:DEEMBedding:x:ADD?}{None}{TRUE or FALSE} \subsubsubsection{VNA:DEEMBedding:x:NUMber} diff --git a/Software/PC_Application/LibreVNA-GUI/Calibration/calkit.cpp b/Software/PC_Application/LibreVNA-GUI/Calibration/calkit.cpp index 70fec89..568cebb 100644 --- a/Software/PC_Application/LibreVNA-GUI/Calibration/calkit.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Calibration/calkit.cpp @@ -16,7 +16,7 @@ using json = nlohmann::json; using namespace std; Calkit::Calkit() - : SCPINode("KIT") + : SCPINode("KIT"), scpi_std("STAndard") { // set default values filename = ""; @@ -77,6 +77,53 @@ Calkit::Calkit() return SCPI::getResultName(SCPI::Result::False); } }, false)); + scpi_std.add(new SCPICommand("CLEAR", [=](QStringList params) -> QString { + Q_UNUSED(params); + setIdealDefault(); + return SCPI::getResultName(SCPI::Result::Empty); + }, nullptr)); + scpi_std.add(new SCPICommand("NUMber", nullptr, [=](QStringList params) -> QString { + Q_UNUSED(params); + return QString::number(standards.size()); + })); + scpi_std.add(new SCPICommand("NEW", [=](QStringList params) -> QString { + if(params.size() != 2) { + return SCPI::getResultName(SCPI::Result::Error); + } + auto type = CalStandard::Virtual::TypeFromString(params[0]); + if(type == CalStandard::Virtual::Type::Last) { + return SCPI::getResultName(SCPI::Result::Error); + } + auto s = CalStandard::Virtual::create(type); + if(!s) { + return SCPI::getResultName(SCPI::Result::Error); + } + s->setName(params[1]); + addStandard(s); + return SCPI::getResultName(SCPI::Result::Empty); + }, nullptr, false)); + scpi_std.add(new SCPICommand("DELete", [=](QStringList params) -> QString { + unsigned long long index; + if(!SCPI::paramToULongLong(params, 0, index)) { + return SCPI::getResultName(SCPI::Result::Error); + } + if(index < 1 || index > standards.size()) { + return SCPI::getResultName(SCPI::Result::Error); + } + removeStandard(standards[index-1]); + return SCPI::getResultName(SCPI::Result::Empty); + }, nullptr)); + scpi_std.add(new SCPICommand("TYPE", nullptr, [=](QStringList params) -> QString { + unsigned long long index = 0; + if(!SCPI::paramToULongLong(params, 0, index)) { + return SCPI::getResultName(SCPI::Result::Error); + } + if(index < 1 || index > standards.size()) { + return SCPI::getResultName(SCPI::Result::Error); + } + return CalStandard::Virtual::TypeToString(standards[index-1]->getType()).replace(" ", "_"); + })); + add(&scpi_std); } void Calkit::toFile(QString filename) @@ -382,6 +429,7 @@ Calkit Calkit::fromFile(QString filename) file.close(); c.filename = filename; + c.updateSCPINames(); return c; } @@ -407,6 +455,21 @@ void Calkit::clearStandards() standards.clear(); } +void Calkit::updateSCPINames() +{ + // Need to remove all standards from the subnode list first, otherwise + // name changes wouldn't work due to temporarily name collisions + for(auto &s : standards) { + scpi_std.remove(s); + } + unsigned int i=1; + for(auto &s : standards) { + s->changeName(QString::number(i)); + scpi_std.add(s); + i++; + } +} + std::vector Calkit::getStandards() const { return standards; @@ -428,6 +491,14 @@ void Calkit::addStandard(CalStandard::Virtual *s) } } standards.push_back(s); + updateSCPINames(); +} + +void Calkit::removeStandard(CalStandard::Virtual *s) +{ + standards.erase(std::remove(standards.begin(), standards.end(), s), standards.end()); + delete s; + updateSCPINames(); } nlohmann::json Calkit::toJSON() @@ -464,6 +535,7 @@ void Calkit::fromJSON(nlohmann::json j) s->fromJSON(js["params"]); addStandard(s); } + updateSCPINames(); } void Calkit::setIdealDefault() @@ -475,4 +547,5 @@ void Calkit::setIdealDefault() addStandard(new CalStandard::Short("Ideal Short Standard", 50.0, 0, 0, 0, 0, 0, 0)); addStandard(new CalStandard::Load("Ideal Load Standard", 50.0, 0, 0, 50.0, 0, 0)); addStandard(new CalStandard::Through("Ideal Through Standard", 50.0, 0, 0)); + updateSCPINames(); } diff --git a/Software/PC_Application/LibreVNA-GUI/Calibration/calkit.h b/Software/PC_Application/LibreVNA-GUI/Calibration/calkit.h index 1999aee..913f47a 100644 --- a/Software/PC_Application/LibreVNA-GUI/Calibration/calkit.h +++ b/Software/PC_Application/LibreVNA-GUI/Calibration/calkit.h @@ -50,6 +50,7 @@ public: std::vector getStandards() const; void addStandard(CalStandard::Virtual* s); + void removeStandard(CalStandard::Virtual* s); virtual nlohmann::json toJSON() override; virtual void fromJSON(nlohmann::json j) override; @@ -58,8 +59,10 @@ public: private: void clearStandards(); + void updateSCPINames(); QString manufacturer, serialnumber, description; QString filename; + SCPINode scpi_std; std::vector standards; const std::vector descr = {{ diff --git a/Software/PC_Application/LibreVNA-GUI/Calibration/calkitdialog.cpp b/Software/PC_Application/LibreVNA-GUI/Calibration/calkitdialog.cpp index f3d057d..96be174 100644 --- a/Software/PC_Application/LibreVNA-GUI/Calibration/calkitdialog.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Calibration/calkitdialog.cpp @@ -27,8 +27,7 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) : connect(ui->bDelete, &QPushButton::clicked, [=](){ auto row = ui->list->currentRow(); if(row >= 0) { - delete kit.standards[row]; - kit.standards.erase(kit.standards.begin() + row); + kit.removeStandard(kit.standards[row]); updateStandardList(); } }); @@ -39,6 +38,7 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) : swap(kit.standards[row], kit.standards[row-1]); ui->list->setCurrentRow(row-1); updateStandardList(); + kit.updateSCPINames(); } }); @@ -48,6 +48,7 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) : swap(kit.standards[row], kit.standards[row+1]); ui->list->setCurrentRow(row+1); updateStandardList(); + kit.updateSCPINames(); } }); diff --git a/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.cpp b/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.cpp index eabdf4f..ffcaf8e 100644 --- a/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.cpp @@ -12,6 +12,7 @@ using namespace std; using namespace CalStandard; Virtual::Virtual(QString name) : + SCPINode(name), name(name), minFreq(std::numeric_limits::lowest()), maxFreq(std::numeric_limits::max()) @@ -60,7 +61,7 @@ QString Virtual::TypeToString(Virtual::Type type) Virtual::Type Virtual::TypeFromString(QString s) { for(int i=0;i<(int) Type::Last;i++) { - if(TypeToString((Type) i) == s) { + if(TypeToString((Type) i).compare(s, Qt::CaseInsensitive) == 0) { return (Type) i; } } @@ -101,6 +102,11 @@ void Virtual::setName(const QString &value) name = value; } +void Virtual::setupSCPI() +{ + addStringParameter("NAME", name); +} + void OnePort::setMeasurement(const Touchstone &ts, int port) { if(!touchstone) { @@ -142,10 +148,35 @@ void OnePort::fromJSON(nlohmann::json j) } } +void OnePort::setupSCPI() +{ + add(new SCPICommand("FILE", [=](QStringList params) -> QString { + if(params.size() < 1) { + return SCPI::getResultName(SCPI::Result::Error); + } + try { + auto ts = Touchstone::fromFile(params[0].toStdString()); + unsigned long long index = 0; + if(params.size() == 2) { + if(!SCPI::paramToULongLong(params, 1, index)) { + return SCPI::getResultName(SCPI::Result::Error); + } + } + setMeasurement(ts, index-1); + return SCPI::getResultName(SCPI::Result::Empty); + } catch(const std::exception& e) { + // failed to load file + return SCPI::getResultName(SCPI::Result::Error); + } + }, nullptr, false)); + Virtual::setupSCPI(); +} + Open::Open() { Z0 = 50.0; delay = loss = C0 = C1 = C2 = C3 = 0.0; + setupSCPI(); } std::complex Open::toS11(double freq) @@ -263,10 +294,23 @@ void Open::fromJSON(nlohmann::json j) C3 = j.value("C3", 0.0); } +void Open::setupSCPI() +{ + addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();}); + addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();}); + addDoubleParameter("LOSS", loss, true, true, [=](){clearMeasurement();}); + addDoubleParameter("C0", C0, true, true, [=](){clearMeasurement();}); + addDoubleParameter("C1", C1, true, true, [=](){clearMeasurement();}); + addDoubleParameter("C2", C2, true, true, [=](){clearMeasurement();}); + addDoubleParameter("C3", C3, true, true, [=](){clearMeasurement();}); + OnePort::setupSCPI(); +} + Short::Short() { Z0 = 50.0; delay = loss = L0 = L1 = L2 = L3 = 0.0; + setupSCPI(); } std::complex Short::toS11(double freq) @@ -378,12 +422,25 @@ void Short::fromJSON(nlohmann::json j) L3 = j.value("L3", 0.0); } +void Short::setupSCPI() +{ + addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();}); + addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();}); + addDoubleParameter("LOSS", loss, true, true, [=](){clearMeasurement();}); + addDoubleParameter("L0", L0, true, true, [=](){clearMeasurement();}); + addDoubleParameter("L1", L1, true, true, [=](){clearMeasurement();}); + addDoubleParameter("L2", L2, true, true, [=](){clearMeasurement();}); + addDoubleParameter("L3", L3, true, true, [=](){clearMeasurement();}); + OnePort::setupSCPI(); +} + Load::Load() { Z0 = 50.0; resistance = 50.0; delay = Cparallel = Lseries = 0; Cfirst = true; + setupSCPI(); } std::complex Load::toS11(double freq) @@ -519,6 +576,18 @@ void Load::fromJSON(nlohmann::json j) Cfirst = j.value("Cfirst", true); } +void Load::setupSCPI() +{ + addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();}); + addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();}); + addDoubleParameter("LOSS", loss, true, true, [=](){clearMeasurement();}); + addDoubleParameter("RESistance", resistance, true, true, [=](){clearMeasurement();}); + addDoubleParameter("CPARallel", Cparallel, true, true, [=](){clearMeasurement();}); + addDoubleParameter("LSERies", Lseries, true, true, [=](){clearMeasurement();}); + addBoolParameter("CFIRST", Cfirst, true, true, [=](){clearMeasurement();}); + OnePort::setupSCPI(); +} + void TwoPort::setMeasurement(const Touchstone &ts, int port1, int port2) { if(!touchstone) { @@ -560,11 +629,37 @@ void TwoPort::fromJSON(nlohmann::json j) } } +void TwoPort::setupSCPI() +{ + add(new SCPICommand("FILE", [=](QStringList params) -> QString { + if(params.size() != 3) { + return SCPI::getResultName(SCPI::Result::Error); + } + try { + auto ts = Touchstone::fromFile(params[0].toStdString()); + unsigned long long index1, index2 = 0; + if(!SCPI::paramToULongLong(params, 1, index1)) { + return SCPI::getResultName(SCPI::Result::Error); + } + if(!SCPI::paramToULongLong(params, 2, index1)) { + return SCPI::getResultName(SCPI::Result::Error); + } + setMeasurement(ts, index1-1, index2-1); + return SCPI::getResultName(SCPI::Result::Empty); + } catch(const std::exception& e) { + // failed to load file + return SCPI::getResultName(SCPI::Result::Error); + } + }, nullptr, false)); + Virtual::setupSCPI(); +} + Through::Through() { Z0 = 50.0; delay = 0.0; loss = 0.0; + setupSCPI(); } Sparam Through::toSparam(double freq) @@ -675,9 +770,18 @@ void Through::fromJSON(nlohmann::json j) loss = j.value("loss", 0.0); } +void Through::setupSCPI() +{ + addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();}); + addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();}); + addDoubleParameter("LOSS", loss, true, true, [=](){clearMeasurement();}); + TwoPort::setupSCPI(); +} + Reflect::Reflect() { isShort = true; + setupSCPI(); } std::complex Reflect::toS11(double freq) @@ -724,10 +828,17 @@ bool Reflect::getIsShort() const return isShort; } +void Reflect::setupSCPI() +{ + addBoolParameter("SHORT", isShort, true, true, [=](){clearMeasurement();}); + OnePort::setupSCPI(); +} + Line::Line() { Z0 = 50.0; setDelay(0.0); + setupSCPI(); } Sparam Line::toSparam(double freq) @@ -800,3 +911,10 @@ void Line::setDelay(double delay) minFreq = 1.0 / delay * 20 / 360; maxFreq = 1.0 / delay * 160 / 360; } + +void Line::setupSCPI() +{ + addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();}); + addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();}); + TwoPort::setupSCPI(); +} diff --git a/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.h b/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.h index 460e763..2ae3e86 100644 --- a/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.h +++ b/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.h @@ -4,6 +4,7 @@ #include "savable.h" #include "touchstone.h" #include "Tools/parameters.h" +#include "scpi.h" #include #include @@ -11,7 +12,7 @@ namespace CalStandard { -class Virtual : public QObject, public Savable +class Virtual : public QObject, public Savable, public SCPINode { Q_OBJECT public: @@ -53,6 +54,7 @@ signals: void deleted(); protected: + void setupSCPI(); QString name; double minFreq; double maxFreq; @@ -75,6 +77,7 @@ public: virtual void fromJSON(nlohmann::json j) override; protected: + void setupSCPI(); Touchstone *touchstone; }; @@ -85,7 +88,7 @@ class Open : public OnePort public: Open(); Open(QString name, double Z0, double delay, double loss, double C0, double C1, double C2, double C3) - : OnePort(name), Z0(Z0), delay(delay), loss(loss), C0(C0), C1(C1), C2(C2), C3(C3){} + : OnePort(name), Z0(Z0), delay(delay), loss(loss), C0(C0), C1(C1), C2(C2), C3(C3){setupSCPI();} virtual std::complex toS11(double freq) override; virtual void edit(std::function finishedCallback = nullptr) override; @@ -93,6 +96,7 @@ public: virtual nlohmann::json toJSON() override; virtual void fromJSON(nlohmann::json j) override; private: + void setupSCPI(); double Z0, delay, loss, C0, C1, C2, C3; }; @@ -101,7 +105,7 @@ class Short : public OnePort public: Short(); Short(QString name, double Z0, double delay, double loss, double L0, double L1, double L2, double L3) - : OnePort(name), Z0(Z0), delay(delay), loss(loss), L0(L0), L1(L1), L2(L2), L3(L3){} + : OnePort(name), Z0(Z0), delay(delay), loss(loss), L0(L0), L1(L1), L2(L2), L3(L3){setupSCPI();} virtual std::complex toS11(double freq) override; virtual void edit(std::function finishedCallback = nullptr) override; @@ -109,6 +113,7 @@ public: virtual nlohmann::json toJSON() override; virtual void fromJSON(nlohmann::json j) override; private: + void setupSCPI(); double Z0, delay, loss, L0, L1, L2, L3; }; @@ -117,7 +122,7 @@ class Load : public OnePort public: Load(); Load(QString name, double Z0, double delay, double loss, double resistance, double Cparallel, double Lseries, bool Cfirst = true) - : OnePort(name), Z0(Z0), delay(delay), loss(loss), resistance(resistance), Cparallel(Cparallel), Lseries(Lseries), Cfirst(Cfirst){} + : OnePort(name), Z0(Z0), delay(delay), loss(loss), resistance(resistance), Cparallel(Cparallel), Lseries(Lseries), Cfirst(Cfirst){setupSCPI();} virtual std::complex toS11(double freq) override; virtual void edit(std::function finishedCallback = nullptr) override; @@ -125,6 +130,7 @@ public: virtual nlohmann::json toJSON() override; virtual void fromJSON(nlohmann::json j) override; private: + void setupSCPI(); double Z0, delay, loss, resistance, Cparallel, Lseries; bool Cfirst; }; @@ -144,6 +150,7 @@ public: bool getIsShort() const; private: + void setupSCPI(); bool isShort; }; @@ -164,6 +171,7 @@ public: virtual void fromJSON(nlohmann::json j) override; protected: + void setupSCPI(); Touchstone *touchstone; }; @@ -172,7 +180,7 @@ class Through : public TwoPort public: Through(); Through(QString name, double Z0, double delay, double loss) - : TwoPort(name), Z0(Z0), delay(delay), loss(loss){} + : TwoPort(name), Z0(Z0), delay(delay), loss(loss){setupSCPI();} virtual Sparam toSparam(double freq) override; virtual void edit(std::function finishedCallback = nullptr) override; @@ -180,6 +188,7 @@ public: virtual nlohmann::json toJSON() override; virtual void fromJSON(nlohmann::json j) override; private: + void setupSCPI(); double Z0, delay, loss; }; @@ -188,7 +197,7 @@ class Line : public TwoPort public: Line(); Line(QString name, double Z0, double delay) - : TwoPort(name), Z0(Z0), delay(delay){} + : TwoPort(name), Z0(Z0), delay(delay){setupSCPI();} virtual Sparam toSparam(double freq) override; virtual void edit(std::function finishedCallback = nullptr) override; @@ -197,6 +206,7 @@ public: virtual void fromJSON(nlohmann::json j) override; private: void setDelay(double delay); + void setupSCPI(); double Z0, delay; }; diff --git a/Software/PC_Application/LibreVNA-GUI/scpi.cpp b/Software/PC_Application/LibreVNA-GUI/scpi.cpp index e2d6df1..f0a0995 100644 --- a/Software/PC_Application/LibreVNA-GUI/scpi.cpp +++ b/Software/PC_Application/LibreVNA-GUI/scpi.cpp @@ -344,6 +344,26 @@ bool SCPINode::addBoolParameter(QString name, bool ¶m, bool gettable, bool s return add(new SCPICommand(name, cmd, query)); } +bool SCPINode::addStringParameter(QString name, QString ¶m, bool gettable, bool settable, std::function setCallback) +{ + auto cmd = settable ? [¶m, setCallback](QStringList params) -> QString { + if(params.size() == 1) { + param = params[0]; + if(setCallback) { + setCallback(); + } + return SCPI::getResultName(SCPI::Result::Empty); + } else { + return SCPI::getResultName(SCPI::Result::Error); + } + } : (std::function) nullptr; + auto query = gettable ? [=](QStringList params) -> QString { + Q_UNUSED(params) + return param; + } : (std::function) nullptr; + return add(new SCPICommand(name, cmd, query)); +} + bool SCPINode::changeName(QString newname) { if(newname == name) { diff --git a/Software/PC_Application/LibreVNA-GUI/scpi.h b/Software/PC_Application/LibreVNA-GUI/scpi.h index c2bd72c..586771b 100644 --- a/Software/PC_Application/LibreVNA-GUI/scpi.h +++ b/Software/PC_Application/LibreVNA-GUI/scpi.h @@ -44,6 +44,7 @@ public: bool addDoubleParameter(QString name, double ¶m, bool gettable = true, bool settable = true, std::function setCallback = nullptr); bool addUnsignedIntParameter(QString name, unsigned int ¶m, bool gettable = true, bool settable = true, std::function setCallback = nullptr); bool addBoolParameter(QString name, bool ¶m, bool gettable = true, bool settable = true, std::function setCallback = nullptr); + bool addStringParameter(QString name, QString ¶m, bool gettable = true, bool settable = true, std::function setCallback = nullptr); bool changeName(QString newname); QString leafName() {return name.split(":").back();}