2020-09-17 21:51:20 +08:00
|
|
|
#include "spectrumanalyzer.h"
|
|
|
|
#include <QGridLayout>
|
|
|
|
#include <QVBoxLayout>
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <math.h>
|
|
|
|
#include <QToolBar>
|
|
|
|
#include <QMenu>
|
|
|
|
#include <QToolButton>
|
|
|
|
#include <QActionGroup>
|
|
|
|
#include <QSpinBox>
|
|
|
|
#include <QCheckBox>
|
|
|
|
#include <QComboBox>
|
|
|
|
#include <QSettings>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QFile>
|
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <QDateTime>
|
|
|
|
#include "unit.h"
|
|
|
|
#include "CustomWidgets/toggleswitch.h"
|
|
|
|
#include "Device/manualcontroldialog.h"
|
|
|
|
#include "Traces/tracemodel.h"
|
2020-11-25 01:08:00 +08:00
|
|
|
#include "tracewidgetsa.h"
|
2020-09-17 21:51:20 +08:00
|
|
|
#include "Traces/tracesmithchart.h"
|
2020-10-28 05:07:14 +08:00
|
|
|
#include "Traces/tracexyplot.h"
|
2020-09-17 21:51:20 +08:00
|
|
|
#include "Traces/traceimportdialog.h"
|
|
|
|
#include "CustomWidgets/tilewidget.h"
|
|
|
|
#include "CustomWidgets/siunitedit.h"
|
|
|
|
#include <QDockWidget>
|
|
|
|
#include "Traces/markerwidget.h"
|
|
|
|
#include "Tools/impedancematchdialog.h"
|
|
|
|
#include "Calibration/calibrationtracedialog.h"
|
|
|
|
#include "ui_main.h"
|
|
|
|
#include "Device/firmwareupdatedialog.h"
|
|
|
|
#include "preferences.h"
|
|
|
|
#include "Generator/signalgenwidget.h"
|
|
|
|
#include <QDesktopWidget>
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QActionGroup>
|
2020-11-19 02:19:29 +08:00
|
|
|
#include "CustomWidgets/informationbox.h"
|
2020-11-22 07:41:42 +08:00
|
|
|
#include <QDebug>
|
2020-09-17 21:51:20 +08:00
|
|
|
|
|
|
|
SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window)
|
|
|
|
: Mode(window, "Spectrum Analyzer"),
|
2021-04-11 18:33:37 +08:00
|
|
|
SCPINode("SA"),
|
2020-11-01 06:03:34 +08:00
|
|
|
central(new TileWidget(traceModel, window))
|
2020-09-17 21:51:20 +08:00
|
|
|
{
|
|
|
|
averages = 1;
|
2020-11-01 06:03:34 +08:00
|
|
|
settings = {};
|
2020-11-21 20:27:23 +08:00
|
|
|
normalize.active = false;
|
|
|
|
normalize.measuring = false;
|
|
|
|
normalize.points = 0;
|
|
|
|
normalize.dialog.reset();
|
2020-09-17 21:51:20 +08:00
|
|
|
|
|
|
|
// Create default traces
|
|
|
|
auto tPort1 = new Trace("Port1", Qt::yellow);
|
|
|
|
tPort1->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::Port1);
|
|
|
|
traceModel.addTrace(tPort1);
|
|
|
|
auto tPort2 = new Trace("Port2", Qt::blue);
|
|
|
|
tPort2->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::Port2);
|
|
|
|
traceModel.addTrace(tPort2);
|
|
|
|
|
2020-10-28 05:08:05 +08:00
|
|
|
auto traceXY = new TraceXYPlot(traceModel);
|
|
|
|
traceXY->enableTrace(tPort1, true);
|
|
|
|
traceXY->enableTrace(tPort2, true);
|
|
|
|
traceXY->setYAxis(0, TraceXYPlot::YAxisType::Magnitude, false, false, -120,0,10);
|
|
|
|
traceXY->setYAxis(1, TraceXYPlot::YAxisType::Disabled, false, true, 0,0,1);
|
2020-09-17 21:51:20 +08:00
|
|
|
|
2020-10-28 05:08:05 +08:00
|
|
|
central->setPlot(traceXY);
|
2020-09-17 21:51:20 +08:00
|
|
|
|
|
|
|
// Create menu entries and connections
|
|
|
|
// Sweep toolbar
|
|
|
|
auto tb_sweep = new QToolBar("Sweep");
|
|
|
|
auto eStart = new SIUnitEdit("Hz", " kMG", 6);
|
2020-11-23 19:43:24 +08:00
|
|
|
// calculate width required with expected string length
|
|
|
|
auto width = QFontMetrics(eStart->font()).width("3.00000GHz") + 15;
|
|
|
|
eStart->setFixedWidth(width);
|
2020-09-17 21:51:20 +08:00
|
|
|
eStart->setToolTip("Start frequency");
|
|
|
|
connect(eStart, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetStartFreq);
|
|
|
|
connect(this, &SpectrumAnalyzer::startFreqChanged, eStart, &SIUnitEdit::setValueQuiet);
|
|
|
|
tb_sweep->addWidget(new QLabel("Start:"));
|
|
|
|
tb_sweep->addWidget(eStart);
|
|
|
|
|
|
|
|
auto eCenter = new SIUnitEdit("Hz", " kMG", 6);
|
2020-11-23 19:43:24 +08:00
|
|
|
eCenter->setFixedWidth(width);
|
2020-09-17 21:51:20 +08:00
|
|
|
eCenter->setToolTip("Center frequency");
|
|
|
|
connect(eCenter, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetCenterFreq);
|
|
|
|
connect(this, &SpectrumAnalyzer::centerFreqChanged, eCenter, &SIUnitEdit::setValueQuiet);
|
|
|
|
tb_sweep->addWidget(new QLabel("Center:"));
|
|
|
|
tb_sweep->addWidget(eCenter);
|
|
|
|
|
|
|
|
auto eStop = new SIUnitEdit("Hz", " kMG", 6);
|
2020-11-23 19:43:24 +08:00
|
|
|
eStop->setFixedWidth(width);
|
2020-09-17 21:51:20 +08:00
|
|
|
eStop->setToolTip("Stop frequency");
|
|
|
|
connect(eStop, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetStopFreq);
|
|
|
|
connect(this, &SpectrumAnalyzer::stopFreqChanged, eStop, &SIUnitEdit::setValueQuiet);
|
|
|
|
tb_sweep->addWidget(new QLabel("Stop:"));
|
|
|
|
tb_sweep->addWidget(eStop);
|
|
|
|
|
|
|
|
auto eSpan = new SIUnitEdit("Hz", " kMG", 6);
|
2020-11-23 19:43:24 +08:00
|
|
|
eSpan->setFixedWidth(width);
|
2020-09-17 21:51:20 +08:00
|
|
|
eSpan->setToolTip("Span");
|
|
|
|
connect(eSpan, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetSpan);
|
|
|
|
connect(this, &SpectrumAnalyzer::spanChanged, eSpan, &SIUnitEdit::setValueQuiet);
|
|
|
|
tb_sweep->addWidget(new QLabel("Span:"));
|
|
|
|
tb_sweep->addWidget(eSpan);
|
|
|
|
|
2020-10-25 06:12:46 +08:00
|
|
|
auto bFull = new QPushButton(QIcon::fromTheme("zoom-fit-best", QIcon(":/icons/zoom-fit.png")), "");
|
2020-09-17 21:51:20 +08:00
|
|
|
bFull->setToolTip("Full span");
|
|
|
|
connect(bFull, &QPushButton::clicked, this, &SpectrumAnalyzer::SetFullSpan);
|
|
|
|
tb_sweep->addWidget(bFull);
|
|
|
|
|
2020-10-25 06:12:46 +08:00
|
|
|
auto bZoomIn = new QPushButton(QIcon::fromTheme("zoom-in", QIcon(":/icons/zoom-in.png")), "");
|
2020-09-17 21:51:20 +08:00
|
|
|
bZoomIn->setToolTip("Zoom in");
|
|
|
|
connect(bZoomIn, &QPushButton::clicked, this, &SpectrumAnalyzer::SpanZoomIn);
|
|
|
|
tb_sweep->addWidget(bZoomIn);
|
|
|
|
|
2020-10-25 06:12:46 +08:00
|
|
|
auto bZoomOut = new QPushButton(QIcon::fromTheme("zoom-out", QIcon(":/icons/zoom-out.png")), "");
|
2020-09-17 21:51:20 +08:00
|
|
|
bZoomOut->setToolTip("Zoom out");
|
|
|
|
connect(bZoomOut, &QPushButton::clicked, this, &SpectrumAnalyzer::SpanZoomOut);
|
|
|
|
tb_sweep->addWidget(bZoomOut);
|
|
|
|
|
|
|
|
window->addToolBar(tb_sweep);
|
|
|
|
toolbars.insert(tb_sweep);
|
|
|
|
|
|
|
|
// Acquisition toolbar
|
|
|
|
auto tb_acq = new QToolBar("Acquisition");
|
|
|
|
|
|
|
|
auto eBandwidth = new SIUnitEdit("Hz", " k", 3);
|
|
|
|
eBandwidth->setFixedWidth(70);
|
|
|
|
eBandwidth->setToolTip("RBW");
|
|
|
|
connect(eBandwidth, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetRBW);
|
|
|
|
connect(this, &SpectrumAnalyzer::RBWChanged, eBandwidth, &SIUnitEdit::setValueQuiet);
|
|
|
|
tb_acq->addWidget(new QLabel("RBW:"));
|
|
|
|
tb_acq->addWidget(eBandwidth);
|
|
|
|
|
|
|
|
tb_acq->addWidget(new QLabel("Window:"));
|
2020-10-22 23:13:36 +08:00
|
|
|
cbWindowType = new QComboBox();
|
2020-09-17 21:51:20 +08:00
|
|
|
cbWindowType->addItem("None");
|
|
|
|
cbWindowType->addItem("Kaiser");
|
|
|
|
cbWindowType->addItem("Hann");
|
|
|
|
cbWindowType->addItem("Flat Top");
|
|
|
|
cbWindowType->setCurrentIndex(1);
|
|
|
|
connect(cbWindowType, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) {
|
2021-04-11 18:33:37 +08:00
|
|
|
SetWindow((Window) index);
|
2020-09-17 21:51:20 +08:00
|
|
|
});
|
|
|
|
tb_acq->addWidget(cbWindowType);
|
|
|
|
|
|
|
|
tb_acq->addWidget(new QLabel("Detector:"));
|
2020-10-22 23:13:36 +08:00
|
|
|
cbDetector = new QComboBox();
|
2020-09-17 21:51:20 +08:00
|
|
|
cbDetector->addItem("+Peak");
|
|
|
|
cbDetector->addItem("-Peak");
|
|
|
|
cbDetector->addItem("Sample");
|
|
|
|
cbDetector->addItem("Normal");
|
|
|
|
cbDetector->addItem("Average");
|
|
|
|
cbDetector->setCurrentIndex(0);
|
|
|
|
connect(cbDetector, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) {
|
2021-04-11 18:33:37 +08:00
|
|
|
SetDetector((Detector) index);
|
2020-09-17 21:51:20 +08:00
|
|
|
});
|
|
|
|
tb_acq->addWidget(cbDetector);
|
|
|
|
|
2020-10-23 17:39:07 +08:00
|
|
|
tb_acq->addWidget(new QLabel("Averaging:"));
|
|
|
|
lAverages = new QLabel("0/");
|
|
|
|
tb_acq->addWidget(lAverages);
|
|
|
|
auto sbAverages = new QSpinBox;
|
|
|
|
sbAverages->setRange(1, 100);
|
|
|
|
sbAverages->setRange(1, 99);
|
|
|
|
sbAverages->setFixedWidth(40);
|
|
|
|
connect(sbAverages, qOverload<int>(&QSpinBox::valueChanged), this, &SpectrumAnalyzer::SetAveraging);
|
|
|
|
connect(this, &SpectrumAnalyzer::averagingChanged, sbAverages, &QSpinBox::setValue);
|
|
|
|
tb_acq->addWidget(sbAverages);
|
|
|
|
|
2020-10-22 23:13:36 +08:00
|
|
|
cbSignalID = new QCheckBox("Signal ID");
|
2021-04-11 18:33:37 +08:00
|
|
|
connect(cbSignalID, &QCheckBox::toggled, this, &SpectrumAnalyzer::SetSignalID);
|
2020-09-17 21:51:20 +08:00
|
|
|
tb_acq->addWidget(cbSignalID);
|
|
|
|
|
|
|
|
window->addToolBar(tb_acq);
|
|
|
|
toolbars.insert(tb_acq);
|
|
|
|
|
2020-11-19 02:19:29 +08:00
|
|
|
// Tracking generator toolbar
|
|
|
|
auto tb_trackgen = new QToolBar("Tracking Generator");
|
|
|
|
auto cbTrackGenEnable = new QCheckBox("Tracking Generator");
|
2020-11-21 20:27:23 +08:00
|
|
|
connect(cbTrackGenEnable, &QCheckBox::toggled, this, &SpectrumAnalyzer::SetTGEnabled);
|
2021-04-11 18:33:37 +08:00
|
|
|
connect(this, &SpectrumAnalyzer::TGStateChanged, cbTrackGenEnable, &QCheckBox::setChecked);
|
2020-11-19 02:19:29 +08:00
|
|
|
tb_trackgen->addWidget(cbTrackGenEnable);
|
|
|
|
|
|
|
|
auto cbTrackGenPort = new QComboBox();
|
|
|
|
cbTrackGenPort->addItem("Port 1");
|
|
|
|
cbTrackGenPort->addItem("Port 2");
|
|
|
|
cbTrackGenPort->setCurrentIndex(0);
|
2021-04-11 18:33:37 +08:00
|
|
|
connect(cbTrackGenPort, qOverload<int>(&QComboBox::currentIndexChanged), this, &SpectrumAnalyzer::SetTGPort);
|
|
|
|
connect(this, &SpectrumAnalyzer::TGPortChanged, cbTrackGenPort, qOverload<int>(&QComboBox::setCurrentIndex));
|
2020-11-19 02:19:29 +08:00
|
|
|
tb_trackgen->addWidget(cbTrackGenPort);
|
|
|
|
|
|
|
|
auto dbm = new QDoubleSpinBox();
|
|
|
|
dbm->setFixedWidth(95);
|
|
|
|
dbm->setRange(-100.0, 100.0);
|
|
|
|
dbm->setSingleStep(0.25);
|
|
|
|
dbm->setSuffix("dbm");
|
|
|
|
dbm->setToolTip("Level");
|
|
|
|
dbm->setKeyboardTracking(false);
|
|
|
|
connect(dbm, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &SpectrumAnalyzer::SetTGLevel);
|
|
|
|
connect(this, &SpectrumAnalyzer::TGLevelChanged, dbm, &QDoubleSpinBox::setValue);
|
|
|
|
tb_trackgen->addWidget(new QLabel("Level:"));
|
|
|
|
tb_trackgen->addWidget(dbm);
|
|
|
|
|
|
|
|
auto tgOffset = new SIUnitEdit("Hz", " kMG", 6);
|
2020-11-23 19:43:24 +08:00
|
|
|
tgOffset->setFixedWidth(width);
|
2020-11-19 02:19:29 +08:00
|
|
|
tgOffset->setToolTip("Tracking generator offset");
|
|
|
|
connect(tgOffset, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetTGOffset);
|
|
|
|
connect(this, &SpectrumAnalyzer::TGOffsetChanged, tgOffset, &SIUnitEdit::setValueQuiet);
|
|
|
|
tb_trackgen->addWidget(new QLabel("Offset:"));
|
|
|
|
tb_trackgen->addWidget(tgOffset);
|
|
|
|
|
2020-11-21 20:27:23 +08:00
|
|
|
normalize.enable = new QCheckBox("Normalize");
|
|
|
|
tb_trackgen->addWidget(normalize.enable);
|
|
|
|
connect(normalize.enable, &QCheckBox::toggled, this, &SpectrumAnalyzer::EnableNormalization);
|
|
|
|
normalize.Level = new SIUnitEdit("dBm", " ", 3);
|
2020-11-23 19:43:24 +08:00
|
|
|
normalize.Level->setFixedWidth(width);
|
2020-11-21 20:27:23 +08:00
|
|
|
normalize.Level->setValue(0);
|
|
|
|
normalize.Level->setToolTip("Level to normalize to");
|
|
|
|
tb_trackgen->addWidget(new QLabel("To:"));
|
|
|
|
tb_trackgen->addWidget(normalize.Level);
|
|
|
|
normalize.measure = new QPushButton("Measure");
|
|
|
|
normalize.measure->setToolTip("Perform normalization measurement");
|
|
|
|
connect(normalize.measure, &QPushButton::clicked, this, &SpectrumAnalyzer::MeasureNormalization);
|
|
|
|
tb_trackgen->addWidget(normalize.measure);
|
|
|
|
|
2020-11-19 02:19:29 +08:00
|
|
|
window->addToolBar(tb_trackgen);
|
|
|
|
toolbars.insert(tb_trackgen);
|
2020-09-17 21:51:20 +08:00
|
|
|
|
2020-11-19 05:47:38 +08:00
|
|
|
markerModel = new TraceMarkerModel(traceModel, this);
|
2020-09-17 21:51:20 +08:00
|
|
|
|
|
|
|
auto tracesDock = new QDockWidget("Traces");
|
2021-04-13 01:48:19 +08:00
|
|
|
traceWidget = new TraceWidgetSA(traceModel, window);
|
|
|
|
tracesDock->setWidget(traceWidget);
|
2020-09-17 21:51:20 +08:00
|
|
|
window->addDockWidget(Qt::LeftDockWidgetArea, tracesDock);
|
|
|
|
docks.insert(tracesDock);
|
|
|
|
|
|
|
|
|
|
|
|
auto markerWidget = new MarkerWidget(*markerModel);
|
|
|
|
|
|
|
|
auto markerDock = new QDockWidget("Marker");
|
|
|
|
markerDock->setWidget(markerWidget);
|
|
|
|
window->addDockWidget(Qt::BottomDockWidgetArea, markerDock);
|
|
|
|
docks.insert(markerDock);
|
|
|
|
|
2021-04-11 18:33:37 +08:00
|
|
|
SetupSCPI();
|
2020-11-19 02:19:29 +08:00
|
|
|
|
|
|
|
// Set initial TG settings
|
|
|
|
SetTGLevel(-20.0);
|
|
|
|
SetTGOffset(0);
|
2020-11-21 20:27:23 +08:00
|
|
|
SetTGEnabled(false);
|
2020-11-19 02:19:29 +08:00
|
|
|
|
2020-09-17 21:51:20 +08:00
|
|
|
// Set initial sweep settings
|
2020-10-23 03:12:33 +08:00
|
|
|
auto pref = Preferences::getInstance();
|
2020-10-22 23:13:36 +08:00
|
|
|
if(pref.Startup.RememberSweepSettings) {
|
|
|
|
LoadSweepSettings();
|
|
|
|
} else {
|
|
|
|
settings.f_start = pref.Startup.SA.start;
|
|
|
|
settings.f_stop = pref.Startup.SA.stop;
|
2020-09-17 21:51:20 +08:00
|
|
|
ConstrainAndUpdateFrequencies();
|
2020-10-22 23:13:36 +08:00
|
|
|
SetRBW(pref.Startup.SA.RBW);
|
2020-10-23 17:39:07 +08:00
|
|
|
SetAveraging(pref.Startup.SA.averaging);
|
2020-09-20 16:13:06 +08:00
|
|
|
settings.pointNum = 1001;
|
2020-10-22 23:13:36 +08:00
|
|
|
cbWindowType->setCurrentIndex(pref.Startup.SA.window);
|
|
|
|
cbDetector->setCurrentIndex(pref.Startup.SA.detector);
|
|
|
|
cbSignalID->setChecked(pref.Startup.SA.signalID);
|
|
|
|
}
|
2020-09-17 21:51:20 +08:00
|
|
|
|
|
|
|
finalize(central);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::deactivate()
|
|
|
|
{
|
|
|
|
StoreSweepSettings();
|
|
|
|
Mode::deactivate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::initializeDevice()
|
|
|
|
{
|
|
|
|
connect(window->getDevice(), &Device::SpectrumResultReceived, this, &SpectrumAnalyzer::NewDatapoint, Qt::UniqueConnection);
|
|
|
|
|
|
|
|
// Configure initial state of device
|
|
|
|
window->getDevice()->Configure(settings);
|
|
|
|
}
|
|
|
|
|
2020-12-05 06:49:52 +08:00
|
|
|
nlohmann::json SpectrumAnalyzer::toJSON()
|
|
|
|
{
|
|
|
|
nlohmann::json j;
|
|
|
|
j["traces"] = traceModel.toJSON();
|
|
|
|
j["tiles"] = central->toJSON();
|
2020-12-05 19:59:23 +08:00
|
|
|
j["markers"] = markerModel->toJSON();
|
2020-12-05 06:49:52 +08:00
|
|
|
return j;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::fromJSON(nlohmann::json j)
|
|
|
|
{
|
|
|
|
if(j.contains("traces")) {
|
|
|
|
traceModel.fromJSON(j["traces"]);
|
|
|
|
}
|
|
|
|
if(j.contains("tiles")) {
|
|
|
|
central->fromJSON(j["tiles"]);
|
|
|
|
}
|
2020-12-05 19:59:23 +08:00
|
|
|
if(j.contains("markers")) {
|
|
|
|
markerModel->fromJSON(j["markers"]);
|
|
|
|
}
|
2020-12-05 06:49:52 +08:00
|
|
|
}
|
|
|
|
|
2020-09-17 21:51:20 +08:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
|
|
|
|
{
|
|
|
|
d = average.process(d);
|
2020-11-21 20:27:23 +08:00
|
|
|
|
|
|
|
if(normalize.measuring) {
|
|
|
|
if(average.currentSweep() == averages) {
|
|
|
|
// this is the last averaging sweep, use values for normalization
|
|
|
|
if(normalize.port1Correction.size() > 0 || d.pointNum == 0) {
|
|
|
|
// add measurement
|
|
|
|
normalize.port1Correction.push_back(d.port1);
|
|
|
|
normalize.port2Correction.push_back(d.port2);
|
|
|
|
if(d.pointNum == settings.pointNum - 1) {
|
|
|
|
// this was the last point
|
|
|
|
normalize.measuring = false;
|
|
|
|
normalize.f_start = settings.f_start;
|
|
|
|
normalize.f_stop = settings.f_stop;
|
|
|
|
normalize.points = settings.pointNum;
|
|
|
|
EnableNormalization(true);
|
|
|
|
qDebug() << "Normalization measuremen complete";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int percentage = (((average.currentSweep() - 1) * 100) + (d.pointNum + 1) * 100 / settings.pointNum) / averages;
|
|
|
|
normalize.dialog.setValue(percentage);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(normalize.active) {
|
|
|
|
d.port1 /= normalize.port1Correction[d.pointNum];
|
|
|
|
d.port2 /= normalize.port2Correction[d.pointNum];
|
|
|
|
double corr = pow(10.0, normalize.Level->value() / 20.0);
|
|
|
|
d.port1 *= corr;
|
|
|
|
d.port2 *= corr;
|
|
|
|
}
|
|
|
|
|
2020-11-09 04:28:47 +08:00
|
|
|
traceModel.addSAData(d, settings);
|
2020-09-17 21:51:20 +08:00
|
|
|
emit dataChanged();
|
2020-10-20 23:03:49 +08:00
|
|
|
if(d.pointNum == settings.pointNum - 1) {
|
2020-10-23 17:39:07 +08:00
|
|
|
UpdateAverageCount();
|
2020-10-20 23:03:49 +08:00
|
|
|
markerModel->updateMarkers();
|
|
|
|
}
|
2020-09-17 21:51:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SettingsChanged()
|
|
|
|
{
|
2020-09-20 16:13:06 +08:00
|
|
|
if(settings.f_stop - settings.f_start >= 1000) {
|
|
|
|
settings.pointNum = 1001;
|
|
|
|
} else {
|
|
|
|
settings.pointNum = settings.f_stop - settings.f_start + 1;
|
|
|
|
}
|
2020-11-18 06:03:13 +08:00
|
|
|
settings.applyReceiverCorrection = 1;
|
2020-11-19 02:19:29 +08:00
|
|
|
settings.applySourceCorrection = 1;
|
2020-09-20 16:13:06 +08:00
|
|
|
|
2020-11-07 20:22:10 +08:00
|
|
|
auto pref = Preferences::getInstance();
|
2020-11-19 02:19:29 +08:00
|
|
|
if(!settings.trackingGenerator && pref.Acquisition.useDFTinSAmode && settings.RBW <= pref.Acquisition.RBWLimitForDFT) {
|
|
|
|
// Enable DFT if below RBW threshold and TG is not enabled
|
2020-11-07 20:22:10 +08:00
|
|
|
settings.UseDFT = 1;
|
|
|
|
} else {
|
|
|
|
settings.UseDFT = 0;
|
|
|
|
}
|
|
|
|
|
2020-11-19 05:47:38 +08:00
|
|
|
if(settings.trackingGenerator && settings.f_stop >= 25000000) {
|
|
|
|
// Check point spacing.
|
|
|
|
// The highband PLL used as the tracking generator is not able to reach every frequency exactly. This
|
|
|
|
// could lead to sharp drops in the spectrum at certain frequencies. If the span is wide enough with
|
|
|
|
// respect to the point number, it is ensured that every displayed point has at least one sample with
|
|
|
|
// a reachable PLL frequency in it. Display a warning message if this is not the case with the current
|
|
|
|
// settings.
|
|
|
|
auto pointSpacing = (settings.f_stop - settings.f_start) / (settings.pointNum - 1);
|
|
|
|
// The frequency resolution of the PLL is frequency dependent (due to PLL divider).
|
|
|
|
// This code assumes some knowledge of the actual hardware and probably should be moved
|
|
|
|
// onto the device at some point
|
|
|
|
double minSpacing = 25000;
|
|
|
|
auto stop = settings.f_stop;
|
|
|
|
while(stop <= 3000000000) {
|
|
|
|
minSpacing /= 2;
|
|
|
|
stop *= 2;
|
|
|
|
}
|
|
|
|
if(pointSpacing < minSpacing) {
|
|
|
|
auto requiredMinSpan = minSpacing * (settings.pointNum - 1);
|
|
|
|
auto message = QString() + "Due to PLL limitations, the tracking generator can not reach every frequency exactly. "
|
|
|
|
"With your current span, this could result in the signal not being detected at some bands. A minimum"
|
|
|
|
" span of " + Unit::ToString(requiredMinSpan, "Hz", " kMG") + " is recommended at this stop frequency.";
|
|
|
|
InformationBox::ShowMessage("Warning", message, "TrackingGeneratorSpanTooSmallWarning");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-21 20:27:23 +08:00
|
|
|
if(normalize.active) {
|
|
|
|
// check if normalization is still valid
|
|
|
|
if(normalize.f_start != settings.f_start || normalize.f_stop != settings.f_stop || normalize.points != settings.pointNum) {
|
|
|
|
// normalization was taken at different settings, disable
|
|
|
|
EnableNormalization(false);
|
|
|
|
InformationBox::ShowMessage("Information", "Normalization was disabled because the span has been changed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-11 18:33:37 +08:00
|
|
|
if(window->getDevice() && Mode::getActiveMode() == this) {
|
2020-09-17 21:51:20 +08:00
|
|
|
window->getDevice()->Configure(settings);
|
|
|
|
}
|
2020-10-30 02:27:04 +08:00
|
|
|
average.reset(settings.pointNum);
|
2020-10-23 17:39:07 +08:00
|
|
|
UpdateAverageCount();
|
2020-09-17 21:51:20 +08:00
|
|
|
traceModel.clearVNAData();
|
2020-09-18 01:54:03 +08:00
|
|
|
emit traceModel.SpanChanged(settings.f_start, settings.f_stop);
|
2020-09-17 21:51:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::StartImpedanceMatching()
|
|
|
|
{
|
|
|
|
auto dialog = new ImpedanceMatchDialog(*markerModel);
|
|
|
|
dialog->show();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SetStartFreq(double freq)
|
|
|
|
{
|
|
|
|
settings.f_start = freq;
|
|
|
|
if(settings.f_stop < freq) {
|
|
|
|
settings.f_stop = freq;
|
|
|
|
}
|
|
|
|
ConstrainAndUpdateFrequencies();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SetStopFreq(double freq)
|
|
|
|
{
|
|
|
|
settings.f_stop = freq;
|
|
|
|
if(settings.f_start > freq) {
|
|
|
|
settings.f_start = freq;
|
|
|
|
}
|
|
|
|
ConstrainAndUpdateFrequencies();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SetCenterFreq(double freq)
|
|
|
|
{
|
|
|
|
auto old_span = settings.f_stop - settings.f_start;
|
2020-11-13 01:56:39 +08:00
|
|
|
if (freq - old_span / 2 <= Device::Info().limits_minFreq) {
|
|
|
|
// would shift start frequency below minimum
|
2020-09-17 21:51:20 +08:00
|
|
|
settings.f_start = 0;
|
|
|
|
settings.f_stop = 2 * freq;
|
2020-11-13 01:56:39 +08:00
|
|
|
} else if(freq + old_span / 2 >= Device::Info().limits_maxFreq) {
|
|
|
|
// would shift stop frequency above maximum
|
|
|
|
settings.f_start = 2 * freq - Device::Info().limits_maxFreq;
|
|
|
|
settings.f_stop = Device::Info().limits_maxFreq;
|
|
|
|
} else {
|
|
|
|
settings.f_start = freq - old_span / 2;
|
|
|
|
settings.f_stop = freq + old_span / 2;
|
2020-09-17 21:51:20 +08:00
|
|
|
}
|
|
|
|
ConstrainAndUpdateFrequencies();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SetSpan(double span)
|
|
|
|
{
|
|
|
|
auto old_center = (settings.f_start + settings.f_stop) / 2;
|
2020-11-13 01:56:39 +08:00
|
|
|
if(old_center < Device::Info().limits_minFreq + span / 2) {
|
|
|
|
// would shift start frequency below minimum
|
|
|
|
settings.f_start = Device::Info().limits_minFreq;
|
|
|
|
settings.f_stop = Device::Info().limits_minFreq + span;
|
|
|
|
} else if(old_center > Device::Info().limits_maxFreq - span / 2) {
|
|
|
|
// would shift stop frequency above maximum
|
|
|
|
settings.f_start = Device::Info().limits_maxFreq - span;
|
|
|
|
settings.f_stop = Device::Info().limits_maxFreq;
|
2020-09-17 21:51:20 +08:00
|
|
|
} else {
|
2020-11-13 01:56:39 +08:00
|
|
|
settings.f_start = old_center - span / 2;
|
|
|
|
settings.f_stop = settings.f_start + span;
|
2020-09-17 21:51:20 +08:00
|
|
|
}
|
|
|
|
ConstrainAndUpdateFrequencies();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SetFullSpan()
|
|
|
|
{
|
2020-11-07 20:22:10 +08:00
|
|
|
settings.f_start = Device::Info().limits_minFreq;
|
|
|
|
settings.f_stop = Device::Info().limits_maxFreq;
|
2020-09-17 21:51:20 +08:00
|
|
|
ConstrainAndUpdateFrequencies();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SpanZoomIn()
|
|
|
|
{
|
|
|
|
auto center = (settings.f_start + settings.f_stop) / 2;
|
|
|
|
auto old_span = settings.f_stop - settings.f_start;
|
|
|
|
settings.f_start = center - old_span / 4;
|
|
|
|
settings.f_stop = center + old_span / 4;
|
|
|
|
ConstrainAndUpdateFrequencies();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SpanZoomOut()
|
|
|
|
{
|
|
|
|
auto center = (settings.f_start + settings.f_stop) / 2;
|
|
|
|
auto old_span = settings.f_stop - settings.f_start;
|
|
|
|
if(center > old_span) {
|
|
|
|
settings.f_start = center - old_span;
|
|
|
|
} else {
|
|
|
|
settings.f_start = 0;
|
|
|
|
}
|
|
|
|
settings.f_stop = center + old_span;
|
|
|
|
ConstrainAndUpdateFrequencies();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SetRBW(double bandwidth)
|
|
|
|
{
|
2020-11-07 20:22:10 +08:00
|
|
|
if(bandwidth > Device::Info().limits_maxRBW) {
|
|
|
|
bandwidth = Device::Info().limits_maxRBW;
|
|
|
|
} else if(bandwidth < Device::Info().limits_minRBW) {
|
|
|
|
bandwidth = Device::Info().limits_minRBW;
|
2020-09-27 05:34:31 +08:00
|
|
|
}
|
2020-09-17 21:51:20 +08:00
|
|
|
settings.RBW = bandwidth;
|
|
|
|
emit RBWChanged(settings.RBW);
|
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
|
2021-04-11 18:33:37 +08:00
|
|
|
void SpectrumAnalyzer::SetWindow(SpectrumAnalyzer::Window w)
|
|
|
|
{
|
|
|
|
settings.WindowType = (int) w;
|
|
|
|
cbWindowType->setCurrentIndex((int) w);
|
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SetDetector(SpectrumAnalyzer::Detector d)
|
|
|
|
{
|
|
|
|
settings.Detector = (int) d;
|
|
|
|
cbDetector->setCurrentIndex((int) d);
|
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
|
2020-09-17 21:51:20 +08:00
|
|
|
void SpectrumAnalyzer::SetAveraging(unsigned int averages)
|
|
|
|
{
|
|
|
|
this->averages = averages;
|
|
|
|
average.setAverages(averages);
|
|
|
|
emit averagingChanged(averages);
|
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
|
2021-04-11 18:33:37 +08:00
|
|
|
void SpectrumAnalyzer::SetSignalID(bool enabled)
|
|
|
|
{
|
|
|
|
settings.SignalID = enabled ? 1 : 0;
|
|
|
|
cbSignalID->setChecked(enabled);
|
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
|
2020-11-21 20:27:23 +08:00
|
|
|
void SpectrumAnalyzer::SetTGEnabled(bool enabled)
|
|
|
|
{
|
|
|
|
if(enabled != settings.trackingGenerator) {
|
|
|
|
settings.trackingGenerator = enabled;
|
2021-04-11 18:33:37 +08:00
|
|
|
emit TGStateChanged(enabled);
|
2020-11-21 20:27:23 +08:00
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
normalize.Level->setEnabled(enabled);
|
|
|
|
normalize.enable->setEnabled(enabled);
|
|
|
|
normalize.measure->setEnabled(enabled);
|
|
|
|
if(!enabled && normalize.active) {
|
|
|
|
// disable normalization when TG is turned off
|
|
|
|
EnableNormalization(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-11 18:33:37 +08:00
|
|
|
void SpectrumAnalyzer::SetTGPort(int port)
|
|
|
|
{
|
|
|
|
if(port < 01 || port > 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(port != settings.trackingGeneratorPort) {
|
|
|
|
settings.trackingGeneratorPort = port;
|
|
|
|
emit TGPortChanged(port);
|
|
|
|
if(settings.trackingGenerator) {
|
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-19 02:19:29 +08:00
|
|
|
void SpectrumAnalyzer::SetTGLevel(double level)
|
|
|
|
{
|
|
|
|
if(level > Device::Info().limits_cdbm_max / 100.0) {
|
|
|
|
level = Device::Info().limits_cdbm_max / 100.0;
|
|
|
|
} else if(level < Device::Info().limits_cdbm_min / 100.0) {
|
|
|
|
level = Device::Info().limits_cdbm_min / 100.0;
|
|
|
|
}
|
|
|
|
emit TGLevelChanged(level);
|
|
|
|
settings.trackingPower = level * 100;
|
|
|
|
if(settings.trackingGenerator) {
|
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SetTGOffset(double offset)
|
|
|
|
{
|
|
|
|
settings.trackingGeneratorOffset = offset;
|
|
|
|
|
|
|
|
ConstrainAndUpdateFrequencies();
|
|
|
|
if(settings.trackingGenerator) {
|
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-21 20:27:23 +08:00
|
|
|
void SpectrumAnalyzer::MeasureNormalization()
|
|
|
|
{
|
|
|
|
normalize.active = false;
|
|
|
|
normalize.port1Correction.clear();
|
|
|
|
normalize.port2Correction.clear();
|
|
|
|
normalize.measuring = true;
|
|
|
|
normalize.dialog.setLabelText("Taking normalization measurement...");
|
|
|
|
normalize.dialog.setCancelButtonText("Abort");
|
|
|
|
normalize.dialog.setWindowTitle("Normalization");
|
|
|
|
normalize.dialog.setValue(0);
|
|
|
|
normalize.dialog.setWindowModality(Qt::ApplicationModal);
|
|
|
|
// always show the dialog
|
|
|
|
normalize.dialog.setMinimumDuration(0);
|
|
|
|
connect(&normalize.dialog, &QProgressDialog::canceled, this, &SpectrumAnalyzer::AbortNormalization);
|
|
|
|
// trigger beginning of next sweep
|
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::AbortNormalization()
|
|
|
|
{
|
|
|
|
EnableNormalization(false);
|
|
|
|
normalize.measuring = false;
|
|
|
|
normalize.points = 0;
|
|
|
|
normalize.dialog.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::EnableNormalization(bool enabled)
|
|
|
|
{
|
|
|
|
if(enabled != normalize.active) {
|
|
|
|
if(enabled) {
|
|
|
|
// check if measurements already taken
|
|
|
|
if(normalize.f_start == settings.f_start && normalize.f_stop == settings.f_stop && normalize.points == settings.pointNum) {
|
|
|
|
// same settings as with normalization measurement, can enable
|
|
|
|
normalize.active = true;
|
|
|
|
} else {
|
|
|
|
// needs to take measurement first
|
|
|
|
MeasureNormalization();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// disabled
|
|
|
|
normalize.active = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
normalize.enable->blockSignals(true);
|
|
|
|
normalize.enable->setChecked(normalize.active);
|
|
|
|
normalize.enable->blockSignals(false);
|
|
|
|
}
|
|
|
|
|
2021-04-11 18:33:37 +08:00
|
|
|
void SpectrumAnalyzer::SetNormalizationLevel(double level)
|
|
|
|
{
|
|
|
|
normalize.Level->setValueQuiet(level);
|
|
|
|
emit NormalizationLevelChanged(level);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::SetupSCPI()
|
|
|
|
{
|
|
|
|
auto scpi_freq = new SCPINode("FREQuency");
|
|
|
|
SCPINode::add(scpi_freq);
|
|
|
|
auto toULong = [](QStringList params) {
|
|
|
|
bool ok;
|
|
|
|
if(params.size() != 1) {
|
|
|
|
return std::numeric_limits<unsigned long>::max();
|
|
|
|
}
|
|
|
|
auto newval = params[0].toULong(&ok);
|
|
|
|
if(!ok) {
|
|
|
|
return std::numeric_limits<unsigned long>::max();
|
|
|
|
} else {
|
|
|
|
return newval;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
scpi_freq->add(new SCPICommand("SPAN", [=](QStringList params) -> QString {
|
|
|
|
auto newval = toULong(params);
|
|
|
|
if(newval == std::numeric_limits<unsigned long>::max()) {
|
|
|
|
return "ERROR";
|
|
|
|
} else {
|
|
|
|
SetSpan(newval);
|
|
|
|
return "";
|
|
|
|
}
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return QString::number(settings.f_stop - settings.f_start);
|
|
|
|
}));
|
|
|
|
scpi_freq->add(new SCPICommand("START", [=](QStringList params) -> QString {
|
|
|
|
auto newval = toULong(params);
|
|
|
|
if(newval == std::numeric_limits<unsigned long>::max()) {
|
|
|
|
return "ERROR";
|
|
|
|
} else {
|
|
|
|
SetStartFreq(newval);
|
|
|
|
return "";
|
|
|
|
}
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return QString::number(settings.f_start);
|
|
|
|
}));
|
|
|
|
scpi_freq->add(new SCPICommand("CENTer", [=](QStringList params) -> QString {
|
|
|
|
auto newval = toULong(params);
|
|
|
|
if(newval == std::numeric_limits<unsigned long>::max()) {
|
|
|
|
return "ERROR";
|
|
|
|
} else {
|
|
|
|
SetCenterFreq(newval);
|
|
|
|
return "";
|
|
|
|
}
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return QString::number((settings.f_start + settings.f_stop)/2);
|
|
|
|
}));
|
|
|
|
scpi_freq->add(new SCPICommand("STOP", [=](QStringList params) -> QString {
|
|
|
|
auto newval = toULong(params);
|
|
|
|
if(newval == std::numeric_limits<unsigned long>::max()) {
|
|
|
|
return "ERROR";
|
|
|
|
} else {
|
|
|
|
SetStopFreq(newval);
|
|
|
|
return "";
|
|
|
|
}
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return QString::number(settings.f_stop);
|
|
|
|
}));
|
|
|
|
scpi_freq->add(new SCPICommand("FULL", [=](QStringList params) -> QString {
|
2021-04-13 01:48:19 +08:00
|
|
|
Q_UNUSED(params)
|
2021-04-11 18:33:37 +08:00
|
|
|
SetFullSpan();
|
|
|
|
return "";
|
|
|
|
}, nullptr));
|
|
|
|
auto scpi_acq = new SCPINode("ACQuisition");
|
|
|
|
SCPINode::add(scpi_acq);
|
|
|
|
scpi_acq->add(new SCPICommand("RBW", [=](QStringList params) -> QString {
|
|
|
|
auto newval = toULong(params);
|
|
|
|
if(newval == std::numeric_limits<unsigned long>::max()) {
|
|
|
|
return "ERROR";
|
|
|
|
} else {
|
|
|
|
SetRBW(newval);
|
|
|
|
return "";
|
|
|
|
}
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return QString::number(settings.RBW);
|
|
|
|
}));
|
|
|
|
scpi_acq->add(new SCPICommand("WINDow", [=](QStringList params) -> QString {
|
|
|
|
if (params.size() != 1) {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
if (params[0] == "NONE") {
|
|
|
|
SetWindow(Window::None);
|
|
|
|
} else if(params[0] == "KAISER") {
|
|
|
|
SetWindow(Window::Kaiser);
|
|
|
|
} else if(params[0] == "HANN") {
|
|
|
|
SetWindow(Window::Hann);
|
|
|
|
} else if(params[0] == "FLATTOP") {
|
|
|
|
SetWindow(Window::FlatTop);
|
|
|
|
} else {
|
|
|
|
return "INVALID MDOE";
|
|
|
|
}
|
|
|
|
return "";
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
switch((Window) settings.WindowType) {
|
|
|
|
case Window::None: return "NONE";
|
|
|
|
case Window::Kaiser: return "KAISER";
|
|
|
|
case Window::Hann: return "HANN";
|
|
|
|
case Window::FlatTop: return "FLATTOP";
|
|
|
|
default: return "ERROR";
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
scpi_acq->add(new SCPICommand("WINDow", [=](QStringList params) -> QString {
|
|
|
|
if (params.size() != 1) {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
if (params[0] == "+PEAK") {
|
|
|
|
SetDetector(Detector::PPeak);
|
|
|
|
} else if(params[0] == "-PEAK") {
|
|
|
|
SetDetector(Detector::NPeak);
|
|
|
|
} else if(params[0] == "NORMAL") {
|
|
|
|
SetDetector(Detector::Normal);
|
|
|
|
} else if(params[0] == "SAMPLE") {
|
|
|
|
SetDetector(Detector::Sample);
|
|
|
|
} else if(params[0] == "AVERAGE") {
|
|
|
|
SetDetector(Detector::Average);
|
|
|
|
} else {
|
|
|
|
return "INVALID MDOE";
|
|
|
|
}
|
|
|
|
return "";
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
switch((Detector) settings.Detector) {
|
|
|
|
case Detector::PPeak: return "+PEAK";
|
|
|
|
case Detector::NPeak: return "-PEAK";
|
|
|
|
case Detector::Normal: return "NORMAL";
|
|
|
|
case Detector::Sample: return "SAMPLE";
|
|
|
|
case Detector::Average: return "AVERAGE";
|
|
|
|
default: return "ERROR";
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
scpi_acq->add(new SCPICommand("AVG", [=](QStringList params) -> QString {
|
|
|
|
auto newval = toULong(params);
|
|
|
|
if(newval == std::numeric_limits<unsigned long>::max()) {
|
|
|
|
return "ERROR";
|
|
|
|
} else {
|
|
|
|
SetAveraging(newval);
|
|
|
|
return "";
|
|
|
|
}
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return QString::number(averages);
|
|
|
|
}));
|
|
|
|
scpi_acq->add(new SCPICommand("SIGid", [=](QStringList params) -> QString {
|
|
|
|
if (params.size() != 1) {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
if(params[0] == "1" || params[0] == "ON") {
|
|
|
|
SetSignalID(true);
|
|
|
|
} else if(params[0] == "0" || params[0] == "OFF") {
|
|
|
|
SetSignalID(false);
|
|
|
|
} else {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
return "";
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return settings.SignalID ? "1" : "0";
|
|
|
|
}));
|
|
|
|
auto scpi_tg = new SCPINode("TRACKing");
|
|
|
|
SCPINode::add(scpi_tg);
|
|
|
|
scpi_tg->add(new SCPICommand("ENable", [=](QStringList params) -> QString {
|
|
|
|
if (params.size() != 1) {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
if(params[0] == "1" || params[0] == "ON") {
|
|
|
|
SetTGEnabled(true);
|
|
|
|
} else if(params[0] == "0" || params[0] == "OFF") {
|
|
|
|
SetTGEnabled(false);
|
|
|
|
} else {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
return "";
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return settings.trackingGenerator ? "1" : "0";
|
|
|
|
}));
|
|
|
|
scpi_tg->add(new SCPICommand("Port", [=](QStringList params) -> QString {
|
|
|
|
if (params.size() != 1) {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
if(params[0] == "1") {
|
|
|
|
SetTGPort(0);
|
|
|
|
} else if(params[0] == "2") {
|
|
|
|
SetTGPort(1);
|
|
|
|
} else {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
return "";
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return settings.trackingGeneratorPort ? "2" : "1";
|
|
|
|
}));
|
|
|
|
scpi_tg->add(new SCPICommand("LVL", [=](QStringList params) -> QString {
|
|
|
|
bool ok;
|
|
|
|
if(params.size() != 1) {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
auto newval = params[0].toDouble(&ok);
|
|
|
|
if(!ok) {
|
|
|
|
return "ERROR";
|
|
|
|
} else {
|
|
|
|
SetTGLevel(newval);
|
|
|
|
return "";
|
|
|
|
}
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return QString::number(settings.trackingPower / 100.0);
|
|
|
|
}));
|
|
|
|
scpi_tg->add(new SCPICommand("OFFset", [=](QStringList params) -> QString {
|
|
|
|
bool ok;
|
|
|
|
if(params.size() != 1) {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
auto newval = params[0].toLong(&ok);
|
|
|
|
if(!ok) {
|
|
|
|
return "ERROR";
|
|
|
|
} else {
|
|
|
|
SetTGOffset(newval);
|
|
|
|
return "";
|
|
|
|
}
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return QString::number(settings.trackingGeneratorOffset);
|
|
|
|
}));
|
|
|
|
auto scpi_norm = new SCPINode("NORMalize");
|
|
|
|
scpi_tg->add(scpi_norm);
|
|
|
|
scpi_norm->add(new SCPICommand("ENable", [=](QStringList params) -> QString {
|
|
|
|
if (params.size() != 1) {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
if(params[0] == "1" || params[0] == "ON") {
|
|
|
|
EnableNormalization(true);
|
|
|
|
} else if(params[0] == "0" || params[0] == "OFF") {
|
|
|
|
EnableNormalization(false);
|
|
|
|
} else {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
return "";
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return normalize.active ? "1" : "0";
|
|
|
|
}));
|
|
|
|
scpi_norm->add(new SCPICommand("MEASure", [=](QStringList params) -> QString {
|
|
|
|
Q_UNUSED(params)
|
|
|
|
MeasureNormalization();
|
|
|
|
return "";
|
|
|
|
}, nullptr));
|
|
|
|
scpi_norm->add(new SCPICommand("LVL", [=](QStringList params) -> QString {
|
|
|
|
bool ok;
|
|
|
|
if(params.size() != 1) {
|
|
|
|
return "ERROR";
|
|
|
|
}
|
|
|
|
auto newval = params[0].toDouble(&ok);
|
|
|
|
if(!ok) {
|
|
|
|
return "ERROR";
|
|
|
|
} else {
|
|
|
|
SetNormalizationLevel(newval);
|
|
|
|
return "";
|
|
|
|
}
|
2021-04-13 01:48:19 +08:00
|
|
|
}, [=](QStringList) -> QString {
|
2021-04-11 18:33:37 +08:00
|
|
|
return QString::number(normalize.Level->value());
|
|
|
|
}));
|
2021-04-13 01:48:19 +08:00
|
|
|
SCPINode::add(traceWidget);
|
2021-04-11 18:33:37 +08:00
|
|
|
}
|
|
|
|
|
2020-10-23 17:39:07 +08:00
|
|
|
void SpectrumAnalyzer::UpdateAverageCount()
|
|
|
|
{
|
|
|
|
lAverages->setText(QString::number(average.getLevel()) + "/");
|
|
|
|
}
|
|
|
|
|
2020-09-17 21:51:20 +08:00
|
|
|
void SpectrumAnalyzer::ConstrainAndUpdateFrequencies()
|
|
|
|
{
|
2020-11-07 20:22:10 +08:00
|
|
|
if(settings.f_stop > Device::Info().limits_maxFreq) {
|
|
|
|
settings.f_stop = Device::Info().limits_maxFreq;
|
2020-09-17 21:51:20 +08:00
|
|
|
}
|
|
|
|
if(settings.f_start > settings.f_stop) {
|
|
|
|
settings.f_start = settings.f_stop;
|
|
|
|
}
|
2020-11-07 20:22:10 +08:00
|
|
|
if(settings.f_start < Device::Info().limits_minFreq) {
|
|
|
|
settings.f_start = Device::Info().limits_minFreq;
|
2020-09-27 05:34:31 +08:00
|
|
|
}
|
2020-11-19 02:19:29 +08:00
|
|
|
|
|
|
|
bool trackingOffset_limited = false;
|
|
|
|
if(settings.f_stop + settings.trackingGeneratorOffset > Device::Info().limits_maxFreq) {
|
|
|
|
trackingOffset_limited = true;
|
|
|
|
settings.trackingGeneratorOffset = Device::Info().limits_maxFreq - settings.f_stop;
|
|
|
|
}
|
2020-11-23 04:25:41 +08:00
|
|
|
if((long) settings.f_start + settings.trackingGeneratorOffset < (long) Device::Info().limits_minFreq) {
|
2020-11-19 02:19:29 +08:00
|
|
|
trackingOffset_limited = true;
|
|
|
|
settings.trackingGeneratorOffset = Device::Info().limits_minFreq - settings.f_start;
|
|
|
|
}
|
|
|
|
if(trackingOffset_limited) {
|
|
|
|
InformationBox::ShowMessage("Warning", "The selected tracking generator offset is not reachable for all frequencies with the current span. "
|
|
|
|
"The tracking generator offset has been constrained according to the selected start and stop frequencies");
|
|
|
|
}
|
2020-09-17 21:51:20 +08:00
|
|
|
emit startFreqChanged(settings.f_start);
|
|
|
|
emit stopFreqChanged(settings.f_stop);
|
|
|
|
emit spanChanged(settings.f_stop - settings.f_start);
|
|
|
|
emit centerFreqChanged((settings.f_stop + settings.f_start)/2);
|
2020-11-19 02:19:29 +08:00
|
|
|
emit TGOffsetChanged(settings.trackingGeneratorOffset);
|
2020-09-17 21:51:20 +08:00
|
|
|
SettingsChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::LoadSweepSettings()
|
|
|
|
{
|
2020-10-22 23:13:36 +08:00
|
|
|
QSettings s;
|
2020-10-23 03:12:33 +08:00
|
|
|
auto pref = Preferences::getInstance();
|
2020-10-22 23:13:36 +08:00
|
|
|
settings.f_start = s.value("SAStart", pref.Startup.SA.start).toULongLong();
|
|
|
|
settings.f_stop = s.value("SAStop", pref.Startup.SA.stop).toULongLong();
|
|
|
|
ConstrainAndUpdateFrequencies();
|
|
|
|
SetRBW(s.value("SARBW", pref.Startup.SA.RBW).toUInt());
|
|
|
|
settings.pointNum = 1001;
|
|
|
|
cbWindowType->setCurrentIndex(s.value("SAWindow", pref.Startup.SA.window).toInt());
|
|
|
|
cbDetector->setCurrentIndex(s.value("SADetector", pref.Startup.SA.detector).toInt());
|
2020-10-23 17:39:07 +08:00
|
|
|
SetAveraging(s.value("SAAveraging", pref.Startup.SA.averaging).toInt());
|
2020-10-22 23:13:36 +08:00
|
|
|
cbSignalID->setChecked(s.value("SASignalID", pref.Startup.SA.signalID).toBool());
|
2020-09-17 21:51:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumAnalyzer::StoreSweepSettings()
|
|
|
|
{
|
2020-10-22 23:13:36 +08:00
|
|
|
QSettings s;
|
|
|
|
s.setValue("SAStart", static_cast<unsigned long long>(settings.f_start));
|
|
|
|
s.setValue("SAStop", static_cast<unsigned long long>(settings.f_stop));
|
|
|
|
s.setValue("SARBW", settings.RBW);
|
|
|
|
s.setValue("SAWindow", settings.WindowType);
|
|
|
|
s.setValue("SADetector", settings.Detector);
|
2020-10-23 17:39:07 +08:00
|
|
|
s.setValue("SAAveraging", averages);
|
2020-10-22 23:13:36 +08:00
|
|
|
s.setValue("SASignalID", static_cast<bool>(settings.SignalID));
|
2020-09-17 21:51:20 +08:00
|
|
|
}
|