ariel_os_rp/
gpio.rs

1//! Provides GPIO access.
2
3pub mod input {
4    //! Input-specific types.
5
6    use embassy_rp::{
7        Peripheral,
8        gpio::{Level, Pull},
9    };
10
11    #[cfg(feature = "external-interrupts")]
12    use ariel_os_embassy_common::gpio::input::InterruptError;
13
14    #[doc(hidden)]
15    pub use embassy_rp::gpio::{Input, Pin as InputPin};
16
17    // Re-export `Input` as `IntEnabledInput` as they are interrupt-enabled.
18    #[cfg(feature = "external-interrupts")]
19    #[doc(hidden)]
20    pub use embassy_rp::gpio::Input as IntEnabledInput;
21
22    /// Whether inputs support configuring whether a Schmitt trigger is enabled.
23    pub const SCHMITT_TRIGGER_CONFIGURABLE: bool = true;
24
25    #[doc(hidden)]
26    pub fn new(
27        pin: impl Peripheral<P: InputPin> + 'static,
28        pull: ariel_os_embassy_common::gpio::Pull,
29        schmitt_trigger: bool,
30    ) -> Result<Input<'static>, core::convert::Infallible> {
31        let pull = from_pull(pull);
32
33        let mut input = Input::new(pin, pull);
34        input.set_schmitt(schmitt_trigger);
35
36        Ok(input)
37    }
38
39    #[cfg(feature = "external-interrupts")]
40    #[doc(hidden)]
41    pub fn new_int_enabled(
42        pin: impl Peripheral<P: InputPin> + 'static,
43        pull: ariel_os_embassy_common::gpio::Pull,
44        schmitt_trigger: bool,
45    ) -> Result<IntEnabledInput<'static>, InterruptError> {
46        // This HAL does not require special treatment of external interrupts.
47        match new(pin, pull, schmitt_trigger) {
48            Ok(input) => Ok(input),
49            Err(err) => match err {
50                // Compile-time check that this never happens as the Result is Infallible.
51            },
52        }
53    }
54
55    ariel_os_embassy_common::define_from_pull!();
56    ariel_os_embassy_common::define_into_level!();
57}
58
59pub mod output {
60    //! Output-specific types.
61
62    use embassy_rp::{Peripheral, gpio::Level};
63
64    #[doc(hidden)]
65    pub use embassy_rp::gpio::{Output, Pin as OutputPin};
66
67    /// Whether outputs support configuring their drive strength.
68    pub const DRIVE_STRENGTH_CONFIGURABLE: bool = true;
69    /// Whether outputs support configuring their speed/slew rate.
70    pub const SPEED_CONFIGURABLE: bool = true;
71
72    #[doc(hidden)]
73    pub fn new(
74        pin: impl Peripheral<P: OutputPin> + 'static,
75        initial_level: ariel_os_embassy_common::gpio::Level,
76        drive_strength: super::DriveStrength,
77        speed: super::Speed,
78    ) -> Output<'static> {
79        let initial_level = match initial_level {
80            ariel_os_embassy_common::gpio::Level::Low => Level::Low,
81            ariel_os_embassy_common::gpio::Level::High => Level::High,
82        };
83        let mut output = Output::new(pin, initial_level);
84        output.set_drive_strength(drive_strength.into());
85        output.set_slew_rate(speed.into());
86        output
87    }
88}
89
90/// Available drive strength settings.
91// We provide our own type because the upstream type is not `Copy` and has no `Default` impl.
92#[derive(Copy, Clone, PartialEq, Eq, Default)]
93pub enum DriveStrength {
94    /// 2 mA.
95    _2mA,
96    /// 4 mA. This is the reset value.
97    #[default]
98    _4mA,
99    /// 8 mA.
100    _8mA,
101    /// 12 mA.
102    _12mA,
103}
104
105impl From<DriveStrength> for embassy_rp::gpio::Drive {
106    fn from(drive_strength: DriveStrength) -> Self {
107        match drive_strength {
108            DriveStrength::_2mA => Self::_2mA,
109            DriveStrength::_4mA => Self::_4mA,
110            DriveStrength::_8mA => Self::_8mA,
111            DriveStrength::_12mA => Self::_12mA,
112        }
113    }
114}
115
116impl ariel_os_embassy_common::gpio::FromDriveStrength for DriveStrength {
117    fn from(drive_strength: ariel_os_embassy_common::gpio::DriveStrength<Self>) -> Self {
118        // ESPs are able to output up to 40 mA, so we somewhat normalize this.
119        match drive_strength {
120            ariel_os_embassy_common::gpio::DriveStrength::Hal(drive_strength) => drive_strength,
121            ariel_os_embassy_common::gpio::DriveStrength::Lowest => Self::_2mA,
122            ariel_os_embassy_common::gpio::DriveStrength::Standard => Self::default(),
123            ariel_os_embassy_common::gpio::DriveStrength::Medium => Self::_8mA,
124            ariel_os_embassy_common::gpio::DriveStrength::High
125            | ariel_os_embassy_common::gpio::DriveStrength::Highest => Self::_12mA,
126        }
127    }
128}
129
130/// Available output speed/slew rate settings.
131// These values do not seem to be quantitatively defined on the RP2040.
132// We provide our own type because the `SlewRate` upstream type is not `Copy` and has no
133// `Default` impl.
134#[derive(Copy, Clone, PartialEq, Eq, Default)]
135pub enum Speed {
136    /// Low. This is the reset value.
137    #[default]
138    Low,
139    /// High.
140    High,
141}
142
143impl From<Speed> for embassy_rp::gpio::SlewRate {
144    fn from(speed: Speed) -> Self {
145        match speed {
146            Speed::Low => Self::Slow,
147            Speed::High => Self::Fast,
148        }
149    }
150}
151
152impl ariel_os_embassy_common::gpio::FromSpeed for Speed {
153    fn from(speed: ariel_os_embassy_common::gpio::Speed<Self>) -> Self {
154        match speed {
155            ariel_os_embassy_common::gpio::Speed::Hal(speed) => speed,
156            ariel_os_embassy_common::gpio::Speed::Low
157            | ariel_os_embassy_common::gpio::Speed::Medium => Self::Low,
158            ariel_os_embassy_common::gpio::Speed::High
159            | ariel_os_embassy_common::gpio::Speed::VeryHigh => Self::High,
160        }
161    }
162}