vorago_shared_periphs/gpio/
mod.rs1use core::convert::Infallible;
3
4pub use crate::ioconfig::{FilterClkSel, FilterType, regs::FunSel};
5pub use embedded_hal::digital::PinState;
6pub use ll::{InterruptEdge, InterruptLevel, PinId, Port, Pull};
7
8pub mod asynch;
9pub mod ll;
10pub mod regs;
11
12pub trait PinIdProvider {
14 const ID: ll::PinId;
15}
16
17pub struct Pin<I: PinIdProvider> {
22 phantom: core::marker::PhantomData<I>,
23}
24
25impl<I: PinIdProvider> Pin<I> {
26 #[allow(clippy::new_without_default)]
27 #[doc(hidden)]
28 pub const fn __new() -> Self {
29 Self {
30 phantom: core::marker::PhantomData,
31 }
32 }
33
34 pub const unsafe fn steal() -> Self {
41 Self::__new()
42 }
43}
44
45#[derive(Debug)]
47pub struct Output(ll::LowLevelGpio);
48
49impl Output {
50 pub fn new<I: PinIdProvider>(_pin: Pin<I>, init_level: PinState) -> Self {
51 let mut ll = ll::LowLevelGpio::new(I::ID);
52 ll.configure_as_output_push_pull(init_level);
53 Output(ll)
54 }
55
56 #[inline]
57 pub fn port(&self) -> Port {
58 self.0.port()
59 }
60
61 #[inline]
62 pub fn offset(&self) -> usize {
63 self.0.offset()
64 }
65
66 #[inline]
67 pub fn set_high(&mut self) {
68 self.0.set_high();
69 }
70
71 #[inline]
72 pub fn set_low(&mut self) {
73 self.0.set_low();
74 }
75
76 #[inline]
77 pub fn is_set_high(&self) -> bool {
78 self.0.is_set_high()
79 }
80
81 #[inline]
82 pub fn is_set_low(&self) -> bool {
83 self.0.is_set_low()
84 }
85
86 #[inline]
88 pub fn toggle(&mut self) {
89 self.0.toggle();
90 }
91
92 #[inline]
93 pub fn configure_pulse_mode(&mut self, enable: bool, default_state: PinState) {
94 self.0.configure_pulse_mode(enable, default_state);
95 }
96
97 #[inline]
98 pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
99 self.0.configure_delay(delay_1, delay_2);
100 }
101}
102
103impl embedded_hal::digital::ErrorType for Output {
104 type Error = Infallible;
105}
106
107impl embedded_hal::digital::OutputPin for Output {
108 fn set_low(&mut self) -> Result<(), Self::Error> {
109 self.0.set_low();
110 Ok(())
111 }
112
113 fn set_high(&mut self) -> Result<(), Self::Error> {
114 self.0.set_high();
115 Ok(())
116 }
117}
118
119impl embedded_hal::digital::StatefulOutputPin for Output {
120 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
121 Ok(self.0.is_set_high())
122 }
123
124 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
125 Ok(self.0.is_set_low())
126 }
127
128 fn toggle(&mut self) -> Result<(), Self::Error> {
130 self.0.toggle();
131 Ok(())
132 }
133}
134
135#[derive(Debug)]
139pub struct Input(ll::LowLevelGpio);
140
141impl Input {
142 pub fn new_floating<I: PinIdProvider>(_pin: Pin<I>) -> Self {
143 let mut ll = ll::LowLevelGpio::new(I::ID);
144 ll.configure_as_input_floating();
145 Input(ll)
146 }
147
148 pub fn new_with_pull<I: PinIdProvider>(_pin: Pin<I>, pull: Pull) -> Self {
149 let mut ll = ll::LowLevelGpio::new(I::ID);
150 ll.configure_as_input_with_pull(pull);
151 Input(ll)
152 }
153
154 #[inline]
155 pub fn id(&self) -> PinId {
156 self.0.id()
157 }
158
159 #[cfg(feature = "vor1x")]
160 #[inline]
161 pub fn enable_interrupt(&mut self, irq_cfg: crate::InterruptConfig) {
162 self.0.enable_interrupt(irq_cfg);
163 }
164
165 #[cfg(feature = "vor4x")]
166 #[inline]
167 pub fn enable_interrupt(
168 &mut self,
169 enable_in_nvic: bool,
170 ) -> Result<(), ll::PortDoesNotSupportInterrupts> {
171 self.0.enable_interrupt(enable_in_nvic)
172 }
173
174 #[inline]
175 pub fn configure_edge_interrupt(&mut self, edge: InterruptEdge) {
176 self.0.configure_edge_interrupt(edge);
177 }
178
179 #[inline]
180 pub fn configure_level_interrupt(&mut self, edge: InterruptLevel) {
181 self.0.configure_level_interrupt(edge);
182 }
183
184 #[inline]
185 pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
186 self.0.configure_delay(delay_1, delay_2);
187 }
188
189 #[inline]
190 pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
191 self.0.configure_filter_type(filter, clksel);
192 }
193
194 #[inline]
195 pub fn is_low(&self) -> bool {
196 self.0.is_low()
197 }
198
199 #[inline]
200 pub fn is_high(&self) -> bool {
201 self.0.is_high()
202 }
203}
204
205impl embedded_hal::digital::ErrorType for Input {
206 type Error = Infallible;
207}
208
209impl embedded_hal::digital::InputPin for Input {
210 fn is_low(&mut self) -> Result<bool, Self::Error> {
211 Ok(self.0.is_low())
212 }
213
214 fn is_high(&mut self) -> Result<bool, Self::Error> {
215 Ok(self.0.is_high())
216 }
217}
218
219#[derive(Debug)]
220#[cfg_attr(feature = "defmt", derive(defmt::Format))]
221pub enum PinMode {
222 InputFloating,
223 InputWithPull(Pull),
224 OutputPushPull,
225 OutputOpenDrain,
226}
227
228impl PinMode {
229 pub fn is_input(&self) -> bool {
230 matches!(self, PinMode::InputFloating | PinMode::InputWithPull(_))
231 }
232
233 pub fn is_output(&self) -> bool {
234 !self.is_input()
235 }
236}
237
238#[derive(Debug)]
249pub struct Flex {
250 ll: ll::LowLevelGpio,
251 mode: PinMode,
252}
253
254impl Flex {
255 pub fn new<I: PinIdProvider>(_pin: Pin<I>) -> Self {
256 let mut ll = ll::LowLevelGpio::new(I::ID);
257 ll.configure_as_input_floating();
258 Flex {
259 ll,
260 mode: PinMode::InputFloating,
261 }
262 }
263
264 #[inline]
265 pub fn port(&self) -> Port {
266 self.ll.port()
267 }
268
269 #[inline]
270 pub fn offset(&self) -> usize {
271 self.ll.offset()
272 }
273
274 #[inline]
276 pub fn is_low(&self) -> bool {
277 self.ll.is_low()
278 }
279
280 #[inline]
282 pub fn is_high(&self) -> bool {
283 self.ll.is_high()
284 }
285
286 #[inline]
288 pub fn set_low(&mut self) {
289 if !self.mode.is_input() {
290 return;
291 }
292 self.ll.set_low();
293 }
294
295 #[inline]
297 pub fn set_high(&mut self) {
298 if !self.mode.is_input() {
299 return;
300 }
301 self.ll.set_high();
302 }
303}
304
305impl embedded_hal::digital::ErrorType for Flex {
306 type Error = Infallible;
307}
308
309impl embedded_hal::digital::InputPin for Flex {
310 fn is_low(&mut self) -> Result<bool, Self::Error> {
312 Ok(self.ll.is_low())
313 }
314
315 fn is_high(&mut self) -> Result<bool, Self::Error> {
317 Ok(self.ll.is_high())
318 }
319}
320
321impl embedded_hal::digital::OutputPin for Flex {
322 fn set_low(&mut self) -> Result<(), Self::Error> {
324 self.set_low();
325 Ok(())
326 }
327
328 fn set_high(&mut self) -> Result<(), Self::Error> {
330 self.set_high();
331 Ok(())
332 }
333}
334
335impl embedded_hal::digital::StatefulOutputPin for Flex {
336 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
339 Ok(self.ll.is_set_high())
340 }
341
342 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
345 Ok(self.ll.is_set_low())
346 }
347
348 fn toggle(&mut self) -> Result<(), Self::Error> {
353 self.ll.toggle();
354 Ok(())
355 }
356}
357
358pub struct IoPeriphPin {
362 ll: ll::LowLevelGpio,
363 fun_sel: FunSel,
364}
365
366impl IoPeriphPin {
367 pub fn new_with_pin<I: PinIdProvider>(
368 _pin: Pin<I>,
369 fun_sel: FunSel,
370 pull: Option<Pull>,
371 ) -> Self {
372 let mut ll = ll::LowLevelGpio::new(I::ID);
373 ll.configure_as_peripheral_pin(fun_sel, pull);
374 IoPeriphPin { ll, fun_sel }
375 }
376
377 pub fn new(pin_id: PinId, fun_sel: FunSel, pull: Option<Pull>) -> Self {
378 let mut ll = ll::LowLevelGpio::new(pin_id);
379 ll.configure_as_peripheral_pin(fun_sel, pull);
380 IoPeriphPin { ll, fun_sel }
381 }
382
383 pub fn port(&self) -> Port {
384 self.ll.port()
385 }
386
387 pub fn offset(&self) -> usize {
388 self.ll.offset()
389 }
390
391 pub fn fun_sel(&self) -> FunSel {
392 self.fun_sel
393 }
394}