@@ -243,7 +243,7 @@ use fugit::RateExtU32;
243
243
use typenum:: U0 ;
244
244
245
245
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 } ;
247
247
248
248
use crate :: pac:: oscctrl:: dpll:: dpllctrlb:: Refclkselect ;
249
249
@@ -347,7 +347,9 @@ impl<D: DpllId> DpllToken<D> {
347
347
w. wuf ( ) . bit ( settings. wake_up_fast ) ;
348
348
if let Some ( cap) = settings. dco_filter {
349
349
w. dcoen ( ) . bit ( true ) ;
350
- unsafe { w. dcofilter ( ) . bits ( cap as u8 ) ; }
350
+ unsafe {
351
+ w. dcofilter ( ) . bits ( cap as u8 ) ;
352
+ }
351
353
} else {
352
354
w. dcoen ( ) . bit ( false ) ;
353
355
}
@@ -606,7 +608,6 @@ pub enum DcoFilter {
606
608
C4pF = 7 ,
607
609
}
608
610
609
-
610
611
/// [`Dpll`] settings relevant to all reference clocks
611
612
#[ derive( Copy , Clone ) ]
612
613
struct Settings {
@@ -989,7 +990,17 @@ where
989
990
990
991
#[ inline]
991
992
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 ( )
993
1004
}
994
1005
995
1006
/// Return the output frequency of the [`Dpll`]
0 commit comments