sam3_hal/pio/
interrupt.rs

1//! PIO interrupts
2//!
3//! By default, a PIO bank's interrupts can only be triggered on edge detections. However, it may be
4//! configured on a per-pin basis to accept other interrupt modes. These modes are:
5//! - Level detection
6//!     - High level detection
7//!     - Low level detection
8//! - Edge detection
9//!     - Rising edge detection
10//!     - Falling edge detection
11//!
12//! Please note that the PIO interrupt signal for the entire PIO bank is fired if the interrupt
13//! condition for any of the individual lines in that PIO bank is met.
14//!
15//! Relevant manual sections:
16//! - SAM3A, SAM3X: [manual][ax], pages 620, 625-628 (31.4.3, 31.5.9, 31.5.10)
17//! - SAM3N: [manual][n], pages 378, 382-385 (27.4.3, 27.5.9, 27.5.10)
18//! - SAM3S1, SAM3S2, SAM3S4: [manual][s124], pages 469, 473-476 (29.4.3, 29.5.9, 29.5.10)
19//! - SAM3S8, SAM3SD8: [manual][sd8], pages 478, 482-485 (28.4.3, 28.5.9, 28.5.11)
20//! - SAM3U: [manual][u], pages 496, 500-503 (29.4.3, 29.5.9, 29.5.10)
21//!
22//! [ax]: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf
23//! [n]: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-11011-32-bit-Cortex-M3-Microcontroller-SAM3N_Datasheet.pdf
24//! [s124]: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-6500-32-bit-Cortex-M3-Microcontroller-SAM3S4-SAM3S2-SAM3S1_Datasheet.pdf
25//! [sd8]: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-11090-32-bit%20Cortex-M3-Microcontroller-SAM-3S8-SD8_Datasheet.pdf
26//! [u]: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-6430-32-bit-Cortex-M3-Microcontroller-SAM3U4-SAM3U2-SAM3U1_Datasheet.pdf
27#[allow(clippy::wildcard_imports)]
28use crate::{
29    pio::{
30        filter::InputFilterCfg,
31        peripheral::PioControlCfg,
32        pin::{Configured, MultiDriverCfg, PadResistorCfg, Pin, PinId, Unconfigured},
33        structure::*,
34    },
35    structure::*,
36};
37use core::marker::PhantomData;
38
39#[allow(clippy::module_name_repetitions)]
40/// Marker trait for interrupt configuration types.
41pub trait InterruptCfg {}
42
43impl InterruptCfg for Unconfigured {}
44
45#[allow(clippy::module_name_repetitions)]
46/// Disable interrupts on an I/O line.
47pub struct InterruptDisabled;
48
49impl InterruptCfg for InterruptDisabled {}
50impl Configured for InterruptDisabled {}
51
52#[allow(clippy::module_name_repetitions)]
53/// Enable interrupts on an I/O line.
54pub struct InterruptEnabled<Aint> {
55    _aint: PhantomData<Aint>,
56}
57
58impl<Aint: AdditionalInterruptModesCfg> InterruptCfg for InterruptEnabled<Aint> {}
59impl<Aint: AdditionalInterruptModesCfg + Configured> Configured for InterruptEnabled<Aint> {}
60
61#[allow(clippy::module_name_repetitions)]
62/// # Input Edge/Level Interrupt
63///
64/// The PIO Controller can be programmed to generate an interrupt when it detects an edge or a level
65/// on an I/O line. The Input Edge/Level Interrupt is controlled by writing `PIO_IER` (Interrupt
66/// Enable Register) and `PIO_IDR` (Interrupt Disable Register). As Input change detection is
67/// possible only by comparing two successive samplings of the input of the I/O line, the PIO
68/// Controller clock must be enabled. The Input Change Interrupt is available, regardless of the
69/// configuration of the I/O line, i.e. configured as an input only, controlled by the PIO
70/// Controller or assigned to a peripheral function.
71///
72/// By default, the interrupt can be generated at any time an edge is detected on the input.
73///
74/// Additional Interrupt Modes can be configured through the [`ConfigureAdditionalInterruptModes`]
75/// trait.
76///
77/// When an input Edge or Level is detected on an I/O line, the corresponding bit in the `PIO_ISR`
78/// (Interrupt Status Register) is set. If the corresponding bit in `PIO_IMR` is set, the PIO
79/// Controller interrupt line is asserted. The interrupt signals of the thirty-two channels are
80/// ORed-wired together to generate a single interrupt signal to the Nested Vector Interrupt
81/// Controller (NVIC).
82///
83/// When the software reads `PIO_ISR`, all the interrupts are automatically cleared. This signifies
84/// that all the interrupts that are pending when `PIO_ISR` is read must be handled. When an
85/// Interrupt is enabled on a "Level", the interrupt is generated as long as the interrupt source is
86/// not cleared, even if some read accesses in `PIO_ISR` are performed.
87pub trait ConfigureInterrupt {
88    type Enabled: ConfigureInterrupt + ConfigureAdditionalInterruptModes;
89    type Disabled: ConfigureInterrupt;
90
91    /// Enable interrupts on this pin. Waits for `PIO_IMR` to update accordingly.
92    fn enable_interrupt(self) -> Self::Enabled;
93    /// Enable interrupts on this pin without waiting for `PIO_IMR` to update.
94    ///
95    /// # Safety
96    ///
97    /// While this function returns a type showing that interrupts are enabled, the pin will not
98    /// actually trigger an interrupt until the corresponding bit in `PIO_IMR` is set.
99    unsafe fn enable_interrupt_unchecked(self) -> Self::Enabled;
100    /// Disable interrupts on this pin. Waits for `PIO_IMR` to update accordingly.
101    fn disable_interrupt(self) -> Self::Disabled;
102    /// Disable interrupts on this pin without waiting for `PIO_IMR` to update.
103    ///
104    /// # Safety
105    ///
106    /// While this function returns a type showing that interrupts are disabled, the pin will
107    /// continue triggering interrupts until the corresponding bit in `PIO_IMR` is cleared.
108    unsafe fn disable_interrupt_unchecked(self) -> Self::Disabled;
109}
110
111/// Marker trait for additional interrupt modes configuration types.
112pub trait AdditionalInterruptModesCfg {}
113
114impl AdditionalInterruptModesCfg for Unconfigured {}
115
116/// Disable additional interrupt modes from the event detector on an I/O line. This uses the default
117/// edge detector for interrupt signals.
118pub struct AdditionalInterruptModesDisabled;
119
120impl Configured for AdditionalInterruptModesDisabled {}
121impl AdditionalInterruptModesCfg for AdditionalInterruptModesDisabled {}
122
123/// # Input Edge/Level Interrupt (Additional Interrupt Modes)
124///
125/// Some additional interrupt modes can be enabled/disabled by writing in the `PIO_AIMER`
126/// (Additional Interrupt Modes Enable Register) and `PIO_AIMDR` (Additional Interrupt Modes Disable
127/// Register). the current state of this selection can be read through the `PIO_AIMMR` (Additional
128/// Interrupt Modes Mask Register).
129///
130/// These Additional Modes are:
131/// - Rising Edge Detection
132/// - Falling Edge Detection
133/// - Low Level Detection
134/// - High Level Detection
135///
136/// In order to select an Additional Interrupt Mode:
137/// - The type of the event detection (Edge or Level) must be selected by writing in the set of
138///   registers; `PIO_ESR` (Edge Select Register) and `PIO_LSR` (Level Select Register) which enable
139///   respectively, the Edge and Level Detection. The current status of this selection is accessible
140///   through the `PIO_ELSR` (Edge/Level Status Register).
141/// - The Polarity of the event detection (Rising/Falling Edge or High/Low Level) must be selected
142///   by writing in the set of registers; `PIO_FELLSR` (Falling Edge/Low Level Select Register) and
143///   `PIO_REHLSR` (Rising Edge/High Level Select Register) which allow to select Falling or Rising
144///   Edge (if Edge is selected in the `PIO_ELSR`) or High or Low Level Detection (if Level is
145///   selected in the `PIO_ELSR`). The current status of this selection is accessible through the
146///   `PIO_FRLHSR` (Fall/Rise - Low/High Status Register).
147pub trait ConfigureAdditionalInterruptModes {
148    type Enabled: ConfigureAdditionalInterruptModes + ConfigureEdgeLevel + ConfigureFallRiseLowHigh;
149    type Disabled: ConfigureAdditionalInterruptModes;
150
151    /// Enable additional interrupt modes on this pin. Waits for `PIO_AIMMR` to update accordingly.
152    fn enable_additional_interrupt_modes(self) -> Self::Enabled;
153    /// Enable additional interrupt modes on this pin without waiting for `PIO_AIMMR` to update.
154    ///
155    /// # Safety
156    ///
157    /// While this function returns a type showing that additional interrupt modes are enabled, the
158    /// pin will not actually trigger an interrupt from any of the additional modes until the
159    /// corresponding bit in `PIO_AIMMR` is set.
160    unsafe fn enable_additional_interrupt_modes_unchecked(self) -> Self::Enabled;
161    /// Disable additional interrupt modes on this pin. Waits for `PIO_AIMMR` to update accordingly.
162    fn disable_additional_interrupt_modes(self) -> Self::Disabled;
163    /// Disable additional interrupt modes on this pin without waiting for `PIO_AIMMR` to update.
164    ///
165    /// # Safety
166    ///
167    /// While this function returns a type showing that additional interrupt modes are disabled, the
168    /// pin will still trigger an interrupt from the configured additional interrupt mode until the
169    /// corresponding bit in `PIO_AIMMR` is cleared.
170    unsafe fn disable_additional_interrupt_modes_unchecked(self) -> Self::Disabled;
171}
172
173/// Enable additional interrupt modes from the event detector on an I/O line. The mode is determined
174/// by the `Edlv` type and which kind of edge or level is detected is determined by the `Frlh` type.
175pub struct AdditionalInterruptModesEnabled<Edlv, Frlh> {
176    _edlv: PhantomData<Edlv>,
177    _frlh: PhantomData<Frlh>,
178}
179
180#[rustfmt::skip]
181impl<Edlv: Configured, Frlh: Configured> Configured
182    for AdditionalInterruptModesEnabled<Edlv, Frlh>
183{}
184#[rustfmt::skip]
185impl<Edlv: EdgeLevelCfg, Frlh: FallRiseLowHighCfg>
186    AdditionalInterruptModesCfg for AdditionalInterruptModesEnabled<Edlv, Frlh>
187{}
188
189/// Marker trait for edge/level configuration types.
190pub trait EdgeLevelCfg {}
191
192impl EdgeLevelCfg for Unconfigured {}
193
194/// Configure an I/O line's event detector to detect edges.
195pub struct DetectEdges;
196
197impl Configured for DetectEdges {}
198impl EdgeLevelCfg for DetectEdges {}
199
200/// # Input Edge/Level Interrupt (Edge/Level)
201///
202/// Determines whether an interrupt is triggered on a falling edge/rising edge (depending on
203/// fall/rise - low/high configuration) or low level/high level (depending on fall/rise - low/high
204/// configuration).
205pub trait ConfigureEdgeLevel {
206    type Edge: ConfigureEdgeLevel;
207    type Level: ConfigureEdgeLevel;
208
209    /// Trigger interrupts on edges for this pin. Waits for `PIO_ELSR` to update accordingly.
210    fn detect_edges(self) -> Self::Edge;
211    /// Trigger interrupts on edges for this pin without waiting for `PIO_ELSR` to update.
212    ///
213    /// # Safety
214    ///
215    /// While this function returns a type showing that interrupts are triggered on edges, the pin
216    /// will not actually trigger an interrupt on an edge until the corresponding bit in `PIO_ELSR`
217    /// is cleared.
218    unsafe fn detect_edges_unchecked(self) -> Self::Edge;
219    /// Trigger interrupts on levels for this pin. Waits for `PIO_ELSR` to update accordingly.
220    fn detect_levels(self) -> Self::Level;
221    /// Trigger interrupts on levels for this pin without waiting for `PIO_ELSR` to update.
222    ///
223    /// # Safety
224    ///
225    /// While this function returns a type showing that interrupts are triggered on levels, the pin
226    /// will not actually trigger an interrupt on a level until the corresponding bit in `PIO_ELSR`
227    /// is set.
228    unsafe fn detect_levels_unchecked(self) -> Self::Level;
229}
230
231/// Configure an I/O line's event detector to detect levels.
232pub struct DetectLevels;
233
234impl Configured for DetectLevels {}
235impl EdgeLevelCfg for DetectLevels {}
236
237/// Marker trait for fall/rise - low/high configuration types.
238pub trait FallRiseLowHighCfg {}
239
240impl FallRiseLowHighCfg for Unconfigured {}
241
242/// Configure an I/O line's event detector to detect falling edges or low levels depending
243/// on whether it is configured to detect edges or levels.
244pub struct DetectFallingEdgeLowLevel;
245
246impl Configured for DetectFallingEdgeLowLevel {}
247impl FallRiseLowHighCfg for DetectFallingEdgeLowLevel {}
248
249/// # Input Edge/Level Interrupt (Fall/Rise - Low/High)
250///
251/// Determines whether an interrupt is triggered on a falling edge/low level (depending on
252/// edge/level configuration) or rising edge/high level (depending on edge/level configuration).
253pub trait ConfigureFallRiseLowHigh {
254    type Fell: ConfigureFallRiseLowHigh;
255    type Rehl: ConfigureFallRiseLowHigh;
256
257    /// Trigger interrupts on falling edges/low levels for this pin. Waits for `PIO_FRLHSR` to
258    /// update accordingly.
259    fn detect_falling_edge_low_level(self) -> Self::Fell;
260    /// Trigger interrupts on falling edges/low levels for this pin without waiting for `PIO_FRLHSR`
261    /// to update.
262    ///
263    /// # Safety
264    ///
265    /// While this function returns a type showing that interrupts are triggered on falling
266    /// edges/rising levels, the pin will not actually trigger an interrupt on either until the
267    /// corresponding bit in `PIO_FRLHSR` is cleared.
268    unsafe fn detect_falling_edge_low_level_unchecked(self) -> Self::Fell;
269    /// Trigger interrupts on rising edges/high levels for this pin. Waits for `PIO_FRLHSR` to
270    /// update accordingly.
271    fn detect_rising_edge_high_level(self) -> Self::Rehl;
272    /// Trigger interrupts on rising edges/high levels for this pin without waiting for `PIO_FRLHSR`
273    /// to update.
274    ///
275    /// # Safety
276    ///
277    /// While this function returns a type showing that interrupts are triggered on rising
278    /// edges/falling levels, the pin will not actually trigger an interrupt on either until the
279    /// corresponding bit in `PIO_FRLHSR` is set.
280    unsafe fn detect_rising_edge_high_level_unchecked(self) -> Self::Rehl;
281}
282
283/// Configure an I/O line's event detector to detect rising edges or high levels depending
284/// on whether it is configured to detect edges or levels.
285pub struct DetectRisingEdgeHighLevel;
286
287impl Configured for DetectRisingEdgeHighLevel {}
288impl FallRiseLowHighCfg for DetectRisingEdgeHighLevel {}
289
290impl<Pio, Pid, Mdvr, Pioc, Padr, Filt> ConfigureInterrupt
291    for Pin<Pio, Pid, Mdvr, Pioc, Padr, Unconfigured, Filt>
292where
293    Pio: PioRegisters,
294    Pid: PinId<Controller = Pio>,
295    Mdvr: MultiDriverCfg,
296    Pioc: PioControlCfg,
297    Padr: PadResistorCfg,
298    Filt: InputFilterCfg,
299{
300    type Enabled = Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptEnabled<Unconfigured>, Filt>;
301    type Disabled = Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptDisabled, Filt>;
302
303    fn enable_interrupt(self) -> Self::Enabled {
304        unsafe {
305            let pioreg = &*Pio::PTR;
306            if pioreg._imr().read().bits() & Pid::MASK == 0 {
307                let _ = self.enable_interrupt_unchecked();
308                while pioreg._imr().read().bits() & Pid::MASK == 0 {}
309            }
310            Pin::new()
311        }
312    }
313
314    unsafe fn enable_interrupt_unchecked(self) -> Self::Enabled {
315        let pioreg = &*Pio::PTR;
316        pioreg._ier().write_with_zero(|w| w.bits(Pid::MASK));
317        Pin::new()
318    }
319
320    fn disable_interrupt(self) -> Self::Disabled {
321        unsafe {
322            let pioreg = &*Pio::PTR;
323            if pioreg._imr().read().bits() & Pid::MASK != 0 {
324                let _ = self.enable_interrupt_unchecked();
325                while pioreg._imr().read().bits() & Pid::MASK != 0 {}
326            }
327            Pin::new()
328        }
329    }
330
331    unsafe fn disable_interrupt_unchecked(self) -> Self::Disabled {
332        let pioreg = &*Pio::PTR;
333        pioreg._idr().write_with_zero(|w| w.bits(Pid::MASK));
334        Pin::new()
335    }
336}
337
338impl<Pio, Pid, Mdvr, Pioc, Padr, Aint, Filt> ConfigureInterrupt
339    for Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptEnabled<Aint>, Filt>
340where
341    Self: ConfigureAdditionalInterruptModes,
342    Pio: PioRegisters,
343    Pid: PinId<Controller = Pio>,
344    Mdvr: MultiDriverCfg,
345    Pioc: PioControlCfg,
346    Padr: PadResistorCfg,
347    Aint: AdditionalInterruptModesCfg,
348    Filt: InputFilterCfg,
349{
350    type Enabled = Self;
351    type Disabled = Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptDisabled, Filt>;
352
353    fn enable_interrupt(self) -> Self::Enabled {
354        self
355    }
356
357    unsafe fn enable_interrupt_unchecked(self) -> Self::Enabled {
358        self
359    }
360
361    fn disable_interrupt(self) -> Self::Disabled {
362        unsafe {
363            let pioreg = &*Pio::PTR;
364            let _ = self.disable_interrupt_unchecked();
365            while pioreg._imr().read().bits() & Pid::MASK != 0 {}
366            Pin::new()
367        }
368    }
369
370    unsafe fn disable_interrupt_unchecked(self) -> Self::Disabled {
371        let pioreg = &*Pio::PTR;
372        pioreg._idr().write_with_zero(|w| w.bits(Pid::MASK));
373        Pin::new()
374    }
375}
376
377impl<Pio, Pid, Mdvr, Pioc, Padr, Filt> ConfigureInterrupt
378    for Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptDisabled, Filt>
379where
380    Pio: PioRegisters,
381    Pid: PinId<Controller = Pio>,
382    Mdvr: MultiDriverCfg,
383    Pioc: PioControlCfg,
384    Padr: PadResistorCfg,
385    Filt: InputFilterCfg,
386{
387    type Enabled = Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptEnabled<Unconfigured>, Filt>;
388    type Disabled = Self;
389
390    fn enable_interrupt(self) -> Self::Enabled {
391        unsafe {
392            let pioreg = &*Pio::PTR;
393            let _ = self.enable_interrupt_unchecked();
394            while pioreg._imr().read().bits() & Pid::MASK == 0 {}
395            Pin::new()
396        }
397    }
398
399    unsafe fn enable_interrupt_unchecked(self) -> Self::Enabled {
400        let pioreg = &*Pio::PTR;
401        pioreg._ier().write_with_zero(|w| w.bits(Pid::MASK));
402        Pin::new()
403    }
404
405    fn disable_interrupt(self) -> Self::Disabled {
406        self
407    }
408
409    unsafe fn disable_interrupt_unchecked(self) -> Self::Disabled {
410        self
411    }
412}
413
414impl<Pio, Pid, Mdvr, Pioc, Padr, Filt> ConfigureAdditionalInterruptModes
415    for Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptEnabled<Unconfigured>, Filt>
416where
417    Pio: PioRegisters,
418    Pid: PinId<Controller = Pio>,
419    Mdvr: MultiDriverCfg,
420    Pioc: PioControlCfg,
421    Padr: PadResistorCfg,
422    Filt: InputFilterCfg,
423{
424    type Enabled = Pin<
425        Pio,
426        Pid,
427        Mdvr,
428        Pioc,
429        Padr,
430        InterruptEnabled<AdditionalInterruptModesEnabled<Unconfigured, Unconfigured>>,
431        Filt,
432    >;
433    type Disabled =
434        Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptEnabled<AdditionalInterruptModesDisabled>, Filt>;
435
436    fn enable_additional_interrupt_modes(self) -> Self::Enabled {
437        unsafe {
438            let pioreg = &*Pio::PTR;
439            if pioreg._aimmr().read().bits() & Pid::MASK == 0 {
440                let _ = self.enable_additional_interrupt_modes_unchecked();
441                while pioreg._aimmr().read().bits() & Pid::MASK == 0 {}
442            }
443            Pin::new()
444        }
445    }
446
447    unsafe fn enable_additional_interrupt_modes_unchecked(self) -> Self::Enabled {
448        let pioreg = &*Pio::PTR;
449        pioreg._aimer().write_with_zero(|w| w.bits(Pid::MASK));
450        Pin::new()
451    }
452
453    fn disable_additional_interrupt_modes(self) -> Self::Disabled {
454        unsafe {
455            let pioreg = &*Pio::PTR;
456            if pioreg._aimmr().read().bits() & Pid::MASK != 0 {
457                let _ = self.disable_additional_interrupt_modes_unchecked();
458                while pioreg._aimmr().read().bits() & Pid::MASK != 0 {}
459            }
460            Pin::new()
461        }
462    }
463
464    unsafe fn disable_additional_interrupt_modes_unchecked(self) -> Self::Disabled {
465        let pioreg = &*Pio::PTR;
466        pioreg._aimdr().write_with_zero(|w| w.bits(Pid::MASK));
467        Pin::new()
468    }
469}
470
471impl<Pio, Pid, Mdvr, Pioc, Padr, Edlv, Frlh, Filt> ConfigureAdditionalInterruptModes
472    for Pin<
473        Pio,
474        Pid,
475        Mdvr,
476        Pioc,
477        Padr,
478        InterruptEnabled<AdditionalInterruptModesEnabled<Edlv, Frlh>>,
479        Filt,
480    >
481where
482    Self: ConfigureEdgeLevel + ConfigureFallRiseLowHigh,
483    Pio: PioRegisters,
484    Pid: PinId<Controller = Pio>,
485    Mdvr: MultiDriverCfg,
486    Pioc: PioControlCfg,
487    Padr: PadResistorCfg,
488    Edlv: EdgeLevelCfg,
489    Frlh: FallRiseLowHighCfg,
490    Filt: InputFilterCfg,
491{
492    type Enabled = Self;
493    type Disabled =
494        Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptEnabled<AdditionalInterruptModesDisabled>, Filt>;
495
496    fn enable_additional_interrupt_modes(self) -> Self::Enabled {
497        self
498    }
499
500    unsafe fn enable_additional_interrupt_modes_unchecked(self) -> Self::Enabled {
501        self
502    }
503
504    fn disable_additional_interrupt_modes(self) -> Self::Disabled {
505        unsafe {
506            let pioreg = &*Pio::PTR;
507            let _ = self.disable_additional_interrupt_modes_unchecked();
508            while pioreg._aimmr().read().bits() & Pid::MASK != 0 {}
509            Pin::new()
510        }
511    }
512
513    unsafe fn disable_additional_interrupt_modes_unchecked(self) -> Self::Disabled {
514        let pioreg = &*Pio::PTR;
515        pioreg._aimdr().write_with_zero(|w| w.bits(Pid::MASK));
516        Pin::new()
517    }
518}
519
520impl<Pio, Pid, Mdvr, Pioc, Padr, Filt> ConfigureAdditionalInterruptModes
521    for Pin<Pio, Pid, Mdvr, Pioc, Padr, InterruptEnabled<AdditionalInterruptModesDisabled>, Filt>
522where
523    Pio: PioRegisters,
524    Pid: PinId<Controller = Pio>,
525    Mdvr: MultiDriverCfg,
526    Pioc: PioControlCfg,
527    Padr: PadResistorCfg,
528    Filt: InputFilterCfg,
529{
530    type Enabled = Pin<
531        Pio,
532        Pid,
533        Mdvr,
534        Pioc,
535        Padr,
536        InterruptEnabled<AdditionalInterruptModesEnabled<Unconfigured, Unconfigured>>,
537        Filt,
538    >;
539    type Disabled = Self;
540
541    fn enable_additional_interrupt_modes(self) -> Self::Enabled {
542        unsafe {
543            let pioreg = &*Pio::PTR;
544            let _ = self.enable_additional_interrupt_modes_unchecked();
545            while pioreg._aimmr().read().bits() & Pid::MASK == 0 {}
546            Pin::new()
547        }
548    }
549
550    unsafe fn enable_additional_interrupt_modes_unchecked(self) -> Self::Enabled {
551        let pioreg = &*Pio::PTR;
552        pioreg._aimer().write_with_zero(|w| w.bits(Pid::MASK));
553        Pin::new()
554    }
555
556    fn disable_additional_interrupt_modes(self) -> Self::Disabled {
557        self
558    }
559
560    unsafe fn disable_additional_interrupt_modes_unchecked(self) -> Self::Disabled {
561        self
562    }
563}
564
565impl<Pio, Pid, Mdvr, Pioc, Padr, Frlh, Filt> ConfigureEdgeLevel
566    for Pin<
567        Pio,
568        Pid,
569        Mdvr,
570        Pioc,
571        Padr,
572        InterruptEnabled<AdditionalInterruptModesEnabled<Unconfigured, Frlh>>,
573        Filt,
574    >
575where
576    Pio: PioRegisters,
577    Pid: PinId<Controller = Pio>,
578    Mdvr: MultiDriverCfg,
579    Pioc: PioControlCfg,
580    Padr: PadResistorCfg,
581    Frlh: FallRiseLowHighCfg,
582    Filt: InputFilterCfg,
583{
584    type Edge = Pin<
585        Pio,
586        Pid,
587        Mdvr,
588        Pioc,
589        Padr,
590        InterruptEnabled<AdditionalInterruptModesEnabled<DetectEdges, Frlh>>,
591        Filt,
592    >;
593    type Level = Pin<
594        Pio,
595        Pid,
596        Mdvr,
597        Pioc,
598        Padr,
599        InterruptEnabled<AdditionalInterruptModesEnabled<DetectLevels, Frlh>>,
600        Filt,
601    >;
602
603    fn detect_edges(self) -> Self::Edge {
604        unsafe {
605            let pioreg = &*Pio::PTR;
606            if pioreg._elsr().read().bits() & Pid::MASK != 0 {
607                let _ = self.detect_edges_unchecked();
608                while pioreg._elsr().read().bits() & Pid::MASK != 0 {}
609            }
610            Pin::new()
611        }
612    }
613
614    unsafe fn detect_edges_unchecked(self) -> Self::Edge {
615        let pioreg = &*Pio::PTR;
616        pioreg._esr().write_with_zero(|w| w.bits(Pid::MASK));
617        Pin::new()
618    }
619
620    fn detect_levels(self) -> Self::Level {
621        unsafe {
622            let pioreg = &*Pio::PTR;
623            if pioreg._elsr().read().bits() & Pid::MASK == 0 {
624                let _ = self.detect_levels_unchecked();
625                while pioreg._elsr().read().bits() & Pid::MASK == 0 {}
626            }
627            Pin::new()
628        }
629    }
630
631    unsafe fn detect_levels_unchecked(self) -> Self::Level {
632        let pioreg = &*Pio::PTR;
633        pioreg._lsr().write_with_zero(|w| w.bits(Pid::MASK));
634        Pin::new()
635    }
636}
637
638impl<Pio, Pid, Mdvr, Pioc, Padr, Frlh, Filt> ConfigureEdgeLevel
639    for Pin<
640        Pio,
641        Pid,
642        Mdvr,
643        Pioc,
644        Padr,
645        InterruptEnabled<AdditionalInterruptModesEnabled<DetectEdges, Frlh>>,
646        Filt,
647    >
648where
649    Pio: PioRegisters,
650    Pid: PinId<Controller = Pio>,
651    Mdvr: MultiDriverCfg,
652    Pioc: PioControlCfg,
653    Padr: PadResistorCfg,
654    Frlh: FallRiseLowHighCfg,
655    Filt: InputFilterCfg,
656{
657    type Edge = Self;
658    type Level = Pin<
659        Pio,
660        Pid,
661        Mdvr,
662        Pioc,
663        Padr,
664        InterruptEnabled<AdditionalInterruptModesEnabled<DetectLevels, Frlh>>,
665        Filt,
666    >;
667
668    fn detect_edges(self) -> Self::Edge {
669        self
670    }
671
672    unsafe fn detect_edges_unchecked(self) -> Self::Edge {
673        self
674    }
675
676    fn detect_levels(self) -> Self::Level {
677        unsafe {
678            let pioreg = &*Pio::PTR;
679            let _ = self.detect_levels_unchecked();
680            while pioreg._elsr().read().bits() & Pid::MASK == 0 {}
681            Pin::new()
682        }
683    }
684
685    unsafe fn detect_levels_unchecked(self) -> Self::Level {
686        let pioreg = &*Pio::PTR;
687        pioreg._lsr().write_with_zero(|w| w.bits(Pid::MASK));
688        Pin::new()
689    }
690}
691
692impl<Pio, Pid, Mdvr, Pioc, Padr, Frlh, Filt> ConfigureEdgeLevel
693    for Pin<
694        Pio,
695        Pid,
696        Mdvr,
697        Pioc,
698        Padr,
699        InterruptEnabled<AdditionalInterruptModesEnabled<DetectLevels, Frlh>>,
700        Filt,
701    >
702where
703    Pio: PioRegisters,
704    Pid: PinId<Controller = Pio>,
705    Mdvr: MultiDriverCfg,
706    Pioc: PioControlCfg,
707    Padr: PadResistorCfg,
708    Frlh: FallRiseLowHighCfg,
709    Filt: InputFilterCfg,
710{
711    type Edge = Pin<
712        Pio,
713        Pid,
714        Mdvr,
715        Pioc,
716        Padr,
717        InterruptEnabled<AdditionalInterruptModesEnabled<DetectEdges, Frlh>>,
718        Filt,
719    >;
720    type Level = Self;
721
722    fn detect_edges(self) -> Self::Edge {
723        unsafe {
724            let pioreg = &*Pio::PTR;
725            let _ = self.detect_edges_unchecked();
726            while pioreg._elsr().read().bits() & Pid::MASK != 0 {}
727            Pin::new()
728        }
729    }
730
731    unsafe fn detect_edges_unchecked(self) -> Self::Edge {
732        let pioreg = &*Pio::PTR;
733        pioreg._esr().write_with_zero(|w| w.bits(Pid::MASK));
734        Pin::new()
735    }
736
737    fn detect_levels(self) -> Self::Level {
738        self
739    }
740
741    unsafe fn detect_levels_unchecked(self) -> Self::Level {
742        self
743    }
744}
745
746impl<Pio, Pid, Mdvr, Pioc, Padr, Edlv, Filt> ConfigureFallRiseLowHigh
747    for Pin<
748        Pio,
749        Pid,
750        Mdvr,
751        Pioc,
752        Padr,
753        InterruptEnabled<AdditionalInterruptModesEnabled<Edlv, Unconfigured>>,
754        Filt,
755    >
756where
757    Pio: PioRegisters,
758    Pid: PinId<Controller = Pio>,
759    Mdvr: MultiDriverCfg,
760    Pioc: PioControlCfg,
761    Padr: PadResistorCfg,
762    Edlv: EdgeLevelCfg,
763    Filt: InputFilterCfg,
764{
765    type Fell = Pin<
766        Pio,
767        Pid,
768        Mdvr,
769        Pioc,
770        Padr,
771        InterruptEnabled<AdditionalInterruptModesEnabled<Edlv, DetectFallingEdgeLowLevel>>,
772        Filt,
773    >;
774    type Rehl = Pin<
775        Pio,
776        Pid,
777        Mdvr,
778        Pioc,
779        Padr,
780        InterruptEnabled<AdditionalInterruptModesEnabled<Edlv, DetectRisingEdgeHighLevel>>,
781        Filt,
782    >;
783
784    fn detect_falling_edge_low_level(self) -> Self::Fell {
785        unsafe {
786            let pioreg = &*Pio::PTR;
787            if pioreg._frlhsr().read().bits() & Pid::MASK != 0 {
788                let _ = self.detect_falling_edge_low_level_unchecked();
789                while pioreg._frlhsr().read().bits() & Pid::MASK != 0 {}
790            }
791            Pin::new()
792        }
793    }
794
795    unsafe fn detect_falling_edge_low_level_unchecked(self) -> Self::Fell {
796        let pioreg = &*Pio::PTR;
797        pioreg._fellsr().write_with_zero(|w| w.bits(Pid::MASK));
798        Pin::new()
799    }
800
801    fn detect_rising_edge_high_level(self) -> Self::Rehl {
802        unsafe {
803            let pioreg = &*Pio::PTR;
804            if pioreg._frlhsr().read().bits() & Pid::MASK == 0 {
805                let _ = self.detect_rising_edge_high_level_unchecked();
806                while pioreg._frlhsr().read().bits() & Pid::MASK == 0 {}
807            }
808            Pin::new()
809        }
810    }
811
812    unsafe fn detect_rising_edge_high_level_unchecked(self) -> Self::Rehl {
813        let pioreg = &*Pio::PTR;
814        pioreg._rehlsr().write_with_zero(|w| w.bits(Pid::MASK));
815        Pin::new()
816    }
817}
818
819impl<Pio, Pid, Mdvr, Pioc, Padr, Edlv, Filt> ConfigureFallRiseLowHigh
820    for Pin<
821        Pio,
822        Pid,
823        Mdvr,
824        Pioc,
825        Padr,
826        InterruptEnabled<AdditionalInterruptModesEnabled<Edlv, DetectFallingEdgeLowLevel>>,
827        Filt,
828    >
829where
830    Pio: PioRegisters,
831    Pid: PinId<Controller = Pio>,
832    Mdvr: MultiDriverCfg,
833    Pioc: PioControlCfg,
834    Padr: PadResistorCfg,
835    Edlv: EdgeLevelCfg,
836    Filt: InputFilterCfg,
837{
838    type Fell = Self;
839    type Rehl = Pin<
840        Pio,
841        Pid,
842        Mdvr,
843        Pioc,
844        Padr,
845        InterruptEnabled<AdditionalInterruptModesEnabled<Edlv, DetectRisingEdgeHighLevel>>,
846        Filt,
847    >;
848
849    fn detect_falling_edge_low_level(self) -> Self::Fell {
850        self
851    }
852
853    unsafe fn detect_falling_edge_low_level_unchecked(self) -> Self::Fell {
854        self
855    }
856
857    fn detect_rising_edge_high_level(self) -> Self::Rehl {
858        unsafe {
859            let pioreg = &*Pio::PTR;
860            let _ = self.detect_rising_edge_high_level_unchecked();
861            while pioreg._frlhsr().read().bits() & Pid::MASK == 0 {}
862            Pin::new()
863        }
864    }
865
866    unsafe fn detect_rising_edge_high_level_unchecked(self) -> Self::Rehl {
867        unsafe {
868            let pioreg = &*Pio::PTR;
869            pioreg._rehlsr().write_with_zero(|w| w.bits(Pid::MASK));
870            Pin::new()
871        }
872    }
873}
874
875impl<Pio, Pid, Mdvr, Pioc, Padr, Edlv, Filt> ConfigureFallRiseLowHigh
876    for Pin<
877        Pio,
878        Pid,
879        Mdvr,
880        Pioc,
881        Padr,
882        InterruptEnabled<AdditionalInterruptModesEnabled<Edlv, DetectRisingEdgeHighLevel>>,
883        Filt,
884    >
885where
886    Pio: PioRegisters,
887    Pid: PinId<Controller = Pio>,
888    Mdvr: MultiDriverCfg,
889    Pioc: PioControlCfg,
890    Padr: PadResistorCfg,
891    Edlv: EdgeLevelCfg,
892    Filt: InputFilterCfg,
893{
894    type Fell = Pin<
895        Pio,
896        Pid,
897        Mdvr,
898        Pioc,
899        Padr,
900        InterruptEnabled<AdditionalInterruptModesEnabled<Edlv, DetectFallingEdgeLowLevel>>,
901        Filt,
902    >;
903    type Rehl = Self;
904
905    fn detect_falling_edge_low_level(self) -> Self::Fell {
906        unsafe {
907            let pioreg = &*Pio::PTR;
908            let _ = self.detect_falling_edge_low_level_unchecked();
909            while pioreg._frlhsr().read().bits() & Pid::MASK != 0 {}
910            Pin::new()
911        }
912    }
913
914    unsafe fn detect_falling_edge_low_level_unchecked(self) -> Self::Fell {
915        let pioreg = &*Pio::PTR;
916        pioreg._fellsr().write_with_zero(|w| w.bits(Pid::MASK));
917        Pin::new()
918    }
919
920    fn detect_rising_edge_high_level(self) -> Self::Rehl {
921        self
922    }
923
924    unsafe fn detect_rising_edge_high_level_unchecked(self) -> Self::Rehl {
925        self
926    }
927}