diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index 4cd59ac..dacfb11 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -20,6 +20,7 @@ #include "CustomWidgets/informationbox.h" #include "Deembedding/manualdeembeddingdialog.h" #include "Calibration/manualcalibrationdialog.h" +#include "Util/util.h" #include #include @@ -365,8 +366,8 @@ VNA::VNA(AppWindow *window) frequencySweepActions.push_back(tb_acq->addWidget(dbm)); auto points = new QSpinBox(); - points->setFixedWidth(55); - points->setRange(1, 9999); + points->setFixedWidth(65); + points->setRange(1, UINT16_MAX); points->setSingleStep(100); points->setToolTip("Points/sweep"); points->setKeyboardTracking(false); @@ -787,6 +788,19 @@ using namespace std; void VNA::NewDatapoint(Protocol::Datapoint d) { + bool needsSegmentUpdate = false; + if (settings.segments > 1) { + // using multiple segments, adjust pointNum + auto pointsPerSegment = ceil((double) settings.npoints / settings.segments); + if (d.pointNum == pointsPerSegment - 1) { + needsSegmentUpdate = true; + } + d.pointNum += pointsPerSegment * settings.activeSegment; + if(d.pointNum == settings.npoints - 1) { + needsSegmentUpdate = true; + } + } + if(d.pointNum >= settings.npoints) { qWarning() << "Ignoring point with too large point number (" << d.pointNum << ")"; return; @@ -838,6 +852,15 @@ void VNA::NewDatapoint(Protocol::Datapoint d) qWarning() << "Got point" << d.pointNum << "but last received point was" << lastPoint << "("<<(d.pointNum-lastPoint-1)<<"missed points)"; } lastPoint = d.pointNum; + + if (needsSegmentUpdate) { + if( settings.activeSegment < settings.segments - 1) { + settings.activeSegment++; + } else { + settings.activeSegment = 0; + } + SettingsChanged(false); + } } void VNA::UpdateAverageCount() @@ -845,7 +868,7 @@ void VNA::UpdateAverageCount() lAverages->setText(QString::number(average.getLevel()) + "/"); } -void VNA::SettingsChanged(std::function cb) +void VNA::SettingsChanged(bool resetTraces, std::function cb) { // assemble VNA protocol settings Protocol::SweepSettings s; @@ -859,20 +882,40 @@ void VNA::SettingsChanged(std::function cb) } settings.excitingPort1 = s.excitePort1; settings.excitingPort2 = s.excitePort2; + + 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); + int segmentStartPoint = npoints * settings.activeSegment; + 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.fixedPowerSetting = Preferences::getInstance().Acquisition.adjustPowerLevel ? 0 : 1; - s.f_start = settings.Freq.start; - s.f_stop = settings.Freq.stop; - s.points = settings.npoints; + s.f_start = start; + s.f_stop = stop; + s.points = npoints; s.if_bandwidth = settings.bandwidth; s.cdbm_excitation_start = settings.Freq.excitation_power * 100; s.cdbm_excitation_stop = settings.Freq.excitation_power * 100; s.logSweep = settings.Freq.logSweep; } else if(settings.sweepType == SweepType::Power) { s.fixedPowerSetting = 0; - s.f_start = settings.Power.frequency; - s.f_stop = settings.Power.frequency; - s.points = settings.npoints; + s.f_start = start; + s.f_stop = stop; + s.points = npoints; s.if_bandwidth = settings.bandwidth; s.cdbm_excitation_start = settings.Power.start * 100; s.cdbm_excitation_stop = settings.Power.stop * 100; @@ -880,22 +923,23 @@ void VNA::SettingsChanged(std::function cb) } if(window->getDevice() && Mode::getActiveMode() == this) { if(s.excitePort1 == 0 && s.excitePort2 == 0) { - // no signal at either port, just set the device to idel + // no signal at either port, just set the device to idle window->getDevice()->SetIdle(); } else { window->getDevice()->Configure(s, [=](Device::TransmissionResult res){ // device received command, reset traces now - average.reset(s.points); - traceModel.clearLiveData(); - UpdateAverageCount(); - UpdateCalWidget(); + if (resetTraces) { + average.reset(s.points); + traceModel.clearLiveData(); + UpdateAverageCount(); + UpdateCalWidget(); + } if(cb) { cb(res); } }); } } - emit traceModel.SpanChanged(s.f_start, s.f_stop); } void VNA::StartImpedanceMatching() @@ -1045,11 +1089,21 @@ void VNA::SetPowerSweepFrequency(double freq) void VNA::SetPoints(unsigned int points) { - if(points > Device::Info().limits_maxPoints) { - points = Device::Info().limits_maxPoints; + auto maxPoints = Preferences::getInstance().Acquisition.allowSegmentedSweep ? UINT16_MAX : Device::Info().limits_maxPoints; + if(points > maxPoints) { + points = maxPoints; } else if (points < 2) { points = 2; } + if (points > Device::Info().limits_maxPoints) { + // needs segmented sweep + settings.segments = ceil((double) points / Device::Info().limits_maxPoints); + settings.activeSegment = 0; + } else { + // can fit all points into one segment + settings.segments = 1; + settings.activeSegment = 0; + } emit pointsChanged(points); settings.npoints = points; SettingsChanged(); @@ -1161,7 +1215,7 @@ void VNA::StartCalibrationMeasurements(std::set m) cal.clearMeasurements(calMeasurements); }); // Trigger sweep to start from beginning - SettingsChanged([=](Device::TransmissionResult){ + SettingsChanged(true, [=](Device::TransmissionResult){ // enable calibration measurement only in transmission callback (prevents accidental sampling of data which was still being processed) calMeasuring = true; }); diff --git a/Software/PC_Application/VNA/vna.h b/Software/PC_Application/VNA/vna.h index 1ad908e..b2ef553 100644 --- a/Software/PC_Application/VNA/vna.h +++ b/Software/PC_Application/VNA/vna.h @@ -40,7 +40,8 @@ public: static QString SweepTypeToString(SweepType sw); static SweepType SweepTypeFromString(QString s); - using Settings = struct { + class Settings { + public: SweepType sweepType; struct { double start; @@ -57,6 +58,9 @@ public: double bandwidth; bool excitingPort1; bool excitingPort2; + // if the number of points is higher than supported by the hardware, the sweep has to be segmented into multiple parts + int segments; + int activeSegment; }; public slots: @@ -101,7 +105,7 @@ private: bool CalibrationMeasurementActive() { return calWaitFirst || calMeasuring; } void SetupSCPI(); void UpdateAverageCount(); - void SettingsChanged(std::function cb = nullptr); + void SettingsChanged(bool resetTraces = true, std::function cb = nullptr); void ConstrainAndUpdateFrequencies(); void LoadSweepSettings(); void StoreSweepSettings(); diff --git a/Software/PC_Application/preferences.cpp b/Software/PC_Application/preferences.cpp index 15ea8ff..efa9fac 100644 --- a/Software/PC_Application/preferences.cpp +++ b/Software/PC_Application/preferences.cpp @@ -233,6 +233,7 @@ void PreferencesDialog::setInitialGUIState() ui->AcquisitionSuppressPeaks->setChecked(p->Acquisition.suppressPeaks); ui->AcquisitionAdjustPowerLevel->setChecked(p->Acquisition.adjustPowerLevel); ui->AcquisitionUseHarmonic->setChecked(p->Acquisition.harmonicMixing); + ui->AcquisitionAllowSegmentedSweep->setChecked(p->Acquisition.allowSegmentedSweep); ui->AcquisitionUseDFT->setChecked(p->Acquisition.useDFTinSAmode); ui->AcquisitionDFTlimitRBW->setValue(p->Acquisition.RBWLimitForDFT); ui->AcquisitionAveragingMode->setCurrentIndex(p->Acquisition.useMedianAveraging ? 1 : 0); @@ -292,6 +293,7 @@ void PreferencesDialog::updateFromGUI() p->Acquisition.suppressPeaks = ui->AcquisitionSuppressPeaks->isChecked(); p->Acquisition.adjustPowerLevel = ui->AcquisitionAdjustPowerLevel->isChecked(); p->Acquisition.harmonicMixing = ui->AcquisitionUseHarmonic->isChecked(); + p->Acquisition.allowSegmentedSweep = ui->AcquisitionAllowSegmentedSweep->isChecked(); p->Acquisition.useDFTinSAmode = ui->AcquisitionUseDFT->isChecked(); p->Acquisition.RBWLimitForDFT = ui->AcquisitionDFTlimitRBW->value(); p->Acquisition.useMedianAveraging = ui->AcquisitionAveragingMode->currentIndex() == 1; diff --git a/Software/PC_Application/preferences.h b/Software/PC_Application/preferences.h index 095cf92..67a28c4 100644 --- a/Software/PC_Application/preferences.h +++ b/Software/PC_Application/preferences.h @@ -69,6 +69,7 @@ public: bool suppressPeaks; bool adjustPowerLevel; bool harmonicMixing; + bool allowSegmentedSweep; bool useDFTinSAmode; double RBWLimitForDFT; bool useMedianAveraging; @@ -147,6 +148,7 @@ private: {&Acquisition.suppressPeaks, "Acquisition.suppressPeaks", true}, {&Acquisition.adjustPowerLevel, "Acquisition.adjustPowerLevel", false}, {&Acquisition.harmonicMixing, "Acquisition.harmonicMixing", false}, + {&Acquisition.allowSegmentedSweep, "Acquisition.allowSegmentedSweep", false}, {&Acquisition.useDFTinSAmode, "Acquisition.useDFTinSAmode", true}, {&Acquisition.RBWLimitForDFT, "Acquisition.RBWLimitForDFT", 3000.0}, {&Acquisition.useMedianAveraging, "Acquisition.useMedianAveraging", false}, diff --git a/Software/PC_Application/preferencesdialog.ui b/Software/PC_Application/preferencesdialog.ui index 13ef28c..5cfa158 100644 --- a/Software/PC_Application/preferencesdialog.ui +++ b/Software/PC_Application/preferencesdialog.ui @@ -83,7 +83,7 @@ - 0 + 1 @@ -738,6 +738,13 @@ + + + + Allow segmented sweep (increases maximum number of points) + + +