Closed DiSlord closed 4 years ago
Also if change I2C bus clock to 48MHz,
#define STM32_I2C1SW STM32_I2C1SW_SYSCLK
And set 400kHz timing settings, allow get less noise (good see on 900-1500MHz)
400kHz @ 48MHz I2C clock from refrence manual get best result (sweep speed increased, and less noise on freq 900-1500MHz)
STM32_TIMINGR_PRESC(5U) |
STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) |
STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U),
Also now allow set #define DELAY_CHANNEL_CHANGE 2 and get good measure result
At last, best result give this settings:
I2C HSI = 8MHz
#define STM32_I2C1SW STM32_I2C1SW_HSI
i2ccfg
// I2C clock bus setting: depend from STM32_I2C1SW in mcuconf.h
// STM32_I2C1SW = STM32_I2C1SW_HSI (HSI=8MHz)
// STM32_I2C1SW = STM32_I2C1SW_SYSCLK (SYSCLK = 48MHz)
static const I2CConfig i2ccfg = {
// TIMINGR register initialization. (use I2C timing configuration tool for STM32F3xx and STM32F0xx microcontrollers (AN4235))
// 400kHz @ SYSCLK 48MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual)
// STM32_TIMINGR_PRESC(5U) |
// STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) |
// STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U),
// 400kHz @ HSI 8MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual)
STM32_TIMINGR_PRESC(0U) |
STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(1U) |
STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U),
// Old values voodoo magic 400kHz @ HSI 8MHz
// STM32_TIMINGR_PRESC(0U) |
// STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(0U) |
// STM32_TIMINGR_SCLH(5U) | STM32_TIMINGR_SCLL(6U),
0, // CR1 register initialization.
0 // CR2 register initialization.
};
#define DELAY_GAIN_CHANGE 2
#define DELAY_CHANNEL_CHANGE 2
si5351.c
#define DELAY_NORMAL 2
#define DELAY_BANDCHANGE 0
#define DELAY_LOWBAND 2
Try check it
Additional
// div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul);
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 6, CLK2_FREQUENCY,
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
Every freq for band 1 and 2 update send Chanel 0 settings (SI5351_PLL_A), Chanel 1 settings (SI5351_PLL_B and freq Multisynth), and here broke CH2 clock freq (processor, audio codec clock) Chanel 2 settings (SI5351_PLL_B), restore correct Multisynth and CH2 clock freq
As minimum need need send CH2 settings before, as maximum at some time apply all or not use it
Possibly this hack used for fix it on band 1?
// Set PLL twice on changing from band 2
if (current_band == 2) {
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul);
}
I2C bus speed not define freq stability, it just define data transfer speed to si5351
Found some problems in si5351.c it contain a lot of hack, need undestand how better solve it At test i get up to 2x speed. Need just minimise I2C data transfer and do correct control
HI DiSlord,
Possibly this hack used for fix it on band 1?
// Set PLL twice on changing from band 2 if (current_band == 2) { si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul); si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul); }
As far I know, that has been thought to avoids PLL unlocks at frequencies around 300MHz.
About the MCLK "arrhythmia": I'm working to an HW mod to improve the odd harmonics behavior when the DUT is an high order low-pass filter that lets pass frequencies in the fundamental carrier range stopping the frequencies in its harmonics range and I discovered that the "arrhythmia" is due to the function si5351_disable_output() used into function si5351_set_frequency_with_offset(...). In fact, function si5351_disable_output() suspends CLK2 output every times the band changes and re-enables it only until si5351_enable_output() is called at the end of si5351_set_frequency_with_offset(...).
In my HW mod (which I ended yesterday and I'll publish soon), I added an external 8MHz oscillator for the MCLK and used CLK2 to get an harmonics only reference signal that fixes the odd harmonics issue. The mod, in few words, uses CLK1 output to source the DUT below 300MHz, while it uses CLK2 output to source the DUT above 300MHz passing the reference signal through a 5th order high-pass elliptic filter (in this case the Si5351A is used as an RF switch, both its outputs generate the very same frequency, but one at time).
Have a great day.
Massimo IK1IZA
Found why need this hack
// Set PLL twice on changing from band 2
if (current_band == 2) {
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul);
}
si5153 have some delay on change MultiSynth Integer and non Integer Mode. Need send MultiSynth and CLK Control twice on change from fractional divider mode
PS Not need enable/disable output on band change. I get good result:
#define DELAY_NORMAL 2
#define DELAY_BANDCHANGE 1
//#define DELAY_LOWBAND 0
/*
* configure output as follows:
* CLK0: frequency + offset
* CLK1: frequency
* CLK2: fixed 8MHz
*/
int
si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength)
{
uint8_t band;
int delay = DELAY_NORMAL;
if (freq == lastfreq)
return delay;
uint32_t ofreq = freq + offset;
uint32_t mul = 1, omul = 1;
uint32_t rdiv = SI5351_R_DIV_1;
lastfreq = freq;
if (freq >= FREQ_HARMONICS * 7U) {
mul = 9;
omul = 11;
} else if (freq >= FREQ_HARMONICS * 5U) {
mul = 7;
omul = 9;
} else if (freq >= FREQ_HARMONICS * 3U) {
mul = 5;
omul = 7;
} else if (freq >= FREQ_HARMONICS) {
mul = 3;
omul = 5;
}
else if (freq <= 500000U) {
rdiv = SI5351_R_DIV_64;
freq *= 64;
ofreq *= 64;
} else if (freq <= 4000000U) {
rdiv = SI5351_R_DIV_8;
freq *= 8;
ofreq *= 8;
}
if ((freq / mul) < 100000000U) {
band = 1;
} else if ((freq / mul) < 150000000U) {
band = 2;
} else {
band = 3;
}
switch (band) {
case 1:
// fractional divider mode.
if (current_band != 1){
si5351_setupPLL(SI5351_REG_PLL_A, PLL_N, 0, 1);
// si5351_setupPLL(SI5351_REG_PLL_B, PLL_N, 0, 1);
si5351_set_frequency_fixedpll(2, SI5351_REG_PLL_A, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA);
}
si5351_set_frequency_fixedpll(0, SI5351_REG_PLL_A, XTALFREQ * PLL_N * omul, ofreq, rdiv, drive_strength);
si5351_set_frequency_fixedpll(1, SI5351_REG_PLL_A, XTALFREQ * PLL_N * mul, freq, rdiv, drive_strength);
// delay += DELAY_LOWBAND;
break;
case 2:
// div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1
si5351_set_frequency_fixeddiv(0, SI5351_REG_PLL_A, ofreq, 6, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_REG_PLL_B, freq, 6, drive_strength, mul);
si5351_set_frequency_fixedpll(2, SI5351_REG_PLL_B, freq / mul * 6, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA);
// Send MultiSynth and CLK Control twice on change from fractional divider mode
if (current_band == 1){
si5351_set_frequency_fixeddiv(0, SI5351_REG_PLL_A, ofreq, 6, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_REG_PLL_B, freq, 6, drive_strength, mul);
}
break;
case 3:
// div by 4 mode. both PLL A and B are dedicated for CLK0, CLK1
si5351_set_frequency_fixeddiv(0, SI5351_REG_PLL_A, ofreq, 4, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_REG_PLL_B, freq, 4, drive_strength, mul);
si5351_set_frequency_fixedpll(2, SI5351_REG_PLL_B, freq / mul * 4, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA);
// Send MultiSynth and CLK Control twice on change from fractional divider mode
if (current_band == 1){
si5351_set_frequency_fixeddiv(0, SI5351_REG_PLL_A, ofreq, 4, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_REG_PLL_B, freq, 4, drive_strength, mul);
}
break;
}
if (current_band != band) {
si5351_reset_pll();
current_band = band;
delay += DELAY_BANDCHANGE;
}
return delay;
}
I also fix some integer overflow on calculation
Seems i solve all hack for si5351, soon i add Pull request
Sweep freq speedup from 8400 sys tick to 5300 (about 40% speedup) Need just test stability
Commit fixes to https://github.com/DiSlord/NanoVNA
Create pull request
Tru undestand how config I2C bus
Refer manual for I2C_TIMINGR register not get this value for 400kHz @ HSI 8MHz
If get example values from manual for 500kHz @ HSI 8MHz and change STM32_TIMINGR_SCLL from 6 to 5-3, possible get 7% sweep speed
Try test it