@ -1,5 +1,6 @@
/*
* Copyright ( c ) 2014 - 2015 , TAKAHASHI Tomohiro ( TTRFTECH ) edy555 @ gmail . com
* Modified by DiSlord dislordlive @ gmail . com
* All rights reserved .
*
* This is free software ; you can redistribute it and / or modify
@ -21,15 +22,19 @@
# include "nanovna.h"
# include "si5351.h"
# define XTALFREQ 26000000L
// MCLK (processor clock, audio codec) frequency clock
# define CLK2_FREQUENCY 8000000L
// Enable cache for SI5351 CLKX_CONTROL register, little speedup exchange
# define USE_CLK_CONTROL_CACHE TRUE
// Fixed PLL mode multiplier
// XTAL frequency on si5351
# define XTALFREQ 26000000U
// MCLK (processor clock if set, audio codec) frequency clock
# define CLK2_FREQUENCY 8000000U
// Fixed PLL mode multiplier (used in band 1)
# define PLL_N 32
//
# define SI5351_I2C_ADDR (0x60<<1)
// I2C address on bus (only 0x60 for Si5351A in 10-Pin MSOP)
# define SI5351_I2C_ADDR 0x60
static uint8_t current_band = 0 ;
static uint32_t current_freq = 0 ;
@ -37,9 +42,8 @@ static uint32_t current_freq = 0;
static void
si5351_bulk_write ( const uint8_t * buf , int len )
{
int addr = SI5351_I2C_ADDR > > 1 ;
i2cAcquireBus ( & I2CD1 ) ;
( void ) i2cMasterTransmitTimeout ( & I2CD1 , addr , buf , len , NULL , 0 , 1000 ) ;
( void ) i2cMasterTransmitTimeout ( & I2CD1 , SI5351_I2C_ADDR , buf , len , NULL , 0 , 1000 ) ;
i2cReleaseBus ( & I2CD1 ) ;
}
#if 0
@ -64,15 +68,18 @@ const uint8_t si5351_configs[] = {
2 , SI5351_REG_3_OUTPUT_ENABLE_CONTROL , 0xff ,
4 , SI5351_REG_16_CLK0_CONTROL , SI5351_CLK_POWERDOWN , SI5351_CLK_POWERDOWN , SI5351_CLK_POWERDOWN ,
2 , SI5351_REG_183_CRYSTAL_LOAD , SI5351_CRYSTAL_LOAD_8PF ,
// All of this init code run late on sweep
#if 0
// setup PLL (26MHz * 32 = 832MHz, 32/2-2=14)
// 9, SI5351_REG_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
// 9, SI5351_REG_PLL_B, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
9 , SI5351_REG_PLL_A , /*P3*/ 0 , 1 , /*P1*/ 0 , 14 , 0 , /*P3/P2*/ 0 , 0 , 0 ,
9 , SI5351_REG_PLL_B , /*P3*/ 0 , 1 , /*P1*/ 0 , 14 , 0 , /*P3/P2*/ 0 , 0 , 0 ,
// RESET PLL
2 , SI5351_REG_177_PLL_RESET , SI5351_PLL_RESET_A | SI5351_PLL_RESET_B | 0x0C , //
// setup multisynth (832MHz / 104 = 8MHz, 104/2-2=50)
// 9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 1, /*P1*/0, 50, 0, /*P2|P3*/0, 0, 0,
// 2, SI5351_REG_18_CLK2_CONTROL, SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE,
// 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0,
9 , SI5351_REG_58_MULTISYNTH2 , /*P3*/ 0 , 1 , /*P1*/ 0 , 50 , 0 , /*P2|P3*/ 0 , 0 , 0 ,
2 , SI5351_REG_18_CLK2_CONTROL , SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE ,
2 , SI5351_REG_3_OUTPUT_ENABLE_CONTROL , 0 ,
# endif
0 // sentinel
} ;
@ -106,217 +113,185 @@ static const uint8_t clkctrl[] = {
SI5351_REG_18_CLK2_CONTROL
} ;
// Reset PLL need then band changes
static void si5351_reset_pll ( uint8_t mask )
{
// Writing a 1<<5 will reset PLLA, 1<<7 reset PLLB, this is a self clearing bits.
// !!! Need delay before reset PLL for apply PLL freq changes before
chThdSleepMicroseconds ( 200 ) ;
si5351_write ( SI5351_REG_177_PLL_RESET , mask | 0x0C ) ;
// chThdSleepMicroseconds(250);
}
void si5351_disable_output ( void )
{
// si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, (SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN));
si5351_write ( SI5351_REG_3_OUTPUT_ENABLE_CONTROL , 0xff ) ;
si5351_write ( SI5351_REG_3_OUTPUT_ENABLE_CONTROL , 0xFF ) ;
si5351_bulk_write ( disable_output , sizeof ( disable_output ) ) ;
}
void si5351_enable_output ( void )
{
si5351_reset_pll ( SI5351_PLL_RESET_A | SI5351_PLL_RESET_B ) ;
// si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN));
si5351_write ( SI5351_REG_3_OUTPUT_ENABLE_CONTROL , 0x00 ) ;
si5351_write ( SI5351_REG_3_OUTPUT_ENABLE_CONTROL , ~ ( SI5351_CLK0_EN | SI5351_CLK1_EN | SI5351_CLK2_EN ) ) ;
//si5351_reset_pll(SI5351_PLL_RESET_A | SI5351_PLL_RESET_B);
current_freq = 0 ;
current_band = 0 ;
}
static void si5351_setupPLL ( uint8_t pll , /* SI5351_PLL_A or SI5351_PLL_B */
uint8_t mult ,
// Set PLL freq = XTALFREQ * (mult + num/denom)
static void si5351_setupPLL ( uint8_t pllSource , /* SI5351_REG_PLL_A or SI5351_REG_PLL_B */
uint32_t mult ,
uint32_t num ,
uint32_t denom )
{
uint32_t P1 ;
uint32_t P2 ;
uint32_t P3 ;
/* Feedback Multisynth Divider Equation
* where : a = mult , b = num and c = denom
* P1 register is an 18 - bit value using following formula :
* P1 [ 17 : 0 ] = 128 * mult + floor ( 128 * ( num / denom ) ) - 512
* P1 [ 17 : 0 ] = 128 * mult + int ( ( 128 * num ) / denom ) - 512
* P2 register is a 20 - bit value using the following formula :
* P2 [ 19 : 0 ] = 128 * num - denom * floor ( 128 * ( num / denom ) )
* P2 [ 19 : 0 ] = ( 128 * num ) % denom
* P3 register is a 20 - bit value using the following formula :
* P3 [ 19 : 0 ] = denom
*/
/* Set the main PLL config registers */
if ( num = = 0 )
{
/* Integer mode */
P1 = 128 * mult - 512 ;
P2 = 0 ;
P3 = 1 ;
}
else
{
/* Fractional mode */
//P1 = (uint32_t)(128 * mult + floor(128 * ((float)num/(float)denom)) - 512);
P1 = 128 * mult + ( ( 128 * num ) / denom ) - 512 ;
//P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num/(float)denom)));
P2 = 128 * num - denom * ( ( 128 * num ) / denom ) ;
mult < < = 7 ;
num < < = 7 ;
uint32_t P1 = mult - 512 ; // Integer mode
uint32_t P2 = 0 ;
uint32_t P3 = 1 ;
if ( num ) { // Fractional mode
P1 + = num / denom ;
P2 = num % denom ;
P3 = denom ;
}
// Pll MSN(A|B) registers Datasheet
// MSN_P3[15:8]
// MSN_P3[ 7:0]
// Reserved | MSN_P1[17:16]
// MSN_P1[15:8]
// MSN_P1[ 7:0]
// MSN_P3[19:16] | MSN_P2[19:16]
// MSN_P2[15:8]
// MSN_P2[ 7:0]
// Pll MSN(A|B) registers Datasheet
uint8_t reg [ 9 ] ;
reg [ 0 ] = pll ; //reg_base[pll];
reg [ 1 ] = ( P3 & 0x0 000 FF00) > > 8 ;
reg [ 2 ] = ( P3 & 0x 0 00000 FF) ;
reg [ 3 ] = ( P1 & 0x 000 30000) > > 16 ;
reg [ 4 ] = ( P1 & 0x0 000 FF00) > > 8 ;
reg [ 5 ] = ( P1 & 0x 0 00000 FF) ;
reg [ 6 ] = ( ( P3 & 0x 000 F0000) > > 12 ) | ( ( P2 & 0x 000 F0000) > > 16 ) ;
reg [ 7 ] = ( P2 & 0x0 000 FF00) > > 8 ;
reg [ 8 ] = ( P2 & 0x 0 00000 FF) ;
reg [ 0 ] = pllSource ; // SI5351_REG_PLL_A or SI5351_REG_PLL_B
reg [ 1 ] = ( P3 & 0x0FF00 ) > > 8 ; // MSN_P3[15: 8]
reg [ 2 ] = ( P3 & 0x000FF ) ; // MSN_P3[ 7: 0]
reg [ 3 ] = ( P1 & 0x30000 ) > > 16 ; // MSN_P1[17:16]
reg [ 4 ] = ( P1 & 0x0FF00 ) > > 8 ; // MSN_P1[15: 8]
reg [ 5 ] = ( P1 & 0x000FF ) ; // MSN_P1[ 7: 0]
reg [ 6 ] = ( ( P3 & 0xF0000 ) > > 12 ) | ( ( P2 & 0xF0000 ) > > 16 ) ; // MSN_P3[19:16] | MSN_P2[19:16]
reg [ 7 ] = ( P2 & 0x0 FF00) > > 8 ; // MSN_P2[15: 8]
reg [ 8 ] = ( P2 & 0x 000FF) ; // MSN_P2[ 7: 0]
si5351_bulk_write ( reg , 9 ) ;
}
// Set Multisynth divider = (div + num/denom) * rdiv
static void
si5351_setupMultisynth ( uint8_t channel ,
uint8_t pllSource ,
uint32_t div , // 4,6,8, 8+ ~ 900
uint32_t num ,
uint32_t denom ,
uint32_t rdiv , // SI5351_R_DIV_1~128
uint8_t drive_strength )
uint8_t chctrl ) // SI5351_REG_16_CLKX_CONTROL settings
{
uint8_t dat ;
uint32_t P1 ;
uint32_t P2 ;
uint32_t P3 ;
uint32_t div4 = 0 ;
/* Output Multisynth Divider Equations
* where : a = div , b = num and c = denom
* P1 register is an 18 - bit value using following formula :
* P1 [ 17 : 0 ] = 128 * a + floor ( 128 * ( b / c ) ) - 512
* P1 [ 17 : 0 ] = 128 * a + int ( ( 128 * b ) / c ) - 512
* P2 register is a 20 - bit value using the following formula :
* P2 [ 19 : 0 ] = 128 * b - c * floor ( 128 * ( b / c ) )
* P2 [ 19 : 0 ] = ( 128 * b ) % c
* P3 register is a 20 - bit value using the following formula :
* P3 [ 19 : 0 ] = c
*/
/* Set the main PLL config registers */
if ( div = = 4 ) {
div4 = SI5351_DIVBY4 ;
P1 = P2 = 0 ;
P3 = 1 ;
} else if ( num = = 0 ) {
/* Integer mode */
P1 = 128 * div - 512 ;
P2 = 0 ;
P3 = 1 ;
} else {
/* Fractional mode */
P1 = 128 * div + ( ( 128 * num ) / denom ) - 512 ;
P2 = 128 * num - denom * ( ( 128 * num ) / denom ) ;
uint32_t P1 = 0 ;
uint32_t P2 = 0 ;
uint32_t P3 = 1 ;
if ( div = = 4 )
rdiv | = SI5351_DIVBY4 ;
else {
num < < = 7 ;
div < < = 7 ;
P1 = div - 512 ; // Integer mode
if ( num ) { // Fractional mode
P1 + = num / denom ;
P2 = num % denom ;
P3 = denom ;
}
}
/* Set the MSx config registers */
uint8_t reg [ 9 ] ;
reg [ 0 ] = msreg_base [ channel ] ;
reg [ 1 ] = ( P3 & 0x0 000 FF00) > > 8 ;
reg [ 2 ] = ( P3 & 0x 0 00000 FF) ;
reg [ 3 ] = ( ( P1 & 0x 000 30000) > > 16 ) | div4 | rdiv ;
reg [ 4 ] = ( P1 & 0x0 000 FF00) > > 8 ;
reg [ 5 ] = ( P1 & 0x 0 00000 FF) ;
reg [ 6 ] = ( ( P3 & 0x 000 F0000) > > 12 ) | ( ( P2 & 0x 000 F0000) > > 16 ) ;
reg [ 7 ] = ( P2 & 0x0 000 FF00) > > 8 ;
reg [ 8 ] = ( P2 & 0x 0 00000 FF) ;
reg [ 0 ] = msreg_base [ channel ] ; // SI5351_REG_42_MULTISYNTH0, SI5351_REG_50_MULTISYNTH1, SI5351_REG_58_MULTISYNTH2
reg [ 1 ] = ( P3 & 0x0 FF00) > > 8 ; // MSx_P3[15: 8]
reg [ 2 ] = ( P3 & 0x 000FF) ; // MSx_P3[ 7: 0]
reg [ 3 ] = ( ( P1 & 0x 30000) > > 16 ) | rdiv ; // Rx_DIV[2:0] | MSx_DIVBY4[1:0] | MSx_P1[17:16]
reg [ 4 ] = ( P1 & 0x0 FF00) > > 8 ; // MSx_P1[15: 8]
reg [ 5 ] = ( P1 & 0x 000FF) ; // MSx_P1[ 7: 0]
reg [ 6 ] = ( ( P3 & 0x F0000) > > 12 ) | ( ( P2 & 0x F0000) > > 16 ) ; // MSx_P3[19:16] | MSx_P2[19:16]
reg [ 7 ] = ( P2 & 0x0 FF00) > > 8 ; // MSx_P2[15: 8]
reg [ 8 ] = ( P2 & 0x 000FF) ; // MSx_P2[ 7: 0]
si5351_bulk_write ( reg , 9 ) ;
/* Configure the clk control and enable the output */
dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N ;
if ( pllSource = = SI5351_REG_PLL_B )
dat | = SI5351_CLK_PLL_SELECT_B ;
uint8_t dat = chctrl | SI5351_CLK_INPUT_MULTISYNTH_N ;
if ( num = = 0 )
dat | = SI5351_CLK_INTEGER_MODE ;
# if USE_CLK_CONTROL_CACHE == TRUE
// Use cache for this reg, not update if not change
static uint8_t clk_cache [ 3 ] ;
if ( clk_cache [ channel ] ! = dat ) {
si5351_write ( clkctrl [ channel ] , dat ) ;
clk_cache [ channel ] = dat ;
}
# else
si5351_write ( clkctrl [ channel ] , dat ) ;
# endif
}
static void
si5351_set_frequency_fixedpll ( uint8_t channel , uint32_t pllSource , uint64_t pllfreq , uint32_t freq , uint32_t rdiv , uint8_t drive_strength )
{
uint32_t denom = freq ;
uint32_t div = pllfreq / denom ; // range: 8 ~ 1800
uint32_t num = pllfreq % denom ;
// Find better approximate values for n/d
# define MAX_DENOMINATOR ((1 << 20) - 1)
static inline void fractionalSolve ( uint32_t * n , uint32_t * d ) {
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
uint32_t max_denominator = ( 1 < < 20 ) - 1 ;
if ( denom > max_denominator ) {
uint32_t denom = * d ;
if ( denom > MAX_DENOMINATOR ) {
uint32_t num = * n ;
uint32_t p0 = 0 , q0 = 1 , p1 = 1 , q1 = 0 ;
while ( denom ! = 0 ) {
uint32_t a = num / denom ;
uint32_t b = num % denom ;
uint32_t q2 = q0 + a * q1 ;
if ( q2 > max_denominator )
if ( q2 > MAX_DENOMINATOR )
break ;
uint32_t p2 = p0 + a * p1 ;
p0 = p1 ;
q0 = q1 ;
p1 = p2 ;
q1 = q2 ;
p0 = p1 ; q0 = q1 ; p1 = p2 ; q1 = q2 ;
num = denom ; denom = b ;
}
num = p1 ;
denom = q1 ;
* n = p1 ;
* d = q1 ;
}
si5351_setupMultisynth ( channel , pllSource , div , num , denom , rdiv , drive_strength ) ;
}
void si5351_setupPLL_freq ( uint32_t pll , uint32_t freq , uint32_t div , uint32_t mul ) {
// Setup Multisynth divider for get correct output freq if fixed PLL = pllfreq
static void
si5351_set_frequency_fixedpll ( uint8_t channel , uint64_t pllfreq , uint32_t freq , uint32_t rdiv , uint8_t chctrl )
{
uint32_t denom = freq ;
uint32_t div = pllfreq / denom ; // range: 8 ~ 1800
uint32_t num = pllfreq % denom ;
fractionalSolve ( & num , & denom ) ;
si5351_setupMultisynth ( channel , div , num , denom , rdiv , chctrl ) ;
}
// Setup PLL freq if Multisynth divider fixed = div (need get output = freq/mul)
static void
si5351_setupPLL_freq ( uint32_t pllSource , uint32_t freq , uint32_t div , uint32_t mul ) {
uint32_t denom = XTALFREQ * mul ;
uint64_t pllfreq = ( uint64_t ) freq * div ;
uint32_t multi = pllfreq / denom ;
uint32_t num = pllfreq % denom ;
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
uint32_t max_denominator = ( 1 < < 20 ) - 1 ;
if ( denom > max_denominator ) {
uint32_t p0 = 0 , q0 = 1 , p1 = 1 , q1 = 0 ;
while ( denom ! = 0 ) {
uint32_t a = num / denom ;
uint32_t b = num % denom ;
uint32_t q2 = q0 + a * q1 ;
if ( q2 > max_denominator )
break ;
uint32_t p2 = p0 + a * p1 ;
p0 = p1 ; q0 = q1 ; p1 = p2 ; q1 = q2 ;
num = denom ; denom = b ;
}
num = p1 ;
denom = q1 ;
}
si5351_setupPLL ( pll , multi , num , denom ) ;
fractionalSolve ( & num , & denom ) ;
si5351_setupPLL ( pllSource , multi , num , denom ) ;
}
#if 0
static void
si5351_set_frequency_fixeddiv ( uint8_t channel , uint32_t pll , uint32_t freq , uint32_t div ,
uint8_t drive_strength , uint32_t mul )
uint8_t chctrl , uint32_t mul )
{
si5351_setupPLL_freq ( pll , freq , div , mul ) ;
si5351_setupMultisynth ( channel , pll, div, 0 , 1 , SI5351_R_DIV_1 , drive_strength ) ;
si5351_setupMultisynth ( channel , div , 0 , 1 , SI5351_R_DIV_1 , chctrl ) ;
}
void
@ -332,19 +307,48 @@ si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength){
}
# endif
/*
* Frequency generation divide on 3 band
* Band 1
* 1 ~ 100 MHz fixed PLL = XTALFREQ * PLL_N , fractional divider
* Band 2
* 100 ~ 150 MHz fractional PLL = 600 - 900 MHz , fixed divider ' fdiv = 6 '
* Band 3
* 150 ~ 300 MHz fractional PLL = 600 - 1200 MHz , fixed divider ' fdiv = 4 '
*
* For FREQ_HARMONICS = 300 MHz - band range is :
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* | Band 1 | Band 2 | Band 3 | Band 2 | Band 3 |
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* | x1 : x1 | x1 : x1 | x1 : x1 | x3 : x5 | x3 : x5 | x5 - x7 | x7 - x9 | x9 - x11 |
* | 50 kHz - 100 MHz | 100 - 150 MHz | 150 - 300 MHz | 300 - 450 MHz | 450 - 900 MHz | 900 - 1500 MHz | 1500 - 2100 MHz | 2100 - 2700 MHz |
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* | f = 50 kHz - 100 MHz | f = 100 - 150 | f = 150 - 300 | f = 150 - 300 | f = 214 - 300 | f = 233 - 300 |
* | of = 50 kHz - 100 MHz | of = 60 - 90 | of = 90 - 180 | of = 128 - 215 | of = 166 - 234 | of = 190 - 246 |
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
static inline uint8_t si5351_getBand ( uint32_t freq ) {
if ( freq < 100000000U ) return 1 ;
if ( freq < 150000000U ) return 2 ;
return 3 ;
}
// Minimum value is 2, freq change apply at next dsp measure, and need skip it
# define DELAY_NORMAL 2
// Additional delay for band 1 (remove unstable generation at begin)
# define DELAY_BAND_1 1
// Band changes need additional delay after reset PLL
# define DELAY_BANDCHANGE 2
/*
* Maximum supported frequency = FREQ_HARMONICS * 9U
* configure output as follows :
* CLK0 : frequency + offset
* CLK1 : frequency
* CLK2 : fixed 8 MHz
*/
int
si5351_set_frequency_with_offset ( uint32_t freq , int offset , uint8_t drive_strength )
{
si5351_set_frequency_with_offset ( uint32_t freq , int offset , uint8_t drive_strength ) {
uint8_t band ;
int delay = DELAY_NORMAL ;
if ( freq = = current_freq )
@ -369,54 +373,40 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng
}
else if ( freq < = 500000U ) {
rdiv = SI5351_R_DIV_64 ;
freq * = 64 ;
ofreq * = 64 ;
freq < < = 6 ;
ofreq < < = 6 ;
} else if ( freq < = 4000000U ) {
rdiv = SI5351_R_DIV_8 ;
freq * = 8 ;
ofreq * = 8 ;
}
/*
* Band 0
* 1 ~ 100 MHz fixed PLL = XTALFREQ * PLL_N , fractional divider
* Band 1
* 100 ~ 150 MHz fractional PLL = 600 - 900 MHz , fixed divider 6
* Band 2
* 150 ~ 300 MHz fractional PLL = 600 - 1200 MHz , fixed divider 4
*/
if ( ( freq / mul ) < 100000000U ) {
band = 1 ;
} else if ( ( freq / mul ) < 150000000U ) {
band = 2 ;
fdiv = 6 ;
} else {
band = 3 ;
fdiv = 4 ;
freq < < = 3 ;
ofreq < < = 3 ;
}
band = si5351_getBand ( freq / mul ) ;
switch ( band ) {
case 1 :
// Setup CH0 and CH1 constant PLL freq at band change, and set CH2 freq = CLK2_FREQUENCY
// Setup CH0 and CH1 constant PLLA freq at band change, and set CH2 freq = CLK2_FREQUENCY
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_B , XTALFREQ * PLL_N , CLK2_FREQUENCY , SI5351_R_DIV_1 , SI5351_CLK_DRIVE_STRENGTH_2MA ) ;
si5351_set_frequency_fixedpll ( 2 , XTALFREQ * PLL_N , CLK2_FREQUENCY , SI5351_R_DIV_1 , SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_PLL_SELECT_A ) ;
}
// Calculate and set CH0 and CH1 divider
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 ) ;
si5351_set_frequency_fixedpll ( 0 , ( uint64_t ) omul * XTALFREQ * PLL_N , ofreq , rdiv , drive_strength | SI5351_CLK_PLL_SELECT_A ) ;
si5351_set_frequency_fixedpll ( 1 , ( uint64_t ) mul * XTALFREQ * PLL_N , freq , rdiv , drive_strength | SI5351_CLK_PLL_SELECT_A ) ;
delay + = DELAY_BAND_1 ;
break ;
case 2 :
case 3 :
case 2 : // fdiv = 6
case 3 : // fdiv = 4;
fdiv = ( band = = 2 ) ? 6 : 4 ;
// Setup CH0 and CH1 constant fdiv divider at change
if ( current_band ! = band ) {
si5351_setupMultisynth ( 0 , SI5351_REG_PLL_A, fdiv, 0 , 1 , SI5351_R_DIV_1 , drive_strength ) ;
si5351_setupMultisynth ( 1 , SI5351_REG_PLL_B, fdiv, 0 , 1 , SI5351_R_DIV_1 , drive_strength ) ;
si5351_setupMultisynth ( 0 , fdiv, 0 , 1 , SI5351_R_DIV_1 , drive_strength | SI5351_CLK_PLL_SELECT_A ) ;
si5351_setupMultisynth ( 1 , fdiv, 0 , 1 , SI5351_R_DIV_1 , drive_strength | SI5351_CLK_PLL_SELECT_B ) ;
}
// Calculate and set CH0 and CH1 PLL freq
si5351_setupPLL_freq ( SI5351_REG_PLL_A , ofreq , fdiv , omul ) ; // set PLLA freq = (ofreq/omul)*fdiv
si5351_setupPLL_freq ( SI5351_REG_PLL_B , freq , fdiv , mul ) ; // set PLLB freq = ( freq/ mul)*fdiv
// Calculate CH2 freq = CLK2_FREQUENCY, depend from calculated before CH1 PLLB = (freq/mul)*fdiv
si5351_set_frequency_fixedpll ( 2 , SI5351_REG_PLL_B , ( freq / mul ) * fdiv , CLK2_FREQUENCY , SI5351_R_DIV_1 , SI5351_CLK_DRIVE_STRENGTH_2MA ) ;
si5351_set_frequency_fixedpll ( 2 , ( uint64_t ) freq * fdiv , CLK2_FREQUENCY * mul , SI5351_R_DIV_1 , SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_PLL_SELECT_B ) ;
break ;
}