mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-04 14:07:30 +00:00
Protocol adjustment + exposing settings for DFT
This commit is contained in:
parent
ce475fa042
commit
a2389fca13
19 changed files with 314 additions and 205 deletions
|
|
@ -155,10 +155,10 @@ void App_Start() {
|
|||
SA::Setup(recv_packet.spectrumSettings);
|
||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||
break;
|
||||
case Protocol::PacketType::RequestDeviceLimits:
|
||||
case Protocol::PacketType::RequestDeviceInfo:
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::DeviceLimits;
|
||||
p.limits = HW::Limits;
|
||||
p.type = Protocol::PacketType::DeviceInfo;
|
||||
HW::fillDeviceInfo(&p.info);
|
||||
Communication::Send(p);
|
||||
break;
|
||||
#ifdef HAS_FLASH
|
||||
|
|
|
|||
|
|
@ -238,35 +238,58 @@ static int16_t EncodeGeneratorSettings(Protocol::GeneratorSettings d, uint8_t *b
|
|||
static Protocol::DeviceInfo DecodeDeviceInfo(uint8_t *buf) {
|
||||
Protocol::DeviceInfo d;
|
||||
Decoder e(buf);
|
||||
e.get<uint16_t>(d.FW_major);
|
||||
e.get<uint16_t>(d.FW_minor);
|
||||
e.get<char>(d.HW_Revision);
|
||||
e.get(d.ProtocolVersion);
|
||||
e.get(d.FW_major);
|
||||
e.get(d.FW_minor);
|
||||
e.get(d.FW_patch);
|
||||
e.get(d.HW_Revision);
|
||||
d.extRefAvailable = e.getBits(1);
|
||||
d.extRefInUse = e.getBits(1);
|
||||
d.FPGA_configured = e.getBits(1);
|
||||
d.source_locked = e.getBits(1);
|
||||
d.LO1_locked = e.getBits(1);
|
||||
d.ADC_overload = e.getBits(1);
|
||||
e.get<uint8_t>(d.temperatures.source);
|
||||
e.get<uint8_t>(d.temperatures.LO1);
|
||||
e.get<uint8_t>(d.temperatures.MCU);
|
||||
e.get(d.temp_source);
|
||||
e.get(d.temp_LO1);
|
||||
e.get(d.temp_MCU);
|
||||
e.get(d.limits_minFreq);
|
||||
e.get(d.limits_maxFreq);
|
||||
e.get(d.limits_minIFBW);
|
||||
e.get(d.limits_maxIFBW);
|
||||
e.get(d.limits_maxPoints);
|
||||
e.get(d.limits_cdbm_min);
|
||||
e.get(d.limits_cdbm_max);
|
||||
e.get(d.limits_minRBW);
|
||||
e.get(d.limits_maxRBW);
|
||||
return d;
|
||||
}
|
||||
static int16_t EncodeDeviceInfo(Protocol::DeviceInfo d, uint8_t *buf,
|
||||
uint16_t bufSize) {
|
||||
d.ProtocolVersion = Protocol::Version;
|
||||
Encoder e(buf, bufSize);
|
||||
e.add<uint16_t>(d.FW_major);
|
||||
e.add<uint16_t>(d.FW_minor);
|
||||
e.add<char>(d.HW_Revision);
|
||||
e.add(d.ProtocolVersion);
|
||||
e.add(d.FW_major);
|
||||
e.add(d.FW_minor);
|
||||
e.add(d.FW_patch);
|
||||
e.add(d.HW_Revision);
|
||||
e.addBits(d.extRefAvailable, 1);
|
||||
e.addBits(d.extRefInUse, 1);
|
||||
e.addBits(d.FPGA_configured, 1);
|
||||
e.addBits(d.source_locked, 1);
|
||||
e.addBits(d.LO1_locked, 1);
|
||||
e.addBits(d.ADC_overload, 1);
|
||||
e.add<uint8_t>(d.temperatures.source);
|
||||
e.add<uint8_t>(d.temperatures.LO1);
|
||||
e.add<uint8_t>(d.temperatures.MCU);
|
||||
e.add(d.temp_source);
|
||||
e.add(d.temp_LO1);
|
||||
e.add(d.temp_MCU);
|
||||
e.add(d.limits_minFreq);
|
||||
e.add(d.limits_maxFreq);
|
||||
e.add(d.limits_minIFBW);
|
||||
e.add(d.limits_maxIFBW);
|
||||
e.add(d.limits_maxPoints);
|
||||
e.add(d.limits_cdbm_min);
|
||||
e.add(d.limits_cdbm_max);
|
||||
e.add(d.limits_minRBW);
|
||||
e.add(d.limits_maxRBW);
|
||||
return e.getSize();
|
||||
}
|
||||
|
||||
|
|
@ -378,6 +401,7 @@ static Protocol::SpectrumAnalyzerSettings DecodeSpectrumAnalyzerSettings(uint8_t
|
|||
d.WindowType = e.getBits(2);
|
||||
d.SignalID = e.getBits(1);
|
||||
d.Detector = e.getBits(3);
|
||||
d.UseDFT = e.getBits(1);
|
||||
return d;
|
||||
}
|
||||
static int16_t EncodeSpectrumAnalyzerSettings(Protocol::SpectrumAnalyzerSettings d, uint8_t *buf,
|
||||
|
|
@ -390,6 +414,7 @@ static int16_t EncodeSpectrumAnalyzerSettings(Protocol::SpectrumAnalyzerSettings
|
|||
e.addBits(d.WindowType, 2);
|
||||
e.addBits(d.SignalID, 1);
|
||||
e.addBits(d.Detector, 3);
|
||||
e.addBits(d.UseDFT, 1);
|
||||
return e.getSize();
|
||||
}
|
||||
|
||||
|
|
@ -412,35 +437,6 @@ static int16_t EncodeSpectrumAnalyzerResult(Protocol::SpectrumAnalyzerResult d,
|
|||
return e.getSize();
|
||||
}
|
||||
|
||||
static Protocol::DeviceLimits DecodeDeviceLimits(uint8_t *buf) {
|
||||
Protocol::DeviceLimits d;
|
||||
Decoder e(buf);
|
||||
e.get(d.minFreq);
|
||||
e.get(d.maxFreq);
|
||||
e.get(d.minIFBW);
|
||||
e.get(d.maxIFBW);
|
||||
e.get(d.maxPoints);
|
||||
e.get(d.cdbm_min);
|
||||
e.get(d.cdbm_max);
|
||||
e.get(d.minRBW);
|
||||
e.get(d.maxRBW);
|
||||
return d;
|
||||
}
|
||||
static int16_t EncodeDeviceLimits(Protocol::DeviceLimits d, uint8_t *buf,
|
||||
uint16_t bufSize) {
|
||||
Encoder e(buf, bufSize);
|
||||
e.add(d.minFreq);
|
||||
e.add(d.maxFreq);
|
||||
e.add(d.minIFBW);
|
||||
e.add(d.maxIFBW);
|
||||
e.add(d.maxPoints);
|
||||
e.add(d.cdbm_min);
|
||||
e.add(d.cdbm_max);
|
||||
e.add(d.minRBW);
|
||||
e.add(d.maxRBW);
|
||||
return e.getSize();
|
||||
}
|
||||
|
||||
static Protocol::FirmwarePacket DecodeFirmwarePacket(uint8_t *buf) {
|
||||
Protocol::FirmwarePacket d;
|
||||
// simple packet format, memcpy is faster than using the decoder
|
||||
|
|
@ -545,14 +541,11 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
|
|||
case PacketType::SpectrumAnalyzerResult:
|
||||
info->spectrumResult = DecodeSpectrumAnalyzerResult(&data[4]);
|
||||
break;
|
||||
case PacketType::DeviceLimits:
|
||||
info->limits = DecodeDeviceLimits(&data[4]);
|
||||
break;
|
||||
case PacketType::Ack:
|
||||
case PacketType::PerformFirmwareUpdate:
|
||||
case PacketType::ClearFlash:
|
||||
case PacketType::Nack:
|
||||
case PacketType::RequestDeviceLimits:
|
||||
case PacketType::RequestDeviceInfo:
|
||||
// no payload, nothing to do
|
||||
break;
|
||||
case PacketType::None:
|
||||
|
|
@ -595,14 +588,11 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
|
|||
case PacketType::SpectrumAnalyzerResult:
|
||||
payload_size = EncodeSpectrumAnalyzerResult(packet.spectrumResult, &dest[4], destsize - 8);
|
||||
break;
|
||||
case PacketType::DeviceLimits:
|
||||
payload_size = EncodeDeviceLimits(packet.limits, &dest[4], destsize - 8);
|
||||
break;
|
||||
case PacketType::Ack:
|
||||
case PacketType::PerformFirmwareUpdate:
|
||||
case PacketType::ClearFlash:
|
||||
case PacketType::Nack:
|
||||
case PacketType::RequestDeviceLimits:
|
||||
case PacketType::RequestDeviceInfo:
|
||||
// no payload, nothing to do
|
||||
break;
|
||||
case PacketType::None:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
namespace Protocol {
|
||||
|
||||
static constexpr uint16_t Version = 1;
|
||||
|
||||
// When changing/adding/removing variables from these structs also adjust the decode/encode functions in Protocol.cpp
|
||||
|
||||
using Datapoint = struct _datapoint {
|
||||
|
|
@ -39,8 +41,10 @@ using GeneratorSettings = struct _generatorSettings {
|
|||
};
|
||||
|
||||
using DeviceInfo = struct _deviceInfo {
|
||||
uint16_t FW_major;
|
||||
uint16_t FW_minor;
|
||||
uint16_t ProtocolVersion;
|
||||
uint8_t FW_major;
|
||||
uint8_t FW_minor;
|
||||
uint8_t FW_patch;
|
||||
char HW_Revision;
|
||||
uint8_t extRefAvailable:1;
|
||||
uint8_t extRefInUse:1;
|
||||
|
|
@ -48,11 +52,18 @@ using DeviceInfo = struct _deviceInfo {
|
|||
uint8_t source_locked:1;
|
||||
uint8_t LO1_locked:1;
|
||||
uint8_t ADC_overload:1;
|
||||
struct {
|
||||
uint8_t source;
|
||||
uint8_t LO1;
|
||||
uint8_t MCU;
|
||||
} temperatures;
|
||||
uint8_t temp_source;
|
||||
uint8_t temp_LO1;
|
||||
uint8_t temp_MCU;
|
||||
uint64_t limits_minFreq;
|
||||
uint64_t limits_maxFreq;
|
||||
uint32_t limits_minIFBW;
|
||||
uint32_t limits_maxIFBW;
|
||||
uint16_t limits_maxPoints;
|
||||
int16_t limits_cdbm_min;
|
||||
int16_t limits_cdbm_max;
|
||||
uint32_t limits_minRBW;
|
||||
uint32_t limits_maxRBW;
|
||||
};
|
||||
|
||||
using ManualStatus = struct _manualstatus {
|
||||
|
|
@ -107,6 +118,7 @@ using SpectrumAnalyzerSettings = struct _spectrumAnalyzerSettings {
|
|||
uint8_t WindowType :2;
|
||||
uint8_t SignalID :1;
|
||||
uint8_t Detector :3;
|
||||
uint8_t UseDFT :1;
|
||||
};
|
||||
|
||||
using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult {
|
||||
|
|
@ -116,18 +128,6 @@ using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult {
|
|||
uint16_t pointNum;
|
||||
};
|
||||
|
||||
using DeviceLimits = struct _deviceLimits {
|
||||
uint64_t minFreq;
|
||||
uint64_t maxFreq;
|
||||
uint32_t minIFBW;
|
||||
uint32_t maxIFBW;
|
||||
uint16_t maxPoints;
|
||||
int16_t cdbm_min;
|
||||
int16_t cdbm_max;
|
||||
uint32_t minRBW;
|
||||
uint32_t maxRBW;
|
||||
};
|
||||
|
||||
static constexpr uint16_t FirmwareChunkSize = 256;
|
||||
using FirmwarePacket = struct _firmwarePacket {
|
||||
uint32_t address;
|
||||
|
|
@ -150,8 +150,7 @@ enum class PacketType : uint8_t {
|
|||
Generator = 12,
|
||||
SpectrumAnalyzerSettings = 13,
|
||||
SpectrumAnalyzerResult = 14,
|
||||
RequestDeviceLimits = 15,
|
||||
DeviceLimits = 16,
|
||||
RequestDeviceInfo = 15,
|
||||
};
|
||||
|
||||
using PacketInfo = struct _packetinfo {
|
||||
|
|
@ -167,7 +166,6 @@ using PacketInfo = struct _packetinfo {
|
|||
ManualStatus status;
|
||||
SpectrumAnalyzerSettings spectrumSettings;
|
||||
SpectrumAnalyzerResult spectrumResult;
|
||||
DeviceLimits limits;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "VNA.hpp"
|
||||
#include "Manual.hpp"
|
||||
#include "SpectrumAnalyzer.hpp"
|
||||
#include <cstring>
|
||||
|
||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||
#define LOG_MODULE "HW"
|
||||
|
|
@ -222,33 +223,39 @@ void HW::SetIdle() {
|
|||
FPGA::Enable(FPGA::Periphery::PortSwitch, false);
|
||||
}
|
||||
|
||||
void HW::fillDeviceInfo(Protocol::DeviceInfo *info) {
|
||||
// read PLL temperatures
|
||||
uint8_t tempSource, tempLO;
|
||||
GetTemps(&tempSource, &tempLO);
|
||||
LOG_INFO("PLL temperatures: %u/%u", tempSource, tempLO);
|
||||
// Read ADC min/max
|
||||
auto limits = FPGA::GetADCLimits();
|
||||
LOG_INFO("ADC limits: P1: %d/%d P2: %d/%d R: %d/%d",
|
||||
limits.P1min, limits.P1max, limits.P2min, limits.P2max,
|
||||
limits.Rmin, limits.Rmax);
|
||||
#define ADC_LIMIT 30000
|
||||
if(limits.P1min < -ADC_LIMIT || limits.P1max > ADC_LIMIT
|
||||
|| limits.P2min < -ADC_LIMIT || limits.P2max > ADC_LIMIT
|
||||
|| limits.Rmin < -ADC_LIMIT || limits.Rmax > ADC_LIMIT) {
|
||||
info->ADC_overload = true;
|
||||
} else {
|
||||
info->ADC_overload = false;
|
||||
void HW::fillDeviceInfo(Protocol::DeviceInfo *info, bool updateEvenWhenBusy) {
|
||||
// copy constant default values
|
||||
memcpy(info, &HW::Info, sizeof(HW::Info));
|
||||
if(activeMode == Mode::Idle || updateEvenWhenBusy) {
|
||||
// updating values from FPGA allowed
|
||||
|
||||
// read PLL temperatures
|
||||
uint8_t tempSource, tempLO;
|
||||
GetTemps(&tempSource, &tempLO);
|
||||
LOG_INFO("PLL temperatures: %u/%u", tempSource, tempLO);
|
||||
// Read ADC min/max
|
||||
auto limits = FPGA::GetADCLimits();
|
||||
LOG_INFO("ADC limits: P1: %d/%d P2: %d/%d R: %d/%d",
|
||||
limits.P1min, limits.P1max, limits.P2min, limits.P2max,
|
||||
limits.Rmin, limits.Rmax);
|
||||
#define ADC_LIMIT 30000
|
||||
if(limits.P1min < -ADC_LIMIT || limits.P1max > ADC_LIMIT
|
||||
|| limits.P2min < -ADC_LIMIT || limits.P2max > ADC_LIMIT
|
||||
|| limits.Rmin < -ADC_LIMIT || limits.Rmax > ADC_LIMIT) {
|
||||
info->ADC_overload = true;
|
||||
} else {
|
||||
info->ADC_overload = false;
|
||||
}
|
||||
auto status = FPGA::GetStatus();
|
||||
info->LO1_locked = (status & (int) FPGA::Interrupt::LO1Unlock) ? 0 : 1;
|
||||
info->source_locked = (status & (int) FPGA::Interrupt::SourceUnlock) ? 0 : 1;
|
||||
info->extRefAvailable = Ref::available();
|
||||
info->extRefInUse = extRefInUse;
|
||||
info->temp_LO1 = tempLO;
|
||||
info->temp_source = tempSource;
|
||||
FPGA::ResetADCLimits();
|
||||
}
|
||||
auto status = FPGA::GetStatus();
|
||||
info->LO1_locked = (status & (int) FPGA::Interrupt::LO1Unlock) ? 0 : 1;
|
||||
info->source_locked = (status & (int) FPGA::Interrupt::SourceUnlock) ? 0 : 1;
|
||||
info->extRefAvailable = Ref::available();
|
||||
info->extRefInUse = extRefInUse;
|
||||
info->temperatures.LO1 = tempLO;
|
||||
info->temperatures.source = tempSource;
|
||||
info->temperatures.MCU = STM::getTemperature();
|
||||
FPGA::ResetADCLimits();
|
||||
info->temp_MCU = STM::getTemperature();
|
||||
}
|
||||
|
||||
bool HW::Ref::available() {
|
||||
|
|
|
|||
|
|
@ -38,16 +38,30 @@ static_assert(ADCprescaler * ADCSamplerate == FPGA::Clockrate, "ADCSamplerate ca
|
|||
static constexpr uint16_t DFTphaseInc = 4096 * IF2 / ADCSamplerate;
|
||||
static_assert(DFTphaseInc * ADCSamplerate == 4096 * IF2, "DFT can not be computed for 2.IF");
|
||||
|
||||
static constexpr Protocol::DeviceLimits Limits = {
|
||||
.minFreq = 0,
|
||||
.maxFreq = 6000000000,
|
||||
.minIFBW = ADCSamplerate / MaxSamples,
|
||||
.maxIFBW = ADCSamplerate / MinSamples,
|
||||
.maxPoints = FPGA::MaxPoints,
|
||||
.cdbm_min = -4000,
|
||||
.cdbm_max = 0,
|
||||
.minRBW = (uint32_t) (ADCSamplerate * 2.23f / MaxSamples),
|
||||
.maxRBW = (uint32_t) (ADCSamplerate * 2.23f / MinSamples),
|
||||
static constexpr Protocol::DeviceInfo Info = {
|
||||
.ProtocolVersion = Protocol::Version,
|
||||
.FW_major = FW_MAJOR,
|
||||
.FW_minor = FW_MINOR,
|
||||
.FW_patch = FW_PATCH,
|
||||
.HW_Revision = HW_REVISION,
|
||||
.extRefAvailable = 0,
|
||||
.extRefInUse = 0,
|
||||
.FPGA_configured = 0,
|
||||
.source_locked = 0,
|
||||
.LO1_locked = 0,
|
||||
.ADC_overload = 0,
|
||||
.temp_source = 0,
|
||||
.temp_LO1 = 0,
|
||||
.temp_MCU = 0,
|
||||
.limits_minFreq = 0,
|
||||
.limits_maxFreq = 6000000000,
|
||||
.limits_minIFBW = ADCSamplerate / MaxSamples,
|
||||
.limits_maxIFBW = ADCSamplerate / MinSamples,
|
||||
.limits_maxPoints = FPGA::MaxPoints,
|
||||
.limits_cdbm_min = -4000,
|
||||
.limits_cdbm_max = 0,
|
||||
.limits_minRBW = (uint32_t) (ADCSamplerate * 2.23f / MaxSamples),
|
||||
.limits_maxRBW = (uint32_t) (ADCSamplerate * 2.23f / MinSamples),
|
||||
};
|
||||
|
||||
enum class Mode {
|
||||
|
|
@ -63,7 +77,7 @@ void SetIdle();
|
|||
void Work();
|
||||
|
||||
bool GetTemps(uint8_t *source, uint8_t *lo);
|
||||
void fillDeviceInfo(Protocol::DeviceInfo *info);
|
||||
void fillDeviceInfo(Protocol::DeviceInfo *info, bool updateEvenWhenBusy = false);
|
||||
namespace Ref {
|
||||
bool available();
|
||||
// reference won't change until update is called
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ static Protocol::PacketInfo p;
|
|||
static bool active = false;
|
||||
static uint32_t lastLO2;
|
||||
static uint32_t actualRBW;
|
||||
static bool usingDFT;
|
||||
static uint16_t DFTpoints;
|
||||
static bool negativeDFT; // if true, a positive frequency shift at input results in a negative shift at the 2.IF. Handle DFT accordingly
|
||||
|
||||
|
|
@ -106,7 +105,7 @@ static void StartNextSample() {
|
|||
Si5351.SetCLK(SiChannel::Port2LO2, LO2freq, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
||||
lastLO2 = LO2freq;
|
||||
}
|
||||
if (usingDFT) {
|
||||
if (s.UseDFT) {
|
||||
uint32_t spacing = (s.f_stop - s.f_start) / (points - 1);
|
||||
uint32_t start = HW::IF2;
|
||||
if(negativeDFT) {
|
||||
|
|
@ -166,11 +165,16 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
|
|||
FPGA::Enable(FPGA::Periphery::Port1Mixer);
|
||||
FPGA::Enable(FPGA::Periphery::Port2Mixer);
|
||||
|
||||
// automatically select DFT mode for lower RBWs
|
||||
usingDFT = actualRBW <= 1000;
|
||||
|
||||
if (usingDFT) {
|
||||
DFTpoints = FPGA::DFTbins; // use full DFT in FPGA
|
||||
if (s.UseDFT) {
|
||||
uint32_t spacing = (s.f_stop - s.f_start) / (points - 1);
|
||||
// The DFT can only look at a small bandwidth otherwise the passband of the final ADC filter is visible in the data
|
||||
// Limit to about 30kHz
|
||||
uint32_t maxDFTpoints = 30000 / spacing;
|
||||
// Limit to actual supported number of bins
|
||||
if(maxDFTpoints > FPGA::DFTbins) {
|
||||
maxDFTpoints = FPGA::DFTbins;
|
||||
}
|
||||
DFTpoints = maxDFTpoints;
|
||||
FPGA::DisableInterrupt(FPGA::Interrupt::NewData);
|
||||
} else {
|
||||
DFTpoints = 1; // can only measure one point at a time
|
||||
|
|
@ -191,7 +195,7 @@ bool SA::MeasurementDone(const FPGA::SamplingResult &result) {
|
|||
|
||||
for(uint16_t i=0;i<DFTpoints;i++) {
|
||||
float port1, port2;
|
||||
if (usingDFT) {
|
||||
if (s.UseDFT) {
|
||||
// use DFT result
|
||||
auto dft = FPGA::ReadDFTResult();
|
||||
port1 = dft.P1;
|
||||
|
|
@ -217,7 +221,7 @@ bool SA::MeasurementDone(const FPGA::SamplingResult &result) {
|
|||
}
|
||||
}
|
||||
|
||||
if (usingDFT) {
|
||||
if (s.UseDFT) {
|
||||
FPGA::StopDFT();
|
||||
// will be started again in StartNextSample
|
||||
}
|
||||
|
|
|
|||
|
|
@ -264,9 +264,8 @@ void VNA::Work() {
|
|||
packet.info.FW_major = FW_MAJOR;
|
||||
packet.info.FW_minor = FW_MINOR;
|
||||
packet.info.HW_Revision = HW_REVISION;
|
||||
HW::fillDeviceInfo(&packet.info);
|
||||
HW::fillDeviceInfo(&packet.info, true);
|
||||
Communication::Send(packet);
|
||||
FPGA::ResetADCLimits();
|
||||
// Start next sweep
|
||||
FPGA::StartSweep();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue