stm32f7xx_hal/gpio/
dynamic.rs

1use super::*;
2
3/// Pin type with dynamic mode
4///
5/// - `P` is port name: `A` for GPIOA, `B` for GPIOB, etc.
6/// - `N` is pin number: from `0` to `15`.
7pub struct DynamicPin<const P: char, const N: u8> {
8    /// Current pin mode
9    pub(crate) mode: Dynamic,
10}
11
12/// Tracks the current pin state for dynamic pins
13pub enum Dynamic {
14    InputFloating,
15    InputPullUp,
16    InputPullDown,
17    OutputPushPull,
18    OutputOpenDrain,
19}
20
21#[derive(Debug, PartialEq)]
22pub enum PinModeError {
23    IncorrectMode,
24}
25
26impl Dynamic {
27    pub fn is_input(&self) -> bool {
28        use Dynamic::*;
29        match self {
30            InputFloating | InputPullUp | InputPullDown | OutputOpenDrain => true,
31            OutputPushPull => false,
32        }
33    }
34    pub fn is_output(&self) -> bool {
35        use Dynamic::*;
36        match self {
37            InputFloating | InputPullUp | InputPullDown => false,
38            OutputPushPull | OutputOpenDrain => true,
39        }
40    }
41}
42
43// For convertion simplify
44struct Unknown;
45
46impl<const P: char, const N: u8> DynamicPin<P, N> {
47    pub const fn new(mode: Dynamic) -> Self {
48        Self { mode }
49    }
50
51    #[inline]
52    pub fn make_pull_up_input(&mut self) {
53        // NOTE(unsafe), we have a mutable reference to the current pin
54        Pin::<P, N, Unknown>::new().into_pull_up_input();
55        self.mode = Dynamic::InputPullUp;
56    }
57    #[inline]
58    pub fn make_pull_down_input(&mut self) {
59        // NOTE(unsafe), we have a mutable reference to the current pin
60        Pin::<P, N, Unknown>::new().into_pull_down_input();
61        self.mode = Dynamic::InputPullDown;
62    }
63    #[inline]
64    pub fn make_floating_input(&mut self) {
65        // NOTE(unsafe), we have a mutable reference to the current pin
66        Pin::<P, N, Unknown>::new().into_floating_input();
67        self.mode = Dynamic::InputFloating;
68    }
69    #[inline]
70    pub fn make_push_pull_output(&mut self) {
71        // NOTE(unsafe), we have a mutable reference to the current pin
72        Pin::<P, N, Unknown>::new().into_push_pull_output();
73        self.mode = Dynamic::OutputPushPull;
74    }
75    #[inline]
76    pub fn make_push_pull_output_in_state(&mut self, state: PinState) {
77        // NOTE(unsafe), we have a mutable reference to the current pin
78        Pin::<P, N, Unknown>::new().into_push_pull_output_in_state(state);
79        self.mode = Dynamic::OutputPushPull;
80    }
81    #[inline]
82    pub fn make_open_drain_output(&mut self) {
83        // NOTE(unsafe), we have a mutable reference to the current pin
84        Pin::<P, N, Unknown>::new().into_open_drain_output();
85        self.mode = Dynamic::OutputOpenDrain;
86    }
87    #[inline]
88    pub fn make_open_drain_output_in_state(&mut self, state: PinState) {
89        // NOTE(unsafe), we have a mutable reference to the current pin
90        Pin::<P, N, Unknown>::new().into_open_drain_output_in_state(state);
91        self.mode = Dynamic::OutputOpenDrain;
92    }
93
94    pub fn set_high(&mut self) -> Result<(), PinModeError> {
95        if self.mode.is_output() {
96            Pin::<P, N, Unknown>::new()._set_state(PinState::High);
97            Ok(())
98        } else {
99            Err(PinModeError::IncorrectMode)
100        }
101    }
102    pub fn set_low(&mut self) -> Result<(), PinModeError> {
103        if self.mode.is_output() {
104            Pin::<P, N, Unknown>::new()._set_state(PinState::Low);
105            Ok(())
106        } else {
107            Err(PinModeError::IncorrectMode)
108        }
109    }
110
111    pub fn is_high(&self) -> Result<bool, PinModeError> {
112        self.is_low().map(|b| !b)
113    }
114    pub fn is_low(&self) -> Result<bool, PinModeError> {
115        if self.mode.is_input() {
116            Ok(Pin::<P, N, Unknown>::new()._is_low())
117        } else {
118            Err(PinModeError::IncorrectMode)
119        }
120    }
121}