WIP: SCPI commands for de-embedding

This commit is contained in:
Jan Käberich 2022-12-12 17:39:17 +01:00
parent fa8f49086c
commit d674d05083
15 changed files with 227 additions and 48 deletions

View File

@ -493,6 +493,16 @@ $$ S_{11}...S_{1n},S_{21}...S_{2n},...,S_{n1}...S_{nn} $$
\subsubsection{VNA:TRACe:PAUSED} \subsubsection{VNA:TRACe:PAUSED}
\query{Queries whether a trace is paused}{VNA:TRACe:PAUSED?}{<trace>, either by name or by index}{TRUE or FALSE} \query{Queries whether a trace is paused}{VNA:TRACe:PAUSED?}{<trace>, 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}{<trace>, either by name or by index\\<enable>, 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?}{<trace>, 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?}{<trace>, either by name or by index}{TRUE or FALSE}
\subsubsection{VNA:TRACe:PARAMeter} \subsubsection{VNA:TRACe:PARAMeter}
\event{Sets the measurement parameter that is stored in the trace}{VNA:TRACe:PARAMeter}{<trace>, either by name or by index\\<parameter>, options are S11, S12, S21 or S22} \event{Sets the measurement parameter that is stored in the trace}{VNA:TRACe:PARAMeter}{<trace>, either by name or by index\\<parameter>, options are S11, S12, S21 or S22}
\query{Queries the measurement parameter of a trace}{VNA:TRACe:PARAMeter?}{<trace>, either by name or by index}{S11, S12, S21 or S22} \query{Queries the measurement parameter of a trace}{VNA:TRACe:PARAMeter?}{<trace>, either by name or by index}{S11, S12, S21 or S22}

View File

@ -208,7 +208,7 @@ void TraceWidget::SetupSCPI()
add(new SCPICommand("DATA", nullptr, [=](QStringList params) -> QString { add(new SCPICommand("DATA", nullptr, [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
QString ret; QString ret;
if(t->size() > 0) { if(t->size() > 0) {
@ -233,11 +233,11 @@ void TraceWidget::SetupSCPI()
add(new SCPICommand("AT", nullptr, [=](QStringList params) -> QString { add(new SCPICommand("AT", nullptr, [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
double x; double x;
if(!SCPI::paramToDouble(params, 1, x)) { if(!SCPI::paramToDouble(params, 1, x)) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} else { } else {
auto d = t->interpolatedSample(x); auto d = t->interpolatedSample(x);
if(std::isnan(d.x)) { if(std::isnan(d.x)) {
@ -250,21 +250,21 @@ void TraceWidget::SetupSCPI()
add(new SCPICommand("TOUCHSTONE", nullptr, [=](QStringList params) -> QString { add(new SCPICommand("TOUCHSTONE", nullptr, [=](QStringList params) -> QString {
if(params.size() < 1) { if(params.size() < 1) {
// no traces given // no traces given
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
// check number of paramaters, must be a square number // check number of paramaters, must be a square number
int numTraces = params.size(); int numTraces = params.size();
int ports = round(sqrt(numTraces)); int ports = round(sqrt(numTraces));
if(ports * ports != numTraces) { if(ports * ports != numTraces) {
// invalid number of traces // invalid number of traces
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
Trace* traces[numTraces]; Trace* traces[numTraces];
for(int i=0;i<numTraces;i++) { for(int i=0;i<numTraces;i++) {
traces[i] = findTraceFromName(params[i]); traces[i] = findTraceFromName(params[i]);
if(!traces[i]) { if(!traces[i]) {
// couldn't find that trace // couldn't find that trace
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
} }
// check if trace selection is valid // check if trace selection is valid
@ -277,15 +277,15 @@ void TraceWidget::SetupSCPI()
auto t = traces[j+i*ports]; auto t = traces[j+i*ports];
if(t->getDataType() != Trace::DataType::Frequency) { if(t->getDataType() != Trace::DataType::Frequency) {
// invalid domain // invalid domain
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
if(t->isReflection() != need_reflection) { if(t->isReflection() != need_reflection) {
// invalid measurement at this position // 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)) { if((t->size() != npoints) || (t->minX() != f_start) || (t->maxX() != f_stop)) {
// frequency points are not identical // 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 { add(new SCPICommand("MAXFrequency", nullptr, [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
return QString::number(t->maxX(), 'f', 0); return QString::number(t->maxX(), 'f', 0);
})); }));
add(new SCPICommand("MINFrequency", nullptr, [=](QStringList params) -> QString { add(new SCPICommand("MINFrequency", nullptr, [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
return QString::number(t->minX(), 'f', 0); return QString::number(t->minX(), 'f', 0);
})); }));
add(new SCPICommand("MAXAmplitude", nullptr, [=](QStringList params) -> QString { add(new SCPICommand("MAXAmplitude", nullptr, [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
auto d = t->interpolatedSample(t->findExtremum(true)); auto d = t->interpolatedSample(t->findExtremum(true));
return QString::number(d.x, 'f', 0)+","+createStringFromData(t, d); 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 { add(new SCPICommand("MINAmplitude", nullptr, [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
auto d = t->interpolatedSample(t->findExtremum(false)); auto d = t->interpolatedSample(t->findExtremum(false));
return QString::number(d.x, 'f', 0)+","+createStringFromData(t, d); return QString::number(d.x, 'f', 0)+","+createStringFromData(t, d);
})); }));
add(new SCPICommand("NEW", [=](QStringList params) -> QString { add(new SCPICommand("NEW", [=](QStringList params) -> QString {
if(params.size() != 1) { if(params.size() != 1) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
createCount++; createCount++;
auto t = new Trace(params[0], Qt::darkYellow, defaultParameter()); auto t = new Trace(params[0], Qt::darkYellow, defaultParameter());
t->setColor(QColor::fromHsl((createCount * 50) % 360, 250, 128)); t->setColor(QColor::fromHsl((createCount * 50) % 360, 250, 128));
model.addTrace(t); model.addTrace(t);
return ""; return SCPI::getResultName(SCPI::Result::Empty);
}, nullptr)); }, nullptr));
add(new SCPICommand("RENAME", [=](QStringList params) -> QString { add(new SCPICommand("RENAME", [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
if(params.size() != 2) { if(params.size() != 2) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
t->setName(params[1]); t->setName(params[1]);
return ""; return SCPI::getResultName(SCPI::Result::Empty);
}, nullptr)); }, nullptr));
add(new SCPICommand("PAUSE", [=](QStringList params) -> QString { add(new SCPICommand("PAUSE", [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
t->pause(); t->pause();
return ""; return SCPI::getResultName(SCPI::Result::Empty);
}, nullptr)); }, nullptr));
add(new SCPICommand("RESUME", [=](QStringList params) -> QString { add(new SCPICommand("RESUME", [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { return "ERROR"; if(!t) {
return SCPI::getResultName(SCPI::Result::Error);
} }
t->resume(); t->resume();
return ""; return SCPI::getResultName(SCPI::Result::Empty);
}, nullptr)); }, nullptr));
add(new SCPICommand("PAUSED", nullptr, [=](QStringList params) -> QString { add(new SCPICommand("PAUSED", nullptr, [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { 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 { add(new SCPICommand("PARAMeter", [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t || params.size() < 2) { if(!t || params.size() < 2) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
auto newparam = params[1]; auto newparam = params[1];
if((Trace::isVNAParameter(t->liveParameter()) && Trace::isVNAParameter(newparam)) if((Trace::isVNAParameter(t->liveParameter()) && Trace::isVNAParameter(newparam))
|| (Trace::isSAParameter(t->liveParameter()) && Trace::isSAParameter(newparam))) { || (Trace::isSAParameter(t->liveParameter()) && Trace::isSAParameter(newparam))) {
t->fromLivedata(t->liveType(), newparam); t->fromLivedata(t->liveType(), newparam);
return ""; return SCPI::getResultName(SCPI::Result::Empty);
} else { } else {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
}, [=](QStringList params) -> QString { }, [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
return t->liveParameter(); return t->liveParameter();
})); }));
add(new SCPICommand("TYPE", [=](QStringList params) -> QString { add(new SCPICommand("TYPE", [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t || params.size() < 2) { if(!t || params.size() < 2) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
auto newtype = Trace::TypeFromString(params[1]); auto newtype = Trace::TypeFromString(params[1]);
if(newtype != Trace::LivedataType::Invalid) { if(newtype != Trace::LivedataType::Invalid) {
t->fromLivedata(newtype, t->liveParameter()); t->fromLivedata(newtype, t->liveParameter());
return ""; return SCPI::getResultName(SCPI::Result::Empty);
} else { } else {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
}, [=](QStringList params) -> QString { }, [=](QStringList params) -> QString {
auto t = findTrace(params); auto t = findTrace(params);
if(!t) { if(!t) {
return "ERROR"; return SCPI::getResultName(SCPI::Result::Error);
} }
return Trace::TypeToString(t->liveType()); return Trace::TypeToString(t->liveType());
})); }));

View File

@ -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) Deembedding::Deembedding(TraceModel &tm)
: measuringOption(nullptr), : SCPINode("DEEMBedding"),
measuringOption(nullptr),
tm(tm), tm(tm),
measuring(false), measuring(false),
measurementDialog(nullptr), measurementDialog(nullptr),
measurementUI(nullptr), measurementUI(nullptr),
sweepPoints(0) 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) void Deembedding::Deembed(VirtualDevice::VNAMeasurement &d)
@ -137,6 +177,7 @@ void Deembedding::removeOption(unsigned int index)
delete options[index]; delete options[index];
options.erase(options.begin() + index); options.erase(options.begin() + index);
} }
updateSCPINames();
if(options.size() == 0) { if(options.size() == 0) {
emit allOptionsCleared(); emit allOptionsCleared();
} }
@ -156,6 +197,7 @@ void Deembedding::addOption(DeembeddingOption *option)
measuringOption = option; measuringOption = option;
startMeasurementDialog(option); startMeasurementDialog(option);
}); });
updateSCPINames();
emit optionAdded(); emit optionAdded();
} }
@ -165,6 +207,7 @@ void Deembedding::swapOptions(unsigned int index)
return; return;
} }
std::swap(options[index], options[index+1]); std::swap(options[index], options[index+1]);
updateSCPINames();
} }
std::set<unsigned int> Deembedding::getAffectedPorts() std::set<unsigned int> Deembedding::getAffectedPorts()
@ -182,7 +225,7 @@ nlohmann::json Deembedding::toJSON()
nlohmann::json list; nlohmann::json list;
for(auto m : options) { for(auto m : options) {
nlohmann::json jm; nlohmann::json jm;
jm["operation"] = DeembeddingOption::getName(m->getType()).toStdString(); jm["operation"] = DeembeddingOption::TypeToString(m->getType()).toStdString();
jm["settings"] = m->toJSON(); jm["settings"] = m->toJSON();
list.push_back(jm); list.push_back(jm);
} }
@ -204,7 +247,7 @@ void Deembedding::fromJSON(nlohmann::json j)
// attempt to find the type of operation // attempt to find the type of operation
DeembeddingOption::Type type = DeembeddingOption::Type::Last; DeembeddingOption::Type type = DeembeddingOption::Type::Last;
for(unsigned int i=0;i<(int) DeembeddingOption::Type::Last;i++) { 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 // found the correct operation
type = (DeembeddingOption::Type) i; type = (DeembeddingOption::Type) i;
break; break;

View File

@ -4,6 +4,7 @@
#include "deembeddingoption.h" #include "deembeddingoption.h"
#include "savable.h" #include "savable.h"
#include "Traces/tracemodel.h" #include "Traces/tracemodel.h"
#include "scpi.h"
#include <vector> #include <vector>
#include <map> #include <map>
@ -14,7 +15,7 @@
class Ui_DeembeddingMeasurementDialog; class Ui_DeembeddingMeasurementDialog;
class Deembedding : public QObject, public Savable class Deembedding : public QObject, public Savable, public SCPINode
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -42,6 +43,7 @@ signals:
private: private:
void measurementCompleted(); void measurementCompleted();
void startMeasurementDialog(DeembeddingOption *option); void startMeasurementDialog(DeembeddingOption *option);
void updateSCPINames();
std::vector<DeembeddingOption*> options; std::vector<DeembeddingOption*> options;
DeembeddingOption *measuringOption; DeembeddingOption *measuringOption;
TraceModel &tm; TraceModel &tm;

View File

@ -15,7 +15,7 @@ DeembeddingDialog::DeembeddingDialog(Deembedding *d, QWidget *parent) :
auto addMenu = new QMenu(); auto addMenu = new QMenu();
for(unsigned int i=0;i<(unsigned int)DeembeddingOption::Type::Last;i++) { for(unsigned int i=0;i<(unsigned int)DeembeddingOption::Type::Last;i++) {
auto type = (DeembeddingOption::Type) i; auto type = (DeembeddingOption::Type) i;
auto action = new QAction(DeembeddingOption::getName(type)); auto action = new QAction(DeembeddingOption::TypeToString(type));
connect(action, &QAction::triggered, [=](){ connect(action, &QAction::triggered, [=](){
auto option = DeembeddingOption::create(type); auto option = DeembeddingOption::create(type);
model.addOption(option); model.addOption(option);
@ -86,7 +86,7 @@ QVariant OptionModel::data(const QModelIndex &index, int role) const
{ {
if(index.isValid() && role == Qt::DisplayRole) { if(index.isValid() && role == Qt::DisplayRole) {
auto type = d->getOptions()[index.row()]->getType(); auto type = d->getOptions()[index.row()]->getType();
return DeembeddingOption::getName(type); return DeembeddingOption::TypeToString(type);
} else { } else {
return QVariant(); return QVariant();
} }

View File

@ -21,7 +21,7 @@ DeembeddingOption *DeembeddingOption::create(DeembeddingOption::Type type)
} }
} }
QString DeembeddingOption::getName(DeembeddingOption::Type type) QString DeembeddingOption::TypeToString(DeembeddingOption::Type type)
{ {
switch(type) { switch(type) {
case Type::PortExtension: case Type::PortExtension:
@ -36,3 +36,13 @@ QString DeembeddingOption::getName(DeembeddingOption::Type type)
return ""; 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;
}

View File

@ -4,10 +4,11 @@
#include "savable.h" #include "savable.h"
#include "Device/device.h" #include "Device/device.h"
#include "Traces/tracemodel.h" #include "Traces/tracemodel.h"
#include "scpi.h"
#include <QWidget> #include <QWidget>
class DeembeddingOption : public QObject, public Savable class DeembeddingOption : public QObject, public Savable, public SCPINode
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -21,7 +22,8 @@ public:
}; };
static DeembeddingOption *create(Type type); static DeembeddingOption *create(Type type);
static QString getName(Type type); static QString TypeToString(Type type);
static Type TypeFromString(QString string);
virtual std::set<unsigned int> getAffectedPorts() = 0; virtual std::set<unsigned int> getAffectedPorts() = 0;
virtual void transformDatapoint(VirtualDevice::VNAMeasurement &p) = 0; virtual void transformDatapoint(VirtualDevice::VNAMeasurement &p) = 0;
@ -35,6 +37,10 @@ signals:
void deleted(DeembeddingOption *option); void deleted(DeembeddingOption *option);
void triggerMeasurement(); void triggerMeasurement();
protected:
DeembeddingOption(QString SCPIname)
: SCPINode(SCPIname){}
}; };
#endif // DEEMBEDDING_H #endif // DEEMBEDDING_H

View File

@ -9,10 +9,20 @@
using namespace std; using namespace std;
ImpedanceRenormalization::ImpedanceRenormalization() ImpedanceRenormalization::ImpedanceRenormalization()
: DeembeddingOption(), : DeembeddingOption("ZNORMalization"),
impedance(50.0) 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<unsigned int> ImpedanceRenormalization::getAffectedPorts() std::set<unsigned int> ImpedanceRenormalization::getAffectedPorts()

View File

@ -20,6 +20,7 @@
using namespace std; using namespace std;
MatchingNetwork::MatchingNetwork() MatchingNetwork::MatchingNetwork()
: DeembeddingOption("MATCHing")
{ {
dropPending = false; dropPending = false;
dragComponent = nullptr; dragComponent = nullptr;
@ -268,7 +269,7 @@ void MatchingNetwork::addComponent(int index, MatchingComponent *c)
matching.clear(); matching.clear();
// remove from list when the component deletes itself // remove from list when the component deletes itself
connect(c, &MatchingComponent::deleted, [=](){ 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(); matching.clear();
}); });
} }
@ -325,7 +326,7 @@ bool MatchingNetwork::eventFilter(QObject *object, QEvent *event)
// remove and hide component while it is being dragged // remove and hide component while it is being dragged
graph->layout()->removeWidget(dragComponent); graph->layout()->removeWidget(dragComponent);
dragComponent->hide(); 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(); graph->update();
// network changed, need to recalculate matching // network changed, need to recalculate matching

View File

@ -11,7 +11,7 @@
using namespace std; using namespace std;
PortExtension::PortExtension() PortExtension::PortExtension()
: DeembeddingOption() : DeembeddingOption("PORTEXTension")
{ {
ext.frequency = 0; ext.frequency = 0;
ext.loss = 0; ext.loss = 0;
@ -25,6 +25,12 @@ PortExtension::PortExtension()
kit = nullptr; kit = nullptr;
ui = nullptr; ui = nullptr;
addUnsignedIntParameter("PORT", port);
addDoubleParameter("DELAY", ext.delay);
addDoubleParameter("DCLOSS", ext.DCloss);
addDoubleParameter("LOSS", ext.loss);
addDoubleParameter("FREQuency", ext.frequency);
} }
std::set<unsigned int> PortExtension::getAffectedPorts() std::set<unsigned int> PortExtension::getAffectedPorts()

View File

@ -11,6 +11,7 @@
using namespace std; using namespace std;
TwoThru::TwoThru() TwoThru::TwoThru()
: DeembeddingOption("TWOTHRU")
{ {
Z0 = 50.0; Z0 = 50.0;
port1 = 1; port1 = 1;

View File

@ -1411,6 +1411,8 @@ void VNA::SetupSCPI()
cal.add(new SCPICommand("BUSy", nullptr, [=](QStringList) -> QString { cal.add(new SCPICommand("BUSy", nullptr, [=](QStringList) -> QString {
return CalibrationMeasurementActive() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False); return CalibrationMeasurementActive() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
})); }));
SCPINode::add(&deembedding);
} }
void VNA::ConstrainAndUpdateFrequencies() void VNA::ConstrainAndUpdateFrequencies()

View File

@ -160,6 +160,54 @@ bool SCPINode::add(SCPICommand *cmd)
return true; return true;
} }
bool SCPINode::addDoubleParameter(QString name, double &param, 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<QString(QStringList)>) nullptr;
auto query = settable ? [=](QStringList params) -> QString {
Q_UNUSED(params)
return QString::number(param);
} : (std::function<QString(QStringList)>) nullptr;
return add(new SCPICommand(name, cmd, query));
}
bool SCPINode::addUnsignedIntParameter(QString name, unsigned int &param, 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<QString(QStringList)>) nullptr;
auto query = settable ? [=](QStringList params) -> QString {
Q_UNUSED(params)
return QString::number(param);
} : (std::function<QString(QStringList)>) 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) bool SCPINode::nameCollision(QString name)
{ {
for(auto n : subnodes) { for(auto n : subnodes) {

View File

@ -35,11 +35,16 @@ public:
bool remove(SCPINode *node); bool remove(SCPINode *node);
bool add(SCPICommand *cmd); bool add(SCPICommand *cmd);
bool addDoubleParameter(QString name, double &param, bool gettable = true, bool settable = true);
bool addUnsignedIntParameter(QString name, unsigned int &param, bool gettable = true, bool settable = true);
bool changeName(QString newname);
private: private:
QString parse(QString cmd, SCPINode* &lastNode); QString parse(QString cmd, SCPINode* &lastNode);
bool nameCollision(QString name); bool nameCollision(QString name);
void createCommandList(QString prefix, QString &list); void createCommandList(QString prefix, QString &list);
const QString name; QString name;
std::vector<SCPINode*> subnodes; std::vector<SCPINode*> subnodes;
std::vector<SCPICommand*> commands; std::vector<SCPICommand*> commands;
SCPINode *parent; SCPINode *parent;