Change ADC samplerate for points at which LO feedthrough would alias

This commit is contained in:
Jan Käberich 2020-10-30 19:23:34 +01:00
parent 2118c07f09
commit d0640e0e42
4 changed files with 48 additions and 6 deletions

View File

@ -70,7 +70,7 @@ void Generator::Setup(Protocol::GeneratorSettings g) {
} else {
// use lower source power (approx -10dbm with no attenuation)
m.SourceHighPower = (int) MAX2871::Power::n4dbm;
m.SourceLowPower = (int) Si5351C::DriveStrength::mA2;
m.SourceLowPower = (int) Si5351C::DriveStrength::mA4;
g.cdbm_level += 1000;
}
// calculate required attenuation

View File

@ -127,8 +127,9 @@ bool HW::Init() {
}
// Set default ADC samplerate
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, 128);
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, 1280);
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, HW::ADCprescaler);
// Set phase increment according to
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, HW::DFTphaseInc);
// Enable new data and sweep halt interrupt
FPGA::EnableInterrupt(FPGA::Interrupt::NewData);

View File

@ -33,8 +33,13 @@ static constexpr uint32_t MinSamples = 16;
static constexpr uint32_t PLLRef = 100000000;
static constexpr uint16_t MaxPoints = 4501;
static constexpr uint8_t ADCprescaler = 102400000UL / ADCSamplerate;
static_assert(ADCprescaler * ADCSamplerate == 102400000UL, "ADCSamplerate can not be reached exactly");
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 = 1000000,
.minFreq = 0,
.maxFreq = 6000000000,
.minIFBW = ADCSamplerate / MaxSamples,
.maxIFBW = ADCSamplerate / MinSamples,

View File

@ -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();
}