use anyhow::Result;
use crate::{pin::PinType, pwm::PWM, utils::map_range};
const FREQ: u32 = 50;
const PERIOD: u32 = 4095;
const MIN_PW: u16 = 500;
const MAX_PW: u16 = 2500;
const CPU_CLOCK: u32 = 72_000_000;
pub struct Servo {
pwm: PWM,
}
impl Servo {
pub fn new(pwm_pin: PinType) -> Result<Self> {
let mut pwm = PWM::new(pwm_pin)?;
pwm.period(PERIOD as u16)?;
let prescaler = ((CPU_CLOCK / FREQ) / PERIOD) as u16;
pwm.prescaler(prescaler)?;
Ok(Self { pwm })
}
pub fn pulse_width_time(&mut self, pw_time: i32) -> Result<()> {
let value = ((pw_time * 4095) / 20000) as u16; self.pwm.pulse_width(value)?;
Ok(())
}
pub fn angle(&mut self, angle: f32) {
let angle = angle.clamp(-90.0, 90.0);
let pw_time = map_range(angle, (-90.0, 90.0), (MIN_PW.into(), MAX_PW.into()));
let pw_time = pw_time.clamp(MIN_PW.into(), MAX_PW.into()) as i32;
let _ = self.pulse_width_time(pw_time);
}
}