ariel_os_rp/
gpio.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
//! Provides GPIO access.

pub mod input {
    //! Input-specific types.

    use embassy_rp::{
        gpio::{Level, Pull},
        Peripheral,
    };

    #[cfg(feature = "external-interrupts")]
    use ariel_os_embassy_common::gpio::input::InterruptError;

    #[doc(hidden)]
    pub use embassy_rp::gpio::{Input, Pin as InputPin};

    // Re-export `Input` as `IntEnabledInput` as they are interrupt-enabled.
    #[cfg(feature = "external-interrupts")]
    #[doc(hidden)]
    pub use embassy_rp::gpio::Input as IntEnabledInput;

    /// Whether inputs support configuring whether a Schmitt trigger is enabled.
    pub const SCHMITT_TRIGGER_CONFIGURABLE: bool = true;

    #[doc(hidden)]
    pub fn new(
        pin: impl Peripheral<P: InputPin> + 'static,
        pull: ariel_os_embassy_common::gpio::Pull,
        schmitt_trigger: bool,
    ) -> Result<Input<'static>, core::convert::Infallible> {
        let pull = from_pull(pull);

        let mut input = Input::new(pin, pull);
        input.set_schmitt(schmitt_trigger);

        Ok(input)
    }

    #[cfg(feature = "external-interrupts")]
    #[doc(hidden)]
    pub fn new_int_enabled(
        pin: impl Peripheral<P: InputPin> + 'static,
        pull: ariel_os_embassy_common::gpio::Pull,
        schmitt_trigger: bool,
    ) -> Result<IntEnabledInput<'static>, InterruptError> {
        // This HAL does not require special treatment of external interrupts.
        match new(pin, pull, schmitt_trigger) {
            Ok(input) => Ok(input),
            Err(err) => match err {
                // Compile-time check that this never happens as the Result is Infallible.
            },
        }
    }

    ariel_os_embassy_common::define_from_pull!();
    ariel_os_embassy_common::define_into_level!();
}

pub mod output {
    //! Output-specific types.

    use embassy_rp::{gpio::Level, Peripheral};

    #[doc(hidden)]
    pub use embassy_rp::gpio::{Output, Pin as OutputPin};

    /// Whether outputs support configuring their drive strength.
    pub const DRIVE_STRENGTH_CONFIGURABLE: bool = true;
    /// Whether outputs support configuring their speed/slew rate.
    pub const SPEED_CONFIGURABLE: bool = true;

    #[doc(hidden)]
    pub fn new(
        pin: impl Peripheral<P: OutputPin> + 'static,
        initial_level: ariel_os_embassy_common::gpio::Level,
        drive_strength: super::DriveStrength,
        speed: super::Speed,
    ) -> Output<'static> {
        let initial_level = match initial_level {
            ariel_os_embassy_common::gpio::Level::Low => Level::Low,
            ariel_os_embassy_common::gpio::Level::High => Level::High,
        };
        let mut output = Output::new(pin, initial_level);
        output.set_drive_strength(drive_strength.into());
        output.set_slew_rate(speed.into());
        output
    }
}

/// Available drive strength settings.
// We provide our own type because the upstream type is not `Copy` and has no `Default` impl.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum DriveStrength {
    /// 2 mA.
    _2mA,
    /// 4 mA.
    _4mA,
    /// 8 mA.
    _8mA,
    /// 12 mA.
    _12mA,
}

impl Default for DriveStrength {
    fn default() -> Self {
        // Reset value
        Self::_4mA
    }
}

impl From<DriveStrength> for embassy_rp::gpio::Drive {
    fn from(drive_strength: DriveStrength) -> Self {
        match drive_strength {
            DriveStrength::_2mA => Self::_2mA,
            DriveStrength::_4mA => Self::_4mA,
            DriveStrength::_8mA => Self::_8mA,
            DriveStrength::_12mA => Self::_12mA,
        }
    }
}

impl ariel_os_embassy_common::gpio::FromDriveStrength for DriveStrength {
    fn from(drive_strength: ariel_os_embassy_common::gpio::DriveStrength<Self>) -> Self {
        use ariel_os_embassy_common::gpio::DriveStrength::*;

        // ESPs are able to output up to 40 mA, so we somewhat normalize this.
        match drive_strength {
            Hal(drive_strength) => drive_strength,
            Lowest => Self::_2mA,
            Standard => Self::default(),
            Medium => Self::_8mA,
            High => Self::_12mA,
            Highest => Self::_12mA,
        }
    }
}

/// Available output speed/slew rate settings.
// These values do not seem to be quantitatively defined on the RP2040.
// We provide our own type because the `SlewRate` upstream type is not `Copy` and has no
// `Default` impl.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Speed {
    /// Low.
    Low,
    /// High.
    High,
}

impl Default for Speed {
    fn default() -> Self {
        // Reset value
        Self::Low
    }
}

impl From<Speed> for embassy_rp::gpio::SlewRate {
    fn from(speed: Speed) -> Self {
        match speed {
            Speed::Low => Self::Slow,
            Speed::High => Self::Fast,
        }
    }
}

impl ariel_os_embassy_common::gpio::FromSpeed for Speed {
    fn from(speed: ariel_os_embassy_common::gpio::Speed<Self>) -> Self {
        use ariel_os_embassy_common::gpio::Speed::*;

        match speed {
            Hal(speed) => speed,
            Low => Self::Low,
            Medium => Self::Low,
            High => Self::High,
            VeryHigh => Self::High,
        }
    }
}