Skip to content

Commit d3aa0e1

Browse files
authored
fix: Maintain accuracy in DPLL frequency math
Explained in issue #907 #907
1 parent b18cc12 commit d3aa0e1

File tree

1 file changed

+15
-4
lines changed
  • hal/src/peripherals/clock/d5x/v2

1 file changed

+15
-4
lines changed

hal/src/peripherals/clock/d5x/v2/dpll.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ use fugit::RateExtU32;
243243
use typenum::U0;
244244

245245
use crate::pac::oscctrl;
246-
use crate::pac::oscctrl::dpll::{dpllstatus, dpllsyncbusy, Dpllctrla, Dpllctrlb, Dpllratio};
246+
use crate::pac::oscctrl::dpll::{Dpllctrla, Dpllctrlb, Dpllratio, dpllstatus, dpllsyncbusy};
247247

248248
use crate::pac::oscctrl::dpll::dpllctrlb::Refclkselect;
249249

@@ -347,7 +347,9 @@ impl<D: DpllId> DpllToken<D> {
347347
w.wuf().bit(settings.wake_up_fast);
348348
if let Some(cap) = settings.dco_filter {
349349
w.dcoen().bit(true);
350-
unsafe { w.dcofilter().bits(cap as u8); }
350+
unsafe {
351+
w.dcofilter().bits(cap as u8);
352+
}
351353
} else {
352354
w.dcoen().bit(false);
353355
}
@@ -606,7 +608,6 @@ pub enum DcoFilter {
606608
C4pF = 7,
607609
}
608610

609-
610611
/// [`Dpll`] settings relevant to all reference clocks
611612
#[derive(Copy, Clone)]
612613
struct Settings {
@@ -989,7 +990,17 @@ where
989990

990991
#[inline]
991992
fn output_freq(&self) -> Hertz {
992-
self.input_freq() * (self.settings.mult as u32 + self.settings.frac as u32 / 32)
993+
// The actual formula is:
994+
// y = x * (mult + frac / 32)
995+
// To avoid integer precision loss, the formula is restructured:
996+
// y = x * (mult + frac / 32) * 32 / 32
997+
// y = x * (32 * mult + 32 * frac / 32) / 32
998+
// y = x * (32 * mult + frac) / 32
999+
let input = self.input_freq().to_Hz() as u64;
1000+
let multiplier_times_32 =
1001+
(32 * self.settings.mult as u32 + self.settings.frac as u32) as u64;
1002+
let output = (input * multiplier_times_32 / 32) as u32;
1003+
output.Hz()
9931004
}
9941005

9951006
/// Return the output frequency of the [`Dpll`]

0 commit comments

Comments
 (0)