ionpak-thermostat/firmware/src/board/pwm.rs

139 lines
4.2 KiB
Rust

use tm4c129x::{
TIMER2, TIMER3, TIMER4, TIMER5,
};
pub struct T2CCP0;
pub struct T2CCP1;
pub struct T3CCP0;
pub struct T3CCP1;
pub struct T4CCP0;
pub struct T4CCP1;
pub struct T5CCP0;
pub struct T5CCP1;
pub trait PwmPeripheral {
type ChannelA: PwmChannel;
type ChannelB: PwmChannel;
fn split() -> (Self::ChannelA, Self::ChannelB);
}
macro_rules! pwm_peripheral {
($TIMER: ty, $A: tt, $B: tt) => {
impl PwmPeripheral for $TIMER {
type ChannelA = $A;
type ChannelB = $B;
fn split() -> (Self::ChannelA, Self::ChannelB) {
let regs = unsafe { &*Self::ptr() };
regs.cfg.write(|w| unsafe { w.bits(4) });
let mut a = $A;
a.configure();
let mut b = $B;
b.configure();
(a, b)
}
}
};
}
pwm_peripheral!(TIMER2, T2CCP0, T2CCP1);
pwm_peripheral!(TIMER3, T3CCP0, T3CCP1);
pwm_peripheral!(TIMER4, T4CCP0, T4CCP1);
pwm_peripheral!(TIMER5, T5CCP0, T5CCP1);
pub trait PwmChannel {
fn configure(&mut self);
fn get(&mut self) -> (u16, u16);
fn set(&mut self, width: u16, total: u16);
}
macro_rules! pwm_channel_a {
($CHANNEL: ty, $TIMER: tt) => {
impl PwmChannel for $CHANNEL {
fn configure(&mut self) {
let timer = unsafe { &*tm4c129x::$TIMER::ptr() };
timer.tamr.modify(|_, w| unsafe {
w
.taams().bit(true)
.tacmr().bit(false)
.tamr().bits(2)
});
timer.ctl.modify(|_, w| {
w
.tapwml().bit(false)
});
// no prescaler
// no interrupts
timer.tailr.write(|w| unsafe { w.bits(0xFFFF) });
timer.tamatchr.write(|w| unsafe { w.bits(0x0) });
timer.ctl.modify(|_, w| {
w
.taen().bit(true)
});
}
fn get(&mut self) -> (u16, u16) {
let timer = unsafe { &*tm4c129x::$TIMER::ptr() };
(timer.tamatchr.read().bits() as u16,
timer.tailr.read().bits() as u16)
}
fn set(&mut self, width: u16, total: u16) {
let timer = unsafe { &*tm4c129x::$TIMER::ptr() };
timer.tamatchr.write(|w| unsafe { w.bits(width.into()) });
timer.tailr.write(|w| unsafe { w.bits(total.into()) });
}
}
};
}
macro_rules! pwm_channel_b {
($CHANNEL: ty, $TIMER: tt) => {
impl PwmChannel for $CHANNEL {
fn configure(&mut self) {
let timer = unsafe { &*tm4c129x::$TIMER::ptr() };
timer.tbmr.modify(|_, w| unsafe {
w
.tbams().bit(true)
.tbcmr().bit(false)
.tbmr().bits(2)
});
timer.ctl.modify(|_, w| {
w
.tbpwml().bit(false)
});
// no prescaler
// no interrupts
timer.tbilr.write(|w| unsafe { w.bits(0xFFFF) });
timer.tbmatchr.write(|w| unsafe { w.bits(0x0) });
timer.ctl.modify(|_, w| {
w
.tben().bit(true)
});
}
fn get(&mut self) -> (u16, u16) {
let timer = unsafe { &*tm4c129x::$TIMER::ptr() };
(timer.tbmatchr.read().bits() as u16,
timer.tbilr.read().bits() as u16)
}
fn set(&mut self, width: u16, total: u16) {
let timer = unsafe { &*tm4c129x::$TIMER::ptr() };
timer.tbmatchr.write(|w| unsafe { w.bits(width.into()) });
timer.tbilr.write(|w| unsafe { w.bits(total.into()) });
}
}
};
}
pwm_channel_a!(T2CCP0, TIMER2);
pwm_channel_b!(T2CCP1, TIMER2);
pwm_channel_a!(T3CCP0, TIMER3);
pwm_channel_b!(T3CCP1, TIMER3);
pwm_channel_a!(T4CCP0, TIMER4);
pwm_channel_b!(T4CCP1, TIMER4);
pwm_channel_a!(T5CCP0, TIMER5);
pwm_channel_b!(T5CCP1, TIMER5);