diff options
| -rw-r--r-- | embassy-rp/src/pwm.rs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs index cfb99c569..4fb8ade12 100644 --- a/embassy-rp/src/pwm.rs +++ b/embassy-rp/src/pwm.rs | |||
| @@ -344,6 +344,119 @@ impl<'d> Pwm<'d> { | |||
| 344 | fn bit(&self) -> u32 { | 344 | fn bit(&self) -> u32 { |
| 345 | 1 << self.slice as usize | 345 | 1 << self.slice as usize |
| 346 | } | 346 | } |
| 347 | |||
| 348 | /// Splits the PWM driver into separate `PwmOutput` instances for channels A and B. | ||
| 349 | #[inline] | ||
| 350 | pub fn split(mut self) -> (Option<PwmOutput<'d>>, Option<PwmOutput<'d>>) { | ||
| 351 | ( | ||
| 352 | self.pin_a | ||
| 353 | .take() | ||
| 354 | .map(|pin| PwmOutput::new(PwmChannelPin::A(pin), self.slice.clone(), true)), | ||
| 355 | self.pin_b | ||
| 356 | .take() | ||
| 357 | .map(|pin| PwmOutput::new(PwmChannelPin::B(pin), self.slice.clone(), true)), | ||
| 358 | ) | ||
| 359 | } | ||
| 360 | /// Splits the PWM driver by reference to allow for separate duty cycle control | ||
| 361 | /// of each channel (A and B) without taking ownership of the PWM instance. | ||
| 362 | #[inline] | ||
| 363 | pub fn split_by_ref(&mut self) -> (Option<PwmOutput<'_>>, Option<PwmOutput<'_>>) { | ||
| 364 | ( | ||
| 365 | self.pin_a | ||
| 366 | .as_mut() | ||
| 367 | .map(|pin| PwmOutput::new(PwmChannelPin::A(pin.reborrow()), self.slice.clone(), false)), | ||
| 368 | self.pin_b | ||
| 369 | .as_mut() | ||
| 370 | .map(|pin| PwmOutput::new(PwmChannelPin::B(pin.reborrow()), self.slice.clone(), false)), | ||
| 371 | ) | ||
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | enum PwmChannelPin<'d> { | ||
| 376 | A(PeripheralRef<'d, AnyPin>), | ||
| 377 | B(PeripheralRef<'d, AnyPin>), | ||
| 378 | } | ||
| 379 | |||
| 380 | /// Single channel of Pwm driver. | ||
| 381 | pub struct PwmOutput<'d> { | ||
| 382 | //pin that can be ether ChannelAPin or ChannelBPin | ||
| 383 | channel_pin: PwmChannelPin<'d>, | ||
| 384 | slice: usize, | ||
| 385 | is_owned: bool, | ||
| 386 | } | ||
| 387 | |||
| 388 | impl<'d> PwmOutput<'d> { | ||
| 389 | fn new(channel_pin: PwmChannelPin<'d>, slice: usize, is_owned: bool) -> Self { | ||
| 390 | Self { | ||
| 391 | channel_pin, | ||
| 392 | slice, | ||
| 393 | is_owned, | ||
| 394 | } | ||
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | impl<'d> Drop for PwmOutput<'d> { | ||
| 399 | fn drop(&mut self) { | ||
| 400 | if self.is_owned { | ||
| 401 | let p = pac::PWM.ch(self.slice); | ||
| 402 | match &self.channel_pin { | ||
| 403 | PwmChannelPin::A(pin) => { | ||
| 404 | p.cc().modify(|w| { | ||
| 405 | w.set_a(0); | ||
| 406 | }); | ||
| 407 | |||
| 408 | pin.gpio().ctrl().write(|w| w.set_funcsel(31)); | ||
| 409 | //Enable pin PULL-DOWN | ||
| 410 | pin.pad_ctrl().modify(|w| { | ||
| 411 | w.set_pde(true); | ||
| 412 | }); | ||
| 413 | } | ||
| 414 | PwmChannelPin::B(pin) => { | ||
| 415 | p.cc().modify(|w| { | ||
| 416 | w.set_b(0); | ||
| 417 | }); | ||
| 418 | pin.gpio().ctrl().write(|w| w.set_funcsel(31)); | ||
| 419 | //Enable pin PULL-DOWN | ||
| 420 | pin.pad_ctrl().modify(|w| { | ||
| 421 | w.set_pde(true); | ||
| 422 | }); | ||
| 423 | } | ||
| 424 | } | ||
| 425 | } | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | impl<'d> ErrorType for PwmOutput<'d> { | ||
| 430 | type Error = PwmError; | ||
| 431 | } | ||
| 432 | |||
| 433 | impl<'d> SetDutyCycle for PwmOutput<'d> { | ||
| 434 | fn max_duty_cycle(&self) -> u16 { | ||
| 435 | pac::PWM.ch(self.slice).top().read().top() | ||
| 436 | } | ||
| 437 | |||
| 438 | fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> { | ||
| 439 | let max_duty = self.max_duty_cycle(); | ||
| 440 | if duty > max_duty { | ||
| 441 | return Err(PwmError::InvalidDutyCycle); | ||
| 442 | } | ||
| 443 | |||
| 444 | let p = pac::PWM.ch(self.slice); | ||
| 445 | match self.channel_pin { | ||
| 446 | PwmChannelPin::A(_) => { | ||
| 447 | p.cc().modify(|w| { | ||
| 448 | w.set_a(duty); | ||
| 449 | }); | ||
| 450 | } | ||
| 451 | PwmChannelPin::B(_) => { | ||
| 452 | p.cc().modify(|w| { | ||
| 453 | w.set_b(duty); | ||
| 454 | }); | ||
| 455 | } | ||
| 456 | } | ||
| 457 | |||
| 458 | Ok(()) | ||
| 459 | } | ||
| 347 | } | 460 | } |
| 348 | 461 | ||
| 349 | /// Batch representation of PWM slices. | 462 | /// Batch representation of PWM slices. |
