use fixed::types::extra::U8;
use crate::clocks::clk_sys_freq;
pub fn calculate_pio_clock_divider(target_hz: u32) -> fixed::FixedU32<U8> {
calculate_pio_clock_divider_value(clk_sys_freq(), target_hz)
}
pub const fn calculate_pio_clock_divider_value(sys_hz: u32, target_hz: u32) -> fixed::FixedU32<U8> {
core::assert!(target_hz > 0);
let integer = sys_hz / target_hz;
let remainder = sys_hz % target_hz;
let frac = (remainder << 8) / target_hz;
let result = integer << 8 | frac;
core::assert!(result <= 0xffff_ff);
core::assert!(result >= 0x0001_00);
fixed::FixedU32::from_bits(result)
}
#[cfg(test)]
mod tests {
use fixed::traits::ToFixed;
use super::*;
#[test]
fn clock_divider_math() {
let divider = calculate_pio_clock_divider_value(125_000_000, 40_000_000);
let expected: fixed::FixedU32<U8> = 3.125.to_fixed();
assert_eq!(divider, expected);
let divider = calculate_pio_clock_divider_value(2_000_000_000, 40_000);
let expected: fixed::FixedU32<U8> = 50000.to_fixed();
assert_eq!(divider, expected);
let divider = calculate_pio_clock_divider_value(134_283_264, 16_777_216);
let expected: fixed::FixedU32<U8> = 8.00390625.to_fixed();
assert_eq!(divider, expected);
}
}