use crate::{peripherals::ctimer::Ctimer, time::Microseconds, traits::wg, typestates::init_state};
pub struct Pwm<TIMER>
where
TIMER: Ctimer<init_state::Enabled>,
{
timer: TIMER,
}
impl<TIMER> Pwm<TIMER>
where
TIMER: Ctimer<init_state::Enabled>,
{
pub fn new(timer: TIMER) -> Self {
timer
.mcr
.modify(|_, w| w.mr3i().set_bit().mr3r().set_bit().mr3s().clear_bit());
timer.pwmc.modify(|_, w| w.pwmen3().clear_bit());
timer.mr[3].write(|w| unsafe { w.bits(0xff) });
timer.mr[0].write(|w| unsafe { w.bits(0x0) });
timer.mr[1].write(|w| unsafe { w.bits(0x0) });
timer.mr[2].write(|w| unsafe { w.bits(0x0) });
timer.mcr.modify(|_, w| {
w.mr0i()
.set_bit()
.mr0r()
.clear_bit()
.mr0s()
.clear_bit()
.mr1i()
.set_bit()
.mr1r()
.clear_bit()
.mr1s()
.clear_bit()
.mr2i()
.set_bit()
.mr2r()
.clear_bit()
.mr2s()
.clear_bit()
});
timer
.pwmc
.modify(|_, w| w.pwmen0().set_bit().pwmen1().set_bit().pwmen2().set_bit());
timer.pr.write(|w| unsafe { w.bits(0) });
timer.tcr.write(|w| w.crst().clear_bit().cen().set_bit());
Self { timer }
}
pub fn release(self) -> TIMER {
self.timer
}
pub fn scale_max_duty_by(&mut self, duty: u32) {
self.timer.mr[3].write(|w| unsafe { w.bits(0xff * duty) });
}
}
impl<TIMER> wg::Pwm for Pwm<TIMER>
where
TIMER: Ctimer<init_state::Enabled>,
{
type Channel = u8;
type Time = Microseconds;
type Duty = u16;
fn enable(&mut self, channel: Self::Channel) {
match channel {
0..=2 => {}
_ => {
panic!("Cannot use channel outside 0-2 for PWM.");
}
}
}
fn disable(&mut self, channel: Self::Channel) {
match channel {
0 => {
self.timer
.mcr
.modify(|_, w| w.mr0i().clear_bit().mr0r().clear_bit().mr0s().clear_bit());
self.timer.pwmc.modify(|_, w| w.pwmen0().clear_bit());
}
1 => {
self.timer
.mcr
.modify(|_, w| w.mr1i().clear_bit().mr1r().clear_bit().mr1s().clear_bit());
self.timer.pwmc.modify(|_, w| w.pwmen1().clear_bit());
}
2 => {
self.timer
.mcr
.modify(|_, w| w.mr2i().clear_bit().mr2r().clear_bit().mr2s().clear_bit());
self.timer.pwmc.modify(|_, w| w.pwmen2().clear_bit());
}
_ => {
panic!("Cannot use channel outside 0-2 for PWM.");
}
}
}
fn get_period(&self) -> Self::Time {
Microseconds(1_000_000 / self.get_max_duty() as u32)
}
fn set_period<P>(&mut self, _period: P)
where
P: Into<Self::Time>,
{
panic!("Currently period is fixed.");
}
fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
self.timer.mr[channel as usize].read().bits() as Self::Duty
}
fn get_max_duty(&self) -> Self::Duty {
self.timer.mr[3].read().bits() as Self::Duty
}
fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
self.timer.mr[channel as usize].write(|w| unsafe { w.bits(duty as u32) });
}
}