1use cast::{u16, u32};
4use hal::timer::{CountDown, Periodic};
5use nb;
6use stm32f30x::{TIM2, TIM3, TIM4, TIM6, TIM7};
7use void::Void;
8
9use rcc::{APB1, Clocks};
10use time::Hertz;
11
12pub struct Timer<TIM> {
14 clocks: Clocks,
15 tim: TIM,
16 timeout: Hertz,
17}
18
19pub enum Event {
21 TimeOut,
23}
24
25macro_rules! hal {
26 ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident),)+) => {
27 $(
28 impl Periodic for Timer<$TIM> {}
29
30 impl CountDown for Timer<$TIM> {
31 type Time = Hertz;
32
33 #[allow(unused_unsafe)]
36 fn start<T>(&mut self, timeout: T)
37 where
38 T: Into<Hertz>,
39 {
40 self.tim.cr1.modify(|_, w| w.cen().clear_bit());
42 self.tim.cnt.reset();
44
45 self.timeout = timeout.into();
46
47 let frequency = self.timeout.0;
48 let ticks = self.clocks.pclk1().0 * if self.clocks.ppre1() == 1 { 1 } else { 2 }
49 / frequency;
50
51 let psc = u16((ticks - 1) / (1 << 16)).unwrap();
52 self.tim.psc.write(|w| unsafe { w.psc().bits(psc) });
53
54 let arr = u16(ticks / u32(psc + 1)).unwrap();
55 self.tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
56
57 self.tim.cr1.modify(|_, w| w.cen().set_bit());
59 }
60
61 fn wait(&mut self) -> nb::Result<(), Void> {
62 if self.tim.sr.read().uif().bit_is_clear() {
63 Err(nb::Error::WouldBlock)
64 } else {
65 self.tim.sr.modify(|_, w| w.uif().clear_bit());
66 Ok(())
67 }
68 }
69 }
70
71 impl Timer<$TIM> {
72 pub fn $tim<T>(tim: $TIM, timeout: T, clocks: Clocks, apb1: &mut APB1) -> Self
77 where
78 T: Into<Hertz>,
79 {
80 apb1.enr().modify(|_, w| w.$timXen().set_bit());
82 apb1.rstr().modify(|_, w| w.$timXrst().set_bit());
83 apb1.rstr().modify(|_, w| w.$timXrst().clear_bit());
84
85 let mut timer = Timer {
86 clocks,
87 tim,
88 timeout: Hertz(0),
89 };
90 timer.start(timeout);
91
92 timer
93 }
94
95 pub fn listen(&mut self, event: Event) {
97 match event {
98 Event::TimeOut => {
99 self.tim.dier.write(|w| w.uie().set_bit());
101 }
102 }
103 }
104
105 pub fn unlisten(&mut self, event: Event) {
107 match event {
108 Event::TimeOut => {
109 self.tim.dier.write(|w| w.uie().clear_bit());
111 }
112 }
113 }
114
115 pub fn free(self) -> $TIM {
117 self.tim.cr1.modify(|_, w| w.cen().clear_bit());
119 self.tim
120 }
121 }
122 )+
123 }
124}
125
126hal! {
127 TIM2: (tim2, tim2en, tim2rst),
128 TIM3: (tim3, tim3en, tim3rst),
129 TIM4: (tim4, tim4en, tim4rst),
130 TIM6: (tim6, tim6en, tim6rst),
131 TIM7: (tim7, tim7en, tim7rst),
132}