@@ -15,7 +15,7 @@ use crate::interrupt::typelevel::{Handler, Interrupt};
1515use crate :: pac:: common:: { RW , Reg } ;
1616use crate :: pac:: gpio:: vals:: { Irqc , Isf , Pdd , Pid , Ptco , Ptso } ;
1717use crate :: pac:: port:: regs:: Pcr ;
18- use crate :: pac:: port:: vals:: { Dse , Ibe , Inv , Mux , Pe , Ps , Sre } ;
18+ use crate :: pac:: port:: vals:: { Dse , Ibe , Inv , Mux , Ode , Pe , Ps , Sre } ;
1919
2020struct BitIter ( u32 ) ;
2121
@@ -145,6 +145,25 @@ impl<T: Instance> Handler<T::Interrupt> for InterruptHandler<T> {
145145 }
146146}
147147
148+ /// Open-drain for GPIO pins.
149+ #[ derive( Copy , Clone , Eq , PartialEq , Debug ) ]
150+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
151+ pub enum OpenDrain {
152+ /// Output is push-pull (not open-drain)
153+ No ,
154+ /// Output is open-drain
155+ Yes ,
156+ }
157+
158+ impl From < OpenDrain > for Ode {
159+ fn from ( open_drain : OpenDrain ) -> Self {
160+ match open_drain {
161+ OpenDrain :: No => Ode :: ODE0 ,
162+ OpenDrain :: Yes => Ode :: ODE1 ,
163+ }
164+ }
165+ }
166+
148167/// Logical level for GPIO pins.
149168#[ derive( Copy , Clone , Eq , PartialEq , Debug ) ]
150169#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
@@ -643,6 +662,18 @@ impl<'d, M: Mode> Flex<'d, M> {
643662 !self . is_set_high ( )
644663 }
645664
665+ /// Configure open-drain output.
666+ #[ inline]
667+ pub fn set_open_drain ( & mut self , open_drain : OpenDrain ) {
668+ self . pin . pcr_reg ( ) . modify ( |w| w. set_ode ( open_drain. into ( ) ) ) ;
669+ }
670+
671+ /// Configure the input logic inversion of this pin.
672+ #[ inline]
673+ pub fn set_input_inversion ( & mut self , invert : Inverter ) {
674+ self . pin . pcr_reg ( ) . modify ( |w| w. set_inv ( invert. into ( ) ) ) ;
675+ }
676+
646677 /// Configure the pin pull up/down level.
647678 pub fn set_pull ( & mut self , pull_select : Pull ) {
648679 self . pin . set_pull ( pull_select) ;
@@ -799,6 +830,7 @@ impl<'d> Output<'d> {
799830 flex. set_as_output ( ) ;
800831 flex. set_drive_strength ( strength) ;
801832 flex. set_slew_rate ( slew_rate) ;
833+ flex. set_open_drain ( OpenDrain :: No ) ;
802834 Self { flex }
803835 }
804836
@@ -843,6 +875,96 @@ impl<'d> Output<'d> {
843875 pub fn into_flex ( self ) -> Flex < ' d > {
844876 self . flex
845877 }
878+
879+ /// Convert this output pin into an open-drain output pin.
880+ #[ inline]
881+ pub fn into_open_drain ( mut self ) -> OutputOpenDrain < ' d > {
882+ self . flex . set_open_drain ( OpenDrain :: Yes ) ;
883+ OutputOpenDrain { flex : self . flex }
884+ }
885+ }
886+
887+ /// GPIO output open-drain driver that owns a `Flex` pin.
888+ pub struct OutputOpenDrain < ' d > {
889+ flex : Flex < ' d > ,
890+ }
891+
892+ impl < ' d > OutputOpenDrain < ' d > {
893+ /// Create a GPIO output open-drain driver for a [GpioPin] with the provided [Level].
894+ pub fn new ( pin : Peri < ' d , impl GpioPin > , initial : Level , strength : DriveStrength , slew_rate : SlewRate ) -> Self {
895+ let mut flex = Flex :: new ( pin) ;
896+ flex. set_level ( initial) ;
897+ flex. set_as_output ( ) ;
898+ flex. set_drive_strength ( strength) ;
899+ flex. set_slew_rate ( slew_rate) ;
900+ flex. set_enable_input_buffer ( true ) ;
901+ flex. set_open_drain ( OpenDrain :: Yes ) ;
902+ Self { flex }
903+ }
904+
905+ /// Get whether the pin level is high.
906+ #[ inline]
907+ pub fn is_high ( & self ) -> bool {
908+ self . flex . is_high ( )
909+ }
910+
911+ /// Get whether the pin level is low.
912+ #[ inline]
913+ pub fn is_low ( & self ) -> bool {
914+ self . flex . is_low ( )
915+ }
916+
917+ /// Set the output as high (open-drain high is just letting go of the line).
918+ #[ inline]
919+ pub fn set_high ( & mut self ) {
920+ self . flex . set_high ( ) ;
921+ }
922+
923+ /// Set the output as low (open-drain low is driving the line low).
924+ #[ inline]
925+ pub fn set_low ( & mut self ) {
926+ self . flex . set_low ( ) ;
927+ }
928+
929+ /// Set the output level.
930+ #[ inline]
931+ pub fn set_level ( & mut self , level : Level ) {
932+ self . flex . set_level ( level) ;
933+ }
934+
935+ /// Get the pin level.
936+ pub fn get_level ( & self ) -> Level {
937+ self . flex . get_level ( )
938+ }
939+
940+ /// Toggle the output level.
941+ #[ inline]
942+ pub fn toggle ( & mut self ) {
943+ if self . flex . is_set_low ( ) {
944+ self . set_high ( ) ;
945+ } else {
946+ self . set_low ( ) ;
947+ }
948+ }
949+
950+ /// Configure the input logic inversion of this pin.
951+ #[ inline]
952+ pub fn set_inversion ( & mut self , invert : Inverter ) {
953+ self . flex . set_input_inversion ( invert)
954+ }
955+
956+ /// Expose the inner `Flex` if callers need to reconfigure the pin.
957+ #[ inline]
958+ pub fn into_flex ( self ) -> Flex < ' d > {
959+ self . flex
960+ }
961+
962+ /// Convert this output pin into an push-pull output pin.
963+ #[ inline]
964+ pub fn into_push_pull ( mut self ) -> Output < ' d > {
965+ self . flex . set_open_drain ( OpenDrain :: No ) ;
966+ Output { flex : self . flex }
967+ }
846968}
847969
848970/// GPIO input driver that owns a `Flex` pin.
@@ -885,6 +1007,12 @@ impl<'d, M: Mode> Input<'d, M> {
8851007 self . flex
8861008 }
8871009
1010+ /// Configure the input logic inversion of this pin.
1011+ #[ inline]
1012+ pub fn set_inversion ( & mut self , invert : Inverter ) {
1013+ self . flex . set_input_inversion ( invert)
1014+ }
1015+
8881016 /// Get the pin level.
8891017 pub fn get_level ( & self ) -> Level {
8901018 self . flex . get_level ( )
0 commit comments