diff --git a/Software/PC_Application/Traces/Math/expression.cpp b/Software/PC_Application/Traces/Math/expression.cpp index 23cd15a..f4a3754 100644 --- a/Software/PC_Application/Traces/Math/expression.cpp +++ b/Software/PC_Application/Traces/Math/expression.cpp @@ -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); diff --git a/Software/PC_Application/Traces/Math/tracemath.h b/Software/PC_Application/Traces/Math/tracemath.h index ecb6015..874126d 100644 --- a/Software/PC_Application/Traces/Math/tracemath.h +++ b/Software/PC_Application/Traces/Math/tracemath.h @@ -60,6 +60,7 @@ public: enum class DataType { Frequency, Time, + Power, Invalid, }; diff --git a/Software/PC_Application/Traces/trace.cpp b/Software/PC_Application/Traces/trace.cpp index 65bed17..73a885f 100644 --- a/Software/PC_Application/Traces/trace.cpp +++ b/Software/PC_Application/Traces/trace.cpp @@ -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 markers; diff --git a/Software/PC_Application/Traces/traceeditdialog.cpp b/Software/PC_Application/Traces/traceeditdialog.cpp index eacb0d2..4792c6a 100644 --- a/Software/PC_Application/Traces/traceeditdialog.cpp +++ b/Software/PC_Application/Traces/traceeditdialog.cpp @@ -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"; } diff --git a/Software/PC_Application/Traces/tracesmithchart.cpp b/Software/PC_Application/Traces/tracesmithchart.cpp index 49557ab..8ebe812 100644 --- a/Software/PC_Application/Traces/tracesmithchart.cpp +++ b/Software/PC_Application/Traces/tracesmithchart.cpp @@ -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; } } diff --git a/Software/PC_Application/Traces/tracexyplot.cpp b/Software/PC_Application/Traces/tracexyplot.cpp index d32de49..fd2aeb7 100644 --- a/Software/PC_Application/Traces/tracexyplot.cpp +++ b/Software/PC_Application/Traces/tracexyplot.cpp @@ -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; } } diff --git a/Software/PC_Application/Traces/tracexyplot.h b/Software/PC_Application/Traces/tracexyplot.h index 0651c5a..684e864 100644 --- a/Software/PC_Application/Traces/tracexyplot.h +++ b/Software/PC_Application/Traces/tracexyplot.h @@ -34,6 +34,7 @@ public: Frequency, Time, Distance, + Power, Last, }; enum class XAxisMode { diff --git a/Software/PC_Application/Traces/xyplotaxisdialog.cpp b/Software/PC_Application/Traces/xyplotaxisdialog.cpp index d3d9079..001ebf2 100644 --- a/Software/PC_Application/Traces/xyplotaxisdialog.cpp +++ b/Software/PC_Application/Traces/xyplotaxisdialog.cpp @@ -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(&QComboBox::currentIndexChanged), [this](int index) { //ui->Y1log->setEnabled(index != 0); @@ -178,6 +182,7 @@ std::set XYplotAxisDialog::supportedYAxis(TraceXYPlot::X set 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); diff --git a/Software/PC_Application/Traces/xyplotaxisdialog.ui b/Software/PC_Application/Traces/xyplotaxisdialog.ui index f6ddc33..aea77ce 100644 --- a/Software/PC_Application/Traces/xyplotaxisdialog.ui +++ b/Software/PC_Application/Traces/xyplotaxisdialog.ui @@ -313,23 +313,7 @@ - - - - Frequency - - - - - Time - - - - - Distance - - - + diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index 1b797d8..640013e 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -235,6 +235,16 @@ VNA::VNA(AppWindow *window) // Sweep toolbar auto tb_sweep = new QToolBar("Sweep"); + + std::vector frequencySweepActions; + std::vector 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(&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);