1use super::{compute_arr_presc, Channel, FTimer, Instance, Ocm, Timer, WithPwm};
2use crate::rcc::Clocks;
3use core::marker::PhantomData;
4use core::ops::{Deref, DerefMut};
5use fugit::{HertzU32 as Hertz, TimerDurationU32};
6
7pub trait Pins<TIM, P> {
8 const C1: bool = false;
9 const C2: bool = false;
10 const C3: bool = false;
11 const C4: bool = false;
12 type Channels;
13
14 fn check_used(c: Channel) -> Channel {
15 if (c == Channel::C1 && Self::C1)
16 || (c == Channel::C2 && Self::C2)
17 || (c == Channel::C3 && Self::C3)
18 || (c == Channel::C4 && Self::C4)
19 {
20 c
21 } else {
22 panic!("Unused channel")
23 }
24 }
25
26 fn split() -> Self::Channels;
27}
28pub use super::{CPin, Ch, C1, C2, C3, C4};
29
30pub struct PwmChannel<TIM, const C: u8> {
31 pub(super) _tim: PhantomData<TIM>,
32}
33
34macro_rules! pins_impl {
35 ( $( ( $($PINX:ident),+ ), ( $($ENCHX:ident),+ ); )+ ) => {
36 $(
37 #[allow(unused_parens)]
38 impl<TIM, $($PINX,)+> Pins<TIM, ($(Ch<$ENCHX>),+)> for ($($PINX),+)
39 where
40 TIM: Instance + WithPwm,
41 $($PINX: CPin<TIM, $ENCHX>,)+
42 {
43 $(const $ENCHX: bool = true;)+
44 type Channels = ($(PwmChannel<TIM, $ENCHX>),+);
45 fn split() -> Self::Channels {
46 ($(PwmChannel::<TIM, $ENCHX>::new()),+)
47 }
48 }
49 )+
50 };
51}
52
53pins_impl!(
54 (P1, P2, P3, P4), (C1, C2, C3, C4);
55 (P2, P3, P4), (C2, C3, C4);
56 (P1, P3, P4), (C1, C3, C4);
57 (P1, P2, P4), (C1, C2, C4);
58 (P1, P2, P3), (C1, C2, C3);
59 (P3, P4), (C3, C4);
60 (P2, P4), (C2, C4);
61 (P2, P3), (C2, C3);
62 (P1, P4), (C1, C4);
63 (P1, P3), (C1, C3);
64 (P1, P2), (C1, C2);
65 (P1), (C1);
66 (P2), (C2);
67 (P3), (C3);
68 (P4), (C4);
69);
70
71impl<TIM, P1, P2, const C: u8> CPin<TIM, C> for (P1, P2)
72where
73 P1: CPin<TIM, C>,
74 P2: CPin<TIM, C>,
75{
76}
77impl<TIM, P1, P2, P3, const C: u8> CPin<TIM, C> for (P1, P2, P3)
78where
79 P1: CPin<TIM, C>,
80 P2: CPin<TIM, C>,
81 P3: CPin<TIM, C>,
82{
83}
84impl<TIM, P1, P2, P3, P4, const C: u8> CPin<TIM, C> for (P1, P2, P3, P4)
85where
86 P1: CPin<TIM, C>,
87 P2: CPin<TIM, C>,
88 P3: CPin<TIM, C>,
89 P4: CPin<TIM, C>,
90{
91}
92
93pub trait PwmExt
94where
95 Self: Sized + Instance + WithPwm,
96{
97 fn pwm<P, PINS, const FREQ: u32>(
98 self,
99 pins: PINS,
100 time: TimerDurationU32<FREQ>,
101 clocks: &Clocks,
102 ) -> Pwm<Self, P, PINS, FREQ>
103 where
104 PINS: Pins<Self, P>;
105
106 fn pwm_hz<P, PINS>(self, pins: PINS, freq: Hertz, clocks: &Clocks) -> PwmHz<Self, P, PINS>
107 where
108 PINS: Pins<Self, P>;
109
110 fn pwm_us<P, PINS>(
111 self,
112 pins: PINS,
113 time: TimerDurationU32<1_000_000>,
114 clocks: &Clocks,
115 ) -> Pwm<Self, P, PINS, 1_000_000>
116 where
117 PINS: Pins<Self, P>,
118 {
119 self.pwm::<_, _, 1_000_000>(pins, time, clocks)
120 }
121}
122
123impl<TIM> PwmExt for TIM
124where
125 Self: Sized + Instance + WithPwm,
126{
127 fn pwm<P, PINS, const FREQ: u32>(
128 self,
129 pins: PINS,
130 time: TimerDurationU32<FREQ>,
131 clocks: &Clocks,
132 ) -> Pwm<TIM, P, PINS, FREQ>
133 where
134 PINS: Pins<Self, P>,
135 {
136 FTimer::<Self, FREQ>::new(self, clocks).pwm(pins, time)
137 }
138
139 fn pwm_hz<P, PINS>(self, pins: PINS, time: Hertz, clocks: &Clocks) -> PwmHz<TIM, P, PINS>
140 where
141 PINS: Pins<Self, P>,
142 {
143 Timer::new(self, clocks).pwm_hz(pins, time)
144 }
145}
146
147impl<TIM: Instance + WithPwm, const C: u8> PwmChannel<TIM, C> {
148 pub(crate) fn new() -> Self {
149 Self {
150 _tim: core::marker::PhantomData,
151 }
152 }
153}
154
155impl<TIM: Instance + WithPwm, const C: u8> PwmChannel<TIM, C> {
156 #[inline]
157 pub fn disable(&mut self) {
158 TIM::enable_channel(C, false);
159 }
160
161 #[inline]
162 pub fn enable(&mut self) {
163 TIM::enable_channel(C, true);
164 }
165
166 #[inline]
167 pub fn get_duty(&self) -> u16 {
168 TIM::read_cc_value(C) as u16
169 }
170
171 #[inline]
173 pub fn get_max_duty(&self) -> u16 {
174 (TIM::read_auto_reload() as u16).wrapping_add(1)
175 }
176
177 #[inline]
178 pub fn set_duty(&mut self, duty: u16) {
179 TIM::set_cc_value(C, duty as u32)
180 }
181}
182
183pub struct PwmHz<TIM, P, PINS>
184where
185 TIM: Instance + WithPwm,
186 PINS: Pins<TIM, P>,
187{
188 timer: Timer<TIM>,
189 _pins: PhantomData<(P, PINS)>,
190}
191
192impl<TIM, P, PINS> PwmHz<TIM, P, PINS>
193where
194 TIM: Instance + WithPwm,
195 PINS: Pins<TIM, P>,
196{
197 pub fn release(mut self) -> Timer<TIM> {
198 self.tim.cr1_reset();
200 self.timer
201 }
202
203 pub fn split(self) -> PINS::Channels {
204 PINS::split()
205 }
206}
207
208impl<TIM, P, PINS> Deref for PwmHz<TIM, P, PINS>
209where
210 TIM: Instance + WithPwm,
211 PINS: Pins<TIM, P>,
212{
213 type Target = Timer<TIM>;
214 fn deref(&self) -> &Self::Target {
215 &self.timer
216 }
217}
218
219impl<TIM, P, PINS> DerefMut for PwmHz<TIM, P, PINS>
220where
221 TIM: Instance + WithPwm,
222 PINS: Pins<TIM, P>,
223{
224 fn deref_mut(&mut self) -> &mut Self::Target {
225 &mut self.timer
226 }
227}
228
229impl<TIM: Instance + WithPwm> Timer<TIM> {
230 pub fn pwm_hz<P, PINS>(mut self, _pins: PINS, freq: Hertz) -> PwmHz<TIM, P, PINS>
231 where
232 PINS: Pins<TIM, P>,
233 {
234 if PINS::C1 {
235 self.tim
236 .preload_output_channel_in_mode(Channel::C1, Ocm::PwmMode1);
237 }
238 if PINS::C2 && TIM::CH_NUMBER > 1 {
239 self.tim
240 .preload_output_channel_in_mode(Channel::C2, Ocm::PwmMode1);
241 }
242 if PINS::C3 && TIM::CH_NUMBER > 2 {
243 self.tim
244 .preload_output_channel_in_mode(Channel::C3, Ocm::PwmMode1);
245 }
246 if PINS::C4 && TIM::CH_NUMBER > 3 {
247 self.tim
248 .preload_output_channel_in_mode(Channel::C4, Ocm::PwmMode1);
249 }
250
251 self.tim.enable_preload(true);
255
256 let (psc, arr) = compute_arr_presc(freq.raw(), self.clk.raw());
257 self.tim.set_prescaler(psc);
258 self.tim.set_auto_reload(arr).unwrap();
259
260 self.tim.trigger_update();
262
263 self.tim.start_pwm();
264
265 PwmHz {
266 timer: self,
267 _pins: PhantomData,
268 }
269 }
270}
271
272impl<TIM, P, PINS> PwmHz<TIM, P, PINS>
273where
274 TIM: Instance + WithPwm,
275 PINS: Pins<TIM, P>,
276{
277 pub fn enable(&mut self, channel: Channel) {
278 TIM::enable_channel(PINS::check_used(channel) as u8, true)
279 }
280
281 pub fn disable(&mut self, channel: Channel) {
282 TIM::enable_channel(PINS::check_used(channel) as u8, false)
283 }
284
285 pub fn get_duty(&self, channel: Channel) -> u16 {
286 TIM::read_cc_value(PINS::check_used(channel) as u8) as u16
287 }
288
289 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
290 TIM::set_cc_value(PINS::check_used(channel) as u8, duty as u32)
291 }
292
293 pub fn get_max_duty(&self) -> u16 {
295 (TIM::read_auto_reload() as u16).wrapping_add(1)
296 }
297
298 pub fn get_period(&self) -> Hertz {
299 let clk = self.clk;
300 let psc = self.tim.read_prescaler() as u32;
301 let arr = TIM::read_auto_reload();
302
303 clk / (psc * arr)
305 }
306
307 pub fn set_period(&mut self, period: Hertz) {
308 let clk = self.clk;
309
310 let (psc, arr) = compute_arr_presc(period.raw(), clk.raw());
311 self.tim.set_prescaler(psc);
312 self.tim.set_auto_reload(arr).unwrap();
313 }
314}
315
316pub struct Pwm<TIM, P, PINS, const FREQ: u32>
317where
318 TIM: Instance + WithPwm,
319 PINS: Pins<TIM, P>,
320{
321 timer: FTimer<TIM, FREQ>,
322 _pins: PhantomData<(P, PINS)>,
323}
324
325impl<TIM, P, PINS, const FREQ: u32> Pwm<TIM, P, PINS, FREQ>
326where
327 TIM: Instance + WithPwm,
328 PINS: Pins<TIM, P>,
329{
330 pub fn split(self) -> PINS::Channels {
331 PINS::split()
332 }
333
334 pub fn release(mut self) -> FTimer<TIM, FREQ> {
335 self.tim.cr1_reset();
337 self.timer
338 }
339}
340
341impl<TIM, P, PINS, const FREQ: u32> Deref for Pwm<TIM, P, PINS, FREQ>
342where
343 TIM: Instance + WithPwm,
344 PINS: Pins<TIM, P>,
345{
346 type Target = FTimer<TIM, FREQ>;
347 fn deref(&self) -> &Self::Target {
348 &self.timer
349 }
350}
351
352impl<TIM, P, PINS, const FREQ: u32> DerefMut for Pwm<TIM, P, PINS, FREQ>
353where
354 TIM: Instance + WithPwm,
355 PINS: Pins<TIM, P>,
356{
357 fn deref_mut(&mut self) -> &mut Self::Target {
358 &mut self.timer
359 }
360}
361
362impl<TIM: Instance + WithPwm, const FREQ: u32> FTimer<TIM, FREQ> {
363 pub fn pwm<P, PINS>(
364 mut self,
365 _pins: PINS,
366 time: TimerDurationU32<FREQ>,
367 ) -> Pwm<TIM, P, PINS, FREQ>
368 where
369 PINS: Pins<TIM, P>,
370 {
371 if PINS::C1 {
372 self.tim
373 .preload_output_channel_in_mode(Channel::C1, Ocm::PwmMode1);
374 }
375 if PINS::C2 && TIM::CH_NUMBER > 1 {
376 self.tim
377 .preload_output_channel_in_mode(Channel::C2, Ocm::PwmMode1);
378 }
379 if PINS::C3 && TIM::CH_NUMBER > 2 {
380 self.tim
381 .preload_output_channel_in_mode(Channel::C3, Ocm::PwmMode1);
382 }
383 if PINS::C4 && TIM::CH_NUMBER > 3 {
384 self.tim
385 .preload_output_channel_in_mode(Channel::C4, Ocm::PwmMode1);
386 }
387
388 self.tim.enable_preload(true);
392
393 self.tim.set_auto_reload(time.ticks() - 1).unwrap();
394
395 self.tim.trigger_update();
397
398 self.tim.start_pwm();
399
400 Pwm {
401 timer: self,
402 _pins: PhantomData,
403 }
404 }
405}
406
407impl<TIM, P, PINS, const FREQ: u32> Pwm<TIM, P, PINS, FREQ>
408where
409 TIM: Instance + WithPwm,
410 PINS: Pins<TIM, P>,
411{
412 pub fn enable(&mut self, channel: Channel) {
413 TIM::enable_channel(PINS::check_used(channel) as u8, true)
414 }
415
416 pub fn disable(&mut self, channel: Channel) {
417 TIM::enable_channel(PINS::check_used(channel) as u8, false)
418 }
419
420 pub fn get_duty(&self, channel: Channel) -> u16 {
421 TIM::read_cc_value(PINS::check_used(channel) as u8) as u16
422 }
423
424 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
425 TIM::set_cc_value(PINS::check_used(channel) as u8, duty.into())
426 }
427
428 pub fn get_max_duty(&self) -> u16 {
430 (TIM::read_auto_reload() as u16).wrapping_add(1)
431 }
432
433 pub fn get_period(&self) -> TimerDurationU32<FREQ> {
434 TimerDurationU32::from_ticks(TIM::read_auto_reload() + 1)
435 }
436
437 pub fn set_period(&mut self, period: TimerDurationU32<FREQ>) {
438 self.tim.set_auto_reload(period.ticks() - 1).unwrap();
439 }
440}