Added mixed mode conversion dialog
This commit is contained in:
parent
1a1c9fd345
commit
7d7bd3a44c
@ -0,0 +1,218 @@
|
||||
#include "tracesetselector.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
|
||||
TraceSetSelector::TraceSetSelector(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
model(nullptr)
|
||||
{
|
||||
points = 0;
|
||||
ports = 0;
|
||||
lowerFreq = upperFreq = 0;
|
||||
referenceImpedance = 50.0;
|
||||
freqsSet = false;
|
||||
partialSelectionAllowed = false;
|
||||
|
||||
setLayout(new QGridLayout);
|
||||
setPorts(2);
|
||||
}
|
||||
|
||||
TraceSetSelector::~TraceSetSelector()
|
||||
{
|
||||
blockSignals(true);
|
||||
// this will free all created widgets
|
||||
setPorts(0);
|
||||
blockSignals(false);
|
||||
}
|
||||
|
||||
unsigned int TraceSetSelector::getPorts() const
|
||||
{
|
||||
return ports;
|
||||
}
|
||||
|
||||
void TraceSetSelector::setPorts(unsigned int newPorts)
|
||||
{
|
||||
if(!model) {
|
||||
return;
|
||||
}
|
||||
QGridLayout *layout = static_cast<QGridLayout*>(this->layout());
|
||||
if(newPorts != ports) {
|
||||
ports = newPorts;
|
||||
// remove the previous widgets
|
||||
QLayoutItem *child;
|
||||
while ((child = layout->takeAt(0)) != 0) {
|
||||
delete child->widget();
|
||||
delete child;
|
||||
}
|
||||
cTraces.clear();
|
||||
for(unsigned int i=0;i<ports;i++) {
|
||||
cTraces.push_back(std::vector<QComboBox*>());
|
||||
for(unsigned int j=0;j<ports;j++) {
|
||||
auto l = new QLabel("S"+QString::number(i+1)+QString::number(j+1)+":");
|
||||
auto c = new QComboBox();
|
||||
cTraces[i].push_back(c);
|
||||
connect(c, qOverload<int>(&QComboBox::currentIndexChanged), [=](int) {
|
||||
selectionChanged(c);
|
||||
});
|
||||
layout->addWidget(l, i, j*2);
|
||||
layout->addWidget(c, i, j*2 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
auto availableTraces = model->getTraces();
|
||||
for(unsigned int i=0;i<ports;i++) {
|
||||
for(unsigned int j=0;j<ports;j++) {
|
||||
auto c = cTraces[i][j];
|
||||
c->blockSignals(true);
|
||||
c->clear();
|
||||
// create possible trace selections
|
||||
c->addItem("None");
|
||||
for(auto t : availableTraces) {
|
||||
if(t->getDataType() != Trace::DataType::Frequency) {
|
||||
// can only add frequency traces
|
||||
continue;
|
||||
}
|
||||
if(i == j && !t->isReflection()) {
|
||||
// can not add through measurement at reflection port
|
||||
continue;
|
||||
} else if(i != j && t->isReflection()) {
|
||||
// can not add reflection measurement at through port
|
||||
continue;
|
||||
}
|
||||
c->addItem(t->name(), QVariant::fromValue<Trace*>(t));
|
||||
}
|
||||
c->blockSignals(false);
|
||||
}
|
||||
}
|
||||
emit selectionChanged();
|
||||
}
|
||||
|
||||
bool TraceSetSelector::setTrace(unsigned int destPort, unsigned int srcPort, Trace *t)
|
||||
{
|
||||
if(destPort < 1 || destPort > ports || srcPort < 1 || srcPort > ports) {
|
||||
// invalid port selection
|
||||
return false;
|
||||
}
|
||||
auto c = cTraces[destPort-1][srcPort-1];
|
||||
// find required trace
|
||||
for(unsigned int i=1;i<(unsigned int) c->count();i++) {
|
||||
if(qvariant_cast<Trace*>(c->itemData(i)) == t) {
|
||||
c->setCurrentIndex(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// requested trace not found, unable to set
|
||||
return false;
|
||||
}
|
||||
|
||||
Trace *TraceSetSelector::getTrace(unsigned int destPort, unsigned int srcPort)
|
||||
{
|
||||
if(destPort < 1 || destPort > ports || srcPort < 1 || srcPort > ports) {
|
||||
// invalid port selection
|
||||
return nullptr;
|
||||
}
|
||||
auto c = cTraces[destPort-1][srcPort-1];
|
||||
if(c->currentIndex() == 0) {
|
||||
// no trace selected
|
||||
return nullptr;
|
||||
} else {
|
||||
return qvariant_cast<Trace*>(c->itemData(c->currentIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
bool TraceSetSelector::selectionValid()
|
||||
{
|
||||
for(unsigned int i=1;i<=ports;i++) {
|
||||
for(unsigned int j=1;j<=ports;j++) {
|
||||
auto t = getTrace(i, j);
|
||||
if(!t && !partialSelectionAllowed) {
|
||||
// at least one trace is missing
|
||||
return false;
|
||||
}
|
||||
if(t && partialSelectionAllowed) {
|
||||
// at least one trace is present
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we get here, either:
|
||||
// - all traces are valid and partial selection is not allowed -> whole selection valid
|
||||
// or:
|
||||
// - all traces are invalid and partial selection is allowed -> whole selection invalid
|
||||
return !partialSelectionAllowed;
|
||||
}
|
||||
|
||||
void TraceSetSelector::selectionChanged(QComboBox *c)
|
||||
{
|
||||
if(c->currentIndex() != 0 && !freqsSet) {
|
||||
// the first trace has been selected, extract frequency info
|
||||
Trace *t = qvariant_cast<Trace*>(c->itemData(c->currentIndex()));
|
||||
points = t->size();
|
||||
referenceImpedance = t->getReferenceImpedance();
|
||||
if(points > 0) {
|
||||
lowerFreq = t->minX();
|
||||
upperFreq = t->maxX();
|
||||
}
|
||||
freqsSet = true;
|
||||
// remove all trace options with incompatible frequencies
|
||||
for(auto v1 : cTraces) {
|
||||
for(auto c : v1) {
|
||||
for(int i=1;i<c->count();i++) {
|
||||
Trace *t = qvariant_cast<Trace*>(c->itemData(i));
|
||||
if(t->getReferenceImpedance() != referenceImpedance || t->size() != points || (points > 0 && (t->minX() != lowerFreq || t->maxX() != upperFreq))) {
|
||||
// this trace is not available anymore
|
||||
c->removeItem(i);
|
||||
// decrement to check the next index in the next loop iteration
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(c->currentIndex() == 0 && freqsSet) {
|
||||
// Check if all trace selections are set for none
|
||||
for(auto v1 : cTraces) {
|
||||
for(auto c : v1) {
|
||||
if(c->currentIndex() != 0) {
|
||||
// some trace is still selected, abort
|
||||
emit selectionChanged();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// all traces set for none
|
||||
freqsSet = false;
|
||||
setPorts(ports);
|
||||
}
|
||||
emit selectionChanged();
|
||||
}
|
||||
|
||||
double TraceSetSelector::getReferenceImpedance() const
|
||||
{
|
||||
return referenceImpedance;
|
||||
}
|
||||
|
||||
double TraceSetSelector::getUpperFreq() const
|
||||
{
|
||||
return upperFreq;
|
||||
}
|
||||
|
||||
double TraceSetSelector::getLowerFreq() const
|
||||
{
|
||||
return lowerFreq;
|
||||
}
|
||||
|
||||
unsigned int TraceSetSelector::getPoints() const
|
||||
{
|
||||
return points;
|
||||
}
|
||||
|
||||
void TraceSetSelector::setModel(TraceModel *newModel)
|
||||
{
|
||||
model = newModel;
|
||||
}
|
||||
|
||||
void TraceSetSelector::setPartialSelectionAllowed(bool newPartialSelectionAllowed)
|
||||
{
|
||||
partialSelectionAllowed = newPartialSelectionAllowed;
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
#ifndef TRACESETSELECTOR_H
|
||||
#define TRACESETSELECTOR_H
|
||||
|
||||
#include "Traces/tracemodel.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
namespace Ui {
|
||||
class TraceSetSelector;
|
||||
}
|
||||
|
||||
class TraceSetSelector : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TraceSetSelector(QWidget *parent = nullptr);
|
||||
~TraceSetSelector();
|
||||
|
||||
unsigned int getPorts() const;
|
||||
void setPorts(unsigned int newPorts);
|
||||
|
||||
bool setTrace(unsigned int destPort, unsigned int srcPort, Trace *t);
|
||||
Trace *getTrace(unsigned int destPort, unsigned int srcPort);
|
||||
|
||||
bool selectionValid();
|
||||
|
||||
void setPartialSelectionAllowed(bool newPartialSelectionAllowed);
|
||||
|
||||
void setModel(TraceModel *newModel);
|
||||
|
||||
unsigned int getPoints() const;
|
||||
double getLowerFreq() const;
|
||||
double getUpperFreq() const;
|
||||
double getReferenceImpedance() const;
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
void selectionChanged(QComboBox *c);
|
||||
Ui::TraceSetSelector *ui;
|
||||
TraceModel *model;
|
||||
unsigned int ports;
|
||||
|
||||
std::vector<std::vector<QComboBox*>> cTraces;
|
||||
|
||||
unsigned int points;
|
||||
double lowerFreq, upperFreq;
|
||||
double referenceImpedance;
|
||||
bool freqsSet;
|
||||
|
||||
bool partialSelectionAllowed;
|
||||
};
|
||||
|
||||
#endif // TRACESETSELECTOR_H
|
@ -21,6 +21,7 @@ HEADERS += \
|
||||
CustomWidgets/tilewidget.h \
|
||||
CustomWidgets/toggleswitch.h \
|
||||
CustomWidgets/touchstoneimport.h \
|
||||
CustomWidgets/tracesetselector.h \
|
||||
Device/compounddevice.h \
|
||||
Device/compounddeviceeditdialog.h \
|
||||
Device/device.h \
|
||||
@ -36,6 +37,7 @@ HEADERS += \
|
||||
SpectrumAnalyzer/tracewidgetsa.h \
|
||||
Tools/eseries.h \
|
||||
Tools/impedancematchdialog.h \
|
||||
Tools/mixedmodeconversion.h \
|
||||
Tools/parameters.h \
|
||||
Traces/Marker/marker.h \
|
||||
Traces/Marker/markergroup.h \
|
||||
@ -167,6 +169,7 @@ SOURCES += \
|
||||
CustomWidgets/tilewidget.cpp \
|
||||
CustomWidgets/toggleswitch.cpp \
|
||||
CustomWidgets/touchstoneimport.cpp \
|
||||
CustomWidgets/tracesetselector.cpp \
|
||||
Device/compounddevice.cpp \
|
||||
Device/compounddeviceeditdialog.cpp \
|
||||
Device/device.cpp \
|
||||
@ -182,6 +185,7 @@ SOURCES += \
|
||||
SpectrumAnalyzer/tracewidgetsa.cpp \
|
||||
Tools/eseries.cpp \
|
||||
Tools/impedancematchdialog.cpp \
|
||||
Tools/mixedmodeconversion.cpp \
|
||||
Tools/parameters.cpp \
|
||||
Traces/Marker/marker.cpp \
|
||||
Traces/Marker/markergroup.cpp \
|
||||
@ -311,6 +315,7 @@ FORMS += \
|
||||
Device/manualcontroldialog.ui \
|
||||
Generator/signalgenwidget.ui \
|
||||
Tools/impedancematchdialog.ui \
|
||||
Tools/mixedmodeconversion.ui \
|
||||
Traces/Marker/markerwidget.ui \
|
||||
Traces/Math/dftdialog.ui \
|
||||
Traces/Math/dftexplanationwidget.ui \
|
||||
|
@ -0,0 +1,146 @@
|
||||
#include "mixedmodeconversion.h"
|
||||
#include "ui_mixedmodeconversion.h"
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
MixedModeConversion::MixedModeConversion(TraceModel &m, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::MixedModeConversion)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
ui->selector->setModel(&m);
|
||||
ui->selector->setPorts(4);
|
||||
connect(ui->selector, qOverload<>(&TraceSetSelector::selectionChanged), this, &MixedModeConversion::selectionChanged);
|
||||
connect(ui->prefix, &QLineEdit::textChanged, this, &MixedModeConversion::selectionChanged);
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, [=](){
|
||||
emit tracesCreated(traces);
|
||||
accept();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &QDialog::reject);
|
||||
selectionChanged();
|
||||
}
|
||||
|
||||
MixedModeConversion::~MixedModeConversion()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MixedModeConversion::selectionChanged()
|
||||
{
|
||||
for(auto t : traces) {
|
||||
delete t;
|
||||
}
|
||||
traces.clear();
|
||||
class Source {
|
||||
public:
|
||||
Source(TraceSetSelector *sel, QString name) {
|
||||
this->name = name;
|
||||
t = sel->getTrace(name.mid(1, 1).toUInt(), name.mid(2, 1).toUInt());
|
||||
}
|
||||
QString name;
|
||||
Trace *t;
|
||||
};
|
||||
|
||||
std::vector<Source> sources = {
|
||||
Source(ui->selector, "S11"),
|
||||
Source(ui->selector, "S12"),
|
||||
Source(ui->selector, "S13"),
|
||||
Source(ui->selector, "S14"),
|
||||
|
||||
Source(ui->selector, "S21"),
|
||||
Source(ui->selector, "S22"),
|
||||
Source(ui->selector, "S23"),
|
||||
Source(ui->selector, "S24"),
|
||||
|
||||
Source(ui->selector, "S31"),
|
||||
Source(ui->selector, "S32"),
|
||||
Source(ui->selector, "S33"),
|
||||
Source(ui->selector, "S34"),
|
||||
|
||||
Source(ui->selector, "S41"),
|
||||
Source(ui->selector, "S42"),
|
||||
Source(ui->selector, "S43"),
|
||||
Source(ui->selector, "S44"),
|
||||
};
|
||||
|
||||
class Destination {
|
||||
public:
|
||||
Destination(std::vector<Source> sources, QString name, QString formula)
|
||||
{
|
||||
this->name = name;
|
||||
t = new Trace(name);
|
||||
t->fromMath();
|
||||
t->setMathFormula(formula);
|
||||
// is a reflection trace if the last two chars in the name are the same
|
||||
t->setReflection(name[name.size()-1] == name[name.size()-2]);
|
||||
// add math sources
|
||||
int index = 0;
|
||||
while((index = formula.indexOf("S", index)) != -1) {
|
||||
QString source = formula.mid(index, 3);
|
||||
// find the source trace
|
||||
bool sourceSet = false;
|
||||
for(auto s : sources) {
|
||||
if(!s.t) {
|
||||
// not set, unable to use this source
|
||||
continue;
|
||||
}
|
||||
if(s.name == source) {
|
||||
if(t->addMathSource(s.t, s.name)) {
|
||||
// added as source, exit loop
|
||||
sourceSet = true;
|
||||
break;
|
||||
} else {
|
||||
// failed to add
|
||||
delete t;
|
||||
t = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!sourceSet) {
|
||||
// can't find this source
|
||||
delete t;
|
||||
t = nullptr;
|
||||
return;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
QString name;
|
||||
Trace *t;
|
||||
};
|
||||
|
||||
auto prefix = ui->prefix->text();
|
||||
|
||||
std::vector<Destination> destinations = {
|
||||
Destination(sources, prefix+"SDD11", "0.5*(S11-S13-S31+S33)"),
|
||||
Destination(sources, prefix+"SDD12", "0.5*(S12-S14-S32+S34)"),
|
||||
Destination(sources, prefix+"SDD21", "0.5*(S21-S23-S41+S43)"),
|
||||
Destination(sources, prefix+"SDD22", "0.5*(S22-S24-S42+S44)"),
|
||||
|
||||
Destination(sources, prefix+"SDC11", "0.5*(S11+S13-S31+S33)"),
|
||||
Destination(sources, prefix+"SDC12", "0.5*(S12+S14-S32+S34)"),
|
||||
Destination(sources, prefix+"SDC21", "0.5*(S21+S23-S41+S43)"),
|
||||
Destination(sources, prefix+"SDC22", "0.5*(S22+S24-S42+S44)"),
|
||||
|
||||
Destination(sources, prefix+"SCD11", "0.5*(S11-S13+S31-S33)"),
|
||||
Destination(sources, prefix+"SCD12", "0.5*(S12-S14+S32-S34)"),
|
||||
Destination(sources, prefix+"SCD21", "0.5*(S21-S23+S41-S43)"),
|
||||
Destination(sources, prefix+"SCD22", "0.5*(S22-S24+S42-S44)"),
|
||||
|
||||
Destination(sources, prefix+"SCC11", "0.5*(S11+S13+S31+S33)"),
|
||||
Destination(sources, prefix+"SCC12", "0.5*(S12+S14+S32+S34)"),
|
||||
Destination(sources, prefix+"SCC21", "0.5*(S21+S23+S41+S43)"),
|
||||
Destination(sources, prefix+"SCC22", "0.5*(S22+S24+S42+S44)"),
|
||||
};
|
||||
|
||||
ui->list->clear();
|
||||
for(auto d : destinations) {
|
||||
if(d.t) {
|
||||
traces.push_back(d.t);
|
||||
ui->list->addItem(d.name);
|
||||
}
|
||||
}
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(traces.size() > 0);
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#ifndef MIXEDMODECONVERSION_H
|
||||
#define MIXEDMODECONVERSION_H
|
||||
|
||||
#include "Traces/tracemodel.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class MixedModeConversion;
|
||||
}
|
||||
|
||||
class MixedModeConversion : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MixedModeConversion(TraceModel &m, QWidget *parent = nullptr);
|
||||
~MixedModeConversion();
|
||||
|
||||
signals:
|
||||
void tracesCreated(std::vector<Trace*> traces);
|
||||
|
||||
private slots:
|
||||
void selectionChanged();
|
||||
private:
|
||||
Ui::MixedModeConversion *ui;
|
||||
std::vector<Trace*> traces;
|
||||
};
|
||||
|
||||
#endif // MIXEDMODECONVERSION_H
|
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MixedModeConversion</class>
|
||||
<widget class="QDialog" name="MixedModeConversion">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>861</width>
|
||||
<height>360</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Single-ended to Mixed-mode S-parameter conversion setup</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Single-ended source traces</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="TraceSetSelector" name="selector" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Mixed-mode destination traces</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Prefix:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="prefix"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="list"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TraceSetSelector</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>CustomWidgets/tracesetselector.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -9,18 +9,13 @@
|
||||
|
||||
TraceTouchstoneExport::TraceTouchstoneExport(TraceModel &model, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::TraceTouchstoneExport),
|
||||
model(model),
|
||||
ports(0),
|
||||
points(0),
|
||||
lowerFreq(0),
|
||||
upperFreq(0),
|
||||
referenceImpedance(50.0),
|
||||
freqsSet(false)
|
||||
ui(new Ui::TraceTouchstoneExport)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
|
||||
ui->gbTraces->setLayout(new QGridLayout);
|
||||
ui->selector->setModel(&model);
|
||||
ui->selector->setPartialSelectionAllowed(true);
|
||||
connect(ui->selector, qOverload<>(&TraceSetSelector::selectionChanged), this, &TraceTouchstoneExport::selectionChanged);
|
||||
on_sbPorts_valueChanged(ui->sbPorts->value());
|
||||
}
|
||||
|
||||
@ -31,30 +26,7 @@ TraceTouchstoneExport::~TraceTouchstoneExport()
|
||||
|
||||
bool TraceTouchstoneExport::setTrace(int portFrom, int portTo, Trace *t)
|
||||
{
|
||||
if(t->getDataType() != Trace::DataType::Frequency) {
|
||||
// can only add frequency traces
|
||||
return false;
|
||||
}
|
||||
if(portFrom < 0 || portFrom >= ui->sbPorts->value() || portTo < 0 || portTo >= ui->sbPorts->value()) {
|
||||
// invalid port selection
|
||||
return false;
|
||||
}
|
||||
auto c = cTraces[portTo][portFrom];
|
||||
if(t) {
|
||||
for(int i=1;i<c->count();i++) {
|
||||
if(t == qvariant_cast<Trace*>(c->itemData(i))) {
|
||||
// select this trace
|
||||
c->setCurrentIndex(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// requested trace is not an option
|
||||
return false;
|
||||
} else {
|
||||
// select 'none' option
|
||||
c->setCurrentIndex(0);
|
||||
return true;
|
||||
}
|
||||
return ui->selector->setTrace(portTo, portFrom, t);
|
||||
}
|
||||
|
||||
bool TraceTouchstoneExport::setPortNum(int ports)
|
||||
@ -63,6 +35,7 @@ bool TraceTouchstoneExport::setPortNum(int ports)
|
||||
return false;
|
||||
}
|
||||
ui->sbPorts->setValue(ports);
|
||||
ui->selector->setPorts(ports);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -72,17 +45,17 @@ void TraceTouchstoneExport::on_buttonBox_accepted()
|
||||
if(filename.length() > 0) {
|
||||
auto ports = ui->sbPorts->value();
|
||||
auto t = Touchstone(ports);
|
||||
t.setReferenceImpedance(referenceImpedance);
|
||||
t.setReferenceImpedance(ui->selector->getReferenceImpedance());
|
||||
// add trace points to touchstone
|
||||
for(unsigned int s=0;s<points;s++) {
|
||||
for(unsigned int s=0;s<ui->selector->getPoints();s++) {
|
||||
Touchstone::Datapoint tData;
|
||||
for(int i=0;i<ports;i++) {
|
||||
for(int j=0;j<ports;j++) {
|
||||
if(cTraces[i][j]->currentIndex() == 0) {
|
||||
for(int i=1;i<=ports;i++) {
|
||||
for(int j=1;j<=ports;j++) {
|
||||
auto t = ui->selector->getTrace(i, j);
|
||||
if(!t) {
|
||||
// missing trace, set to 0
|
||||
tData.S.push_back(0.0);
|
||||
} else {
|
||||
Trace *t = qvariant_cast<Trace*>(cTraces[i][j]->itemData(cTraces[i][j]->currentIndex()));
|
||||
// extract frequency (will overwrite for each trace but all traces have the same frequency points anyway)
|
||||
tData.frequency = t->sample(s).x;
|
||||
// add S parameter from trace to touchstone
|
||||
@ -113,103 +86,22 @@ void TraceTouchstoneExport::on_buttonBox_accepted()
|
||||
|
||||
void TraceTouchstoneExport::on_sbPorts_valueChanged(int ports)
|
||||
{
|
||||
QGridLayout *layout = static_cast<QGridLayout*>(ui->gbTraces->layout());
|
||||
if((unsigned) ports != this->ports) {
|
||||
this->ports = ports;
|
||||
// remove the previous widgets
|
||||
QLayoutItem *child;
|
||||
while ((child = layout->takeAt(0)) != 0) {
|
||||
delete child->widget();
|
||||
delete child;
|
||||
}
|
||||
cTraces.clear();
|
||||
for(int i=0;i<ports;i++) {
|
||||
cTraces.push_back(std::vector<QComboBox*>());
|
||||
for(int j=0;j<ports;j++) {
|
||||
auto l = new QLabel("S"+QString::number(i+1)+QString::number(j+1)+":");
|
||||
auto c = new QComboBox();
|
||||
cTraces[i].push_back(c);
|
||||
connect(c, qOverload<int>(&QComboBox::currentIndexChanged), [=](int) {
|
||||
selectionChanged(c);
|
||||
});
|
||||
layout->addWidget(l, i, j*2);
|
||||
layout->addWidget(c, i, j*2 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
auto availableTraces = model.getTraces();
|
||||
for(int i=0;i<ports;i++) {
|
||||
for(int j=0;j<ports;j++) {
|
||||
auto c = cTraces[i][j];
|
||||
c->blockSignals(true);
|
||||
c->clear();
|
||||
// create possible trace selections
|
||||
c->addItem("None");
|
||||
for(auto t : availableTraces) {
|
||||
if(t->getDataType() != Trace::DataType::Frequency) {
|
||||
// can only add frequency traces
|
||||
continue;
|
||||
}
|
||||
if(i == j && !t->isReflection()) {
|
||||
// can not add through measurement at reflection port
|
||||
continue;
|
||||
} else if(i != j && t->isReflection()) {
|
||||
// can not add reflection measurement at through port
|
||||
continue;
|
||||
}
|
||||
c->addItem(t->name(), QVariant::fromValue<Trace*>(t));
|
||||
}
|
||||
c->blockSignals(false);
|
||||
}
|
||||
}
|
||||
ui->selector->setPorts(ports);
|
||||
}
|
||||
|
||||
void TraceTouchstoneExport::selectionChanged(QComboBox *w)
|
||||
void TraceTouchstoneExport::selectionChanged()
|
||||
{
|
||||
if(w->currentIndex() != 0 && !freqsSet) {
|
||||
// the first trace has been selected, extract frequency info
|
||||
Trace *t = qvariant_cast<Trace*>(w->itemData(w->currentIndex()));
|
||||
points = t->size();
|
||||
referenceImpedance = t->getReferenceImpedance();
|
||||
ui->points->setText(QString::number(points));
|
||||
if(points > 0) {
|
||||
lowerFreq = t->minX();
|
||||
upperFreq = t->maxX();
|
||||
ui->lowerFreq->setText(QString::number(lowerFreq));
|
||||
ui->upperFreq->setText(QString::number(upperFreq));
|
||||
auto valid = ui->selector->selectionValid();
|
||||
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(valid);
|
||||
if(valid) {
|
||||
ui->points->setText(QString::number(ui->selector->getPoints()));
|
||||
if(ui->selector->getPoints() > 0) {
|
||||
ui->lowerFreq->setText(QString::number(ui->selector->getLowerFreq()));
|
||||
ui->upperFreq->setText(QString::number(ui->selector->getUpperFreq()));
|
||||
}
|
||||
freqsSet = true;
|
||||
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(true);
|
||||
// remove all trace options with incompatible frequencies
|
||||
for(auto v1 : cTraces) {
|
||||
for(auto c : v1) {
|
||||
for(int i=1;i<c->count();i++) {
|
||||
Trace *t = qvariant_cast<Trace*>(c->itemData(i));
|
||||
if(t->getReferenceImpedance() != referenceImpedance || t->size() != points || (points > 0 && (t->minX() != lowerFreq || t->maxX() != upperFreq))) {
|
||||
// this trace is not available anymore
|
||||
c->removeItem(i);
|
||||
// decrement to check the next index in the next loop iteration
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(w->currentIndex() == 0 && freqsSet) {
|
||||
// Check if all trace selections are set for none
|
||||
for(auto v1 : cTraces) {
|
||||
for(auto c : v1) {
|
||||
if(c->currentIndex() != 0) {
|
||||
// some trace is still selected, abort
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// all traces set for none
|
||||
freqsSet = false;
|
||||
} else {
|
||||
ui->points->clear();
|
||||
ui->lowerFreq->clear();
|
||||
ui->upperFreq->clear();
|
||||
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
|
||||
on_sbPorts_valueChanged(ui->sbPorts->value());
|
||||
}
|
||||
}
|
||||
|
@ -24,18 +24,10 @@ public:
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
void on_sbPorts_valueChanged(int ports);
|
||||
void selectionChanged(QComboBox *w);
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
Ui::TraceTouchstoneExport *ui;
|
||||
TraceModel &model;
|
||||
std::vector<std::vector<QComboBox*>> cTraces;
|
||||
|
||||
unsigned int ports;
|
||||
unsigned int points;
|
||||
double lowerFreq, upperFreq;
|
||||
double referenceImpedance;
|
||||
bool freqsSet;
|
||||
};
|
||||
|
||||
#endif // TRACEEXPORTDIALOG_H
|
||||
|
@ -68,6 +68,11 @@
|
||||
<property name="title">
|
||||
<string>Traces</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="TraceSetSelector" name="selector" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -221,6 +226,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TraceSetSelector</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>CustomWidgets/tracesetselector.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
@ -34,7 +34,7 @@ TraceWidgetVNA::TraceWidgetVNA(TraceModel &model, Calibration &cal, Deembedding
|
||||
if(i >= traces.size()) {
|
||||
break;
|
||||
}
|
||||
e->setTrace(i%2, i/2, traces[i]);
|
||||
e->setTrace(i%2+1, i/2+1, traces[i]);
|
||||
}
|
||||
if(AppWindow::showGUI()) {
|
||||
e->show();
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "CustomWidgets/siunitedit.h"
|
||||
#include "Traces/Marker/markerwidget.h"
|
||||
#include "Tools/impedancematchdialog.h"
|
||||
#include "Tools/mixedmodeconversion.h"
|
||||
#include "ui_main.h"
|
||||
#include "Device/firmwareupdatedialog.h"
|
||||
#include "preferences.h"
|
||||
@ -188,6 +189,8 @@ VNA::VNA(AppWindow *window, QString name)
|
||||
actions.insert(toolsMenu->menuAction());
|
||||
auto impedanceMatching = toolsMenu->addAction("Impedance Matching");
|
||||
connect(impedanceMatching, &QAction::triggered, this, &VNA::StartImpedanceMatching);
|
||||
auto mixedMode = toolsMenu->addAction("Mixed Mode Conversion");
|
||||
connect(mixedMode, &QAction::triggered, this, &VNA::StartMixedModeConversion);
|
||||
|
||||
defaultCalMenu = new QMenu("Default Calibration", window);
|
||||
assignDefaultCal = defaultCalMenu->addAction("Assign...");
|
||||
@ -913,6 +916,20 @@ void VNA::StartImpedanceMatching()
|
||||
}
|
||||
}
|
||||
|
||||
void VNA::StartMixedModeConversion()
|
||||
{
|
||||
auto dialog = new MixedModeConversion(traceModel);
|
||||
connect(dialog, &MixedModeConversion::tracesCreated, [=](std::vector<Trace*> traces) {
|
||||
auto d = new TraceImportDialog(traceModel, traces);
|
||||
if(AppWindow::showGUI()) {
|
||||
d->show();
|
||||
}
|
||||
});
|
||||
if(AppWindow::showGUI()) {
|
||||
dialog->show();
|
||||
}
|
||||
}
|
||||
|
||||
void VNA::SetSweepType(SweepType sw)
|
||||
{
|
||||
if(settings.sweepType != sw) {
|
||||
|
@ -81,6 +81,7 @@ public slots:
|
||||
private slots:
|
||||
void NewDatapoint(VirtualDevice::VNAMeasurement m);
|
||||
void StartImpedanceMatching();
|
||||
void StartMixedModeConversion();
|
||||
// Sweep control
|
||||
void SetSweepType(SweepType sw);
|
||||
void SetStartFreq(double freq);
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,82 +0,0 @@
|
||||
{
|
||||
"calkit": {
|
||||
"Description": "TRL test calibration kit",
|
||||
"Manufacturer": "Hugen",
|
||||
"Serialnumber": "-",
|
||||
"standards": [
|
||||
{
|
||||
"params": {
|
||||
"id": 5166523964218309461,
|
||||
"isShort": true,
|
||||
"name": "TRL"
|
||||
},
|
||||
"type": "Reflect"
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"Z0": 50.0,
|
||||
"delay": 0.0,
|
||||
"id": 4725361202400330854,
|
||||
"loss": 0.0,
|
||||
"name": "TRL"
|
||||
},
|
||||
"type": "Through"
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"delay": 1e-09,
|
||||
"id": 10060287735088848795,
|
||||
"name": "TRL"
|
||||
},
|
||||
"type": "Line"
|
||||
}
|
||||
],
|
||||
"version": "1.4.0-b20e5598b"
|
||||
},
|
||||
"device": "205835943750",
|
||||
"measurements": [
|
||||
{
|
||||
"data": {
|
||||
"points": null,
|
||||
"port": 1,
|
||||
"standard": 5166523964218309461,
|
||||
"timestamp": -3600
|
||||
},
|
||||
"type": "Reflect"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"points": null,
|
||||
"port": 1,
|
||||
"standard": 5166523964218309461,
|
||||
"timestamp": -3600
|
||||
},
|
||||
"type": "Reflect"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"points": null,
|
||||
"port1": 1,
|
||||
"port2": 2,
|
||||
"reverseStandard": false,
|
||||
"standard": 4725361202400330854,
|
||||
"timestamp": -3600
|
||||
},
|
||||
"type": "Through"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"points": null,
|
||||
"port1": 1,
|
||||
"port2": 2,
|
||||
"reverseStandard": false,
|
||||
"standard": 10060287735088848795,
|
||||
"timestamp": -3600
|
||||
},
|
||||
"type": "Line"
|
||||
}
|
||||
],
|
||||
"ports": null,
|
||||
"type": "None",
|
||||
"version": "1.4.0-b20e5598b"
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
{
|
||||
"Description": "TRL test calibration kit",
|
||||
"Manufacturer": "Hugen",
|
||||
"Serialnumber": "-",
|
||||
"standards": [
|
||||
{
|
||||
"params": {
|
||||
"id": 5166523964218309461,
|
||||
"isShort": true,
|
||||
"name": "TRL"
|
||||
},
|
||||
"type": "Reflect"
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"Z0": 50.0,
|
||||
"delay": 0.0,
|
||||
"id": 4725361202400330854,
|
||||
"loss": 0.0,
|
||||
"name": "TRL"
|
||||
},
|
||||
"type": "Through"
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"delay": 1e-09,
|
||||
"id": 10060287735088848795,
|
||||
"name": "TRL"
|
||||
},
|
||||
"type": "Line"
|
||||
}
|
||||
],
|
||||
"version": "1.4.0-b20e5598b"
|
||||
}
|
@ -28,6 +28,7 @@ SOURCES += \
|
||||
../LibreVNA-GUI/CustomWidgets/tilewidget.cpp \
|
||||
../LibreVNA-GUI/CustomWidgets/toggleswitch.cpp \
|
||||
../LibreVNA-GUI/CustomWidgets/touchstoneimport.cpp \
|
||||
../LibreVNA-GUI/CustomWidgets/tracesetselector.cpp \
|
||||
../LibreVNA-GUI/Device/compounddevice.cpp \
|
||||
../LibreVNA-GUI/Device/compounddeviceeditdialog.cpp \
|
||||
../LibreVNA-GUI/Device/device.cpp \
|
||||
@ -43,6 +44,7 @@ SOURCES += \
|
||||
../LibreVNA-GUI/SpectrumAnalyzer/tracewidgetsa.cpp \
|
||||
../LibreVNA-GUI/Tools/eseries.cpp \
|
||||
../LibreVNA-GUI/Tools/impedancematchdialog.cpp \
|
||||
../LibreVNA-GUI/Tools/mixedmodeconversion.cpp \
|
||||
../LibreVNA-GUI/Tools/parameters.cpp \
|
||||
../LibreVNA-GUI/Traces/Marker/marker.cpp \
|
||||
../LibreVNA-GUI/Traces/Marker/markergroup.cpp \
|
||||
@ -193,6 +195,7 @@ HEADERS += \
|
||||
../LibreVNA-GUI/CustomWidgets/tilewidget.h \
|
||||
../LibreVNA-GUI/CustomWidgets/toggleswitch.h \
|
||||
../LibreVNA-GUI/CustomWidgets/touchstoneimport.h \
|
||||
../LibreVNA-GUI/CustomWidgets/tracesetselector.h \
|
||||
../LibreVNA-GUI/Device/compounddevice.h \
|
||||
../LibreVNA-GUI/Device/compounddeviceeditdialog.h \
|
||||
../LibreVNA-GUI/Device/device.h \
|
||||
@ -208,6 +211,7 @@ HEADERS += \
|
||||
../LibreVNA-GUI/SpectrumAnalyzer/tracewidgetsa.h \
|
||||
../LibreVNA-GUI/Tools/eseries.h \
|
||||
../LibreVNA-GUI/Tools/impedancematchdialog.h \
|
||||
../LibreVNA-GUI/Tools/mixedmodeconversion.h \
|
||||
../LibreVNA-GUI/Tools/parameters.h \
|
||||
../LibreVNA-GUI/Traces/Marker/marker.h \
|
||||
../LibreVNA-GUI/Traces/Marker/markergroup.h \
|
||||
@ -348,6 +352,7 @@ FORMS += \
|
||||
../LibreVNA-GUI/Device/manualcontroldialog.ui \
|
||||
../LibreVNA-GUI/Generator/signalgenwidget.ui \
|
||||
../LibreVNA-GUI/Tools/impedancematchdialog.ui \
|
||||
../LibreVNA-GUI/Tools/mixedmodeconversion.ui \
|
||||
../LibreVNA-GUI/Traces/Marker/markerwidget.ui \
|
||||
../LibreVNA-GUI/Traces/Math/dftdialog.ui \
|
||||
../LibreVNA-GUI/Traces/Math/dftexplanationwidget.ui \
|
||||
|
Loading…
Reference in New Issue
Block a user