From 042e11960e6018082801d4f268bbe0bdc62edfac Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sun, 10 Jul 2022 17:07:18 -0400 Subject: [PATCH] embassy-stm32/pwm: Generalize channel selection 550da471be7b56927b50b5955a6de0916ebe6b1f previously refactored the STM32 PWM logic in such a way to preclude use of non-contiguous channels (e.g. channel 2 but not channel 1). Refactor it yet again to yet again allow this sort of usage. --- embassy-stm32/src/pwm/simple_pwm.rs | 104 ++++++++++++---------------- 1 file changed, 45 insertions(+), 59 deletions(-) diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs index 7b2cdbc0..5fcd1ed0 100644 --- a/embassy-stm32/src/pwm/simple_pwm.rs +++ b/embassy-stm32/src/pwm/simple_pwm.rs @@ -1,85 +1,71 @@ +use core::marker::PhantomData; + use embassy_hal_common::{into_ref, PeripheralRef}; use super::*; #[allow(unused_imports)] use crate::gpio::sealed::{AFType, Pin}; +use crate::gpio::AnyPin; use crate::time::Hertz; use crate::Peripheral; +pub struct Ch1; +pub struct Ch2; +pub struct Ch3; +pub struct Ch4; + +pub struct PwmPin<'d, Perip, Channel> { + _pin: PeripheralRef<'d, AnyPin>, + phantom: PhantomData<(Perip, Channel)>, +} + +macro_rules! channel_impl { + ($channel:ident, $pin_trait:ident) => { + impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { + pub fn new(pin: impl Peripheral

> + 'd) -> Self { + into_ref!(pin); + critical_section::with(|_| unsafe { + pin.set_low(); + pin.set_as_af(pin.af_num(), AFType::OutputPushPull); + #[cfg(gpio_v2)] + pin.set_speed(crate::gpio::Speed::VeryHigh); + }); + PwmPin { + _pin: pin.map_into(), + phantom: PhantomData, + } + } + } + }; +} + +channel_impl!(Ch1, Channel1Pin); +channel_impl!(Ch2, Channel2Pin); +channel_impl!(Ch3, Channel3Pin); +channel_impl!(Ch4, Channel4Pin); + pub struct SimplePwm<'d, T> { inner: PeripheralRef<'d, T>, } -macro_rules! config_pins { - ($($pin:ident),*) => { - into_ref!($($pin),*); - // NOTE(unsafe) Exclusive access to the registers - critical_section::with(|_| unsafe { - $( - $pin.set_low(); - $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); - #[cfg(gpio_v2)] - $pin.set_speed(crate::gpio::Speed::VeryHigh); - )* - }) - }; -} - impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { - pub fn new_1ch( + pub fn new( tim: impl Peripheral

+ 'd, - ch1: impl Peripheral

> + 'd, + _ch1: Option>, + _ch2: Option>, + _ch3: Option>, + _ch4: Option>, freq: Hertz, ) -> Self { - Self::new_inner(tim, freq, move || { - config_pins!(ch1); - }) + Self::new_inner(tim, freq) } - pub fn new_2ch( - tim: impl Peripheral

+ 'd, - ch1: impl Peripheral

> + 'd, - ch2: impl Peripheral

> + 'd, - freq: Hertz, - ) -> Self { - Self::new_inner(tim, freq, move || { - config_pins!(ch1, ch2); - }) - } - - pub fn new_3ch( - tim: impl Peripheral

+ 'd, - ch1: impl Peripheral

> + 'd, - ch2: impl Peripheral

> + 'd, - ch3: impl Peripheral

> + 'd, - freq: Hertz, - ) -> Self { - Self::new_inner(tim, freq, move || { - config_pins!(ch1, ch2, ch3); - }) - } - - pub fn new_4ch( - tim: impl Peripheral

+ 'd, - ch1: impl Peripheral

> + 'd, - ch2: impl Peripheral

> + 'd, - ch3: impl Peripheral

> + 'd, - ch4: impl Peripheral

> + 'd, - freq: Hertz, - ) -> Self { - Self::new_inner(tim, freq, move || { - config_pins!(ch1, ch2, ch3, ch4); - }) - } - - fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, configure_pins: impl FnOnce()) -> Self { + fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz) -> Self { into_ref!(tim); T::enable(); ::reset(); - configure_pins(); - let mut this = Self { inner: tim }; this.inner.set_frequency(freq);