diff options
| author | Ben Gamari <[email protected]> | 2022-07-10 17:07:18 -0400 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-07-23 15:57:13 +0200 |
| commit | 042e11960e6018082801d4f268bbe0bdc62edfac (patch) | |
| tree | 09054d6a5f593717df6a4d5031a03a54b35a0ad0 | |
| parent | 709df0dc1dfff577fb79bbc2f67ea84670072456 (diff) | |
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.
| -rw-r--r-- | embassy-stm32/src/pwm/simple_pwm.rs | 100 |
1 files changed, 43 insertions, 57 deletions
diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs index 7b2cdbc01..5fcd1ed09 100644 --- a/embassy-stm32/src/pwm/simple_pwm.rs +++ b/embassy-stm32/src/pwm/simple_pwm.rs | |||
| @@ -1,85 +1,71 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 2 | |||
| 1 | use embassy_hal_common::{into_ref, PeripheralRef}; | 3 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 2 | 4 | ||
| 3 | use super::*; | 5 | use super::*; |
| 4 | #[allow(unused_imports)] | 6 | #[allow(unused_imports)] |
| 5 | use crate::gpio::sealed::{AFType, Pin}; | 7 | use crate::gpio::sealed::{AFType, Pin}; |
| 8 | use crate::gpio::AnyPin; | ||
| 6 | use crate::time::Hertz; | 9 | use crate::time::Hertz; |
| 7 | use crate::Peripheral; | 10 | use crate::Peripheral; |
| 8 | 11 | ||
| 9 | pub struct SimplePwm<'d, T> { | 12 | pub struct Ch1; |
| 10 | inner: PeripheralRef<'d, T>, | 13 | pub struct Ch2; |
| 14 | pub struct Ch3; | ||
| 15 | pub struct Ch4; | ||
| 16 | |||
| 17 | pub struct PwmPin<'d, Perip, Channel> { | ||
| 18 | _pin: PeripheralRef<'d, AnyPin>, | ||
| 19 | phantom: PhantomData<(Perip, Channel)>, | ||
| 11 | } | 20 | } |
| 12 | 21 | ||
| 13 | macro_rules! config_pins { | 22 | macro_rules! channel_impl { |
| 14 | ($($pin:ident),*) => { | 23 | ($channel:ident, $pin_trait:ident) => { |
| 15 | into_ref!($($pin),*); | 24 | impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { |
| 16 | // NOTE(unsafe) Exclusive access to the registers | 25 | pub fn new(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self { |
| 17 | critical_section::with(|_| unsafe { | 26 | into_ref!(pin); |
| 18 | $( | 27 | critical_section::with(|_| unsafe { |
| 19 | $pin.set_low(); | 28 | pin.set_low(); |
| 20 | $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); | 29 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); |
| 21 | #[cfg(gpio_v2)] | 30 | #[cfg(gpio_v2)] |
| 22 | $pin.set_speed(crate::gpio::Speed::VeryHigh); | 31 | pin.set_speed(crate::gpio::Speed::VeryHigh); |
| 23 | )* | 32 | }); |
| 24 | }) | 33 | PwmPin { |
| 34 | _pin: pin.map_into(), | ||
| 35 | phantom: PhantomData, | ||
| 36 | } | ||
| 37 | } | ||
| 38 | } | ||
| 25 | }; | 39 | }; |
| 26 | } | 40 | } |
| 27 | 41 | ||
| 28 | impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | 42 | channel_impl!(Ch1, Channel1Pin); |
| 29 | pub fn new_1ch( | 43 | channel_impl!(Ch2, Channel2Pin); |
| 30 | tim: impl Peripheral<P = T> + 'd, | 44 | channel_impl!(Ch3, Channel3Pin); |
| 31 | ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, | 45 | channel_impl!(Ch4, Channel4Pin); |
| 32 | freq: Hertz, | ||
| 33 | ) -> Self { | ||
| 34 | Self::new_inner(tim, freq, move || { | ||
| 35 | config_pins!(ch1); | ||
| 36 | }) | ||
| 37 | } | ||
| 38 | |||
| 39 | pub fn new_2ch( | ||
| 40 | tim: impl Peripheral<P = T> + 'd, | ||
| 41 | ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, | ||
| 42 | ch2: impl Peripheral<P = impl Channel2Pin<T>> + 'd, | ||
| 43 | freq: Hertz, | ||
| 44 | ) -> Self { | ||
| 45 | Self::new_inner(tim, freq, move || { | ||
| 46 | config_pins!(ch1, ch2); | ||
| 47 | }) | ||
| 48 | } | ||
| 49 | 46 | ||
| 50 | pub fn new_3ch( | 47 | pub struct SimplePwm<'d, T> { |
| 51 | tim: impl Peripheral<P = T> + 'd, | 48 | inner: PeripheralRef<'d, T>, |
| 52 | ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, | 49 | } |
| 53 | ch2: impl Peripheral<P = impl Channel2Pin<T>> + 'd, | ||
| 54 | ch3: impl Peripheral<P = impl Channel3Pin<T>> + 'd, | ||
| 55 | freq: Hertz, | ||
| 56 | ) -> Self { | ||
| 57 | Self::new_inner(tim, freq, move || { | ||
| 58 | config_pins!(ch1, ch2, ch3); | ||
| 59 | }) | ||
| 60 | } | ||
| 61 | 50 | ||
| 62 | pub fn new_4ch( | 51 | impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { |
| 52 | pub fn new( | ||
| 63 | tim: impl Peripheral<P = T> + 'd, | 53 | tim: impl Peripheral<P = T> + 'd, |
| 64 | ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, | 54 | _ch1: Option<PwmPin<T, Ch1>>, |
| 65 | ch2: impl Peripheral<P = impl Channel2Pin<T>> + 'd, | 55 | _ch2: Option<PwmPin<T, Ch2>>, |
| 66 | ch3: impl Peripheral<P = impl Channel3Pin<T>> + 'd, | 56 | _ch3: Option<PwmPin<T, Ch3>>, |
| 67 | ch4: impl Peripheral<P = impl Channel4Pin<T>> + 'd, | 57 | _ch4: Option<PwmPin<T, Ch4>>, |
| 68 | freq: Hertz, | 58 | freq: Hertz, |
| 69 | ) -> Self { | 59 | ) -> Self { |
| 70 | Self::new_inner(tim, freq, move || { | 60 | Self::new_inner(tim, freq) |
| 71 | config_pins!(ch1, ch2, ch3, ch4); | ||
| 72 | }) | ||
| 73 | } | 61 | } |
| 74 | 62 | ||
| 75 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, configure_pins: impl FnOnce()) -> Self { | 63 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz) -> Self { |
| 76 | into_ref!(tim); | 64 | into_ref!(tim); |
| 77 | 65 | ||
| 78 | T::enable(); | 66 | T::enable(); |
| 79 | <T as crate::rcc::sealed::RccPeripheral>::reset(); | 67 | <T as crate::rcc::sealed::RccPeripheral>::reset(); |
| 80 | 68 | ||
| 81 | configure_pins(); | ||
| 82 | |||
| 83 | let mut this = Self { inner: tim }; | 69 | let mut this = Self { inner: tim }; |
| 84 | 70 | ||
| 85 | this.inner.set_frequency(freq); | 71 | this.inner.set_frequency(freq); |
