embedded_c_sdk_bind_hal/gpio/
pin.rs

1//! General-purpose Input/Output (GPIO)
2
3use crate::ll_api::{ll_cmd::*, GpioInitFlag};
4use core::convert::Infallible;
5use embassy_hal_internal::{Peri, PeripheralType};
6
7/// GPIO flexible pin.
8///
9/// This pin can either be a disconnected, input, or output pin, or both. The level register bit will remain
10/// set while not in output mode, so the pin's level will be 'remembered' when it is not in output
11/// mode.
12pub struct Flex<'d> {
13    pub(crate) pin: Peri<'d, AnyPin>,
14}
15
16impl<'d> Flex<'d> {
17    /// Wrap the pin in a `Flex`.
18    ///
19    /// The pin remains disconnected. The initial output level is unspecified, but can be changed
20    /// before the pin is put into output mode.
21    ///
22    #[inline]
23    pub fn new(pin: Peri<'d, impl Pin>) -> Self {
24        // Pin will be in disconnected state.
25        Self { pin: pin.into() }
26    }
27
28    /// Put the pin into input mode.
29    ///
30    /// The internal weak pull-up and pull-down resistors will be enabled according to `pull`.
31    #[inline(never)]
32    pub fn set_as_input(&mut self, pull: Pull) {
33        let port = self.pin._port();
34        let pin = self.pin._pin();
35        let flag = pull.to_pupdr();
36
37        ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
38    }
39
40    /// Put the pin into push-pull output mode.
41    ///
42    /// The pin level will be whatever was set before (or low by default). If you want it to begin
43    /// at a specific level, call `set_high`/`set_low` on the pin first.
44    ///
45    /// The internal weak pull-up and pull-down resistors will be disabled.
46    #[inline(never)]
47    pub fn set_as_output(&mut self) {
48        let port = self.pin._port();
49        let pin = self.pin._pin();
50        let flag = GpioInitFlag::OutPP as u32;
51
52        ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
53    }
54
55    /// Put the pin into open-drain output mode.
56    #[inline(never)]
57    pub fn set_as_open_drain(&mut self) {
58        let port = self.pin._port();
59        let pin = self.pin._pin();
60        let flag = GpioInitFlag::OutOD as u32;
61
62        ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
63    }
64
65    /// Put the pin into alternate function mode.
66    pub fn set_as_alternate(&mut self, mode: AltMode) {
67        let port = self.pin._port();
68        let pin = self.pin._pin();
69        let flag = mode.to_flag();
70
71        ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
72    }
73
74    /// Put the pin into analog mode.
75    pub fn set_as_analog(&mut self) {
76        let port = self.pin._port();
77        let pin = self.pin._pin();
78        let flag = GpioInitFlag::Analog as u32;
79
80        ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
81    }
82
83    /// Get whether the pin input level is high.
84    #[inline]
85    pub fn is_high(&self) -> bool {
86        let port = self.pin._port();
87        let pin = self.pin._pin();
88
89        ll_invoke_inner!(INVOKE_ID_GPIO_GET_INPUT, port, pin) > 0
90    }
91
92    /// Get whether the pin input level is low.
93    #[inline]
94    pub fn is_low(&self) -> bool {
95        let port = self.pin._port();
96        let pin = self.pin._pin();
97
98        ll_invoke_inner!(INVOKE_ID_GPIO_GET_INPUT, port, pin) == 0
99    }
100
101    /// Get the current pin input level.
102    #[inline]
103    pub fn get_level(&self) -> Level {
104        self.is_high().into()
105    }
106
107    /// Get whether the output level is set to high.
108    #[inline]
109    pub fn is_set_high(&self) -> bool {
110        !self.is_set_low()
111    }
112
113    /// Get whether the output level is set to low.
114    #[inline]
115    pub fn is_set_low(&self) -> bool {
116        let port = self.pin._port();
117        let pin = self.pin._pin();
118
119        ll_invoke_inner!(INVOKE_ID_GPIO_GET_OUTPUT, port, pin) == 0
120    }
121
122    /// Get the current output level.
123    #[inline]
124    pub fn get_output_level(&self) -> Level {
125        self.is_set_high().into()
126    }
127
128    /// Set the output as high.
129    #[inline]
130    pub fn set_high(&mut self) {
131        self.pin.set_high();
132    }
133
134    /// Set the output as low.
135    #[inline]
136    pub fn set_low(&mut self) {
137        self.pin.set_low();
138    }
139
140    /// Set the output level.
141    #[inline]
142    pub fn set_level(&mut self, level: Level) {
143        match level {
144            Level::Low => self.pin.set_low(),
145            Level::High => self.pin.set_high(),
146        }
147    }
148
149    /// Toggle the output level.
150    #[inline]
151    pub fn toggle(&mut self) {
152        if self.is_set_low() {
153            self.set_high()
154        } else {
155            self.set_low()
156        }
157    }
158}
159
160impl<'d> Drop for Flex<'d> {
161    #[inline]
162    fn drop(&mut self) {
163        //Do nothing, hold status
164    }
165}
166
167/// Pull setting for an input.
168#[derive(Debug, Eq, PartialEq, Copy, Clone)]
169pub enum Pull {
170    /// No pull
171    None,
172    /// Pull up
173    Up,
174    /// Pull down
175    Down,
176}
177
178impl Pull {
179    const fn to_pupdr(self) -> u32 {
180        match self {
181            Pull::None => GpioInitFlag::InFloating as u32,
182            Pull::Up => GpioInitFlag::InPU as u32,
183            Pull::Down => GpioInitFlag::InPD as u32,
184        }
185    }
186}
187
188/// GPIO input driver.
189pub struct Input<'d> {
190    pub(crate) pin: Flex<'d>,
191}
192
193impl<'d> Input<'d> {
194    /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
195    #[inline]
196    pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self {
197        let mut pin = Flex::new(pin);
198        pin.set_as_input(pull);
199        Self { pin }
200    }
201
202    /// Get whether the pin input level is high.
203    #[inline]
204    pub fn is_high(&self) -> bool {
205        self.pin.is_high()
206    }
207
208    /// Get whether the pin input level is low.
209    #[inline]
210    pub fn is_low(&self) -> bool {
211        self.pin.is_low()
212    }
213
214    /// Get the current pin input level.
215    #[inline]
216    pub fn get_level(&self) -> Level {
217        self.pin.get_level()
218    }
219}
220
221/// Digital input or output level.
222#[derive(Debug, Eq, PartialEq, Copy, Clone)]
223pub enum Level {
224    /// Low
225    Low,
226    /// High
227    High,
228}
229
230impl From<bool> for Level {
231    fn from(val: bool) -> Self {
232        match val {
233            true => Self::High,
234            false => Self::Low,
235        }
236    }
237}
238
239impl From<Level> for bool {
240    fn from(level: Level) -> bool {
241        match level {
242            Level::Low => false,
243            Level::High => true,
244        }
245    }
246}
247
248/// GPIO output driver.
249///
250/// Note that pins will **return to their floating state** when `Output` is dropped.
251/// If pins should retain their state indefinitely, either keep ownership of the
252/// `Output`, or pass it to [`core::mem::forget`].
253pub struct Output<'d> {
254    pub(crate) pin: Flex<'d>,
255}
256
257impl<'d> Output<'d> {
258    /// Create GPIO output driver for a [Pin] with the provided [Level] and [Speed] configuration.
259    #[inline]
260    pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
261        let mut pin = Flex::new(pin);
262        match initial_output {
263            Level::High => pin.set_high(),
264            Level::Low => pin.set_low(),
265        }
266        pin.set_as_output();
267        Self { pin }
268    }
269
270    /// Set the output as high.
271    #[inline]
272    pub fn set_high(&mut self) {
273        self.pin.set_high();
274    }
275
276    /// Set the output as low.
277    #[inline]
278    pub fn set_low(&mut self) {
279        self.pin.set_low();
280    }
281
282    /// Set the output level.
283    #[inline]
284    pub fn set_level(&mut self, level: Level) {
285        self.pin.set_level(level)
286    }
287
288    /// Is the output pin set as high?
289    #[inline]
290    pub fn is_set_high(&self) -> bool {
291        self.pin.is_set_high()
292    }
293
294    /// Is the output pin set as low?
295    #[inline]
296    pub fn is_set_low(&self) -> bool {
297        self.pin.is_set_low()
298    }
299
300    /// What level output is set to
301    #[inline]
302    pub fn get_output_level(&self) -> Level {
303        self.pin.get_output_level()
304    }
305
306    /// Toggle pin output
307    #[inline]
308    pub fn toggle(&mut self) {
309        self.pin.toggle();
310    }
311}
312
313/// GPIO output open-drain driver.
314///
315/// Note that pins will **return to their floating state** when `OutputOpenDrain` is dropped.
316/// If pins should retain their state indefinitely, either keep ownership of the
317/// `OutputOpenDrain`, or pass it to [`core::mem::forget`].
318pub struct OutputOpenDrain<'d> {
319    pub(crate) pin: Flex<'d>,
320}
321
322impl<'d> OutputOpenDrain<'d> {
323    /// Create a new GPIO open drain output driver for a [Pin] with the provided [Level] and [Speed].
324    #[inline]
325    pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
326        let mut pin = Flex::new(pin);
327        match initial_output {
328            Level::High => pin.set_high(),
329            Level::Low => pin.set_low(),
330        }
331        pin.set_as_open_drain();
332        Self { pin }
333    }
334
335    /// Get whether the pin input level is high.
336    #[inline]
337    pub fn is_high(&self) -> bool {
338        !self.pin.is_low()
339    }
340
341    /// Get whether the pin input level is low.
342    #[inline]
343    pub fn is_low(&self) -> bool {
344        self.pin.is_low()
345    }
346
347    /// Get the current pin input level.
348    #[inline]
349    pub fn get_level(&self) -> Level {
350        self.pin.get_level()
351    }
352
353    /// Set the output as high.
354    #[inline]
355    pub fn set_high(&mut self) {
356        self.pin.set_high();
357    }
358
359    /// Set the output as low.
360    #[inline]
361    pub fn set_low(&mut self) {
362        self.pin.set_low();
363    }
364
365    /// Set the output level.
366    #[inline]
367    pub fn set_level(&mut self, level: Level) {
368        self.pin.set_level(level);
369    }
370
371    /// Get whether the output level is set to high.
372    #[inline]
373    pub fn is_set_high(&self) -> bool {
374        self.pin.is_set_high()
375    }
376
377    /// Get whether the output level is set to low.
378    #[inline]
379    pub fn is_set_low(&self) -> bool {
380        self.pin.is_set_low()
381    }
382
383    /// Get the current output level.
384    #[inline]
385    pub fn get_output_level(&self) -> Level {
386        self.pin.get_output_level()
387    }
388
389    /// Toggle pin output
390    #[inline]
391    pub fn toggle(&mut self) {
392        self.pin.toggle()
393    }
394}
395
396pub enum AltMode {
397    AF(u8),
398    AFOD,
399    AFPP,
400}
401
402impl AltMode {
403    fn to_flag(&self) -> u32 {
404        match self {
405            AltMode::AF(idx) => {
406                use GpioInitFlag::*;
407                const AF_FLAGS: [GpioInitFlag; 8] = [AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7];
408                AF_FLAGS.get(*idx as usize).copied().unwrap_or(AF0) as u32
409            }
410            AltMode::AFOD => GpioInitFlag::AFOD as u32,
411            AltMode::AFPP => GpioInitFlag::AFPP as u32,
412        }
413    }
414}
415
416/// GPIO alternate driver.
417pub struct Alternate<'d> {
418    pub(crate) _pin: Flex<'d>,
419}
420
421impl<'d> Alternate<'d> {
422    /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
423    #[inline]
424    pub fn new(pin: Peri<'d, impl Pin>, mode: AltMode) -> Self {
425        let mut pin = Flex::new(pin);
426        pin.set_as_alternate(mode);
427        Self { _pin: pin }
428    }
429}
430
431/// GPIO analog driver.
432pub struct Analog<'d> {
433    pub(crate) _pin: Flex<'d>,
434}
435
436impl<'d> Analog<'d> {
437    /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
438    #[inline]
439    pub fn new(pin: Peri<'d, impl Pin>) -> Self {
440        let mut pin = Flex::new(pin);
441        pin.set_as_analog();
442        Self { _pin: pin }
443    }
444}
445
446pub(crate) trait SealedPin {
447    fn pin_port(&self) -> u8;
448
449    #[inline]
450    fn _pin(&self) -> u8 {
451        self.pin_port() % 16
452    }
453
454    #[inline]
455    fn _port(&self) -> u8 {
456        self.pin_port() / 16
457    }
458
459    // #[inline]
460    // fn block(&self) -> gpio::Gpio {
461    //     crate::chip::gpio_block(self._port() as _)
462    // }
463
464    /// Set the output as high.
465    #[inline]
466    fn set_high(&self) {
467        let port = self._port();
468        let pin = self._pin();
469
470        ll_invoke_inner!(INVOKE_ID_GPIO_SET, port, pin, 1);
471    }
472
473    /// Set the output as low.
474    #[inline]
475    fn set_low(&self) {
476        let port = self._port();
477        let pin = self._pin();
478
479        ll_invoke_inner!(INVOKE_ID_GPIO_SET, port, pin, 0);
480    }
481}
482
483/// GPIO pin trait.
484#[allow(private_bounds)]
485pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
486    /// Number of the pin within the port (0..31)
487    #[inline]
488    fn pin(&self) -> u8 {
489        self._pin()
490    }
491
492    /// Port of the pin
493    #[inline]
494    fn port(&self) -> u8 {
495        self._port()
496    }
497}
498
499/// Type-erased GPIO pin
500pub struct AnyPin {
501    pin_port: u8,
502}
503
504impl AnyPin {
505    /// Unsafely create an `AnyPin` from a pin+port number.
506    ///
507    /// `pin_port` is `port_num * 16 + pin_num`, where `port_num` is 0 for port `A`, 1 for port `B`, etc...
508    #[inline]
509    pub unsafe fn steal(pin_port: u8) -> Peri<'static, Self> {
510        Peri::new_unchecked(Self { pin_port })
511    }
512
513    #[inline]
514    fn _port(&self) -> u8 {
515        self.pin_port / 16
516    }
517}
518
519impl Copy for AnyPin {}
520
521impl Clone for AnyPin {
522    fn clone(&self) -> Self {
523        *self
524    }
525}
526impl PeripheralType for AnyPin {}
527
528impl Pin for AnyPin {}
529
530impl SealedPin for AnyPin {
531    #[inline]
532    fn pin_port(&self) -> u8 {
533        self.pin_port
534    }
535}
536
537crate::foreach_pin!(
538    ($pin_name:ident, $port_num:expr, $pin_num:expr) => {
539        impl SealedPin for $crate::peripherals::$pin_name {
540            #[inline]
541            fn pin_port(&self) -> u8 {
542                $port_num * 16 + $pin_num
543            }
544        }
545
546        impl From<$crate::peripherals::$pin_name> for AnyPin {
547            fn from(val: $crate::peripherals::$pin_name) -> Self {
548                Self {
549                    pin_port: val.pin_port(),
550                }
551            }
552        }
553    };
554);
555
556impl<'d> embedded_hal::digital::ErrorType for Input<'d> {
557    type Error = Infallible;
558}
559
560impl<'d> embedded_hal::digital::InputPin for Input<'d> {
561    #[inline]
562    fn is_high(&mut self) -> Result<bool, Self::Error> {
563        Ok(Input::is_high(self))
564    }
565
566    #[inline]
567    fn is_low(&mut self) -> Result<bool, Self::Error> {
568        Ok(Input::is_low(self))
569    }
570}
571
572impl<'d> embedded_hal::digital::ErrorType for Output<'d> {
573    type Error = Infallible;
574}
575
576impl<'d> embedded_hal::digital::OutputPin for Output<'d> {
577    #[inline]
578    fn set_high(&mut self) -> Result<(), Self::Error> {
579        Output::set_high(self);
580        Ok(())
581    }
582
583    #[inline]
584    fn set_low(&mut self) -> Result<(), Self::Error> {
585        Output::set_low(self);
586        Ok(())
587    }
588}
589
590impl<'d> embedded_hal::digital::StatefulOutputPin for Output<'d> {
591    #[inline]
592    fn is_set_high(&mut self) -> Result<bool, Self::Error> {
593        Ok(Output::is_set_high(self))
594    }
595
596    /// Is the output pin set as low?
597    #[inline]
598    fn is_set_low(&mut self) -> Result<bool, Self::Error> {
599        Ok(Output::is_set_low(self))
600    }
601}
602
603impl<'d> embedded_hal::digital::ErrorType for OutputOpenDrain<'d> {
604    type Error = Infallible;
605}
606
607impl<'d> embedded_hal::digital::InputPin for OutputOpenDrain<'d> {
608    #[inline]
609    fn is_high(&mut self) -> Result<bool, Self::Error> {
610        Ok(OutputOpenDrain::is_high(self))
611    }
612
613    #[inline]
614    fn is_low(&mut self) -> Result<bool, Self::Error> {
615        Ok(OutputOpenDrain::is_low(self))
616    }
617}
618
619impl<'d> embedded_hal::digital::OutputPin for OutputOpenDrain<'d> {
620    #[inline]
621    fn set_high(&mut self) -> Result<(), Self::Error> {
622        OutputOpenDrain::set_high(self);
623        Ok(())
624    }
625
626    #[inline]
627    fn set_low(&mut self) -> Result<(), Self::Error> {
628        OutputOpenDrain::set_low(self);
629        Ok(())
630    }
631}
632
633impl<'d> embedded_hal::digital::StatefulOutputPin for OutputOpenDrain<'d> {
634    #[inline]
635    fn is_set_high(&mut self) -> Result<bool, Self::Error> {
636        Ok(OutputOpenDrain::is_set_high(self))
637    }
638
639    /// Is the output pin set as low?
640    #[inline]
641    fn is_set_low(&mut self) -> Result<bool, Self::Error> {
642        Ok(OutputOpenDrain::is_set_low(self))
643    }
644}
645
646impl<'d> embedded_hal::digital::InputPin for Flex<'d> {
647    #[inline]
648    fn is_high(&mut self) -> Result<bool, Self::Error> {
649        Ok(Flex::is_high(self))
650    }
651
652    #[inline]
653    fn is_low(&mut self) -> Result<bool, Self::Error> {
654        Ok(Flex::is_low(self))
655    }
656}
657
658impl<'d> embedded_hal::digital::OutputPin for Flex<'d> {
659    #[inline]
660    fn set_high(&mut self) -> Result<(), Self::Error> {
661        Flex::set_high(self);
662        Ok(())
663    }
664
665    #[inline]
666    fn set_low(&mut self) -> Result<(), Self::Error> {
667        Flex::set_low(self);
668        Ok(())
669    }
670}
671
672impl<'d> embedded_hal::digital::ErrorType for Flex<'d> {
673    type Error = Infallible;
674}
675
676impl<'d> embedded_hal::digital::StatefulOutputPin for Flex<'d> {
677    #[inline]
678    fn is_set_high(&mut self) -> Result<bool, Self::Error> {
679        Ok(Flex::is_set_high(self))
680    }
681
682    /// Is the output pin set as low?
683    #[inline]
684    fn is_set_low(&mut self) -> Result<bool, Self::Error> {
685        Ok(Flex::is_set_low(self))
686    }
687}