stm32f7xx_hal/gpio/
partially_erased.rs

1use super::*;
2
3pub type PEPin<const P: char, MODE> = PartiallyErasedPin<P, MODE>;
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<const P: char, MODE> {
10    i: u8,
11    _mode: PhantomData<MODE>,
12}
13
14impl<const P: char, MODE> PartiallyErasedPin<P, MODE> {
15    pub(crate) fn new(i: u8) -> Self {
16        Self {
17            i,
18            _mode: PhantomData,
19        }
20    }
21}
22
23impl<const P: char, MODE> fmt::Debug for PartiallyErasedPin<P, MODE> {
24    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
25        formatter.write_fmt(format_args!(
26            "P{}({})<{}>",
27            P,
28            self.i,
29            crate::stripped_type_name::<MODE>()
30        ))
31    }
32}
33
34impl<const P: char, MODE> PinExt for PartiallyErasedPin<P, MODE> {
35    type Mode = MODE;
36
37    #[inline(always)]
38    fn pin_id(&self) -> u8 {
39        self.i
40    }
41    #[inline(always)]
42    fn port_id(&self) -> u8 {
43        P as u8 - b'A'
44    }
45}
46
47impl<const P: char, MODE> PartiallyErasedPin<P, Output<MODE>> {
48    #[inline(always)]
49    pub fn set_high(&mut self) {
50        // NOTE(unsafe) atomic write to a stateless register
51        unsafe { (*Gpio::<P>::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }
52    }
53
54    #[inline(always)]
55    pub fn set_low(&mut self) {
56        // NOTE(unsafe) atomic write to a stateless register
57        unsafe {
58            (*Gpio::<P>::ptr())
59                .bsrr
60                .write(|w| w.bits(1 << (self.i + 16)))
61        }
62    }
63
64    #[inline(always)]
65    pub fn get_state(&self) -> PinState {
66        if self.is_set_low() {
67            PinState::Low
68        } else {
69            PinState::High
70        }
71    }
72
73    #[inline(always)]
74    pub fn set_state(&mut self, state: PinState) {
75        match state {
76            PinState::Low => self.set_low(),
77            PinState::High => self.set_high(),
78        }
79    }
80
81    #[inline(always)]
82    pub fn is_set_high(&self) -> bool {
83        !self.is_set_low()
84    }
85
86    #[inline(always)]
87    pub fn is_set_low(&self) -> bool {
88        // NOTE(unsafe) atomic read with no side effects
89        unsafe { (*Gpio::<P>::ptr()).odr.read().bits() & (1 << self.i) == 0 }
90    }
91
92    #[inline(always)]
93    pub fn toggle(&mut self) {
94        if self.is_set_low() {
95            self.set_high()
96        } else {
97            self.set_low()
98        }
99    }
100}
101
102impl<const P: char> PartiallyErasedPin<P, Output<OpenDrain>> {
103    #[inline(always)]
104    pub fn is_high(&self) -> bool {
105        !self.is_low()
106    }
107
108    #[inline(always)]
109    pub fn is_low(&self) -> bool {
110        // NOTE(unsafe) atomic read with no side effects
111        unsafe { (*Gpio::<P>::ptr()).idr.read().bits() & (1 << self.i) == 0 }
112    }
113}
114
115impl<const P: char, MODE> PartiallyErasedPin<P, Input<MODE>> {
116    #[inline(always)]
117    pub fn is_high(&self) -> bool {
118        !self.is_low()
119    }
120
121    #[inline(always)]
122    pub fn is_low(&self) -> bool {
123        // NOTE(unsafe) atomic read with no side effects
124        unsafe { (*Gpio::<P>::ptr()).idr.read().bits() & (1 << self.i) == 0 }
125    }
126}