diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index 30bfa60..217db19 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -298,6 +298,12 @@ VNA::VNA(AppWindow *window) connect(bZoomOut, &QPushButton::clicked, this, &VNA::SpanZoomOut); frequencySweepActions.push_back(tb_sweep->addWidget(bZoomOut)); + auto cbLogSweep = new QCheckBox("Log"); + cbLogSweep->setToolTip("Logarithmic sweep"); + connect(cbLogSweep, &QCheckBox::toggled, this, &VNA::SetLogSweep); + connect(this, &VNA::logSweepChanged, cbLogSweep, &QCheckBox::setChecked); + frequencySweepActions.push_back(tb_sweep->addWidget(cbLogSweep)); + // power sweep widgets auto sbPowerLow = new QDoubleSpinBox(); width = QFontMetrics(sbPowerLow->font()).width("-30.00dBm") + 20; @@ -700,6 +706,7 @@ nlohmann::json VNA::toJSON() freq["start"] = settings.Freq.start; freq["stop"] = settings.Freq.stop; freq["power"] = settings.Freq.excitation_power; + freq["log"] = settings.Freq.logSweep; sweep["frequency"] = freq; nlohmann::json power; power["start"] = settings.Power.start; @@ -750,6 +757,7 @@ void VNA::fromJSON(nlohmann::json j) SetStartFreq(freq.value("start", settings.Freq.start)); SetStopFreq(freq.value("stop", settings.Freq.stop)); SetSourceLevel(freq.value("power", settings.Freq.excitation_power)); + SetLogSweep(freq.value("log", settings.Freq.logSweep)); } if(sweep.contains("power")) { auto power = sweep["power"]; @@ -850,6 +858,7 @@ void VNA::SettingsChanged(std::function cb) 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; @@ -858,6 +867,7 @@ void VNA::SettingsChanged(std::function cb) s.if_bandwidth = settings.bandwidth; s.cdbm_excitation_start = settings.Power.start * 100; s.cdbm_excitation_stop = settings.Power.stop * 100; + s.logSweep = false; } if(window->getDevice() && Mode::getActiveMode() == this) { if(s.excitePort1 == 0 && s.excitePort2 == 0) { @@ -979,6 +989,16 @@ void VNA::SpanZoomOut() ConstrainAndUpdateFrequencies(); } +void VNA::SetLogSweep(bool log) +{ + if(settings.Freq.logSweep != log) { + settings.Freq.logSweep = log; + emit logSweepChanged(log); + SettingsChanged(); + } +} + + void VNA::SetSourceLevel(double level) { if(level > Device::Info().limits_cdbm_max / 100.0) { @@ -1500,3 +1520,4 @@ VNA::SweepType VNA::SweepTypeFromString(QString s) // not found return SweepType::Last; } + diff --git a/Software/PC_Application/VNA/vna.h b/Software/PC_Application/VNA/vna.h index dcb03d4..34c53f2 100644 --- a/Software/PC_Application/VNA/vna.h +++ b/Software/PC_Application/VNA/vna.h @@ -46,6 +46,7 @@ public: double start; double stop; double excitation_power; + bool logSweep; } Freq; struct { double start; @@ -70,6 +71,8 @@ private slots: void SetFullSpan(); void SpanZoomIn(); void SpanZoomOut(); + + void SetLogSweep(bool log); // Acquisition control void SetSourceLevel(double level); // Power sweep settings @@ -146,6 +149,7 @@ signals: void stopFreqChanged(double freq); void centerFreqChanged(double freq); void spanChanged(double span); + void logSweepChanged(bool log); void sourceLevelChanged(double level); void pointsChanged(unsigned int points); diff --git a/Software/PC_Application/preferences.h b/Software/PC_Application/preferences.h index 9ff2307..d3f3c83 100644 --- a/Software/PC_Application/preferences.h +++ b/Software/PC_Application/preferences.h @@ -35,6 +35,7 @@ public: QString type; double f_start; double f_stop; + bool logSweep; double f_excitation; double dbm_start; @@ -103,12 +104,13 @@ private: QString name; QVariant def; }; - const std::array descr = {{ + const std::array descr = {{ {&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true}, {&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false}, {&Startup.DefaultSweep.type, "Startup.DefaultSweep.type", "Frequency"}, {&Startup.DefaultSweep.f_start, "Startup.DefaultSweep.start", 1000000.0}, {&Startup.DefaultSweep.f_stop, "Startup.DefaultSweep.stop", 6000000000.0}, + {&Startup.DefaultSweep.logSweep, "Startup.DefaultSweep.logSweep", false}, {&Startup.DefaultSweep.f_excitation, "Startup.DefaultSweep.excitation", -10.00}, {&Startup.DefaultSweep.dbm_start, "Startup.DefaultSweep.dbm_start", -30.00}, {&Startup.DefaultSweep.dbm_stop, "Startup.DefaultSweep.dbm_stop", -10.0}, diff --git a/Software/VNA_embedded/Application/Communication/Protocol.hpp b/Software/VNA_embedded/Application/Communication/Protocol.hpp index 412b662..9c78004 100644 --- a/Software/VNA_embedded/Application/Communication/Protocol.hpp +++ b/Software/VNA_embedded/Application/Communication/Protocol.hpp @@ -4,7 +4,7 @@ namespace Protocol { -static constexpr uint16_t Version = 7; +static constexpr uint16_t Version = 8; #pragma pack(push, 1) @@ -28,6 +28,7 @@ using SweepSettings = struct _sweepSettings { uint8_t excitePort2:1; uint8_t suppressPeaks:1; uint8_t fixedPowerSetting:1; // if set the attenuator and source PLL power will not be changed across the sweep + uint8_t logSweep:1; int16_t cdbm_excitation_stop; // in 1/100 dbm }; diff --git a/Software/VNA_embedded/Application/VNA.cpp b/Software/VNA_embedded/Application/VNA.cpp index 65b0973..a05e3c0 100644 --- a/Software/VNA_embedded/Application/VNA.cpp +++ b/Software/VNA_embedded/Application/VNA.cpp @@ -13,6 +13,7 @@ #include "task.h" #include "Util.hpp" #include "usb.h" +#include #define LOG_LEVEL LOG_LEVEL_INFO #define LOG_MODULE "VNA" @@ -20,6 +21,7 @@ static Protocol::SweepSettings settings; static uint16_t pointCnt; +static float span_log10; static bool excitingPort1; static Protocol::Datapoint data; static bool active = false; @@ -51,6 +53,14 @@ static constexpr uint32_t reservedUSBbuffer = maxPointsBetweenHalts * (sizeof(Pr using namespace HWHAL; +static uint64_t getPointFrequency(uint16_t pointNum) { + if(!settings.logSweep) { + return settings.f_start + (settings.f_stop - settings.f_start) * pointNum / (settings.points - 1); + } else { + return settings.f_start * powf(10.0, pointNum * span_log10 / (settings.points - 1)); + } +} + bool VNA::Setup(Protocol::SweepSettings s) { VNA::Stop(); vTaskDelay(5); @@ -62,11 +72,14 @@ bool VNA::Setup(Protocol::SweepSettings s) { return false; } settings = s; + span_log10 = log10((double) settings.f_stop / settings.f_start); // Abort possible active sweep first FPGA::SetMode(FPGA::Mode::FPGA); - uint16_t points = settings.points <= FPGA::MaxPoints ? settings.points : FPGA::MaxPoints; + if(settings.points > FPGA::MaxPoints) { + settings.points = FPGA::MaxPoints; + } // Configure sweep - FPGA::SetNumberOfPoints(points); + FPGA::SetNumberOfPoints(settings.points); uint32_t samplesPerPoint = (HW::ADCSamplerate / s.if_bandwidth); // round up to next multiple of 16 (16 samples are spread across 5 IF2 periods) if(samplesPerPoint%16) { @@ -120,10 +133,10 @@ bool VNA::Setup(Protocol::SweepSettings s) { uint16_t pointsWithoutHalt = 0; // Transfer PLL configuration to FPGA - for (uint16_t i = 0; i < points; i++) { + for (uint16_t i = 0; i < settings.points; i++) { bool harmonic_mixing = false; - uint64_t freq = s.f_start + (s.f_stop - s.f_start) * i / (points - 1); - int16_t power = s.cdbm_excitation_start + (s.cdbm_excitation_stop - s.cdbm_excitation_start) * i / (points - 1); + uint64_t freq = getPointFrequency(i); + int16_t power = s.cdbm_excitation_start + (s.cdbm_excitation_stop - s.cdbm_excitation_start) * i / (settings.points - 1); freq = Cal::FrequencyCorrectionToDevice(freq); if(freq > 6000000000ULL) { @@ -286,7 +299,7 @@ bool VNA::MeasurementDone(const FPGA::SamplingResult &result) { auto port1 = port1_raw / ref; auto port2 = port2_raw / ref; data.pointNum = pointCnt; - data.frequency = settings.f_start + (settings.f_stop - settings.f_start) * pointCnt / (settings.points - 1); + data.frequency = getPointFrequency(pointCnt); data.cdbm = settings.cdbm_excitation_start + (settings.cdbm_excitation_stop - settings.cdbm_excitation_start) * pointCnt / (settings.points - 1); if(excitingPort1) { data.real_S11 = port1.real(); @@ -352,9 +365,7 @@ void VNA::SweepHalted() { // PLL reset causes the 2.LO to turn off briefly and then ramp on back, needs delay before next point Delay::us(1300); } - uint64_t frequency = settings.f_start - + (settings.f_stop - settings.f_start) * pointCnt - / (settings.points - 1); + uint64_t frequency = getPointFrequency(pointCnt); int16_t power = settings.cdbm_excitation_start + (settings.cdbm_excitation_stop - settings.cdbm_excitation_start) * pointCnt / (settings.points - 1);