Fixed PLL calculations
This commit is contained in:
parent
d19c799151
commit
558bc0d496
|
@ -100,14 +100,9 @@ where
|
|||
}
|
||||
|
||||
pub fn set_pll_freq(&mut self, i2c: &mut I2C, pll: PLL, freq: u32) {
|
||||
let fdiv = freq / self.freq_xtal;
|
||||
let rm = freq % self.freq_xtal;
|
||||
// Divider is a + (b/c)
|
||||
|
||||
let gcd = num::integer::gcd(rm, self.freq_xtal);
|
||||
|
||||
let c = if gcd < 0x0FFFFF { gcd } else { 0x0FFFFF };
|
||||
let a = fdiv;
|
||||
let b = ((rm as u64) * (c as u64) / (self.freq_xtal as u64)) as u32;
|
||||
let (a, b, c) = as_fraction(freq, self.freq_xtal);
|
||||
|
||||
let params = PllParams {
|
||||
p1: 128 * a + (128 * b / c) - 512,
|
||||
|
@ -143,14 +138,9 @@ where
|
|||
|
||||
pub fn set_ms_freq(&mut self, i2c: &mut I2C, synth: Multisynth, freq: u32) {
|
||||
let pll = self.ms_srcs[synth as usize];
|
||||
let fdiv = self.pll_freqs[pll as usize] / freq;
|
||||
let rm = self.pll_freqs[pll as usize] % freq;
|
||||
let pll_freq = self.pll_freqs[pll as usize];
|
||||
|
||||
let gcd = num::integer::gcd(rm, freq);
|
||||
|
||||
let c: u32 = if gcd < 0x0FFFFF { gcd } else { 0x0FFFFF };
|
||||
let a: u32 = fdiv;
|
||||
let b: u32 = ((rm as u64) * (c as u64) / (freq as u64)) as u32;
|
||||
let (a, b, c) = as_fraction(pll_freq, freq);
|
||||
|
||||
let params = PllParams {
|
||||
p1: 128 * a + (128 * b / c) - 512,
|
||||
|
@ -207,3 +197,27 @@ where
|
|||
self.write_params(i2c, synth.base_address(), params);
|
||||
}
|
||||
}
|
||||
|
||||
// Turns a fraction x/y into a + b/c with minimal c.
|
||||
// If c is larger than 0x0FFFFF, c will be limited to that value and
|
||||
// a best effort approximation for b will be computed
|
||||
fn as_fraction(x: u32, y: u32) -> (u32, u32, u32) {
|
||||
let gcd = num::integer::gcd(x, y);
|
||||
|
||||
let num = x / gcd;
|
||||
let denom = y / gcd;
|
||||
|
||||
let a = num / denom;
|
||||
|
||||
if denom < 0x0FFFFF {
|
||||
let rm = num % denom;
|
||||
let c = denom;
|
||||
let b = rm;
|
||||
(a, b, c)
|
||||
} else {
|
||||
let rm = x % y;
|
||||
let c = 0x0FFFFF;
|
||||
let b = ((rm as u64) * (c as u64) / (y as u64)) as u32;
|
||||
(a, b, c)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue