Merge branch 'master' into compoundDevice
This commit is contained in:
commit
00ef868671
@ -684,6 +684,9 @@ void Marker::traceDataChanged()
|
||||
void Marker::updateSymbol()
|
||||
{
|
||||
if(isDisplayedMarker()) {
|
||||
auto style = Preferences::getInstance().Marker.symbolStyle;
|
||||
switch(style) {
|
||||
case MarkerSymbolStyle::FilledNumberInside: {
|
||||
constexpr int width = 15, height = 15;
|
||||
symbol = QPixmap(width, height);
|
||||
symbol.fill(Qt::transparent);
|
||||
@ -696,6 +699,36 @@ void Marker::updateSymbol()
|
||||
p.drawConvexPolygon(points, 3);
|
||||
p.setPen(Util::getFontColorFromBackground(traceColor));
|
||||
p.drawText(QRectF(0,0,width, height * 2.0 / 3.0), Qt::AlignCenter, QString::number(number) + suffix);
|
||||
}
|
||||
break;
|
||||
case MarkerSymbolStyle::FilledNumberAbove: {
|
||||
constexpr int width = 15, height = 30;
|
||||
symbol = QPixmap(width, height);
|
||||
symbol.fill(Qt::transparent);
|
||||
QPainter p(&symbol);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
QPointF points[] = {QPointF(0,height/2),QPointF(width,height/2),QPointF(width/2,height)};
|
||||
auto traceColor = parentTrace->color();
|
||||
p.setPen(traceColor);
|
||||
p.setBrush(traceColor);
|
||||
p.drawConvexPolygon(points, 3);
|
||||
p.drawText(QRectF(0,0,width, height * 0.45), Qt::AlignCenter, QString::number(number) + suffix);
|
||||
}
|
||||
break;
|
||||
case MarkerSymbolStyle::EmptyNumberAbove: {
|
||||
constexpr int width = 15, height = 30;
|
||||
symbol = QPixmap(width, height);
|
||||
symbol.fill(Qt::transparent);
|
||||
QPainter p(&symbol);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
QPointF points[] = {QPointF(0,height/2),QPointF(width,height/2),QPointF(width/2,height)};
|
||||
auto traceColor = parentTrace->color();
|
||||
p.setPen(traceColor);
|
||||
p.drawConvexPolygon(points, 3);
|
||||
p.drawText(QRectF(0,0,width, height * 0.45), Qt::AlignCenter, QString::number(number) + suffix);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
symbol = QPixmap(1,1);
|
||||
}
|
||||
|
@ -17,8 +17,34 @@ ImpedanceRenormalization::ImpedanceRenormalization()
|
||||
|
||||
void ImpedanceRenormalization::transformDatapoint(VirtualDevice::VNAMeasurement &p)
|
||||
{
|
||||
//p.S = Sparam(ABCDparam(p.S, p.Z0), impedance);
|
||||
// TODO
|
||||
std::map<QString, std::complex<double>> transformed;
|
||||
int ports = 0;
|
||||
QString name = "S11";
|
||||
while(p.measurements.count(name) > 0) {
|
||||
ports++;
|
||||
name = "S"+QString::number(ports+1)+QString::number(ports+1);
|
||||
}
|
||||
for(auto i=1;i<=ports;i++) {
|
||||
auto S11name = "S"+QString::number(i)+QString::number(i);
|
||||
auto S11 = p.measurements[S11name];
|
||||
transformed[S11name] = Sparam(ABCDparam(Sparam(S11, 0.0, 0.0, 1.0), p.Z0), impedance).m11;
|
||||
for(auto j=i+1;j<=ports;j++) {
|
||||
auto S12name = "S"+QString::number(i)+QString::number(j);
|
||||
auto S21name = "S"+QString::number(j)+QString::number(i);
|
||||
auto S22name = "S"+QString::number(j)+QString::number(j);
|
||||
if(!p.measurements.count(S12name) || !p.measurements.count(S21name) || !p.measurements.count(S22name)) {
|
||||
// not all measurements available, skip this
|
||||
continue;
|
||||
}
|
||||
auto S12 = p.measurements[S12name];
|
||||
auto S21 = p.measurements[S21name];
|
||||
auto S22 = p.measurements[S22name];
|
||||
auto S_t = Sparam(ABCDparam(Sparam(S11, S12, S21, S22), p.Z0), impedance);
|
||||
transformed[S12name] = S_t.m12;
|
||||
transformed[S21name] = S_t.m21;
|
||||
}
|
||||
}
|
||||
p.measurements = transformed;
|
||||
p.Z0 = impedance;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ MatchingNetwork::MatchingNetwork()
|
||||
dragComponent = nullptr;
|
||||
dropComponent = nullptr;
|
||||
addNetwork = true;
|
||||
port = 1;
|
||||
}
|
||||
|
||||
void MatchingNetwork::transformDatapoint(VirtualDevice::VNAMeasurement &p)
|
||||
@ -34,26 +35,40 @@ void MatchingNetwork::transformDatapoint(VirtualDevice::VNAMeasurement &p)
|
||||
// this point is not calculated yet
|
||||
MatchingPoint m;
|
||||
// start with identiy matrix
|
||||
m.p1 = ABCDparam(1.0,0.0,0.0,1.0);
|
||||
for(auto c : p1Network) {
|
||||
m.p1 = m.p1 * c->parameters(p.frequency);
|
||||
}
|
||||
// same for network at port 2
|
||||
m.p2 = ABCDparam(1.0,0.0,0.0,1.0);
|
||||
for(auto c : p2Network) {
|
||||
m.p2 = m.p2 * c->parameters(p.frequency);
|
||||
m.p = ABCDparam(1.0,0.0,0.0,1.0);
|
||||
for(auto c : network) {
|
||||
m.p = m.p * c->parameters(p.frequency);
|
||||
}
|
||||
if(!addNetwork) {
|
||||
// need to remove the effect of the networks, invert matrices
|
||||
m.p1 = m.p1.inverse();
|
||||
m.p2 = m.p2.inverse();
|
||||
// need to remove the effect of the network, invert matrix
|
||||
m.p = m.p.inverse();
|
||||
}
|
||||
matching[p.frequency] = m;
|
||||
}
|
||||
// at this point the map contains the matching network effect
|
||||
auto m = matching[p.frequency];
|
||||
auto corrected = m.p1 * measurement * m.p2;
|
||||
p.fromSparam(Sparam(corrected, p.Z0), 1, 2);
|
||||
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(int i=0;i<VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;i++) {
|
||||
for(int j=i+1;j<VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;j++) {
|
||||
if(i == port) {
|
||||
auto S = uncorrected.toSparam(i, j);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MatchingNetwork::edit()
|
||||
@ -80,6 +95,10 @@ void MatchingNetwork::edit()
|
||||
ui->lParallelL->installEventFilter(this);
|
||||
ui->lParallelR->installEventFilter(this);
|
||||
ui->lDefinedThrough->installEventFilter(this);
|
||||
|
||||
ui->port->setValue(port);
|
||||
ui->port->setMaximum(VirtualDevice::getInfo(VirtualDevice::getConnected()).ports);
|
||||
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
layout->setSpacing(0);
|
||||
layout->addStretch(1);
|
||||
@ -93,26 +112,15 @@ void MatchingNetwork::edit()
|
||||
DUT->setMaximumSize(DUTWidth, 151);
|
||||
DUT->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
DUT->setStyleSheet("image: url(:/icons/DUT.png);");
|
||||
auto p2 = new QWidget();
|
||||
p2->setMinimumSize(portWidth, 151);
|
||||
p2->setMaximumSize(portWidth, 151);
|
||||
p2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
p2->setStyleSheet("image: url(:/icons/port2.png);");
|
||||
|
||||
layout->addWidget(p1);
|
||||
for(auto w : p1Network) {
|
||||
for(auto w : network) {
|
||||
layout->addWidget(w);
|
||||
connect(w, &MatchingComponent::MatchingComponent::valueChanged, [=](){
|
||||
matching.clear();
|
||||
});
|
||||
}
|
||||
layout->addWidget(DUT);
|
||||
for(auto w : p2Network) {
|
||||
layout->addWidget(w);
|
||||
connect(w, &MatchingComponent::MatchingComponent::valueChanged, [=](){
|
||||
matching.clear();
|
||||
});
|
||||
}
|
||||
layout->addWidget(p2);
|
||||
|
||||
layout->addStretch(1);
|
||||
|
||||
@ -129,37 +137,34 @@ void MatchingNetwork::edit()
|
||||
// network changed, need to recalculate matching
|
||||
matching.clear();
|
||||
});
|
||||
connect(ui->port, qOverload<int>(&QSpinBox::valueChanged), [=](){
|
||||
port = ui->port->value();
|
||||
});
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
|
||||
}
|
||||
|
||||
nlohmann::json MatchingNetwork::toJSON()
|
||||
{
|
||||
nlohmann::json j;
|
||||
nlohmann::json jn1, jn2;
|
||||
for(auto c : p1Network) {
|
||||
nlohmann::json jn;
|
||||
for(auto c : network) {
|
||||
nlohmann::json jc;
|
||||
jc["component"] = c->getName().toStdString();
|
||||
jc["params"] = c->toJSON();
|
||||
jn1.push_back(jc);
|
||||
jn.push_back(jc);
|
||||
}
|
||||
for(auto c : p2Network) {
|
||||
nlohmann::json jc;
|
||||
jc["component"] = c->getName().toStdString();
|
||||
jc["params"] = c->toJSON();
|
||||
jn2.push_back(jc);
|
||||
}
|
||||
j["port1"] = jn1;
|
||||
j["port2"] = jn2;
|
||||
j["port"] = port;
|
||||
j["network"] = jn;
|
||||
j["addNetwork"] = addNetwork;
|
||||
return j;
|
||||
}
|
||||
|
||||
void MatchingNetwork::fromJSON(nlohmann::json j)
|
||||
{
|
||||
p1Network.clear();
|
||||
p2Network.clear();
|
||||
if(j.contains("port1")) {
|
||||
for(auto jc : j["port1"]) {
|
||||
network.clear();
|
||||
port = j.value("port", 1);
|
||||
if(j.contains("network")) {
|
||||
for(auto jc : j["network"]) {
|
||||
if(!jc.contains("component")) {
|
||||
continue;
|
||||
}
|
||||
@ -168,20 +173,7 @@ void MatchingNetwork::fromJSON(nlohmann::json j)
|
||||
continue;
|
||||
}
|
||||
c->fromJSON(jc["params"]);
|
||||
p1Network.push_back(c);
|
||||
}
|
||||
}
|
||||
if(j.contains("port2")) {
|
||||
for(auto jc : j["port2"]) {
|
||||
if(!jc.contains("component")) {
|
||||
continue;
|
||||
}
|
||||
auto c = MatchingComponent::createFromName(QString::fromStdString(jc["component"]));
|
||||
if(!c) {
|
||||
continue;
|
||||
}
|
||||
c->fromJSON(jc["params"]);
|
||||
p2Network.push_back(c);
|
||||
network.push_back(c);
|
||||
}
|
||||
}
|
||||
addNetwork = j.value("addNetwork", true);
|
||||
@ -192,15 +184,9 @@ MatchingComponent *MatchingNetwork::componentAtPosition(int pos)
|
||||
{
|
||||
pos -= graph->layout()->itemAt(0)->geometry().width();
|
||||
pos -= portWidth;
|
||||
if(pos > 0 && pos <= (int) p1Network.size() * componentWidth) {
|
||||
if(pos > 0 && pos <= (int) network.size() * componentWidth) {
|
||||
// position is in port 1 network
|
||||
return p1Network[pos / componentWidth];
|
||||
} else if(pos > (int) p1Network.size() * componentWidth + DUTWidth) {
|
||||
pos -= (int) p1Network.size() * componentWidth + DUTWidth;
|
||||
if(pos <= (int) p2Network.size() * componentWidth) {
|
||||
// position is in port 2 network
|
||||
return p2Network[pos / componentWidth];
|
||||
}
|
||||
return network[pos / componentWidth];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -209,28 +195,15 @@ unsigned int MatchingNetwork::findInsertPosition(int xcoord)
|
||||
{
|
||||
xcoord -= graph->layout()->itemAt(0)->geometry().width();
|
||||
xcoord -= portWidth;
|
||||
if(xcoord <= (int) p1Network.size() * componentWidth + DUTWidth/2) {
|
||||
// added in port 1 network
|
||||
int index = (xcoord + componentWidth / 2) / componentWidth;
|
||||
if(index < 0) {
|
||||
index = 0;
|
||||
} else if(index > (int) p1Network.size()) {
|
||||
index = p1Network.size();
|
||||
} else if(index > (int) network.size()) {
|
||||
index = network.size();
|
||||
}
|
||||
// add 2 (first two widgets are always the stretch and port 1 widget)
|
||||
return index + 2;
|
||||
} else {
|
||||
// added in port 2 network
|
||||
xcoord -= (int) p1Network.size() * componentWidth + DUTWidth;
|
||||
int index = (xcoord + componentWidth / 2) / componentWidth;
|
||||
if(index < 0) {
|
||||
index = 0;
|
||||
} else if(index > (int) p2Network.size()) {
|
||||
index = p2Network.size();
|
||||
}
|
||||
// add 3 (same two widgets as in port 1 + DUT) and the size of the port 1 network
|
||||
return index + 3 + p1Network.size();
|
||||
}
|
||||
}
|
||||
|
||||
void MatchingNetwork::addComponentAtPosition(int pos, MatchingComponent *c)
|
||||
@ -242,12 +215,7 @@ void MatchingNetwork::addComponentAtPosition(int pos, MatchingComponent *c)
|
||||
|
||||
// add component to correct matching network
|
||||
index -= 2; // first two widgets are fixed
|
||||
if(index <= p1Network.size()) {
|
||||
addComponent(true, index, c);
|
||||
} else {
|
||||
index -= 1 + p1Network.size();
|
||||
addComponent(false, index, c);
|
||||
}
|
||||
addComponent(index, c);
|
||||
|
||||
// network changed, need to recalculate matching
|
||||
matching.clear();
|
||||
@ -256,22 +224,13 @@ void MatchingNetwork::addComponentAtPosition(int pos, MatchingComponent *c)
|
||||
});
|
||||
}
|
||||
|
||||
void MatchingNetwork::addComponent(bool port1, int index, MatchingComponent *c)
|
||||
void MatchingNetwork::addComponent(int index, MatchingComponent *c)
|
||||
{
|
||||
if(port1) {
|
||||
p1Network.insert(p1Network.begin() + index, c);
|
||||
network.insert(network.begin() + index, c);
|
||||
// remove from list when the component deletes itself
|
||||
connect(c, &MatchingComponent::deleted, [=](){
|
||||
p1Network.erase(remove(p1Network.begin(), p1Network.end(), c), p1Network.end());
|
||||
network.erase(remove(network.begin(), network.end(), c), network.end());
|
||||
});
|
||||
} else {
|
||||
// same procedure for port 2 network
|
||||
p2Network.insert(p2Network.begin() + index, c);
|
||||
// remove from list when the component deletes itself
|
||||
connect(c, &MatchingComponent::deleted, [=](){
|
||||
p2Network.erase(remove(p2Network.begin(), p2Network.end(), c), p2Network.end());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MatchingNetwork::createDragComponent(MatchingComponent *c)
|
||||
@ -326,8 +285,7 @@ bool MatchingNetwork::eventFilter(QObject *object, QEvent *event)
|
||||
// remove and hide component while it is being dragged
|
||||
graph->layout()->removeWidget(dragComponent);
|
||||
dragComponent->hide();
|
||||
p1Network.erase(remove(p1Network.begin(), p1Network.end(), dragComponent), p1Network.end());
|
||||
p2Network.erase(remove(p2Network.begin(), p2Network.end(), dragComponent), p2Network.end());
|
||||
network.erase(remove(network.begin(), network.end(), dragComponent), network.end());
|
||||
graph->update();
|
||||
|
||||
// network changed, need to recalculate matching
|
||||
|
@ -77,11 +77,13 @@ private:
|
||||
MatchingComponent *componentAtPosition(int pos);
|
||||
unsigned int findInsertPosition(int xcoord);
|
||||
void addComponentAtPosition(int pos, MatchingComponent *c);
|
||||
void addComponent(bool port1, int index, MatchingComponent *c);
|
||||
void addComponent(int index, MatchingComponent *c);
|
||||
void createDragComponent(MatchingComponent *c);
|
||||
void updateInsertIndicator(int xcoord);
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
std::vector<MatchingComponent*> p1Network, p2Network;
|
||||
|
||||
std::vector<MatchingComponent*> network;
|
||||
int port;
|
||||
|
||||
QWidget *graph, *insertIndicator;
|
||||
QPoint dragStartPosition;
|
||||
@ -91,7 +93,7 @@ private:
|
||||
|
||||
class MatchingPoint {
|
||||
public:
|
||||
ABCDparam p1, p2;
|
||||
ABCDparam p;
|
||||
};
|
||||
std::map<double, MatchingPoint> matching;
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>772</width>
|
||||
<height>443</height>
|
||||
<width>913</width>
|
||||
<height>633</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -21,6 +21,37 @@
|
||||
</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="port">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
@ -48,7 +79,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>750</width>
|
||||
<width>891</width>
|
||||
<height>168</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -13,50 +13,35 @@ using namespace std;
|
||||
PortExtension::PortExtension()
|
||||
: DeembeddingOption()
|
||||
{
|
||||
port1.enabled = false;
|
||||
port1.frequency = 0;
|
||||
port1.loss = 0;
|
||||
port1.DCloss = 0;
|
||||
port1.delay = 0;
|
||||
port1.velocityFactor = 0.66;
|
||||
port2.enabled = false;
|
||||
port2.frequency = 0;
|
||||
port2.loss = 0;
|
||||
port2.DCloss = 0;
|
||||
port2.delay = 0;
|
||||
port2.velocityFactor = 0.66;
|
||||
ext.frequency = 0;
|
||||
ext.loss = 0;
|
||||
ext.DCloss = 0;
|
||||
ext.delay = 0;
|
||||
ext.velocityFactor = 0.66;
|
||||
|
||||
port = 1;
|
||||
|
||||
kit = nullptr;
|
||||
}
|
||||
|
||||
void PortExtension::transformDatapoint(VirtualDevice::VNAMeasurement &d)
|
||||
{
|
||||
if(port1.enabled || port2.enabled) {
|
||||
if(port1.enabled) {
|
||||
auto phase = -2 * M_PI * port1.delay * d.frequency;
|
||||
auto db_attennuation = port1.DCloss;
|
||||
if(port1.frequency != 0) {
|
||||
db_attennuation += port1.loss * sqrt(d.frequency / port1.frequency);
|
||||
auto phase = -2 * M_PI * ext.delay * d.frequency;
|
||||
auto db_attennuation = ext.DCloss;
|
||||
if(ext.frequency != 0) {
|
||||
db_attennuation += ext.loss * sqrt(d.frequency / ext.frequency);
|
||||
}
|
||||
// convert from db to factor
|
||||
auto att = pow(10.0, -db_attennuation / 20.0);
|
||||
auto correction = polar<double>(att, phase);
|
||||
d.measurements["S11"] /= correction * correction;
|
||||
d.measurements["S21"] /= correction;
|
||||
d.measurements["S12"] /= correction;
|
||||
for(auto &m : d.measurements) {
|
||||
if(m.first.mid(1, 1).toInt() == port) {
|
||||
// selected port is the destination of this S parameter
|
||||
m.second /= correction;
|
||||
}
|
||||
if(port2.enabled) {
|
||||
auto phase = -2 * M_PI * port2.delay * d.frequency;
|
||||
auto db_attennuation = port2.DCloss;
|
||||
if(port2.frequency != 0) {
|
||||
db_attennuation += port2.loss * sqrt(d.frequency / port2.frequency);
|
||||
}
|
||||
// convert from db to factor
|
||||
auto att = pow(10.0, -db_attennuation / 20.0);
|
||||
auto correction = polar<double>(att, phase);
|
||||
d.measurements["S22"] /= correction * correction;
|
||||
d.measurements["S21"] /= correction;
|
||||
d.measurements["S12"] /= correction;
|
||||
if(m.first.mid(2, 1).toInt() == port) {
|
||||
// selected port is the source of this S parameter
|
||||
m.second /= correction;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -73,117 +58,56 @@ void PortExtension::edit()
|
||||
});
|
||||
|
||||
// set initial values
|
||||
ui->P1Enabled->setChecked(port1.enabled);
|
||||
ui->P1Time->setUnit("s");
|
||||
ui->P1Time->setPrefixes("pnum ");
|
||||
ui->P1Distance->setUnit("m");
|
||||
ui->P1Distance->setPrefixes("m ");
|
||||
ui->P1DCloss->setUnit("db");
|
||||
ui->P1Loss->setUnit("db");
|
||||
ui->P1Frequency->setUnit("Hz");
|
||||
ui->P1Frequency->setPrefixes(" kMG");
|
||||
ui->P1Time->setValue(port1.delay);
|
||||
ui->P1Velocity->setValue(port1.velocityFactor);
|
||||
ui->P1Distance->setValue(port1.delay * port1.velocityFactor * c);
|
||||
ui->P1DCloss->setValue(port1.DCloss);
|
||||
ui->P1Loss->setValue(port1.loss);
|
||||
ui->P1Frequency->setValue(port1.frequency);
|
||||
ui->Time->setUnit("s");
|
||||
ui->Time->setPrefixes("pnum ");
|
||||
ui->Distance->setUnit("m");
|
||||
ui->Distance->setPrefixes("m ");
|
||||
ui->DCloss->setUnit("db");
|
||||
ui->Loss->setUnit("db");
|
||||
ui->Frequency->setUnit("Hz");
|
||||
ui->Frequency->setPrefixes(" kMG");
|
||||
ui->Time->setValue(ext.delay);
|
||||
ui->Velocity->setValue(ext.velocityFactor);
|
||||
ui->Distance->setValue(ext.delay * ext.velocityFactor * c);
|
||||
ui->DCloss->setValue(ext.DCloss);
|
||||
ui->Loss->setValue(ext.loss);
|
||||
ui->Frequency->setValue(ext.frequency);
|
||||
if(!kit) {
|
||||
ui->P1calkit->setEnabled(false);
|
||||
}
|
||||
|
||||
ui->P2Enabled->setChecked(port2.enabled);
|
||||
ui->P2Time->setUnit("s");
|
||||
ui->P2Time->setPrefixes("pnum ");
|
||||
ui->P2Distance->setUnit("m");
|
||||
ui->P2Distance->setPrefixes("m ");
|
||||
ui->P2DCloss->setUnit("db");
|
||||
ui->P2Loss->setUnit("db");
|
||||
ui->P2Frequency->setUnit("Hz");
|
||||
ui->P2Frequency->setPrefixes(" kMG");
|
||||
ui->P2Time->setValue(port2.delay);
|
||||
ui->P2Velocity->setValue(port2.velocityFactor);
|
||||
ui->P2Distance->setValue(port2.delay * port2.velocityFactor * c);
|
||||
ui->P2DCloss->setValue(port2.DCloss);
|
||||
ui->P2Loss->setValue(port2.loss);
|
||||
ui->P2Frequency->setValue(port2.frequency);
|
||||
if(!kit) {
|
||||
ui->P2calkit->setEnabled(false);
|
||||
ui->calkit->setEnabled(false);
|
||||
}
|
||||
|
||||
auto updateValuesFromUI = [=](){
|
||||
port1.delay = ui->P1Time->value();
|
||||
port1.velocityFactor = ui->P1Velocity->value();
|
||||
port1.DCloss = ui->P1DCloss->value();
|
||||
port1.loss = ui->P1Loss->value();
|
||||
port1.frequency = ui->P1Frequency->value();
|
||||
port2.delay = ui->P2Time->value();
|
||||
port2.velocityFactor = ui->P2Velocity->value();
|
||||
port2.DCloss = ui->P2DCloss->value();
|
||||
port2.loss = ui->P2Loss->value();
|
||||
port2.frequency = ui->P2Frequency->value();
|
||||
ext.delay = ui->Time->value();
|
||||
ext.velocityFactor = ui->Velocity->value();
|
||||
ext.DCloss = ui->DCloss->value();
|
||||
ext.loss = ui->Loss->value();
|
||||
ext.frequency = ui->Frequency->value();
|
||||
};
|
||||
|
||||
connect(ui->P1Enabled, &QCheckBox::toggled, [=](bool enabled) {
|
||||
port1.enabled = enabled;
|
||||
});
|
||||
// connections to link delay and distance
|
||||
connect(ui->P1Time, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
ui->P1Distance->setValueQuiet(newval * ui->P1Velocity->value() * c);
|
||||
connect(ui->Time, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
ui->Distance->setValueQuiet(newval * ui->Velocity->value() * c);
|
||||
updateValuesFromUI();
|
||||
});
|
||||
connect(ui->P1Distance, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
ui->P1Time->setValueQuiet(newval / (ui->P1Velocity->value() * c));
|
||||
connect(ui->Distance, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
ui->Time->setValueQuiet(newval / (ui->Velocity->value() * c));
|
||||
updateValuesFromUI();
|
||||
});
|
||||
connect(ui->P1Velocity, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
ui->P1Time->setValueQuiet(ui->P1Distance->value() / (newval * c));
|
||||
connect(ui->Velocity, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
ui->Time->setValueQuiet(ui->Distance->value() / (newval * c));
|
||||
updateValuesFromUI();
|
||||
});
|
||||
connect(ui->P1DCloss, &SIUnitEdit::valueChanged, updateValuesFromUI);
|
||||
connect(ui->P1Loss, &SIUnitEdit::valueChanged, updateValuesFromUI);
|
||||
connect(ui->P1Frequency, &SIUnitEdit::valueChanged, updateValuesFromUI);
|
||||
connect(ui->P1short, &QPushButton::pressed, [=](){
|
||||
connect(ui->DCloss, &SIUnitEdit::valueChanged, updateValuesFromUI);
|
||||
connect(ui->Loss, &SIUnitEdit::valueChanged, updateValuesFromUI);
|
||||
connect(ui->Frequency, &SIUnitEdit::valueChanged, updateValuesFromUI);
|
||||
connect(ui->_short, &QPushButton::pressed, [=](){
|
||||
isOpen = false;
|
||||
isPort1 = true;
|
||||
isIdeal = ui->P1ideal->isChecked();
|
||||
isIdeal = ui->ideal->isChecked();
|
||||
startMeasurement();
|
||||
});
|
||||
connect(ui->P1open, &QPushButton::pressed, [=](){
|
||||
connect(ui->open, &QPushButton::pressed, [=](){
|
||||
isOpen = true;
|
||||
isPort1 = true;
|
||||
isIdeal = ui->P1ideal->isChecked();
|
||||
startMeasurement();
|
||||
});
|
||||
|
||||
connect(ui->P2Enabled, &QCheckBox::toggled, [=](bool enabled) {
|
||||
port2.enabled = enabled;
|
||||
});
|
||||
connect(ui->P2Time, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
ui->P2Distance->setValueQuiet(newval * ui->P2Velocity->value() * c);
|
||||
updateValuesFromUI();
|
||||
});
|
||||
connect(ui->P2Distance, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
ui->P2Time->setValueQuiet(newval / (ui->P2Velocity->value() * c));
|
||||
updateValuesFromUI();
|
||||
});
|
||||
connect(ui->P2Velocity, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
ui->P2Time->setValueQuiet(ui->P2Distance->value() / (newval * c));
|
||||
updateValuesFromUI();
|
||||
});
|
||||
connect(ui->P2DCloss, &SIUnitEdit::valueChanged, updateValuesFromUI);
|
||||
connect(ui->P2Loss, &SIUnitEdit::valueChanged, updateValuesFromUI);
|
||||
connect(ui->P2Frequency, &SIUnitEdit::valueChanged, updateValuesFromUI);
|
||||
connect(ui->P2short, &QPushButton::pressed, [=](){
|
||||
isOpen = false;
|
||||
isPort1 = false;
|
||||
isIdeal = ui->P2ideal->isChecked();
|
||||
startMeasurement();
|
||||
});
|
||||
connect(ui->P2open, &QPushButton::pressed, [=](){
|
||||
isOpen = true;
|
||||
isPort1 = false;
|
||||
isIdeal = ui->P2ideal->isChecked();
|
||||
isIdeal = ui->ideal->isChecked();
|
||||
startMeasurement();
|
||||
});
|
||||
|
||||
@ -203,22 +127,17 @@ void PortExtension::measurementCompleted(std::vector<VirtualDevice::VNAMeasureme
|
||||
double avg_x = 0.0, avg_y = 0.0;
|
||||
for(auto p : m) {
|
||||
// grab correct measurement
|
||||
complex<double> reflection;
|
||||
if(isPort1) {
|
||||
reflection = p.measurements["S11"];
|
||||
} else {
|
||||
reflection = p.measurements["S22"];
|
||||
}
|
||||
QString name = "S"+QString::number(port)+QString::number(port);
|
||||
auto reflection = p.measurements[name];
|
||||
// remove calkit if specified
|
||||
if(!isIdeal) {
|
||||
complex<double> calStandard = 1.0;
|
||||
// TODO
|
||||
// auto standards = kit->toSOLT(p.frequency);
|
||||
// if(isOpen) {
|
||||
// calStandard = standards.Open;
|
||||
// } else {
|
||||
// calStandard = standards.Short;
|
||||
// }
|
||||
auto comp = isOpen ? CalStandard::Virtual::Type::Open : CalStandard::Virtual::Type::Short;
|
||||
for(auto s : kit->getStandards()) {
|
||||
if(s->getType() == comp) {
|
||||
calStandard = static_cast<CalStandard::OnePort*>(s)->toS11(p.frequency);
|
||||
}
|
||||
}
|
||||
// remove effect of calibration standard
|
||||
reflection /= calStandard;
|
||||
}
|
||||
@ -266,23 +185,16 @@ void PortExtension::measurementCompleted(std::vector<VirtualDevice::VNAMeasureme
|
||||
double DCloss = -alpha / 2;
|
||||
double loss = -beta / 2;
|
||||
double freq = m.back().frequency;
|
||||
if(isPort1) {
|
||||
ui->P1Time->setValue(delay);
|
||||
ui->P1DCloss->setValue(DCloss);
|
||||
ui->P1Loss->setValue(loss);
|
||||
ui->P1Frequency->setValue(freq);
|
||||
} else {
|
||||
ui->P2Time->setValue(delay);
|
||||
ui->P2DCloss->setValue(DCloss);
|
||||
ui->P2Loss->setValue(loss);
|
||||
ui->P2Frequency->setValue(freq);
|
||||
}
|
||||
ui->Time->setValue(delay);
|
||||
ui->DCloss->setValue(DCloss);
|
||||
ui->Loss->setValue(loss);
|
||||
ui->Frequency->setValue(freq);
|
||||
}
|
||||
}
|
||||
|
||||
void PortExtension::startMeasurement()
|
||||
{
|
||||
emit triggerMeasurement(isPort1, false, false, !isPort1);
|
||||
emit triggerMeasurement();
|
||||
}
|
||||
|
||||
void PortExtension::setCalkit(Calkit *kit)
|
||||
@ -293,35 +205,28 @@ void PortExtension::setCalkit(Calkit *kit)
|
||||
nlohmann::json PortExtension::toJSON()
|
||||
{
|
||||
nlohmann::json j;
|
||||
for(int i=0;i<2;i++) {
|
||||
auto ext = i == 0 ? port1 : port2;
|
||||
nlohmann::json je;
|
||||
je["enabled"] = ext.enabled;
|
||||
je["delay"] = ext.delay;
|
||||
je["velocityFactor"] = ext.velocityFactor;
|
||||
je["DCloss"] = ext.DCloss;
|
||||
je["loss"] = ext.loss;
|
||||
je["frequency"] = ext.frequency;
|
||||
j.push_back(je);
|
||||
}
|
||||
j["port"] = port;
|
||||
j["delay"] = ext.delay;
|
||||
j["velocityFactor"] = ext.velocityFactor;
|
||||
j["DCloss"] = ext.DCloss;
|
||||
j["loss"] = ext.loss;
|
||||
j["frequency"] = ext.frequency;
|
||||
return j;
|
||||
}
|
||||
|
||||
void PortExtension::fromJSON(nlohmann::json j)
|
||||
{
|
||||
for(int i=0;i<2;i++) {
|
||||
Extension ext;
|
||||
nlohmann::json je = j[i];
|
||||
ext.enabled = je.value("enabled", false);
|
||||
ext.delay = je.value("delay", 0.0);
|
||||
ext.velocityFactor = je.value("velocityFactor", 0.66);
|
||||
ext.DCloss = je.value("DCloss", 0.0);
|
||||
ext.loss = je.value("loss", 0.0);
|
||||
ext.frequency = je.value("frequency", 6000000000);
|
||||
if(i==0) {
|
||||
port1 = ext;
|
||||
nlohmann::json jfrom;
|
||||
if(j.contains("port")) {
|
||||
// new format
|
||||
jfrom = j;
|
||||
} else {
|
||||
port2 = ext;
|
||||
}
|
||||
jfrom = j[0];
|
||||
port = 1;
|
||||
}
|
||||
ext.delay = jfrom.value("delay", 0.0);
|
||||
ext.velocityFactor = jfrom.value("velocityFactor", 0.66);
|
||||
ext.DCloss = jfrom.value("DCloss", 0.0);
|
||||
ext.loss = jfrom.value("loss", 0.0);
|
||||
ext.frequency = jfrom.value("frequency", 6000000000);
|
||||
}
|
||||
|
@ -31,18 +31,17 @@ private:
|
||||
void startMeasurement();
|
||||
class Extension {
|
||||
public:
|
||||
bool enabled;
|
||||
double delay;
|
||||
double velocityFactor;
|
||||
double DCloss;
|
||||
double loss;
|
||||
double frequency;
|
||||
};
|
||||
Extension port1, port2;
|
||||
Extension ext;
|
||||
|
||||
// status variables for automatic measurements
|
||||
Calkit *kit;
|
||||
bool isPort1;
|
||||
int port;
|
||||
bool isOpen;
|
||||
bool isIdeal;
|
||||
|
||||
|
@ -9,8 +9,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>318</width>
|
||||
<height>505</height>
|
||||
<width>312</width>
|
||||
<height>459</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -21,22 +21,23 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Port 1</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="P1Enabled">
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Enabled</string>
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="port">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
@ -51,7 +52,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="SIUnitEdit" name="P1Distance"/>
|
||||
<widget class="SIUnitEdit" name="Distance"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
@ -61,7 +62,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="P1Time"/>
|
||||
<widget class="SIUnitEdit" name="Time"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
@ -71,7 +72,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="SIUnitEdit" name="P1Velocity"/>
|
||||
<widget class="SIUnitEdit" name="Velocity"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -92,7 +93,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SIUnitEdit" name="P1DCloss"/>
|
||||
<widget class="SIUnitEdit" name="DCloss"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
@ -112,7 +113,7 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="SIUnitEdit" name="P1Loss"/>
|
||||
<widget class="SIUnitEdit" name="Loss"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
@ -122,7 +123,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SIUnitEdit" name="P1Frequency"/>
|
||||
<widget class="SIUnitEdit" name="Frequency"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
@ -136,7 +137,7 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="P1ideal">
|
||||
<widget class="QRadioButton" name="ideal">
|
||||
<property name="text">
|
||||
<string>Assume ideal open/short</string>
|
||||
</property>
|
||||
@ -146,7 +147,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="P1calkit">
|
||||
<widget class="QRadioButton" name="calkit">
|
||||
<property name="text">
|
||||
<string>Use definition from calibration kit</string>
|
||||
</property>
|
||||
@ -155,14 +156,14 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="P1short">
|
||||
<widget class="QPushButton" name="_short">
|
||||
<property name="text">
|
||||
<string>Measure short</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="P1open">
|
||||
<widget class="QPushButton" name="open">
|
||||
<property name="text">
|
||||
<string>Measure open</string>
|
||||
</property>
|
||||
@ -173,160 +174,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Port 2</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="P2Enabled">
|
||||
<property name="text">
|
||||
<string>Enabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Delay</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Distance:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="SIUnitEdit" name="P2Distance"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Time:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="P2Time"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Velocity Factor:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="SIUnitEdit" name="P2Velocity"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Loss</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>At DC:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SIUnitEdit" name="P2DCloss"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="SIUnitEdit" name="P2Loss"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>at</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SIUnitEdit" name="P2Frequency"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Determine automatically</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="P2ideal">
|
||||
<property name="text">
|
||||
<string>Assume ideal open/short</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="P2calkit">
|
||||
<property name="text">
|
||||
<string>Use definition from calibration kit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="P2short">
|
||||
<property name="text">
|
||||
<string>Measure short</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="P2open">
|
||||
<property name="text">
|
||||
<string>Measure open</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
|
@ -13,13 +13,15 @@ using namespace std;
|
||||
TwoThru::TwoThru()
|
||||
{
|
||||
Z0 = 50.0;
|
||||
port1 = 1;
|
||||
port2 = 2;
|
||||
}
|
||||
|
||||
void TwoThru::transformDatapoint(VirtualDevice::VNAMeasurement &p)
|
||||
{
|
||||
// correct measurement
|
||||
if(points.size() > 0) {
|
||||
Tparam meas(p.toSparam(1,2));
|
||||
Tparam meas(p.toSparam(port1,port2));
|
||||
|
||||
Tparam inv1, inv2;
|
||||
if(p.frequency < points.front().freq) {
|
||||
@ -49,7 +51,7 @@ void TwoThru::transformDatapoint(VirtualDevice::VNAMeasurement &p)
|
||||
// perform correction
|
||||
Tparam corrected = inv1*meas*inv2;
|
||||
// transform back into S parameters
|
||||
p.fromSparam(Sparam(corrected), 1, 2);
|
||||
p.fromSparam(Sparam(corrected), port1, port2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,6 +127,27 @@ void TwoThru::edit()
|
||||
ui->Z0->setVisible(false);
|
||||
ui->lZ0->setVisible(false);
|
||||
|
||||
ui->port1->setValue(port1);
|
||||
ui->port1->setMaximum(VirtualDevice::getInfo(VirtualDevice::getConnected()).ports);
|
||||
ui->port2->setValue(port2);
|
||||
ui->port2->setMaximum(VirtualDevice::getInfo(VirtualDevice::getConnected()).ports);
|
||||
|
||||
auto portChanged = [=](){
|
||||
port1 = ui->port1->value();
|
||||
port2 = ui->port2->value();
|
||||
// clear all points
|
||||
points.clear();
|
||||
measurements2xthru.clear();
|
||||
measurementsDUT.clear();
|
||||
// enable taking of new measurements only if ports are different
|
||||
ui->bMeasure->setEnabled(port1 != port2);
|
||||
ui->bMeasureDUT->setEnabled(port1 != port2);
|
||||
updateGUI();
|
||||
};
|
||||
|
||||
connect(ui->port1, qOverload<int>(&QSpinBox::valueChanged), portChanged);
|
||||
connect(ui->port2, qOverload<int>(&QSpinBox::valueChanged), portChanged);
|
||||
|
||||
connect(ui->bMeasure, &QPushButton::clicked, [=](){
|
||||
measuringDUT = false;
|
||||
measuring2xthru = true;
|
||||
@ -168,6 +191,8 @@ void TwoThru::edit()
|
||||
nlohmann::json TwoThru::toJSON()
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["port1"] = port1;
|
||||
j["port2"] = port2;
|
||||
for(auto p : points) {
|
||||
nlohmann::json jp;
|
||||
jp["frequency"] = p.freq;
|
||||
@ -194,6 +219,8 @@ nlohmann::json TwoThru::toJSON()
|
||||
|
||||
void TwoThru::fromJSON(nlohmann::json j)
|
||||
{
|
||||
port1 = j.value("port1", 1);
|
||||
port2 = j.value("port2", 2);
|
||||
points.clear();
|
||||
for(auto jp : j) {
|
||||
Point p;
|
||||
@ -229,10 +256,11 @@ std::vector<TwoThru::Point> TwoThru::calculateErrorBoxes(std::vector<VirtualDevi
|
||||
// ignore possible DC point
|
||||
continue;
|
||||
}
|
||||
S11.push_back(m.measurements["S11"]);
|
||||
S12.push_back(m.measurements["S12"]);
|
||||
S21.push_back(m.measurements["S21"]);
|
||||
S22.push_back(m.measurements["S22"]);
|
||||
auto S = m.toSparam(port1, port2);
|
||||
S11.push_back(S.m11);
|
||||
S12.push_back(S.m12);
|
||||
S21.push_back(S.m21);
|
||||
S22.push_back(S.m22);
|
||||
f.push_back(m.frequency);
|
||||
}
|
||||
auto n = f.size();
|
||||
|
@ -33,12 +33,13 @@ private:
|
||||
};
|
||||
|
||||
static std::vector<VirtualDevice::VNAMeasurement> interpolateEvenFrequencySteps(std::vector<VirtualDevice::VNAMeasurement> input);
|
||||
static std::vector<Point> calculateErrorBoxes(std::vector<VirtualDevice::VNAMeasurement> data_2xthru);
|
||||
static std::vector<Point> calculateErrorBoxes(std::vector<VirtualDevice::VNAMeasurement> data_2xthru, std::vector<VirtualDevice::VNAMeasurement> data_fix_dut_fix, double z0);
|
||||
std::vector<Point> calculateErrorBoxes(std::vector<VirtualDevice::VNAMeasurement> data_2xthru);
|
||||
std::vector<Point> calculateErrorBoxes(std::vector<VirtualDevice::VNAMeasurement> data_2xthru, std::vector<VirtualDevice::VNAMeasurement> data_fix_dut_fix, double z0);
|
||||
|
||||
std::vector<VirtualDevice::VNAMeasurement> measurements2xthru;
|
||||
std::vector<VirtualDevice::VNAMeasurement> measurementsDUT;
|
||||
double Z0;
|
||||
int port1, port2;
|
||||
std::vector<Point> points;
|
||||
bool measuring2xthru;
|
||||
bool measuringDUT;
|
||||
|
@ -9,8 +9,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>701</width>
|
||||
<height>465</height>
|
||||
<width>732</width>
|
||||
<height>520</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -19,7 +19,7 @@
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,0,0">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
@ -51,6 +51,56 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Configuration</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>2xthru is between ports</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="port1">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>and</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="port2">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
|
@ -1,11 +1,14 @@
|
||||
#include "appwindow.h"
|
||||
#include <QtWidgets/QApplication>
|
||||
#include "Device/device.h"
|
||||
#include "Device/virtualdevice.h"
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "Tools/parameters.h"
|
||||
#include <complex>
|
||||
using namespace std;
|
||||
|
||||
static QApplication *app;
|
||||
static AppWindow *window;
|
||||
|
||||
@ -21,9 +24,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
qSetMessagePattern("%{time process}: [%{type}] %{message}");
|
||||
|
||||
Device::RegisterTypes();
|
||||
VirtualDevice::RegisterTypes();
|
||||
|
||||
app = new QApplication(argc, argv);
|
||||
QCoreApplication::setOrganizationName("LibreVNA");
|
||||
QCoreApplication::setApplicationName("LibreVNA-GUI");
|
||||
@ -31,6 +31,34 @@ int main(int argc, char *argv[]) {
|
||||
QCoreApplication::setApplicationVersion(window->getAppVersion() + "-" +
|
||||
window->getAppGitHash().left(9));
|
||||
|
||||
Device::RegisterTypes();
|
||||
|
||||
auto S11 = complex<double>(-0.5, 0.25);
|
||||
auto S22 = complex<double>(0.5, 0.15);
|
||||
auto S33 = complex<double>(0.8, -0.25);
|
||||
|
||||
auto S12 = complex<double>(0.1, 0);
|
||||
auto S21 = complex<double>(0.2, 0.3);
|
||||
|
||||
auto S13 = complex<double>(0.3, -0.2);
|
||||
auto S31 = complex<double>(0.4, 0.4);
|
||||
|
||||
auto S23 = complex<double>(0.5, 0.2);
|
||||
auto S32 = complex<double>(0.6, -0.2);
|
||||
|
||||
auto p12 = Sparam(S11, S12, S21, S22);
|
||||
auto p12_only = Sparam(0.0, S12, 1.0, 0.0);
|
||||
auto p13 = Sparam(S11, S13, S31, S33);
|
||||
auto p23 = Sparam(S22, S23, S32, S33);
|
||||
|
||||
// convert to 75 ohm
|
||||
auto p12_75 = Sparam(ABCDparam(p12, 50.0), 75.0);
|
||||
auto p12_only_75 = Sparam(ABCDparam(p12_only, 50.0), 75.0);
|
||||
auto p13_75 = Sparam(ABCDparam(p12, 50.0), 75.0);
|
||||
auto Zp23_75 = Sparam(ABCDparam(p12, 50.0), 75.0);
|
||||
|
||||
auto p1 = Sparam(S11, 0.0, 0.0, 1.0);
|
||||
auto p1_75 = Sparam(ABCDparam(p12, 50.0), 75.0);
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
signal(SIGINT, tryExitGracefully);
|
||||
|
@ -310,6 +310,7 @@ void PreferencesDialog::setInitialGUIState()
|
||||
ui->MarkerShowAllMarkerData->setChecked(p->Marker.defaultBehavior.showAllData);
|
||||
ui->MarkerInterpolate->setCurrentIndex(p->Marker.interpolatePoints ? 1 : 0);
|
||||
ui->MarkerSortOrder->setCurrentIndex((int) p->Marker.sortOrder);
|
||||
ui->MarkerSymbolStyle->setCurrentIndex((int) p->Marker.symbolStyle);
|
||||
|
||||
ui->SCPIServerEnabled->setChecked(p->SCPIServer.enabled);
|
||||
ui->SCPIServerPort->setValue(p->SCPIServer.port);
|
||||
@ -380,6 +381,7 @@ void PreferencesDialog::updateFromGUI()
|
||||
p->Marker.defaultBehavior.showAllData = ui->MarkerShowAllMarkerData->isChecked();
|
||||
p->Marker.interpolatePoints = ui->MarkerInterpolate->currentIndex() == 1;
|
||||
p->Marker.sortOrder = (MarkerSortOrder) ui->MarkerSortOrder->currentIndex();
|
||||
p->Marker.symbolStyle = (MarkerSymbolStyle) ui->MarkerSymbolStyle->currentIndex();
|
||||
|
||||
p->SCPIServer.enabled = ui->SCPIServerEnabled->isChecked();
|
||||
p->SCPIServer.port = ui->SCPIServerPort->value();
|
||||
|
@ -34,6 +34,14 @@ enum MarkerSortOrder {
|
||||
|
||||
Q_DECLARE_METATYPE(MarkerSortOrder)
|
||||
|
||||
enum MarkerSymbolStyle {
|
||||
FilledNumberInside = 0,
|
||||
FilledNumberAbove = 1,
|
||||
EmptyNumberAbove = 2,
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(MarkerSymbolStyle);
|
||||
|
||||
|
||||
class Preferences : public Savable {
|
||||
public:
|
||||
@ -126,6 +134,7 @@ public:
|
||||
} defaultBehavior;
|
||||
bool interpolatePoints;
|
||||
MarkerSortOrder sortOrder;
|
||||
MarkerSymbolStyle symbolStyle;
|
||||
} Marker;
|
||||
struct {
|
||||
bool enabled;
|
||||
@ -204,6 +213,7 @@ private:
|
||||
{&Marker.defaultBehavior.showAllData, "Marker.defaultBehavior.ShowAllData", false},
|
||||
{&Marker.interpolatePoints, "Marker.interpolatePoints", false},
|
||||
{&Marker.sortOrder, "Marker.sortOrder", MarkerSortOrder::PrefMarkerSortXCoord},
|
||||
{&Marker.symbolStyle, "Marker.symbolStyle", MarkerSymbolStyle::EmptyNumberAbove},
|
||||
{&SCPIServer.enabled, "SCPIServer.enabled", true},
|
||||
{&SCPIServer.port, "SCPIServer.port", 19542},
|
||||
{&compoundDeviceJSON, "compoundDeviceJSON", "[]"},
|
||||
|
@ -84,7 +84,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>687</width>
|
||||
<height>938</height>
|
||||
<height>884</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
@ -103,7 +103,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="Startup">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
@ -1286,6 +1286,32 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_45">
|
||||
<property name="text">
|
||||
<string>Symbol Style:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="MarkerSymbolStyle">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Filled triangle - Marker number inside</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Filled triangle - Marker number above</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Empty triangle - Marker number above</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
Loading…
Reference in New Issue
Block a user