Proof-of-concept TDR measurements
This commit is contained in:
parent
d313988bfd
commit
e68a9abffe
@ -19,10 +19,9 @@ HEADERS += \
|
|||||||
SpectrumAnalyzer/spectrumanalyzer.h \
|
SpectrumAnalyzer/spectrumanalyzer.h \
|
||||||
Tools/eseries.h \
|
Tools/eseries.h \
|
||||||
Tools/impedancematchdialog.h \
|
Tools/impedancematchdialog.h \
|
||||||
Traces/bodeplotaxisdialog.h \
|
Traces/fftcomplex.h \
|
||||||
Traces/markerwidget.h \
|
Traces/markerwidget.h \
|
||||||
Traces/trace.h \
|
Traces/trace.h \
|
||||||
Traces/tracebodeplot.h \
|
|
||||||
Traces/traceeditdialog.h \
|
Traces/traceeditdialog.h \
|
||||||
Traces/traceexportdialog.h \
|
Traces/traceexportdialog.h \
|
||||||
Traces/traceimportdialog.h \
|
Traces/traceimportdialog.h \
|
||||||
@ -32,6 +31,8 @@ HEADERS += \
|
|||||||
Traces/traceplot.h \
|
Traces/traceplot.h \
|
||||||
Traces/tracesmithchart.h \
|
Traces/tracesmithchart.h \
|
||||||
Traces/tracewidget.h \
|
Traces/tracewidget.h \
|
||||||
|
Traces/tracexyplot.h \
|
||||||
|
Traces/xyplotaxisdialog.h \
|
||||||
VNA/vna.h \
|
VNA/vna.h \
|
||||||
appwindow.h \
|
appwindow.h \
|
||||||
averaging.h \
|
averaging.h \
|
||||||
@ -63,10 +64,9 @@ SOURCES += \
|
|||||||
SpectrumAnalyzer/spectrumanalyzer.cpp \
|
SpectrumAnalyzer/spectrumanalyzer.cpp \
|
||||||
Tools/eseries.cpp \
|
Tools/eseries.cpp \
|
||||||
Tools/impedancematchdialog.cpp \
|
Tools/impedancematchdialog.cpp \
|
||||||
Traces/bodeplotaxisdialog.cpp \
|
Traces/fftcomplex.cpp \
|
||||||
Traces/markerwidget.cpp \
|
Traces/markerwidget.cpp \
|
||||||
Traces/trace.cpp \
|
Traces/trace.cpp \
|
||||||
Traces/tracebodeplot.cpp \
|
|
||||||
Traces/traceeditdialog.cpp \
|
Traces/traceeditdialog.cpp \
|
||||||
Traces/traceexportdialog.cpp \
|
Traces/traceexportdialog.cpp \
|
||||||
Traces/traceimportdialog.cpp \
|
Traces/traceimportdialog.cpp \
|
||||||
@ -76,6 +76,8 @@ SOURCES += \
|
|||||||
Traces/traceplot.cpp \
|
Traces/traceplot.cpp \
|
||||||
Traces/tracesmithchart.cpp \
|
Traces/tracesmithchart.cpp \
|
||||||
Traces/tracewidget.cpp \
|
Traces/tracewidget.cpp \
|
||||||
|
Traces/tracexyplot.cpp \
|
||||||
|
Traces/xyplotaxisdialog.cpp \
|
||||||
VNA/vna.cpp \
|
VNA/vna.cpp \
|
||||||
appwindow.cpp \
|
appwindow.cpp \
|
||||||
averaging.cpp \
|
averaging.cpp \
|
||||||
@ -103,12 +105,12 @@ FORMS += \
|
|||||||
Device/manualcontroldialog.ui \
|
Device/manualcontroldialog.ui \
|
||||||
Generator/signalgenwidget.ui \
|
Generator/signalgenwidget.ui \
|
||||||
Tools/impedancematchdialog.ui \
|
Tools/impedancematchdialog.ui \
|
||||||
Traces/bodeplotaxisdialog.ui \
|
|
||||||
Traces/markerwidget.ui \
|
Traces/markerwidget.ui \
|
||||||
Traces/traceeditdialog.ui \
|
Traces/traceeditdialog.ui \
|
||||||
Traces/traceexportdialog.ui \
|
Traces/traceexportdialog.ui \
|
||||||
Traces/traceimportdialog.ui \
|
Traces/traceimportdialog.ui \
|
||||||
Traces/tracewidget.ui \
|
Traces/tracewidget.ui \
|
||||||
|
Traces/xyplotaxisdialog.ui \
|
||||||
main.ui \
|
main.ui \
|
||||||
preferencesdialog.ui
|
preferencesdialog.ui
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "tilewidget.h"
|
#include "tilewidget.h"
|
||||||
#include "ui_tilewidget.h"
|
#include "ui_tilewidget.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "Traces/tracebodeplot.h"
|
#include "Traces/tracexyplot.h"
|
||||||
#include "Traces/tracesmithchart.h"
|
#include "Traces/tracesmithchart.h"
|
||||||
|
|
||||||
TileWidget::TileWidget(TraceModel &model, QWidget *parent) :
|
TileWidget::TileWidget(TraceModel &model, QWidget *parent) :
|
||||||
@ -130,7 +130,7 @@ void TileWidget::on_bSmithchart_clicked()
|
|||||||
|
|
||||||
void TileWidget::on_bBodeplot_clicked()
|
void TileWidget::on_bBodeplot_clicked()
|
||||||
{
|
{
|
||||||
setContent(new TraceBodePlot(model));
|
setContent(new TraceXYPlot(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileWidget::traceDeleted(TracePlot *)
|
void TileWidget::traceDeleted(TracePlot *)
|
||||||
|
@ -81,7 +81,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="bBodeplot">
|
<widget class="QPushButton" name="bBodeplot">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bodeplot</string>
|
<string>XY-plot</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "Traces/tracemodel.h"
|
#include "Traces/tracemodel.h"
|
||||||
#include "Traces/tracewidget.h"
|
#include "Traces/tracewidget.h"
|
||||||
#include "Traces/tracesmithchart.h"
|
#include "Traces/tracesmithchart.h"
|
||||||
#include "Traces/tracebodeplot.h"
|
#include "Traces/tracexyplot.h"
|
||||||
#include "Traces/traceimportdialog.h"
|
#include "Traces/traceimportdialog.h"
|
||||||
#include "CustomWidgets/tilewidget.h"
|
#include "CustomWidgets/tilewidget.h"
|
||||||
#include "CustomWidgets/siunitedit.h"
|
#include "CustomWidgets/siunitedit.h"
|
||||||
@ -55,11 +55,11 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window)
|
|||||||
tPort2->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::Port2);
|
tPort2->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::Port2);
|
||||||
traceModel.addTrace(tPort2);
|
traceModel.addTrace(tPort2);
|
||||||
|
|
||||||
auto tracebode = new TraceBodePlot(traceModel);
|
auto tracebode = new TraceXYPlot(traceModel);
|
||||||
tracebode->enableTrace(tPort1, true);
|
tracebode->enableTrace(tPort1, true);
|
||||||
tracebode->enableTrace(tPort2, true);
|
tracebode->enableTrace(tPort2, true);
|
||||||
tracebode->setYAxis(0, TraceBodePlot::YAxisType::Magnitude, false, false, -120,0,10);
|
tracebode->setYAxis(0, TraceXYPlot::YAxisType::Magnitude, false, false, -120,0,10);
|
||||||
tracebode->setYAxis(1, TraceBodePlot::YAxisType::Disabled, false, true, 0,0,1);
|
tracebode->setYAxis(1, TraceXYPlot::YAxisType::Disabled, false, true, 0,0,1);
|
||||||
|
|
||||||
central->setPlot(tracebode);
|
central->setPlot(tracebode);
|
||||||
|
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
#include "bodeplotaxisdialog.h"
|
|
||||||
#include "ui_bodeplotaxisdialog.h"
|
|
||||||
|
|
||||||
BodeplotAxisDialog::BodeplotAxisDialog(TraceBodePlot *plot) :
|
|
||||||
QDialog(nullptr),
|
|
||||||
ui(new Ui::BodeplotAxisDialog),
|
|
||||||
plot(plot)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
// Setup GUI connections
|
|
||||||
connect(ui->Y1type, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
|
|
||||||
ui->Y1log->setEnabled(index != 0);
|
|
||||||
ui->Y1linear->setEnabled(index != 0);
|
|
||||||
ui->Y1auto->setEnabled(index != 0);
|
|
||||||
bool autoRange = ui->Y1auto->isChecked();
|
|
||||||
ui->Y1min->setEnabled(index != 0 && !autoRange);
|
|
||||||
ui->Y1max->setEnabled(index != 0 && !autoRange);
|
|
||||||
ui->Y1divs->setEnabled(index != 0 && !autoRange);
|
|
||||||
auto type = (TraceBodePlot::YAxisType) index;
|
|
||||||
QString unit;
|
|
||||||
switch(type) {
|
|
||||||
case TraceBodePlot::YAxisType::Magnitude: unit = "db"; break;
|
|
||||||
case TraceBodePlot::YAxisType::Phase: unit = "°"; break;
|
|
||||||
case TraceBodePlot::YAxisType::VSWR: unit = ""; break;
|
|
||||||
default: unit = ""; break;
|
|
||||||
}
|
|
||||||
ui->Y1min->setUnit(unit);
|
|
||||||
ui->Y1max->setUnit(unit);
|
|
||||||
ui->Y1divs->setUnit(unit);
|
|
||||||
});
|
|
||||||
connect(ui->Y1auto, &QCheckBox::toggled, [this](bool checked) {
|
|
||||||
ui->Y1min->setEnabled(!checked);
|
|
||||||
ui->Y1max->setEnabled(!checked);
|
|
||||||
ui->Y1divs->setEnabled(!checked);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(ui->Y2type, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
|
|
||||||
ui->Y2log->setEnabled(index != 0);
|
|
||||||
ui->Y2linear->setEnabled(index != 0);
|
|
||||||
ui->Y2auto->setEnabled(index != 0);
|
|
||||||
bool autoRange = ui->Y2auto->isChecked();
|
|
||||||
ui->Y2min->setEnabled(index != 0 && !autoRange);
|
|
||||||
ui->Y2max->setEnabled(index != 0 && !autoRange);
|
|
||||||
ui->Y2divs->setEnabled(index != 0 && !autoRange);
|
|
||||||
auto type = (TraceBodePlot::YAxisType) index;
|
|
||||||
QString unit;
|
|
||||||
switch(type) {
|
|
||||||
case TraceBodePlot::YAxisType::Magnitude: unit = "db"; break;
|
|
||||||
case TraceBodePlot::YAxisType::Phase: unit = "°"; break;
|
|
||||||
case TraceBodePlot::YAxisType::VSWR: unit = ""; break;
|
|
||||||
default: unit = ""; break;
|
|
||||||
}
|
|
||||||
ui->Y2min->setUnit(unit);
|
|
||||||
ui->Y2max->setUnit(unit);
|
|
||||||
ui->Y2divs->setUnit(unit);
|
|
||||||
});
|
|
||||||
connect(ui->Y2auto, &QCheckBox::toggled, [this](bool checked) {
|
|
||||||
ui->Y2min->setEnabled(!checked);
|
|
||||||
ui->Y2max->setEnabled(!checked);
|
|
||||||
ui->Y2divs->setEnabled(!checked);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(ui->Xauto, &QCheckBox::toggled, [this](bool checked) {
|
|
||||||
ui->Xmin->setEnabled(!checked);
|
|
||||||
ui->Xmax->setEnabled(!checked);
|
|
||||||
ui->Xdivs->setEnabled(!checked);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui->Xmin->setUnit("Hz");
|
|
||||||
ui->Xmax->setUnit("Hz");
|
|
||||||
ui->Xdivs->setUnit("Hz");
|
|
||||||
ui->Xmin->setPrefixes(" kMG");
|
|
||||||
ui->Xmax->setPrefixes(" kMG");
|
|
||||||
ui->Xdivs->setPrefixes(" kMG");
|
|
||||||
|
|
||||||
// Fill initial values
|
|
||||||
// assume same order in YAxisType enum as in ComboBox items
|
|
||||||
ui->Y1type->setCurrentIndex((int) plot->YAxis[0].type);
|
|
||||||
if(plot->YAxis[0].log) {
|
|
||||||
ui->Y1log->setChecked(true);
|
|
||||||
} else {
|
|
||||||
ui->Y1linear->setChecked(true);
|
|
||||||
}
|
|
||||||
ui->Y1auto->setChecked(plot->YAxis[0].autorange);
|
|
||||||
ui->Y1min->setValueQuiet(plot->YAxis[0].rangeMin);
|
|
||||||
ui->Y1max->setValueQuiet(plot->YAxis[0].rangeMax);
|
|
||||||
ui->Y1divs->setValueQuiet(plot->YAxis[0].rangeDiv);
|
|
||||||
|
|
||||||
ui->Y2type->setCurrentIndex((int) plot->YAxis[1].type);
|
|
||||||
if(plot->YAxis[1].log) {
|
|
||||||
ui->Y2log->setChecked(true);
|
|
||||||
} else {
|
|
||||||
ui->Y2linear->setChecked(true);
|
|
||||||
}
|
|
||||||
ui->Y2auto->setChecked(plot->YAxis[1].autorange);
|
|
||||||
ui->Y2min->setValueQuiet(plot->YAxis[1].rangeMin);
|
|
||||||
ui->Y2max->setValueQuiet(plot->YAxis[1].rangeMax);
|
|
||||||
ui->Y2divs->setValueQuiet(plot->YAxis[1].rangeDiv);
|
|
||||||
|
|
||||||
ui->Xauto->setChecked(plot->XAxis.autorange);
|
|
||||||
ui->Xmin->setValueQuiet(plot->XAxis.rangeMin);
|
|
||||||
ui->Xmax->setValueQuiet(plot->XAxis.rangeMax);
|
|
||||||
ui->Xdivs->setValueQuiet(plot->XAxis.rangeDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
BodeplotAxisDialog::~BodeplotAxisDialog()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BodeplotAxisDialog::on_buttonBox_accepted()
|
|
||||||
{
|
|
||||||
// set plot values to the ones selected in the dialog
|
|
||||||
plot->setYAxis(0, (TraceBodePlot::YAxisType) ui->Y1type->currentIndex(), ui->Y1log->isChecked(), ui->Y1auto->isChecked(), ui->Y1min->value(), ui->Y1max->value(), ui->Y1divs->value());
|
|
||||||
plot->setYAxis(1, (TraceBodePlot::YAxisType) ui->Y2type->currentIndex(), ui->Y2log->isChecked(), ui->Y2auto->isChecked(), ui->Y2min->value(), ui->Y2max->value(), ui->Y2divs->value());
|
|
||||||
plot->setXAxis(ui->Xauto->isChecked(), ui->Xmin->value(), ui->Xmax->value(), ui->Xdivs->value());
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
#ifndef BODEPLOTAXISDIALOG_H
|
|
||||||
#define BODEPLOTAXISDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include "tracebodeplot.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class BodeplotAxisDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class BodeplotAxisDialog : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit BodeplotAxisDialog(TraceBodePlot *plot);
|
|
||||||
~BodeplotAxisDialog();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_buttonBox_accepted();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::BodeplotAxisDialog *ui;
|
|
||||||
TraceBodePlot *plot;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BODEPLOTAXISDIALOG_H
|
|
@ -1,462 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>BodeplotAxisDialog</class>
|
|
||||||
<widget class="QDialog" name="BodeplotAxisDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>715</width>
|
|
||||||
<height>282</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Axis Setup</string>
|
|
||||||
</property>
|
|
||||||
<property name="modal">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>15</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Primary Y axis</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Type:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QComboBox" name="Y1type">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Disabled</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Magnitude</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Phase</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>VSWR</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="Y1linear">
|
|
||||||
<property name="text">
|
|
||||||
<string>Linear</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="buttonGroup">
|
|
||||||
<string notr="true">Y1group</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="Y1log">
|
|
||||||
<property name="text">
|
|
||||||
<string>Log</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="buttonGroup">
|
|
||||||
<string notr="true">Y1group</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout_2">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Range:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QCheckBox" name="Y1auto">
|
|
||||||
<property name="text">
|
|
||||||
<string>Auto</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Maximum:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="SIUnitEdit" name="Y1max"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Minimum:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="SIUnitEdit" name="Y1min"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Divisions:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="SIUnitEdit" name="Y1divs"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_3">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>15</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Secondary Y axis</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout_3">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string>Type:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QComboBox" name="Y2type">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Disabled</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Magnitude</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Phase</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>VSWR</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_4">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="Y2linear">
|
|
||||||
<property name="text">
|
|
||||||
<string>Linear</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="buttonGroup">
|
|
||||||
<string notr="true">Y2group</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="Y2log">
|
|
||||||
<property name="text">
|
|
||||||
<string>Log</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="buttonGroup">
|
|
||||||
<string notr="true">Y2group</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_5">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout_4">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string>Range:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QCheckBox" name="Y2auto">
|
|
||||||
<property name="text">
|
|
||||||
<string>Auto</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_10">
|
|
||||||
<property name="text">
|
|
||||||
<string>Maximum:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="SIUnitEdit" name="Y2max"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_11">
|
|
||||||
<property name="text">
|
|
||||||
<string>Minimum:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="SIUnitEdit" name="Y2min"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_12">
|
|
||||||
<property name="text">
|
|
||||||
<string>Divisions:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="SIUnitEdit" name="Y2divs"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_6">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_13">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>15</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>X axis</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout_6">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_15">
|
|
||||||
<property name="text">
|
|
||||||
<string>Range:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QCheckBox" name="Xauto">
|
|
||||||
<property name="text">
|
|
||||||
<string>Auto</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_16">
|
|
||||||
<property name="text">
|
|
||||||
<string>Maximum:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="SIUnitEdit" name="Xmax"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_17">
|
|
||||||
<property name="text">
|
|
||||||
<string>Minimum:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="SIUnitEdit" name="Xmin"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_18">
|
|
||||||
<property name="text">
|
|
||||||
<string>Divisions:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="SIUnitEdit" name="Xdivs"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>SIUnitEdit</class>
|
|
||||||
<extends>QLineEdit</extends>
|
|
||||||
<header>CustomWidgets/siunitedit.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>BodeplotAxisDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>BodeplotAxisDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
<buttongroups>
|
|
||||||
<buttongroup name="Y1group"/>
|
|
||||||
<buttongroup name="Y2group"/>
|
|
||||||
</buttongroups>
|
|
||||||
</ui>
|
|
152
Software/PC_Application/Traces/fftcomplex.cpp
Normal file
152
Software/PC_Application/Traces/fftcomplex.cpp
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Free FFT and convolution (C++)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Project Nayuki. (MIT License)
|
||||||
|
* https://www.nayuki.io/page/free-small-fft-in-multiple-languages
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
* - The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
* - The Software is provided "as is", without warranty of any kind, express or
|
||||||
|
* implied, including but not limited to the warranties of merchantability,
|
||||||
|
* fitness for a particular purpose and noninfringement. In no event shall the
|
||||||
|
* authors or copyright holders be liable for any claim, damages or other
|
||||||
|
* liability, whether in an action of contract, tort or otherwise, arising from,
|
||||||
|
* out of or in connection with the Software or the use or other dealings in the
|
||||||
|
* Software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <utility>
|
||||||
|
#include "fftcomplex.h"
|
||||||
|
|
||||||
|
using std::complex;
|
||||||
|
using std::size_t;
|
||||||
|
using std::uintmax_t;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
|
||||||
|
// Private function prototypes
|
||||||
|
static size_t reverseBits(size_t val, int width);
|
||||||
|
|
||||||
|
|
||||||
|
void Fft::transform(vector<complex<double> > &vec, bool inverse) {
|
||||||
|
size_t n = vec.size();
|
||||||
|
if (n == 0)
|
||||||
|
return;
|
||||||
|
else if ((n & (n - 1)) == 0) // Is power of 2
|
||||||
|
transformRadix2(vec, inverse);
|
||||||
|
else // More complicated algorithm for arbitrary sizes
|
||||||
|
transformBluestein(vec, inverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Fft::transformRadix2(vector<complex<double> > &vec, bool inverse) {
|
||||||
|
// Length variables
|
||||||
|
size_t n = vec.size();
|
||||||
|
int levels = 0; // Compute levels = floor(log2(n))
|
||||||
|
for (size_t temp = n; temp > 1U; temp >>= 1)
|
||||||
|
levels++;
|
||||||
|
if (static_cast<size_t>(1U) << levels != n)
|
||||||
|
throw std::domain_error("Length is not a power of 2");
|
||||||
|
|
||||||
|
// Trigonometric table
|
||||||
|
vector<complex<double> > expTable(n / 2);
|
||||||
|
for (size_t i = 0; i < n / 2; i++)
|
||||||
|
expTable[i] = std::polar(1.0, (inverse ? 2 : -2) * M_PI * i / n);
|
||||||
|
|
||||||
|
// Bit-reversed addressing permutation
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
size_t j = reverseBits(i, levels);
|
||||||
|
if (j > i)
|
||||||
|
std::swap(vec[i], vec[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cooley-Tukey decimation-in-time radix-2 FFT
|
||||||
|
for (size_t size = 2; size <= n; size *= 2) {
|
||||||
|
size_t halfsize = size / 2;
|
||||||
|
size_t tablestep = n / size;
|
||||||
|
for (size_t i = 0; i < n; i += size) {
|
||||||
|
for (size_t j = i, k = 0; j < i + halfsize; j++, k += tablestep) {
|
||||||
|
complex<double> temp = vec[j + halfsize] * expTable[k];
|
||||||
|
vec[j + halfsize] = vec[j] - temp;
|
||||||
|
vec[j] += temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (size == n) // Prevent overflow in 'size *= 2'
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Fft::transformBluestein(vector<complex<double> > &vec, bool inverse) {
|
||||||
|
// Find a power-of-2 convolution length m such that m >= n * 2 + 1
|
||||||
|
size_t n = vec.size();
|
||||||
|
size_t m = 1;
|
||||||
|
while (m / 2 <= n) {
|
||||||
|
if (m > SIZE_MAX / 2)
|
||||||
|
throw std::length_error("Vector too large");
|
||||||
|
m *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigonometric table
|
||||||
|
vector<complex<double> > expTable(n);
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
uintmax_t temp = static_cast<uintmax_t>(i) * i;
|
||||||
|
temp %= static_cast<uintmax_t>(n) * 2;
|
||||||
|
double angle = (inverse ? M_PI : -M_PI) * temp / n;
|
||||||
|
expTable[i] = std::polar(1.0, angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary vectors and preprocessing
|
||||||
|
vector<complex<double> > avec(m);
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
avec[i] = vec[i] * expTable[i];
|
||||||
|
vector<complex<double> > bvec(m);
|
||||||
|
bvec[0] = expTable[0];
|
||||||
|
for (size_t i = 1; i < n; i++)
|
||||||
|
bvec[i] = bvec[m - i] = std::conj(expTable[i]);
|
||||||
|
|
||||||
|
// Convolution
|
||||||
|
vector<complex<double> > cvec(m);
|
||||||
|
convolve(avec, bvec, cvec);
|
||||||
|
|
||||||
|
// Postprocessing
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
vec[i] = cvec[i] * expTable[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Fft::convolve(
|
||||||
|
const vector<complex<double> > &xvec,
|
||||||
|
const vector<complex<double> > &yvec,
|
||||||
|
vector<complex<double> > &outvec) {
|
||||||
|
|
||||||
|
size_t n = xvec.size();
|
||||||
|
if (n != yvec.size() || n != outvec.size())
|
||||||
|
throw std::domain_error("Mismatched lengths");
|
||||||
|
vector<complex<double> > xv = xvec;
|
||||||
|
vector<complex<double> > yv = yvec;
|
||||||
|
transform(xv, false);
|
||||||
|
transform(yv, false);
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
xv[i] *= yv[i];
|
||||||
|
transform(xv, true);
|
||||||
|
for (size_t i = 0; i < n; i++) // Scaling (because this FFT implementation omits it)
|
||||||
|
outvec[i] = xv[i] / static_cast<double>(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t reverseBits(size_t val, int width) {
|
||||||
|
size_t result = 0;
|
||||||
|
for (int i = 0; i < width; i++, val >>= 1)
|
||||||
|
result = (result << 1) | (val & 1U);
|
||||||
|
return result;
|
||||||
|
}
|
62
Software/PC_Application/Traces/fftcomplex.h
Normal file
62
Software/PC_Application/Traces/fftcomplex.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Free FFT and convolution (C++)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Project Nayuki. (MIT License)
|
||||||
|
* https://www.nayuki.io/page/free-small-fft-in-multiple-languages
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
* - The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
* - The Software is provided "as is", without warranty of any kind, express or
|
||||||
|
* implied, including but not limited to the warranties of merchantability,
|
||||||
|
* fitness for a particular purpose and noninfringement. In no event shall the
|
||||||
|
* authors or copyright holders be liable for any claim, damages or other
|
||||||
|
* liability, whether in an action of contract, tort or otherwise, arising from,
|
||||||
|
* out of or in connection with the Software or the use or other dealings in the
|
||||||
|
* Software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <complex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Fft {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result back into the vector.
|
||||||
|
* The vector can have any length. This is a wrapper function. The inverse transform does not perform scaling, so it is not a true inverse.
|
||||||
|
*/
|
||||||
|
void transform(std::vector<std::complex<double> > &vec, bool inverse);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result back into the vector.
|
||||||
|
* The vector's length must be a power of 2. Uses the Cooley-Tukey decimation-in-time radix-2 algorithm.
|
||||||
|
*/
|
||||||
|
void transformRadix2(std::vector<std::complex<double> > &vec, bool inverse);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result back into the vector.
|
||||||
|
* The vector can have any length. This requires the convolution function, which in turn requires the radix-2 FFT function.
|
||||||
|
* Uses Bluestein's chirp z-transform algorithm.
|
||||||
|
*/
|
||||||
|
void transformBluestein(std::vector<std::complex<double> > &vec, bool inverse);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Computes the circular convolution of the given complex vectors. Each vector's length must be the same.
|
||||||
|
*/
|
||||||
|
void convolve(
|
||||||
|
const std::vector<std::complex<double> > &xvec,
|
||||||
|
const std::vector<std::complex<double> > &yvec,
|
||||||
|
std::vector<std::complex<double> > &outvec);
|
||||||
|
|
||||||
|
}
|
@ -1,9 +1,12 @@
|
|||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include "fftcomplex.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Trace::Trace(QString name, QColor color, LiveParameter live)
|
Trace::Trace(QString name, QColor color, LiveParameter live)
|
||||||
: _name(name),
|
: tdr_users(0),
|
||||||
|
_name(name),
|
||||||
_color(color),
|
_color(color),
|
||||||
_liveType(LivedataType::Overwrite),
|
_liveType(LivedataType::Overwrite),
|
||||||
_liveParam(live),
|
_liveParam(live),
|
||||||
@ -64,6 +67,12 @@ void Trace::addData(Trace::Data d) {
|
|||||||
}
|
}
|
||||||
emit dataAdded(this, d);
|
emit dataAdded(this, d);
|
||||||
emit dataChanged();
|
emit dataChanged();
|
||||||
|
if(lower == _data.begin()) {
|
||||||
|
// received the first point, which means the last sweep just finished
|
||||||
|
if(tdr_users) {
|
||||||
|
updateTimeDomainData();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Trace::setName(QString name) {
|
void Trace::setName(QString name) {
|
||||||
@ -137,12 +146,79 @@ void Trace::removeMarker(TraceMarker *m)
|
|||||||
markers.erase(m);
|
markers.erase(m);
|
||||||
emit markerRemoved(m);
|
emit markerRemoved(m);
|
||||||
}
|
}
|
||||||
|
//#include <iostream>
|
||||||
|
//#include <chrono>
|
||||||
|
|
||||||
|
void Trace::updateTimeDomainData()
|
||||||
|
{
|
||||||
|
// using namespace std::chrono;
|
||||||
|
// auto starttime = duration_cast< milliseconds >(
|
||||||
|
// system_clock::now().time_since_epoch()
|
||||||
|
// ).count();
|
||||||
|
auto steps = size();
|
||||||
|
if(minFreq() * size() != maxFreq()) {
|
||||||
|
// data is not available with correct frequency spacing, calculate required steps
|
||||||
|
steps = maxFreq() / minFreq();
|
||||||
|
}
|
||||||
|
const double PI = 3.141592653589793238463;
|
||||||
|
// reserve vector for negative frequenies and DC as well
|
||||||
|
vector<complex<double>> frequencyDomain(2*steps + 1);
|
||||||
|
// copy frequencies, use the flipped conjugate for negative part
|
||||||
|
for(unsigned int i = 1;i<=steps;i++) {
|
||||||
|
auto S = getData(minFreq() * i);
|
||||||
|
constexpr double alpha0 = 0.54;
|
||||||
|
auto hamming = alpha0 - (1.0 - alpha0) * -cos(PI * i / steps);
|
||||||
|
S *= hamming;
|
||||||
|
frequencyDomain[2 * steps - i + 1] = conj(S);
|
||||||
|
frequencyDomain[i] = S;
|
||||||
|
}
|
||||||
|
// use simple extrapolation from lowest two points to extract DC value
|
||||||
|
auto abs_DC = 2.0 * abs(frequencyDomain[1]) - abs(frequencyDomain[2]);
|
||||||
|
auto phase_DC = 2.0 * arg(frequencyDomain[1]) - arg(frequencyDomain[2]);
|
||||||
|
frequencyDomain[0] = polar(abs_DC, phase_DC);
|
||||||
|
|
||||||
|
auto fft_bins = frequencyDomain.size();
|
||||||
|
timeDomain.clear();
|
||||||
|
timeDomain.resize(fft_bins);
|
||||||
|
const double fs = 1.0 / (minFreq() * fft_bins);
|
||||||
|
double last_step = 0.0;
|
||||||
|
|
||||||
|
Fft::transform(frequencyDomain, true);
|
||||||
|
for(unsigned int i = 0;i<fft_bins;i++) {
|
||||||
|
TimedomainData t;
|
||||||
|
t.time = fs * i;
|
||||||
|
t.impulseResponse = real(frequencyDomain[i]) / fft_bins;
|
||||||
|
t.stepResponse = last_step;
|
||||||
|
last_step += t.impulseResponse;
|
||||||
|
timeDomain.push_back(t);
|
||||||
|
}
|
||||||
|
// auto duration = duration_cast< milliseconds >(
|
||||||
|
// system_clock::now().time_since_epoch()
|
||||||
|
// ).count() - starttime;
|
||||||
|
// cout << "TDR: " << this << " (took " << duration << "ms)" <<endl;
|
||||||
|
}
|
||||||
|
|
||||||
void Trace::setReflection(bool value)
|
void Trace::setReflection(bool value)
|
||||||
{
|
{
|
||||||
reflection = value;
|
reflection = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Trace::addTDRinterest()
|
||||||
|
{
|
||||||
|
if(tdr_users == 0) {
|
||||||
|
// no recent time domain data available, calculate now
|
||||||
|
updateTimeDomainData();
|
||||||
|
}
|
||||||
|
tdr_users++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Trace::removeTDRinterest()
|
||||||
|
{
|
||||||
|
if(tdr_users > 0) {
|
||||||
|
tdr_users--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Trace::setCalibration(bool value)
|
void Trace::setCalibration(bool value)
|
||||||
{
|
{
|
||||||
calibration = value;
|
calibration = value;
|
||||||
@ -288,7 +364,16 @@ std::complex<double> Trace::getData(double frequency)
|
|||||||
return std::numeric_limits<std::complex<double>>::quiet_NaN();
|
return std::numeric_limits<std::complex<double>>::quiet_NaN();
|
||||||
}
|
}
|
||||||
|
|
||||||
return sample(index(frequency)).S;
|
auto i = index(frequency);
|
||||||
|
if(_data.at(i).frequency == frequency) {
|
||||||
|
return _data[i].S;
|
||||||
|
} else {
|
||||||
|
// no exact frequency match, needs to interpolate
|
||||||
|
auto high = _data[i];
|
||||||
|
auto low = _data[i-1];
|
||||||
|
double alpha = (frequency - low.frequency) / (high.frequency - low.frequency);
|
||||||
|
return low.S * (1 - alpha) + high.S * alpha;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Trace::index(double frequency)
|
int Trace::index(double frequency)
|
||||||
|
@ -21,6 +21,13 @@ public:
|
|||||||
std::complex<double> S;
|
std::complex<double> S;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TimedomainData {
|
||||||
|
public:
|
||||||
|
double time;
|
||||||
|
double impulseResponse;
|
||||||
|
double stepResponse;
|
||||||
|
};
|
||||||
|
|
||||||
enum class LiveParameter {
|
enum class LiveParameter {
|
||||||
S11,
|
S11,
|
||||||
S12,
|
S12,
|
||||||
@ -76,6 +83,14 @@ public:
|
|||||||
void setCalibration(bool value);
|
void setCalibration(bool value);
|
||||||
void setReflection(bool value);
|
void setReflection(bool value);
|
||||||
|
|
||||||
|
// TDR calculation can be ressource intensive, only perform when some other module is interested.
|
||||||
|
// Each interested module should call addTDRinterest(), read the data with getTDR() and finally
|
||||||
|
// call removeTDRinterest() once TDR updates are no longer required.
|
||||||
|
// The data is only updated at the end of a sweep and upon the first addTDRinterest() call.
|
||||||
|
void addTDRinterest();
|
||||||
|
void removeTDRinterest();
|
||||||
|
const std::vector<TimedomainData>& getTDR() { return timeDomain;}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setTouchstoneParameter(int value);
|
void setTouchstoneParameter(int value);
|
||||||
void setTouchstoneFilename(const QString &value);
|
void setTouchstoneFilename(const QString &value);
|
||||||
@ -98,7 +113,11 @@ signals:
|
|||||||
void markerRemoved(TraceMarker *m);
|
void markerRemoved(TraceMarker *m);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateTimeDomainData();
|
||||||
|
void printTimeDomain();
|
||||||
std::vector<Data> _data;
|
std::vector<Data> _data;
|
||||||
|
std::vector<TimedomainData> timeDomain;
|
||||||
|
unsigned int tdr_users;
|
||||||
QString _name;
|
QString _name;
|
||||||
QColor _color;
|
QColor _color;
|
||||||
LivedataType _liveType;
|
LivedataType _liveType;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "tracebodeplot.h"
|
#include "tracexyplot.h"
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include "qwtplotpiecewisecurve.h"
|
#include "qwtplotpiecewisecurve.h"
|
||||||
#include "qwt_series_data.h"
|
#include "qwt_series_data.h"
|
||||||
@ -11,18 +11,26 @@
|
|||||||
#include "tracemarker.h"
|
#include "tracemarker.h"
|
||||||
#include <qwt_symbol.h>
|
#include <qwt_symbol.h>
|
||||||
#include <qwt_picker_machine.h>
|
#include <qwt_picker_machine.h>
|
||||||
#include "bodeplotaxisdialog.h"
|
#include "xyplotaxisdialog.h"
|
||||||
#include <preferences.h>
|
#include <preferences.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
set<TraceBodePlot*> TraceBodePlot::allPlots;
|
set<TraceXYPlot*> TraceXYPlot::allPlots;
|
||||||
|
|
||||||
static double AxisTransformation(TraceBodePlot::YAxisType type, complex<double> data) {
|
const set<TraceXYPlot::YAxisType> TraceXYPlot::YAxisTypes = {TraceXYPlot::YAxisType::Disabled,
|
||||||
|
TraceXYPlot::YAxisType::Magnitude,
|
||||||
|
TraceXYPlot::YAxisType::Phase,
|
||||||
|
TraceXYPlot::YAxisType::VSWR,
|
||||||
|
TraceXYPlot::YAxisType::Impulse,
|
||||||
|
TraceXYPlot::YAxisType::Step,
|
||||||
|
TraceXYPlot::YAxisType::Impedance};
|
||||||
|
|
||||||
|
static double FrequencyAxisTransformation(TraceXYPlot::YAxisType type, complex<double> data) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case TraceBodePlot::YAxisType::Magnitude: return 20*log10(abs(data)); break;
|
case TraceXYPlot::YAxisType::Magnitude: return 20*log10(abs(data)); break;
|
||||||
case TraceBodePlot::YAxisType::Phase: return arg(data) * 180.0 / M_PI; break;
|
case TraceXYPlot::YAxisType::Phase: return arg(data) * 180.0 / M_PI; break;
|
||||||
case TraceBodePlot::YAxisType::VSWR:
|
case TraceXYPlot::YAxisType::VSWR:
|
||||||
if(abs(data) < 1.0) {
|
if(abs(data) < 1.0) {
|
||||||
return (1+abs(data)) / (1-abs(data));
|
return (1+abs(data)) / (1-abs(data));
|
||||||
}
|
}
|
||||||
@ -31,31 +39,79 @@ static double AxisTransformation(TraceBodePlot::YAxisType type, complex<double>
|
|||||||
}
|
}
|
||||||
return numeric_limits<double>::quiet_NaN();
|
return numeric_limits<double>::quiet_NaN();
|
||||||
}
|
}
|
||||||
|
static double TimeAxisTransformation(TraceXYPlot::YAxisType type, Trace *t, int index) {
|
||||||
|
auto timeData = t->getTDR()[index];
|
||||||
|
switch(type) {
|
||||||
|
case TraceXYPlot::YAxisType::Impulse: return timeData.impulseResponse; break;
|
||||||
|
case TraceXYPlot::YAxisType::Step: return timeData.stepResponse; break;
|
||||||
|
case TraceXYPlot::YAxisType::Impedance:
|
||||||
|
if(abs(timeData.stepResponse) < 1.0) {
|
||||||
|
return 50 * (1+timeData.stepResponse) / (1-timeData.stepResponse);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return numeric_limits<double>::quiet_NaN();
|
||||||
|
}
|
||||||
|
|
||||||
template<TraceBodePlot::YAxisType E> class QwtTraceSeries : public QwtSeriesData<QPointF> {
|
class QwtTraceSeries : public QwtSeriesData<QPointF> {
|
||||||
public:
|
public:
|
||||||
QwtTraceSeries(Trace &t)
|
QwtTraceSeries(Trace &t, TraceXYPlot::YAxisType Ytype, TraceXYPlot::XAxisType Xtype)
|
||||||
: QwtSeriesData<QPointF>(),
|
: QwtSeriesData<QPointF>(),
|
||||||
t(t){};
|
Ytype(Ytype),
|
||||||
|
Xtype(Xtype),
|
||||||
|
t(t){}
|
||||||
size_t size() const override {
|
size_t size() const override {
|
||||||
return t.size();
|
switch(Ytype) {
|
||||||
|
case TraceXYPlot::YAxisType::Magnitude:
|
||||||
|
case TraceXYPlot::YAxisType::Phase:
|
||||||
|
case TraceXYPlot::YAxisType::VSWR:
|
||||||
|
return t.size();
|
||||||
|
case TraceXYPlot::YAxisType::Impulse:
|
||||||
|
case TraceXYPlot::YAxisType::Step:
|
||||||
|
case TraceXYPlot::YAxisType::Impedance:
|
||||||
|
return t.getTDR().size();
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
QPointF sample(size_t i) const override {
|
QPointF sample(size_t i) const override {
|
||||||
Trace::Data d = t.sample(i);
|
switch(Ytype) {
|
||||||
QPointF p;
|
case TraceXYPlot::YAxisType::Magnitude:
|
||||||
p.setX(d.frequency);
|
case TraceXYPlot::YAxisType::Phase:
|
||||||
p.setY(AxisTransformation(E, d.S));
|
case TraceXYPlot::YAxisType::VSWR: {
|
||||||
return p;
|
Trace::Data d = t.sample(i);
|
||||||
|
QPointF p;
|
||||||
|
p.setX(d.frequency);
|
||||||
|
p.setY(FrequencyAxisTransformation(Ytype, d.S));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
case TraceXYPlot::YAxisType::Impulse:
|
||||||
|
case TraceXYPlot::YAxisType::Step:
|
||||||
|
case TraceXYPlot::YAxisType::Impedance: {
|
||||||
|
auto sample = t.getTDR()[i];
|
||||||
|
QPointF p;
|
||||||
|
// TODO set distance
|
||||||
|
p.setX(sample.time);
|
||||||
|
p.setY(TimeAxisTransformation(Ytype, &t, i));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return QPointF();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
QRectF boundingRect() const override {
|
QRectF boundingRect() const override {
|
||||||
return qwtBoundingRect(*this);
|
return qwtBoundingRect(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
TraceXYPlot::YAxisType Ytype;
|
||||||
|
TraceXYPlot::XAxisType Xtype;
|
||||||
Trace &t;
|
Trace &t;
|
||||||
};
|
};
|
||||||
|
|
||||||
TraceBodePlot::TraceBodePlot(TraceModel &model, QWidget *parent)
|
TraceXYPlot::TraceXYPlot(TraceModel &model, QWidget *parent)
|
||||||
: TracePlot(parent),
|
: TracePlot(parent),
|
||||||
selectedMarker(nullptr)
|
selectedMarker(nullptr)
|
||||||
{
|
{
|
||||||
@ -69,10 +125,10 @@ TraceBodePlot::TraceBodePlot(TraceModel &model, QWidget *parent)
|
|||||||
grid->attach(plot);
|
grid->attach(plot);
|
||||||
setColorFromPreferences();
|
setColorFromPreferences();
|
||||||
|
|
||||||
auto selectPicker = new BodeplotPicker(plot->xBottom, plot->yLeft, QwtPicker::NoRubberBand, QwtPicker::ActiveOnly, plot->canvas());
|
auto selectPicker = new XYplotPicker(plot->xBottom, plot->yLeft, QwtPicker::NoRubberBand, QwtPicker::ActiveOnly, plot->canvas());
|
||||||
selectPicker->setStateMachine(new QwtPickerClickPointMachine);
|
selectPicker->setStateMachine(new QwtPickerClickPointMachine);
|
||||||
|
|
||||||
drawPicker = new BodeplotPicker(plot->xBottom, plot->yLeft, QwtPicker::NoRubberBand, QwtPicker::ActiveOnly, plot->canvas());
|
drawPicker = new XYplotPicker(plot->xBottom, plot->yLeft, QwtPicker::NoRubberBand, QwtPicker::ActiveOnly, plot->canvas());
|
||||||
drawPicker->setStateMachine(new QwtPickerDragPointMachine);
|
drawPicker->setStateMachine(new QwtPickerDragPointMachine);
|
||||||
drawPicker->setTrackerPen(QPen(Qt::white));
|
drawPicker->setTrackerPen(QPen(Qt::white));
|
||||||
|
|
||||||
@ -94,14 +150,14 @@ TraceBodePlot::TraceBodePlot(TraceModel &model, QWidget *parent)
|
|||||||
setYAxis(1, YAxisType::Phase, false, false, -180, 180, 30);
|
setYAxis(1, YAxisType::Phase, false, false, -180, 180, 30);
|
||||||
// enable autoscaling and set for full span (no information about actual span available yet)
|
// enable autoscaling and set for full span (no information about actual span available yet)
|
||||||
setXAxis(0, 6000000000);
|
setXAxis(0, 6000000000);
|
||||||
setXAxis(true, 0, 6000000000, 600000000);
|
setXAxis(XAxisType::Frequency, true, 0, 6000000000, 600000000);
|
||||||
// get notified when the span changes
|
// get notified when the span changes
|
||||||
connect(&model, &TraceModel::SpanChanged, this, qOverload<double, double>(&TraceBodePlot::setXAxis));
|
connect(&model, &TraceModel::SpanChanged, this, qOverload<double, double>(&TraceXYPlot::setXAxis));
|
||||||
|
|
||||||
allPlots.insert(this);
|
allPlots.insert(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceBodePlot::~TraceBodePlot()
|
TraceXYPlot::~TraceXYPlot()
|
||||||
{
|
{
|
||||||
for(int axis = 0;axis < 2;axis++) {
|
for(int axis = 0;axis < 2;axis++) {
|
||||||
for(auto pd : curves[axis]) {
|
for(auto pd : curves[axis]) {
|
||||||
@ -112,17 +168,16 @@ TraceBodePlot::~TraceBodePlot()
|
|||||||
allPlots.erase(this);
|
allPlots.erase(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::setXAxis(double min, double max)
|
void TraceXYPlot::setXAxis(double min, double max)
|
||||||
{
|
{
|
||||||
sweep_fmin = min;
|
sweep_fmin = min;
|
||||||
sweep_fmax = max;
|
sweep_fmax = max;
|
||||||
updateXAxis();
|
updateXAxis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::setYAxis(int axis, TraceBodePlot::YAxisType type, bool log, bool autorange, double min, double max, double div)
|
void TraceXYPlot::setYAxis(int axis, TraceXYPlot::YAxisType type, bool log, bool autorange, double min, double max, double div)
|
||||||
{
|
{
|
||||||
if(YAxis[axis].type != type) {
|
if(YAxis[axis].Ytype != type) {
|
||||||
YAxis[axis].type = type;
|
|
||||||
// remove traces that are active but not supported with the new axis type
|
// remove traces that are active but not supported with the new axis type
|
||||||
bool erased = false;
|
bool erased = false;
|
||||||
do {
|
do {
|
||||||
@ -136,6 +191,13 @@ void TraceBodePlot::setYAxis(int axis, TraceBodePlot::YAxisType type, bool log,
|
|||||||
}
|
}
|
||||||
} while(erased);
|
} while(erased);
|
||||||
|
|
||||||
|
if(isTDRtype(YAxis[axis].Ytype)) {
|
||||||
|
for(auto t : tracesAxis[axis]) {
|
||||||
|
t->removeTDRinterest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
YAxis[axis].Ytype = type;
|
||||||
|
|
||||||
for(auto t : tracesAxis[axis]) {
|
for(auto t : tracesAxis[axis]) {
|
||||||
// supported but needs an adjusted QwtSeriesData
|
// supported but needs an adjusted QwtSeriesData
|
||||||
auto td = curves[axis][t];
|
auto td = curves[axis][t];
|
||||||
@ -149,6 +211,9 @@ void TraceBodePlot::setYAxis(int axis, TraceBodePlot::YAxisType type, bool log,
|
|||||||
markerDataChanged(m);
|
markerDataChanged(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(isTDRtype(type)) {
|
||||||
|
t->addTDRinterest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
YAxis[axis].log = log;
|
YAxis[axis].log = log;
|
||||||
@ -168,8 +233,9 @@ void TraceBodePlot::setYAxis(int axis, TraceBodePlot::YAxisType type, bool log,
|
|||||||
replot();
|
replot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::setXAxis(bool autorange, double min, double max, double div)
|
void TraceXYPlot::setXAxis(XAxisType type, bool autorange, double min, double max, double div)
|
||||||
{
|
{
|
||||||
|
XAxis.Xtype = type;
|
||||||
XAxis.autorange = autorange;
|
XAxis.autorange = autorange;
|
||||||
XAxis.rangeMin = min;
|
XAxis.rangeMin = min;
|
||||||
XAxis.rangeMax = max;
|
XAxis.rangeMax = max;
|
||||||
@ -177,33 +243,45 @@ void TraceBodePlot::setXAxis(bool autorange, double min, double max, double div)
|
|||||||
updateXAxis();
|
updateXAxis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::enableTrace(Trace *t, bool enabled)
|
void TraceXYPlot::enableTrace(Trace *t, bool enabled)
|
||||||
{
|
{
|
||||||
for(int axis = 0;axis < 2;axis++) {
|
for(int axis = 0;axis < 2;axis++) {
|
||||||
if(supported(t, YAxis[axis].type)) {
|
if(supported(t, YAxis[axis].Ytype)) {
|
||||||
enableTraceAxis(t, axis, enabled);
|
enableTraceAxis(t, axis, enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::updateGraphColors()
|
void TraceXYPlot::updateGraphColors()
|
||||||
{
|
{
|
||||||
for(auto p : allPlots) {
|
for(auto p : allPlots) {
|
||||||
p->setColorFromPreferences();
|
p->setColorFromPreferences();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::updateContextMenu()
|
bool TraceXYPlot::isTDRtype(TraceXYPlot::YAxisType type)
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case YAxisType::Impulse:
|
||||||
|
case YAxisType::Step:
|
||||||
|
case YAxisType::Impedance:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceXYPlot::updateContextMenu()
|
||||||
{
|
{
|
||||||
contextmenu->clear();
|
contextmenu->clear();
|
||||||
auto setup = new QAction("Axis setup...");
|
auto setup = new QAction("Axis setup...");
|
||||||
connect(setup, &QAction::triggered, [this]() {
|
connect(setup, &QAction::triggered, [this]() {
|
||||||
auto setup = new BodeplotAxisDialog(this);
|
auto setup = new XYplotAxisDialog(this);
|
||||||
setup->show();
|
setup->show();
|
||||||
});
|
});
|
||||||
contextmenu->addAction(setup);
|
contextmenu->addAction(setup);
|
||||||
for(int axis = 0;axis < 2;axis++) {
|
for(int axis = 0;axis < 2;axis++) {
|
||||||
if(YAxis[axis].type == YAxisType::Disabled) {
|
if(YAxis[axis].Ytype == YAxisType::Disabled) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(axis == 0) {
|
if(axis == 0) {
|
||||||
@ -213,7 +291,7 @@ void TraceBodePlot::updateContextMenu()
|
|||||||
}
|
}
|
||||||
for(auto t : traces) {
|
for(auto t : traces) {
|
||||||
// Skip traces that are not applicable for the selected axis type
|
// Skip traces that are not applicable for the selected axis type
|
||||||
if(!supported(t.first, YAxis[axis].type)) {
|
if(!supported(t.first, YAxis[axis].Ytype)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,18 +314,18 @@ void TraceBodePlot::updateContextMenu()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TraceBodePlot::supported(Trace *)
|
bool TraceXYPlot::supported(Trace *)
|
||||||
{
|
{
|
||||||
// potentially possible to add every kind of trace (depends on axis)
|
// potentially possible to add every kind of trace (depends on axis)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::replot()
|
void TraceXYPlot::replot()
|
||||||
{
|
{
|
||||||
plot->replot();
|
plot->replot();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TraceBodePlot::AxisTypeToName(TraceBodePlot::YAxisType type)
|
QString TraceXYPlot::AxisTypeToName(TraceXYPlot::YAxisType type)
|
||||||
{
|
{
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case YAxisType::Disabled: return "Disabled"; break;
|
case YAxisType::Disabled: return "Disabled"; break;
|
||||||
@ -258,7 +336,7 @@ QString TraceBodePlot::AxisTypeToName(TraceBodePlot::YAxisType type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::enableTraceAxis(Trace *t, int axis, bool enabled)
|
void TraceXYPlot::enableTraceAxis(Trace *t, int axis, bool enabled)
|
||||||
{
|
{
|
||||||
bool alreadyEnabled = tracesAxis[axis].find(t) != tracesAxis[axis].end();
|
bool alreadyEnabled = tracesAxis[axis].find(t) != tracesAxis[axis].end();
|
||||||
if(alreadyEnabled != enabled) {
|
if(alreadyEnabled != enabled) {
|
||||||
@ -272,20 +350,26 @@ void TraceBodePlot::enableTraceAxis(Trace *t, int axis, bool enabled)
|
|||||||
cd.curve->setSamples(cd.data);
|
cd.curve->setSamples(cd.data);
|
||||||
curves[axis][t] = cd;
|
curves[axis][t] = cd;
|
||||||
// connect signals
|
// connect signals
|
||||||
connect(t, &Trace::dataChanged, this, &TraceBodePlot::triggerReplot);
|
connect(t, &Trace::dataChanged, this, &TraceXYPlot::triggerReplot);
|
||||||
connect(t, &Trace::colorChanged, this, &TraceBodePlot::traceColorChanged);
|
connect(t, &Trace::colorChanged, this, &TraceXYPlot::traceColorChanged);
|
||||||
connect(t, &Trace::visibilityChanged, this, &TraceBodePlot::traceColorChanged);
|
connect(t, &Trace::visibilityChanged, this, &TraceXYPlot::traceColorChanged);
|
||||||
connect(t, &Trace::visibilityChanged, this, &TraceBodePlot::triggerReplot);
|
connect(t, &Trace::visibilityChanged, this, &TraceXYPlot::triggerReplot);
|
||||||
if(axis == 0) {
|
if(axis == 0) {
|
||||||
connect(t, &Trace::markerAdded, this, &TraceBodePlot::markerAdded);
|
connect(t, &Trace::markerAdded, this, &TraceXYPlot::markerAdded);
|
||||||
connect(t, &Trace::markerRemoved, this, &TraceBodePlot::markerRemoved);
|
connect(t, &Trace::markerRemoved, this, &TraceXYPlot::markerRemoved);
|
||||||
auto tracemarkers = t->getMarkers();
|
auto tracemarkers = t->getMarkers();
|
||||||
for(auto m : tracemarkers) {
|
for(auto m : tracemarkers) {
|
||||||
markerAdded(m);
|
markerAdded(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(isTDRtype(YAxis[axis].Ytype)) {
|
||||||
|
t->addTDRinterest();
|
||||||
|
}
|
||||||
traceColorChanged(t);
|
traceColorChanged(t);
|
||||||
} else {
|
} else {
|
||||||
|
if(isTDRtype(YAxis[axis].Ytype)) {
|
||||||
|
t->removeTDRinterest();
|
||||||
|
}
|
||||||
tracesAxis[axis].erase(t);
|
tracesAxis[axis].erase(t);
|
||||||
// clean up and delete
|
// clean up and delete
|
||||||
if(curves[axis].find(t) != curves[axis].end()) {
|
if(curves[axis].find(t) != curves[axis].end()) {
|
||||||
@ -295,14 +379,14 @@ void TraceBodePlot::enableTraceAxis(Trace *t, int axis, bool enabled)
|
|||||||
int otherAxis = axis == 0 ? 1 : 0;
|
int otherAxis = axis == 0 ? 1 : 0;
|
||||||
if(curves[otherAxis].find(t) == curves[otherAxis].end()) {
|
if(curves[otherAxis].find(t) == curves[otherAxis].end()) {
|
||||||
// this trace is not used anymore, disconnect from notifications
|
// this trace is not used anymore, disconnect from notifications
|
||||||
disconnect(t, &Trace::dataChanged, this, &TraceBodePlot::triggerReplot);
|
disconnect(t, &Trace::dataChanged, this, &TraceXYPlot::triggerReplot);
|
||||||
disconnect(t, &Trace::colorChanged, this, &TraceBodePlot::traceColorChanged);
|
disconnect(t, &Trace::colorChanged, this, &TraceXYPlot::traceColorChanged);
|
||||||
disconnect(t, &Trace::visibilityChanged, this, &TraceBodePlot::traceColorChanged);
|
disconnect(t, &Trace::visibilityChanged, this, &TraceXYPlot::traceColorChanged);
|
||||||
disconnect(t, &Trace::visibilityChanged, this, &TraceBodePlot::triggerReplot);
|
disconnect(t, &Trace::visibilityChanged, this, &TraceXYPlot::triggerReplot);
|
||||||
}
|
}
|
||||||
if(axis == 0) {
|
if(axis == 0) {
|
||||||
disconnect(t, &Trace::markerAdded, this, &TraceBodePlot::markerAdded);
|
disconnect(t, &Trace::markerAdded, this, &TraceXYPlot::markerAdded);
|
||||||
disconnect(t, &Trace::markerRemoved, this, &TraceBodePlot::markerRemoved);
|
disconnect(t, &Trace::markerRemoved, this, &TraceXYPlot::markerRemoved);
|
||||||
auto tracemarkers = t->getMarkers();
|
auto tracemarkers = t->getMarkers();
|
||||||
for(auto m : tracemarkers) {
|
for(auto m : tracemarkers) {
|
||||||
markerRemoved(m);
|
markerRemoved(m);
|
||||||
@ -315,7 +399,7 @@ void TraceBodePlot::enableTraceAxis(Trace *t, int axis, bool enabled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TraceBodePlot::supported(Trace *t, TraceBodePlot::YAxisType type)
|
bool TraceXYPlot::supported(Trace *t, TraceXYPlot::YAxisType type)
|
||||||
{
|
{
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case YAxisType::Disabled:
|
case YAxisType::Disabled:
|
||||||
@ -331,7 +415,7 @@ bool TraceBodePlot::supported(Trace *t, TraceBodePlot::YAxisType type)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::updateXAxis()
|
void TraceXYPlot::updateXAxis()
|
||||||
{
|
{
|
||||||
if(XAxis.autorange && sweep_fmax-sweep_fmin > 0) {
|
if(XAxis.autorange && sweep_fmax-sweep_fmin > 0) {
|
||||||
QList<double> tickList;
|
QList<double> tickList;
|
||||||
@ -346,21 +430,12 @@ void TraceBodePlot::updateXAxis()
|
|||||||
triggerReplot();
|
triggerReplot();
|
||||||
}
|
}
|
||||||
|
|
||||||
QwtSeriesData<QPointF> *TraceBodePlot::createQwtSeriesData(Trace &t, int axis)
|
QwtSeriesData<QPointF> *TraceXYPlot::createQwtSeriesData(Trace &t, int axis)
|
||||||
{
|
{
|
||||||
switch(YAxis[axis].type) {
|
return new QwtTraceSeries(t, YAxis[axis].Ytype, XAxis.Xtype);
|
||||||
case YAxisType::Magnitude:
|
|
||||||
return new QwtTraceSeries<YAxisType::Magnitude>(t);
|
|
||||||
case YAxisType::Phase:
|
|
||||||
return new QwtTraceSeries<YAxisType::Phase>(t);
|
|
||||||
case YAxisType::VSWR:
|
|
||||||
return new QwtTraceSeries<YAxisType::VSWR>(t);
|
|
||||||
default:
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::traceColorChanged(Trace *t)
|
void TraceXYPlot::traceColorChanged(Trace *t)
|
||||||
{
|
{
|
||||||
for(int axis = 0;axis < 2;axis++) {
|
for(int axis = 0;axis < 2;axis++) {
|
||||||
if(curves[axis].find(t) != curves[axis].end()) {
|
if(curves[axis].find(t) != curves[axis].end()) {
|
||||||
@ -388,7 +463,7 @@ void TraceBodePlot::traceColorChanged(Trace *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::markerAdded(TraceMarker *m)
|
void TraceXYPlot::markerAdded(TraceMarker *m)
|
||||||
{
|
{
|
||||||
if(markers.count(m)) {
|
if(markers.count(m)) {
|
||||||
return;
|
return;
|
||||||
@ -396,17 +471,17 @@ void TraceBodePlot::markerAdded(TraceMarker *m)
|
|||||||
auto qwtMarker = new QwtPlotMarker;
|
auto qwtMarker = new QwtPlotMarker;
|
||||||
markers[m] = qwtMarker;
|
markers[m] = qwtMarker;
|
||||||
markerSymbolChanged(m);
|
markerSymbolChanged(m);
|
||||||
connect(m, &TraceMarker::symbolChanged, this, &TraceBodePlot::markerSymbolChanged);
|
connect(m, &TraceMarker::symbolChanged, this, &TraceXYPlot::markerSymbolChanged);
|
||||||
connect(m, &TraceMarker::dataChanged, this, &TraceBodePlot::markerDataChanged);
|
connect(m, &TraceMarker::dataChanged, this, &TraceXYPlot::markerDataChanged);
|
||||||
markerDataChanged(m);
|
markerDataChanged(m);
|
||||||
qwtMarker->attach(plot);
|
qwtMarker->attach(plot);
|
||||||
triggerReplot();
|
triggerReplot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::markerRemoved(TraceMarker *m)
|
void TraceXYPlot::markerRemoved(TraceMarker *m)
|
||||||
{
|
{
|
||||||
disconnect(m, &TraceMarker::symbolChanged, this, &TraceBodePlot::markerSymbolChanged);
|
disconnect(m, &TraceMarker::symbolChanged, this, &TraceXYPlot::markerSymbolChanged);
|
||||||
disconnect(m, &TraceMarker::dataChanged, this, &TraceBodePlot::markerDataChanged);
|
disconnect(m, &TraceMarker::dataChanged, this, &TraceXYPlot::markerDataChanged);
|
||||||
if(markers.count(m)) {
|
if(markers.count(m)) {
|
||||||
markers[m]->detach();
|
markers[m]->detach();
|
||||||
delete markers[m];
|
delete markers[m];
|
||||||
@ -415,15 +490,15 @@ void TraceBodePlot::markerRemoved(TraceMarker *m)
|
|||||||
triggerReplot();
|
triggerReplot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::markerDataChanged(TraceMarker *m)
|
void TraceXYPlot::markerDataChanged(TraceMarker *m)
|
||||||
{
|
{
|
||||||
auto qwtMarker = markers[m];
|
auto qwtMarker = markers[m];
|
||||||
qwtMarker->setXValue(m->getFrequency());
|
qwtMarker->setXValue(m->getFrequency());
|
||||||
qwtMarker->setYValue(AxisTransformation(YAxis[0].type, m->getData()));
|
qwtMarker->setYValue(FrequencyAxisTransformation(YAxis[0].Ytype, m->getData()));
|
||||||
triggerReplot();
|
triggerReplot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::markerSymbolChanged(TraceMarker *m)
|
void TraceXYPlot::markerSymbolChanged(TraceMarker *m)
|
||||||
{
|
{
|
||||||
auto qwtMarker = markers[m];
|
auto qwtMarker = markers[m];
|
||||||
auto old_sym = qwtMarker->symbol();
|
auto old_sym = qwtMarker->symbol();
|
||||||
@ -437,7 +512,7 @@ void TraceBodePlot::markerSymbolChanged(TraceMarker *m)
|
|||||||
triggerReplot();
|
triggerReplot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::clicked(const QPointF pos)
|
void TraceXYPlot::clicked(const QPointF pos)
|
||||||
{
|
{
|
||||||
auto clickPoint = drawPicker->plotToPixel(pos);
|
auto clickPoint = drawPicker->plotToPixel(pos);
|
||||||
unsigned int closestDistance = numeric_limits<unsigned int>::max();
|
unsigned int closestDistance = numeric_limits<unsigned int>::max();
|
||||||
@ -461,7 +536,7 @@ void TraceBodePlot::clicked(const QPointF pos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::moved(const QPointF pos)
|
void TraceXYPlot::moved(const QPointF pos)
|
||||||
{
|
{
|
||||||
if(!selectedMarker || !selectedCurve) {
|
if(!selectedMarker || !selectedCurve) {
|
||||||
return;
|
return;
|
||||||
@ -469,7 +544,7 @@ void TraceBodePlot::moved(const QPointF pos)
|
|||||||
selectedMarker->setFrequency(pos.x());
|
selectedMarker->setFrequency(pos.x());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceBodePlot::setColorFromPreferences()
|
void TraceXYPlot::setColorFromPreferences()
|
||||||
{
|
{
|
||||||
auto pref = Preferences::getInstance();
|
auto pref = Preferences::getInstance();
|
||||||
plot->setCanvasBackground(pref.General.graphColors.background);
|
plot->setCanvasBackground(pref.General.graphColors.background);
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef TRACEBODEPLOT_H
|
#ifndef TRACEXYPLOT_H
|
||||||
#define TRACEBODEPLOT_H
|
#define TRACEXYPLOT_H
|
||||||
|
|
||||||
#include "traceplot.h"
|
#include "traceplot.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -11,10 +11,10 @@
|
|||||||
#include <qwt_plot_picker.h>
|
#include <qwt_plot_picker.h>
|
||||||
|
|
||||||
// Derived plotpicker, exposing transformation functions
|
// Derived plotpicker, exposing transformation functions
|
||||||
class BodeplotPicker : public QwtPlotPicker {
|
class XYplotPicker : public QwtPlotPicker {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
BodeplotPicker(int xAxis, int yAxis, RubberBand rubberBand, DisplayMode trackerMode, QWidget *w)
|
XYplotPicker(int xAxis, int yAxis, RubberBand rubberBand, DisplayMode trackerMode, QWidget *w)
|
||||||
: QwtPlotPicker(xAxis, yAxis, rubberBand, trackerMode, w) {};
|
: QwtPlotPicker(xAxis, yAxis, rubberBand, trackerMode, w) {};
|
||||||
QPoint plotToPixel(const QPointF &pos) {
|
QPoint plotToPixel(const QPointF &pos) {
|
||||||
return transform(pos);
|
return transform(pos);
|
||||||
@ -24,33 +24,46 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TraceBodePlot : public TracePlot
|
class TraceXYPlot : public TracePlot
|
||||||
{
|
{
|
||||||
friend class BodeplotAxisDialog;
|
friend class XYplotAxisDialog;
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
TraceBodePlot(TraceModel &model, QWidget *parent = nullptr);
|
TraceXYPlot(TraceModel &model, QWidget *parent = nullptr);
|
||||||
~TraceBodePlot();
|
~TraceXYPlot();
|
||||||
|
|
||||||
enum class YAxisType {
|
enum class YAxisType {
|
||||||
Disabled = 0,
|
Disabled = 0,
|
||||||
|
// S parameter options
|
||||||
Magnitude = 1,
|
Magnitude = 1,
|
||||||
Phase = 2,
|
Phase = 2,
|
||||||
VSWR = 3,
|
VSWR = 3,
|
||||||
|
// TDR options
|
||||||
|
Impulse = 4,
|
||||||
|
Step = 5,
|
||||||
|
Impedance = 6,
|
||||||
Last,
|
Last,
|
||||||
};
|
};
|
||||||
|
static const std::set<YAxisType> YAxisTypes;
|
||||||
|
enum class XAxisType {
|
||||||
|
Frequency,
|
||||||
|
Time,
|
||||||
|
Distance,
|
||||||
|
};
|
||||||
|
|
||||||
virtual void setXAxis(double min, double max) override;
|
virtual void setXAxis(double min, double max) override;
|
||||||
void setYAxis(int axis, YAxisType type, bool log, bool autorange, double min, double max, double div);
|
void setYAxis(int axis, YAxisType type, bool log, bool autorange, double min, double max, double div);
|
||||||
void setXAxis(bool autorange, double min, double max, double div);
|
void setXAxis(XAxisType type, bool autorange, double min, double max, double div);
|
||||||
void enableTrace(Trace *t, bool enabled) override;
|
void enableTrace(Trace *t, bool enabled) override;
|
||||||
|
|
||||||
// Applies potentially changed colors to all bodeplots
|
// Applies potentially changed colors to all XY-plots
|
||||||
static void updateGraphColors();
|
static void updateGraphColors();
|
||||||
|
|
||||||
|
bool isTDRtype(YAxisType type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void updateContextMenu();
|
virtual void updateContextMenu() override;
|
||||||
virtual bool supported(Trace *t);
|
virtual bool supported(Trace *t) override;
|
||||||
void replot() override;
|
void replot() override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
@ -74,7 +87,10 @@ private:
|
|||||||
|
|
||||||
class Axis {
|
class Axis {
|
||||||
public:
|
public:
|
||||||
YAxisType type;
|
union {
|
||||||
|
YAxisType Ytype;
|
||||||
|
XAxisType Xtype;
|
||||||
|
};
|
||||||
bool log;
|
bool log;
|
||||||
bool autorange;
|
bool autorange;
|
||||||
double rangeMin;
|
double rangeMin;
|
||||||
@ -97,10 +113,10 @@ private:
|
|||||||
TraceMarker *selectedMarker;
|
TraceMarker *selectedMarker;
|
||||||
QwtPlotCurve *selectedCurve;
|
QwtPlotCurve *selectedCurve;
|
||||||
|
|
||||||
BodeplotPicker *drawPicker;
|
XYplotPicker *drawPicker;
|
||||||
|
|
||||||
// keep track of all created plots for changing colors
|
// keep track of all created plots for changing colors
|
||||||
static std::set<TraceBodePlot*> allPlots;
|
static std::set<TraceXYPlot*> allPlots;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRACEBODEPLOT_H
|
#endif // TRACEXYPLOT_H
|
177
Software/PC_Application/Traces/xyplotaxisdialog.cpp
Normal file
177
Software/PC_Application/Traces/xyplotaxisdialog.cpp
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#include "xyplotaxisdialog.h"
|
||||||
|
#include "ui_bodeplotaxisdialog.h"
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
||||||
|
QDialog(nullptr),
|
||||||
|
ui(new Ui::XYplotAxisDialog),
|
||||||
|
plot(plot)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
// Setup GUI connections
|
||||||
|
connect(ui->Y1type, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
|
||||||
|
//ui->Y1log->setEnabled(index != 0);
|
||||||
|
ui->Y1linear->setEnabled(index != 0);
|
||||||
|
ui->Y1auto->setEnabled(index != 0);
|
||||||
|
bool autoRange = ui->Y1auto->isChecked();
|
||||||
|
ui->Y1min->setEnabled(index != 0 && !autoRange);
|
||||||
|
ui->Y1max->setEnabled(index != 0 && !autoRange);
|
||||||
|
ui->Y1divs->setEnabled(index != 0 && !autoRange);
|
||||||
|
auto type = (TraceXYPlot::YAxisType) index;
|
||||||
|
QString unit = YAxisUnit(type);
|
||||||
|
ui->Y1min->setUnit(unit);
|
||||||
|
ui->Y1max->setUnit(unit);
|
||||||
|
ui->Y1divs->setUnit(unit);
|
||||||
|
});
|
||||||
|
connect(ui->Y1auto, &QCheckBox::toggled, [this](bool checked) {
|
||||||
|
ui->Y1min->setEnabled(!checked);
|
||||||
|
ui->Y1max->setEnabled(!checked);
|
||||||
|
ui->Y1divs->setEnabled(!checked);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(ui->Y2type, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
|
||||||
|
//ui->Y2log->setEnabled(index != 0);
|
||||||
|
ui->Y2linear->setEnabled(index != 0);
|
||||||
|
ui->Y2auto->setEnabled(index != 0);
|
||||||
|
bool autoRange = ui->Y2auto->isChecked();
|
||||||
|
ui->Y2min->setEnabled(index != 0 && !autoRange);
|
||||||
|
ui->Y2max->setEnabled(index != 0 && !autoRange);
|
||||||
|
ui->Y2divs->setEnabled(index != 0 && !autoRange);
|
||||||
|
auto type = (TraceXYPlot::YAxisType) index;
|
||||||
|
QString unit = YAxisUnit(type);
|
||||||
|
ui->Y2min->setUnit(unit);
|
||||||
|
ui->Y2max->setUnit(unit);
|
||||||
|
ui->Y2divs->setUnit(unit);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(ui->XType, qOverload<int>(&QComboBox::currentIndexChanged), this, &XYplotAxisDialog::XAxisTypeChanged);
|
||||||
|
|
||||||
|
connect(ui->Y2auto, &QCheckBox::toggled, [this](bool checked) {
|
||||||
|
ui->Y2min->setEnabled(!checked);
|
||||||
|
ui->Y2max->setEnabled(!checked);
|
||||||
|
ui->Y2divs->setEnabled(!checked);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(ui->Xauto, &QCheckBox::toggled, [this](bool checked) {
|
||||||
|
ui->Xmin->setEnabled(!checked);
|
||||||
|
ui->Xmax->setEnabled(!checked);
|
||||||
|
ui->Xdivs->setEnabled(!checked);
|
||||||
|
});
|
||||||
|
|
||||||
|
ui->XType->setCurrentIndex((int) plot->XAxis.Xtype);
|
||||||
|
ui->Xmin->setPrefixes("pnum kMG");
|
||||||
|
ui->Xmax->setPrefixes("pnum kMG");
|
||||||
|
ui->Xdivs->setPrefixes("pnum kMG");
|
||||||
|
|
||||||
|
// Fill initial values
|
||||||
|
// assume same order in YAxisType enum as in ComboBox items
|
||||||
|
ui->Y1type->setCurrentIndex((int) plot->YAxis[0].Ytype);
|
||||||
|
if(plot->YAxis[0].log) {
|
||||||
|
ui->Y1log->setChecked(true);
|
||||||
|
} else {
|
||||||
|
ui->Y1linear->setChecked(true);
|
||||||
|
}
|
||||||
|
ui->Y1auto->setChecked(plot->YAxis[0].autorange);
|
||||||
|
ui->Y1min->setValueQuiet(plot->YAxis[0].rangeMin);
|
||||||
|
ui->Y1max->setValueQuiet(plot->YAxis[0].rangeMax);
|
||||||
|
ui->Y1divs->setValueQuiet(plot->YAxis[0].rangeDiv);
|
||||||
|
|
||||||
|
ui->Y2type->setCurrentIndex((int) plot->YAxis[1].Ytype);
|
||||||
|
if(plot->YAxis[1].log) {
|
||||||
|
ui->Y2log->setChecked(true);
|
||||||
|
} else {
|
||||||
|
ui->Y2linear->setChecked(true);
|
||||||
|
}
|
||||||
|
ui->Y2auto->setChecked(plot->YAxis[1].autorange);
|
||||||
|
ui->Y2min->setValueQuiet(plot->YAxis[1].rangeMin);
|
||||||
|
ui->Y2max->setValueQuiet(plot->YAxis[1].rangeMax);
|
||||||
|
ui->Y2divs->setValueQuiet(plot->YAxis[1].rangeDiv);
|
||||||
|
|
||||||
|
ui->Xauto->setChecked(plot->XAxis.autorange);
|
||||||
|
ui->Xmin->setValueQuiet(plot->XAxis.rangeMin);
|
||||||
|
ui->Xmax->setValueQuiet(plot->XAxis.rangeMax);
|
||||||
|
ui->Xdivs->setValueQuiet(plot->XAxis.rangeDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
XYplotAxisDialog::~XYplotAxisDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XYplotAxisDialog::on_buttonBox_accepted()
|
||||||
|
{
|
||||||
|
// set plot values to the ones selected in the dialog
|
||||||
|
plot->setYAxis(0, (TraceXYPlot::YAxisType) ui->Y1type->currentIndex(), ui->Y1log->isChecked(), ui->Y1auto->isChecked(), ui->Y1min->value(), ui->Y1max->value(), ui->Y1divs->value());
|
||||||
|
plot->setYAxis(1, (TraceXYPlot::YAxisType) ui->Y2type->currentIndex(), ui->Y2log->isChecked(), ui->Y2auto->isChecked(), ui->Y2min->value(), ui->Y2max->value(), ui->Y2divs->value());
|
||||||
|
plot->setXAxis((TraceXYPlot::XAxisType) ui->XType->currentIndex(), ui->Xauto->isChecked(), ui->Xmin->value(), ui->Xmax->value(), ui->Xdivs->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void XYplotAxisDialog::XAxisTypeChanged(int XAxisIndex)
|
||||||
|
{
|
||||||
|
auto type = (TraceXYPlot::XAxisType) XAxisIndex;
|
||||||
|
auto supported = supportedYAxis(type);
|
||||||
|
for(auto t : TraceXYPlot::YAxisTypes) {
|
||||||
|
auto enable = supported.count(t) > 0;
|
||||||
|
auto index = (int) t;
|
||||||
|
auto *model = qobject_cast<QStandardItemModel *>(ui->Y1type->model());
|
||||||
|
auto item = model->item(index);
|
||||||
|
item->setFlags(enable ? item->flags() | Qt::ItemIsEnabled
|
||||||
|
: item->flags() & ~Qt::ItemIsEnabled);
|
||||||
|
model = qobject_cast<QStandardItemModel *>(ui->Y2type->model());
|
||||||
|
item = model->item(index);
|
||||||
|
item->setFlags(enable ? item->flags() | Qt::ItemIsEnabled
|
||||||
|
: item->flags() & ~Qt::ItemIsEnabled);
|
||||||
|
}
|
||||||
|
// Disable Yaxis if previously selected type is not supported
|
||||||
|
if(!supported.count((TraceXYPlot::YAxisType)ui->Y1type->currentIndex())) {
|
||||||
|
ui->Y1type->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
if(!supported.count((TraceXYPlot::YAxisType)ui->Y2type->currentIndex())) {
|
||||||
|
ui->Y2type->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString unit;
|
||||||
|
switch(type) {
|
||||||
|
case TraceXYPlot::XAxisType::Frequency: unit = "Hz"; break;
|
||||||
|
case TraceXYPlot::XAxisType::Time: unit = "s"; break;
|
||||||
|
case TraceXYPlot::XAxisType::Distance: unit = "m"; break;
|
||||||
|
}
|
||||||
|
ui->Xmin->setUnit(unit);
|
||||||
|
ui->Xmax->setUnit(unit);
|
||||||
|
ui->Xdivs->setUnit(unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XYplotAxisDialog::YAxisUnit(TraceXYPlot::YAxisType type)
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case TraceXYPlot::YAxisType::Magnitude: return "db"; break;
|
||||||
|
case TraceXYPlot::YAxisType::Phase: return "°"; break;
|
||||||
|
case TraceXYPlot::YAxisType::VSWR: return ""; break;
|
||||||
|
case TraceXYPlot::YAxisType::Impulse: return ""; break;
|
||||||
|
case TraceXYPlot::YAxisType::Step: return ""; break;
|
||||||
|
case TraceXYPlot::YAxisType::Impedance: return "Ohm"; break;
|
||||||
|
default: return ""; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<TraceXYPlot::YAxisType> XYplotAxisDialog::supportedYAxis(TraceXYPlot::XAxisType type)
|
||||||
|
{
|
||||||
|
set<TraceXYPlot::YAxisType> ret = {TraceXYPlot::YAxisType::Disabled};
|
||||||
|
switch(type) {
|
||||||
|
case TraceXYPlot::XAxisType::Frequency:
|
||||||
|
ret.insert(TraceXYPlot::YAxisType::Magnitude);
|
||||||
|
ret.insert(TraceXYPlot::YAxisType::Phase);
|
||||||
|
ret.insert(TraceXYPlot::YAxisType::VSWR);
|
||||||
|
break;
|
||||||
|
case TraceXYPlot::XAxisType::Time:
|
||||||
|
case TraceXYPlot::XAxisType::Distance:
|
||||||
|
ret.insert(TraceXYPlot::YAxisType::Impulse);
|
||||||
|
ret.insert(TraceXYPlot::YAxisType::Step);
|
||||||
|
ret.insert(TraceXYPlot::YAxisType::Impedance);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
30
Software/PC_Application/Traces/xyplotaxisdialog.h
Normal file
30
Software/PC_Application/Traces/xyplotaxisdialog.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef XYPLOTAXISDIALOG_H
|
||||||
|
#define XYPLOTAXISDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "tracexyplot.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class XYplotAxisDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class XYplotAxisDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit XYplotAxisDialog(TraceXYPlot *plot);
|
||||||
|
~XYplotAxisDialog();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonBox_accepted();
|
||||||
|
void XAxisTypeChanged(int XAxisIndex);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString YAxisUnit(TraceXYPlot::YAxisType type);
|
||||||
|
std::set<TraceXYPlot::YAxisType> supportedYAxis(TraceXYPlot::XAxisType type);
|
||||||
|
Ui::XYplotAxisDialog *ui;
|
||||||
|
TraceXYPlot *plot;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // XYPLOTAXISDIALOG_H
|
547
Software/PC_Application/Traces/xyplotaxisdialog.ui
Normal file
547
Software/PC_Application/Traces/xyplotaxisdialog.ui
Normal file
@ -0,0 +1,547 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>BodeplotAxisDialog</class>
|
||||||
|
<widget class="QDialog" name="BodeplotAxisDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>715</width>
|
||||||
|
<height>282</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Axis Setup</string>
|
||||||
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>9</x>
|
||||||
|
<y>248</y>
|
||||||
|
<width>166</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>701</width>
|
||||||
|
<height>233</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>15</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Primary Y axis</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="Y1type">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Disabled</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Magnitude</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Phase</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>VSWR</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Impulse Response</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Step Response</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Impedance</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="Y1linear">
|
||||||
|
<property name="text">
|
||||||
|
<string>Linear</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">Y1group</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="Y1log">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Log</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">Y1group</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Range:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QCheckBox" name="Y1auto">
|
||||||
|
<property name="text">
|
||||||
|
<string>Auto</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Maximum:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Y1max"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Minimum:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Y1min"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Divisions:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Y1divs"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>15</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Secondary Y axis</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>Type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="Y2type">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Disabled</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Magnitude</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Phase</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>VSWR</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Impulse Response</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Step Response</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Impedance</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="Y2linear">
|
||||||
|
<property name="text">
|
||||||
|
<string>Linear</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">Y2group</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="Y2log">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Log</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">Y2group</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_4">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>Range:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QCheckBox" name="Y2auto">
|
||||||
|
<property name="text">
|
||||||
|
<string>Auto</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>Maximum:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Y2max"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Minimum:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Y2min"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>Divisions:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Y2divs"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_6">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>15</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>X axis</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_5">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_14">
|
||||||
|
<property name="text">
|
||||||
|
<string>Type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="XType">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Frequency</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Time</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Distance</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_7">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_6">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_15">
|
||||||
|
<property name="text">
|
||||||
|
<string>Range:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QCheckBox" name="Xauto">
|
||||||
|
<property name="text">
|
||||||
|
<string>Auto</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_16">
|
||||||
|
<property name="text">
|
||||||
|
<string>Maximum:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Xmax"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_17">
|
||||||
|
<property name="text">
|
||||||
|
<string>Minimum:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Xmin"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_18">
|
||||||
|
<property name="text">
|
||||||
|
<string>Divisions:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Xdivs"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>SIUnitEdit</class>
|
||||||
|
<extends>QLineEdit</extends>
|
||||||
|
<header>CustomWidgets/siunitedit.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>BodeplotAxisDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>BodeplotAxisDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
<buttongroups>
|
||||||
|
<buttongroup name="Y1group"/>
|
||||||
|
<buttongroup name="Y2group"/>
|
||||||
|
</buttongroups>
|
||||||
|
</ui>
|
@ -26,7 +26,7 @@
|
|||||||
#include "Traces/tracemodel.h"
|
#include "Traces/tracemodel.h"
|
||||||
#include "Traces/tracewidget.h"
|
#include "Traces/tracewidget.h"
|
||||||
#include "Traces/tracesmithchart.h"
|
#include "Traces/tracesmithchart.h"
|
||||||
#include "Traces/tracebodeplot.h"
|
#include "Traces/tracexyplot.h"
|
||||||
#include "Traces/traceimportdialog.h"
|
#include "Traces/traceimportdialog.h"
|
||||||
#include "CustomWidgets/tilewidget.h"
|
#include "CustomWidgets/tilewidget.h"
|
||||||
#include "CustomWidgets/siunitedit.h"
|
#include "CustomWidgets/siunitedit.h"
|
||||||
@ -70,9 +70,9 @@ VNA::VNA(AppWindow *window)
|
|||||||
auto tracesmith2 = new TraceSmithChart(traceModel);
|
auto tracesmith2 = new TraceSmithChart(traceModel);
|
||||||
tracesmith2->enableTrace(tS22, true);
|
tracesmith2->enableTrace(tS22, true);
|
||||||
|
|
||||||
auto tracebode1 = new TraceBodePlot(traceModel);
|
auto tracebode1 = new TraceXYPlot(traceModel);
|
||||||
tracebode1->enableTrace(tS12, true);
|
tracebode1->enableTrace(tS12, true);
|
||||||
auto tracebode2 = new TraceBodePlot(traceModel);
|
auto tracebode2 = new TraceXYPlot(traceModel);
|
||||||
tracebode2->enableTrace(tS21, true);
|
tracebode2->enableTrace(tS21, true);
|
||||||
|
|
||||||
connect(&traceModel, &TraceModel::requiredExcitation, this, &VNA::ExcitationRequired);
|
connect(&traceModel, &TraceModel::requiredExcitation, this, &VNA::ExcitationRequired);
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "Traces/tracemodel.h"
|
#include "Traces/tracemodel.h"
|
||||||
#include "Traces/tracewidget.h"
|
#include "Traces/tracewidget.h"
|
||||||
#include "Traces/tracesmithchart.h"
|
#include "Traces/tracesmithchart.h"
|
||||||
#include "Traces/tracebodeplot.h"
|
#include "Traces/tracexyplot.h"
|
||||||
#include "Traces/traceimportdialog.h"
|
#include "Traces/traceimportdialog.h"
|
||||||
#include "CustomWidgets/tilewidget.h"
|
#include "CustomWidgets/tilewidget.h"
|
||||||
#include "CustomWidgets/siunitedit.h"
|
#include "CustomWidgets/siunitedit.h"
|
||||||
@ -110,7 +110,7 @@ AppWindow::AppWindow(QWidget *parent)
|
|||||||
connect(ui->actionPreferences, &QAction::triggered, [=](){
|
connect(ui->actionPreferences, &QAction::triggered, [=](){
|
||||||
Preferences::getInstance().edit();
|
Preferences::getInstance().edit();
|
||||||
// settings might have changed, update necessary stuff
|
// settings might have changed, update necessary stuff
|
||||||
TraceBodePlot::updateGraphColors();
|
TraceXYPlot::updateGraphColors();
|
||||||
});
|
});
|
||||||
|
|
||||||
setWindowTitle("VNA");
|
setWindowTitle("VNA");
|
||||||
|
Loading…
Reference in New Issue
Block a user