Fix reference impedance for de-embedding traces

This commit is contained in:
Jan Käberich 2022-12-08 00:02:51 +01:00
parent 3cf37d17b1
commit 77f73d3e05
8 changed files with 117 additions and 38 deletions

View File

@ -7,11 +7,11 @@
<x>0</x>
<y>0</y>
<width>597</width>
<height>200</height>
<height>331</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
<string>Manual Calibration</string>
</property>
<property name="modal">
<bool>true</bool>

View File

@ -2,21 +2,27 @@
#include <QFormLayout>
#include <QLabel>
#include <QCheckBox>
#include <QScrollArea>
#include <QEvent>
#include <QScrollBar>
using namespace std;
SparamTraceSelector::SparamTraceSelector(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed)
SparamTraceSelector::SparamTraceSelector(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed, unsigned int editablePorts)
: model(model),
empty_allowed(empty_allowed),
used_ports(used_ports)
used_ports(used_ports),
editablePorts(editablePorts)
{
createGUI();
setInitialChoices();
}
SparamTraceSelector::SparamTraceSelector(const TraceModel &model, std::set<unsigned int> used_ports, bool empty_allowed)
SparamTraceSelector::SparamTraceSelector(const TraceModel &model, std::set<unsigned int> used_ports, bool empty_allowed, unsigned int editablePorts)
: model(model),
empty_allowed(empty_allowed)
empty_allowed(empty_allowed),
editablePorts(editablePorts)
{
// create vector from set
std::copy(used_ports.begin(), used_ports.end(), std::back_inserter(this->used_ports));
@ -113,7 +119,9 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
for(int j=0;j<b->count();j++) {
auto candidate = b->itemText(j);
// check if correct parameter
QString expectedSparam = QString::number(i/used_ports.size()+1)+QString::number(i%used_ports.size()+1);
int port1 = used_ports[i/used_ports.size()];
int port2 = used_ports[i%used_ports.size()];
QString expectedSparam = QString::number(port1)+QString::number(port2);
if(!candidate.endsWith(expectedSparam)) {
// wrong S parameter, skip
continue;
@ -131,7 +139,9 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
}
} else if(cb->currentIndex() == 0 && points > 0) {
emit selectionValid(false);
if(!empty_allowed) {
emit selectionValid(false);
}
// Check if all trace selections are set for none
for(auto c : boxes) {
if(!c->isVisible()) {
@ -150,8 +160,8 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
setInitialChoices();
}
if(empty_allowed) {
// always valid
emit selectionValid(true);
// always valid as soon as at least one trace is selected
emit selectionValid(points > 0);
} else {
// actually need to check
valid = true;
@ -172,8 +182,44 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
void SparamTraceSelector::createGUI()
{
// Create comboboxes
auto layout = new QFormLayout;
setLayout(layout);
qDeleteAll(findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly));
delete layout();
boxes.clear();
auto scroll = new QScrollArea(this);
scroll->installEventFilter(this);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
auto w = new QWidget();
auto boxlayout = new QVBoxLayout();
setLayout(boxlayout);
boxlayout->setContentsMargins(0,0,0,0);
boxlayout->addWidget(scroll);
auto formlayout = new QFormLayout;
w->setLayout(formlayout);
for(unsigned int i=1;i<=editablePorts;i++) {
auto label = new QLabel("Include Port "+QString::number(i)+":");
auto cb = new QCheckBox();
if(std::find(used_ports.begin(), used_ports.end(), i) != used_ports.end()) {
cb->setChecked(true);
}
connect(cb, &QCheckBox::toggled, [=](bool checked){
if(checked) {
// add this port to the vector at the correct position
used_ports.insert(upper_bound(used_ports.begin(), used_ports.end(), i), i);
} else {
// remove port from the vector
used_ports.erase(std::remove(used_ports.begin(), used_ports.end(), i), used_ports.end());
}
QTimer::singleShot(0, [=](){
createGUI();
setInitialChoices();
});
});
formlayout->addRow(label, cb);
}
for(unsigned int i=0;i<used_ports.size();i++) {
for(unsigned int j=0;j<used_ports.size();j++) {
auto label = new QLabel("S"+QString::number(used_ports[i])+QString::number(used_ports[j])+":");
@ -182,7 +228,26 @@ void SparamTraceSelector::createGUI()
traceSelectionChanged(box);
});
boxes.push_back(box);
layout->addRow(label, box);
formlayout->addRow(label, box);
}
}
scroll->setWidget(w);
w->show();
eventFilter(scroll, new QEvent(QEvent::Resize));
}
bool SparamTraceSelector::eventFilter(QObject *watched, QEvent *event)
{
// Make sure that the widget in the scroll area always expands to the scroll area size horizontally (only vertical scrolling)
if(event->type() == QEvent::Resize) {
auto scroll = (QScrollArea*) watched;
auto w = scroll->widget();
auto width = scroll->width();
if(scroll->verticalScrollBar()->isVisible()) {
width -= scroll->verticalScrollBar()->width();
}
w->setFixedWidth(width);
}
return false;
}

View File

@ -13,8 +13,8 @@ class SparamTraceSelector : public QWidget
Q_OBJECT
public:
SparamTraceSelector(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed = false);
SparamTraceSelector(const TraceModel &model, std::set<unsigned int> used_ports, bool empty_allowed = false);
SparamTraceSelector(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed = false, unsigned int editablePorts = 0);
SparamTraceSelector(const TraceModel &model, std::set<unsigned int> used_ports, bool empty_allowed = false, unsigned int editablePorts = 0);
bool isValid();
@ -29,11 +29,14 @@ private:
void traceSelectionChanged(QComboBox *cb);
void createGUI();
bool eventFilter(QObject *watched, QEvent *event) override;
const TraceModel &model;
std::vector<QComboBox*> boxes;
bool empty_allowed;
std::vector<unsigned int> used_ports;
unsigned int editablePorts;
unsigned int points;
double minFreq, maxFreq;
bool valid;

View File

@ -979,6 +979,7 @@ std::vector<VirtualDevice::VNAMeasurement> Trace::assembleDatapoints(std::map<QS
}
d.pointNum = i;
d.frequency = freqs[i];
d.Z0 = impedance;
ret.push_back(d);
}
return ret;

