mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-05 22:45:23 +00:00
Change ADC samplerate for points at which LO feedthrough would alias
This commit is contained in:
parent
2118c07f09
commit
d0640e0e42
4 changed files with 48 additions and 6 deletions
|
|
@ -23,6 +23,8 @@ static bool excitingPort1;
|
|||
static Protocol::Datapoint data;
|
||||
static bool active = false;
|
||||
static bool sourceHighPower;
|
||||
static bool adcShifted;
|
||||
static uint32_t actualBandwidth;
|
||||
|
||||
using IFTableEntry = struct {
|
||||
uint16_t pointCnt;
|
||||
|
|
@ -34,6 +36,11 @@ static IFTableEntry IFTable[IFTableNumEntries];
|
|||
static uint16_t IFTableIndexCnt = 0;
|
||||
|
||||
static constexpr uint32_t BandSwitchFrequency = 25000000;
|
||||
static constexpr float alternativeSamplerate = 914285.7143f;
|
||||
static constexpr uint8_t alternativePrescaler = 102400000UL / alternativeSamplerate;
|
||||
static_assert(alternativePrescaler * alternativeSamplerate == 102400000UL, "alternative ADCSamplerate can not be reached exactly");
|
||||
static constexpr uint16_t alternativePhaseInc = 4096 * HW::IF2 / alternativeSamplerate;
|
||||
static_assert(alternativePhaseInc * alternativeSamplerate == 4096 * HW::IF2, "DFT can not be computed for 2.IF when using alternative samplerate");
|
||||
|
||||
using namespace HWHAL;
|
||||
|
||||
|
|
@ -59,7 +66,7 @@ bool VNA::Setup(Protocol::SweepSettings s, SweepCallback cb) {
|
|||
if(samplesPerPoint%16) {
|
||||
samplesPerPoint += 16 - samplesPerPoint%16;
|
||||
}
|
||||
uint32_t actualBandwidth = HW::ADCSamplerate / samplesPerPoint;
|
||||
actualBandwidth = HW::ADCSamplerate / samplesPerPoint;
|
||||
// has to be one less than actual number of samples
|
||||
FPGA::SetSamplesPerPoint(samplesPerPoint);
|
||||
|
||||
|
|
@ -178,6 +185,7 @@ bool VNA::Setup(Protocol::SweepSettings s, SweepCallback cb) {
|
|||
// starting port depends on whether port 1 is active in sweep
|
||||
excitingPort1 = s.excitePort1;
|
||||
IFTableIndexCnt = 0;
|
||||
adcShifted = false;
|
||||
active = true;
|
||||
// Start the sweep
|
||||
FPGA::StartSweep();
|
||||
|
|
@ -273,22 +281,50 @@ void VNA::SweepHalted() {
|
|||
uint64_t frequency = settings.f_start
|
||||
+ (settings.f_stop - settings.f_start) * pointCnt
|
||||
/ (settings.points - 1);
|
||||
bool adcShiftRequired = false;
|
||||
if (frequency < BandSwitchFrequency) {
|
||||
// need the Si5351 as Source
|
||||
Si5351.SetCLK(SiChannel::LowbandSource, frequency, Si5351C::PLL::B,
|
||||
sourceHighPower ? Si5351C::DriveStrength::mA8 : Si5351C::DriveStrength::mA2);
|
||||
sourceHighPower ? Si5351C::DriveStrength::mA8 : Si5351C::DriveStrength::mA4);
|
||||
if (pointCnt == 0) {
|
||||
// First point in sweep, enable CLK
|
||||
Si5351.Enable(SiChannel::LowbandSource);
|
||||
FPGA::Disable(FPGA::Periphery::SourceRF);
|
||||
Delay::us(1300);
|
||||
}
|
||||
|
||||
// At low frequencies the 1.LO feedtrough mixes with the 2.LO in the second mixer.
|
||||
// Depending on the stimulus frequency, the resulting mixing product might alias to the 2.IF
|
||||
// in the ADC which causes a spike. Check for this and shift the ADC sampling frequency if necessary
|
||||
uint32_t LO_mixing = (HW::IF1 + frequency) - (HW::IF1 - HW::IF2);
|
||||
// move frequency into ADC range
|
||||
LO_mixing %= HW::ADCSamplerate;
|
||||
// fold at half the samplerate
|
||||
if(LO_mixing >= HW::ADCSamplerate / 2) {
|
||||
LO_mixing = HW::ADCSamplerate - LO_mixing;
|
||||
}
|
||||
if(abs(LO_mixing - HW::IF2) <= actualBandwidth * 2) {
|
||||
// the image is in or near the IF bandwidth and would cause a peak
|
||||
// Use a slightly different ADC samplerate
|
||||
adcShiftRequired = true;
|
||||
}
|
||||
} else if(!FPGA::IsEnabled(FPGA::Periphery::SourceRF)){
|
||||
// first sweep point in highband is also halted, disable lowband source
|
||||
Si5351.Disable(SiChannel::LowbandSource);
|
||||
FPGA::Enable(FPGA::Periphery::SourceRF);
|
||||
}
|
||||
|
||||
if(adcShiftRequired) {
|
||||
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, alternativePrescaler);
|
||||
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, alternativePhaseInc);
|
||||
adcShifted = true;
|
||||
} else if(adcShifted) {
|
||||
// reset to default value
|
||||
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, HW::ADCprescaler);
|
||||
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, HW::DFTphaseInc);
|
||||
adcShifted = false;
|
||||
}
|
||||
|
||||
FPGA::ResumeHaltedSweep();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue