WIP: additional SCPI commands for de-embedding

This commit is contained in:
Jan Käberich 2022-12-12 22:42:33 +01:00
parent a0476d1bf2
commit e6678435bd
7 changed files with 202 additions and 20 deletions

View File

@ -80,6 +80,7 @@ void Deembedding::updateSCPINames()
for(auto &option : options) {
option->changeName(QString::number(i));
add(option);
i++;
}
}
@ -104,13 +105,13 @@ Deembedding::Deembedding(TraceModel &tm)
if(index < 1 || index > options.size()) {
return SCPI::getResultName(SCPI::Result::Error);
}
return DeembeddingOption::TypeToString(options[index]->getType());
return DeembeddingOption::TypeToString(options[index-1]->getType()).replace(" ", "_");
}));
add(new SCPICommand("NEW", [=](QStringList params) -> QString {
if(params.size() < 1) {
return SCPI::getResultName(SCPI::Result::Error);
}
auto type = DeembeddingOption::TypeFromString(params[0]);
auto type = DeembeddingOption::TypeFromString(params[0].replace("_", " "));
if(type == DeembeddingOption::Type::Last) {
return SCPI::getResultName(SCPI::Result::Error);
}
@ -118,6 +119,11 @@ Deembedding::Deembedding(TraceModel &tm)
addOption(option);
return SCPI::getResultName(SCPI::Result::Empty);
}, nullptr));
add(new SCPICommand("CLEAR", [=](QStringList params) -> QString {
Q_UNUSED(params);
clear();
return SCPI::getResultName(SCPI::Result::Empty);
}, nullptr));
}
void Deembedding::Deembed(VirtualDevice::VNAMeasurement &d)
@ -210,6 +216,13 @@ void Deembedding::swapOptions(unsigned int index)
updateSCPINames();
}
void Deembedding::clear()
{
while(options.size() > 0) {
removeOption(0);
}
}
std::set<unsigned int> Deembedding::getAffectedPorts()
{
set<unsigned int> ret;

View File

@ -28,6 +28,7 @@ public:
void removeOption(unsigned int index);
void addOption(DeembeddingOption* option);
void swapOptions(unsigned int index);
void clear();
std::set<unsigned int> getAffectedPorts();

View File

@ -40,7 +40,7 @@ QString DeembeddingOption::TypeToString(DeembeddingOption::Type type)
DeembeddingOption::Type DeembeddingOption::TypeFromString(QString string)
{
for(unsigned int i=0;i<(int) Type::Last;i++) {
if(TypeToString((Type) i) == string) {
if(TypeToString((Type) i).compare(string, Qt::CaseInsensitive) == 0) {
return (Type) i;
}
}

View File

@ -27,6 +27,50 @@ MatchingNetwork::MatchingNetwork()
dropComponent = nullptr;
addNetwork = true;
port = 1;
graph = nullptr;
insertIndicator = nullptr;
addUnsignedIntParameter("PORT", port);
addBoolParameter("ADD", addNetwork);
add(new SCPICommand("CLEAR", [=](QStringList params) -> QString {
Q_UNUSED(params);
clearNetwork();
return SCPI::getResultName(SCPI::Result::Empty);
}, nullptr));
add(new SCPICommand("NUMber", nullptr, [=](QStringList params) -> QString {
Q_UNUSED(params);
return QString::number(network.size());
}));
add(new SCPICommand("NEW", [=](QStringList params) -> QString {
if(params.size() < 1) {
return SCPI::getResultName(SCPI::Result::Error);
}
auto c = MatchingComponent::createFromName(params[0].replace("_", " "));
if(!c) {
return SCPI::getResultName(SCPI::Result::Error);
}
unsigned long long index = network.size();
// parse index (unchanged if not provided)
SCPI::paramToULongLong(params, 1, index);
addComponent(index, c);
return SCPI::getResultName(SCPI::Result::Empty);
}, nullptr));
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 > network.size()) {
return SCPI::getResultName(SCPI::Result::Error);
}
return network[index-1]->getName().replace(" ", "_");
}));
}
MatchingNetwork::~MatchingNetwork()
{
clearNetwork();
}
std::set<unsigned int> MatchingNetwork::getAffectedPorts()
@ -179,7 +223,10 @@ void MatchingNetwork::edit()
connect(ui->port, qOverload<int>(&QSpinBox::valueChanged), [=](){
port = ui->port->value();
});
connect(ui->buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
connect(ui->buttonBox, &QDialogButtonBox::accepted, [=](){
graph = nullptr;
dialog->accept();
});
}
nlohmann::json MatchingNetwork::toJSON()
@ -200,7 +247,7 @@ nlohmann::json MatchingNetwork::toJSON()
void MatchingNetwork::fromJSON(nlohmann::json j)
{
network.clear();
clearNetwork();
port = j.value("port", 1);
if(j.contains("network")) {
for(auto jc : j["network"]) {
@ -219,6 +266,15 @@ void MatchingNetwork::fromJSON(nlohmann::json j)
matching.clear();
}
void MatchingNetwork::clearNetwork()
{
while(network.size() > 0) {
auto c = network[0];
removeComponent(c);
delete c;
}
}
MatchingComponent *MatchingNetwork::componentAtPosition(int pos)
{
pos -= graph->layout()->itemAt(0)->geometry().width();
@ -266,14 +322,37 @@ void MatchingNetwork::addComponentAtPosition(int pos, MatchingComponent *c)
void MatchingNetwork::addComponent(int index, MatchingComponent *c)
{
network.insert(network.begin() + index, c);
updateSCPINames();
if(graph) {
graph->update();
}
matching.clear();
// remove from list when the component deletes itself
connect(c, &MatchingComponent::deleted, [=](){
network.erase(std::remove(network.begin(), network.end(), c), network.end());
matching.clear();
removeComponent(c);
});
}
void MatchingNetwork::removeComponent(int index)
{
network.erase(network.begin() + index);
matching.clear();
updateSCPINames();
if(graph) {
graph->update();
}
}
void MatchingNetwork::removeComponent(MatchingComponent *c)
{
network.erase(std::remove(network.begin(), network.end(), c), network.end());
matching.clear();
updateSCPINames();
if(graph) {
graph->update();
}
}
void MatchingNetwork::createDragComponent(MatchingComponent *c)
{
QDrag *drag = new QDrag(this);
@ -326,7 +405,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(std::remove(network.begin(), network.end(), dragComponent), network.end());
removeComponent(dragComponent);
graph->update();
// network changed, need to recalculate matching
@ -414,7 +493,23 @@ bool MatchingNetwork::eventFilter(QObject *object, QEvent *event)
return false;
}
void MatchingNetwork::updateSCPINames()
{
// Need to remove all components from the subnode list first, otherwise
// name changes wouldn't work due to temporarily name collisions
for(auto &c : network) {
remove(c);
}
unsigned int i=1;
for(auto &c : network) {
c->changeName(QString::number(i));
add(c);
i++;
}
}
MatchingComponent::MatchingComponent(Type type)
: SCPINode("COMPONENT")
{
this->type = type;
eValue = nullptr;
@ -431,7 +526,10 @@ MatchingComponent::MatchingComponent(Type type)
eValue = new SIUnitEdit();
eValue->setPrecision(4);
eValue->setPrefixes("fpnum k");
connect(eValue, &SIUnitEdit::valueChanged, this, &MatchingComponent::valueChanged);
connect(eValue, &SIUnitEdit::valueChanged, [=](double newval) {
value = newval;
emit valueChanged();
});
auto layout = new QVBoxLayout();
layout->addWidget(eValue);
setLayout(layout);
@ -443,7 +541,10 @@ MatchingComponent::MatchingComponent(Type type)
eValue = new SIUnitEdit();
eValue->setPrecision(4);
eValue->setPrefixes("fpnum k");
connect(eValue, &SIUnitEdit::valueChanged, this, &MatchingComponent::valueChanged);
connect(eValue, &SIUnitEdit::valueChanged, [=](double newval) {
value = newval;
emit valueChanged();
});
auto layout = new QVBoxLayout();
layout->addWidget(eValue);
layout->addStretch(1);
@ -513,6 +614,37 @@ MatchingComponent::MatchingComponent(Type type)
default:
break;
}
switch(type) {
case Type::SeriesR:
case Type::SeriesL:
case Type::SeriesC:
case Type::ParallelR:
case Type::ParallelL:
case Type::ParallelC:
addDoubleParameter("VALue", value, true, true, [=](){
eValue->setValue(value);
});
break;
case Type::DefinedThrough:
case Type::DefinedShunt:
add(new SCPICommand("FILE", [=](QStringList params) -> QString {
if(params.size() < 1) {
return SCPI::getResultName(SCPI::Result::Error);
}
try {
*touchstone = Touchstone::fromFile(params[0].toStdString());
updateTouchstoneLabel();
emit valueChanged();
return SCPI::getResultName(SCPI::Result::Empty);
} catch(const std::exception& e) {
// failed to load file
return SCPI::getResultName(SCPI::Result::Error);
}
}, nullptr));
break;
default:
break;
}
}
MatchingComponent::~MatchingComponent()
@ -562,6 +694,7 @@ ABCDparam MatchingComponent::parameters(double freq)
void MatchingComponent::MatchingComponent::setValue(double v)
{
value = v;
if(eValue) {
eValue->setValue(v);
}
@ -570,7 +703,7 @@ void MatchingComponent::MatchingComponent::setValue(double v)
MatchingComponent *MatchingComponent::createFromName(QString name)
{
for(unsigned int i=0;i<(int) Type::Last;i++) {
if(name == typeToName((Type) i)) {
if(typeToName((Type) i).compare(name, Qt::CaseInsensitive) == 0) {
return new MatchingComponent((Type) i);
}
}

View File

@ -12,7 +12,7 @@
#include <vector>
class MatchingComponent : public QFrame, public Savable
class MatchingComponent : public QFrame, public Savable, public SCPINode
{
Q_OBJECT
public:
@ -56,12 +56,14 @@ private:
void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
QString oldStylesheet;
double value;
};
class MatchingNetwork : public DeembeddingOption
{
public:
MatchingNetwork();
~MatchingNetwork();
// DeembeddingOption interface
public:
@ -71,6 +73,8 @@ public:
Type getType() override {return Type::MatchingNetwork;}
nlohmann::json toJSON() override;
void fromJSON(nlohmann::json j) override;
void clearNetwork();
private:
static constexpr int imageHeight = 151;
static constexpr int componentWidth = 151;
@ -80,10 +84,14 @@ private:
unsigned int findInsertPosition(int xcoord);
void addComponentAtPosition(int pos, MatchingComponent *c);
void addComponent(int index, MatchingComponent *c);
void removeComponent(int index);
void removeComponent(MatchingComponent *c);
void createDragComponent(MatchingComponent *c);
void updateInsertIndicator(int xcoord);
bool eventFilter(QObject *object, QEvent *event) override;
void updateSCPINames();
std::vector<MatchingComponent*> network;
unsigned int port;

View File

@ -160,40 +160,65 @@ bool SCPINode::add(SCPICommand *cmd)
return true;
}
bool SCPINode::addDoubleParameter(QString name, double &param, bool gettable, bool settable)
bool SCPINode::addDoubleParameter(QString name, double &param, bool gettable, bool settable, std::function<void(void)> setCallback)
{
auto cmd = settable ? [&](QStringList params) -> QString {
auto cmd = settable ? [&param, setCallback](QStringList params) -> QString {
if(SCPI::paramToDouble(params, 0, param)) {
if(setCallback) {
setCallback();
}
return SCPI::getResultName(SCPI::Result::Empty);
} else {
return SCPI::getResultName(SCPI::Result::Error);
}
} : (std::function<QString(QStringList)>) nullptr;
auto query = settable ? [=](QStringList params) -> QString {
auto query = gettable ? [=](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)
bool SCPINode::addUnsignedIntParameter(QString name, unsigned int &param, bool gettable, bool settable, std::function<void(void)> setCallback)
{
auto cmd = settable ? [&](QStringList params) -> QString {
auto cmd = settable ? [&param, setCallback](QStringList params) -> QString {
unsigned long long value;
if(SCPI::paramToULongLong(params, 0, value)) {
param = value;
if(setCallback) {
setCallback();
}
return SCPI::getResultName(SCPI::Result::Empty);
} else {
return SCPI::getResultName(SCPI::Result::Error);
}
} : (std::function<QString(QStringList)>) nullptr;
auto query = settable ? [=](QStringList params) -> QString {
auto query = gettable ? [=](QStringList params) -> QString {
Q_UNUSED(params)
return QString::number(param);
} : (std::function<QString(QStringList)>) nullptr;
return add(new SCPICommand(name, cmd, query));
}
bool SCPINode::addBoolParameter(QString name, bool &param, bool gettable, bool settable, std::function<void(void)> setCallback)
{
auto cmd = settable ? [&param, setCallback](QStringList params) -> QString {
if(SCPI::paramToBool(params, 0, param)) {
if(setCallback) {
setCallback();
}
return SCPI::getResultName(SCPI::Result::Empty);
} else {
return SCPI::getResultName(SCPI::Result::Error);
}
} : (std::function<QString(QStringList)>) nullptr;
auto query = gettable ? [=](QStringList params) -> QString {
Q_UNUSED(params)
return param ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
} : (std::function<QString(QStringList)>) nullptr;
return add(new SCPICommand(name, cmd, query));
}
bool SCPINode::changeName(QString newname)
{
if(newname == name) {
@ -206,6 +231,7 @@ bool SCPINode::changeName(QString newname)
}
}
name = newname;
return true;
}
bool SCPINode::nameCollision(QString name)

View File

@ -35,8 +35,9 @@ public:
bool remove(SCPINode *node);
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 addDoubleParameter(QString name, double &param, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
bool addUnsignedIntParameter(QString name, unsigned int &param, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
bool addBoolParameter(QString name, bool &param, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
bool changeName(QString newname);