1use core::marker::PhantomData;
4use core::mem;
5
6use crate::hal;
7use crate::stm32::{TIM1, TIM15, TIM2};
8
9use crate::gpio::gpioa::{PA0, PA1, PA10, PA11, PA15, PA2, PA3, PA8, PA9};
10use crate::gpio::gpiob::{PB10, PB11, PB14, PB3};
11use crate::gpio::Alternate;
12use crate::rcc::{Clocks, Enable, Reset, APB1R1, APB2};
13use crate::time::Hertz;
14
15pub trait Pins<TIM> {
17 const C1: bool = false;
19 const C2: bool = false;
20 const C3: bool = false;
21 const C4: bool = false;
22 type Channels;
23}
24
25macro_rules! pins_to_channels_mapping {
26 ( $( $TIMX:ident: ( $($PINX:ident),+ ), ( $($ENCHX:ident),+ ), ( $($AF:literal),+ ); )+ ) => {
27 $(
28 #[allow(unused_parens)]
29 impl<OTYPE> Pins<$TIMX> for ($($PINX<Alternate<OTYPE, $AF>>),+)
30 {
31 $(const $ENCHX: bool = true;)+
32 type Channels = ($(Pwm<$TIMX, $ENCHX>),+);
33 }
34 )+
35 };
36}
37
38pins_to_channels_mapping! {
39 TIM1: (PA8, PA9, PA10, PA11), (C1, C2, C3, C4), (1, 1, 1, 1);
41 TIM1: (PA9, PA10, PA11), (C2, C3, C4), (1, 1, 1);
42 TIM1: (PA8, PA10, PA11), (C1, C3, C4), (1, 1, 1);
43 TIM1: (PA8, PA9, PA11), (C1, C2, C4), (1, 1, 1);
44 TIM1: (PA8, PA9, PA10), (C1, C2, C3), (1, 1, 1);
45 TIM1: (PA10, PA11), (C3, C4), (1, 1);
46 TIM1: (PA9, PA11), (C2, C4), (1, 1);
47 TIM1: (PA9, PA10), (C2, C3), (1, 1);
48 TIM1: (PA8, PA11), (C1, C4), (1, 1);
49 TIM1: (PA8, PA10), (C1, C3), (1, 1);
50 TIM1: (PA8, PA9), (C1, C2), (1, 1);
51 TIM1: (PA8), (C1), (1);
52 TIM1: (PA9), (C2), (1);
53 TIM1: (PA10), (C3), (1);
54 TIM1: (PA11), (C4), (1);
55
56 TIM2: (PA0, PA1, PA2, PA3), (C1, C2, C3, C4), (1, 1, 1, 1);
58 TIM2: (PA0, PA1, PA2, PB11), (C1, C2, C3, C4), (1, 1, 1, 1);
59 TIM2: (PA15, PB3, PB10, PB11), (C1, C2, C3, C4), (1, 1, 1, 1);
60
61 TIM2: (PA1, PA2, PA3), (C2, C3, C4), (1, 1, 1);
62 TIM2: (PA0, PA2, PA3), (C1, C3, C4), (1, 1, 1);
63 TIM2: (PA0, PA1, PA3), (C1, C2, C4), (1, 1, 1);
64 TIM2: (PA0, PA1, PA2), (C1, C2, C3), (1, 1, 1);
65
66 TIM2: (PB3, PB10, PB11), (C2, C3, C4), (1, 1, 1);
67 TIM2: (PA15, PB10, PB11), (C1, C3, C4), (1, 1, 1);
68 TIM2: (PA15, PB3, PB11), (C1, C2, C4), (1, 1, 1);
69 TIM2: (PA15, PB3, PB10), (C1, C2, C3), (1, 1, 1);
70
71 TIM2: (PA2, PA3), (C3, C4), (1, 1);
72 TIM2: (PA1, PA3), (C2, C4), (1, 1);
73 TIM2: (PA1, PA2), (C2, C3), (1, 1);
74 TIM2: (PA0, PA3), (C1, C4), (1, 1);
75 TIM2: (PA0, PA2), (C1, C3), (1, 1);
76 TIM2: (PA0, PA1), (C1, C2), (1, 1);
77
78 TIM2: (PB10, PB11), (C3, C4), (1, 1);
79 TIM2: (PB3, PB11), (C2, C4), (1, 1);
80 TIM2: (PB3, PB10), (C2, C3), (1, 1);
81 TIM2: (PA15, PB11), (C1, C4), (1, 1);
82 TIM2: (PA15, PB10), (C1, C3), (1, 1);
83 TIM2: (PA15, PB3), (C1, C2), (1, 1);
84
85 TIM2: (PA0), (C1), (1);
86 TIM2: (PA1), (C2), (1);
87 TIM2: (PA2), (C3), (1);
88 TIM2: (PA3), (C4), (1);
89
90 TIM2: (PA15), (C1), (1);
91 TIM2: (PB3), (C2), (1);
92 TIM2: (PB10), (C3), (1);
93 TIM2: (PB11), (C4), (1);
94
95 TIM15: (PB14), (C1), (14);
97 TIM15: (PA2), (C1), (14);
99 }
105
106pub trait PwmExt1: Sized {
107 fn pwm<PINS>(self, _: PINS, frequency: Hertz, clocks: Clocks, apb: &mut APB2) -> PINS::Channels
108 where
109 PINS: Pins<Self>;
110}
111
112pub trait PwmExt2: Sized {
113 fn pwm<PINS>(
114 self,
115 _: PINS,
116 frequency: Hertz,
117 clocks: Clocks,
118 apb: &mut APB1R1,
119 ) -> PINS::Channels
120 where
121 PINS: Pins<Self>;
122}
123
124impl PwmExt1 for TIM1 {
125 fn pwm<PINS>(self, _pins: PINS, freq: Hertz, clocks: Clocks, apb: &mut APB2) -> PINS::Channels
126 where
127 PINS: Pins<Self>,
128 {
129 tim1(self, _pins, freq, clocks, apb)
130 }
131}
132
133impl PwmExt1 for TIM15 {
134 fn pwm<PINS>(self, _pins: PINS, freq: Hertz, clocks: Clocks, apb: &mut APB2) -> PINS::Channels
135 where
136 PINS: Pins<Self>,
137 {
138 tim15(self, _pins, freq, clocks, apb)
139 }
140}
141
142impl PwmExt2 for TIM2 {
143 fn pwm<PINS>(self, _pins: PINS, freq: Hertz, clocks: Clocks, apb: &mut APB1R1) -> PINS::Channels
144 where
145 PINS: Pins<Self>,
146 {
147 tim2(self, _pins, freq, clocks, apb)
154 }
155}
156
157pub struct Pwm<TIM, CHANNEL> {
158 _channel: PhantomData<CHANNEL>,
159 _tim: PhantomData<TIM>,
160}
161
162pub struct C1;
163pub struct C2;
164pub struct C3;
165pub struct C4;
166
167macro_rules! advanced_timer {
168 ($($TIMX:ident: ($timX:ident, $apb:ident, $psc_width:ident, $arr_width:ident),)+) => {
169 $(
170 fn $timX<PINS>(
171 tim: $TIMX,
172 _pins: PINS,
173 freq: Hertz,
174 clocks: Clocks,
175 apb: &mut $apb,
176 ) -> PINS::Channels
177 where
178 PINS: Pins<$TIMX>,
179 {
180 <$TIMX>::enable(apb);
181 <$TIMX>::reset(apb);
182
183 if PINS::C1 {
184 tim.ccmr1_output().modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6));
185 }
186
187 if PINS::C2 {
188 tim.ccmr1_output().modify(|_, w| w.oc2pe().set_bit().oc2m().bits(6));
189 }
190
191 if PINS::C3 {
192 tim.ccmr2_output().modify(|_, w| w.oc3pe().set_bit().oc3m().bits(6));
193 }
194
195 if PINS::C4 {
196 tim.ccmr2_output().modify(|_, w| w.oc4pe().set_bit().oc4m().bits(6));
197 }
198
199 let clk = clocks.pclk2();
200 let ticks = clk / freq;
201
202 let psc = ticks / (1 << 16);
204 tim.psc.write(|w| { w.psc().bits(psc as $psc_width) });
205 let arr = ticks / (psc + 1);
206 tim.arr.write(|w| { w.arr().bits(arr as $arr_width) });
207
208 tim.bdtr.write(|w| w.moe().set_bit());
210 tim.egr.write(|w| w.ug().set_bit());
211
212 tim.cr1.write(|w| {
213 w.cms()
214 .bits(0b00)
215 .dir().clear_bit()
216 .opm().clear_bit()
217 .cen().set_bit()
218 .arpe().set_bit()
219 });
220
221 unsafe { mem::MaybeUninit::uninit().assume_init() }
222 }
223
224 pwm_channels! {
225 $TIMX: (C1, $arr_width, cc1e, ccr1, ccr),
226 (C2, $arr_width, cc2e, ccr2, ccr),
227 (C3, $arr_width, cc3e, ccr3, ccr),
228 (C4, $arr_width, cc4e, ccr4, ccr),
229 }
230
231 )+
232 }
233}
234
235macro_rules! standard_timer {
236 ($($TIMX:ident: ($timX:ident, $apb:ident, $psc_width:ident, $arr_width:ident),)+) => {
237 $(
238 fn $timX<PINS>(
239 tim: $TIMX,
240 _pins: PINS,
241 freq: Hertz,
242 clocks: Clocks,
243 apb: &mut $apb,
244 ) -> PINS::Channels
245 where
246 PINS: Pins<$TIMX>,
247 {
248 <$TIMX>::enable(apb);
249 <$TIMX>::reset(apb);
250
251 if PINS::C1 {
252 tim.ccmr1_output().modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6));
253 }
254
255 if PINS::C2 {
256 tim.ccmr1_output().modify(|_, w| w.oc2pe().set_bit().oc2m().bits(6));
257 }
258
259 if PINS::C3 {
260 tim.ccmr2_output().modify(|_, w| w.oc3pe().set_bit().oc3m().bits(6));
261 }
262
263 if PINS::C4 {
264 tim.ccmr2_output().modify(|_, w| w.oc4pe().set_bit().oc4m().bits(6));
265 }
266
267 let clk = clocks.pclk1();
268 let ticks = clk / freq;
269
270 let psc = ticks / (1 << 16);
272 tim.psc.write(|w| { w.psc().bits(psc as $psc_width) });
273 let arr = ticks / (psc + 1);
274 tim.arr.write(|w| { w.arr().bits(arr as $arr_width) });
275
276 tim.cr1.write(|w| {
277 w.cms()
278 .bits(0b00)
279 .dir().clear_bit()
280 .opm().clear_bit()
281 .cen().set_bit()
282 .arpe().set_bit()
283 });
284
285 unsafe { mem::MaybeUninit::uninit().assume_init() }
286 }
287
288 pwm_channels! {
289 $TIMX: (C1, $arr_width, cc1e, ccr1, ccr),
290 (C2, $arr_width, cc2e, ccr2, ccr),
291 (C3, $arr_width, cc3e, ccr3, ccr),
292 (C4, $arr_width, cc4e, ccr4, ccr),
293 }
294
295 )+
296 }
297}
298
299macro_rules! small_timer {
300 ($($TIMX:ident: ($timX:ident, $apb:ident, $psc_width:ident, $arr_width:ident),)+) => {
301 $(
302 fn $timX<PINS>(
303 tim: $TIMX,
304 _pins: PINS,
305 freq: Hertz,
306 clocks: Clocks,
307 apb: &mut $apb,
308 ) -> PINS::Channels
309 where
310 PINS: Pins<$TIMX>,
311 {
312 <$TIMX>::enable(apb);
313 <$TIMX>::reset(apb);
314
315 if PINS::C1 {
316 tim.ccmr1_output().modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6));
317 }
318
319 let clk = clocks.pclk1();
325 let ticks = clk / freq;
326
327 let psc = ticks / (1 << 16);
329 tim.psc.write(|w| { w.psc().bits(psc as $psc_width) });
330 let arr = ticks / (psc + 1);
331 unsafe { tim.arr.write(|w| { w.arr().bits(arr as $arr_width) }); }
332
333 tim.bdtr.write(|w| w.moe().set_bit());
334 tim.egr.write(|w| w.ug().set_bit());
335
336 tim.cr1.write(|w| {
337 w.opm().clear_bit()
338 .cen().set_bit()
339 .arpe().set_bit()
340 });
341
342 unsafe { mem::MaybeUninit::uninit().assume_init() }
343 }
344
345 pwm_channels! {
346 $TIMX: (C1, $arr_width, cc1e, ccr1, ccr),
347 }
350
351 )+
352 }
353}
354
355macro_rules! pwm_channels {
356 ($TIMX:ident: $(($channel:ident, $arr_width:ident, $ccXe:ident, $ccrX:ident, $ccr:ident),)+) => {
357 $(
358 impl hal::PwmPin for Pwm<$TIMX, $channel> {
359 type Duty = $arr_width;
360
361 #[inline(always)]
362 fn disable(&mut self) {
363 unsafe { (*$TIMX::ptr()).ccer.modify(|_, w| w.$ccXe().clear_bit()) }
364 }
365
366 #[inline(always)]
367 fn enable(&mut self) {
368 unsafe { (*$TIMX::ptr()).ccer.modify(|_, w| w.$ccXe().set_bit()) }
369 }
370
371 #[inline(always)]
372 fn get_duty(&self) -> Self::Duty {
373 unsafe { (*$TIMX::ptr()).$ccrX.read().$ccr().bits() }
374 }
375
376 #[inline(always)]
377 fn get_max_duty(&self) -> Self::Duty {
378 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() }
379 }
380
381 #[inline(always)]
382 fn set_duty(&mut self, duty: Self::Duty) {
383 unsafe { (*$TIMX::ptr()).$ccrX.write(|w| w.$ccr().bits(duty)) }
384 }
385 }
386 )+
387 }
388}
389
390advanced_timer! {
391 TIM1: (tim1, APB2, u16, u16),
392}
393
394standard_timer! {
395 TIM2: (tim2, APB1R1, u16, u32),
396}
397
398small_timer! {
399 TIM15: (tim15, APB2, u16, u16),
400}