aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs119
1 files changed, 63 insertions, 56 deletions
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index f94ed1be5..7179a7a59 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -51,7 +51,8 @@ channel_impl!(new_ch2, Ch2, Channel2Pin);
51channel_impl!(new_ch3, Ch3, Channel3Pin); 51channel_impl!(new_ch3, Ch3, Channel3Pin);
52channel_impl!(new_ch4, Ch4, Channel4Pin); 52channel_impl!(new_ch4, Ch4, Channel4Pin);
53 53
54/// A single channel of a pwm, obtained from [`SimplePwm::split`]. 54/// A single channel of a pwm, obtained from [`SimplePwm::split`],
55/// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc.
55/// 56///
56/// It is not possible to change the pwm frequency because 57/// It is not possible to change the pwm frequency because
57/// the frequency configuration is shared with all four channels. 58/// the frequency configuration is shared with all four channels.
@@ -179,13 +180,52 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
179 this 180 this
180 } 181 }
181 182
182 fn channel(&self, channel: Channel) -> SimplePwmChannel<'_, T> { 183 /// Get a single channel
184 ///
185 /// If you need to use multiple channels, use [`Self::split`].
186 pub fn channel(&mut self, channel: Channel) -> SimplePwmChannel<'_, T> {
183 SimplePwmChannel { 187 SimplePwmChannel {
184 timer: &self.inner, 188 timer: &self.inner,
185 channel, 189 channel,
186 } 190 }
187 } 191 }
188 192
193 /// Channel 1
194 ///
195 /// This is just a convenience wrapper around [`Self::channel`].
196 ///
197 /// If you need to use multiple channels, use [`Self::split`].
198 pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> {
199 self.channel(Channel::Ch1)
200 }
201
202 /// Channel 2
203 ///
204 /// This is just a convenience wrapper around [`Self::channel`].
205 ///
206 /// If you need to use multiple channels, use [`Self::split`].
207 pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> {
208 self.channel(Channel::Ch2)
209 }
210
211 /// Channel 3
212 ///
213 /// This is just a convenience wrapper around [`Self::channel`].
214 ///
215 /// If you need to use multiple channels, use [`Self::split`].
216 pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> {
217 self.channel(Channel::Ch3)
218 }
219
220 /// Channel 4
221 ///
222 /// This is just a convenience wrapper around [`Self::channel`].
223 ///
224 /// If you need to use multiple channels, use [`Self::split`].
225 pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> {
226 self.channel(Channel::Ch4)
227 }
228
189 /// Splits a [`SimplePwm`] into four pwm channels. 229 /// Splits a [`SimplePwm`] into four pwm channels.
190 /// 230 ///
191 /// This returns all four channels, including channels that 231 /// This returns all four channels, including channels that
@@ -193,27 +233,19 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
193 // TODO: I hate the name "split" 233 // TODO: I hate the name "split"
194 pub fn split(&mut self) -> SimplePwmChannels<'_, T> { 234 pub fn split(&mut self) -> SimplePwmChannels<'_, T> {
195 // TODO: pre-enable channels? 235 // 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
204 /// Enable the given channel.
205 pub fn enable(&mut self, channel: Channel) {
206 self.inner.enable_channel(channel, true);
207 }
208 236
209 /// Disable the given channel. 237 // we can't use self.channel() because that takes &mut self
210 pub fn disable(&mut self, channel: Channel) { 238 let ch = |channel| SimplePwmChannel {
211 self.inner.enable_channel(channel, false); 239 timer: &self.inner,
212 } 240 channel,
241 };
213 242
214 /// Check whether given channel is enabled 243 SimplePwmChannels {
215 pub fn is_enabled(&self, channel: Channel) -> bool { 244 ch1: ch(Channel::Ch1),
216 self.inner.get_channel_enable_state(channel) 245 ch2: ch(Channel::Ch2),
246 ch3: ch(Channel::Ch3),
247 ch4: ch(Channel::Ch4),
248 }
217 } 249 }
218 250
219 /// Set PWM frequency. 251 /// Set PWM frequency.
@@ -236,31 +268,6 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
236 self.inner.get_max_compare_value() + 1 268 self.inner.get_max_compare_value() + 1
237 } 269 }
238 270
239 /// Set the duty for a given channel.
240 ///
241 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
242 pub fn set_duty(&mut self, channel: Channel, duty: u32) {
243 assert!(duty <= self.get_max_duty());
244 self.inner.set_compare_value(channel, duty)
245 }
246
247 /// Get the duty for a given channel.
248 ///
249 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
250 pub fn get_duty(&self, channel: Channel) -> u32 {
251 self.inner.get_compare_value(channel)
252 }
253
254 /// Set the output polarity for a given channel.
255 pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
256 self.inner.set_output_polarity(channel, polarity);
257 }
258
259 /// Set the output compare mode for a given channel.
260 pub fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
261 self.inner.set_output_compare_mode(channel, mode);
262 }
263
264 /// Generate a sequence of PWM waveform 271 /// Generate a sequence of PWM waveform
265 /// 272 ///
266 /// Note: 273 /// Note:
@@ -276,8 +283,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
276 #[allow(clippy::let_unit_value)] // eg. stm32f334 283 #[allow(clippy::let_unit_value)] // eg. stm32f334
277 let req = dma.request(); 284 let req = dma.request();
278 285
279 let original_duty_state = self.get_duty(channel); 286 let original_duty_state = self.channel(channel).get_duty();
280 let original_enable_state = self.is_enabled(channel); 287 let original_enable_state = self.channel(channel).is_enabled();
281 let original_update_dma_state = self.inner.get_update_dma_state(); 288 let original_update_dma_state = self.inner.get_update_dma_state();
282 289
283 if !original_update_dma_state { 290 if !original_update_dma_state {
@@ -285,7 +292,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
285 } 292 }
286 293
287 if !original_enable_state { 294 if !original_enable_state {
288 self.enable(channel); 295 self.channel(channel).enable();
289 } 296 }
290 297
291 unsafe { 298 unsafe {
@@ -313,10 +320,10 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
313 320
314 // restore output compare state 321 // restore output compare state
315 if !original_enable_state { 322 if !original_enable_state {
316 self.disable(channel); 323 self.channel(channel).disable();
317 } 324 }
318 325
319 self.set_duty(channel, original_duty_state); 326 self.channel(channel).set_duty(original_duty_state);
320 327
321 // Since DMA is closed before timer update event trigger DMA is turn off, 328 // Since DMA is closed before timer update event trigger DMA is turn off,
322 // this can almost always trigger a DMA FIFO error. 329 // this can almost always trigger a DMA FIFO error.
@@ -346,8 +353,8 @@ macro_rules! impl_waveform_chx {
346 353
347 let cc_channel = Channel::$cc_ch; 354 let cc_channel = Channel::$cc_ch;
348 355
349 let original_duty_state = self.get_duty(cc_channel); 356 let original_duty_state = self.channel(cc_channel).get_duty();
350 let original_enable_state = self.is_enabled(cc_channel); 357 let original_enable_state = self.channel(cc_channel).is_enabled();
351 let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ONUPDATE; 358 let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ONUPDATE;
352 let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel); 359 let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
353 360
@@ -361,7 +368,7 @@ macro_rules! impl_waveform_chx {
361 } 368 }
362 369
363 if !original_enable_state { 370 if !original_enable_state {
364 self.enable(cc_channel); 371 self.channel(cc_channel).enable();
365 } 372 }
366 373
367 unsafe { 374 unsafe {
@@ -389,10 +396,10 @@ macro_rules! impl_waveform_chx {
389 396
390 // restore output compare state 397 // restore output compare state
391 if !original_enable_state { 398 if !original_enable_state {
392 self.disable(cc_channel); 399 self.channel(cc_channel).disable();
393 } 400 }
394 401
395 self.set_duty(cc_channel, original_duty_state); 402 self.channel(cc_channel).set_duty(original_duty_state);
396 403
397 // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off, 404 // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off,
398 // this can almost always trigger a DMA FIFO error. 405 // this can almost always trigger a DMA FIFO error.