diff --git a/Software/VNA_embedded/Application/Drivers/Si5351C.cpp b/Software/VNA_embedded/Application/Drivers/Si5351C.cpp index 3997afb..cd9800c 100644 --- a/Software/VNA_embedded/Application/Drivers/Si5351C.cpp +++ b/Software/VNA_embedded/Application/Drivers/Si5351C.cpp @@ -119,6 +119,29 @@ bool Si5351C::SetCLK(uint8_t clknum, uint32_t frequency, PLL source, DriveStreng return WriteClkConfig(c, clknum); } +bool Si5351C::SetBypass(uint8_t clknum, PLLSource source, DriveStrength strength) { + // compile CLKControl register + uint8_t clkcontrol = 0x00; + if (source == PLLSource::CLKIN) { + clkcontrol |= 0x04; + } + switch (strength) { + case DriveStrength::mA2: + break; + case DriveStrength::mA4: + clkcontrol |= 0x01; + break; + case DriveStrength::mA6: + clkcontrol |= 0x02; + break; + case DriveStrength::mA8: + clkcontrol |= 0x03; + break; + } + Reg reg = (Reg) ((int) Reg::CLK0Control + clknum); + return WriteRegister(reg, clkcontrol); +} + bool Si5351C::SetCLKtoXTAL(uint8_t clknum) { Reg reg = (Reg) ((int) Reg::CLK0Control + clknum); LOG_INFO("Connecting CLK%d to XTAL", clknum); @@ -163,8 +186,15 @@ bool Si5351C::WritePLLConfig(PLLConfig config, PLL pll) { PllData[5] = ((config.P3 >> 12) & 0xF0) | ((config.P2 >> 16) & 0x0F); PllData[6] = (config.P2 >> 8) & 0xFF; PllData[7] = config.P2 & 0xFF; + // Check if integer mode is applicable + Reg reg = pll == PLL::A ? Reg::CLK6Control : Reg::CLK7Control; + if (config.P2 == 0 && config.P1 % 128 == 0) { + SetBits(reg, 0x40); + } else { + ClearBits(reg, 0x40); + } bool success = true; - Reg reg = pll == PLL::A ? Reg::MSNA_CONFIG : Reg::MSNB_CONFIG; + reg = pll == PLL::A ? Reg::MSNA_CONFIG : Reg::MSNB_CONFIG; success &= WriteRegisterRange(reg, PllData, sizeof(PllData)); reg = pll == PLL::A ? Reg::CLK6Control : Reg::CLK7Control; if (config.IntegerMode) { @@ -229,6 +259,11 @@ bool Si5351C::WriteClkConfig(ClkConfig config, uint8_t clknum) { clkcontrol |= 0x03; break; } + // Check if integer mode is applicable + if(config.P2 == 0 && config.P1%128 == 0) { + // Use integer mode + clkcontrol |= 0x40; + } Reg reg = (Reg) ((int) Reg::CLK0Control + clknum); success &= WriteRegister(reg, clkcontrol); if (clknum <= 5) { @@ -242,6 +277,7 @@ bool Si5351C::WriteClkConfig(ClkConfig config, uint8_t clknum) { ClkData[5] = ((config.P3 >> 12) & 0xF0) | ((config.P2 >> 16) & 0x0F); ClkData[6] = (config.P2 >> 8) & 0xFF; ClkData[7] = config.P2 & 0xFF; + // Calculate address of register control block reg = (Reg) ((int) Reg::MS0_CONFIG + 8 * clknum); success &= WriteRegisterRange(reg, ClkData, sizeof(ClkData)); @@ -318,28 +354,6 @@ void Si5351C::FindOptimalDivider(uint32_t f_pll, uint32_t f, uint32_t &P1, // always using the highest modulus divider results in less than 1Hz deviation for all frequencies, that is good enough uint32_t best_c = (1UL << 20) - 1; uint32_t best_b = (uint64_t) f_rem * best_c / f; -// uint32_t best_deviation = UINT32_MAX; -// for (uint32_t c = (1UL << 20) - 1; c >= (1UL << 19); c--) { -// uint32_t guess_b = (uint64_t) f_rem * c / f; -// for (uint32_t b = guess_b; b <= guess_b + 1; b++) { -// int32_t f_div = (uint64_t) f * b / c; -// uint32_t deviation = abs(f_rem - f_div); -// if (deviation < best_deviation) { -// best_b = b; -// best_c = c; -// best_deviation = deviation; -// if (deviation <= 3) { -// break; -// } -// } -// } -// if (best_deviation <= 3) { -// break; -// } -// } -// LOG_DEBUG( -// "Optimal divider for %luHz/%luHz is: a=%lu, b=%lu, c=%lu (%luHz deviation)", -// f_pll, f, a, best_b, best_c, best_deviation); // convert to Si5351C parameters uint32_t floor = 128 * best_b / best_c; P1 = 128 * a + floor - 512; @@ -360,4 +374,3 @@ bool Si5351C::ReadRawCLKConfig(uint8_t clknum, uint8_t *config) { return ReadRegisterRange(reg, config, 8); } - diff --git a/Software/VNA_embedded/Application/Drivers/Si5351C.hpp b/Software/VNA_embedded/Application/Drivers/Si5351C.hpp index 16b8011..c20a861 100644 --- a/Software/VNA_embedded/Application/Drivers/Si5351C.hpp +++ b/Software/VNA_embedded/Application/Drivers/Si5351C.hpp @@ -33,6 +33,7 @@ public: bool ConfigureCLKIn(uint32_t clkin_freq); bool SetPLL(PLL pll, uint32_t frequency, PLLSource src); bool SetCLK(uint8_t clknum, uint32_t frequency, PLL source, DriveStrength strength = DriveStrength::mA2, uint32_t PLLFreqOverride = 0); + bool SetBypass(uint8_t clknum, PLLSource source, DriveStrength strength = DriveStrength::mA2); bool SetCLKtoXTAL(uint8_t clknum); bool SetCLKToCLKIN(uint8_t clknum); bool Enable(uint8_t clknum); diff --git a/Software/VNA_embedded/Application/Drivers/max2871.cpp b/Software/VNA_embedded/Application/Drivers/max2871.cpp index 5a78c95..9781898 100644 --- a/Software/VNA_embedded/Application/Drivers/max2871.cpp +++ b/Software/VNA_embedded/Application/Drivers/max2871.cpp @@ -42,7 +42,7 @@ bool MAX2871::Init(uint32_t f_ref, bool doubler, uint16_t r, bool div2) { // recommended phase setting regs[1] |= (1UL << 15); - SetMode(Mode::LowSpur2); + SetMode(Mode::LowNoise); // for all other CP modes the PLL reports unlock condition (output signal appears to be locked) SetCPMode(CPMode::CP20); SetCPCurrent(15); diff --git a/Software/VNA_embedded/Application/Hardware.cpp b/Software/VNA_embedded/Application/Hardware.cpp index 3b8a83a..795822a 100644 --- a/Software/VNA_embedded/Application/Hardware.cpp +++ b/Software/VNA_embedded/Application/Hardware.cpp @@ -92,10 +92,10 @@ bool HW::Init() { Si5351.Init(); // Use Si5351 to generate reference frequencies for other PLLs and ADC - Si5351.SetPLL(Si5351C::PLL::A, 800000000, Si5351C::PLLSource::XTAL); + Si5351.SetPLL(Si5351C::PLL::A, 832000000, Si5351C::PLLSource::XTAL); while(!Si5351.Locked(Si5351C::PLL::A)); - Si5351.SetPLL(Si5351C::PLL::B, 800000000, Si5351C::PLLSource::XTAL); + Si5351.SetPLL(Si5351C::PLL::B, 832000000, Si5351C::PLLSource::XTAL); while(!Si5351.Locked(Si5351C::PLL::B)); extRefInUse = 0; @@ -103,8 +103,10 @@ bool HW::Init() { Si5351.Disable(SiChannel::ReferenceOut); // Both MAX2871 get a 100MHz reference +// Si5351.SetBypass(SiChannel::Source, Si5351C::PLLSource::XTAL); Si5351.SetCLK(SiChannel::Source, HW::PLLRef, Si5351C::PLL::A, Si5351C::DriveStrength::mA2); Si5351.Enable(SiChannel::Source); +// Si5351.SetBypass(SiChannel::LO1, Si5351C::PLLSource::XTAL); Si5351.SetCLK(SiChannel::LO1, HW::PLLRef, Si5351C::PLL::A, Si5351C::DriveStrength::mA2); Si5351.Enable(SiChannel::LO1); // 16MHz FPGA clock diff --git a/Software/VNA_embedded/Application/Hardware.hpp b/Software/VNA_embedded/Application/Hardware.hpp index 370505f..4653e70 100644 --- a/Software/VNA_embedded/Application/Hardware.hpp +++ b/Software/VNA_embedded/Application/Hardware.hpp @@ -34,7 +34,7 @@ static constexpr uint32_t IF2 = 250000; static constexpr uint32_t LO1_minFreq = 25000000; static constexpr uint32_t MaxSamples = 130944; static constexpr uint32_t MinSamples = 16; -static constexpr uint32_t PLLRef = 100000000; +static constexpr uint32_t PLLRef = 104000000; static constexpr uint32_t BandSwitchFrequency = 25000000; static constexpr uint8_t ADCprescaler = FPGA::Clockrate / ADCSamplerate;