Log option for frequency sweep

This commit is contained in:
Jan Käberich 2022-01-05 16:01:51 +01:00
parent 0379040a05
commit 6fd2598ae8
5 changed files with 50 additions and 11 deletions

View File

@ -298,6 +298,12 @@ VNA::VNA(AppWindow *window)
connect(bZoomOut, &QPushButton::clicked, this, &VNA::SpanZoomOut); connect(bZoomOut, &QPushButton::clicked, this, &VNA::SpanZoomOut);
frequencySweepActions.push_back(tb_sweep->addWidget(bZoomOut)); 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 // power sweep widgets
auto sbPowerLow = new QDoubleSpinBox(); auto sbPowerLow = new QDoubleSpinBox();
width = QFontMetrics(sbPowerLow->font()).width("-30.00dBm") + 20; width = QFontMetrics(sbPowerLow->font()).width("-30.00dBm") + 20;
@ -700,6 +706,7 @@ nlohmann::json VNA::toJSON()
freq["start"] = settings.Freq.start; freq["start"] = settings.Freq.start;
freq["stop"] = settings.Freq.stop; freq["stop"] = settings.Freq.stop;
freq["power"] = settings.Freq.excitation_power; freq["power"] = settings.Freq.excitation_power;
freq["log"] = settings.Freq.logSweep;
sweep["frequency"] = freq; sweep["frequency"] = freq;
nlohmann::json power; nlohmann::json power;
power["start"] = settings.Power.start; power["start"] = settings.Power.start;
@ -750,6 +757,7 @@ void VNA::fromJSON(nlohmann::json j)
SetStartFreq(freq.value("start", settings.Freq.start)); SetStartFreq(freq.value("start", settings.Freq.start));
SetStopFreq(freq.value("stop", settings.Freq.stop)); SetStopFreq(freq.value("stop", settings.Freq.stop));
SetSourceLevel(freq.value("power", settings.Freq.excitation_power)); SetSourceLevel(freq.value("power", settings.Freq.excitation_power));
SetLogSweep(freq.value("log", settings.Freq.logSweep));
} }
if(sweep.contains("power")) { if(sweep.contains("power")) {
auto power = sweep["power"]; auto power = sweep["power"];
@ -850,6 +858,7 @@ void VNA::SettingsChanged(std::function<void (Device::TransmissionResult)> cb)
s.if_bandwidth = settings.bandwidth; s.if_bandwidth = settings.bandwidth;
s.cdbm_excitation_start = settings.Freq.excitation_power * 100; s.cdbm_excitation_start = settings.Freq.excitation_power * 100;
s.cdbm_excitation_stop = 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) { } else if(settings.sweepType == SweepType::Power) {
s.fixedPowerSetting = 0; s.fixedPowerSetting = 0;
s.f_start = settings.Power.frequency; s.f_start = settings.Power.frequency;
@ -858,6 +867,7 @@ void VNA::SettingsChanged(std::function<void (Device::TransmissionResult)> cb)
s.if_bandwidth = settings.bandwidth; s.if_bandwidth = settings.bandwidth;
s.cdbm_excitation_start = settings.Power.start * 100; s.cdbm_excitation_start = settings.Power.start * 100;
s.cdbm_excitation_stop = settings.Power.stop * 100; s.cdbm_excitation_stop = settings.Power.stop * 100;
s.logSweep = false;
} }
if(window->getDevice() && Mode::getActiveMode() == this) { if(window->getDevice() && Mode::getActiveMode() == this) {
if(s.excitePort1 == 0 && s.excitePort2 == 0) { if(s.excitePort1 == 0 && s.excitePort2 == 0) {
@ -979,6 +989,16 @@ void VNA::SpanZoomOut()
ConstrainAndUpdateFrequencies(); ConstrainAndUpdateFrequencies();
} }
void VNA::SetLogSweep(bool log)
{
if(settings.Freq.logSweep != log) {
settings.Freq.logSweep = log;
emit logSweepChanged(log);
SettingsChanged();
}
}
void VNA::SetSourceLevel(double level) void VNA::SetSourceLevel(double level)
{ {
if(level > Device::Info().limits_cdbm_max / 100.0) { if(level > Device::Info().limits_cdbm_max / 100.0) {
@ -1500,3 +1520,4 @@ VNA::SweepType VNA::SweepTypeFromString(QString s)
// not found // not found
return SweepType::Last; return SweepType::Last;
} }

View File

@ -46,6 +46,7 @@ public:
double start; double start;
double stop; double stop;
double excitation_power; double excitation_power;
bool logSweep;
} Freq; } Freq;
struct { struct {
double start; double start;
@ -70,6 +71,8 @@ private slots:
void SetFullSpan(); void SetFullSpan();
void SpanZoomIn(); void SpanZoomIn();
void SpanZoomOut(); void SpanZoomOut();
void SetLogSweep(bool log);
// Acquisition control // Acquisition control
void SetSourceLevel(double level); void SetSourceLevel(double level);
// Power sweep settings // Power sweep settings
@ -146,6 +149,7 @@ signals:
void stopFreqChanged(double freq); void stopFreqChanged(double freq);
void centerFreqChanged(double freq); void centerFreqChanged(double freq);
void spanChanged(double span); void spanChanged(double span);
void logSweepChanged(bool log);
void sourceLevelChanged(double level); void sourceLevelChanged(double level);
void pointsChanged(unsigned int points); void pointsChanged(unsigned int points);

View File

@ -35,6 +35,7 @@ public:
QString type; QString type;
double f_start; double f_start;
double f_stop; double f_stop;
bool logSweep;
double f_excitation; double f_excitation;
double dbm_start; double dbm_start;
@ -103,12 +104,13 @@ private:
QString name; QString name;
QVariant def; QVariant def;
}; };
const std::array<SettingDescription, 40> descr = {{ const std::array<SettingDescription, 41> descr = {{
{&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true}, {&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true},
{&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false}, {&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false},
{&Startup.DefaultSweep.type, "Startup.DefaultSweep.type", "Frequency"}, {&Startup.DefaultSweep.type, "Startup.DefaultSweep.type", "Frequency"},
{&Startup.DefaultSweep.f_start, "Startup.DefaultSweep.start", 1000000.0}, {&Startup.DefaultSweep.f_start, "Startup.DefaultSweep.start", 1000000.0},
{&Startup.DefaultSweep.f_stop, "Startup.DefaultSweep.stop", 6000000000.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.f_excitation, "Startup.DefaultSweep.excitation", -10.00},
{&Startup.DefaultSweep.dbm_start, "Startup.DefaultSweep.dbm_start", -30.00}, {&Startup.DefaultSweep.dbm_start, "Startup.DefaultSweep.dbm_start", -30.00},
{&Startup.DefaultSweep.dbm_stop, "Startup.DefaultSweep.dbm_stop", -10.0}, {&Startup.DefaultSweep.dbm_stop, "Startup.DefaultSweep.dbm_stop", -10.0},

View File

@ -4,7 +4,7 @@
namespace Protocol { namespace Protocol {
static constexpr uint16_t Version = 7; static constexpr uint16_t Version = 8;
#pragma pack(push, 1) #pragma pack(push, 1)
@ -28,6 +28,7 @@ using SweepSettings = struct _sweepSettings {
uint8_t excitePort2:1; uint8_t excitePort2:1;
uint8_t suppressPeaks: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 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 int16_t cdbm_excitation_stop; // in 1/100 dbm
}; };

View File

@ -13,6 +13,7 @@
#include "task.h" #include "task.h"
#include "Util.hpp" #include "Util.hpp"
#include "usb.h" #include "usb.h"
#include <cmath>
#define LOG_LEVEL LOG_LEVEL_INFO #define LOG_LEVEL LOG_LEVEL_INFO
#define LOG_MODULE "VNA" #define LOG_MODULE "VNA"
@ -20,6 +21,7 @@
static Protocol::SweepSettings settings; static Protocol::SweepSettings settings;
static uint16_t pointCnt; static uint16_t pointCnt;
static float span_log10;
static bool excitingPort1; static bool excitingPort1;
static Protocol::Datapoint data; static Protocol::Datapoint data;
static bool active = false; static bool active = false;
@ -51,6 +53,14 @@ static constexpr uint32_t reservedUSBbuffer = maxPointsBetweenHalts * (sizeof(Pr
using namespace HWHAL; 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) { bool VNA::Setup(Protocol::SweepSettings s) {
VNA::Stop(); VNA::Stop();
vTaskDelay(5); vTaskDelay(5);
@ -62,11 +72,14 @@ bool VNA::Setup(Protocol::SweepSettings s) {
return false; return false;
} }
settings = s; settings = s;
span_log10 = log10((double) settings.f_stop / settings.f_start);
// Abort possible active sweep first // Abort possible active sweep first
FPGA::SetMode(FPGA::Mode::FPGA); 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 // Configure sweep
FPGA::SetNumberOfPoints(points); FPGA::SetNumberOfPoints(settings.points);
uint32_t samplesPerPoint = (HW::ADCSamplerate / s.if_bandwidth); uint32_t samplesPerPoint = (HW::ADCSamplerate / s.if_bandwidth);
// round up to next multiple of 16 (16 samples are spread across 5 IF2 periods) // round up to next multiple of 16 (16 samples are spread across 5 IF2 periods)
if(samplesPerPoint%16) { if(samplesPerPoint%16) {
@ -120,10 +133,10 @@ bool VNA::Setup(Protocol::SweepSettings s) {
uint16_t pointsWithoutHalt = 0; uint16_t pointsWithoutHalt = 0;
// Transfer PLL configuration to FPGA // 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; bool harmonic_mixing = false;
uint64_t freq = s.f_start + (s.f_stop - s.f_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 / (points - 1); int16_t power = s.cdbm_excitation_start + (s.cdbm_excitation_stop - s.cdbm_excitation_start) * i / (settings.points - 1);
freq = Cal::FrequencyCorrectionToDevice(freq); freq = Cal::FrequencyCorrectionToDevice(freq);
if(freq > 6000000000ULL) { if(freq > 6000000000ULL) {
@ -286,7 +299,7 @@ bool VNA::MeasurementDone(const FPGA::SamplingResult &result) {
auto port1 = port1_raw / ref; auto port1 = port1_raw / ref;
auto port2 = port2_raw / ref; auto port2 = port2_raw / ref;
data.pointNum = pointCnt; 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); data.cdbm = settings.cdbm_excitation_start + (settings.cdbm_excitation_stop - settings.cdbm_excitation_start) * pointCnt / (settings.points - 1);
if(excitingPort1) { if(excitingPort1) {
data.real_S11 = port1.real(); 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 // PLL reset causes the 2.LO to turn off briefly and then ramp on back, needs delay before next point
Delay::us(1300); Delay::us(1300);
} }
uint64_t frequency = settings.f_start uint64_t frequency = getPointFrequency(pointCnt);
+ (settings.f_stop - settings.f_start) * pointCnt
/ (settings.points - 1);
int16_t power = settings.cdbm_excitation_start int16_t power = settings.cdbm_excitation_start
+ (settings.cdbm_excitation_stop - settings.cdbm_excitation_start) + (settings.cdbm_excitation_stop - settings.cdbm_excitation_start)
* pointCnt / (settings.points - 1); * pointCnt / (settings.points - 1);