From eff18a22e8751bda35382e781038674dddc6cfef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Sun, 30 Oct 2022 12:07:59 +0100 Subject: [PATCH] Improve load time of setup files by omitting excessive device configuration --- .../SpectrumAnalyzer/spectrumanalyzer.cpp | 160 +++++++------- .../SpectrumAnalyzer/spectrumanalyzer.h | 3 + .../PC_Application/LibreVNA-GUI/VNA/vna.cpp | 196 +++++++++--------- .../PC_Application/LibreVNA-GUI/VNA/vna.h | 4 +- .../PC_Application/LibreVNA-GUI/appwindow.cpp | 13 ++ .../LibreVNA-GUI/modehandler.cpp | 8 +- .../PC_Application/LibreVNA-GUI/modehandler.h | 2 +- 7 files changed, 213 insertions(+), 173 deletions(-) diff --git a/Software/PC_Application/LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.cpp b/Software/PC_Application/LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.cpp index 8e32edf..ec6087e 100644 --- a/Software/PC_Application/LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.cpp +++ b/Software/PC_Application/LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.cpp @@ -64,6 +64,11 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name) normalize.measure = nullptr; normalize.enable = nullptr; + configurationTimer.setSingleShot(true); + connect(&configurationTimer, &QTimer::timeout, this, [=](){ + ConfigureDevice(); + }); + traceModel.setSource(TraceModel::DataSource::SA); // Create default traces @@ -543,77 +548,7 @@ void SpectrumAnalyzer::NewDatapoint(VirtualDevice::SAMeasurement m) void SpectrumAnalyzer::SettingsChanged() { - if(running) { - changingSettings = true; - if(settings.freqStop - settings.freqStart >= 1000 || settings.freqStop - settings.freqStart <= 0) { - settings.points = 1001; - } else { - settings.points = settings.freqStop - settings.freqStart + 1; - } - - if(settings.trackingGenerator && settings.freqStop >= 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.freqStop - settings.freqStart) / (settings.points - 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.freqStop; - while(stop <= 3000000000) { - minSpacing /= 2; - stop *= 2; - } - if(pointSpacing < minSpacing) { - auto requiredMinSpan = minSpacing * (settings.points - 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"); - } - } - - if(normalize.active) { - // check if normalization is still valid - if(normalize.f_start != settings.freqStart || normalize.f_stop != settings.freqStop || normalize.points != settings.points) { - // normalization was taken at different settings, disable - EnableNormalization(false); - InformationBox::ShowMessage("Information", "Normalization was disabled because the span has been changed"); - } - } - - if(window->getDevice() && isActive) { - window->getDevice()->setSA(settings, [=](bool){ - // device received command - changingSettings = false; - }); - emit sweepStarted(); - } else { - // no device, unable to start sweep - emit sweepStopped(); - changingSettings = false; - } - average.reset(settings.points); - UpdateAverageCount(); - traceModel.clearLiveData(); - emit traceModel.SpanChanged(settings.freqStart, settings.freqStop); - } else { - if(window->getDevice()) { - changingSettings = true; - // single sweep finished - window->getDevice()->setIdle([=](bool){ - emit sweepStopped(); - changingSettings = false; - }); - } else { - emit sweepStopped(); - changingSettings = false; - } - } + configurationTimer.start(100); } void SpectrumAnalyzer::SetStartFreq(double freq) @@ -718,7 +653,9 @@ void SpectrumAnalyzer::SetSingleSweep(bool single) singleSweep = single; emit singleSweepChanged(single); } - SettingsChanged(); + if(single) { + Run(); + } } void SpectrumAnalyzer::SetRBW(double bandwidth) @@ -888,13 +825,88 @@ void SpectrumAnalyzer::SetNormalizationLevel(double level) void SpectrumAnalyzer::Run() { running = true; - SettingsChanged(); + ConfigureDevice(); } void SpectrumAnalyzer::Stop() { running = false; - SettingsChanged(); + ConfigureDevice(); +} + +void SpectrumAnalyzer::ConfigureDevice() +{ + if(running) { + changingSettings = true; + if(settings.freqStop - settings.freqStart >= 1000 || settings.freqStop - settings.freqStart <= 0) { + settings.points = 1001; + } else { + settings.points = settings.freqStop - settings.freqStart + 1; + } + + if(settings.trackingGenerator && settings.freqStop >= 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.freqStop - settings.freqStart) / (settings.points - 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.freqStop; + while(stop <= 3000000000) { + minSpacing /= 2; + stop *= 2; + } + if(pointSpacing < minSpacing) { + auto requiredMinSpan = minSpacing * (settings.points - 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"); + } + } + + if(normalize.active) { + // check if normalization is still valid + if(normalize.f_start != settings.freqStart || normalize.f_stop != settings.freqStop || normalize.points != settings.points) { + // normalization was taken at different settings, disable + EnableNormalization(false); + InformationBox::ShowMessage("Information", "Normalization was disabled because the span has been changed"); + } + } + + if(window->getDevice() && isActive) { + window->getDevice()->setSA(settings, [=](bool){ + // device received command + changingSettings = false; + }); + emit sweepStarted(); + } else { + // no device, unable to start sweep + emit sweepStopped(); + changingSettings = false; + } + average.reset(settings.points); + UpdateAverageCount(); + traceModel.clearLiveData(); + emit traceModel.SpanChanged(settings.freqStart, settings.freqStop); + } else { + if(window->getDevice()) { + changingSettings = true; + // single sweep finished + window->getDevice()->setIdle([=](bool){ + emit sweepStopped(); + changingSettings = false; + }); + } else { + emit sweepStopped(); + changingSettings = false; + } + } } void SpectrumAnalyzer::SetupSCPI() diff --git a/Software/PC_Application/LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.h b/Software/PC_Application/LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.h index 9336689..0b49ad2 100644 --- a/Software/PC_Application/LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.h +++ b/Software/PC_Application/LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.h @@ -73,6 +73,7 @@ private slots: void Run(); void Stop(); + void ConfigureDevice(); private: void SetupSCPI(); @@ -89,6 +90,8 @@ private: unsigned int averages; bool singleSweep; bool running; + QTimer configurationTimer; + double firstPointTime; // timestamp of the first point in the sweep, only use when zerospan is used TraceModel traceModel; TraceWidget *traceWidget; diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp index 3dd4fac..ecfc816 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp @@ -69,6 +69,11 @@ VNA::VNA(AppWindow *window, QString name) traceModel.setSource(TraceModel::DataSource::VNA); + configurationTimer.setSingleShot(true); + connect(&configurationTimer, &QTimer::timeout, this, [=](){ + ConfigureDevice(); + }); + // Create default traces createDefaultTracesAndGraphs(2); @@ -886,7 +891,7 @@ void VNA::NewDatapoint(VirtualDevice::VNAMeasurement m) } else { settings.activeSegment = 0; } - SettingsChanged(false); + SettingsChanged(); } } @@ -895,95 +900,9 @@ void VNA::UpdateAverageCount() lAverages->setText(QString::number(average.getLevel()) + "/"); } -void VNA::SettingsChanged(bool resetTraces, std::function cb) +void VNA::SettingsChanged() { - if(running) { - if (resetTraces) { - settings.activeSegment = 0; - } - changingSettings = true; - // assemble VNA protocol settings - VirtualDevice::VNASettings s = {}; - s.IFBW = settings.bandwidth; - if(Preferences::getInstance().Acquisition.alwaysExciteAllPorts) { - for(unsigned int i=0;igetDevice()).ports;i++) { - s.excitedPorts.push_back(i); - } - } else { - for(unsigned int i=0;igetDevice()).ports;i++) { - if(traceModel.PortExcitationRequired(i)) - s.excitedPorts.push_back(i); - } - } - settings.excitedPorts = s.excitedPorts; - - double start = settings.sweepType == SweepType::Frequency ? settings.Freq.start : settings.Power.start; - double stop = settings.sweepType == SweepType::Frequency ? settings.Freq.stop : settings.Power.stop; - int npoints = settings.npoints; - emit traceModel.SpanChanged(start, stop); - if (settings.segments > 1) { - // more than one segment, adjust start/stop - npoints = ceil((double) settings.npoints / settings.segments); - unsigned int segmentStartPoint = npoints * settings.activeSegment; - unsigned int segmentStopPoint = segmentStartPoint + npoints - 1; - if(segmentStopPoint >= settings.npoints) { - segmentStopPoint = settings.npoints - 1; - npoints = settings.npoints - segmentStartPoint; - } - auto seg_start = Util::Scale(segmentStartPoint, 0, settings.npoints - 1, start, stop); - auto seg_stop = Util::Scale(segmentStopPoint, 0, settings.npoints - 1, start, stop); - start = seg_start; - stop = seg_stop; - } - - if(settings.sweepType == SweepType::Frequency) { - s.freqStart = start; - s.freqStop = stop; - s.points = npoints; - s.dBmStart = settings.Freq.excitation_power; - s.dBmStop = settings.Freq.excitation_power; - s.logSweep = settings.Freq.logSweep; - } else if(settings.sweepType == SweepType::Power) { - s.freqStart = settings.Power.frequency; - s.freqStop = settings.Power.frequency; - s.points = npoints; - s.dBmStart = start; - s.dBmStop = stop; - s.logSweep = false; - } - if(window->getDevice() && isActive) { - window->getDevice()->setVNA(s, [=](bool res){ - // device received command, reset traces now - if (resetTraces) { - average.reset(settings.npoints); - traceModel.clearLiveData(); - UpdateAverageCount(); - UpdateCalWidget(); - } - if(cb) { - cb(res); - } - changingSettings = false; - }); - emit sweepStarted(); - } else { - // no device, unable to start sweep - emit sweepStopped(); - changingSettings = false; - } - } else { - if(window->getDevice()) { - changingSettings = true; - // single sweep finished - window->getDevice()->setIdle([=](bool){ - emit sweepStopped(); - changingSettings = false; - }); - } else { - emit sweepStopped(); - changingSettings = false; - } - } + configurationTimer.start(100); } void VNA::StartImpedanceMatching() @@ -1268,7 +1187,7 @@ void VNA::StartCalibrationMeasurements(std::set m cal.clearMeasurements(calMeasurements); }); // Trigger sweep to start from beginning - SettingsChanged(true, [=](bool){ + ConfigureDevice(true, [=](bool){ // enable calibration measurement only in transmission callback (prevents accidental sampling of data which was still being processed) calMeasuring = true; }); @@ -1693,20 +1612,111 @@ void VNA::SetSingleSweep(bool single) emit singleSweepChanged(single); } if(single) { - SettingsChanged(); + Run(); } } void VNA::Run() { running = true; - SettingsChanged(); + ConfigureDevice(); } void VNA::Stop() { running = false; - SettingsChanged(); + ConfigureDevice(false); +} + +void VNA::ConfigureDevice(bool resetTraces, std::function cb) +{ + if(running) { + if (resetTraces) { + settings.activeSegment = 0; + } + changingSettings = true; + // assemble VNA protocol settings + VirtualDevice::VNASettings s = {}; + s.IFBW = settings.bandwidth; + if(Preferences::getInstance().Acquisition.alwaysExciteAllPorts) { + for(unsigned int i=0;igetDevice()).ports;i++) { + s.excitedPorts.push_back(i); + } + } else { + for(unsigned int i=0;igetDevice()).ports;i++) { + if(traceModel.PortExcitationRequired(i)) + s.excitedPorts.push_back(i); + } + } + settings.excitedPorts = s.excitedPorts; + + double start = settings.sweepType == SweepType::Frequency ? settings.Freq.start : settings.Power.start; + double stop = settings.sweepType == SweepType::Frequency ? settings.Freq.stop : settings.Power.stop; + int npoints = settings.npoints; + emit traceModel.SpanChanged(start, stop); + if (settings.segments > 1) { + // more than one segment, adjust start/stop + npoints = ceil((double) settings.npoints / settings.segments); + unsigned int segmentStartPoint = npoints * settings.activeSegment; + unsigned int segmentStopPoint = segmentStartPoint + npoints - 1; + if(segmentStopPoint >= settings.npoints) { + segmentStopPoint = settings.npoints - 1; + npoints = settings.npoints - segmentStartPoint; + } + auto seg_start = Util::Scale(segmentStartPoint, 0, settings.npoints - 1, start, stop); + auto seg_stop = Util::Scale(segmentStopPoint, 0, settings.npoints - 1, start, stop); + start = seg_start; + stop = seg_stop; + } + + if(settings.sweepType == SweepType::Frequency) { + s.freqStart = start; + s.freqStop = stop; + s.points = npoints; + s.dBmStart = settings.Freq.excitation_power; + s.dBmStop = settings.Freq.excitation_power; + s.logSweep = settings.Freq.logSweep; + } else if(settings.sweepType == SweepType::Power) { + s.freqStart = settings.Power.frequency; + s.freqStop = settings.Power.frequency; + s.points = npoints; + s.dBmStart = start; + s.dBmStop = stop; + s.logSweep = false; + } + if(window->getDevice() && isActive) { + window->getDevice()->setVNA(s, [=](bool res){ + // device received command, reset traces now + if (resetTraces) { + average.reset(settings.npoints); + traceModel.clearLiveData(); + UpdateAverageCount(); + UpdateCalWidget(); + } + if(cb) { + cb(res); + } + changingSettings = false; + }); + emit sweepStarted(); + } else { + // no device, unable to start sweep + emit sweepStopped(); + changingSettings = false; + } + } else { + if(window->getDevice()) { + changingSettings = true; + // single sweep finished + window->getDevice()->setIdle([=](bool){ + emit sweepStopped(); + changingSettings = false; + }); + } else { + emit sweepStopped(); + changingSettings = false; + } + } } bool VNA::LoadCalibration(QString filename) diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/vna.h b/Software/PC_Application/LibreVNA-GUI/VNA/vna.h index 72ccdd7..9add81a 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/vna.h +++ b/Software/PC_Application/LibreVNA-GUI/VNA/vna.h @@ -116,7 +116,7 @@ private: bool CalibrationMeasurementActive() { return calWaitFirst || calMeasuring; } void SetupSCPI(); void UpdateAverageCount(); - void SettingsChanged(bool resetTraces = true, std::function cb = nullptr); + void SettingsChanged(); void ConstrainAndUpdateFrequencies(); void LoadSweepSettings(); void StoreSweepSettings(); @@ -129,6 +129,7 @@ private slots: void SetSingleSweep(bool single); void Run(); void Stop(); + void ConfigureDevice(bool resetTraces = true, std::function cb = nullptr); private: Settings settings; unsigned int averages; @@ -138,6 +139,7 @@ private: Averaging average; bool singleSweep; bool running; + QTimer configurationTimer; // Calibration Calibration cal; diff --git a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp index 11f6618..d8683a5 100644 --- a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp +++ b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp @@ -1140,6 +1140,14 @@ void AppWindow::LoadSetup(nlohmann::json j) toolbars.reference.outFreq->setCurrentText(QString::fromStdString(j["Reference"].value("Output", "Off"))); } + // Disconnect device prior to deleting and creating new modes. This prevents excessice and unnnecessary configuration of the device + QString serial = QString(); + if(vdevice->getConnected()) { + serial = vdevice->serial(); + delete vdevice; + vdevice = nullptr; + } + modeHandler->closeModes(); /* old style VNA/Generator/Spectrum Analyzer settings, @@ -1170,6 +1178,11 @@ void AppWindow::LoadSetup(nlohmann::json j) } } + // reconnect to device + if(!serial.isEmpty()) { + vdevice = new VirtualDevice(serial); + } + // activate the correct mode QString modeName = QString::fromStdString(j.value("activeMode", "")); for(auto m : modeHandler->getModes()) { diff --git a/Software/PC_Application/LibreVNA-GUI/modehandler.cpp b/Software/PC_Application/LibreVNA-GUI/modehandler.cpp index e44d8be..d251113 100644 --- a/Software/PC_Application/LibreVNA-GUI/modehandler.cpp +++ b/Software/PC_Application/LibreVNA-GUI/modehandler.cpp @@ -23,17 +23,17 @@ void ModeHandler::shutdown() int ModeHandler::createMode(QString name, Mode::Type t) { auto mode = createNew(aw, name, t); - return createMode(mode); + return addMode(mode); } -int ModeHandler::createMode(Mode *mode) +int ModeHandler::addMode(Mode *mode) { modes.push_back(mode); currentModeIndex = int(modes.size()) - 1; connect(mode, &Mode::statusbarMessage, this, &ModeHandler::setStatusBarMessageChanged); - auto m = getMode(currentModeIndex); - activate(m); +// auto m = getMode(currentModeIndex); +// activate(m); emit ModeCreated(currentModeIndex); return (currentModeIndex); diff --git a/Software/PC_Application/LibreVNA-GUI/modehandler.h b/Software/PC_Application/LibreVNA-GUI/modehandler.h index ea0d1c7..b371ad9 100644 --- a/Software/PC_Application/LibreVNA-GUI/modehandler.h +++ b/Software/PC_Application/LibreVNA-GUI/modehandler.h @@ -46,7 +46,7 @@ public slots: private: std::vector modes; int currentModeIndex; - int createMode(Mode *mode); + int addMode(Mode *mode); Mode *createNew(AppWindow *window, QString name, Mode::Type t); AppWindow *aw; Mode *activeMode;