diff --git a/Documentation/UserManual/ProgrammingGuide.pdf b/Documentation/UserManual/ProgrammingGuide.pdf index f2992f9..7eff4fb 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 511fcfc..a3d502a 100644 --- a/Documentation/UserManual/ProgrammingGuide.tex +++ b/Documentation/UserManual/ProgrammingGuide.tex @@ -493,6 +493,16 @@ $$ S_{11}...S_{1n},S_{21}...S_{2n},...,S_{n1}...S_{nn} $$ \subsubsection{VNA:TRACe:PAUSED} \query{Queries whether a trace is paused}{VNA:TRACe:PAUSED?}{, either by name or by index}{TRUE or FALSE} +\subsubsection{VNA:TRACe:DEEMBedding:ACTive} +\event{Enables/disables de-embedding on a trace}{VNA:TRACe:DEEMBedding:ACTive}{, either by name or by index\\, either TRUE or FALSE} + +If no de-embedding is configured for the selected trace, enabling the de-embedding will fail. + +\query{Queries whether de-embedding is active for the selected trace}{VNA:TRACe:DEEMBedding:ACTive?}{, either by name or by index}{TRUE or FALSE} + +\subsubsection{VNA:TRACe:DEEMBedding:AVAILable} +\query{Queries whether de-embedding is available for the selected trace}{VNA:TRACe:DEEMBedding:AVAILable?}{, either by name or by index}{TRUE or FALSE} + \subsubsection{VNA:TRACe:PARAMeter} \event{Sets the measurement parameter that is stored in the trace}{VNA:TRACe:PARAMeter}{, either by name or by index\\, options are S11, S12, S21 or S22} \query{Queries the measurement parameter of a trace}{VNA:TRACe:PARAMeter?}{, either by name or by index}{S11, S12, S21 or S22} diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/tracewidget.cpp b/Software/PC_Application/LibreVNA-GUI/Traces/tracewidget.cpp index 7ad90cc..e59dd31 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/tracewidget.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Traces/tracewidget.cpp @@ -208,7 +208,7 @@ void TraceWidget::SetupSCPI() add(new SCPICommand("DATA", nullptr, [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } QString ret; if(t->size() > 0) { @@ -233,11 +233,11 @@ void TraceWidget::SetupSCPI() add(new SCPICommand("AT", nullptr, [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } double x; if(!SCPI::paramToDouble(params, 1, x)) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } else { auto d = t->interpolatedSample(x); if(std::isnan(d.x)) { @@ -250,21 +250,21 @@ void TraceWidget::SetupSCPI() add(new SCPICommand("TOUCHSTONE", nullptr, [=](QStringList params) -> QString { if(params.size() < 1) { // no traces given - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } // check number of paramaters, must be a square number int numTraces = params.size(); int ports = round(sqrt(numTraces)); if(ports * ports != numTraces) { // invalid number of traces - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } Trace* traces[numTraces]; for(int i=0;igetDataType() != Trace::DataType::Frequency) { // invalid domain - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } if(t->isReflection() != need_reflection) { // invalid measurement at this position - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } if((t->size() != npoints) || (t->minX() != f_start) || (t->maxX() != f_stop)) { // frequency points are not identical - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } } } @@ -307,21 +307,21 @@ void TraceWidget::SetupSCPI() add(new SCPICommand("MAXFrequency", nullptr, [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } return QString::number(t->maxX(), 'f', 0); })); add(new SCPICommand("MINFrequency", nullptr, [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } return QString::number(t->minX(), 'f', 0); })); add(new SCPICommand("MAXAmplitude", nullptr, [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } auto d = t->interpolatedSample(t->findExtremum(true)); return QString::number(d.x, 'f', 0)+","+createStringFromData(t, d); @@ -329,90 +329,125 @@ void TraceWidget::SetupSCPI() add(new SCPICommand("MINAmplitude", nullptr, [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } auto d = t->interpolatedSample(t->findExtremum(false)); return QString::number(d.x, 'f', 0)+","+createStringFromData(t, d); })); add(new SCPICommand("NEW", [=](QStringList params) -> QString { if(params.size() != 1) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } createCount++; auto t = new Trace(params[0], Qt::darkYellow, defaultParameter()); t->setColor(QColor::fromHsl((createCount * 50) % 360, 250, 128)); model.addTrace(t); - return ""; + return SCPI::getResultName(SCPI::Result::Empty); }, nullptr)); add(new SCPICommand("RENAME", [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } if(params.size() != 2) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } t->setName(params[1]); - return ""; + return SCPI::getResultName(SCPI::Result::Empty); }, nullptr)); add(new SCPICommand("PAUSE", [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } t->pause(); - return ""; + return SCPI::getResultName(SCPI::Result::Empty); }, nullptr)); add(new SCPICommand("RESUME", [=](QStringList params) -> QString { auto t = findTrace(params); - if(!t) { return "ERROR"; + if(!t) { + return SCPI::getResultName(SCPI::Result::Error); } t->resume(); - return ""; + return SCPI::getResultName(SCPI::Result::Empty); }, nullptr)); add(new SCPICommand("PAUSED", nullptr, [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } - return t->isPaused() ? "TRUE" : "FALSE"; + return t->isPaused() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False); })); + auto deembed = new SCPINode("DEEMBedding"); + deembed->add(new SCPICommand("ACTive", [=](QStringList params) -> QString { + Trace* t = findTrace(params); + if(!t) { + return SCPI::getResultName(SCPI::Result::Error); + } + bool activate = false; + if(!SCPI::paramToBool(params, 1, activate)) { + return SCPI::getResultName(SCPI::Result::Error); + } + if(activate) { + if(!t->deembeddingAvailable()) { + return SCPI::getResultName(SCPI::Result::Error); + } + t->setDeembeddingActive(true); + } else { + t->setDeembeddingActive(false); + } + return SCPI::getResultName(SCPI::Result::Empty); + }, [=](QStringList params) -> QString { + Trace* t = findTrace(params); + if(!t) { + return SCPI::getResultName(SCPI::Result::Error); + } + return t->isDeembeddingActive() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False); + })); + deembed->add(new SCPICommand("AVAILable", nullptr, [=](QStringList params) -> QString { + Trace* t = findTrace(params); + if(!t) { + return SCPI::getResultName(SCPI::Result::Error); + } + return t->deembeddingAvailable() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False); + })); + add(deembed); add(new SCPICommand("PARAMeter", [=](QStringList params) -> QString { auto t = findTrace(params); if(!t || params.size() < 2) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } auto newparam = params[1]; if((Trace::isVNAParameter(t->liveParameter()) && Trace::isVNAParameter(newparam)) || (Trace::isSAParameter(t->liveParameter()) && Trace::isSAParameter(newparam))) { t->fromLivedata(t->liveType(), newparam); - return ""; + return SCPI::getResultName(SCPI::Result::Empty); } else { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } }, [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } return t->liveParameter(); })); add(new SCPICommand("TYPE", [=](QStringList params) -> QString { auto t = findTrace(params); if(!t || params.size() < 2) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } auto newtype = Trace::TypeFromString(params[1]); if(newtype != Trace::LivedataType::Invalid) { t->fromLivedata(newtype, t->liveParameter()); - return ""; + return SCPI::getResultName(SCPI::Result::Empty); } else { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } }, [=](QStringList params) -> QString { auto t = findTrace(params); if(!t) { - return "ERROR"; + return SCPI::getResultName(SCPI::Result::Error); } return Trace::TypeToString(t->liveType()); })); diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembedding.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembedding.cpp index 7ac3f2d..d3133db 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembedding.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembedding.cpp @@ -69,15 +69,55 @@ void Deembedding::startMeasurementDialog(DeembeddingOption *option) } } +void Deembedding::updateSCPINames() +{ + // Need to remove all options from the subnode list first, otherwise + // name changes wouldn't work due to temporarily name collisions + for(auto &option : options) { + remove(option); + } + unsigned int i=1; + for(auto &option : options) { + option->changeName(QString::number(i)); + add(option); + } +} + Deembedding::Deembedding(TraceModel &tm) - : measuringOption(nullptr), + : SCPINode("DEEMBedding"), + measuringOption(nullptr), tm(tm), measuring(false), measurementDialog(nullptr), measurementUI(nullptr), sweepPoints(0) { - + add(new SCPICommand("NUMber", nullptr, [=](QStringList params) -> QString { + Q_UNUSED(params); + return QString::number(options.size()); + })); + add(new SCPICommand("TYPE", nullptr, [=](QStringList params) -> QString { + unsigned long long index; + if(!SCPI::paramToULongLong(params, 0, index)) { + return SCPI::getResultName(SCPI::Result::Error); + } + if(index < 1 || index > options.size()) { + return SCPI::getResultName(SCPI::Result::Error); + } + return DeembeddingOption::TypeToString(options[index]->getType()); + })); + add(new SCPICommand("NEW", [=](QStringList params) -> QString { + if(params.size() < 1) { + return SCPI::getResultName(SCPI::Result::Error); + } + auto type = DeembeddingOption::TypeFromString(params[0]); + if(type == DeembeddingOption::Type::Last) { + return SCPI::getResultName(SCPI::Result::Error); + } + auto option = DeembeddingOption::create(type); + addOption(option); + return SCPI::getResultName(SCPI::Result::Empty); + }, nullptr)); } void Deembedding::Deembed(VirtualDevice::VNAMeasurement &d) @@ -137,6 +177,7 @@ void Deembedding::removeOption(unsigned int index) delete options[index]; options.erase(options.begin() + index); } + updateSCPINames(); if(options.size() == 0) { emit allOptionsCleared(); } @@ -156,6 +197,7 @@ void Deembedding::addOption(DeembeddingOption *option) measuringOption = option; startMeasurementDialog(option); }); + updateSCPINames(); emit optionAdded(); } @@ -165,6 +207,7 @@ void Deembedding::swapOptions(unsigned int index) return; } std::swap(options[index], options[index+1]); + updateSCPINames(); } std::set Deembedding::getAffectedPorts() @@ -182,7 +225,7 @@ nlohmann::json Deembedding::toJSON() nlohmann::json list; for(auto m : options) { nlohmann::json jm; - jm["operation"] = DeembeddingOption::getName(m->getType()).toStdString(); + jm["operation"] = DeembeddingOption::TypeToString(m->getType()).toStdString(); jm["settings"] = m->toJSON(); list.push_back(jm); } @@ -204,7 +247,7 @@ void Deembedding::fromJSON(nlohmann::json j) // attempt to find the type of operation DeembeddingOption::Type type = DeembeddingOption::Type::Last; for(unsigned int i=0;i<(int) DeembeddingOption::Type::Last;i++) { - if(DeembeddingOption::getName((DeembeddingOption::Type) i) == operation) { + if(DeembeddingOption::TypeToString((DeembeddingOption::Type) i) == operation) { // found the correct operation type = (DeembeddingOption::Type) i; break; diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembedding.h b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembedding.h index 85eb0af..4d1ab0c 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembedding.h +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembedding.h @@ -4,6 +4,7 @@ #include "deembeddingoption.h" #include "savable.h" #include "Traces/tracemodel.h" +#include "scpi.h" #include #include @@ -14,7 +15,7 @@ class Ui_DeembeddingMeasurementDialog; -class Deembedding : public QObject, public Savable +class Deembedding : public QObject, public Savable, public SCPINode { Q_OBJECT public: @@ -42,6 +43,7 @@ signals: private: void measurementCompleted(); void startMeasurementDialog(DeembeddingOption *option); + void updateSCPINames(); std::vector options; DeembeddingOption *measuringOption; TraceModel &tm; diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingdialog.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingdialog.cpp index b296c96..1eb5a7d 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingdialog.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingdialog.cpp @@ -15,7 +15,7 @@ DeembeddingDialog::DeembeddingDialog(Deembedding *d, QWidget *parent) : auto addMenu = new QMenu(); for(unsigned int i=0;i<(unsigned int)DeembeddingOption::Type::Last;i++) { auto type = (DeembeddingOption::Type) i; - auto action = new QAction(DeembeddingOption::getName(type)); + auto action = new QAction(DeembeddingOption::TypeToString(type)); connect(action, &QAction::triggered, [=](){ auto option = DeembeddingOption::create(type); model.addOption(option); @@ -86,7 +86,7 @@ QVariant OptionModel::data(const QModelIndex &index, int role) const { if(index.isValid() && role == Qt::DisplayRole) { auto type = d->getOptions()[index.row()]->getType(); - return DeembeddingOption::getName(type); + return DeembeddingOption::TypeToString(type); } else { return QVariant(); } diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingoption.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingoption.cpp index 1e17300..ade07fe 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingoption.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingoption.cpp @@ -21,7 +21,7 @@ DeembeddingOption *DeembeddingOption::create(DeembeddingOption::Type type) } } -QString DeembeddingOption::getName(DeembeddingOption::Type type) +QString DeembeddingOption::TypeToString(DeembeddingOption::Type type) { switch(type) { case Type::PortExtension: @@ -36,3 +36,13 @@ QString DeembeddingOption::getName(DeembeddingOption::Type type) return ""; } } + +DeembeddingOption::Type DeembeddingOption::TypeFromString(QString string) +{ + for(unsigned int i=0;i<(int) Type::Last;i++) { + if(TypeToString((Type) i) == string) { + return (Type) i; + } + } + return Type::Last; +} diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingoption.h b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingoption.h index b72560c..5c10637 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingoption.h +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/deembeddingoption.h @@ -4,10 +4,11 @@ #include "savable.h" #include "Device/device.h" #include "Traces/tracemodel.h" +#include "scpi.h" #include -class DeembeddingOption : public QObject, public Savable +class DeembeddingOption : public QObject, public Savable, public SCPINode { Q_OBJECT public: @@ -21,7 +22,8 @@ public: }; static DeembeddingOption *create(Type type); - static QString getName(Type type); + static QString TypeToString(Type type); + static Type TypeFromString(QString string); virtual std::set getAffectedPorts() = 0; virtual void transformDatapoint(VirtualDevice::VNAMeasurement &p) = 0; @@ -35,6 +37,10 @@ signals: void deleted(DeembeddingOption *option); void triggerMeasurement(); + +protected: + DeembeddingOption(QString SCPIname) + : SCPINode(SCPIname){} }; #endif // DEEMBEDDING_H diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/impedancerenormalization.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/impedancerenormalization.cpp index fd1237d..d63253a 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/impedancerenormalization.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/impedancerenormalization.cpp @@ -9,10 +9,20 @@ using namespace std; ImpedanceRenormalization::ImpedanceRenormalization() - : DeembeddingOption(), + : DeembeddingOption("ZNORMalization"), impedance(50.0) { - + add(new SCPICommand("IMPedance", [=](QStringList params) -> QString { + double new_value; + if(!SCPI::paramToDouble(params, 0, new_value)) { + return SCPI::getResultName(SCPI::Result::Error); + } + impedance = new_value; + return SCPI::getResultName(SCPI::Result::Empty); + }, [=](QStringList params) -> QString { + Q_UNUSED(params); + return QString::number(impedance); + })); } std::set ImpedanceRenormalization::getAffectedPorts() diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.cpp index 61ebec3..f996d9a 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.cpp @@ -20,6 +20,7 @@ using namespace std; MatchingNetwork::MatchingNetwork() + : DeembeddingOption("MATCHing") { dropPending = false; dragComponent = nullptr; @@ -268,7 +269,7 @@ void MatchingNetwork::addComponent(int index, MatchingComponent *c) matching.clear(); // remove from list when the component deletes itself connect(c, &MatchingComponent::deleted, [=](){ - network.erase(remove(network.begin(), network.end(), c), network.end()); + network.erase(std::remove(network.begin(), network.end(), c), network.end()); matching.clear(); }); } @@ -325,7 +326,7 @@ bool MatchingNetwork::eventFilter(QObject *object, QEvent *event) // remove and hide component while it is being dragged graph->layout()->removeWidget(dragComponent); dragComponent->hide(); - network.erase(remove(network.begin(), network.end(), dragComponent), network.end()); + network.erase(std::remove(network.begin(), network.end(), dragComponent), network.end()); graph->update(); // network changed, need to recalculate matching diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/portextension.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/portextension.cpp index 816f41e..078f363 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/portextension.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/portextension.cpp @@ -11,7 +11,7 @@ using namespace std; PortExtension::PortExtension() - : DeembeddingOption() + : DeembeddingOption("PORTEXTension") { ext.frequency = 0; ext.loss = 0; @@ -25,6 +25,12 @@ PortExtension::PortExtension() kit = nullptr; ui = nullptr; + + addUnsignedIntParameter("PORT", port); + addDoubleParameter("DELAY", ext.delay); + addDoubleParameter("DCLOSS", ext.DCloss); + addDoubleParameter("LOSS", ext.loss); + addDoubleParameter("FREQuency", ext.frequency); } std::set PortExtension::getAffectedPorts() diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/twothru.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/twothru.cpp index b3e4a22..729ae5d 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/twothru.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/twothru.cpp @@ -11,6 +11,7 @@ using namespace std; TwoThru::TwoThru() + : DeembeddingOption("TWOTHRU") { Z0 = 50.0; port1 = 1; diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp index 8d9af79..c597722 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp @@ -1411,6 +1411,8 @@ void VNA::SetupSCPI() cal.add(new SCPICommand("BUSy", nullptr, [=](QStringList) -> QString { return CalibrationMeasurementActive() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False); })); + + SCPINode::add(&deembedding); } void VNA::ConstrainAndUpdateFrequencies() diff --git a/Software/PC_Application/LibreVNA-GUI/scpi.cpp b/Software/PC_Application/LibreVNA-GUI/scpi.cpp index a81fe99..5a00147 100644 --- a/Software/PC_Application/LibreVNA-GUI/scpi.cpp +++ b/Software/PC_Application/LibreVNA-GUI/scpi.cpp @@ -160,6 +160,54 @@ bool SCPINode::add(SCPICommand *cmd) return true; } +bool SCPINode::addDoubleParameter(QString name, double ¶m, bool gettable, bool settable) +{ + auto cmd = settable ? [&](QStringList params) -> QString { + if(SCPI::paramToDouble(params, 0, param)) { + return SCPI::getResultName(SCPI::Result::Empty); + } else { + return SCPI::getResultName(SCPI::Result::Error); + } + } : (std::function) nullptr; + auto query = settable ? [=](QStringList params) -> QString { + Q_UNUSED(params) + return QString::number(param); + } : (std::function) nullptr; + return add(new SCPICommand(name, cmd, query)); +} + +bool SCPINode::addUnsignedIntParameter(QString name, unsigned int ¶m, bool gettable, bool settable) +{ + auto cmd = settable ? [&](QStringList params) -> QString { + unsigned long long value; + if(SCPI::paramToULongLong(params, 0, value)) { + param = value; + return SCPI::getResultName(SCPI::Result::Empty); + } else { + return SCPI::getResultName(SCPI::Result::Error); + } + } : (std::function) nullptr; + auto query = settable ? [=](QStringList params) -> QString { + Q_UNUSED(params) + return QString::number(param); + } : (std::function) nullptr; + return add(new SCPICommand(name, cmd, query)); +} + +bool SCPINode::changeName(QString newname) +{ + if(newname == name) { + return true; + } + if(parent) { + if(parent->nameCollision(newname)) { + // new name would result in a collision + return false; + } + } + name = newname; +} + bool SCPINode::nameCollision(QString name) { for(auto n : subnodes) { diff --git a/Software/PC_Application/LibreVNA-GUI/scpi.h b/Software/PC_Application/LibreVNA-GUI/scpi.h index 3c15538..85d751e 100644 --- a/Software/PC_Application/LibreVNA-GUI/scpi.h +++ b/Software/PC_Application/LibreVNA-GUI/scpi.h @@ -35,11 +35,16 @@ public: bool remove(SCPINode *node); bool add(SCPICommand *cmd); + bool addDoubleParameter(QString name, double ¶m, bool gettable = true, bool settable = true); + bool addUnsignedIntParameter(QString name, unsigned int ¶m, bool gettable = true, bool settable = true); + + bool changeName(QString newname); + private: QString parse(QString cmd, SCPINode* &lastNode); bool nameCollision(QString name); void createCommandList(QString prefix, QString &list); - const QString name; + QString name; std::vector subnodes; std::vector commands; SCPINode *parent;