stm32f1_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    pin_number: u8,
11    _mode: PhantomData<MODE>,
12}
13
14impl<const P: char, MODE> PartiallyErasedPin<P, MODE> {
15    pub(crate) fn new(pin_number: u8) -> Self {
16        Self {
17            pin_number,
18            _mode: PhantomData,
19        }
20    }
21}
22
23impl<const P: char, MODE> PinExt for PartiallyErasedPin<P, MODE> {
24    type Mode = MODE;
25
26    #[inline(always)]
27    fn pin_id(&self) -> u8 {
28        self.pin_number
29    }
30
31    #[inline(always)]
32    fn port_id(&self) -> u8 {
33        P as u8 - b'A'
34    }
35}
36
37impl<const P: char, MODE> PartiallyErasedPin<P, Output<MODE>> {
38    #[inline(always)]
39    pub fn set_high(&mut self) {
40        // NOTE(unsafe) atomic write to a stateless register
41        let gpio = unsafe { &(*gpiox::<P>()) };
42        gpio.bsrr().write(|w| w.bs(self.pin_number).set_bit());
43    }
44
45    #[inline(always)]
46    pub fn set_low(&mut self) {
47        // NOTE(unsafe) atomic write to a stateless register
48        let gpio = unsafe { &(*gpiox::<P>()) };
49        gpio.bsrr().write(|w| w.br(self.pin_number).set_bit());
50    }
51
52    #[inline(always)]
53    pub fn get_state(&self) -> PinState {
54        if self.is_set_low() {
55            PinState::Low
56        } else {
57            PinState::High
58        }
59    }
60
61    #[inline(always)]
62    pub fn set_state(&mut self, state: PinState) {
63        match state {
64            PinState::Low => self.set_low(),
65            PinState::High => self.set_high(),
66        }
67    }
68
69    #[inline(always)]
70    pub fn is_set_high(&self) -> bool {
71        !self.is_set_low()
72    }
73
74    #[inline(always)]
75    pub fn is_set_low(&self) -> bool {
76        // NOTE(unsafe) atomic read with no side effects
77        let gpio = unsafe { &(*gpiox::<P>()) };
78        gpio.odr().read().odr(self.pin_number).bit_is_clear()
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<const P: char> PartiallyErasedPin<P, Output<OpenDrain>> {
92    #[inline(always)]
93    pub fn is_high(&self) -> bool {
94        !self.is_low()
95    }
96
97    #[inline(always)]
98    pub fn is_low(&self) -> bool {
99        // NOTE(unsafe) atomic read with no side effects
100        let gpio = unsafe { &(*gpiox::<P>()) };
101        gpio.idr().read().idr(self.pin_number).bit_is_clear()
102    }
103}
104
105impl<const P: char, MODE> PartiallyErasedPin<P, Input<MODE>> {
106    #[inline(always)]
107    pub fn is_high(&self) -> bool {
108        !self.is_low()
109    }
110
111    #[inline(always)]
112    pub fn is_low(&self) -> bool {
113        // NOTE(unsafe) atomic read with no side effects
114        let gpio = unsafe { &(*gpiox::<P>()) };
115        gpio.idr().read().idr(self.pin_number).bit_is_clear()
116    }
117}