stm32l4xx_hal/gpio/
partially_erased.rs

1use super::*;
2
3pub type PEPin<MODE, const P: char> = PartiallyErasedPin<MODE, P>;
4
5/// Partially erased pin
6///
7/// - `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section).
8/// - `P` is port name: `A` for GPIOA, `B` for GPIOB, etc.
9pub struct PartiallyErasedPin<MODE, const P: char> {
10    i: u8,
11    _mode: PhantomData<MODE>,
12}
13
14impl<MODE, const P: char> PartiallyErasedPin<MODE, P> {
15    pub(crate) fn new(i: u8) -> Self {
16        Self {
17            i,
18            _mode: PhantomData,
19        }
20    }
21}
22
23impl<MODE, const P: char> PinExt for PartiallyErasedPin<MODE, P> {
24    type Mode = MODE;
25
26    #[inline(always)]
27    fn pin_id(&self) -> u8 {
28        self.i
29    }
30    #[inline(always)]
31    fn port_id(&self) -> u8 {
32        P as u8 - b'A'
33    }
34}
35
36impl<MODE, const P: char> PartiallyErasedPin<Output<MODE>, P> {
37    #[inline(always)]
38    pub fn set_high(&mut self) {
39        // NOTE(unsafe) atomic write to a stateless register
40        unsafe { (*Gpio::<P>::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }
41    }
42
43    #[inline(always)]
44    pub fn set_low(&mut self) {
45        // NOTE(unsafe) atomic write to a stateless register
46        unsafe {
47            (*Gpio::<P>::ptr())
48                .bsrr
49                .write(|w| w.bits(1 << (self.i + 16)))
50        }
51    }
52
53    #[inline(always)]
54    pub fn get_state(&self) -> PinState {
55        if self.is_set_low() {
56            PinState::Low
57        } else {
58            PinState::High
59        }
60    }
61
62    #[inline(always)]
63    pub fn set_state(&mut self, state: PinState) {
64        match state {
65            PinState::Low => self.set_low(),
66            PinState::High => self.set_high(),
67        }
68    }
69
70    #[inline(always)]
71    pub fn is_set_high(&self) -> bool {
72        !self.is_set_low()
73    }
74
75    #[inline(always)]
76    pub fn is_set_low(&self) -> bool {
77        // NOTE(unsafe) atomic read with no side effects
78        unsafe { (*Gpio::<P>::ptr()).odr.read().bits() & (1 << self.i) == 0 }
79    }
80
81    #[inline(always)]
82    pub fn toggle(&mut self) {
83        if self.is_set_low() {
84            self.set_high()
85        } else {
86            self.set_low()
87        }
88    }
89}
90
91impl<MODE, const P: char> OutputPin for PartiallyErasedPin<Output<MODE>, P> {
92    type Error = Infallible;
93
94    #[inline(always)]
95    fn set_high(&mut self) -> Result<(), Self::Error> {
96        self.set_high();
97        Ok(())
98    }
99
100    #[inline(always)]
101    fn set_low(&mut self) -> Result<(), Self::Error> {
102        self.set_low();
103        Ok(())
104    }
105}
106
107impl<MODE, const P: char> StatefulOutputPin for PartiallyErasedPin<Output<MODE>, P> {
108    #[inline(always)]
109    fn is_set_high(&self) -> Result<bool, Self::Error> {
110        Ok(self.is_set_high())
111    }
112
113    #[inline(always)]
114    fn is_set_low(&self) -> Result<bool, Self::Error> {
115        Ok(self.is_set_low())
116    }
117}
118
119impl<MODE, const P: char> ToggleableOutputPin for PartiallyErasedPin<Output<MODE>, P> {
120    type Error = Infallible;
121
122    #[inline(always)]
123    fn toggle(&mut self) -> Result<(), Self::Error> {
124        self.toggle();
125        Ok(())
126    }
127}
128
129impl<const P: char> PartiallyErasedPin<Output<OpenDrain>, P> {
130    #[inline(always)]
131    pub fn is_high(&self) -> bool {
132        !self.is_low()
133    }
134
135    #[inline(always)]
136    pub fn is_low(&self) -> bool {
137        // NOTE(unsafe) atomic read with no side effects
138        unsafe { (*Gpio::<P>::ptr()).idr.read().bits() & (1 << self.i) == 0 }
139    }
140}
141
142impl<const P: char> InputPin for PartiallyErasedPin<Output<OpenDrain>, P> {
143    type Error = Infallible;
144
145    #[inline(always)]
146    fn is_high(&self) -> Result<bool, Self::Error> {
147        Ok(self.is_high())
148    }
149
150    #[inline(always)]
151    fn is_low(&self) -> Result<bool, Self::Error> {
152        Ok(self.is_low())
153    }
154}
155
156impl<MODE, const P: char> PartiallyErasedPin<Input<MODE>, P> {
157    #[inline(always)]
158    pub fn is_high(&self) -> bool {
159        !self.is_low()
160    }
161
162    #[inline(always)]
163    pub fn is_low(&self) -> bool {
164        // NOTE(unsafe) atomic read with no side effects
165        unsafe { (*Gpio::<P>::ptr()).idr.read().bits() & (1 << self.i) == 0 }
166    }
167}
168
169impl<MODE, const P: char> InputPin for PartiallyErasedPin<Input<MODE>, P> {
170    type Error = Infallible;
171
172    #[inline(always)]
173    fn is_high(&self) -> Result<bool, Self::Error> {
174        Ok(self.is_high())
175    }
176
177    #[inline(always)]
178    fn is_low(&self) -> Result<bool, Self::Error> {
179        Ok(self.is_low())
180    }
181}