aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/pio_programs/clock_divider.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-rp/src/pio_programs/clock_divider.rs')
-rw-r--r--embassy-rp/src/pio_programs/clock_divider.rs30
1 files changed, 29 insertions, 1 deletions
diff --git a/embassy-rp/src/pio_programs/clock_divider.rs b/embassy-rp/src/pio_programs/clock_divider.rs
index 02e353f53..687fd53ba 100644
--- a/embassy-rp/src/pio_programs/clock_divider.rs
+++ b/embassy-rp/src/pio_programs/clock_divider.rs
@@ -16,10 +16,38 @@ use crate::clocks::clk_sys_freq;
16/// A fixed-point divider value suitable for use in a PIO state machine configuration 16/// A fixed-point divider value suitable for use in a PIO state machine configuration
17#[inline] 17#[inline]
18pub fn calculate_pio_clock_divider(target_hz: u32) -> fixed::FixedU32<U8> { 18pub fn calculate_pio_clock_divider(target_hz: u32) -> fixed::FixedU32<U8> {
19 calculate_pio_clock_divider_inner(clk_sys_freq(), target_hz)
20}
21
22#[inline]
23fn calculate_pio_clock_divider_inner(sys_freq: u32, target_hz: u32) -> fixed::FixedU32<U8> {
19 // Requires a non-zero frequency 24 // Requires a non-zero frequency
20 assert!(target_hz > 0, "PIO clock frequency cannot be zero"); 25 assert!(target_hz > 0, "PIO clock frequency cannot be zero");
21 26
22 // Calculate the divider 27 // Calculate the divider
23 let divider = (clk_sys_freq() + target_hz / 2) / target_hz; 28 let divider = (sys_freq + target_hz / 2) / target_hz;
24 divider.to_fixed() 29 divider.to_fixed()
25} 30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35
36 #[test]
37 fn clock_divider_math() {
38 // A simple divider that must have a fractional part.
39 let divider = calculate_pio_clock_divider_inner(125_000_000, 40_000_000);
40 let expected: fixed::FixedU32<U8> = 3.125.to_fixed();
41 assert_eq!(divider, expected);
42
43 // A system clk so high it would overflow a u32 if shifted left.
44 let divider = calculate_pio_clock_divider_inner(2_000_000_000, 40_000);
45 let expected: fixed::FixedU32<U8> = 50000.to_fixed();
46 assert_eq!(divider, expected);
47
48 // A divider that requires all 8 fractional bits.
49 let divider = calculate_pio_clock_divider_inner(134_283_264, 16_777_216);
50 let expected: fixed::FixedU32<U8> = 8.00390625.to_fixed();
51 assert_eq!(divider, expected);
52 }
53}