mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-04 14:07:30 +00:00
Fix generator output spikes
- Add manual overwrite in FPGA for hardware that is usually handled by sweep control - Use static hardware configuration for generator (no sweep active anymore)
This commit is contained in:
parent
36f826f7a6
commit
43b588c2f6
12 changed files with 169 additions and 72 deletions
|
|
@ -259,6 +259,7 @@ inline void App_Process() {
|
|||
// insert the last received packet (restarts the timed out operation)
|
||||
USBPacketReceived(last_measure_packet);
|
||||
}
|
||||
HW::updateDeviceStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -356,6 +356,27 @@ uint16_t FPGA::GetStatus() {
|
|||
return (uint16_t) status[0] << 8 | status[1];
|
||||
}
|
||||
|
||||
void FPGA::OverwriteHardware(uint8_t attenuation, LowpassFilter filter, bool lowband, bool port1_enabled, bool port2_enabled) {
|
||||
uint16_t val = 0;
|
||||
val |= 0x8000; // enable overwrite
|
||||
val |= (attenuation & 0x7F) << 8;
|
||||
val |= (int) filter << 6;
|
||||
if (lowband) {
|
||||
val |= 0x0020;
|
||||
}
|
||||
if (port1_enabled) {
|
||||
val |= 0x0010;
|
||||
}
|
||||
if (port2_enabled) {
|
||||
val |= 0x0008;
|
||||
}
|
||||
WriteRegister(Reg::HardwareOverwrite, val);
|
||||
}
|
||||
|
||||
void FPGA::DisableHardwareOverwrite() {
|
||||
WriteRegister(Reg::HardwareOverwrite, 0x0000);
|
||||
}
|
||||
|
||||
FPGA::ADCLimits FPGA::GetADCLimits() {
|
||||
uint16_t cmd = 0xE000;
|
||||
SwitchBytes(cmd);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ enum class Reg {
|
|||
ADCPrescaler = 0x04,
|
||||
PhaseIncrement = 0x05,
|
||||
SweepSetup = 0x06,
|
||||
HardwareOverwrite = 0x07,
|
||||
MAX2871Def0LSB = 0x08,
|
||||
MAX2871Def0MSB = 0x09,
|
||||
MAX2871Def1LSB = 0x0A,
|
||||
|
|
@ -134,6 +135,9 @@ void ResetADCLimits();
|
|||
void ResumeHaltedSweep();
|
||||
uint16_t GetStatus();
|
||||
|
||||
void OverwriteHardware(uint8_t attenuation, LowpassFilter filter, bool lowband, bool port1_enabled, bool port2_enabled);
|
||||
void DisableHardwareOverwrite();
|
||||
|
||||
void StartSweep();
|
||||
void AbortSweep();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,73 +2,59 @@
|
|||
#include "Generator.hpp"
|
||||
#include "Manual.hpp"
|
||||
#include "Hardware.hpp"
|
||||
#include "HW_HAL.hpp"
|
||||
#include "max2871.hpp"
|
||||
#include "Si5351C.hpp"
|
||||
|
||||
void Generator::Setup(Protocol::GeneratorSettings g) {
|
||||
if(g.activePort == 0) {
|
||||
// both ports disabled, no need to configure PLLs
|
||||
HW::SetIdle();
|
||||
return;
|
||||
}
|
||||
Protocol::ManualControlV1 m;
|
||||
// LOs not required
|
||||
m.LO1CE = 0;
|
||||
m.LO1Frequency = 1000000000;
|
||||
m.LO1RFEN = 0;
|
||||
m.LO1RFEN = 0;
|
||||
m.LO2EN = 0;
|
||||
m.LO2Frequency = 60000000;
|
||||
m.Port1EN = 0;
|
||||
m.Port2EN = 0;
|
||||
m.RefEN = 0;
|
||||
m.Samples = 131072;
|
||||
m.WindowType = (int) FPGA::Window::None;
|
||||
using namespace HWHAL;
|
||||
|
||||
switch(g.activePort) {
|
||||
case 1:
|
||||
m.AmplifierEN = 1;
|
||||
m.PortSwitch = 0;
|
||||
break;
|
||||
case 2:
|
||||
m.AmplifierEN = 1;
|
||||
m.PortSwitch = 1;
|
||||
break;
|
||||
void Generator::Setup(Protocol::GeneratorSettings g) {
|
||||
HW::SetMode(HW::Mode::Generator);
|
||||
if(g.activePort == 0) {
|
||||
// both ports disabled, no need to configure PLLs
|
||||
Si5351.Disable(SiChannel::LowbandSource);
|
||||
FPGA::Disable(FPGA::Periphery::SourceChip);
|
||||
FPGA::Disable(FPGA::Periphery::Amplifier);
|
||||
FPGA::Disable(FPGA::Periphery::SourceRF);
|
||||
FPGA::Disable(FPGA::Periphery::PortSwitch);
|
||||
FPGA::DisableHardwareOverwrite();
|
||||
return;
|
||||
}
|
||||
|
||||
g.frequency = Cal::FrequencyCorrectionToDevice(g.frequency);
|
||||
auto amplitude = HW::GetAmplitudeSettings(g.cdbm_level, g.frequency, g.applyAmplitudeCorrection, g.activePort == 2);
|
||||
// Select correct source
|
||||
bool bandSelect;
|
||||
FPGA::LowpassFilter lp = FPGA::LowpassFilter::M947;
|
||||
if(g.frequency < HW::BandSwitchFrequency) {
|
||||
m.SourceLowEN = 1;
|
||||
m.SourceLowFrequency = g.frequency;
|
||||
m.SourceHighCE = 0;
|
||||
m.SourceHighRFEN = 0;
|
||||
m.SourceHighFrequency = HW::BandSwitchFrequency;
|
||||
m.SourceHighLowpass = (int) FPGA::LowpassFilter::M947;
|
||||
m.SourceHighPower = (int) MAX2871::Power::n4dbm;
|
||||
m.SourceHighband = false;
|
||||
m.SourceLowPower = (int) amplitude.lowBandPower;
|
||||
bandSelect = true;
|
||||
FPGA::Disable(FPGA::Periphery::SourceChip);
|
||||
Si5351.SetCLK(SiChannel::LowbandSource, g.frequency, Si5351C::PLL::B,
|
||||
amplitude.lowBandPower);
|
||||
Si5351.Enable(SiChannel::LowbandSource);
|
||||
} else {
|
||||
m.SourceLowEN = 0;
|
||||
m.SourceLowFrequency = HW::BandSwitchFrequency;
|
||||
m.SourceHighCE = 1;
|
||||
m.SourceHighRFEN = 1;
|
||||
m.SourceHighFrequency = g.frequency;
|
||||
bandSelect = false;
|
||||
Si5351.Disable(SiChannel::LowbandSource);
|
||||
FPGA::Enable(FPGA::Periphery::SourceChip);
|
||||
FPGA::SetMode(FPGA::Mode::SourcePLL);
|
||||
Source.SetPowerOutA(amplitude.highBandPower);
|
||||
Source.SetFrequency(g.frequency);
|
||||
Source.Update();
|
||||
FPGA::SetMode(FPGA::Mode::FPGA);
|
||||
if(g.frequency < 900000000UL) {
|
||||
m.SourceHighLowpass = (int) FPGA::LowpassFilter::M947;
|
||||
lp = FPGA::LowpassFilter::M947;
|
||||
} else if(g.frequency < 1800000000UL) {
|
||||
m.SourceHighLowpass = (int) FPGA::LowpassFilter::M1880;
|
||||
lp = FPGA::LowpassFilter::M1880;
|
||||
} else if(g.frequency < 3500000000UL) {
|
||||
m.SourceHighLowpass = (int) FPGA::LowpassFilter::M3500;
|
||||
lp = FPGA::LowpassFilter::M3500;
|
||||
} else {
|
||||
m.SourceHighLowpass = (int) FPGA::LowpassFilter::None;
|
||||
lp = FPGA::LowpassFilter::None;
|
||||
}
|
||||
m.SourceHighband = true;
|
||||
m.SourceHighPower = (int) amplitude.highBandPower;
|
||||
m.SourceLowPower = (int) Si5351C::DriveStrength::mA2;
|
||||
}
|
||||
|
||||
m.attenuator = amplitude.attenuator;
|
||||
Manual::Setup(m);
|
||||
FPGA::OverwriteHardware(amplitude.attenuator, lp, bandSelect, g.activePort == 1, g.activePort == 2);
|
||||
HW::SetOutputUnlevel(amplitude.unlevel);
|
||||
FPGA::Enable(FPGA::Periphery::Amplifier, true);
|
||||
FPGA::Enable(FPGA::Periphery::SourceRF, true);
|
||||
FPGA::Enable(FPGA::Periphery::PortSwitch, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "Manual.hpp"
|
||||
#include "delay.hpp"
|
||||
#include "SpectrumAnalyzer.hpp"
|
||||
#include "Communication.h"
|
||||
#include <cstring>
|
||||
|
||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||
|
|
@ -139,6 +140,8 @@ bool HW::Init() {
|
|||
return false;
|
||||
}
|
||||
|
||||
FPGA::DisableHardwareOverwrite();
|
||||
|
||||
// Set default ADC samplerate
|
||||
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, ADCprescaler);
|
||||
// Set phase increment according to
|
||||
|
|
@ -229,6 +232,7 @@ void HW::SetIdle() {
|
|||
unlevel = false;
|
||||
FPGA::AbortSweep();
|
||||
FPGA::SetMode(FPGA::Mode::FPGA);
|
||||
FPGA::DisableHardwareOverwrite();
|
||||
FPGA::Enable(FPGA::Periphery::SourceChip, false);
|
||||
FPGA::Enable(FPGA::Periphery::SourceRF, false);
|
||||
FPGA::Enable(FPGA::Periphery::LO1Chip, false);
|
||||
|
|
@ -289,7 +293,7 @@ HW::AmplitudeSettings HW::GetAmplitudeSettings(int16_t cdbm, uint64_t freq, bool
|
|||
|
||||
bool HW::TimedOut() {
|
||||
constexpr uint64_t timeout = 1000000;
|
||||
if(activeMode != Mode::Idle && Delay::get_us() - lastISR > timeout) {
|
||||
if(activeMode != Mode::Idle && activeMode != Mode::Generator && Delay::get_us() - lastISR > timeout) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -420,6 +424,28 @@ uint64_t HW::getLastISRTimestamp() {
|
|||
return lastISR;
|
||||
}
|
||||
|
||||
void HW::updateDeviceStatus() {
|
||||
if(activeMode == Mode::Idle || activeMode == Mode::Generator) {
|
||||
static uint32_t last_update = 0;
|
||||
if(HAL_GetTick() - last_update >= 1000) {
|
||||
last_update = HAL_GetTick();
|
||||
HW::Ref::update();
|
||||
Protocol::PacketInfo packet;
|
||||
packet.type = Protocol::PacketType::DeviceStatusV1;
|
||||
// Enable PLL chips for temperature reading
|
||||
bool srcEn = FPGA::IsEnabled(FPGA::Periphery::SourceChip);
|
||||
bool LOEn = FPGA::IsEnabled(FPGA::Periphery::LO1Chip);
|
||||
FPGA::Enable(FPGA::Periphery::SourceChip);
|
||||
FPGA::Enable(FPGA::Periphery::LO1Chip);
|
||||
HW::getDeviceStatus(&packet.statusV1, true);
|
||||
// restore PLL state
|
||||
FPGA::Enable(FPGA::Periphery::SourceChip, srcEn);
|
||||
FPGA::Enable(FPGA::Periphery::LO1Chip, LOEn);
|
||||
Communication::Send(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t HW::getDFTPhaseInc() {
|
||||
return DFTphaseInc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ static constexpr Protocol::DeviceInfo Info = {
|
|||
enum class Mode {
|
||||
Idle,
|
||||
Manual,
|
||||
Generator,
|
||||
VNA,
|
||||
SA,
|
||||
};
|
||||
|
|
@ -101,6 +102,8 @@ uint64_t getLastISRTimestamp();
|
|||
|
||||
void SetOutputUnlevel(bool unlev);
|
||||
|
||||
void updateDeviceStatus();
|
||||
|
||||
using AmplitudeSettings = struct _amplitudeSettings {
|
||||
uint8_t attenuator;
|
||||
union {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue