diff --git a/Software/PC_Application/LibreVNA-GUI/Tools/parameters.cpp b/Software/PC_Application/LibreVNA-GUI/Tools/parameters.cpp index b5e715b..2128680 100644 --- a/Software/PC_Application/LibreVNA-GUI/Tools/parameters.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Tools/parameters.cpp @@ -65,3 +65,18 @@ void Parameters::fromJSON(nlohmann::json j) m21 = complex(j.value("m21_real", 0.0), j.value("m21_imag", 0.0)); m22 = complex(j.value("m22_real", 0.0), j.value("m22_imag", 0.0)); } + +Yparam::Yparam(const Sparam &s, Type Z01, Type Z02) +{ + // from https://www.rfcafe.com/references/electrical/s-h-y-z.htm + auto denom = (conj(Z01)+s.m11*Z01)*(conj(Z02)+s.m22*Z02)-s.m12*s.m21*Z01*Z02; + m11 = ((1.0-s.m11)*(conj(Z02)+s.m22*Z02)+s.m12*s.m21*Z02) / denom; + m12 = -2.0*s.m12*sqrt(real(Z01)*real(Z02)); + m21 = -2.0*s.m21*sqrt(real(Z01)*real(Z02)); + m22 = ((conj(Z01)+s.m11*Z01)*(1.0-s.m22)+s.m12*s.m21*Z01) / denom; +} + +Yparam::Yparam(const Sparam &s, Type Z0) + : Yparam(s, Z0, Z0) +{ +} diff --git a/Software/PC_Application/LibreVNA-GUI/Tools/parameters.h b/Software/PC_Application/LibreVNA-GUI/Tools/parameters.h index 41e4129..2da96a7 100644 --- a/Software/PC_Application/LibreVNA-GUI/Tools/parameters.h +++ b/Software/PC_Application/LibreVNA-GUI/Tools/parameters.h @@ -131,4 +131,11 @@ public: } }; +class Yparam : public Parameters { +public: + using Parameters::Parameters; + Yparam(const Sparam &s, Type Z01, Type Z02); + Yparam(const Sparam &s, Type Z0); +}; + #endif // TPARAM_H diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.cpp index 747b08e..1ae5180 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.cpp @@ -109,6 +109,7 @@ void MatchingNetwork::edit() ui->lParallelL->installEventFilter(this); ui->lParallelR->installEventFilter(this); ui->lDefinedThrough->installEventFilter(this); + ui->lDefinedShunt->installEventFilter(this); ui->port->setValue(port); ui->port->setMaximum(VirtualDevice::getInfo(VirtualDevice::getConnected()).ports); @@ -361,6 +362,8 @@ bool MatchingNetwork::eventFilter(QObject *object, QEvent *event) dragComponent = new MatchingComponent(MatchingComponent::Type::ParallelR); } else if(object->objectName() == "lDefinedThrough") { dragComponent = new MatchingComponent(MatchingComponent::Type::DefinedThrough); + } else if(object->objectName() == "lDefinedShunt") { + dragComponent = new MatchingComponent(MatchingComponent::Type::DefinedShunt); } else { dragComponent = nullptr; } @@ -470,6 +473,19 @@ MatchingComponent::MatchingComponent(Type type) updateTouchstoneLabel(); } break; + case Type::DefinedShunt: { + touchstone = new Touchstone(2); + touchstoneLabel = new QLabel(); + touchstoneLabel->setWordWrap(true); + touchstoneLabel->setAlignment(Qt::AlignCenter); + auto layout = new QVBoxLayout(); + layout->addWidget(touchstoneLabel); + layout->setContentsMargins(0, 0, 0, 0); + setLayout(layout); + setStyleSheet("image: url(:/icons/definedShunt.png);"); + updateTouchstoneLabel(); + } + break; default: break; } @@ -504,7 +520,16 @@ ABCDparam MatchingComponent::parameters(double freq) } else { auto d = touchstone->interpolate(freq); auto S = Sparam(d.S[0], d.S[1], d.S[2], d.S[3]); - return ABCDparam(S, 50.0); + return ABCDparam(S, touchstone->getReferenceImpedance()); + } + case Type::DefinedShunt: + if(touchstone->points() == 0 || freq < touchstone->minFreq() || freq > touchstone->maxFreq()) { + // outside of provided frequency range, pass through unchanged + return ABCDparam(1.0, 0.0, 0.0, 1.0); + } else { + auto d = touchstone->interpolate(freq); + auto Y = Yparam(Sparam(d.S[0], d.S[1], d.S[2], d.S[3]), touchstone->getReferenceImpedance()); + return ABCDparam(1.0, 0.0, Y.m11, 1.0); } default: return ABCDparam(1.0, 0.0, 0.0, 1.0); @@ -547,6 +572,7 @@ nlohmann::json MatchingComponent::toJSON() j["value"] = eValue->value(); break; case Type::DefinedThrough: + case Type::DefinedShunt: j["touchstone"] = touchstone->toJSON(); break; case Type::Last: @@ -567,6 +593,7 @@ void MatchingComponent::fromJSON(nlohmann::json j) eValue->setValue(j.value("value", 1e-12)); break; case Type::DefinedThrough: + case Type::DefinedShunt: touchstone->fromJSON(j["touchstone"]); updateTouchstoneLabel(); break; @@ -578,7 +605,7 @@ void MatchingComponent::fromJSON(nlohmann::json j) void MatchingComponent::mouseDoubleClickEvent(QMouseEvent *e) { Q_UNUSED(e); - if(type == Type::DefinedThrough) { + if(type == Type::DefinedThrough || type == Type::DefinedShunt) { // select new touchstone file auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", "", "Touchstone files (*.s2p)", nullptr, QFileDialog::DontUseNativeDialog); if (!filename.isEmpty()) { @@ -588,6 +615,7 @@ void MatchingComponent::mouseDoubleClickEvent(QMouseEvent *e) InformationBox::ShowError("Failed to load file", QString("Attempt to load file ended with error: \"") + e.what()+"\""); } updateTouchstoneLabel(); + emit valueChanged(); } } } @@ -597,6 +625,9 @@ void MatchingComponent::updateTouchstoneLabel() if(!touchstone || !touchstoneLabel) { return; } + QFont font = touchstoneLabel->font(); + font.setPointSize(10); + touchstoneLabel->setFont(font); if(touchstone->points() == 0) { touchstoneLabel->setText("No data. Double-click to select touchstone file"); } else { @@ -604,6 +635,11 @@ void MatchingComponent::updateTouchstoneLabel() + " to "+Unit::ToString(touchstone->maxFreq(), "Hz", " kMG", 4); touchstoneLabel->setText(text); } + if(type == Type::DefinedThrough) { + touchstoneLabel->setAlignment(Qt::AlignCenter); + } else if(type == Type::DefinedShunt) { + touchstoneLabel->setAlignment(Qt::AlignTop | Qt::AlignHCenter); + } } QString MatchingComponent::typeToName(MatchingComponent::Type type) @@ -616,6 +652,7 @@ QString MatchingComponent::typeToName(MatchingComponent::Type type) case Type::ParallelL: return "ParallelL"; case Type::ParallelC: return "ParallelC"; case Type::DefinedThrough: return "Touchstone Through"; + case Type::DefinedShunt: return "Touchstone Shunt"; default: return ""; } } diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.h b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.h index 7297bf2..6825ebd 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.h +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetwork.h @@ -24,6 +24,7 @@ public: ParallelL, ParallelC, DefinedThrough, + DefinedShunt, // Add new matching components here, do not explicitly assign values and keep the Last entry at the last position Last, }; diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetworkdialog.ui b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetworkdialog.ui index ee9eb7e..d5c06ea 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetworkdialog.ui +++ b/Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/matchingnetworkdialog.ui @@ -596,6 +596,49 @@ + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + border-image: url(:/icons/definedShunt.svg); + + + Def. Shunt + + + Qt::AlignHCenter|Qt::AlignTop + + + true + + + + + + diff --git a/Software/PC_Application/LibreVNA-GUI/icons.qrc b/Software/PC_Application/LibreVNA-GUI/icons.qrc index 58f230d..0c25332 100644 --- a/Software/PC_Application/LibreVNA-GUI/icons.qrc +++ b/Software/PC_Application/LibreVNA-GUI/icons.qrc @@ -50,14 +50,12 @@ icons/down.png icons/up.png icons/chainlink.png - icons/definedThrough.svg icons/seriesR.png icons/seriesL.png icons/seriesC.png icons/parallelR.png icons/parallelL.png icons/parallelC.png - icons/definedThrough.png icons/LibreVNAV1.svg icons/compound_V1_Ref_Left.svg icons/compound_V1_Ref_Middle.svg @@ -69,5 +67,9 @@ icons/compound_V1_USB.png icons/DUT_onePort.png icons/port.png + icons/definedShunt.png + icons/definedShunt.svg + icons/definedThrough.png + icons/definedThrough.svg diff --git a/Software/PC_Application/LibreVNA-GUI/icons/definedShunt.png b/Software/PC_Application/LibreVNA-GUI/icons/definedShunt.png new file mode 100644 index 0000000..81bfba7 Binary files /dev/null and b/Software/PC_Application/LibreVNA-GUI/icons/definedShunt.png differ diff --git a/Software/PC_Application/LibreVNA-GUI/icons/definedShunt.svg b/Software/PC_Application/LibreVNA-GUI/icons/definedShunt.svg new file mode 100644 index 0000000..0390736 --- /dev/null +++ b/Software/PC_Application/LibreVNA-GUI/icons/definedShunt.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/PC_Application/LibreVNA-GUI/icons/definedThrough.png b/Software/PC_Application/LibreVNA-GUI/icons/definedThrough.png index 71b4182..38be093 100644 Binary files a/Software/PC_Application/LibreVNA-GUI/icons/definedThrough.png and b/Software/PC_Application/LibreVNA-GUI/icons/definedThrough.png differ diff --git a/Software/PC_Application/LibreVNA-GUI/icons/definedThrough.svg b/Software/PC_Application/LibreVNA-GUI/icons/definedThrough.svg index c50ab38..d3f3102 100644 --- a/Software/PC_Application/LibreVNA-GUI/icons/definedThrough.svg +++ b/Software/PC_Application/LibreVNA-GUI/icons/definedThrough.svg @@ -20,6 +20,12 @@ + + + + + + @@ -27,7 +33,7 @@ - + @@ -40,5 +46,13 @@ + + + + + + + +