rp2040_hal/gpio/
mod.rs

1//! General Purpose Input and Output (GPIO)
2//!
3//! ## Basic usage
4//! ```no_run
5//! use embedded_hal::digital::{InputPin, OutputPin};
6//! use rp2040_hal::{clocks::init_clocks_and_plls, gpio::Pins, watchdog::Watchdog, pac, Sio};
7//! let mut peripherals = pac::Peripherals::take().unwrap();
8//! let mut watchdog = Watchdog::new(peripherals.WATCHDOG);
9//! const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // Typically found in BSP crates
10//! let mut clocks = init_clocks_and_plls(XOSC_CRYSTAL_FREQ, peripherals.XOSC, peripherals.CLOCKS, peripherals.PLL_SYS, peripherals.PLL_USB, &mut peripherals.RESETS, &mut watchdog).ok().unwrap();
11//!
12//! let mut pac = pac::Peripherals::take().unwrap();
13//! let sio = Sio::new(pac.SIO);
14//! let pins = rp2040_hal::gpio::Pins::new(pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS);
15//! // Set a pin to drive output
16//! let mut output_pin = pins.gpio25.into_push_pull_output();
17//! // Drive output to 3.3V
18//! output_pin.set_high().unwrap();
19//! // Drive output to 0V
20//! output_pin.set_low().unwrap();
21//! // Set a pin to input
22//! let mut input_pin = pins.gpio24.into_floating_input();
23//! // pinstate will be true if the pin is above 2V
24//! let pinstate = input_pin.is_high().unwrap();
25//! // pinstate_low will be true if the pin is below 1.15V
26//! let pinstate_low = input_pin.is_low().unwrap();
27//! // you'll want to pull-up or pull-down a switch if it's not done externally
28//! let button_pin = pins.gpio23.into_pull_down_input();
29//! let button2_pin = pins.gpio22.into_pull_up_input();
30//! ```
31//! See [examples/gpio_in_out.rs](https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal-examples/src/bin/gpio_in_out.rs) for a more practical example
32
33// Design Notes:
34//
35// - The user must not be able to instantiate by themselves nor obtain an instance of the Type-level
36//   structure.
37// - non-typestated features (overrides, irq configuration, pads' output disable, pad's input
38//   enable, drive strength, schmitt, slew rate, sio's in sync bypass) are considered somewhat
39//   advanced usage of the pin (relative to reading/writing a gpio) and it is the responsibility of
40//   the user to make sure these are in a correct state when converting and passing the pin around.
41
42pub use embedded_hal::digital::PinState;
43
44use crate::{
45    atomic_register_access::{write_bitmask_clear, write_bitmask_set},
46    pac,
47    sio::Sio,
48    typelevel::{self, Sealed},
49};
50
51mod func;
52pub(crate) mod pin;
53mod pin_group;
54mod pull;
55
56pub use func::*;
57pub use pin::{DynBankId, DynPinId, PinId};
58pub use pin_group::PinGroup;
59pub use pull::*;
60
61/// The amount of current that a pin can drive when used as an output.
62#[allow(clippy::enum_variant_names)]
63#[derive(Clone, Copy, Eq, PartialEq, Debug)]
64pub enum OutputDriveStrength {
65    /// 2 mA
66    TwoMilliAmps,
67    /// 4 mA
68    FourMilliAmps,
69    /// 8 mA
70    EightMilliAmps,
71    /// 12 mA
72    TwelveMilliAmps,
73}
74
75/// The slew rate of a pin when used as an output.
76#[derive(Clone, Copy, Eq, PartialEq, Debug)]
77pub enum OutputSlewRate {
78    /// Slew slow
79    Slow,
80    /// Slew fast
81    Fast,
82}
83
84/// Interrupt kind.
85#[derive(Clone, Copy, Eq, PartialEq, Debug)]
86pub enum Interrupt {
87    /// While low
88    LevelLow,
89    /// While high
90    LevelHigh,
91    /// On falling edge
92    EdgeLow,
93    /// On rising edge
94    EdgeHigh,
95}
96impl Interrupt {
97    fn mask(&self) -> u32 {
98        match self {
99            Interrupt::LevelLow => 0b0001,
100            Interrupt::LevelHigh => 0b0010,
101            Interrupt::EdgeLow => 0b0100,
102            Interrupt::EdgeHigh => 0b1000,
103        }
104    }
105}
106
107/// Interrupt override state.
108#[derive(Clone, Copy, Eq, PartialEq, Debug)]
109pub enum InterruptOverride {
110    /// Don't invert the interrupt.
111    Normal = 0,
112    /// Invert the interrupt.
113    Invert = 1,
114    /// Drive interrupt low.
115    AlwaysLow = 2,
116    /// Drive interrupt high.
117    AlwaysHigh = 3,
118}
119
120/// Input override state.
121#[derive(Clone, Copy, Eq, PartialEq, Debug)]
122pub enum InputOverride {
123    /// Don't invert the peripheral input.
124    Normal = 0,
125    /// Invert the peripheral input.
126    Invert = 1,
127    /// Drive peripheral input low.
128    AlwaysLow = 2,
129    /// Drive peripheral input high.
130    AlwaysHigh = 3,
131}
132
133#[derive(Clone, Copy, Eq, PartialEq, Debug)]
134/// Output enable override state.
135pub enum OutputEnableOverride {
136    /// Use the original output enable signal from selected peripheral.
137    Normal = 0,
138    /// Invert the output enable signal from selected peripheral.
139    Invert = 1,
140    /// Disable output.
141    Disable = 2,
142    /// Enable output.
143    Enable = 3,
144}
145
146#[derive(Clone, Copy, Eq, PartialEq, Debug)]
147/// Output override state.
148pub enum OutputOverride {
149    /// Use the original output signal from selected peripheral.
150    DontInvert = 0,
151    /// Invert the output signal from selected peripheral.
152    Invert = 1,
153    /// Drive output low.
154    AlwaysLow = 2,
155    /// Drive output high.
156    AlwaysHigh = 3,
157}
158
159/// Represents a pin, with a given ID (e.g. Gpio3), a given function (e.g. FunctionUart) and a given pull type
160/// (e.g. pull-down).
161#[derive(Debug)]
162pub struct Pin<I: PinId, F: func::Function, P: PullType> {
163    id: I,
164    function: F,
165    pull_type: P,
166}
167
168/// Create a new pin instance.
169///
170/// # Safety
171/// The uniqueness of the pin is not verified. User must make sure no other instance of that specific
172/// pin exists at the same time.
173pub unsafe fn new_pin(id: DynPinId) -> Pin<DynPinId, DynFunction, DynPullType> {
174    use pac::io_bank0::gpio::gpio_ctrl::FUNCSEL_A;
175    use pin::pin_sealed::PinIdOps;
176
177    let funcsel = id
178        .io_ctrl()
179        .read()
180        .funcsel()
181        .variant()
182        .expect("Invalid funcsel read from register.");
183    let function = match funcsel {
184        FUNCSEL_A::JTAG => DynFunction::Xip,
185        FUNCSEL_A::SPI => DynFunction::Spi,
186        FUNCSEL_A::UART => DynFunction::Uart,
187        FUNCSEL_A::I2C => DynFunction::I2c,
188        FUNCSEL_A::PWM => DynFunction::Pwm,
189        FUNCSEL_A::SIO => {
190            let mask = id.mask();
191            let cfg = if id.sio_oe().read().bits() & mask == mask {
192                DynSioConfig::Output
193            } else {
194                DynSioConfig::Input
195            };
196            DynFunction::Sio(cfg)
197        }
198        FUNCSEL_A::PIO0 => DynFunction::Pio0,
199        FUNCSEL_A::PIO1 => DynFunction::Pio1,
200        FUNCSEL_A::CLOCK => DynFunction::Clock,
201        FUNCSEL_A::USB => DynFunction::Usb,
202        FUNCSEL_A::NULL => DynFunction::Null,
203    };
204    let pad = id.pad_ctrl().read();
205    let pull_type = match (pad.pue().bit_is_set(), pad.pde().bit_is_set()) {
206        (true, true) => DynPullType::BusKeep,
207        (true, false) => DynPullType::Up,
208        (false, true) => DynPullType::Down,
209        (false, false) => DynPullType::None,
210    };
211
212    Pin {
213        id,
214        function,
215        pull_type,
216    }
217}
218
219impl<I: PinId, F: func::Function, P: PullType> Pin<I, F, P> {
220    /// Pin ID.
221    pub fn id(&self) -> DynPinId {
222        self.id.as_dyn()
223    }
224
225    /// # Safety
226    /// This method does not check if the pin is actually configured as the target function or pull
227    /// mode. This may lead to inconsistencies between the type-state and the actual state of the
228    /// pin's configuration.
229    pub unsafe fn into_unchecked<F2: func::Function, P2: PullType>(self) -> Pin<I, F2, P2> {
230        Pin {
231            id: self.id,
232            function: F2::from(self.function.as_dyn()),
233            pull_type: P2::from(self.pull_type.as_dyn()),
234        }
235    }
236
237    /// Convert the pin from one state to the other.
238    pub fn reconfigure<F2, P2>(self) -> Pin<I, F2, P2>
239    where
240        F2: func::Function,
241        P2: PullType,
242        I: func::ValidFunction<F2>,
243    {
244        self.into_function().into_pull_type()
245    }
246
247    /// Convert the pin function.
248    #[deprecated(
249        note = "Misleading name `mode` when it changes the `function`. Please use `into_function` instead.",
250        since = "0.9.0"
251    )]
252    pub fn into_mode<F2>(self) -> Pin<I, F2, P>
253    where
254        F2: func::Function,
255        I: func::ValidFunction<F2>,
256    {
257        self.into_function()
258    }
259
260    /// Convert the pin function.
261    pub fn into_function<F2>(self) -> Pin<I, F2, P>
262    where
263        F2: func::Function,
264        I: func::ValidFunction<F2>,
265    {
266        // Thanks to type-level validation, we know F2 is valid for I
267        let prev_function = self.function.as_dyn();
268        let function = F2::from(prev_function);
269        let new_function = function.as_dyn();
270
271        if prev_function != new_function {
272            pin::set_function(&self.id, new_function);
273        }
274
275        Pin {
276            function,
277            id: self.id,
278            pull_type: self.pull_type,
279        }
280    }
281
282    /// Convert the pin pull type.
283    pub fn into_pull_type<M2: PullType>(self) -> Pin<I, F, M2> {
284        let prev_pull_type = self.pull_type.as_dyn();
285        let pull_type = M2::from(prev_pull_type);
286        let new_pull_type = pull_type.as_dyn();
287
288        if prev_pull_type != new_pull_type {
289            pin::set_pull_type(&self.id, new_pull_type);
290        }
291
292        Pin {
293            pull_type,
294            id: self.id,
295            function: self.function,
296        }
297    }
298
299    /// Erase the Pin ID type check.
300    pub fn into_dyn_pin(self) -> Pin<DynPinId, F, P> {
301        Pin {
302            id: self.id.as_dyn(),
303            function: self.function,
304            pull_type: self.pull_type,
305        }
306    }
307
308    /// Get the pin's pull type.
309    pub fn pull_type(&self) -> DynPullType {
310        self.pull_type.as_dyn()
311    }
312
313    //==============================================================================
314    // Typical pin conversions.
315    //==============================================================================
316
317    /// Disable the pin and set it to float
318    #[inline]
319    pub fn into_floating_disabled(self) -> Pin<I, FunctionNull, PullNone>
320    where
321        I: ValidFunction<FunctionNull>,
322    {
323        self.reconfigure()
324    }
325
326    /// Disable the pin and set it to pull down
327    #[inline]
328    pub fn into_pull_down_disabled(self) -> Pin<I, FunctionNull, PullDown>
329    where
330        I: ValidFunction<FunctionNull>,
331    {
332        self.reconfigure()
333    }
334
335    /// Disable the pin and set it to pull up
336    #[inline]
337    pub fn into_pull_up_disabled(self) -> Pin<I, FunctionNull, PullUp>
338    where
339        I: ValidFunction<FunctionNull>,
340    {
341        self.reconfigure()
342    }
343
344    /// Configure the pin to operate as a floating input
345    #[inline]
346    pub fn into_floating_input(self) -> Pin<I, FunctionSio<SioInput>, PullNone>
347    where
348        I: ValidFunction<FunctionSio<SioInput>>,
349    {
350        self.into_function().into_pull_type()
351    }
352
353    /// Configure the pin to operate as a pulled down input
354    #[inline]
355    pub fn into_pull_down_input(self) -> Pin<I, FunctionSio<SioInput>, PullDown>
356    where
357        I: ValidFunction<FunctionSio<SioInput>>,
358    {
359        self.into_function().into_pull_type()
360    }
361
362    /// Configure the pin to operate as a pulled up input
363    #[inline]
364    pub fn into_pull_up_input(self) -> Pin<I, FunctionSio<SioInput>, PullUp>
365    where
366        I: ValidFunction<FunctionSio<SioInput>>,
367    {
368        self.into_function().into_pull_type()
369    }
370
371    /// Configure the pin to operate as a bus keep input
372    #[inline]
373    pub fn into_bus_keep_input(self) -> Pin<I, FunctionSio<SioInput>, PullBusKeep>
374    where
375        I: ValidFunction<FunctionSio<SioInput>>,
376    {
377        self.into_function().into_pull_type()
378    }
379
380    /// Configure the pin to operate as a push-pull output.
381    ///
382    /// If you want to specify the initial pin state, use [`Pin::into_push_pull_output_in_state`].
383    #[inline]
384    pub fn into_push_pull_output(self) -> Pin<I, FunctionSio<SioOutput>, P>
385    where
386        I: ValidFunction<FunctionSio<SioOutput>>,
387    {
388        self.into_function()
389    }
390
391    /// Configure the pin to operate as a push-pull output, specifying an initial
392    /// state which is applied immediately.
393    #[inline]
394    pub fn into_push_pull_output_in_state(
395        mut self,
396        state: PinState,
397    ) -> Pin<I, FunctionSio<SioOutput>, P>
398    where
399        I: ValidFunction<FunctionSio<SioOutput>>,
400    {
401        match state {
402            PinState::High => self._set_high(),
403            PinState::Low => self._set_low(),
404        }
405        self.into_push_pull_output()
406    }
407
408    /// Configure the pin to operate as a readable push pull output.
409    ///
410    /// If you want to specify the initial pin state, use [`Pin::into_readable_output_in_state`].
411    #[inline]
412    #[deprecated(
413        note = "All gpio are readable, use `.into_push_pull_output()` instead.",
414        since = "0.9.0"
415    )]
416    pub fn into_readable_output(self) -> Pin<I, FunctionSio<SioOutput>, P>
417    where
418        I: ValidFunction<FunctionSio<SioOutput>>,
419    {
420        self.into_function()
421    }
422
423    /// Configure the pin to operate as a readable push pull output, specifying an initial
424    /// state which is applied immediately.
425    #[inline]
426    #[deprecated(
427        note = "All gpio are readable, use `.into_push_pull_output_in_state()` instead.",
428        since = "0.9.0"
429    )]
430    pub fn into_readable_output_in_state(self, state: PinState) -> Pin<I, FunctionSio<SioOutput>, P>
431    where
432        I: ValidFunction<FunctionSio<SioOutput>>,
433    {
434        self.into_push_pull_output_in_state(state)
435    }
436
437    //==============================================================================
438    // methods available for all pins.
439    //==============================================================================
440
441    // =======================
442    // Pad related methods
443
444    /// Get the current drive strength of the pin.
445    #[inline]
446    pub fn get_drive_strength(&self) -> OutputDriveStrength {
447        use pac::pads_bank0::gpio::DRIVE_A;
448        match self.id.pad_ctrl().read().drive().variant() {
449            DRIVE_A::_2M_A => OutputDriveStrength::TwoMilliAmps,
450            DRIVE_A::_4M_A => OutputDriveStrength::FourMilliAmps,
451            DRIVE_A::_8M_A => OutputDriveStrength::EightMilliAmps,
452            DRIVE_A::_12M_A => OutputDriveStrength::TwelveMilliAmps,
453        }
454    }
455
456    /// Set the drive strength for the pin.
457    #[inline]
458    pub fn set_drive_strength(&mut self, strength: OutputDriveStrength) {
459        use pac::pads_bank0::gpio::DRIVE_A;
460        let variant = match strength {
461            OutputDriveStrength::TwoMilliAmps => DRIVE_A::_2M_A,
462            OutputDriveStrength::FourMilliAmps => DRIVE_A::_4M_A,
463            OutputDriveStrength::EightMilliAmps => DRIVE_A::_8M_A,
464            OutputDriveStrength::TwelveMilliAmps => DRIVE_A::_12M_A,
465        };
466        self.id.pad_ctrl().modify(|_, w| w.drive().variant(variant))
467    }
468
469    /// Get the slew rate for the pin.
470    #[inline]
471    pub fn get_slew_rate(&self) -> OutputSlewRate {
472        if self.id.pad_ctrl().read().slewfast().bit_is_set() {
473            OutputSlewRate::Fast
474        } else {
475            OutputSlewRate::Slow
476        }
477    }
478
479    /// Set the slew rate for the pin.
480    #[inline]
481    pub fn set_slew_rate(&mut self, rate: OutputSlewRate) {
482        self.id
483            .pad_ctrl()
484            .modify(|_, w| w.slewfast().bit(OutputSlewRate::Fast == rate));
485    }
486
487    /// Get whether the schmitt trigger (hysteresis) is enabled.
488    #[inline]
489    pub fn get_schmitt_enabled(&self) -> bool {
490        self.id.pad_ctrl().read().schmitt().bit_is_set()
491    }
492
493    /// Enable/Disable the schmitt trigger.
494    #[inline]
495    pub fn set_schmitt_enabled(&self, enable: bool) {
496        self.id.pad_ctrl().modify(|_, w| w.schmitt().bit(enable));
497    }
498
499    /// Get the state of the digital output circuitry of the pad.
500    #[inline]
501    pub fn get_output_disable(&mut self) -> bool {
502        self.id.pad_ctrl().read().od().bit_is_set()
503    }
504
505    /// Set the digital output circuitry of the pad.
506    #[inline]
507    pub fn set_output_disable(&mut self, disable: bool) {
508        self.id.pad_ctrl().modify(|_, w| w.od().bit(disable));
509    }
510
511    /// Get the state of the digital input circuitry of the pad.
512    #[inline]
513    pub fn get_input_enable(&mut self) -> bool {
514        self.id.pad_ctrl().read().ie().bit_is_set()
515    }
516
517    /// Set the digital input circuitry of the pad.
518    #[inline]
519    pub fn set_input_enable(&mut self, enable: bool) {
520        self.id.pad_ctrl().modify(|_, w| w.ie().bit(enable));
521    }
522
523    // =======================
524    // IO related methods
525
526    /// Get the input override.
527    #[inline]
528    pub fn get_input_override(&self) -> InputOverride {
529        use pac::io_bank0::gpio::gpio_ctrl::INOVER_A;
530        match self.id.io_ctrl().read().inover().variant() {
531            INOVER_A::NORMAL => InputOverride::Normal,
532            INOVER_A::INVERT => InputOverride::Invert,
533            INOVER_A::LOW => InputOverride::AlwaysLow,
534            INOVER_A::HIGH => InputOverride::AlwaysHigh,
535        }
536    }
537
538    /// Set the input override.
539    #[inline]
540    pub fn set_input_override(&mut self, override_value: InputOverride) {
541        use pac::io_bank0::gpio::gpio_ctrl::INOVER_A;
542        let variant = match override_value {
543            InputOverride::Normal => INOVER_A::NORMAL,
544            InputOverride::Invert => INOVER_A::INVERT,
545            InputOverride::AlwaysLow => INOVER_A::LOW,
546            InputOverride::AlwaysHigh => INOVER_A::HIGH,
547        };
548        self.id.io_ctrl().modify(|_, w| w.inover().variant(variant));
549    }
550
551    /// Get the output enable override.
552    #[inline]
553    pub fn get_output_enable_override(&self) -> OutputEnableOverride {
554        use pac::io_bank0::gpio::gpio_ctrl::OEOVER_A;
555        match self.id.io_ctrl().read().oeover().variant() {
556            OEOVER_A::NORMAL => OutputEnableOverride::Normal,
557            OEOVER_A::INVERT => OutputEnableOverride::Invert,
558            OEOVER_A::DISABLE => OutputEnableOverride::Disable,
559            OEOVER_A::ENABLE => OutputEnableOverride::Enable,
560        }
561    }
562
563    /// Set the output enable override.
564    #[inline]
565    pub fn set_output_enable_override(&mut self, override_value: OutputEnableOverride) {
566        use pac::io_bank0::gpio::gpio_ctrl::OEOVER_A;
567        let variant = match override_value {
568            OutputEnableOverride::Normal => OEOVER_A::NORMAL,
569            OutputEnableOverride::Invert => OEOVER_A::INVERT,
570            OutputEnableOverride::Disable => OEOVER_A::DISABLE,
571            OutputEnableOverride::Enable => OEOVER_A::ENABLE,
572        };
573        self.id.io_ctrl().modify(|_, w| w.oeover().variant(variant));
574    }
575
576    /// Get the output override.
577    #[inline]
578    pub fn get_output_override(&self) -> OutputOverride {
579        use pac::io_bank0::gpio::gpio_ctrl::OUTOVER_A;
580        match self.id.io_ctrl().read().outover().variant() {
581            OUTOVER_A::NORMAL => OutputOverride::DontInvert,
582            OUTOVER_A::INVERT => OutputOverride::Invert,
583            OUTOVER_A::LOW => OutputOverride::AlwaysLow,
584            OUTOVER_A::HIGH => OutputOverride::AlwaysHigh,
585        }
586    }
587
588    /// Set the output override.
589    #[inline]
590    pub fn set_output_override(&mut self, override_value: OutputOverride) {
591        use pac::io_bank0::gpio::gpio_ctrl::OUTOVER_A;
592        let variant = match override_value {
593            OutputOverride::DontInvert => OUTOVER_A::NORMAL,
594            OutputOverride::Invert => OUTOVER_A::INVERT,
595            OutputOverride::AlwaysLow => OUTOVER_A::LOW,
596            OutputOverride::AlwaysHigh => OUTOVER_A::HIGH,
597        };
598        self.id
599            .io_ctrl()
600            .modify(|_, w| w.outover().variant(variant));
601    }
602
603    /// Get the interrupt override.
604    #[inline]
605    pub fn get_interrupt_override(&self) -> InterruptOverride {
606        use pac::io_bank0::gpio::gpio_ctrl::IRQOVER_A;
607        match self.id.io_ctrl().read().irqover().variant() {
608            IRQOVER_A::NORMAL => InterruptOverride::Normal,
609            IRQOVER_A::INVERT => InterruptOverride::Invert,
610            IRQOVER_A::LOW => InterruptOverride::AlwaysLow,
611            IRQOVER_A::HIGH => InterruptOverride::AlwaysHigh,
612        }
613    }
614
615    /// Set the interrupt override.
616    #[inline]
617    pub fn set_interrupt_override(&mut self, override_value: InterruptOverride) {
618        use pac::io_bank0::gpio::gpio_ctrl::IRQOVER_A;
619        let variant = match override_value {
620            InterruptOverride::Normal => IRQOVER_A::NORMAL,
621            InterruptOverride::Invert => IRQOVER_A::INVERT,
622            InterruptOverride::AlwaysLow => IRQOVER_A::LOW,
623            InterruptOverride::AlwaysHigh => IRQOVER_A::HIGH,
624        };
625        self.id
626            .io_ctrl()
627            .modify(|_, w| w.irqover().variant(variant));
628    }
629
630    // =======================
631    // SIO related methods
632
633    #[inline]
634    #[allow(clippy::bool_comparison)] // more explicit this way
635    pub(crate) fn _is_low(&self) -> bool {
636        let mask = self.id.mask();
637        self.id.sio_in().read().bits() & mask == 0
638    }
639
640    #[inline]
641    #[allow(clippy::bool_comparison)] // more explicit this way
642    pub(crate) fn _is_high(&self) -> bool {
643        !self._is_low()
644    }
645
646    #[inline]
647    pub(crate) fn _set_low(&mut self) {
648        let mask = self.id.mask();
649        self.id
650            .sio_out_clr()
651            .write(|w| unsafe { w.gpio_out_clr().bits(mask) });
652    }
653
654    #[inline]
655    pub(crate) fn _set_high(&mut self) {
656        let mask = self.id.mask();
657        self.id
658            .sio_out_set()
659            .write(|w| unsafe { w.gpio_out_set().bits(mask) });
660    }
661
662    #[inline]
663    pub(crate) fn _toggle(&mut self) {
664        let mask = self.id.mask();
665        self.id
666            .sio_out_xor()
667            .write(|w| unsafe { w.gpio_out_xor().bits(mask) });
668    }
669
670    #[inline]
671    pub(crate) fn _is_set_low(&self) -> bool {
672        let mask = self.id.mask();
673        self.id.sio_out().read().bits() & mask == 0
674    }
675
676    #[inline]
677    pub(crate) fn _is_set_high(&self) -> bool {
678        !self._is_set_low()
679    }
680
681    // =======================
682    // Interrupt related methods
683
684    /// Clear interrupt.
685    #[inline]
686    pub fn clear_interrupt(&mut self, interrupt: Interrupt) {
687        let (reg, offset) = self.id.intr();
688        let mask = interrupt.mask();
689        reg.write(|w| unsafe { w.bits(mask << offset) });
690    }
691
692    /// Interrupt status.
693    #[inline]
694    pub fn interrupt_status(&self, interrupt: Interrupt) -> bool {
695        let (reg, offset) = self.id.proc_ints(Sio::core());
696        let mask = interrupt.mask();
697        (reg.read().bits() >> offset) & mask == mask
698    }
699
700    /// Is interrupt enabled.
701    #[inline]
702    pub fn is_interrupt_enabled(&self, interrupt: Interrupt) -> bool {
703        let (reg, offset) = self.id.proc_inte(Sio::core());
704        let mask = interrupt.mask();
705        (reg.read().bits() >> offset) & mask == mask
706    }
707
708    /// Enable or disable interrupt.
709    #[inline]
710    pub fn set_interrupt_enabled(&self, interrupt: Interrupt, enabled: bool) {
711        let (reg, offset) = self.id.proc_inte(Sio::core());
712        let mask = interrupt.mask();
713        unsafe {
714            if enabled {
715                write_bitmask_set(reg.as_ptr(), mask << offset);
716            } else {
717                write_bitmask_clear(reg.as_ptr(), mask << offset);
718            }
719        }
720    }
721
722    /// Is interrupt forced.
723    #[inline]
724    pub fn is_interrupt_forced(&self, interrupt: Interrupt) -> bool {
725        let (reg, offset) = self.id.proc_intf(Sio::core());
726        let mask = interrupt.mask();
727        (reg.read().bits() >> offset) & mask == mask
728    }
729
730    /// Force or release interrupt.
731    #[inline]
732    pub fn set_interrupt_forced(&self, interrupt: Interrupt, forced: bool) {
733        let (reg, offset) = self.id.proc_intf(Sio::core());
734        let mask = interrupt.mask();
735        unsafe {
736            if forced {
737                write_bitmask_set(reg.as_ptr(), mask << offset);
738            } else {
739                write_bitmask_clear(reg.as_ptr(), mask << offset);
740            }
741        }
742    }
743
744    /// Dormant wake status.
745    #[inline]
746    pub fn dormant_wake_status(&self, interrupt: Interrupt) -> bool {
747        let (reg, offset) = self.id.dormant_wake_ints();
748        let mask = interrupt.mask();
749        (reg.read().bits() >> offset) & mask == mask
750    }
751
752    /// Is dormant wake enabled.
753    #[inline]
754    pub fn is_dormant_wake_enabled(&self, interrupt: Interrupt) -> bool {
755        let (reg, offset) = self.id.dormant_wake_inte();
756        let mask = interrupt.mask();
757        (reg.read().bits() >> offset) & mask == mask
758    }
759
760    /// Enable or disable dormant wake.
761    #[inline]
762    pub fn set_dormant_wake_enabled(&self, interrupt: Interrupt, enabled: bool) {
763        let (reg, offset) = self.id.dormant_wake_inte();
764        let mask = interrupt.mask();
765        unsafe {
766            if enabled {
767                write_bitmask_set(reg.as_ptr(), mask << offset);
768            } else {
769                write_bitmask_clear(reg.as_ptr(), mask << offset);
770            }
771        }
772    }
773
774    /// Is dormant wake forced.
775    #[inline]
776    pub fn is_dormant_wake_forced(&self, interrupt: Interrupt) -> bool {
777        let (reg, offset) = self.id.dormant_wake_intf();
778        let mask = interrupt.mask();
779        (reg.read().bits() >> offset) & mask == mask
780    }
781
782    /// Force dormant wake.
783    #[inline]
784    pub fn set_dormant_wake_forced(&mut self, interrupt: Interrupt, forced: bool) {
785        let (reg, offset) = self.id.dormant_wake_intf();
786        let mask = interrupt.mask();
787        unsafe {
788            if forced {
789                write_bitmask_set(reg.as_ptr(), mask << offset);
790            } else {
791                write_bitmask_clear(reg.as_ptr(), mask << offset);
792            }
793        }
794    }
795
796    /// Return a wrapper that implements InputPin.
797    ///
798    /// This allows to read from the pin independent of the selected function.
799    /// Depending on the pad configuration, reading from the pin may not return a
800    /// meaningful result.
801    ///
802    /// Calling this function does not set the pad's input enable bit.
803    pub fn as_input(&self) -> AsInputPin<I, F, P> {
804        AsInputPin(self)
805    }
806}
807impl<I: PinId, C: SioConfig, P: PullType> Pin<I, FunctionSio<C>, P> {
808    /// Is bypass enabled
809    #[inline]
810    pub fn is_sync_bypass(&self) -> bool {
811        let mask = self.id.mask();
812        self.id.proc_in_by_pass().read().bits() & mask == mask
813    }
814
815    /// Bypass the input sync stages.
816    ///
817    /// This saves two clock cycles in the input signal's path at the risks of introducing metastability.
818    #[inline]
819    pub fn set_sync_bypass(&mut self, bypass: bool) {
820        let mask = self.id.mask();
821        let reg = self.id.proc_in_by_pass();
822        unsafe {
823            if bypass {
824                write_bitmask_set(reg.as_ptr(), mask);
825            } else {
826                write_bitmask_clear(reg.as_ptr(), mask);
827            }
828        }
829    }
830}
831impl<F: func::Function, P: PullType> Pin<DynPinId, F, P> {
832    /// Try to return to a type-checked pin id.
833    ///
834    /// This method may fail if the target pin id differs from the current dynamic one.
835    pub fn try_into_pin<P2: pin::pin_sealed::TypeLevelPinId>(self) -> Result<Pin<P2, F, P>, Self> {
836        if P2::ID == self.id {
837            Ok(Pin {
838                id: P2::new(),
839                function: self.function,
840                pull_type: self.pull_type,
841            })
842        } else {
843            Err(self)
844        }
845    }
846
847    /// Try to change the pin's function.
848    pub fn try_into_function<F2>(self) -> Result<Pin<DynPinId, F2, P>, Pin<DynPinId, F, P>>
849    where
850        F2: func::Function,
851    {
852        // Thanks to type-level validation, we know F2 is valid for I
853        let prev_function = self.function.as_dyn();
854        let function = F2::from(prev_function);
855        let function_as_dyn = function.as_dyn();
856
857        use func_sealed::Function;
858        if function_as_dyn.is_valid(&self.id) {
859            if function_as_dyn != prev_function.as_dyn() {
860                pin::set_function(&self.id, function_as_dyn);
861            }
862            Ok(Pin {
863                function,
864                id: self.id,
865                pull_type: self.pull_type,
866            })
867        } else {
868            Err(self)
869        }
870    }
871}
872impl<I: PinId, P: PullType> Pin<I, DynFunction, P> {
873    /// Try to set the pin's function.
874    ///
875    /// This method may fail if the requested function is not supported by the pin, eg `FunctionXiP`
876    /// on a gpio from `Bank0`.
877    pub fn try_set_function(&mut self, function: DynFunction) -> Result<(), func::InvalidFunction> {
878        use func_sealed::Function;
879        if !function.is_valid(&self.id) {
880            return Err(func::InvalidFunction);
881        } else if function != self.function.as_dyn() {
882            pin::set_function(&self.id, function);
883            self.function = function;
884        }
885        Ok(())
886    }
887
888    /// Gets the pin's function.
889    pub fn function(&self) -> DynFunction {
890        use func_sealed::Function;
891        self.function.as_dyn()
892    }
893}
894
895impl<I: PinId, F: func::Function> Pin<I, F, DynPullType> {
896    /// Set the pin's pull type.
897    pub fn set_pull_type(&mut self, pull_type: DynPullType) {
898        if pull_type != self.pull_type {
899            pin::set_pull_type(&self.id, pull_type);
900            self.pull_type = pull_type;
901        }
902    }
903}
904
905/// Wrapper providing input pin functions for GPIO pins independent of the configured mode.
906pub struct AsInputPin<'a, I: PinId, F: func::Function, P: PullType>(&'a Pin<I, F, P>);
907
908//==============================================================================
909//  Embedded-HAL
910//==============================================================================
911
912/// GPIO error type.
913pub type Error = core::convert::Infallible;
914
915impl<I, P> embedded_hal_0_2::digital::v2::OutputPin for Pin<I, FunctionSio<SioOutput>, P>
916where
917    I: PinId,
918    P: PullType,
919{
920    type Error = Error;
921
922    fn set_low(&mut self) -> Result<(), Self::Error> {
923        self._set_low();
924        Ok(())
925    }
926
927    fn set_high(&mut self) -> Result<(), Self::Error> {
928        self._set_high();
929        Ok(())
930    }
931}
932
933/// Deprecated: Instead of implicitly implementing InputPin for function SioOutput,
934/// use `pin.as_input()` to get access to input values independent of the selected function.
935impl<I, P> embedded_hal_0_2::digital::v2::InputPin for Pin<I, FunctionSio<SioOutput>, P>
936where
937    I: PinId,
938    P: PullType,
939{
940    type Error = Error;
941
942    fn is_high(&self) -> Result<bool, Self::Error> {
943        Ok(self._is_high())
944    }
945
946    fn is_low(&self) -> Result<bool, Self::Error> {
947        Ok(self._is_low())
948    }
949}
950
951impl<I: PinId, F: func::Function, P: PullType> embedded_hal_0_2::digital::v2::InputPin
952    for AsInputPin<'_, I, F, P>
953{
954    type Error = core::convert::Infallible;
955
956    fn is_high(&self) -> Result<bool, Self::Error> {
957        Ok(self.0._is_high())
958    }
959
960    fn is_low(&self) -> Result<bool, Self::Error> {
961        Ok(self.0._is_low())
962    }
963}
964
965impl<I, P> embedded_hal_0_2::digital::v2::StatefulOutputPin for Pin<I, FunctionSio<SioOutput>, P>
966where
967    I: PinId,
968    P: PullType,
969{
970    fn is_set_high(&self) -> Result<bool, Self::Error> {
971        Ok(self._is_set_high())
972    }
973
974    fn is_set_low(&self) -> Result<bool, Self::Error> {
975        Ok(self._is_set_low())
976    }
977}
978
979impl<I, P> embedded_hal_0_2::digital::v2::ToggleableOutputPin for Pin<I, FunctionSio<SioOutput>, P>
980where
981    I: PinId,
982    P: PullType,
983{
984    type Error = Error;
985
986    fn toggle(&mut self) -> Result<(), Self::Error> {
987        self._toggle();
988        Ok(())
989    }
990}
991impl<I, P> embedded_hal_0_2::digital::v2::InputPin for Pin<I, FunctionSio<SioInput>, P>
992where
993    I: PinId,
994    P: PullType,
995{
996    type Error = Error;
997
998    fn is_high(&self) -> Result<bool, Self::Error> {
999        Ok(self._is_high())
1000    }
1001
1002    fn is_low(&self) -> Result<bool, Self::Error> {
1003        Ok(self._is_low())
1004    }
1005}
1006
1007//==============================================================================
1008//  Pins
1009//==============================================================================
1010
1011/// Default type state of a pin after reset of the pads, io and sio.
1012pub trait DefaultTypeState: crate::typelevel::Sealed {
1013    /// Default function.
1014    type Function: Function;
1015    /// Default pull type.
1016    type PullType: PullType;
1017}
1018
1019// Clear input enable for pins of bank0.
1020// Pins 26-29 are ADC pins. If the pins are connected to an analog input,
1021// the signal level may not be valid for a digital input. Therefore, input
1022// should be disabled by default.
1023// For the other GPIO pins, the same setting is applied for consistency.
1024macro_rules! reset_ie {
1025    ( Bank0, $pads:ident ) => {
1026        for id in (0..=29) {
1027            $pads.gpio(id).modify(|_, w| w.ie().clear_bit());
1028        }
1029    };
1030    ( Qspi, $pads:ident ) => {};
1031}
1032
1033macro_rules! gpio {
1034    ( $bank:ident:$prefix:ident, [ $(($id:expr, $pull_type:ident, $func:ident)),* ] ) => {
1035        paste::paste!{
1036            #[doc = "Pin bank " [<$bank>] ]
1037            pub mod [<$bank:snake>] {
1038                use $crate::pac::{[<IO_ $bank:upper>],[<PADS_ $bank:upper>]};
1039                use crate::sio::[<SioGpio $bank>];
1040                use super::{Pin, pin, pull, func};
1041                $(pub use super::pin::[<$bank:lower>]::[<$prefix $id>];)*
1042
1043                $(
1044                    impl super::DefaultTypeState for [<$prefix $id>] {
1045                        type Function = super::[<Function $func>];
1046                        type PullType = super::[<Pull $pull_type>];
1047                    }
1048                 )*
1049                gpio!(struct: $bank $prefix $([<$prefix $id>], $id, $func, $pull_type),*);
1050
1051                impl Pins {
1052                    /// Take ownership of the PAC peripherals and SIO slice and split it into discrete [`Pin`]s
1053                    ///
1054                    /// This clears the input-enable flag for all Bank0 pads.
1055                    pub fn new(io : [<IO_ $bank:upper>], pads: [<PADS_ $bank:upper>], sio: [<SioGpio $bank>], reset : &mut $crate::pac::RESETS) -> Self {
1056                        use $crate::resets::SubsystemReset;
1057                        pads.reset_bring_down(reset);
1058                        io.reset_bring_down(reset);
1059
1060                        {
1061                            use $crate::gpio::pin::DynBankId;
1062                            // SAFETY: this function owns the whole bank that will be affected.
1063                            let sio = unsafe { &*$crate::pac::SIO::PTR };
1064                            if DynBankId::$bank == DynBankId::Bank0 {
1065                                sio.gpio_oe().reset();
1066                                sio.gpio_out().reset();
1067                            } else {
1068                                sio.gpio_hi_oe().reset();
1069                                sio.gpio_hi_out().reset();
1070                            }
1071                        }
1072
1073                        io.reset_bring_up(reset);
1074                        pads.reset_bring_up(reset);
1075                        reset_ie!($bank, pads);
1076                        gpio!(members: io, pads, sio, $(([<$prefix $id>], $func, $pull_type)),+)
1077                    }
1078                }
1079            }
1080        }
1081    };
1082    (struct: $bank:ident $prefix:ident $($PXi:ident, $id:expr, $func:ident, $pull_type:ident),*) => {
1083        paste::paste!{
1084                /// Collection of all the individual [`Pin`]s
1085                #[derive(Debug)]
1086                pub struct Pins {
1087                    _io: [<IO_ $bank:upper>],
1088                    _pads: [<PADS_ $bank:upper>],
1089                    _sio: [<SioGpio $bank>],
1090                    $(
1091                        #[doc = "Pin " [<$PXi>] ]
1092                        pub [<$PXi:snake>]: Pin<pin::[<$bank:lower>]::[<$prefix $id>] , func::[<Function $func>], pull::[<Pull $pull_type>]>,
1093                     )*
1094                }
1095        }
1096    };
1097    (members: $io:ident, $pads:ident, $sio:ident, $(($PXi:ident, $func:ident, $pull_type:ident)),+) => {
1098        paste::paste!{
1099            Self {
1100                _io: $io,
1101                _pads: $pads,
1102                _sio: $sio,
1103                $(
1104                    [<$PXi:snake>]: Pin {
1105                        id: [<$PXi>] (()),
1106                        function: func::[<Function $func>] (()),
1107                        pull_type: pull::[<Pull $pull_type>] (())
1108                    },
1109                )+
1110            }
1111        }
1112    };
1113}
1114
1115gpio!(
1116    Bank0: Gpio,
1117    [
1118        (0, Down, Null),
1119        (1, Down, Null),
1120        (2, Down, Null),
1121        (3, Down, Null),
1122        (4, Down, Null),
1123        (5, Down, Null),
1124        (6, Down, Null),
1125        (7, Down, Null),
1126        (8, Down, Null),
1127        (9, Down, Null),
1128        (10, Down, Null),
1129        (11, Down, Null),
1130        (12, Down, Null),
1131        (13, Down, Null),
1132        (14, Down, Null),
1133        (15, Down, Null),
1134        (16, Down, Null),
1135        (17, Down, Null),
1136        (18, Down, Null),
1137        (19, Down, Null),
1138        (20, Down, Null),
1139        (21, Down, Null),
1140        (22, Down, Null),
1141        (23, Down, Null),
1142        (24, Down, Null),
1143        (25, Down, Null),
1144        (26, Down, Null),
1145        (27, Down, Null),
1146        (28, Down, Null),
1147        (29, Down, Null)
1148    ]
1149);
1150
1151gpio!(
1152    Qspi: Qspi,
1153    [
1154        (Sclk, Down, Null),
1155        (Ss, Up, Null),
1156        (Sd0, None, Null),
1157        (Sd1, None, Null),
1158        (Sd2, None, Null),
1159        (Sd3, None, Null)
1160    ]
1161);
1162
1163pub use bank0::Pins;
1164
1165//==============================================================================
1166//  AnyPin
1167//==============================================================================
1168
1169/// Type class for [`Pin`] types.
1170///
1171/// This trait uses the [`AnyKind`] trait pattern to create a [type class] for
1172/// [`Pin`] types. See the `AnyKind` documentation for more details on the
1173/// pattern.
1174///
1175/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
1176/// [type class]: crate::typelevel#type-classes
1177pub trait AnyPin: Sealed
1178where
1179    Self: typelevel::Sealed,
1180    Self: typelevel::Is<Type = SpecificPin<Self>>,
1181{
1182    /// [`PinId`] of the corresponding [`Pin`]
1183    type Id: PinId;
1184    /// [`func::Function`] of the corresponding [`Pin`]
1185    type Function: func::Function;
1186    /// [`PullType`] of the corresponding [`Pin`]
1187    type Pull: PullType;
1188}
1189
1190impl<I, F, P> Sealed for Pin<I, F, P>
1191where
1192    I: PinId,
1193    F: func::Function,
1194    P: PullType,
1195{
1196}
1197
1198impl<I, F, P> AnyPin for Pin<I, F, P>
1199where
1200    I: PinId,
1201    F: func::Function,
1202    P: PullType,
1203{
1204    type Id = I;
1205    type Function = F;
1206    type Pull = P;
1207}
1208
1209/// Type alias to recover the specific [`Pin`] type from an implementation of [`AnyPin`].
1210///
1211/// See the [`AnyKind`] documentation for more details on the pattern.
1212///
1213/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
1214pub type SpecificPin<P> = Pin<<P as AnyPin>::Id, <P as AnyPin>::Function, <P as AnyPin>::Pull>;
1215
1216//==============================================================================
1217//  bsp_pins helper macro
1218//==============================================================================
1219
1220/// Helper macro to give meaningful names to GPIO pins
1221///
1222/// The normal [`Pins`] struct names each [`Pin`] according to its [`PinId`].
1223/// However, BSP authors would prefer to name each [`Pin`] according to its
1224/// function. This macro defines a new `Pins` struct with custom field names
1225/// for each [`Pin`].
1226///
1227/// # Example
1228/// Calling the macro like this:
1229/// ```rust
1230/// use rp2040_hal::bsp_pins;
1231/// bsp_pins! {
1232///     #[cfg(feature = "gpio")]
1233///     Gpio0 {
1234///          /// Doc gpio0
1235///          name: gpio0,
1236///          aliases: { FunctionPio0, PullNone: PioPin }
1237///     },
1238///     Gpio1 {
1239///          name: led,
1240///          aliases: { FunctionPwm, PullDown: LedPwm }
1241///      },
1242/// }
1243/// ```
1244///
1245/// Is roughly equivalent to the following source code (excluding the docs strings below):
1246/// ```
1247/// use ::rp2040_hal as hal;
1248/// use hal::gpio;
1249/// pub struct Pins {
1250///     /// Doc gpio0
1251///     #[cfg(feature = "gpio")]
1252///     pub gpio0: gpio::Pin<
1253///         gpio::bank0::Gpio0,
1254///         <gpio::bank0::Gpio0 as gpio::DefaultTypeState>::Function,
1255///         <gpio::bank0::Gpio0 as gpio::DefaultTypeState>::PullType,
1256///     >,
1257///     pub led: gpio::Pin<
1258///         gpio::bank0::Gpio1,
1259///         <gpio::bank0::Gpio1 as gpio::DefaultTypeState>::Function,
1260///         <gpio::bank0::Gpio1 as gpio::DefaultTypeState>::PullType,
1261///     >,
1262/// }
1263/// impl Pins {
1264///     #[inline]
1265///     pub fn new(
1266///         io: hal::pac::IO_BANK0,
1267///         pads: hal::pac::PADS_BANK0,
1268///         sio: hal::sio::SioGpioBank0,
1269///         reset: &mut hal::pac::RESETS,
1270///     ) -> Self {
1271///         let mut pins = gpio::Pins::new(io, pads, sio, reset);
1272///         Self {
1273///             #[cfg(feature = "gpio")]
1274///             gpio0: pins.gpio0,
1275///             led: pins.gpio1,
1276///         }
1277///     }
1278/// }
1279/// pub type PioPin = gpio::Pin<gpio::bank0::Gpio0, gpio::FunctionPio0, gpio::PullNone>;
1280/// pub type LedPwm = gpio::Pin<gpio::bank0::Gpio1, gpio::FunctionPwm, gpio::PullDown>;
1281/// ```
1282#[macro_export]
1283macro_rules! bsp_pins {
1284    (
1285        $(
1286            $( #[$id_cfg:meta] )*
1287            $Id:ident {
1288                $( #[$name_doc:meta] )*
1289                name: $name:ident $(,)?
1290                $(
1291                    aliases: {
1292                        $(
1293                            $( #[$alias_cfg:meta] )*
1294                            $Function:ty, $PullType:ident: $Alias:ident
1295                        ),+
1296                    }
1297                )?
1298            } $(,)?
1299        )+
1300    ) => {
1301        $crate::paste::paste! {
1302
1303            /// BSP replacement for the HAL
1304            /// [`Pins`](rp2040_hal::gpio::Pins) type
1305            ///
1306            /// This type is intended to provide more meaningful names for the
1307            /// given pins.
1308            ///
1309            /// To enable specific functions of the pins you can use the
1310            /// [rp2040_hal::gpio::pin::Pin::into_function] function with
1311            /// one of:
1312            /// - [rp2040_hal::gpio::FunctionI2C]
1313            /// - [rp2040_hal::gpio::FunctionPwm]
1314            /// - [rp2040_hal::gpio::FunctionSpi]
1315            /// - [rp2040_hal::gpio::FunctionXip]
1316            /// - [rp2040_hal::gpio::FunctionPio0]
1317            /// - [rp2040_hal::gpio::FunctionPio1]
1318            /// - [rp2040_hal::gpio::FunctionUart]
1319            ///
1320            /// like this:
1321            ///```no_run
1322            /// use rp2040_hal::{pac, gpio::{bank0::Gpio12, Pin, Pins}, sio::Sio};
1323            ///
1324            /// let mut peripherals = pac::Peripherals::take().unwrap();
1325            /// let sio = Sio::new(peripherals.SIO);
1326            /// let pins = Pins::new(peripherals.IO_BANK0,peripherals.PADS_BANK0,sio.gpio_bank0, &mut peripherals.RESETS);
1327            ///
1328            /// let _spi_sclk = pins.gpio2.into_function::<rp2040_hal::gpio::FunctionSpi>();
1329            /// let _spi_mosi = pins.gpio3.into_function::<rp2040_hal::gpio::FunctionSpi>();
1330            /// let _spi_miso = pins.gpio4.into_function::<rp2040_hal::gpio::FunctionSpi>();
1331            ///```
1332            ///
1333            /// **See also [rp2040_hal::gpio] for more in depth information about this**!
1334            pub struct Pins {
1335                $(
1336                    $( #[$id_cfg] )*
1337                    $( #[$name_doc] )*
1338                    pub $name: $crate::gpio::Pin<
1339                        $crate::gpio::bank0::$Id,
1340                        <$crate::gpio::bank0::$Id as $crate::gpio::DefaultTypeState>::Function,
1341                        <$crate::gpio::bank0::$Id as $crate::gpio::DefaultTypeState>::PullType,
1342                    >,
1343                )+
1344            }
1345
1346            impl Pins {
1347                /// Take ownership of the PAC [`PORT`] and split it into
1348                /// discrete [`Pin`]s.
1349                ///
1350                /// This struct serves as a replacement for the HAL [`Pins`]
1351                /// struct. It is intended to provide more meaningful names for
1352                /// each [`Pin`] in a BSP. Any [`Pin`] not defined by the BSP is
1353                /// dropped.
1354                ///
1355                /// [`Pin`](rp2040_hal::gpio::Pin)
1356                /// [`Pins`](rp2040_hal::gpio::Pins)
1357                #[inline]
1358                pub fn new(io : $crate::pac::IO_BANK0, pads: $crate::pac::PADS_BANK0, sio: $crate::sio::SioGpioBank0, reset : &mut $crate::pac::RESETS) -> Self {
1359                    let mut pins = $crate::gpio::Pins::new(io,pads,sio,reset);
1360                    Self {
1361                        $(
1362                            $( #[$id_cfg] )*
1363                            $name: pins.[<$Id:lower>],
1364                        )+
1365                    }
1366                }
1367            }
1368            $(
1369                $( #[$id_cfg] )*
1370                $crate::bsp_pins!(@aliases, $( $( $( #[$alias_cfg] )* $Id $Function $PullType $Alias )+ )? );
1371            )+
1372        }
1373    };
1374    ( @aliases, $( $( $( #[$attr:meta] )* $Id:ident $Function:ident $PullType:ident $Alias:ident )+ )? ) => {
1375        $crate::paste::paste! {
1376            $(
1377                $(
1378                    $( #[$attr] )*
1379                    /// Alias for a configured [`Pin`](rp2040_hal::gpio::Pin)
1380                    pub type $Alias = $crate::gpio::Pin<
1381                        $crate::gpio::bank0::$Id,
1382                        $crate::gpio::$Function,
1383                        $crate::gpio::$PullType
1384                    >;
1385                )+
1386            )?
1387        }
1388    };
1389}
1390
1391//==============================================================================
1392//  InOutPin
1393//==============================================================================
1394
1395/// A wrapper [`AnyPin`]`<Function = `[`FunctionSioOutput`]`>` emulating open-drain function.
1396///
1397/// This wrapper implements both InputPin and OutputPin, to simulate an open-drain pin as needed for
1398/// example by the wire protocol the DHT11 sensor speaks.
1399///
1400/// <https://how2electronics.com/interfacing-dht11-temperature-humidity-sensor-with-raspberry-pi-pico/>
1401pub struct InOutPin<T: AnyPin> {
1402    inner: Pin<T::Id, FunctionSioOutput, T::Pull>,
1403}
1404
1405impl<T: AnyPin> InOutPin<T> {
1406    /// Create a new wrapper
1407    pub fn new(inner: T) -> InOutPin<T>
1408    where
1409        T::Id: ValidFunction<FunctionSioOutput>,
1410    {
1411        let mut inner = inner.into();
1412        inner.set_output_enable_override(OutputEnableOverride::Disable);
1413
1414        // into Pin<_, FunctionSioOutput, _>
1415        let inner = inner.into_push_pull_output_in_state(PinState::Low);
1416
1417        Self { inner }
1418    }
1419}
1420
1421impl<T> InOutPin<T>
1422where
1423    T: AnyPin,
1424    T::Id: ValidFunction<T::Function>,
1425{
1426    /// Releases the pin reverting to its previous function.
1427    pub fn release(self) -> T {
1428        // restore the previous typestate first
1429        let mut inner = self.inner.reconfigure();
1430        // disable override
1431        inner.set_output_enable_override(OutputEnableOverride::Normal);
1432        // typelevel-return
1433        T::from(inner)
1434    }
1435}
1436
1437impl<T: AnyPin> embedded_hal_0_2::digital::v2::InputPin for InOutPin<T> {
1438    type Error = Error;
1439    fn is_high(&self) -> Result<bool, Error> {
1440        self.inner.is_high()
1441    }
1442
1443    fn is_low(&self) -> Result<bool, Error> {
1444        self.inner.is_low()
1445    }
1446}
1447
1448impl<T: AnyPin> embedded_hal_0_2::digital::v2::OutputPin for InOutPin<T> {
1449    type Error = Error;
1450    fn set_low(&mut self) -> Result<(), Error> {
1451        // The pin is already set to output low but this is inhibited by the override.
1452        self.inner
1453            .set_output_enable_override(OutputEnableOverride::Enable);
1454        Ok(())
1455    }
1456
1457    fn set_high(&mut self) -> Result<(), Error> {
1458        // To set the open-drain pin to high, just disable the output driver by configuring the
1459        // output override. That way, the DHT11 can still pull the data line down to send its response.
1460        self.inner
1461            .set_output_enable_override(OutputEnableOverride::Disable);
1462        Ok(())
1463    }
1464}
1465
1466mod eh1 {
1467    use embedded_hal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin};
1468
1469    use super::{
1470        func, AnyPin, AsInputPin, Error, FunctionSio, InOutPin, OutputEnableOverride, Pin, PinId,
1471        PullType, SioConfig, SioInput, SioOutput,
1472    };
1473
1474    impl<I, P, S> ErrorType for Pin<I, FunctionSio<S>, P>
1475    where
1476        I: PinId,
1477        P: PullType,
1478        S: SioConfig,
1479    {
1480        type Error = Error;
1481    }
1482
1483    impl<I, P> OutputPin for Pin<I, FunctionSio<SioOutput>, P>
1484    where
1485        I: PinId,
1486        P: PullType,
1487    {
1488        fn set_low(&mut self) -> Result<(), Self::Error> {
1489            self._set_low();
1490            Ok(())
1491        }
1492
1493        fn set_high(&mut self) -> Result<(), Self::Error> {
1494            self._set_high();
1495            Ok(())
1496        }
1497    }
1498
1499    impl<I, P> StatefulOutputPin for Pin<I, FunctionSio<SioOutput>, P>
1500    where
1501        I: PinId,
1502        P: PullType,
1503    {
1504        fn is_set_high(&mut self) -> Result<bool, Self::Error> {
1505            Ok(self._is_set_high())
1506        }
1507
1508        fn is_set_low(&mut self) -> Result<bool, Self::Error> {
1509            Ok(self._is_set_low())
1510        }
1511
1512        fn toggle(&mut self) -> Result<(), Self::Error> {
1513            self._toggle();
1514            Ok(())
1515        }
1516    }
1517
1518    impl<I, P> InputPin for Pin<I, FunctionSio<SioInput>, P>
1519    where
1520        I: PinId,
1521        P: PullType,
1522    {
1523        fn is_high(&mut self) -> Result<bool, Self::Error> {
1524            Ok(self._is_high())
1525        }
1526
1527        fn is_low(&mut self) -> Result<bool, Self::Error> {
1528            Ok(self._is_low())
1529        }
1530    }
1531
1532    impl<I, F, P> ErrorType for AsInputPin<'_, I, F, P>
1533    where
1534        I: PinId,
1535        F: func::Function,
1536        P: PullType,
1537    {
1538        type Error = Error;
1539    }
1540
1541    impl<I: PinId, F: func::Function, P: PullType> InputPin for AsInputPin<'_, I, F, P> {
1542        fn is_high(&mut self) -> Result<bool, Self::Error> {
1543            Ok(self.0._is_high())
1544        }
1545
1546        fn is_low(&mut self) -> Result<bool, Self::Error> {
1547            Ok(self.0._is_low())
1548        }
1549    }
1550
1551    impl<I> ErrorType for InOutPin<I>
1552    where
1553        I: AnyPin,
1554    {
1555        type Error = Error;
1556    }
1557
1558    impl<I> OutputPin for InOutPin<I>
1559    where
1560        I: AnyPin,
1561    {
1562        fn set_low(&mut self) -> Result<(), Self::Error> {
1563            // The pin is already set to output low but this is inhibited by the override.
1564            self.inner
1565                .set_output_enable_override(OutputEnableOverride::Enable);
1566            Ok(())
1567        }
1568
1569        fn set_high(&mut self) -> Result<(), Self::Error> {
1570            // To set the open-drain pin to high, just disable the output driver by configuring the
1571            // output override. That way, the DHT11 can still pull the data line down to send its response.
1572            self.inner
1573                .set_output_enable_override(OutputEnableOverride::Disable);
1574            Ok(())
1575        }
1576    }
1577
1578    impl<I> InputPin for InOutPin<I>
1579    where
1580        I: AnyPin,
1581    {
1582        fn is_high(&mut self) -> Result<bool, Self::Error> {
1583            Ok(self.inner._is_high())
1584        }
1585
1586        fn is_low(&mut self) -> Result<bool, Self::Error> {
1587            Ok(self.inner._is_low())
1588        }
1589    }
1590}