View File

@ -7,7 +7,7 @@ ManualDeembeddingDialog::ManualDeembeddingDialog(const TraceModel &model, Deembe
ui(new Ui::ManualDeembeddingDialog)
{
ui->setupUi(this);
auto traceSelector = new SparamTraceSelector(model, deemb->getAffectedPorts());
auto traceSelector = new SparamTraceSelector(model, deemb->getAffectedPorts(), true, 8);
ui->verticalLayout->insertWidget(1, traceSelector, 1.0);
ui->buttonBox->setEnabled(false);
connect(traceSelector, &SparamTraceSelector::selectionValid, ui->buttonBox, &QDialogButtonBox::setEnabled);

View File

@ -6,12 +6,12 @@
<rect>
<x>0</x>
<y>0</y>
<width>508</width>
<height>168</height>
<width>522</width>
<height>371</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
<string>Manual De-embedding</string>
</property>
<property name="modal">
<bool>true</bool>

View File

@ -51,25 +51,33 @@ void MatchingNetwork::transformDatapoint(VirtualDevice::VNAMeasurement &p)
// at this point the map contains the matching network effect
auto m = matching[p.frequency];
VirtualDevice::VNAMeasurement uncorrected = p;
// correct reflection measurement (in case no two-port measurement is complete
QString name = "S"+QString::number(port)+QString::number(port);
if(uncorrected.measurements.count(name) > 0) {
auto S = Sparam(uncorrected.measurements[name], 0.0, 0.0, 1.0);
auto corrected = Sparam(m.p * ABCDparam(S, p.Z0), p.Z0);
p.measurements[name] = corrected.m11;
}
// handle the rest of the measurements
for(unsigned int i=1;i<=VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;i++) {
for(unsigned int j=i+1;j<=VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;j++) {
// handle the measurements
for(auto &meas : p.measurements) {
QString name = meas.first;
unsigned int i = name.mid(1,1).toUInt();
unsigned int j = name.mid(2,1).toUInt();
if(i == j) {
// reflection measurement
if(i == port) {
auto S = uncorrected.toSparam(i, j);
// the port of the matching network itself
auto S = Sparam(uncorrected.measurements[name], 1.0, 1.0, 0.0);
auto corrected = Sparam(m.p * ABCDparam(S, p.Z0), p.Z0);
p.fromSparam(corrected, i, j);
} else if(j == port) {
auto S = uncorrected.toSparam(i, j);
auto corrected = Sparam(ABCDparam(S, p.Z0) * m.p, p.Z0);
p.fromSparam(corrected, i, j);
p.measurements[name] = corrected.m11;
} else {
// another reflection measurement
try {
auto S = uncorrected.toSparam(i, port);
auto corrected = Sparam(ABCDparam(S, p.Z0) * m.p, p.Z0);
p.fromSparam(corrected, i, port);
} catch (...) {
// missing measurements, nothing can be done
}
}
} else {
// through measurement
// Already handled by reflection measurement (toSparam uses S12/S21 as well)
// and if the corresponding reflection measurement is not available, we can't
// do anything anyway
}
}
}
@ -230,9 +238,11 @@ void MatchingNetwork::addComponentAtPosition(int pos, MatchingComponent *c)
void MatchingNetwork::addComponent(int index, MatchingComponent *c)
{
network.insert(network.begin() + index, 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());
matching.clear();
});
}

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>913</width>
<height>633</height>
<width>902</width>
<height>492</height>
</rect>
</property>
<property name="windowTitle">
@ -79,7 +79,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>891</width>
<width>880</width>
<height>168</height>
</rect>
</property>