Prepare GUI for power sweep

This commit is contained in:
Jan Käberich 2021-07-09 18:42:22 +02:00
parent fc5947c9a8
commit 6490d6fd14
11 changed files with 159 additions and 74 deletions

View File

@ -41,6 +41,7 @@ void Math::Expression::edit()
exp = ui->expEdit->text();
expressionChanged();
});
// TODO add power domain
if(dataType == DataType::Time) {
// select the label explaining the time domain variables (frequency label is the default)
ui->stackedWidget->setCurrentIndex(1);

View File

@ -60,6 +60,7 @@ public:
enum class DataType {
Frequency,
Time,
Power,
Invalid,
};

View File

@ -21,7 +21,7 @@ Trace::Trace(QString name, QColor color, LiveParameter live)
paused(false),
createdFromFile(false),
calibration(false),
timeDomain(false),
domain(DataType::Frequency),
lastMath(nullptr)
{
MathInfo self = {.math = this, .enabled = true};
@ -31,7 +31,7 @@ Trace::Trace(QString name, QColor color, LiveParameter live)
self.enabled = false;
dataType = DataType::Frequency;
connect(this, &Trace::typeChanged, [=](){
dataType = timeDomain ? DataType::Time : DataType::Frequency;
dataType = domain;
emit outputTypeChanged(dataType);
});
}
@ -120,7 +120,7 @@ void Trace::fillFromTouchstone(Touchstone &t, unsigned int parameter)
throw runtime_error("Parameter for touchstone out of range");
}
clear();
timeDomain = false;
domain = DataType::Frequency;
fileParemeter = parameter;
filename = t.getFilename();
for(unsigned int i=0;i<t.points();i++) {
@ -206,7 +206,13 @@ QString Trace::fillFromCSV(CSV &csv, unsigned int parameter)
fileParemeter = parameter;
filename = csv.getFilename();
auto xColumn = csv.getColumn(0);
timeDomain = csv.getHeader(0).compare("time", Qt::CaseInsensitive) == 0;
if(csv.getHeader(0).compare("time", Qt::CaseInsensitive) == 0) {
domain = DataType::Time;
} else if(csv.getHeader(0).compare("power", Qt::CaseInsensitive) == 0) {
domain = DataType::Power;
} else {
domain = DataType::Frequency;
}
for(unsigned int i=0;i<xColumn.size();i++) {
Data d;
d.x = xColumn[i];
@ -242,7 +248,8 @@ void Trace::fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, c
void Trace::fromLivedata(Trace::LivedataType type, LiveParameter param)
{
timeDomain = false;
// TODO set domain depending on incoming data
domain = DataType::Frequency;
createdFromFile = false;
_liveType = type;
_liveParam = param;
@ -635,11 +642,7 @@ void Trace::setReflection(bool value)
TraceMath::DataType Trace::outputType(TraceMath::DataType inputType)
{
Q_UNUSED(inputType);
if(timeDomain) {
return DataType::Time;
} else {
return DataType::Frequency;
}
return domain;
}
QString Trace::description()

View File

@ -173,7 +173,7 @@ private:
bool paused;
bool createdFromFile;
bool calibration;
bool timeDomain;
DataType domain;
QString filename;
unsigned int fileParemeter;
std::set<Marker*> markers;

View File

@ -294,6 +294,8 @@ QVariant MathModel::data(const QModelIndex &index, int role) const
return "Time";
case TraceMath::DataType::Frequency:
return "Frequency";
case TraceMath::DataType::Power:
return "Power";
case TraceMath::DataType::Invalid:
return "Invalid";
}

View File

@ -337,9 +337,14 @@ bool TraceSmithChart::supported(Trace *t)
bool TraceSmithChart::dropSupported(Trace *t)
{
if(t->outputType() == Trace::DataType::Frequency && t->isReflection()) {
if(!t->isReflection()) {
return false;
}
switch(t->outputType()) {
case Trace::DataType::Frequency:
case Trace::DataType::Power:
return true;
} else {
default:
return false;
}
}

View File

@ -711,9 +711,10 @@ void TraceXYPlot::updateAxisTicks()
QString TraceXYPlot::AxisTypeToName(TraceXYPlot::XAxisType type)
{
switch(type) {
case XAxisType::Frequency: return "Frequency"; break;
case XAxisType::Time: return "Time"; break;
case XAxisType::Distance: return "Distance"; break;
case XAxisType::Frequency: return "Frequency";
case XAxisType::Time: return "Time";
case XAxisType::Distance: return "Distance";
case XAxisType::Power: return "Power";
default: return "Unknown";
}
}
@ -824,6 +825,11 @@ bool TraceXYPlot::supported(Trace *t, TraceXYPlot::YAxisType type)
return false;
}
break;
case XAxisType::Power:
if(t->outputType() != Trace::DataType::Power) {
return false;
}
break;
default:
break;
}
@ -981,29 +987,34 @@ bool TraceXYPlot::xCoordinateVisible(double x)
void TraceXYPlot::traceDropped(Trace *t, QPoint position)
{
if(t->outputType() == Trace::DataType::Frequency && XAxis.type != XAxisType::Frequency) {
// needs to switch to frequency domain graph
if(!InformationBox::AskQuestion("X Axis Domain Change", "You dropped a frequency domain trace but the graph is still set up for the time domain."
" Do you want to remove all traces and change the graph to frequency domain?", true, "DomainChangeRequest")) {
if(!supported(t)) {
// needs to switch to a different domain for the graph
if(!InformationBox::AskQuestion("X Axis Domain Change", "You dropped a trace that is not supported with the currently selected X axis domain."
" Do you want to remove all traces and change the graph to the correct domain?", true, "DomainChangeRequest")) {
// user declined to change domain, to not add trace
return;
}
setXAxis(XAxisType::Frequency, XAxisMode::FitTraces, 0, 1, 0.1);
setYAxis(0, YAxisType::Magnitude, false, true, 0, 1, 1.0);
setYAxis(1, YAxisType::Phase, false, true, 0, 1, 1.0);
}
if(t->outputType() != Trace::DataType::Frequency && XAxis.type == XAxisType::Frequency) {
// needs to switch to time domain graph
if(!InformationBox::AskQuestion("X Axis Domain Change", "You dropped a time domain trace but the graph is still set up for the frequency domain."
" Do you want to remove all traces and change the graph to time domain?", true, "DomainChangeRequest")) {
// user declined to change domain, to not add trace
switch(t->outputType()) {
case Trace::DataType::Frequency:
setXAxis(XAxisType::Frequency, XAxisMode::FitTraces, 0, 1, 0.1);
setYAxis(0, YAxisType::Magnitude, false, true, 0, 1, 1.0);
setYAxis(1, YAxisType::Phase, false, true, 0, 1, 1.0);
break;
case Trace::DataType::Time:
setXAxis(XAxisType::Time, XAxisMode::FitTraces, 0, 1, 0.1);
setYAxis(0, YAxisType::ImpulseMag, false, true, 0, 1, 1.0);
setYAxis(1, YAxisType::Disabled, false, true, 0, 1, 1.0);
break;
case Trace::DataType::Power:
setXAxis(XAxisType::Power, XAxisMode::FitTraces, 0, 1, 0.1);
setYAxis(0, YAxisType::Magnitude, false, true, 0, 1, 1.0);
setYAxis(1, YAxisType::Phase, false, true, 0, 1, 1.0);
break;
case Trace::DataType::Invalid:
// unable to add
return;
}
setXAxis(XAxisType::Time, XAxisMode::FitTraces, 0, 1, 0.1);
setYAxis(0, YAxisType::ImpulseMag, false, true, 0, 1, 1.0);
setYAxis(1, YAxisType::Disabled, false, true, 0, 1, 1.0);
}
if(YAxis[0].type == YAxisType::Disabled && YAxis[1].type == YAxisType::Disabled) {
// no Y axis enabled, unable to drop
return;
@ -1053,23 +1064,24 @@ QString TraceXYPlot::mouseText(QPoint pos)
QString TraceXYPlot::AxisUnit(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::ImpulseReal: return ""; break;
case TraceXYPlot::YAxisType::ImpulseMag: return "db"; break;
case TraceXYPlot::YAxisType::Step: return ""; break;
case TraceXYPlot::YAxisType::Impedance: return "Ohm"; break;
default: return ""; break;
case TraceXYPlot::YAxisType::Magnitude: return "db";
case TraceXYPlot::YAxisType::Phase: return "°";
case TraceXYPlot::YAxisType::VSWR: return "";
case TraceXYPlot::YAxisType::ImpulseReal: return "";
case TraceXYPlot::YAxisType::ImpulseMag: return "db";
case TraceXYPlot::YAxisType::Step: return "";
case TraceXYPlot::YAxisType::Impedance: return "Ohm";
default: return "";
}
}
QString TraceXYPlot::AxisUnit(TraceXYPlot::XAxisType type)
{
switch(type) {
case XAxisType::Frequency: return "Hz"; break;
case XAxisType::Time: return "s"; break;
case XAxisType::Distance: return "m"; break;
case XAxisType::Frequency: return "Hz";
case XAxisType::Time: return "s";
case XAxisType::Distance: return "m";
case XAxisType::Power: return "dBm";
default: return ""; break;
}
}

View File

@ -34,6 +34,7 @@ public:
Frequency,
Time,
Distance,
Power,
Last,
};
enum class XAxisMode {

View File

@ -18,6 +18,10 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
ui->Y2type->addItem(TraceXYPlot::AxisTypeToName((TraceXYPlot::YAxisType) i));
}
for(int i=0;i<(int) TraceXYPlot::XAxisType::Last;i++) {
ui->XType->addItem(TraceXYPlot::AxisTypeToName((TraceXYPlot::XAxisType) i));
}
// Setup GUI connections
connect(ui->Y1type, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
//ui->Y1log->setEnabled(index != 0);
@ -178,6 +182,7 @@ std::set<TraceXYPlot::YAxisType> XYplotAxisDialog::supportedYAxis(TraceXYPlot::X
set<TraceXYPlot::YAxisType> ret = {TraceXYPlot::YAxisType::Disabled};
switch(type) {
case TraceXYPlot::XAxisType::Frequency:
case TraceXYPlot::XAxisType::Power:
ret.insert(TraceXYPlot::YAxisType::Magnitude);
ret.insert(TraceXYPlot::YAxisType::Phase);
ret.insert(TraceXYPlot::YAxisType::VSWR);

View File

@ -313,23 +313,7 @@
</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>
<widget class="QComboBox" name="XType"/>
</item>
</layout>
</item>

View File

@ -235,6 +235,16 @@ VNA::VNA(AppWindow *window)
// Sweep toolbar
auto tb_sweep = new QToolBar("Sweep");
std::vector<QAction*> frequencySweepActions;
std::vector<QAction*> powerSweepActions;
tb_sweep->addWidget(new QLabel("Sweep type:"));
auto cbSweepType = new QComboBox();
cbSweepType->addItem("Frequency");
cbSweepType->addItem("Power");
tb_sweep->addWidget(cbSweepType);
auto eStart = new SIUnitEdit("Hz", " kMG", 6);
// calculate width required with expected string length
auto width = QFontMetrics(eStart->font()).width("3.00000GHz") + 15;
@ -242,47 +252,80 @@ VNA::VNA(AppWindow *window)
eStart->setToolTip("Start frequency");
connect(eStart, &SIUnitEdit::valueChanged, this, &VNA::SetStartFreq);
connect(this, &VNA::startFreqChanged, eStart, &SIUnitEdit::setValueQuiet);
tb_sweep->addWidget(new QLabel("Start:"));
tb_sweep->addWidget(eStart);
frequencySweepActions.push_back(tb_sweep->addWidget(new QLabel("Start:")));
frequencySweepActions.push_back(tb_sweep->addWidget(eStart));
auto eCenter = new SIUnitEdit("Hz", " kMG", 6);
eCenter->setFixedWidth(width);
eCenter->setToolTip("Center frequency");
connect(eCenter, &SIUnitEdit::valueChanged, this, &VNA::SetCenterFreq);
connect(this, &VNA::centerFreqChanged, eCenter, &SIUnitEdit::setValueQuiet);
tb_sweep->addWidget(new QLabel("Center:"));
tb_sweep->addWidget(eCenter);
frequencySweepActions.push_back(tb_sweep->addWidget(new QLabel("Center:")));
frequencySweepActions.push_back(tb_sweep->addWidget(eCenter));
auto eStop = new SIUnitEdit("Hz", " kMG", 6);
eStop->setFixedWidth(width);
eStop->setToolTip("Stop frequency");
connect(eStop, &SIUnitEdit::valueChanged, this, &VNA::SetStopFreq);
connect(this, &VNA::stopFreqChanged, eStop, &SIUnitEdit::setValueQuiet);
tb_sweep->addWidget(new QLabel("Stop:"));
tb_sweep->addWidget(eStop);
frequencySweepActions.push_back(tb_sweep->addWidget(new QLabel("Stop:")));
frequencySweepActions.push_back(tb_sweep->addWidget(eStop));
auto eSpan = new SIUnitEdit("Hz", " kMG", 6);
eSpan->setFixedWidth(width);
eSpan->setToolTip("Span");
connect(eSpan, &SIUnitEdit::valueChanged, this, &VNA::SetSpan);
connect(this, &VNA::spanChanged, eSpan, &SIUnitEdit::setValueQuiet);
tb_sweep->addWidget(new QLabel("Span:"));
tb_sweep->addWidget(eSpan);
frequencySweepActions.push_back(tb_sweep->addWidget(new QLabel("Span:")));
frequencySweepActions.push_back(tb_sweep->addWidget(eSpan));
auto bFull = new QPushButton(QIcon::fromTheme("zoom-fit-best", QIcon(":/icons/zoom-fit.png")), "");
bFull->setToolTip("Full span");
connect(bFull, &QPushButton::clicked, this, &VNA::SetFullSpan);
tb_sweep->addWidget(bFull);
frequencySweepActions.push_back(tb_sweep->addWidget(bFull));
auto bZoomIn = new QPushButton(QIcon::fromTheme("zoom-in", QIcon(":/icons/zoom-in.png")), "");
bZoomIn->setToolTip("Zoom in");
connect(bZoomIn, &QPushButton::clicked, this, &VNA::SpanZoomIn);
tb_sweep->addWidget(bZoomIn);
frequencySweepActions.push_back(tb_sweep->addWidget(bZoomIn));
auto bZoomOut = new QPushButton(QIcon::fromTheme("zoom-out", QIcon(":/icons/zoom-out.png")), "");
bZoomOut->setToolTip("Zoom out");
connect(bZoomOut, &QPushButton::clicked, this, &VNA::SpanZoomOut);
tb_sweep->addWidget(bZoomOut);
frequencySweepActions.push_back(tb_sweep->addWidget(bZoomOut));
// power sweep widgets
auto sbPowerLow = new QDoubleSpinBox();
width = QFontMetrics(sbPowerLow->font()).width("-30.00dBm") + 20;
sbPowerLow->setFixedWidth(width);
sbPowerLow->setRange(-100.0, 100.0);
sbPowerLow->setSingleStep(0.25);
sbPowerLow->setSuffix("dbm");
sbPowerLow->setToolTip("Stimulus level");
sbPowerLow->setKeyboardTracking(false);
// TODO connect
powerSweepActions.push_back(tb_sweep->addWidget(new QLabel("From:")));
powerSweepActions.push_back(tb_sweep->addWidget(sbPowerLow));
auto sbPowerHigh = new QDoubleSpinBox();
width = QFontMetrics(sbPowerHigh->font()).width("-30.00dBm") + 20;
sbPowerHigh->setFixedWidth(width);
sbPowerHigh->setRange(-100.0, 100.0);
sbPowerHigh->setSingleStep(0.25);
sbPowerHigh->setSuffix("dbm");
sbPowerHigh->setToolTip("Stimulus level");
sbPowerHigh->setKeyboardTracking(false);
// TODO connect
powerSweepActions.push_back(tb_sweep->addWidget(new QLabel("To:")));
powerSweepActions.push_back(tb_sweep->addWidget(sbPowerHigh));
auto ePowerFreq = new SIUnitEdit("Hz", " kMG", 6);
width = QFontMetrics(ePowerFreq->font()).width("3.00000GHz") + 15;
ePowerFreq->setFixedWidth(width);
ePowerFreq->setToolTip("Start frequency");
// TODO connect
powerSweepActions.push_back(tb_sweep->addWidget(new QLabel("at:")));
powerSweepActions.push_back(tb_sweep->addWidget(ePowerFreq));
window->addToolBar(tb_sweep);
toolbars.insert(tb_sweep);
@ -299,8 +342,36 @@ VNA::VNA(AppWindow *window)
dbm->setKeyboardTracking(false);
connect(dbm, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &VNA::SetSourceLevel);
connect(this, &VNA::sourceLevelChanged, dbm, &QDoubleSpinBox::setValue);
tb_acq->addWidget(new QLabel("Level:"));
tb_acq->addWidget(dbm);
frequencySweepActions.push_back(tb_acq->addWidget(new QLabel("Level:")));
frequencySweepActions.push_back(tb_acq->addWidget(dbm));
auto configureToolbarForFrequencySweep = [=](){
for(auto a : frequencySweepActions) {
a->setVisible(true);
}
for(auto a : powerSweepActions) {
a->setVisible(false);
}
};
auto configureToolbarForPowerSweep = [=](){
for(auto a : frequencySweepActions) {
a->setVisible(false);
}
for(auto a : powerSweepActions) {
a->setVisible(true);
}
};
connect(cbSweepType, &QComboBox::currentTextChanged, [=](QString text) {
if(text == "Frequency") {
configureToolbarForFrequencySweep();
} else if(text == "Power") {
configureToolbarForPowerSweep();
}
});
// initial setup is frequency sweep
configureToolbarForFrequencySweep();
auto points = new QSpinBox();
points->setFixedWidth(55);