Fix reference impedance for de-embedding traces
This commit is contained in:
parent
3cf37d17b1
commit
77f73d3e05
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user