@@ -311,6 +311,53 @@ impl Default for Config {
311311 }
312312}
313313
314+ /// Configuration for the simple PWM driver.
315+ #[ derive( Debug , Clone ) ]
316+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
317+ #[ non_exhaustive]
318+ pub struct SimpleConfig {
319+ /// Selects up mode or up-and-down mode for the counter
320+ pub counter_mode : CounterMode ,
321+ /// Top value to be compared against buffer values
322+ pub max_duty : u16 ,
323+ /// Configuration for PWM_CLK
324+ pub prescaler : Prescaler ,
325+ /// Drive strength for the channel 0 line.
326+ pub ch0_drive : OutputDrive ,
327+ /// Drive strength for the channel 1 line.
328+ pub ch1_drive : OutputDrive ,
329+ /// Drive strength for the channel 2 line.
330+ pub ch2_drive : OutputDrive ,
331+ /// Drive strength for the channel 3 line.
332+ pub ch3_drive : OutputDrive ,
333+ /// Output level for the channel 0 line when PWM if disabled.
334+ pub ch0_idle_level : Level ,
335+ /// Output level for the channel 1 line when PWM if disabled.
336+ pub ch1_idle_level : Level ,
337+ /// Output level for the channel 2 line when PWM if disabled.
338+ pub ch2_idle_level : Level ,
339+ /// Output level for the channel 3 line when PWM if disabled.
340+ pub ch3_idle_level : Level ,
341+ }
342+
343+ impl Default for SimpleConfig {
344+ fn default ( ) -> Self {
345+ Self {
346+ counter_mode : CounterMode :: Up ,
347+ max_duty : 1000 ,
348+ prescaler : Prescaler :: Div16 ,
349+ ch0_drive : OutputDrive :: Standard ,
350+ ch1_drive : OutputDrive :: Standard ,
351+ ch2_drive : OutputDrive :: Standard ,
352+ ch3_drive : OutputDrive :: Standard ,
353+ ch0_idle_level : Level :: Low ,
354+ ch1_idle_level : Level :: Low ,
355+ ch2_idle_level : Level :: Low ,
356+ ch3_idle_level : Level :: Low ,
357+ }
358+ }
359+ }
360+
314361/// Configuration per sequence
315362#[ non_exhaustive]
316363#[ derive( Debug , Clone ) ]
@@ -643,46 +690,48 @@ impl defmt::Format for DutyCycle {
643690
644691impl < ' d > SimplePwm < ' d > {
645692 /// Create a new 1-channel PWM
646- #[ allow( unused_unsafe) ]
647- pub fn new_1ch < T : Instance > ( pwm : Peri < ' d , T > , ch0 : Peri < ' d , impl GpioPin > ) -> Self {
648- unsafe { Self :: new_inner ( pwm, Some ( ch0. into ( ) ) , None , None , None ) }
693+ pub fn new_1ch < T : Instance > ( pwm : Peri < ' d , T > , ch0 : Peri < ' d , impl GpioPin > , config : & SimpleConfig ) -> Self {
694+ Self :: new_inner ( pwm, Some ( ch0. into ( ) ) , None , None , None , config)
649695 }
650696
651697 /// Create a new 2-channel PWM
652- #[ allow( unused_unsafe) ]
653- pub fn new_2ch < T : Instance > ( pwm : Peri < ' d , T > , ch0 : Peri < ' d , impl GpioPin > , ch1 : Peri < ' d , impl GpioPin > ) -> Self {
654- Self :: new_inner ( pwm, Some ( ch0. into ( ) ) , Some ( ch1. into ( ) ) , None , None )
698+ pub fn new_2ch < T : Instance > (
699+ pwm : Peri < ' d , T > ,
700+ ch0 : Peri < ' d , impl GpioPin > ,
701+ ch1 : Peri < ' d , impl GpioPin > ,
702+ config : & SimpleConfig ,
703+ ) -> Self {
704+ Self :: new_inner ( pwm, Some ( ch0. into ( ) ) , Some ( ch1. into ( ) ) , None , None , config)
655705 }
656706
657707 /// Create a new 3-channel PWM
658- #[ allow( unused_unsafe) ]
659708 pub fn new_3ch < T : Instance > (
660709 pwm : Peri < ' d , T > ,
661710 ch0 : Peri < ' d , impl GpioPin > ,
662711 ch1 : Peri < ' d , impl GpioPin > ,
663712 ch2 : Peri < ' d , impl GpioPin > ,
713+ config : & SimpleConfig ,
664714 ) -> Self {
665- unsafe { Self :: new_inner ( pwm, Some ( ch0. into ( ) ) , Some ( ch1. into ( ) ) , Some ( ch2. into ( ) ) , None ) }
715+ Self :: new_inner ( pwm, Some ( ch0. into ( ) ) , Some ( ch1. into ( ) ) , Some ( ch2. into ( ) ) , None , config )
666716 }
667717
668718 /// Create a new 4-channel PWM
669- #[ allow( unused_unsafe) ]
670719 pub fn new_4ch < T : Instance > (
671720 pwm : Peri < ' d , T > ,
672721 ch0 : Peri < ' d , impl GpioPin > ,
673722 ch1 : Peri < ' d , impl GpioPin > ,
674723 ch2 : Peri < ' d , impl GpioPin > ,
675724 ch3 : Peri < ' d , impl GpioPin > ,
725+ config : & SimpleConfig ,
676726 ) -> Self {
677- unsafe {
678- Self :: new_inner (
679- pwm,
680- Some ( ch0. into ( ) ) ,
681- Some ( ch1. into ( ) ) ,
682- Some ( ch2. into ( ) ) ,
683- Some ( ch3. into ( ) ) ,
684- )
685- }
727+ Self :: new_inner (
728+ pwm,
729+ Some ( ch0. into ( ) ) ,
730+ Some ( ch1. into ( ) ) ,
731+ Some ( ch2. into ( ) ) ,
732+ Some ( ch3. into ( ) ) ,
733+ config,
734+ )
686735 }
687736
688737 fn new_inner < T : Instance > (
@@ -691,24 +740,33 @@ impl<'d> SimplePwm<'d> {
691740 ch1 : Option < Peri < ' d , AnyPin > > ,
692741 ch2 : Option < Peri < ' d , AnyPin > > ,
693742 ch3 : Option < Peri < ' d , AnyPin > > ,
743+ config : & SimpleConfig ,
694744 ) -> Self {
695745 let r = T :: regs ( ) ;
696746
697- for ( i, ch) in [ & ch0, & ch1, & ch2, & ch3] . into_iter ( ) . enumerate ( ) {
698- if let Some ( pin) = ch {
699- pin. set_low ( ) ;
700-
747+ let channels = [
748+ ( & ch0, config. ch0_drive , config. ch0_idle_level ) ,
749+ ( & ch1, config. ch1_drive , config. ch1_idle_level ) ,
750+ ( & ch2, config. ch2_drive , config. ch2_idle_level ) ,
751+ ( & ch3, config. ch3_drive , config. ch3_idle_level ) ,
752+ ] ;
753+ for ( i, ( pin, drive, idle_level) ) in channels. into_iter ( ) . enumerate ( ) {
754+ if let Some ( pin) = pin {
755+ match idle_level {
756+ Level :: Low => pin. set_low ( ) ,
757+ Level :: High => pin. set_high ( ) ,
758+ }
701759 pin. conf ( ) . write ( |w| {
702760 w. set_dir ( gpiovals:: Dir :: OUTPUT ) ;
703761 w. set_input ( gpiovals:: Input :: DISCONNECT ) ;
704- w . set_drive ( gpiovals :: Drive :: S0S1 ) ;
762+ convert_drive ( w , drive ) ;
705763 } ) ;
706764 }
707- r. psel ( ) . out ( i) . write_value ( ch . psel_bits ( ) ) ;
765+ r. psel ( ) . out ( i) . write_value ( pin . psel_bits ( ) ) ;
708766 }
709767
710768 let pwm = Self {
711- r : T :: regs ( ) ,
769+ r,
712770 ch0,
713771 ch1,
714772 ch2,
@@ -732,9 +790,13 @@ impl<'d> SimplePwm<'d> {
732790 w. set_load ( vals:: Load :: INDIVIDUAL ) ;
733791 w. set_mode ( vals:: Mode :: REFRESH_COUNT ) ;
734792 } ) ;
735- r. mode ( ) . write ( |w| w. set_updown ( vals:: Updown :: UP ) ) ;
736- r. prescaler ( ) . write ( |w| w. set_prescaler ( vals:: Prescaler :: DIV_16 ) ) ;
737- r. countertop ( ) . write ( |w| w. set_countertop ( 1000 ) ) ;
793+ r. mode ( ) . write ( |w| match config. counter_mode {
794+ CounterMode :: UpAndDown => w. set_updown ( vals:: Updown :: UP_AND_DOWN ) ,
795+ CounterMode :: Up => w. set_updown ( vals:: Updown :: UP ) ,
796+ } ) ;
797+ r. prescaler ( )
798+ . write ( |w| w. set_prescaler ( vals:: Prescaler :: from_bits ( config. prescaler as u8 ) ) ) ;
799+ r. countertop ( ) . write ( |w| w. set_countertop ( config. max_duty ) ) ;
738800 r. loop_ ( ) . write ( |w| w. set_cnt ( vals:: LoopCnt :: DISABLED ) ) ;
739801
740802 pwm
0 commit comments