embedded_c_sdk_bind_hal/gpio/
fast_pin.rs

1use super::PinNum;
2use crate::ll_api::{ll_cmd::*, GpioInitParam, PortNum};
3use core::marker::PhantomData;
4
5pub trait FastPinReg {
6    /// Port number, define by ll_api
7    const PORT: PortNum;
8    /// Port input data register address
9    const IDR: usize;
10    /// Port output data register address
11    const ODR: usize;
12    /// Port bit set register address
13    const BSR: usize;
14    /// Port bit clear register address
15    const BCR: usize;
16}
17
18pub trait FastPinNum {
19    const PIN: PinNum;
20}
21
22/// Automatically implement the `FastPinNum` trait for pin numbers 0 to 15.
23pub mod fast_pin_num {
24    use super::FastPinNum;
25    use crate::gpio::PinNum;
26    macro_rules! impl_fast_pin_num {
27        ($( $pin_num:expr ),*) => {
28            $(
29                paste::paste! {
30                    pub struct [<FastPin $pin_num>];
31                    impl FastPinNum for [<FastPin $pin_num>] {
32                        const PIN: PinNum = PinNum::[<Pin $pin_num>];
33                    }
34                }
35            )*
36        };
37    }
38
39    impl_fast_pin_num![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
40}
41
42#[derive(Clone, Copy, PartialEq, Eq, Debug)]
43pub enum FastPinModeInput {
44    /// Floating input mode.
45    InFloating,
46    /// Pull-up input mode.
47    InPullUp,
48    /// Pull-down input mode.
49    InPullDown,
50}
51
52impl FastPinModeInput {
53    fn to_flag(&self) -> u32 {
54        match self {
55            FastPinModeInput::InFloating => GpioInitParam::InFloating.param(),
56            FastPinModeInput::InPullUp => GpioInitParam::InPU.param(),
57            FastPinModeInput::InPullDown => GpioInitParam::InPD.param(),
58        }
59    }
60}
61
62pub enum FastPinModeOutput {
63    /// Open-drain output mode.
64    OutOD,
65    /// Push-pull output mode.
66    OutPP,
67}
68
69impl FastPinModeOutput {
70    fn to_flag(&self) -> u32 {
71        match self {
72            FastPinModeOutput::OutOD => GpioInitParam::OutOD.param(),
73            FastPinModeOutput::OutPP => GpioInitParam::OutPP.param(),
74        }
75    }
76}
77
78pub struct InputFastPin;
79pub struct OutputFastPin;
80
81#[derive(Clone, Copy, Debug)]
82pub struct FastPin<R, N, MODE> {
83    phantom: PhantomData<(R, N, MODE)>,
84}
85
86impl<R: FastPinReg, N: FastPinNum, MODE> FastPin<R, N, MODE> {
87    /// Create a new instance of `FastPin`.
88    pub const fn new() -> Self {
89        FastPin {
90            phantom: PhantomData,
91        }
92    }
93
94    /// Configure the pin as an input pin and return a new `FastPin` instance.
95    pub fn into_input(&self, mode: FastPinModeInput) -> FastPin<R, N, InputFastPin> {
96        ll_invoke_inner!(INVOKE_ID_GPIO_INIT, R::PORT, N::PIN, mode.to_flag());
97
98        FastPin {
99            phantom: PhantomData,
100        }
101    }
102
103    /// Configure the pin as an output pin and return a new `FastPin` instance.
104    pub fn into_output(&self, mode: FastPinModeOutput) -> FastPin<R, N, OutputFastPin> {
105        ll_invoke_inner!(INVOKE_ID_GPIO_INIT, R::PORT, N::PIN, mode.to_flag());
106
107        FastPin {
108            phantom: PhantomData,
109        }
110    }
111}
112
113impl<R: FastPinReg, N: FastPinNum> FastPin<R, N, InputFastPin> {
114    /// Check if the input pin is high.
115    #[inline]
116    pub fn is_input_high(&self) -> bool {
117        (unsafe { core::ptr::read_volatile(R::IDR as *const u16) } & (1 << N::PIN as u8)) != 0
118    }
119
120    /// Check if the input pin is low.
121    #[inline]
122    pub fn is_input_low(&self) -> bool {
123        (unsafe { core::ptr::read_volatile(R::IDR as *const u16) } & (1 << N::PIN as u8)) == 0
124    }
125}
126
127impl<R: FastPinReg, N: FastPinNum> FastPin<R, N, OutputFastPin> {
128    /// Set the output pin high.
129    #[inline]
130    pub fn output_high(&self) {
131        unsafe { core::ptr::write_volatile(R::BSR as *mut u16, 1 << N::PIN as u8) };
132    }
133
134    /// Set the output pin low.
135    #[inline]
136    pub fn output_low(&self) {
137        unsafe { core::ptr::write_volatile(R::BCR as *mut u16, 1 << N::PIN as u8) };
138    }
139
140    /// Check if the output pin is high.
141    #[inline]
142    pub fn is_output_high(&self) -> bool {
143        (unsafe { core::ptr::read_volatile(R::ODR as *const u16) } & (1 << N::PIN as u8)) != 0
144    }
145
146    /// Check if the output pin is low.
147    #[inline]
148    pub fn is_output_low(&self) -> bool {
149        (unsafe { core::ptr::read_volatile(R::ODR as *const u16) } & (1 << N::PIN as u8)) == 0
150    }
151
152    /// Check if the open drain pin is high.
153    #[inline]
154    pub fn is_input_high(&self) -> bool {
155        (unsafe { core::ptr::read_volatile(R::IDR as *const u16) } & (1 << N::PIN as u8)) != 0
156    }
157
158    /// Check if the open drain pin is low.
159    #[inline]
160    pub fn is_input_low(&self) -> bool {
161        (unsafe { core::ptr::read_volatile(R::IDR as *const u16) } & (1 << N::PIN as u8)) == 0
162    }
163}
164
165impl<R: FastPinReg, N: FastPinNum, MODE> embedded_hal::digital::ErrorType for FastPin<R, N, MODE> {
166    type Error = core::convert::Infallible;
167}
168
169impl<R: FastPinReg, N: FastPinNum> embedded_hal::digital::OutputPin
170    for FastPin<R, N, OutputFastPin>
171{
172    #[inline(always)]
173    fn set_high(&mut self) -> Result<(), Self::Error> {
174        self.output_high();
175        Ok(())
176    }
177
178    #[inline(always)]
179    fn set_low(&mut self) -> Result<(), Self::Error> {
180        self.output_low();
181        Ok(())
182    }
183
184    fn set_state(&mut self, state: embedded_hal::digital::PinState) -> Result<(), Self::Error> {
185        match state {
186            embedded_hal::digital::PinState::Low => self.set_low(),
187            embedded_hal::digital::PinState::High => self.set_high(),
188        }
189    }
190}
191
192impl<R: FastPinReg, N: FastPinNum> embedded_hal::digital::StatefulOutputPin
193    for FastPin<R, N, OutputFastPin>
194{
195    #[inline(always)]
196    fn is_set_high(&mut self) -> Result<bool, Self::Error> {
197        Ok(self.is_output_high())
198    }
199
200    #[inline(always)]
201    fn is_set_low(&mut self) -> Result<bool, Self::Error> {
202        Ok(self.is_output_low())
203    }
204}
205
206impl<R: FastPinReg, N: FastPinNum> embedded_hal::digital::InputPin for FastPin<R, N, InputFastPin> {
207    #[inline(always)]
208    fn is_high(&mut self) -> Result<bool, Self::Error> {
209        Ok(self.is_input_high())
210    }
211
212    #[inline(always)]
213    fn is_low(&mut self) -> Result<bool, Self::Error> {
214        Ok(self.is_input_low())
215    }
216}
217
218impl<R: FastPinReg, N: FastPinNum> embedded_hal::digital::InputPin
219    for FastPin<R, N, OutputFastPin>
220{
221    #[inline(always)]
222    fn is_high(&mut self) -> Result<bool, Self::Error> {
223        Ok(self.is_input_high())
224    }
225
226    #[inline(always)]
227    fn is_low(&mut self) -> Result<bool, Self::Error> {
228        Ok(self.is_input_low())
229    }
230}