use core::marker;
use hal;
use atmega32u4;
use port;
macro_rules! timer_impl {
(
Info: ($Timer:ident, $TIMER:ident, $tim:ident),
Init: $init:block,
Pins: [
$(|$port:ident, $PIN:ident, $pwm:ident| ($ocr:ident, $setup:block),)+
]
) => {
pub struct $Timer {
$tim: atmega32u4::$TIMER,
}
impl $Timer {
pub fn new($tim: atmega32u4::$TIMER) -> $Timer {
$init
$Timer {
$tim: $tim,
}
}
}
$(
impl port::$port::$PIN<port::mode::io::Output> {
pub fn into_pwm(
self,
$pwm: &mut $Timer,
) -> port::$port::$PIN<port::mode::Pwm<$Timer>> {
$setup
port::$port::$PIN {
_mode: marker::PhantomData,
}
}
}
impl hal::PwmPin for port::$port::$PIN<port::mode::Pwm<$Timer>> {
type Duty = u8;
fn disable(&mut self) {
unimplemented!()
}
fn enable(&mut self) {
unimplemented!()
}
fn get_duty(&self) -> Self::Duty {
unsafe { (&*atmega32u4::$TIMER::ptr()) }.$ocr.read().bits()
}
fn get_max_duty(&self) -> Self::Duty {
::core::u8::MAX
}
fn set_duty(&mut self, duty: Self::Duty) {
unsafe { (&*atmega32u4::$TIMER::ptr()) }.$ocr.write(|w| w.bits(duty));
}
}
)+
}
}
timer_impl! {
Info: (Timer0Pwm, TIMER0, tim),
Init: {
tim.tccr_a.modify(|_, w| w.wgm0().pwm_fast());
tim.tccr_b.modify(|_, w| w.cs().io_64());
},
Pins: [
|portb, PB7, pwm| (ocr_a, {
pwm.tim.tccr_a.modify(|_, w| w.com_a().match_clear());
}),
|portd, PD0, pwm| (ocr_b, {
pwm.tim.tccr_a.modify(|_, w| w.com_b().match_clear());
}),
]
}
timer_impl! {
Info: (Timer1Pwm, TIMER1, tim),
Init: {
tim.tccr_a.modify(|_, w| unsafe { w.wgm0().bits(0b01) });
tim.tccr_b.modify(|_, w| unsafe { w.wgm2().bits(0b01)}.cs().io_64());
},
Pins: [
|portb, PB5, pwm| (ocr_a_l, {
pwm.tim.tccr_a.modify(|_, w| w.com_a().match_clear());
}),
|portb, PB6, pwm| (ocr_b_l, {
pwm.tim.tccr_a.modify(|_, w| w.com_b().match_clear());
}),
]
}
impl port::portb::PB7<port::mode::io::Output> {
pub fn into_pwm1(self, pwm: &mut Timer1Pwm) -> port::portb::PB7<port::mode::Pwm<Timer1Pwm>> {
pwm.tim.tccr_a.modify(|_, w| w.com_c().match_clear());
port::portb::PB7 { _mode: marker::PhantomData }
}
}
impl hal::PwmPin for port::portb::PB7<port::mode::Pwm<Timer1Pwm>> {
type Duty = u8;
fn disable(&mut self) {
unimplemented!()
}
fn enable(&mut self) {
unimplemented!()
}
fn get_duty(&self) -> Self::Duty {
unsafe { (&*atmega32u4::TIMER1::ptr()) }
.ocr_c_l
.read()
.bits()
}
fn get_max_duty(&self) -> Self::Duty {
::core::u8::MAX
}
fn set_duty(&mut self, duty: Self::Duty) {
unsafe { (&*atmega32u4::TIMER1::ptr()) }.ocr_c_l.write(
|w| {
w.bits(duty)
},
);
}
}
timer_impl! {
Info: (Timer3Pwm, TIMER3, tim),
Init: {
tim.tccr_a.modify(|_, w| unsafe { w.wgm0().bits(0b01) });
tim.tccr_b.modify(|_, w| unsafe { w.wgm2().bits(0b01) }.cs().io_64());
},
Pins: [
|portc, PC6, pwm| (ocr_a_l, {
pwm.tim.tccr_a.modify(|_, w| w.com_a().match_clear());
}),
]
}
timer_impl! {
Info: (Timer4Pwm, TIMER4, tim),
Init: {
tim.tccr_b.modify(|_, w| w.cs().clk_64());
tim.tccr_d.modify(|_, w| unsafe { w.wgm().bits(0b01) });
},
Pins: [
|portc, PC7, pwm| (ocr_a, {
pwm.tim.tccr_a.modify(|_, w| w.com_a().match_clear().pwm_a().set_bit());
}),
|portd, PD7, pwm| (ocr_d, {
pwm.tim.tccr_c.modify(|_, w| w.com_d().match_clear().pwm_d().set_bit());
}),
]
}
impl port::portb::PB6<port::mode::io::Output> {
pub fn into_pwm4(self, pwm: &mut Timer4Pwm) -> port::portb::PB6<port::mode::Pwm<Timer4Pwm>> {
pwm.tim.tccr_a.modify(|_, w| {
w.com_b().match_clear().pwm_b().set_bit()
});
port::portb::PB6 { _mode: marker::PhantomData }
}
}
impl hal::PwmPin for port::portb::PB6<port::mode::Pwm<Timer4Pwm>> {
type Duty = u8;
fn disable(&mut self) {
unimplemented!()
}
fn enable(&mut self) {
unimplemented!()
}
fn get_duty(&self) -> Self::Duty {
unsafe { (&*atmega32u4::TIMER4::ptr()) }.ocr_b.read().bits()
}
fn get_max_duty(&self) -> Self::Duty {
::core::u8::MAX
}
fn set_duty(&mut self, duty: Self::Duty) {
unsafe { (&*atmega32u4::TIMER4::ptr()) }.ocr_b.write(|w| {
w.bits(duty)
});
}
}