Change ADC samplerate for points at which LO feedthrough would alias
This commit is contained in:
parent
2118c07f09
commit
d0640e0e42
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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…
Reference in New Issue
Block a user