1use core::marker::Copy;
57use core::marker::PhantomData;
58
59use crate::hal;
60#[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity",))]
61use crate::pac::TIM1;
62#[cfg(feature = "medium")]
63use crate::pac::TIM4;
64use crate::pac::{TIM2, TIM3};
65use cast::{u16, u32};
66
67use crate::afio::MAPR;
68use crate::bb;
69use crate::gpio::{self, Alternate, PushPull};
70use crate::time::Hertz;
71use crate::time::U32Ext;
72use crate::timer::Timer;
73
74pub trait Pins<REMAP, P> {
75 const C1: bool = false;
76 const C2: bool = false;
77 const C3: bool = false;
78 const C4: bool = false;
79 type Channels;
80
81 fn check_used(c: Channel) -> Channel {
82 if (c == Channel::C1 && Self::C1)
83 || (c == Channel::C2 && Self::C2)
84 || (c == Channel::C3 && Self::C3)
85 || (c == Channel::C4 && Self::C4)
86 {
87 c
88 } else {
89 panic!("Unused channel")
90 }
91 }
92
93 fn split() -> Self::Channels;
94}
95
96#[derive(Clone, Copy, PartialEq)]
97pub enum Channel {
98 C1,
99 C2,
100 C3,
101 C4,
102}
103
104use crate::timer::sealed::{Ch1, Ch2, Ch3, Ch4, Remap};
105macro_rules! pins_impl {
106 ( $( ( $($PINX:ident),+ ), ( $($TRAIT:ident),+ ), ( $($ENCHX:ident),+ ); )+ ) => {
107 $(
108 #[allow(unused_parens)]
109 impl<TIM, REMAP, $($PINX,)+> Pins<REMAP, ($($ENCHX),+)> for ($($PINX),+)
110 where
111 REMAP: Remap<Periph = TIM>,
112 $($PINX: $TRAIT<REMAP> + gpio::Mode<Alternate<PushPull>>,)+
113 {
114 $(const $ENCHX: bool = true;)+
115 type Channels = ($(PwmChannel<TIM, $ENCHX>),+);
116 fn split() -> Self::Channels {
117 ($(PwmChannel::<TIM, $ENCHX> { _channel: PhantomData, _tim: PhantomData }),+)
118 }
119 }
120 )+
121 };
122}
123
124pins_impl!(
125 (P1, P2, P3, P4), (Ch1, Ch2, Ch3, Ch4), (C1, C2, C3, C4);
126 (P2, P3, P4), (Ch2, Ch3, Ch4), (C2, C3, C4);
127 (P1, P3, P4), (Ch1, Ch3, Ch4), (C1, C3, C4);
128 (P1, P2, P4), (Ch1, Ch2, Ch4), (C1, C2, C4);
129 (P1, P2, P3), (Ch1, Ch2, Ch3), (C1, C2, C3);
130 (P3, P4), (Ch3, Ch4), (C3, C4);
131 (P2, P4), (Ch2, Ch4), (C2, C4);
132 (P2, P3), (Ch2, Ch3), (C2, C3);
133 (P1, P4), (Ch1, Ch4), (C1, C4);
134 (P1, P3), (Ch1, Ch3), (C1, C3);
135 (P1, P2), (Ch1, Ch2), (C1, C2);
136 (P1), (Ch1), (C1);
137 (P2), (Ch2), (C2);
138 (P3), (Ch3), (C3);
139 (P4), (Ch4), (C4);
140);
141
142#[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity",))]
143impl Timer<TIM1> {
144 pub fn pwm<REMAP, P, PINS, T>(
145 self,
146 _pins: PINS,
147 mapr: &mut MAPR,
148 freq: T,
149 ) -> Pwm<TIM1, REMAP, P, PINS>
150 where
151 REMAP: Remap<Periph = TIM1>,
152 PINS: Pins<REMAP, P>,
153 T: Into<Hertz>,
154 {
155 mapr.modify_mapr(|_, w| unsafe { w.tim1_remap().bits(REMAP::REMAP) });
156
157 self.tim.bdtr.modify(|_, w| w.aoe().set_bit());
160
161 let Self { tim, clk } = self;
162 tim1(tim, _pins, freq.into(), clk)
163 }
164}
165
166impl Timer<TIM2> {
167 pub fn pwm<REMAP, P, PINS, T>(
168 self,
169 _pins: PINS,
170 mapr: &mut MAPR,
171 freq: T,
172 ) -> Pwm<TIM2, REMAP, P, PINS>
173 where
174 REMAP: Remap<Periph = TIM2>,
175 PINS: Pins<REMAP, P>,
176 T: Into<Hertz>,
177 {
178 mapr.modify_mapr(|_, w| unsafe { w.tim2_remap().bits(REMAP::REMAP) });
179
180 let Self { tim, clk } = self;
181 tim2(tim, _pins, freq.into(), clk)
182 }
183}
184
185impl Timer<TIM3> {
186 pub fn pwm<REMAP, P, PINS, T>(
187 self,
188 _pins: PINS,
189 mapr: &mut MAPR,
190 freq: T,
191 ) -> Pwm<TIM3, REMAP, P, PINS>
192 where
193 REMAP: Remap<Periph = TIM3>,
194 PINS: Pins<REMAP, P>,
195 T: Into<Hertz>,
196 {
197 mapr.modify_mapr(|_, w| unsafe { w.tim3_remap().bits(REMAP::REMAP) });
198
199 let Self { tim, clk } = self;
200 tim3(tim, _pins, freq.into(), clk)
201 }
202}
203
204#[cfg(feature = "medium")]
205impl Timer<TIM4> {
206 pub fn pwm<REMAP, P, PINS, T>(
207 self,
208 _pins: PINS,
209 mapr: &mut MAPR,
210 freq: T,
211 ) -> Pwm<TIM4, REMAP, P, PINS>
212 where
213 REMAP: Remap<Periph = TIM4>,
214 PINS: Pins<REMAP, P>,
215 T: Into<Hertz>,
216 {
217 mapr.modify_mapr(|_, w| w.tim4_remap().bit(REMAP::REMAP == 1));
218
219 let Self { tim, clk } = self;
220 tim4(tim, _pins, freq.into(), clk)
221 }
222}
223
224pub struct Pwm<TIM, REMAP, P, PINS>
225where
226 REMAP: Remap<Periph = TIM>,
227 PINS: Pins<REMAP, P>,
228{
229 clk: Hertz,
230 _pins: PhantomData<(TIM, REMAP, P, PINS)>,
231}
232
233impl<TIM, REMAP, P, PINS> Pwm<TIM, REMAP, P, PINS>
234where
235 REMAP: Remap<Periph = TIM>,
236 PINS: Pins<REMAP, P>,
237{
238 pub fn split(self) -> PINS::Channels {
239 PINS::split()
240 }
241}
242
243pub struct PwmChannel<TIM, CHANNEL> {
244 _channel: PhantomData<CHANNEL>,
245 _tim: PhantomData<TIM>,
246}
247
248pub struct C1;
249pub struct C2;
250pub struct C3;
251pub struct C4;
252
253macro_rules! hal {
254 ($($TIMX:ident: ($timX:ident),)+) => {
255 $(
256 fn $timX<REMAP, P, PINS>(
257 tim: $TIMX,
258 _pins: PINS,
259 freq: Hertz,
260 clk: Hertz,
261 ) -> Pwm<$TIMX, REMAP, P, PINS>
262 where
263 REMAP: Remap<Periph = $TIMX>,
264 PINS: Pins<REMAP, P>,
265 {
266 if PINS::C1 {
267 tim.ccmr1_output()
268 .modify(|_, w| w.oc1pe().set_bit().oc1m().pwm_mode1() );
269 }
270
271 if PINS::C2 {
272 tim.ccmr1_output()
273 .modify(|_, w| w.oc2pe().set_bit().oc2m().pwm_mode1() );
274 }
275
276 if PINS::C3 {
277 tim.ccmr2_output()
278 .modify(|_, w| w.oc3pe().set_bit().oc3m().pwm_mode1() );
279 }
280
281 if PINS::C4 {
282 tim.ccmr2_output()
283 .modify(|_, w| w.oc4pe().set_bit().oc4m().pwm_mode1() );
284 }
285 let ticks = clk.0 / freq.0;
286 let psc = u16(ticks / (1 << 16)).unwrap();
287 tim.psc.write(|w| w.psc().bits(psc) );
288 let arr = u16(ticks / u32(psc + 1)).unwrap();
289 tim.arr.write(|w| w.arr().bits(arr));
290
291 tim.cr1.modify(|_, w| w.urs().set_bit());
294 tim.egr.write(|w| w.ug().set_bit());
295 tim.cr1.modify(|_, w| w.urs().clear_bit());
296
297 tim.cr1.write(|w|
298 w.cms()
299 .bits(0b00)
300 .dir()
301 .clear_bit()
302 .opm()
303 .clear_bit()
304 .cen()
305 .set_bit()
306 );
307
308 Pwm {
309 clk,
310 _pins: PhantomData
311 }
312 }
313
314 impl<REMAP, P, PINS> hal::Pwm for Pwm<$TIMX, REMAP, P, PINS> where
328 REMAP: Remap<Periph = $TIMX>,
329 PINS: Pins<REMAP, P>,
330 {
331 type Channel = Channel;
332 type Duty = u16;
333 type Time = Hertz;
334
335 fn enable(&mut self, channel: Self::Channel) {
336 match PINS::check_used(channel) {
337 Channel::C1 => unsafe { bb::set(&(*$TIMX::ptr()).ccer, 0) },
338 Channel::C2 => unsafe { bb::set(&(*$TIMX::ptr()).ccer, 4) },
339 Channel::C3 => unsafe { bb::set(&(*$TIMX::ptr()).ccer, 8) },
340 Channel::C4 => unsafe { bb::set(&(*$TIMX::ptr()).ccer, 12) }
341 }
342 }
343
344 fn disable(&mut self, channel: Self::Channel) {
345 match PINS::check_used(channel) {
346 Channel::C1 => unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 0) },
347 Channel::C2 => unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 4) },
348 Channel::C3 => unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 8) },
349 Channel::C4 => unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 12) },
350 }
351 }
352
353 fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
354 match PINS::check_used(channel) {
355 Channel::C1 => unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() },
356 Channel::C2 => unsafe { (*$TIMX::ptr()).ccr2.read().ccr().bits() },
357 Channel::C3 => unsafe { (*$TIMX::ptr()).ccr3.read().ccr().bits() },
358 Channel::C4 => unsafe { (*$TIMX::ptr()).ccr4.read().ccr().bits() },
359 }
360 }
361
362 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
363 match PINS::check_used(channel) {
364 Channel::C1 => unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty)) },
365 Channel::C2 => unsafe { (*$TIMX::ptr()).ccr2.write(|w| w.ccr().bits(duty)) },
366 Channel::C3 => unsafe { (*$TIMX::ptr()).ccr3.write(|w| w.ccr().bits(duty)) },
367 Channel::C4 => unsafe { (*$TIMX::ptr()).ccr4.write(|w| w.ccr().bits(duty)) },
368 }
369 }
370
371 fn get_max_duty(&self) -> Self::Duty {
372 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() }
373 }
374
375 fn get_period(&self) -> Self::Time {
376 let clk = self.clk;
377 let psc: u16 = unsafe{(*$TIMX::ptr()).psc.read().psc().bits()};
378 let arr: u16 = unsafe{(*$TIMX::ptr()).arr.read().arr().bits()};
379
380 (clk.0 / u32(psc * arr)).hz()
382 }
383
384 fn set_period<T>(&mut self, period: T) where
385 T: Into<Self::Time> {
386 let clk = self.clk;
387
388 let ticks = clk.0 / period.into().0;
389 let psc = u16(ticks / (1 << 16)).unwrap();
390 let arr = u16(ticks / u32(psc + 1)).unwrap();
391 unsafe {
392 (*$TIMX::ptr()).psc.write(|w| w.psc().bits(psc));
393 (*$TIMX::ptr()).arr.write(|w| w.arr().bits(arr));
394 }
395 }
396 }
397
398 impl hal::PwmPin for PwmChannel<$TIMX, C1> {
399 type Duty = u16;
400
401 fn disable(&mut self) {
402 unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 0) }
403 }
404
405 fn enable(&mut self) {
406 unsafe { bb::set(&(*$TIMX::ptr()).ccer, 0) }
407 }
408
409 fn get_duty(&self) -> u16 {
410 unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() }
411 }
412
413 fn get_max_duty(&self) -> u16 {
414 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() }
415 }
416
417 fn set_duty(&mut self, duty: u16) {
418 unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty)) }
419 }
420 }
421
422 impl hal::PwmPin for PwmChannel<$TIMX, C2> {
423 type Duty = u16;
424
425 fn disable(&mut self) {
426 unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 4) }
427 }
428
429 fn enable(&mut self) {
430 unsafe { bb::set(&(*$TIMX::ptr()).ccer, 4) }
431 }
432
433 fn get_duty(&self) -> u16 {
434 unsafe { (*$TIMX::ptr()).ccr2.read().ccr().bits() }
435 }
436
437 fn get_max_duty(&self) -> u16 {
438 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() }
439 }
440
441 fn set_duty(&mut self, duty: u16) {
442 unsafe { (*$TIMX::ptr()).ccr2.write(|w| w.ccr().bits(duty)) }
443 }
444 }
445
446 impl hal::PwmPin for PwmChannel<$TIMX, C3> {
447 type Duty = u16;
448
449 fn disable(&mut self) {
450 unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 8) }
451 }
452
453 fn enable(&mut self) {
454 unsafe { bb::set(&(*$TIMX::ptr()).ccer, 8) }
455 }
456
457 fn get_duty(&self) -> u16 {
458 unsafe { (*$TIMX::ptr()).ccr3.read().ccr().bits() }
459 }
460
461 fn get_max_duty(&self) -> u16 {
462 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() }
463 }
464
465 fn set_duty(&mut self, duty: u16) {
466 unsafe { (*$TIMX::ptr()).ccr3.write(|w| w.ccr().bits(duty)) }
467 }
468 }
469
470 impl hal::PwmPin for PwmChannel<$TIMX, C4> {
471 type Duty = u16;
472
473 fn disable(&mut self) {
474 unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 12) }
475 }
476
477 fn enable(&mut self) {
478 unsafe { bb::set(&(*$TIMX::ptr()).ccer, 12) }
479 }
480
481 fn get_duty(&self) -> u16 {
482 unsafe { (*$TIMX::ptr()).ccr4.read().ccr().bits() }
483 }
484
485 fn get_max_duty(&self) -> u16 {
486 unsafe { (*$TIMX::ptr()).arr.read().arr().bits() }
487 }
488
489 fn set_duty(&mut self, duty: u16) {
490 unsafe { (*$TIMX::ptr()).ccr4.write(|w| w.ccr().bits(duty)) }
491 }
492 }
493 )+
494 }
495}
496
497#[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity",))]
498hal! {
499 TIM1: (tim1),
500}
501
502hal! {
503 TIM2: (tim2),
504 TIM3: (tim3),
505}
506
507#[cfg(feature = "medium")]
508hal! {
509 TIM4: (tim4),
510}