diff options
| -rw-r--r-- | embassy-stm32/src/timer/simple_pwm.rs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index b7771bd64..f94ed1be5 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs | |||
| @@ -51,6 +51,96 @@ channel_impl!(new_ch2, Ch2, Channel2Pin); | |||
| 51 | channel_impl!(new_ch3, Ch3, Channel3Pin); | 51 | channel_impl!(new_ch3, Ch3, Channel3Pin); |
| 52 | channel_impl!(new_ch4, Ch4, Channel4Pin); | 52 | channel_impl!(new_ch4, Ch4, Channel4Pin); |
| 53 | 53 | ||
| 54 | /// A single channel of a pwm, obtained from [`SimplePwm::split`]. | ||
| 55 | /// | ||
| 56 | /// It is not possible to change the pwm frequency because | ||
| 57 | /// the frequency configuration is shared with all four channels. | ||
| 58 | pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> { | ||
| 59 | timer: &'d Timer<'d, T>, | ||
| 60 | channel: Channel, | ||
| 61 | } | ||
| 62 | |||
| 63 | // TODO: check for RMW races | ||
| 64 | impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> { | ||
| 65 | /// Enable the given channel. | ||
| 66 | pub fn enable(&mut self) { | ||
| 67 | self.timer.enable_channel(self.channel, true); | ||
| 68 | } | ||
| 69 | |||
| 70 | /// Disable the given channel. | ||
| 71 | pub fn disable(&mut self) { | ||
| 72 | self.timer.enable_channel(self.channel, false); | ||
| 73 | } | ||
| 74 | |||
| 75 | /// Check whether given channel is enabled | ||
| 76 | pub fn is_enabled(&self) -> bool { | ||
| 77 | self.timer.get_channel_enable_state(self.channel) | ||
| 78 | } | ||
| 79 | |||
| 80 | /// Get max duty value. | ||
| 81 | /// | ||
| 82 | /// This value depends on the configured frequency and the timer's clock rate from RCC. | ||
| 83 | pub fn get_max_duty(&self) -> u32 { | ||
| 84 | self.timer.get_max_compare_value() + 1 | ||
| 85 | } | ||
| 86 | |||
| 87 | /// Set the duty for a given channel. | ||
| 88 | /// | ||
| 89 | /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. | ||
| 90 | pub fn set_duty(&mut self, duty: u32) { | ||
| 91 | assert!(duty <= self.get_max_duty()); | ||
| 92 | self.timer.set_compare_value(self.channel, duty) | ||
| 93 | } | ||
| 94 | |||
| 95 | /// Get the duty for a given channel. | ||
| 96 | /// | ||
| 97 | /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. | ||
| 98 | pub fn get_duty(&self) -> u32 { | ||
| 99 | self.timer.get_compare_value(self.channel) | ||
| 100 | } | ||
| 101 | |||
| 102 | /// Set the output polarity for a given channel. | ||
| 103 | pub fn set_polarity(&mut self, polarity: OutputPolarity) { | ||
| 104 | self.timer.set_output_polarity(self.channel, polarity); | ||
| 105 | } | ||
| 106 | |||
| 107 | /// Set the output compare mode for a given channel. | ||
| 108 | pub fn set_output_compare_mode(&mut self, mode: OutputCompareMode) { | ||
| 109 | self.timer.set_output_compare_mode(self.channel, mode); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | /// A group of four [`SimplePwmChannel`]s, obtained from [`SimplePwm::split`]. | ||
| 114 | pub struct SimplePwmChannels<'d, T: GeneralInstance4Channel> { | ||
| 115 | /// Channel 1 | ||
| 116 | pub ch1: SimplePwmChannel<'d, T>, | ||
| 117 | /// Channel 2 | ||
| 118 | pub ch2: SimplePwmChannel<'d, T>, | ||
| 119 | /// Channel 3 | ||
| 120 | pub ch3: SimplePwmChannel<'d, T>, | ||
| 121 | /// Channel 4 | ||
| 122 | pub ch4: SimplePwmChannel<'d, T>, | ||
| 123 | } | ||
| 124 | |||
| 125 | impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> { | ||
| 126 | type Error = core::convert::Infallible; | ||
| 127 | } | ||
| 128 | |||
| 129 | impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for SimplePwmChannel<'d, T> { | ||
| 130 | fn max_duty_cycle(&self) -> u16 { | ||
| 131 | // TODO: panics if CCR is 0xFFFF | ||
| 132 | // TODO: rename get_max_duty to max_duty_cycle | ||
| 133 | unwrap!(self.get_max_duty().try_into()) | ||
| 134 | } | ||
| 135 | |||
| 136 | fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> { | ||
| 137 | self.set_duty(duty.into()); | ||
| 138 | Ok(()) | ||
| 139 | } | ||
| 140 | |||
| 141 | // TODO: default methods? | ||
| 142 | } | ||
| 143 | |||
| 54 | /// Simple PWM driver. | 144 | /// Simple PWM driver. |
| 55 | pub struct SimplePwm<'d, T: GeneralInstance4Channel> { | 145 | pub struct SimplePwm<'d, T: GeneralInstance4Channel> { |
| 56 | inner: Timer<'d, T>, | 146 | inner: Timer<'d, T>, |
| @@ -89,6 +179,28 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { | |||
| 89 | this | 179 | this |
| 90 | } | 180 | } |
| 91 | 181 | ||
| 182 | fn channel(&self, channel: Channel) -> SimplePwmChannel<'_, T> { | ||
| 183 | SimplePwmChannel { | ||
| 184 | timer: &self.inner, | ||
| 185 | channel, | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | /// Splits a [`SimplePwm`] into four pwm channels. | ||
| 190 | /// | ||
| 191 | /// This returns all four channels, including channels that | ||
| 192 | /// aren't configured with a [`PwmPin`]. | ||
| 193 | // TODO: I hate the name "split" | ||
| 194 | pub fn split(&mut self) -> SimplePwmChannels<'_, T> { | ||
| 195 | // TODO: pre-enable channels? | ||
| 196 | SimplePwmChannels { | ||
| 197 | ch1: self.channel(Channel::Ch1), | ||
| 198 | ch2: self.channel(Channel::Ch2), | ||
| 199 | ch3: self.channel(Channel::Ch3), | ||
| 200 | ch4: self.channel(Channel::Ch4), | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 92 | /// Enable the given channel. | 204 | /// Enable the given channel. |
| 93 | pub fn enable(&mut self, channel: Channel) { | 205 | pub fn enable(&mut self, channel: Channel) { |
| 94 | self.inner.enable_channel(channel, true); | 206 | self.inner.enable_channel(channel, true); |
