Improve load time of setup files by omitting excessive device configuration

This commit is contained in:
Jan Käberich 2022-10-30 12:07:59 +01:00
parent 2f5cbc80e9
commit eff18a22e8
7 changed files with 213 additions and 173 deletions

View File

@ -64,6 +64,11 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
normalize.measure = nullptr; normalize.measure = nullptr;
normalize.enable = nullptr; normalize.enable = nullptr;
configurationTimer.setSingleShot(true);
connect(&configurationTimer, &QTimer::timeout, this, [=](){
ConfigureDevice();
});
traceModel.setSource(TraceModel::DataSource::SA); traceModel.setSource(TraceModel::DataSource::SA);
// Create default traces // Create default traces
@ -543,77 +548,7 @@ void SpectrumAnalyzer::NewDatapoint(VirtualDevice::SAMeasurement m)
void SpectrumAnalyzer::SettingsChanged() void SpectrumAnalyzer::SettingsChanged()
{ {
if(running) { configurationTimer.start(100);
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::SetStartFreq(double freq) void SpectrumAnalyzer::SetStartFreq(double freq)
@ -718,7 +653,9 @@ void SpectrumAnalyzer::SetSingleSweep(bool single)
singleSweep = single; singleSweep = single;
emit singleSweepChanged(single); emit singleSweepChanged(single);
} }
SettingsChanged(); if(single) {
Run();
}
} }
void SpectrumAnalyzer::SetRBW(double bandwidth) void SpectrumAnalyzer::SetRBW(double bandwidth)
@ -888,13 +825,88 @@ void SpectrumAnalyzer::SetNormalizationLevel(double level)
void SpectrumAnalyzer::Run() void SpectrumAnalyzer::Run()
{ {
running = true; running = true;
SettingsChanged(); ConfigureDevice();
} }
void SpectrumAnalyzer::Stop() void SpectrumAnalyzer::Stop()
{ {
running = false; 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() void SpectrumAnalyzer::SetupSCPI()

View File

@ -73,6 +73,7 @@ private slots:
void Run(); void Run();
void Stop(); void Stop();
void ConfigureDevice();
private: private:
void SetupSCPI(); void SetupSCPI();
@ -89,6 +90,8 @@ private:
unsigned int averages; unsigned int averages;
bool singleSweep; bool singleSweep;
bool running; bool running;
QTimer configurationTimer;
double firstPointTime; // timestamp of the first point in the sweep, only use when zerospan is used double firstPointTime; // timestamp of the first point in the sweep, only use when zerospan is used
TraceModel traceModel; TraceModel traceModel;
TraceWidget *traceWidget; TraceWidget *traceWidget;

View File

@ -69,6 +69,11 @@ VNA::VNA(AppWindow *window, QString name)
traceModel.setSource(TraceModel::DataSource::VNA); traceModel.setSource(TraceModel::DataSource::VNA);
configurationTimer.setSingleShot(true);
connect(&configurationTimer, &QTimer::timeout, this, [=](){
ConfigureDevice();
});
// Create default traces // Create default traces
createDefaultTracesAndGraphs(2); createDefaultTracesAndGraphs(2);
@ -886,7 +891,7 @@ void VNA::NewDatapoint(VirtualDevice::VNAMeasurement m)
} else { } else {
settings.activeSegment = 0; settings.activeSegment = 0;
} }
SettingsChanged(false); SettingsChanged();
} }
} }
@ -895,95 +900,9 @@ void VNA::UpdateAverageCount()
lAverages->setText(QString::number(average.getLevel()) + "/"); lAverages->setText(QString::number(average.getLevel()) + "/");
} }
void VNA::SettingsChanged(bool resetTraces, std::function<void (bool)> cb) void VNA::SettingsChanged()
{ {
if(running) { configurationTimer.start(100);
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;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
s.excitedPorts.push_back(i);
}
} else {
for(unsigned int i=0;i<VirtualDevice::getInfo(window->getDevice()).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<double>(segmentStartPoint, 0, settings.npoints - 1, start, stop);
auto seg_stop = Util::Scale<double>(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;
}
}
} }
void VNA::StartImpedanceMatching() void VNA::StartImpedanceMatching()
@ -1268,7 +1187,7 @@ void VNA::StartCalibrationMeasurements(std::set<CalibrationMeasurement::Base*> m
cal.clearMeasurements(calMeasurements); cal.clearMeasurements(calMeasurements);
}); });
// Trigger sweep to start from beginning // 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) // enable calibration measurement only in transmission callback (prevents accidental sampling of data which was still being processed)
calMeasuring = true; calMeasuring = true;
}); });
@ -1693,20 +1612,111 @@ void VNA::SetSingleSweep(bool single)
emit singleSweepChanged(single); emit singleSweepChanged(single);
} }
if(single) { if(single) {
SettingsChanged(); Run();
} }
} }
void VNA::Run() void VNA::Run()
{ {
running = true; running = true;
SettingsChanged(); ConfigureDevice();
} }
void VNA::Stop() void VNA::Stop()
{ {
running = false; running = false;
SettingsChanged(); ConfigureDevice(false);
}
void VNA::ConfigureDevice(bool resetTraces, std::function<void(bool)> 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;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
s.excitedPorts.push_back(i);
}
} else {
for(unsigned int i=0;i<VirtualDevice::getInfo(window->getDevice()).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<double>(segmentStartPoint, 0, settings.npoints - 1, start, stop);
auto seg_stop = Util::Scale<double>(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) bool VNA::LoadCalibration(QString filename)

View File

@ -116,7 +116,7 @@ private:
bool CalibrationMeasurementActive() { return calWaitFirst || calMeasuring; } bool CalibrationMeasurementActive() { return calWaitFirst || calMeasuring; }
void SetupSCPI(); void SetupSCPI();
void UpdateAverageCount(); void UpdateAverageCount();
void SettingsChanged(bool resetTraces = true, std::function<void(bool)> cb = nullptr); void SettingsChanged();
void ConstrainAndUpdateFrequencies(); void ConstrainAndUpdateFrequencies();
void LoadSweepSettings(); void LoadSweepSettings();
void StoreSweepSettings(); void StoreSweepSettings();
@ -129,6 +129,7 @@ private slots:
void SetSingleSweep(bool single); void SetSingleSweep(bool single);
void Run(); void Run();
void Stop(); void Stop();
void ConfigureDevice(bool resetTraces = true, std::function<void(bool)> cb = nullptr);
private: private:
Settings settings; Settings settings;
unsigned int averages; unsigned int averages;
@ -138,6 +139,7 @@ private:
Averaging average; Averaging average;
bool singleSweep; bool singleSweep;
bool running; bool running;
QTimer configurationTimer;
// Calibration // Calibration
Calibration cal; Calibration cal;

View File

@ -1140,6 +1140,14 @@ void AppWindow::LoadSetup(nlohmann::json j)
toolbars.reference.outFreq->setCurrentText(QString::fromStdString(j["Reference"].value("Output", "Off"))); 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(); modeHandler->closeModes();
/* old style VNA/Generator/Spectrum Analyzer settings, /* 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 // activate the correct mode
QString modeName = QString::fromStdString(j.value("activeMode", "")); QString modeName = QString::fromStdString(j.value("activeMode", ""));
for(auto m : modeHandler->getModes()) { for(auto m : modeHandler->getModes()) {

View File

@ -23,17 +23,17 @@ void ModeHandler::shutdown()
int ModeHandler::createMode(QString name, Mode::Type t) int ModeHandler::createMode(QString name, Mode::Type t)
{ {
auto mode = createNew(aw, name, 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); modes.push_back(mode);
currentModeIndex = int(modes.size()) - 1; currentModeIndex = int(modes.size()) - 1;
connect(mode, &Mode::statusbarMessage, this, &ModeHandler::setStatusBarMessageChanged); connect(mode, &Mode::statusbarMessage, this, &ModeHandler::setStatusBarMessageChanged);
auto m = getMode(currentModeIndex); // auto m = getMode(currentModeIndex);
activate(m); // activate(m);
emit ModeCreated(currentModeIndex); emit ModeCreated(currentModeIndex);
return (currentModeIndex); return (currentModeIndex);

View File

@ -46,7 +46,7 @@ public slots:
private: private:
std::vector<Mode*> modes; std::vector<Mode*> modes;
int currentModeIndex; int currentModeIndex;
int createMode(Mode *mode); int addMode(Mode *mode);
Mode *createNew(AppWindow *window, QString name, Mode::Type t); Mode *createNew(AppWindow *window, QString name, Mode::Type t);
AppWindow *aw; AppWindow *aw;
Mode *activeMode; Mode *activeMode;