atsamd_hal/peripherals/eic/d11/
pin.rs

1use atsamd_hal_macros::hal_cfg;
2
3use crate::ehal::digital::{ErrorType, InputPin};
4use crate::ehal_02::digital::v2::InputPin as InputPin_02;
5use crate::eic::*;
6use crate::gpio::{
7    self, pin::*, AnyPin, FloatingInterrupt, PinMode, PullDownInterrupt, PullUpInterrupt,
8};
9use core::convert::Infallible;
10
11/// The pad macro defines the given EIC pin and implements EicPin for the
12/// given pins. The EicPin implementation will configure the pin for the
13/// appropriate function and return the pin wrapped in the EIC type.
14macro_rules! ei {
15    (
16        $PadType:ident [ $num:expr ] {
17            $(
18                $(#[$attr:meta])*
19                $PinType:ident,
20            )+
21        }
22    ) => {
23        crate::paste::item! {
24            $(
25                $(#[$attr])*
26                impl<M: PinMode> EicPin for Pin<gpio::$PinType, M> {
27                    type Floating = ExtInt<Pin<gpio::$PinType, FloatingInterrupt>, Self::ChId>;
28                    type PullUp = ExtInt<Pin<gpio::$PinType, PullUpInterrupt>, Self::ChId>;
29                    type PullDown = ExtInt<Pin<gpio::$PinType, PullDownInterrupt>, Self::ChId>;
30
31                    type ChId = [<Ch $num>];
32
33                    fn into_floating_ei(self, chan: Channel<Self::ChId>) -> Self::Floating {
34                        Self::Floating::new(self.into_floating_interrupt(), chan)
35                    }
36
37                    fn into_pull_up_ei(self, chan: Channel<Self::ChId>) -> Self::PullUp {
38                    Self::PullUp::new(self.into_pull_up_interrupt(), chan)
39                    }
40
41                    fn into_pull_down_ei(self, chan: Channel<Self::ChId>) -> Self::PullDown {
42                        Self::PullDown::new(self.into_pull_down_interrupt(), chan)
43                    }
44                }
45            )+
46        }
47    };
48}
49
50impl<P, Id, F> ExtInt<P, Id, F>
51where
52    P: EicPin,
53    Id: ChId,
54{
55    /// Enables the event output of the channel for the event system.
56    ///
57    /// Note that whilst this function is executed, the EIC peripheral is disabled
58    /// in order to write to the evctrl register
59    pub fn enable_event(&mut self) {
60        self.chan.with_disable(|e| {
61            e.evctrl()
62                .modify(|_, w| unsafe { w.bits(1 << P::ChId::ID) });
63        });
64    }
65
66    pub fn enable_interrupt(&mut self) {
67        self.chan
68            .eic
69            .intenset()
70            .write(|w| unsafe { w.bits(1 << P::ChId::ID) });
71    }
72
73    pub fn enable_interrupt_wake(&mut self) {
74        self.chan
75            .eic
76            .wakeup()
77            .modify(|r, w| unsafe { w.bits(r.bits() | (1 << P::ChId::ID)) })
78    }
79
80    pub fn disable_interrupt(&mut self) {
81        self.chan
82            .eic
83            .intenclr()
84            .write(|w| unsafe { w.bits(1 << P::ChId::ID) });
85    }
86
87    pub fn is_interrupt(&mut self) -> bool {
88        self.chan.eic.intflag().read().bits() & (1 << P::ChId::ID) != 0
89    }
90
91    pub fn clear_interrupt(&mut self) {
92        self.chan
93            .eic
94            .intflag()
95            .write(|w| unsafe { w.bits(1 << P::ChId::ID) });
96    }
97
98    pub fn sense(&mut self, sense: Sense) {
99        self.chan.with_disable(|e| {
100            // Which of the two config blocks this eic config is in
101            let offset = (P::ChId::ID >> 3) & 0b0001;
102            let config = &e.config(offset);
103
104            config.modify(|_, w| unsafe {
105                // Which of the eight eic configs in this config block
106                match P::ChId::ID & 0b111 {
107                    0b000 => w.sense0().bits(sense as u8),
108                    0b001 => w.sense1().bits(sense as u8),
109                    0b010 => w.sense2().bits(sense as u8),
110                    0b011 => w.sense3().bits(sense as u8),
111                    0b100 => w.sense4().bits(sense as u8),
112                    0b101 => w.sense5().bits(sense as u8),
113                    0b110 => w.sense6().bits(sense as u8),
114                    0b111 => w.sense7().bits(sense as u8),
115                    _ => unreachable!(),
116                }
117            });
118        });
119    }
120
121    pub fn filter(&mut self, filter: bool) {
122        self.chan.with_disable(|e| {
123            // Which of the two config blocks this eic config is in
124            let offset = (P::ChId::ID >> 3) & 0b0001;
125            let config = &e.config(offset);
126
127            config.modify(|_, w| {
128                // Which of the eight eic configs in this config block
129                match P::ChId::ID & 0b111 {
130                    0b000 => w.filten0().bit(filter),
131                    0b001 => w.filten1().bit(filter),
132                    0b010 => w.filten2().bit(filter),
133                    0b011 => w.filten3().bit(filter),
134                    0b100 => w.filten4().bit(filter),
135                    0b101 => w.filten5().bit(filter),
136                    0b110 => w.filten6().bit(filter),
137                    0b111 => w.filten7().bit(filter),
138                    _ => unreachable!(),
139                }
140            });
141        });
142    }
143}
144
145impl<P, C, Id, F> InputPin_02 for ExtInt<P, Id, F>
146where
147    P: EicPin + AnyPin<Mode = Interrupt<C>>,
148    Id: ChId,
149    C: InterruptConfig,
150{
151    type Error = Infallible;
152    #[inline]
153    fn is_high(&self) -> Result<bool, Self::Error> {
154        self.pin.is_high()
155    }
156    #[inline]
157    fn is_low(&self) -> Result<bool, Self::Error> {
158        self.pin.is_low()
159    }
160}
161
162impl<P, Id, F> InputPin for ExtInt<P, Id, F>
163where
164    Self: ErrorType,
165    P: EicPin,
166    Id: ChId,
167{
168    #[inline]
169    fn is_high(&mut self) -> Result<bool, Self::Error> {
170        Ok(self.pin._is_high())
171    }
172
173    #[inline]
174    fn is_low(&mut self) -> Result<bool, Self::Error> {
175        Ok(self.pin._is_low())
176    }
177}
178
179impl<P, Id, F> ErrorType for ExtInt<P, Id, F>
180where
181    P: EicPin,
182    Id: ChId,
183{
184    type Error = Infallible;
185}
186
187#[cfg(feature = "async")]
188mod async_impls {
189    use embedded_hal_async::digital::Wait;
190
191    use super::super::async_api::WAKERS;
192    use super::*;
193
194    impl<P, Id> ExtInt<P, Id, EicFuture>
195    where
196        P: EicPin,
197        Id: ChId,
198        Self: InputPin<Error = Infallible>,
199    {
200        pub async fn wait(&mut self, sense: Sense) {
201            use core::{future::poll_fn, task::Poll};
202            self.disable_interrupt();
203
204            match sense {
205                Sense::High => {
206                    if self.is_high().unwrap() {
207                        return;
208                    }
209                }
210                Sense::Low => {
211                    if self.is_low().unwrap() {
212                        return;
213                    }
214                }
215                _ => (),
216            }
217
218            self.enable_interrupt_wake();
219            self.sense(sense);
220            poll_fn(|cx| {
221                if self.is_interrupt() {
222                    self.clear_interrupt();
223                    self.disable_interrupt();
224                    self.sense(Sense::None);
225                    return Poll::Ready(());
226                }
227
228                WAKERS[P::ChId::ID].register(cx.waker());
229                self.enable_interrupt();
230
231                if self.is_interrupt() {
232                    self.clear_interrupt();
233                    self.disable_interrupt();
234                    self.sense(Sense::None);
235                    return Poll::Ready(());
236                }
237
238                Poll::Pending
239            })
240            .await;
241        }
242    }
243
244    impl<P, Id> Wait for ExtInt<P, Id, EicFuture>
245    where
246        P: EicPin,
247        Id: ChId,
248        Self: InputPin<Error = Infallible>,
249    {
250        async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
251            self.wait(Sense::High).await;
252            Ok(())
253        }
254
255        async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
256            self.wait(Sense::Low).await;
257            Ok(())
258        }
259
260        async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
261            self.wait(Sense::Rise).await;
262            Ok(())
263        }
264
265        async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
266            self.wait(Sense::Fall).await;
267            Ok(())
268        }
269
270        async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
271            self.wait(Sense::Both).await;
272            Ok(())
273        }
274    }
275}
276
277// The SAMD11 and SAMD21 devices have different ExtInt designations. Just for
278// clarity's sake, the `ei!()` invocations below have been split into SAMD11-
279// and SAMD21-specific declarations.
280
281// SAMD11
282#[hal_cfg("eic-d11")]
283mod impls {
284    use super::*;
285
286    ei!(ExtInt[1] {
287        #[hal_cfg("pa15")]
288        PA15,
289    });
290
291    ei!(ExtInt[2] {
292        #[hal_cfg("pa02")]
293        PA02,
294    });
295
296    ei!(ExtInt[3] {
297        #[hal_cfg("pa31")]
298        PA31,
299    });
300
301    ei!(ExtInt[4] {
302        #[hal_cfg("pa04")]
303        PA04,
304        #[hal_cfg("pa24")]
305        PA24,
306    });
307
308    ei!(ExtInt[5] {
309        #[hal_cfg("pa05")]
310        PA05,
311        #[hal_cfg("pa25")]
312        PA25,
313    });
314
315    ei!(ExtInt[6] {
316        #[hal_cfg("pa08")]
317        PA08,
318    });
319
320    ei!(ExtInt[7] {
321        #[hal_cfg("pa09")]
322        PA09,
323    });
324}
325
326// SAMD21
327#[hal_cfg("eic-d21")]
328mod impls {
329    use super::*;
330
331    ei!(ExtInt[0] {
332        #[hal_cfg("pa00")]
333        PA00,
334        #[hal_cfg("pa16")]
335        PA16,
336        #[hal_cfg("pb00")]
337        PB00,
338        #[hal_cfg("pb16")]
339        PB16,
340    });
341
342    ei!(ExtInt[1] {
343        #[hal_cfg("pa01")]
344        PA01,
345        #[hal_cfg("pa17")]
346        PA17,
347        #[hal_cfg("pb01")]
348        PB01,
349        #[hal_cfg("pb17")]
350        PB17,
351    });
352
353    ei!(ExtInt[2] {
354        #[hal_cfg("pa02")]
355        PA02,
356        #[hal_cfg("pa18")]
357        PA18,
358        #[hal_cfg("pb02")]
359        PB02,
360    });
361
362    ei!(ExtInt[3] {
363        #[hal_cfg("pa03")]
364        PA03,
365        #[hal_cfg("pa19")]
366        PA19,
367        #[hal_cfg("pb03")]
368        PB03,
369    });
370
371    ei!(ExtInt[4] {
372        #[hal_cfg("pa04")]
373        PA04,
374        #[hal_cfg("pa20")]
375        PA20,
376        #[hal_cfg("pb04")]
377        PB04,
378    });
379
380    ei!(ExtInt[5] {
381        #[hal_cfg("pa05")]
382        PA05,
383        #[hal_cfg("pa21")]
384        PA21,
385        #[hal_cfg("pb05")]
386        PB05,
387    });
388
389    ei!(ExtInt[6] {
390        #[hal_cfg("pa06")]
391        PA06,
392        #[hal_cfg("pa22")]
393        PA22,
394        #[hal_cfg("pb06")]
395        PB06,
396        #[hal_cfg("pb22")]
397        PB22,
398    });
399
400    ei!(ExtInt[7] {
401        #[hal_cfg("pa07")]
402        PA07,
403        #[hal_cfg("pa23")]
404        PA23,
405        #[hal_cfg("pb07")]
406        PB07,
407        #[hal_cfg("pb23")]
408        PB23,
409    });
410
411    ei!(ExtInt[8] {
412        #[hal_cfg("pa28")]
413        PA28,
414        #[hal_cfg("pb08")]
415        PB08,
416    });
417
418    ei!(ExtInt[9] {
419        #[hal_cfg("pa09")]
420        PA09,
421        #[hal_cfg("pb09")]
422        PB09,
423    });
424
425    ei!(ExtInt[10] {
426        #[hal_cfg("pa10")]
427        PA10,
428        #[hal_cfg("pa30")]
429        PA30,
430        #[hal_cfg("pb10")]
431        PB10,
432    });
433
434    ei!(ExtInt[11] {
435        #[hal_cfg("pa11")]
436        PA11,
437        #[hal_cfg("pa31")]
438        PA31,
439        #[hal_cfg("pb11")]
440        PB11,
441    });
442
443    ei!(ExtInt[12] {
444        #[hal_cfg("pa12")]
445        PA12,
446        #[hal_cfg("pa24")]
447        PA24,
448        #[hal_cfg("pb12")]
449        PB12,
450    });
451
452    ei!(ExtInt[13] {
453        #[hal_cfg("pa13")]
454        PA13,
455        #[hal_cfg("pa25")]
456        PA25,
457        #[hal_cfg("pb13")]
458        PB13,
459    });
460
461    ei!(ExtInt[14] {
462        #[hal_cfg("pa14")]
463        PA14,
464        #[hal_cfg("pb14")]
465        PB14,
466        #[hal_cfg("pb30")]
467        PB30,
468    });
469
470    ei!(ExtInt[15] {
471        #[hal_cfg("pa15")]
472        PA15,
473        #[hal_cfg("pa27")]
474        PA27,
475        #[hal_cfg("pb15")]
476        PB15,
477        #[hal_cfg("pb31")]
478        PB31,
479    });
480}