esp_hal/
parl_io.rs

1//! # Parallel IO (PARL_IO)
2//!
3//! ## Overview
4//! The Parallel IO peripheral is a general purpose parallel interface that can
5//! be used to connect to external devices such as LED matrix, LCD display,
6//! Printer and Camera. The peripheral has independent TX and RX units. Each
7//! unit can have up to 8 or 16 data signals (depending on your target hardware)
8//! plus 1 or 2 clock signals.
9//!
10//! ## Configuration
11//! The driver uses DMA (Direct Memory Access) for efficient data transfer.
12//!
13//! ## Examples
14//! ### Initialization for RX
15//!
16//! ```rust, no_run
17#![doc = crate::before_snippet!()]
18//! # use esp_hal::delay::Delay;
19//! # use esp_hal::dma_buffers;
20//! # use esp_hal::dma::DmaRxBuf;
21//! # use esp_hal::gpio::NoPin;
22//! # use esp_hal::parl_io::{BitPackOrder, ParlIoRxOnly, RxFourBits};
23//!
24//! // Initialize DMA buffer and descriptors for data reception
25//! let (rx_buffer, rx_descriptors, _, _) = dma_buffers!(32000, 0);
26//! let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer)?;
27//! let dma_channel = peripherals.DMA_CH0;
28//!
29//! // Configure the 4-bit input pins and clock pin
30//! let mut rx_pins = RxFourBits::new(
31//!     peripherals.GPIO1,
32//!     peripherals.GPIO2,
33//!     peripherals.GPIO3,
34//!     peripherals.GPIO4,
35//! );
36//! let mut rx_clk_pin = NoPin;
37//!
38//! // Set up Parallel IO for 1MHz data input, with DMA and bit packing
39//! //  configuration
40//!  let parl_io = ParlIoRxOnly::new(
41//!     peripherals.PARL_IO,
42//!     dma_channel,
43//!     Rate::from_mhz(1),
44//! )?;
45//!
46//! let mut parl_io_rx = parl_io
47//!     .rx
48//!     .with_config(
49//!         &mut rx_pins,
50//!         &mut rx_clk_pin,
51//!         BitPackOrder::Msb,
52//!         Some(0xfff),
53//!     )?;
54//!
55//! // Initialize the buffer and delay
56//! dma_rx_buf.as_mut_slice().fill(0u8);
57//! let delay = Delay::new();
58//!
59//! loop {
60//!     // Read data via DMA and print received values
61//!     let transfer = parl_io_rx.read(Some(dma_rx_buf.len()), dma_rx_buf)?;
62//!     (_, parl_io_rx, dma_rx_buf) = transfer.wait();
63//!
64//!     delay.delay_millis(500);
65//! }
66//! # }
67//! ```
68//! 
69//! ### Initialization for TX
70//! ```rust, no_run
71#![doc = crate::before_snippet!()]
72//! # use esp_hal::delay::Delay;
73//! # use esp_hal::dma_tx_buffer;
74//! # use esp_hal::parl_io::{BitPackOrder, ParlIoTxOnly, TxFourBits, SampleEdge, ClkOutPin, TxPinConfigWithValidPin};
75//!
76//! // Initialize DMA buffer and descriptors for data reception
77//! let mut dma_tx_buf = dma_tx_buffer!(32000).unwrap();
78//! let dma_channel = peripherals.DMA_CH0;
79//!
80//! // Configure the 4-bit input pins and clock pin
81//! let tx_pins = TxFourBits::new(
82//!     peripherals.GPIO1,
83//!     peripherals.GPIO2,
84//!     peripherals.GPIO3,
85//!     peripherals.GPIO4,
86//! );
87//!
88//! let mut pin_conf = TxPinConfigWithValidPin::new(tx_pins, peripherals.GPIO5);
89//!
90//! // Set up Parallel IO for 1MHz data input, with DMA and bit packing
91//! //  configuration
92//!  let parl_io = ParlIoTxOnly::new(
93//!     peripherals.PARL_IO,
94//!     dma_channel,
95//!     Rate::from_mhz(1),
96//! )?;
97//!
98//! let mut clock_pin = ClkOutPin::new(peripherals.GPIO6);
99//! let mut parl_io_tx = parl_io
100//!     .tx
101//!     .with_config(
102//!         &mut pin_conf,
103//!         &mut clock_pin,
104//!         0,
105//!         SampleEdge::Normal,
106//!         BitPackOrder::Msb,
107//!     )?;
108//!
109//! for i in 0..dma_tx_buf.len() {
110//!      dma_tx_buf.as_mut_slice()[i] = (i % 255) as u8;
111//! }
112//!
113//! let delay = Delay::new();
114//! loop {
115//!     let transfer = parl_io_tx.write(dma_tx_buf.len(), dma_tx_buf)?;
116//!     (_, parl_io_tx, dma_tx_buf) = transfer.wait();
117//!     delay.delay_millis(500);
118//! }
119//! # }
120//! ```
121
122use core::{
123    mem::ManuallyDrop,
124    ops::{Deref, DerefMut},
125};
126
127use enumset::{EnumSet, EnumSetType};
128use peripheral::PeripheralRef;
129use private::*;
130
131use crate::{
132    dma::{
133        Channel,
134        ChannelRx,
135        ChannelTx,
136        DmaChannelFor,
137        DmaError,
138        DmaPeripheral,
139        DmaRxBuffer,
140        DmaTxBuffer,
141        PeripheralRxChannel,
142        PeripheralTxChannel,
143        Rx,
144        RxChannelFor,
145        Tx,
146        TxChannelFor,
147    },
148    gpio::{
149        interconnect::{InputConnection, OutputConnection, PeripheralInput, PeripheralOutput},
150        NoPin,
151    },
152    interrupt::InterruptHandler,
153    parl_io::asynch::interrupt_handler,
154    peripheral::{self, Peripheral},
155    peripherals::{Interrupt, PARL_IO, PCR},
156    system::{self, GenericPeripheralGuard},
157    time::Rate,
158    Async,
159    Blocking,
160    DriverMode,
161};
162
163#[allow(unused)]
164const MAX_DMA_SIZE: usize = 32736;
165
166/// Interrupts generated by the peripheral
167#[derive(Debug, EnumSetType)]
168#[cfg_attr(feature = "defmt", derive(defmt::Format))]
169pub enum ParlIoInterrupt {
170    /// Triggered when TX FIFO is empty. This interrupt indicates that there
171    /// might be error in the data sent by TX.
172    TxFifoReEmpty,
173    /// Triggered when RX FIFO is full. This interrupt indicates that there
174    /// might be error in the data received by RX.
175    RxFifoWOvf,
176    /// Triggered when TX finishes sending a complete frame of data.
177    TxEof,
178}
179
180/// Parallel IO errors
181#[derive(Debug, Clone, Copy, PartialEq)]
182#[cfg_attr(feature = "defmt", derive(defmt::Format))]
183#[allow(clippy::enum_variant_names, reason = "peripheral is unstable")]
184pub enum Error {
185    /// General DMA error
186    DmaError(DmaError),
187    /// Maximum transfer size (32736) exceeded
188    MaxDmaTransferSizeExceeded,
189    /// Trying to use an impossible clock rate
190    UnreachableClockRate,
191}
192
193impl From<DmaError> for Error {
194    fn from(value: DmaError) -> Self {
195        Error::DmaError(value)
196    }
197}
198
199/// Parallel IO sample edge
200#[derive(Debug, Clone, Copy, PartialEq)]
201#[cfg_attr(feature = "defmt", derive(defmt::Format))]
202pub enum SampleEdge {
203    /// Positive edge
204    Normal = 0,
205    /// Negative edge
206    Invert = 1,
207}
208
209/// Parallel IO bit packing order
210#[derive(Debug, Clone, Copy, PartialEq)]
211#[cfg_attr(feature = "defmt", derive(defmt::Format))]
212pub enum BitPackOrder {
213    /// Bit pack order: MSB
214    Msb = 0,
215    /// Bit pack order: LSB
216    Lsb = 1,
217}
218
219#[cfg(esp32c6)]
220/// Enable Mode
221#[derive(Debug, Clone, Copy, PartialEq)]
222#[cfg_attr(feature = "defmt", derive(defmt::Format))]
223pub enum EnableMode {
224    /// Enable at high level
225    HighLevel,
226    /// Enable at low level
227    LowLevel,
228    /// Positive pulse start (data bit included) & Positive pulse end (data bit
229    /// included)
230    PulseMode1,
231    /// Positive pulse start (data bit included) & Positive pulse end (data bit
232    /// excluded)
233    PulseMode2,
234    /// Positive pulse start (data bit excluded) & Positive pulse end (data bit
235    /// included)
236    PulseMode3,
237    /// Positive pulse start (data bit excluded) & Positive pulse end (data bit
238    /// excluded)
239    PulseMode4,
240    /// Positive pulse start (data bit included) & Length end
241    PulseMode5,
242    /// Positive pulse start (data bit excluded) & Length end
243    PulseMode6,
244    /// Negative pulse start (data bit included) & Negative pulse end(data bit
245    /// included)
246    PulseMode7,
247    /// Negative pulse start (data bit included) & Negative pulse end (data bit
248    /// excluded)
249    PulseMode8,
250    /// Negative pulse start (data bit excluded) & Negative pulse end (data bit
251    /// included)
252    PulseMode9,
253    /// Negative pulse start (data bit excluded) & Negative pulse end (data bit
254    /// excluded)
255    PulseMode10,
256    /// Negative pulse start (data bit included) & Length end
257    PulseMode11,
258    /// Negative pulse start (data bit excluded) & Length end
259    PulseMode12,
260}
261
262#[cfg(esp32c6)]
263impl EnableMode {
264    fn pulse_submode_sel(&self) -> Option<u8> {
265        match self {
266            EnableMode::PulseMode1 => Some(0),
267            EnableMode::PulseMode2 => Some(1),
268            EnableMode::PulseMode3 => Some(2),
269            EnableMode::PulseMode4 => Some(3),
270            EnableMode::PulseMode5 => Some(4),
271            EnableMode::PulseMode6 => Some(5),
272            EnableMode::PulseMode7 => Some(6),
273            EnableMode::PulseMode8 => Some(7),
274            EnableMode::PulseMode9 => Some(8),
275            EnableMode::PulseMode10 => Some(9),
276            EnableMode::PulseMode11 => Some(10),
277            EnableMode::PulseMode12 => Some(11),
278            _ => None,
279        }
280    }
281
282    fn level_submode_sel(&self) -> Option<u8> {
283        match self {
284            EnableMode::HighLevel => Some(0),
285            EnableMode::LowLevel => Some(1),
286            _ => None,
287        }
288    }
289
290    fn smp_model_sel(&self) -> Option<self::private::SampleMode> {
291        match self {
292            EnableMode::HighLevel => Some(self::private::SampleMode::ExternalLevel),
293            EnableMode::LowLevel => Some(self::private::SampleMode::ExternalLevel),
294            _ => Some(self::private::SampleMode::ExternalPulse),
295        }
296    }
297}
298
299#[cfg(esp32h2)]
300/// Enable Mode
301#[derive(Debug, Clone, Copy, PartialEq)]
302#[cfg_attr(feature = "defmt", derive(defmt::Format))]
303pub enum EnableMode {
304    /// Enable at high level
305    HighLevel,
306    /// Positive pulse start (data bit included) & Positive pulse end (data bit
307    /// included)
308    PulseMode1,
309    /// Positive pulse start (data bit included) & Positive pulse end (data bit
310    /// excluded)
311    PulseMode2,
312    /// Positive pulse start (data bit excluded) & Positive pulse end (data bit
313    /// included)
314    PulseMode3,
315    /// Positive pulse start (data bit excluded) & Positive pulse end (data bit
316    /// excluded)
317    PulseMode4,
318    /// Positive pulse start (data bit included) & Length end
319    PulseMode5,
320    /// Positive pulse start (data bit excluded) & Length end
321    PulseMode6,
322}
323
324#[cfg(esp32h2)]
325impl EnableMode {
326    fn pulse_submode_sel(&self) -> Option<u8> {
327        match self {
328            EnableMode::PulseMode1 => Some(0),
329            EnableMode::PulseMode2 => Some(1),
330            EnableMode::PulseMode3 => Some(2),
331            EnableMode::PulseMode4 => Some(3),
332            EnableMode::PulseMode5 => Some(4),
333            EnableMode::PulseMode6 => Some(5),
334            _ => None,
335        }
336    }
337
338    fn level_submode_sel(&self) -> Option<u8> {
339        match self {
340            EnableMode::HighLevel => Some(0),
341            _ => None,
342        }
343    }
344
345    fn smp_model_sel(&self) -> Option<self::private::SampleMode> {
346        match self {
347            EnableMode::HighLevel => Some(self::private::SampleMode::ExternalLevel),
348            _ => Some(self::private::SampleMode::ExternalPulse),
349        }
350    }
351}
352
353/// Used to configure no pin as clock output
354impl TxClkPin for NoPin {
355    fn configure(&mut self) {
356        crate::gpio::OutputSignal::PARL_TX_CLK.connect_to(self);
357    }
358}
359impl RxClkPin for NoPin {
360    fn configure(&mut self) {
361        crate::gpio::InputSignal::PARL_RX_CLK.connect_to(self);
362    }
363}
364
365/// Wraps a GPIO pin which will be used as the clock output signal
366pub struct ClkOutPin<'d> {
367    pin: PeripheralRef<'d, OutputConnection>,
368}
369impl<'d> ClkOutPin<'d> {
370    /// Create a ClkOutPin
371    pub fn new(pin: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self {
372        crate::into_mapped_ref!(pin);
373        Self { pin }
374    }
375}
376impl TxClkPin for ClkOutPin<'_> {
377    fn configure(&mut self) {
378        self.pin.set_to_push_pull_output();
379        crate::gpio::OutputSignal::PARL_TX_CLK.connect_to(&mut self.pin);
380    }
381}
382
383/// Wraps a GPIO pin which will be used as the TX clock input signal
384pub struct ClkInPin<'d> {
385    pin: PeripheralRef<'d, InputConnection>,
386}
387impl<'d> ClkInPin<'d> {
388    /// Create a new ClkInPin
389    pub fn new(pin: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self {
390        crate::into_mapped_ref!(pin);
391        Self { pin }
392    }
393}
394impl TxClkPin for ClkInPin<'_> {
395    fn configure(&mut self) {
396        let pcr = PCR::regs();
397        pcr.parl_clk_tx_conf()
398            .modify(|_, w| unsafe { w.parl_clk_tx_sel().bits(3).parl_clk_tx_div_num().bits(0) }); // PAD_CLK_TX, no divider
399
400        self.pin.init_input(crate::gpio::Pull::None);
401        crate::gpio::InputSignal::PARL_TX_CLK.connect_to(&mut self.pin);
402    }
403}
404
405/// Wraps a GPIO pin which will be used as the RX clock input signal
406pub struct RxClkInPin<'d> {
407    pin: PeripheralRef<'d, InputConnection>,
408    sample_edge: SampleEdge,
409}
410impl<'d> RxClkInPin<'d> {
411    /// Create a new RxClkInPin
412    pub fn new(
413        pin: impl Peripheral<P = impl PeripheralInput> + 'd,
414        sample_edge: SampleEdge,
415    ) -> Self {
416        crate::into_mapped_ref!(pin);
417        Self { pin, sample_edge }
418    }
419}
420impl RxClkPin for RxClkInPin<'_> {
421    fn configure(&mut self) {
422        let pcr = PCR::regs();
423        pcr.parl_clk_rx_conf()
424            .modify(|_, w| unsafe { w.parl_clk_rx_sel().bits(3).parl_clk_rx_div_num().bits(0) }); // PAD_CLK_TX, no divider
425
426        self.pin.init_input(crate::gpio::Pull::None);
427        crate::gpio::InputSignal::PARL_RX_CLK.connect_to(&mut self.pin);
428
429        Instance::set_rx_clk_edge_sel(self.sample_edge);
430    }
431}
432
433/// Pin configuration with an additional pin for the valid signal.
434pub struct TxPinConfigWithValidPin<'d, P>
435where
436    P: NotContainsValidSignalPin + TxPins + ConfigurePins,
437{
438    tx_pins: P,
439    valid_pin: PeripheralRef<'d, OutputConnection>,
440}
441
442impl<'d, P> TxPinConfigWithValidPin<'d, P>
443where
444    P: NotContainsValidSignalPin + TxPins + ConfigurePins,
445{
446    /// Create a [TxPinConfigWithValidPin]
447    pub fn new(tx_pins: P, valid_pin: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self {
448        crate::into_mapped_ref!(valid_pin);
449        Self { tx_pins, valid_pin }
450    }
451}
452
453impl<P> TxPins for TxPinConfigWithValidPin<'_, P> where
454    P: NotContainsValidSignalPin + TxPins + ConfigurePins
455{
456}
457
458impl<P> ConfigurePins for TxPinConfigWithValidPin<'_, P>
459where
460    P: NotContainsValidSignalPin + TxPins + ConfigurePins,
461{
462    fn configure(&mut self) -> Result<(), Error> {
463        self.tx_pins.configure()?;
464        self.valid_pin.set_to_push_pull_output();
465        Instance::tx_valid_pin_signal().connect_to(&mut self.valid_pin);
466        Instance::set_tx_hw_valid_en(true);
467        Ok(())
468    }
469}
470
471/// Pin configuration where the pin for the valid signal is the MSB pin.
472pub struct TxPinConfigIncludingValidPin<P>
473where
474    P: ContainsValidSignalPin + TxPins + ConfigurePins,
475{
476    tx_pins: P,
477}
478
479impl<P> TxPinConfigIncludingValidPin<P>
480where
481    P: ContainsValidSignalPin + TxPins + ConfigurePins,
482{
483    /// Create a new [TxPinConfigIncludingValidPin]
484    pub fn new(tx_pins: P) -> Self {
485        Self { tx_pins }
486    }
487}
488
489impl<P> TxPins for TxPinConfigIncludingValidPin<P> where
490    P: ContainsValidSignalPin + TxPins + ConfigurePins
491{
492}
493
494impl<P> ConfigurePins for TxPinConfigIncludingValidPin<P>
495where
496    P: ContainsValidSignalPin + TxPins + ConfigurePins,
497{
498    fn configure(&mut self) -> Result<(), Error> {
499        self.tx_pins.configure()?;
500        Instance::set_tx_hw_valid_en(true);
501        Ok(())
502    }
503}
504
505macro_rules! tx_pins {
506    ($name:ident, $width:literal, $($pin:ident = $signal:ident),+ ) => {
507        paste::paste! {
508            #[doc = "Data pin configuration for "]
509            #[doc = stringify!($width)]
510            #[doc = "bit output mode"]
511            pub struct $name<'d> {
512                $(
513                    [< pin_ $pin:lower >] : PeripheralRef<'d, OutputConnection>,
514                )+
515            }
516
517            impl<'d> $name<'d>
518            {
519                /// Create a new TX pin
520                #[allow(clippy::too_many_arguments)]
521                pub fn new(
522                    $(
523                        [< pin_ $pin:lower >] : impl Peripheral<P = impl PeripheralOutput > + 'd,
524                    )+
525                ) -> Self {
526                    crate::into_mapped_ref!($( [< pin_ $pin:lower >] ),+);
527                    Self { $( [< pin_ $pin:lower >] ),+ }
528                }
529            }
530
531            impl ConfigurePins for $name<'_>
532            {
533                fn configure(&mut self) -> Result<(), Error>{
534                    $(
535                        self.[< pin_ $pin:lower >].set_to_push_pull_output();
536                        crate::gpio::OutputSignal::$signal.connect_to(&mut self.[< pin_ $pin:lower >]);
537                    )+
538
539                    private::Instance::set_tx_bit_width( private::WidSel::[< Bits $width >]);
540                    Ok(())
541                }
542            }
543
544            impl TxPins for $name<'_> {}
545        }
546    };
547}
548
549tx_pins!(TxOneBit, 1, P0 = PARL_TX_DATA0);
550tx_pins!(TxTwoBits, 2, P0 = PARL_TX_DATA0, P1 = PARL_TX_DATA1);
551tx_pins!(
552    TxFourBits,
553    4,
554    P0 = PARL_TX_DATA0,
555    P1 = PARL_TX_DATA1,
556    P2 = PARL_TX_DATA2,
557    P3 = PARL_TX_DATA3
558);
559tx_pins!(
560    TxEightBits,
561    8,
562    P0 = PARL_TX_DATA0,
563    P1 = PARL_TX_DATA1,
564    P2 = PARL_TX_DATA2,
565    P3 = PARL_TX_DATA3,
566    P4 = PARL_TX_DATA4,
567    P5 = PARL_TX_DATA5,
568    P6 = PARL_TX_DATA6,
569    P7 = PARL_TX_DATA7
570);
571#[cfg(esp32c6)]
572tx_pins!(
573    TxSixteenBits,
574    16,
575    P0 = PARL_TX_DATA0,
576    P1 = PARL_TX_DATA1,
577    P2 = PARL_TX_DATA2,
578    P3 = PARL_TX_DATA3,
579    P4 = PARL_TX_DATA4,
580    P5 = PARL_TX_DATA5,
581    P6 = PARL_TX_DATA6,
582    P7 = PARL_TX_DATA7,
583    P8 = PARL_TX_DATA8,
584    P9 = PARL_TX_DATA9,
585    P10 = PARL_TX_DATA10,
586    P11 = PARL_TX_DATA11,
587    P12 = PARL_TX_DATA12,
588    P13 = PARL_TX_DATA13,
589    P14 = PARL_TX_DATA14,
590    P15 = PARL_TX_DATA15
591);
592
593impl FullDuplex for TxOneBit<'_> {}
594impl FullDuplex for TxTwoBits<'_> {}
595impl FullDuplex for TxFourBits<'_> {}
596impl FullDuplex for TxEightBits<'_> {}
597impl FullDuplex for TxPinConfigWithValidPin<'_, TxFourBits<'_>> {}
598
599impl NotContainsValidSignalPin for TxOneBit<'_> {}
600impl NotContainsValidSignalPin for TxTwoBits<'_> {}
601impl NotContainsValidSignalPin for TxFourBits<'_> {}
602
603#[cfg(esp32c6)]
604impl NotContainsValidSignalPin for TxEightBits<'_> {}
605
606#[cfg(esp32h2)]
607impl ContainsValidSignalPin for TxEightBits<'_> {}
608
609#[cfg(esp32c6)]
610impl ContainsValidSignalPin for TxSixteenBits<'_> {}
611
612/// Pin configuration with an additional pin for the valid signal.
613pub struct RxPinConfigWithValidPin<'d, P>
614where
615    P: NotContainsValidSignalPin + RxPins + ConfigurePins,
616{
617    rx_pins: P,
618    valid_pin: PeripheralRef<'d, InputConnection>,
619    enable_mode: EnableMode,
620}
621
622impl<'d, P> RxPinConfigWithValidPin<'d, P>
623where
624    P: NotContainsValidSignalPin + RxPins + ConfigurePins,
625{
626    /// Create a new [RxPinConfigWithValidPin]
627    pub fn new(
628        rx_pins: P,
629        valid_pin: impl Peripheral<P = impl PeripheralInput> + 'd,
630        enable_mode: EnableMode,
631    ) -> Self {
632        crate::into_mapped_ref!(valid_pin);
633        Self {
634            rx_pins,
635            valid_pin,
636            enable_mode,
637        }
638    }
639}
640
641impl<P> RxPins for RxPinConfigWithValidPin<'_, P> where
642    P: NotContainsValidSignalPin + RxPins + ConfigurePins
643{
644}
645
646impl<P> ConfigurePins for RxPinConfigWithValidPin<'_, P>
647where
648    P: NotContainsValidSignalPin + RxPins + ConfigurePins,
649{
650    fn configure(&mut self) -> Result<(), Error> {
651        self.rx_pins.configure()?;
652        self.valid_pin.init_input(crate::gpio::Pull::None);
653        Instance::rx_valid_pin_signal().connect_to(&mut self.valid_pin);
654        Instance::set_rx_sw_en(false);
655        if let Some(sel) = self.enable_mode.pulse_submode_sel() {
656            Instance::set_rx_pulse_submode_sel(sel);
657        }
658        if let Some(sel) = self.enable_mode.level_submode_sel() {
659            Instance::set_rx_level_submode_sel(sel);
660        }
661        if let Some(sel) = self.enable_mode.smp_model_sel() {
662            Instance::set_rx_sample_mode(sel);
663        }
664
665        Ok(())
666    }
667}
668
669/// Pin configuration where the pin for the valid signal is the MSB pin.
670pub struct RxPinConfigIncludingValidPin<P>
671where
672    P: ContainsValidSignalPin + RxPins + ConfigurePins,
673{
674    rx_pins: P,
675    enable_mode: EnableMode,
676}
677
678impl<P> RxPinConfigIncludingValidPin<P>
679where
680    P: ContainsValidSignalPin + RxPins + ConfigurePins,
681{
682    /// Create a new [RxPinConfigIncludingValidPin]
683    pub fn new(rx_pins: P, enable_mode: EnableMode) -> Self {
684        Self {
685            rx_pins,
686            enable_mode,
687        }
688    }
689}
690
691impl<P> RxPins for RxPinConfigIncludingValidPin<P> where
692    P: ContainsValidSignalPin + RxPins + ConfigurePins
693{
694}
695
696impl<P> ConfigurePins for RxPinConfigIncludingValidPin<P>
697where
698    P: ContainsValidSignalPin + RxPins + ConfigurePins,
699{
700    fn configure(&mut self) -> Result<(), Error> {
701        self.rx_pins.configure()?;
702        Instance::set_rx_sw_en(false);
703        if let Some(sel) = self.enable_mode.pulse_submode_sel() {
704            Instance::set_rx_pulse_submode_sel(sel);
705        }
706        if let Some(sel) = self.enable_mode.level_submode_sel() {
707            Instance::set_rx_level_submode_sel(sel);
708        }
709        if let Some(sel) = self.enable_mode.smp_model_sel() {
710            Instance::set_rx_sample_mode(sel);
711        }
712
713        Ok(())
714    }
715}
716
717macro_rules! rx_pins {
718    ($name:ident, $width:literal, $($pin:ident = $signal:ident),+ ) => {
719        paste::paste! {
720            #[doc = "Data pin configuration for "]
721            #[doc = stringify!($width)]
722            #[doc = "bit input mode"]
723            pub struct $name<'d> {
724                $(
725                    [< pin_ $pin:lower >] : PeripheralRef<'d, InputConnection>,
726                )+
727            }
728
729            impl<'d> $name<'d>
730            {
731                /// Create a new RX pin
732                #[allow(clippy::too_many_arguments)]
733                pub fn new(
734                    $(
735                        [< pin_ $pin:lower >] : impl Peripheral<P = impl PeripheralInput > + 'd,
736                    )+
737                ) -> Self {
738                    crate::into_mapped_ref!($( [< pin_ $pin:lower >] ),+);
739                    Self { $( [< pin_ $pin:lower >] ),+ }
740                }
741            }
742
743            impl ConfigurePins for $name<'_>
744            {
745                fn configure(&mut self)  -> Result<(), Error> {
746                    $(
747                        self.[< pin_ $pin:lower >].init_input(crate::gpio::Pull::None);
748                        crate::gpio::InputSignal::$signal.connect_to(&mut self.[< pin_ $pin:lower >]);
749                    )+
750
751                    private::Instance::set_rx_bit_width( private::WidSel::[< Bits $width >]);
752                    Ok(())
753                }
754            }
755
756            impl RxPins for $name<'_> {}
757        }
758    };
759}
760
761rx_pins!(RxOneBit, 1, P0 = PARL_RX_DATA0);
762rx_pins!(RxTwoBits, 2, P0 = PARL_RX_DATA0, P1 = PARL_RX_DATA1);
763rx_pins!(
764    RxFourBits,
765    4,
766    P0 = PARL_RX_DATA0,
767    P1 = PARL_RX_DATA1,
768    P2 = PARL_RX_DATA2,
769    P3 = PARL_RX_DATA3
770);
771rx_pins!(
772    RxEightBits,
773    8,
774    P0 = PARL_RX_DATA0,
775    P1 = PARL_RX_DATA1,
776    P2 = PARL_RX_DATA2,
777    P3 = PARL_RX_DATA3,
778    P4 = PARL_RX_DATA4,
779    P5 = PARL_RX_DATA5,
780    P6 = PARL_RX_DATA6,
781    P7 = PARL_RX_DATA7
782);
783#[cfg(esp32c6)]
784rx_pins!(
785    RxSixteenBits,
786    16,
787    P0 = PARL_RX_DATA0,
788    P1 = PARL_RX_DATA1,
789    P2 = PARL_RX_DATA2,
790    P3 = PARL_RX_DATA3,
791    P4 = PARL_RX_DATA4,
792    P5 = PARL_RX_DATA5,
793    P6 = PARL_RX_DATA6,
794    P7 = PARL_RX_DATA7,
795    P8 = PARL_RX_DATA8,
796    P9 = PARL_RX_DATA9,
797    P10 = PARL_RX_DATA10,
798    P11 = PARL_RX_DATA11,
799    P12 = PARL_RX_DATA12,
800    P13 = PARL_RX_DATA13,
801    P14 = PARL_RX_DATA14,
802    P15 = PARL_RX_DATA15
803);
804
805impl FullDuplex for RxOneBit<'_> {}
806impl FullDuplex for RxTwoBits<'_> {}
807impl FullDuplex for RxFourBits<'_> {}
808impl FullDuplex for RxEightBits<'_> {}
809impl FullDuplex for RxPinConfigWithValidPin<'_, RxFourBits<'_>> {}
810
811impl NotContainsValidSignalPin for RxOneBit<'_> {}
812impl NotContainsValidSignalPin for RxTwoBits<'_> {}
813impl NotContainsValidSignalPin for RxFourBits<'_> {}
814
815#[cfg(esp32c6)]
816impl NotContainsValidSignalPin for RxEightBits<'_> {}
817
818#[cfg(esp32h2)]
819impl ContainsValidSignalPin for RxEightBits<'_> {}
820
821#[cfg(esp32c6)]
822impl ContainsValidSignalPin for RxSixteenBits<'_> {}
823
824impl<'d, Dm> TxCreatorFullDuplex<'d, Dm>
825where
826    Dm: DriverMode,
827{
828    /// Configure TX to use the given pins and settings
829    pub fn with_config<P, CP>(
830        self,
831        mut tx_pins: P,
832        mut clk_pin: CP,
833        idle_value: u16,
834        sample_edge: SampleEdge,
835        bit_order: BitPackOrder,
836    ) -> Result<ParlIoTx<'d, Dm>, Error>
837    where
838        P: FullDuplex + TxPins + ConfigurePins,
839        CP: TxClkPin,
840    {
841        tx_pins.configure()?;
842        clk_pin.configure();
843
844        Instance::set_tx_idle_value(idle_value);
845        Instance::set_tx_sample_edge(sample_edge);
846        Instance::set_tx_bit_order(bit_order);
847
848        Ok(ParlIoTx {
849            tx_channel: self.tx_channel,
850            _guard: self._guard,
851        })
852    }
853}
854
855impl<'d, Dm> TxCreator<'d, Dm>
856where
857    Dm: DriverMode,
858{
859    /// Configure TX to use the given pins and settings
860    pub fn with_config<P, CP>(
861        self,
862        tx_pins: &'d mut P,
863        clk_pin: &'d mut CP,
864        idle_value: u16,
865        sample_edge: SampleEdge,
866        bit_order: BitPackOrder,
867    ) -> Result<ParlIoTx<'d, Dm>, Error>
868    where
869        P: TxPins + ConfigurePins,
870        CP: TxClkPin,
871    {
872        tx_pins.configure()?;
873        clk_pin.configure();
874
875        Instance::set_tx_idle_value(idle_value);
876        Instance::set_tx_sample_edge(sample_edge);
877        Instance::set_tx_bit_order(bit_order);
878
879        Ok(ParlIoTx {
880            tx_channel: self.tx_channel,
881            _guard: self._guard,
882        })
883    }
884}
885
886/// Parallel IO TX channel
887#[instability::unstable]
888pub struct ParlIoTx<'d, Dm>
889where
890    Dm: DriverMode,
891{
892    tx_channel: ChannelTx<'d, Dm, PeripheralTxChannel<PARL_IO>>,
893    _guard: GenericPeripheralGuard<{ crate::system::Peripheral::ParlIo as u8 }>,
894}
895
896impl<Dm> core::fmt::Debug for ParlIoTx<'_, Dm>
897where
898    Dm: DriverMode,
899{
900    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
901        f.debug_struct("ParlIoTx").finish()
902    }
903}
904
905impl<'d, Dm> RxCreatorFullDuplex<'d, Dm>
906where
907    Dm: DriverMode,
908{
909    /// Configure RX to use the given pins and settings
910    pub fn with_config<P, CP>(
911        self,
912        rx_pins: &'d mut P,
913        clk_pin: &'d mut CP,
914        bit_order: BitPackOrder,
915        timeout_ticks: Option<u16>,
916    ) -> Result<ParlIoRx<'d, Dm>, Error>
917    where
918        P: FullDuplex + RxPins + ConfigurePins,
919        CP: RxClkPin,
920    {
921        let guard = GenericPeripheralGuard::new();
922
923        rx_pins.configure()?;
924        clk_pin.configure();
925
926        Instance::set_rx_bit_order(bit_order);
927        Instance::set_rx_timeout_ticks(timeout_ticks);
928
929        Ok(ParlIoRx {
930            rx_channel: self.rx_channel,
931            _guard: guard,
932        })
933    }
934}
935
936impl<'d, Dm> RxCreator<'d, Dm>
937where
938    Dm: DriverMode,
939{
940    /// Configure RX to use the given pins and settings
941    pub fn with_config<P, CP>(
942        self,
943        rx_pins: &'d mut P,
944        clk_pin: &'d mut CP,
945        bit_order: BitPackOrder,
946        timeout_ticks: Option<u16>,
947    ) -> Result<ParlIoRx<'d, Dm>, Error>
948    where
949        P: RxPins + ConfigurePins,
950        CP: RxClkPin,
951    {
952        rx_pins.configure()?;
953        clk_pin.configure();
954
955        Instance::set_rx_bit_order(bit_order);
956        Instance::set_rx_timeout_ticks(timeout_ticks);
957
958        Ok(ParlIoRx {
959            rx_channel: self.rx_channel,
960            _guard: self._guard,
961        })
962    }
963}
964
965/// Parallel IO RX channel
966#[instability::unstable]
967pub struct ParlIoRx<'d, Dm>
968where
969    Dm: DriverMode,
970{
971    rx_channel: ChannelRx<'d, Dm, PeripheralRxChannel<PARL_IO>>,
972    _guard: GenericPeripheralGuard<{ crate::system::Peripheral::ParlIo as u8 }>,
973}
974
975impl<Dm> core::fmt::Debug for ParlIoRx<'_, Dm>
976where
977    Dm: DriverMode,
978{
979    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
980        f.debug_struct("ParlIoTx").finish()
981    }
982}
983
984fn internal_set_interrupt_handler(handler: InterruptHandler) {
985    let mut peri = unsafe { PARL_IO::steal() };
986    #[cfg(esp32c6)]
987    {
988        for core in crate::system::Cpu::other() {
989            crate::interrupt::disable(core, Interrupt::PARL_IO);
990        }
991        internal_listen(EnumSet::all(), false);
992        internal_clear_interrupts(EnumSet::all());
993        peri.bind_parl_io_interrupt(handler.handler());
994
995        unwrap!(crate::interrupt::enable(
996            Interrupt::PARL_IO,
997            handler.priority()
998        ));
999    }
1000    #[cfg(esp32h2)]
1001    {
1002        for core in crate::system::Cpu::other() {
1003            crate::interrupt::disable(core, Interrupt::PARL_IO_RX);
1004            crate::interrupt::disable(core, Interrupt::PARL_IO_TX);
1005        }
1006        internal_listen(EnumSet::all(), false);
1007        internal_clear_interrupts(EnumSet::all());
1008        peri.bind_parl_io_tx_interrupt(handler.handler());
1009        peri.bind_parl_io_rx_interrupt(handler.handler());
1010
1011        unwrap!(crate::interrupt::enable(
1012            Interrupt::PARL_IO_TX,
1013            handler.priority(),
1014        ));
1015        unwrap!(crate::interrupt::enable(
1016            Interrupt::PARL_IO_RX,
1017            handler.priority(),
1018        ));
1019    }
1020}
1021
1022fn internal_listen(interrupts: EnumSet<ParlIoInterrupt>, enable: bool) {
1023    PARL_IO::regs().int_ena().write(|w| {
1024        for interrupt in interrupts {
1025            match interrupt {
1026                ParlIoInterrupt::TxFifoReEmpty => w.tx_fifo_rempty().bit(enable),
1027                ParlIoInterrupt::RxFifoWOvf => w.rx_fifo_wovf().bit(enable),
1028                ParlIoInterrupt::TxEof => w.tx_eof().bit(enable),
1029            };
1030        }
1031        w
1032    });
1033}
1034
1035fn internal_interrupts() -> EnumSet<ParlIoInterrupt> {
1036    let mut res = EnumSet::new();
1037    let parl_io = PARL_IO::regs();
1038    let ints = parl_io.int_st().read();
1039    if ints.tx_fifo_rempty().bit() {
1040        res.insert(ParlIoInterrupt::TxFifoReEmpty);
1041    }
1042    if ints.rx_fifo_wovf().bit() {
1043        res.insert(ParlIoInterrupt::RxFifoWOvf);
1044    }
1045    if ints.tx_eof().bit() {
1046        res.insert(ParlIoInterrupt::TxEof);
1047    }
1048
1049    res
1050}
1051
1052fn internal_clear_interrupts(interrupts: EnumSet<ParlIoInterrupt>) {
1053    let parl_io = PARL_IO::regs();
1054    parl_io.int_clr().write(|w| {
1055        for interrupt in interrupts {
1056            match interrupt {
1057                ParlIoInterrupt::TxFifoReEmpty => w.tx_fifo_rempty().clear_bit_by_one(),
1058                ParlIoInterrupt::RxFifoWOvf => w.rx_fifo_wovf().clear_bit_by_one(),
1059                ParlIoInterrupt::TxEof => w.tx_eof().clear_bit_by_one(),
1060            };
1061        }
1062        w
1063    });
1064}
1065
1066/// Parallel IO in full duplex mode
1067///
1068/// Full duplex mode might limit the maximum possible bit width.
1069pub struct ParlIoFullDuplex<'d, Dm>
1070where
1071    Dm: DriverMode,
1072{
1073    /// The transmitter (TX) channel responsible for handling DMA transfers in
1074    /// the parallel I/O full-duplex operation.
1075    pub tx: TxCreatorFullDuplex<'d, Dm>,
1076    /// The receiver (RX) channel responsible for handling DMA transfers in the
1077    /// parallel I/O full-duplex operation.
1078    pub rx: RxCreatorFullDuplex<'d, Dm>,
1079}
1080
1081impl<'d> ParlIoFullDuplex<'d, Blocking> {
1082    /// Create a new instance of [ParlIoFullDuplex]
1083    pub fn new<CH>(
1084        _parl_io: impl Peripheral<P = PARL_IO> + 'd,
1085        dma_channel: impl Peripheral<P = CH> + 'd,
1086        frequency: Rate,
1087    ) -> Result<Self, Error>
1088    where
1089        CH: DmaChannelFor<PARL_IO>,
1090    {
1091        let tx_guard = GenericPeripheralGuard::new();
1092        let rx_guard = GenericPeripheralGuard::new();
1093        let dma_channel = Channel::new(dma_channel.map(|ch| ch.degrade()));
1094        internal_init(frequency)?;
1095
1096        Ok(Self {
1097            tx: TxCreatorFullDuplex {
1098                tx_channel: dma_channel.tx,
1099                _guard: tx_guard,
1100            },
1101            rx: RxCreatorFullDuplex {
1102                rx_channel: dma_channel.rx,
1103                _guard: rx_guard,
1104            },
1105        })
1106    }
1107
1108    /// Convert to an async version.
1109    pub fn into_async(self) -> ParlIoFullDuplex<'d, Async> {
1110        for core in crate::system::Cpu::other() {
1111            #[cfg(esp32c6)]
1112            {
1113                crate::interrupt::disable(core, Interrupt::PARL_IO);
1114            }
1115            #[cfg(esp32h2)]
1116            {
1117                crate::interrupt::disable(core, Interrupt::PARL_IO_RX);
1118                crate::interrupt::disable(core, Interrupt::PARL_IO_TX);
1119            }
1120        }
1121
1122        #[cfg(esp32c6)]
1123        {
1124            unsafe {
1125                crate::interrupt::bind_interrupt(Interrupt::PARL_IO, interrupt_handler.handler());
1126            }
1127            unwrap!(crate::interrupt::enable(
1128                Interrupt::PARL_IO,
1129                interrupt_handler.priority()
1130            ));
1131        }
1132        #[cfg(esp32h2)]
1133        {
1134            unsafe {
1135                crate::interrupt::bind_interrupt(
1136                    Interrupt::PARL_IO_TX,
1137                    interrupt_handler.handler(),
1138                );
1139            }
1140            unwrap!(crate::interrupt::enable(
1141                Interrupt::PARL_IO_TX,
1142                interrupt_handler.priority()
1143            ));
1144        }
1145
1146        ParlIoFullDuplex {
1147            tx: TxCreatorFullDuplex {
1148                tx_channel: self.tx.tx_channel.into_async(),
1149                _guard: self.tx._guard,
1150            },
1151            rx: RxCreatorFullDuplex {
1152                rx_channel: self.rx.rx_channel.into_async(),
1153                _guard: self.rx._guard,
1154            },
1155        }
1156    }
1157
1158    /// Sets the interrupt handler, enables it with
1159    /// [crate::interrupt::Priority::min()]
1160    ///
1161    /// Interrupts are not enabled at the peripheral level here.
1162    #[instability::unstable]
1163    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1164        internal_set_interrupt_handler(handler);
1165    }
1166
1167    /// Listen for the given interrupts
1168    pub fn listen(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1169        internal_listen(interrupts.into(), true);
1170    }
1171
1172    /// Unlisten the given interrupts
1173    pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1174        internal_listen(interrupts.into(), false);
1175    }
1176
1177    /// Gets asserted interrupts
1178    pub fn interrupts(&mut self) -> EnumSet<ParlIoInterrupt> {
1179        internal_interrupts()
1180    }
1181
1182    /// Resets asserted interrupts
1183    pub fn clear_interrupts(&mut self, interrupts: EnumSet<ParlIoInterrupt>) {
1184        internal_clear_interrupts(interrupts);
1185    }
1186}
1187
1188impl crate::private::Sealed for ParlIoFullDuplex<'_, Blocking> {}
1189
1190#[instability::unstable]
1191impl crate::interrupt::InterruptConfigurable for ParlIoFullDuplex<'_, Blocking> {
1192    fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
1193        ParlIoFullDuplex::set_interrupt_handler(self, handler);
1194    }
1195}
1196
1197impl<'d> ParlIoFullDuplex<'d, Async> {
1198    /// Convert to a blocking version.
1199    pub fn into_blocking(self) -> ParlIoFullDuplex<'d, Blocking> {
1200        ParlIoFullDuplex {
1201            tx: TxCreatorFullDuplex {
1202                tx_channel: self.tx.tx_channel.into_blocking(),
1203                _guard: self.tx._guard,
1204            },
1205            rx: RxCreatorFullDuplex {
1206                rx_channel: self.rx.rx_channel.into_blocking(),
1207                _guard: self.rx._guard,
1208            },
1209        }
1210    }
1211}
1212
1213/// Parallel IO in half duplex / TX only mode
1214pub struct ParlIoTxOnly<'d, Dm>
1215where
1216    Dm: DriverMode,
1217{
1218    /// The transmitter (TX) channel responsible for handling DMA transfers in
1219    /// the parallel I/O operation.
1220    pub tx: TxCreator<'d, Dm>,
1221}
1222
1223impl<'d> ParlIoTxOnly<'d, Blocking> {
1224    /// Creates a new [ParlIoTxOnly]
1225    pub fn new<CH>(
1226        _parl_io: impl Peripheral<P = PARL_IO> + 'd,
1227        dma_channel: impl Peripheral<P = CH> + 'd,
1228        frequency: Rate,
1229    ) -> Result<Self, Error>
1230    where
1231        CH: TxChannelFor<PARL_IO>,
1232    {
1233        let guard = GenericPeripheralGuard::new();
1234        let tx_channel = ChannelTx::new(dma_channel.map(|ch| ch.degrade()));
1235        internal_init(frequency)?;
1236
1237        Ok(Self {
1238            tx: TxCreator {
1239                tx_channel,
1240                _guard: guard,
1241            },
1242        })
1243    }
1244
1245    /// Converts to Async mode.
1246    pub fn into_async(self) -> ParlIoTxOnly<'d, Async> {
1247        for core in crate::system::Cpu::other() {
1248            #[cfg(esp32c6)]
1249            {
1250                crate::interrupt::disable(core, Interrupt::PARL_IO);
1251            }
1252            #[cfg(esp32h2)]
1253            {
1254                crate::interrupt::disable(core, Interrupt::PARL_IO_RX);
1255                crate::interrupt::disable(core, Interrupt::PARL_IO_TX);
1256            }
1257        }
1258        #[cfg(esp32c6)]
1259        {
1260            unsafe {
1261                crate::interrupt::bind_interrupt(Interrupt::PARL_IO, interrupt_handler.handler());
1262            }
1263            unwrap!(crate::interrupt::enable(
1264                Interrupt::PARL_IO,
1265                interrupt_handler.priority()
1266            ));
1267        }
1268        #[cfg(esp32h2)]
1269        {
1270            unsafe {
1271                crate::interrupt::bind_interrupt(
1272                    Interrupt::PARL_IO_TX,
1273                    interrupt_handler.handler(),
1274                );
1275            }
1276            unwrap!(crate::interrupt::enable(
1277                Interrupt::PARL_IO_TX,
1278                interrupt_handler.priority()
1279            ));
1280        }
1281
1282        ParlIoTxOnly {
1283            tx: TxCreator {
1284                tx_channel: self.tx.tx_channel.into_async(),
1285                _guard: self.tx._guard,
1286            },
1287        }
1288    }
1289
1290    /// Sets the interrupt handler, enables it with
1291    /// [crate::interrupt::Priority::min()]
1292    ///
1293    /// Interrupts are not enabled at the peripheral level here.
1294    #[instability::unstable]
1295    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1296        internal_set_interrupt_handler(handler);
1297    }
1298
1299    /// Listen for the given interrupts
1300    pub fn listen(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1301        internal_listen(interrupts.into(), true);
1302    }
1303
1304    /// Unlisten the given interrupts
1305    pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1306        internal_listen(interrupts.into(), false);
1307    }
1308
1309    /// Gets asserted interrupts
1310    pub fn interrupts(&mut self) -> EnumSet<ParlIoInterrupt> {
1311        internal_interrupts()
1312    }
1313
1314    /// Resets asserted interrupts
1315    pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1316        internal_clear_interrupts(interrupts.into());
1317    }
1318}
1319
1320impl<'d> ParlIoTxOnly<'d, Async> {
1321    /// Convert to a blocking version.
1322    pub fn into_blocking(self) -> ParlIoTxOnly<'d, Blocking> {
1323        ParlIoTxOnly {
1324            tx: TxCreator {
1325                tx_channel: self.tx.tx_channel.into_blocking(),
1326                _guard: self.tx._guard,
1327            },
1328        }
1329    }
1330}
1331
1332impl crate::private::Sealed for ParlIoTxOnly<'_, Blocking> {}
1333
1334#[instability::unstable]
1335impl crate::interrupt::InterruptConfigurable for ParlIoTxOnly<'_, Blocking> {
1336    fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
1337        ParlIoTxOnly::set_interrupt_handler(self, handler);
1338    }
1339}
1340
1341/// Parallel IO in half duplex / RX only mode
1342pub struct ParlIoRxOnly<'d, Dm>
1343where
1344    Dm: DriverMode,
1345{
1346    /// The receiver (RX) channel responsible for handling DMA transfers in the
1347    /// parallel I/O operation.
1348    pub rx: RxCreator<'d, Dm>,
1349}
1350
1351impl<'d> ParlIoRxOnly<'d, Blocking> {
1352    /// Create a new [ParlIoRxOnly] instance
1353    pub fn new<CH>(
1354        _parl_io: impl Peripheral<P = PARL_IO> + 'd,
1355        dma_channel: impl Peripheral<P = CH> + 'd,
1356        frequency: Rate,
1357    ) -> Result<Self, Error>
1358    where
1359        CH: RxChannelFor<PARL_IO>,
1360    {
1361        let guard = GenericPeripheralGuard::new();
1362        let rx_channel = ChannelRx::new(dma_channel.map(|ch| ch.degrade()));
1363        internal_init(frequency)?;
1364
1365        Ok(Self {
1366            rx: RxCreator {
1367                rx_channel,
1368                _guard: guard,
1369            },
1370        })
1371    }
1372
1373    /// Converts to Async mode.
1374    pub fn into_async(self) -> ParlIoRxOnly<'d, Async> {
1375        for core in crate::system::Cpu::other() {
1376            #[cfg(esp32c6)]
1377            {
1378                crate::interrupt::disable(core, Interrupt::PARL_IO);
1379            }
1380            #[cfg(esp32h2)]
1381            {
1382                crate::interrupt::disable(core, Interrupt::PARL_IO_RX);
1383                crate::interrupt::disable(core, Interrupt::PARL_IO_TX);
1384            }
1385        }
1386        #[cfg(esp32c6)]
1387        {
1388            unsafe {
1389                crate::interrupt::bind_interrupt(Interrupt::PARL_IO, interrupt_handler.handler());
1390            }
1391            unwrap!(crate::interrupt::enable(
1392                Interrupt::PARL_IO,
1393                interrupt_handler.priority()
1394            ));
1395        }
1396        #[cfg(esp32h2)]
1397        {
1398            unsafe {
1399                crate::interrupt::bind_interrupt(
1400                    Interrupt::PARL_IO_TX,
1401                    interrupt_handler.handler(),
1402                );
1403            }
1404            unwrap!(crate::interrupt::enable(
1405                Interrupt::PARL_IO_TX,
1406                interrupt_handler.priority()
1407            ));
1408        }
1409
1410        ParlIoRxOnly {
1411            rx: RxCreator {
1412                rx_channel: self.rx.rx_channel.into_async(),
1413                _guard: self.rx._guard,
1414            },
1415        }
1416    }
1417
1418    /// Sets the interrupt handler, enables it with
1419    /// [crate::interrupt::Priority::min()]
1420    ///
1421    /// Interrupts are not enabled at the peripheral level here.
1422    #[instability::unstable]
1423    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1424        internal_set_interrupt_handler(handler);
1425    }
1426
1427    /// Listen for the given interrupts
1428    pub fn listen(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1429        internal_listen(interrupts.into(), true);
1430    }
1431
1432    /// Unlisten the given interrupts
1433    pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1434        internal_listen(interrupts.into(), false);
1435    }
1436
1437    /// Gets asserted interrupts
1438    pub fn interrupts(&mut self) -> EnumSet<ParlIoInterrupt> {
1439        internal_interrupts()
1440    }
1441
1442    /// Resets asserted interrupts
1443    pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1444        internal_clear_interrupts(interrupts.into());
1445    }
1446}
1447
1448impl<'d> ParlIoRxOnly<'d, Async> {
1449    /// Convert to a blocking version.
1450    pub fn into_blocking(self) -> ParlIoRxOnly<'d, Blocking> {
1451        ParlIoRxOnly {
1452            rx: RxCreator {
1453                rx_channel: self.rx.rx_channel.into_blocking(),
1454                _guard: self.rx._guard,
1455            },
1456        }
1457    }
1458}
1459
1460impl crate::private::Sealed for ParlIoRxOnly<'_, Blocking> {}
1461
1462#[instability::unstable]
1463impl crate::interrupt::InterruptConfigurable for ParlIoRxOnly<'_, Blocking> {
1464    fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
1465        ParlIoRxOnly::set_interrupt_handler(self, handler);
1466    }
1467}
1468
1469fn internal_init(frequency: Rate) -> Result<(), Error> {
1470    if frequency.as_hz() > 40_000_000 {
1471        return Err(Error::UnreachableClockRate);
1472    }
1473
1474    let divider = crate::soc::constants::PARL_IO_SCLK / frequency.as_hz();
1475    if divider > 0xffff {
1476        return Err(Error::UnreachableClockRate);
1477    }
1478    let divider = divider as u16;
1479
1480    PCR::regs().parl_clk_tx_conf().modify(|_, w| unsafe {
1481        w.parl_clk_tx_en().set_bit();
1482        w.parl_clk_tx_sel().bits(1); // PLL
1483        w.parl_clk_tx_div_num().bits(divider)
1484    });
1485
1486    PCR::regs().parl_clk_rx_conf().modify(|_, w| unsafe {
1487        w.parl_clk_rx_en().set_bit();
1488        w.parl_clk_rx_sel().bits(1); // PLL
1489        w.parl_clk_rx_div_num().bits(divider)
1490    });
1491    Instance::set_rx_sw_en(true);
1492    Instance::set_rx_sample_mode(SampleMode::InternalSoftwareEnable);
1493
1494    Ok(())
1495}
1496
1497impl<'d, Dm> ParlIoTx<'d, Dm>
1498where
1499    Dm: DriverMode,
1500{
1501    /// Perform a DMA write.
1502    ///
1503    /// This will return a [ParlIoTxTransfer]
1504    ///
1505    /// The maximum amount of data to be sent is 32736 bytes.
1506    pub fn write<BUF>(
1507        mut self,
1508        number_of_bytes: usize,
1509        mut buffer: BUF,
1510    ) -> Result<ParlIoTxTransfer<'d, BUF, Dm>, (Error, Self, BUF)>
1511    where
1512        BUF: DmaTxBuffer,
1513    {
1514        if number_of_bytes > MAX_DMA_SIZE {
1515            return Err((Error::MaxDmaTransferSizeExceeded, self, buffer));
1516        }
1517
1518        PCR::regs()
1519            .parl_clk_tx_conf()
1520            .modify(|_, w| w.parl_tx_rst_en().set_bit());
1521
1522        Instance::clear_tx_interrupts();
1523        Instance::set_tx_bytes(number_of_bytes as u16);
1524
1525        let result = unsafe {
1526            self.tx_channel
1527                .prepare_transfer(DmaPeripheral::ParlIo, &mut buffer)
1528                .and_then(|_| self.tx_channel.start_transfer())
1529        };
1530        if let Err(err) = result {
1531            return Err((Error::DmaError(err), self, buffer));
1532        }
1533
1534        while !Instance::is_tx_ready() {}
1535
1536        Instance::set_tx_start(true);
1537
1538        PCR::regs()
1539            .parl_clk_tx_conf()
1540            .modify(|_, w| w.parl_tx_rst_en().clear_bit());
1541
1542        Ok(ParlIoTxTransfer {
1543            parl_io: ManuallyDrop::new(self),
1544            buf_view: ManuallyDrop::new(buffer.into_view()),
1545        })
1546    }
1547}
1548
1549/// Represents an ongoing (or potentially finished) transfer using the PARL_IO
1550/// TX.
1551pub struct ParlIoTxTransfer<'d, BUF: DmaTxBuffer, Dm: DriverMode> {
1552    parl_io: ManuallyDrop<ParlIoTx<'d, Dm>>,
1553    buf_view: ManuallyDrop<BUF::View>,
1554}
1555
1556impl<'d, BUF: DmaTxBuffer, Dm: DriverMode> ParlIoTxTransfer<'d, BUF, Dm> {
1557    /// Returns true when [Self::wait] will not block.
1558    pub fn is_done(&self) -> bool {
1559        Instance::is_tx_eof()
1560    }
1561
1562    /// Waits for the transfer to finish and returns the peripheral and buffer.
1563    pub fn wait(mut self) -> (Result<(), DmaError>, ParlIoTx<'d, Dm>, BUF) {
1564        while !self.is_done() {}
1565
1566        Instance::set_tx_start(false);
1567        Instance::clear_is_tx_done();
1568
1569        // Stop the DMA as it doesn't know that the parl io has stopped.
1570        self.parl_io.tx_channel.stop_transfer();
1571
1572        let (parl_io, view) = self.release();
1573
1574        let result = if parl_io.tx_channel.has_error() {
1575            Err(DmaError::DescriptorError)
1576        } else {
1577            Ok(())
1578        };
1579
1580        (result, parl_io, BUF::from_view(view))
1581    }
1582
1583    fn release(mut self) -> (ParlIoTx<'d, Dm>, BUF::View) {
1584        let (parl_io, view) = unsafe {
1585            (
1586                ManuallyDrop::take(&mut self.parl_io),
1587                ManuallyDrop::take(&mut self.buf_view),
1588            )
1589        };
1590        core::mem::forget(self);
1591        (parl_io, view)
1592    }
1593}
1594
1595impl<BUF: DmaTxBuffer, Dm: DriverMode> Deref for ParlIoTxTransfer<'_, BUF, Dm> {
1596    type Target = BUF::View;
1597
1598    fn deref(&self) -> &Self::Target {
1599        &self.buf_view
1600    }
1601}
1602
1603impl<BUF: DmaTxBuffer, Dm: DriverMode> DerefMut for ParlIoTxTransfer<'_, BUF, Dm> {
1604    fn deref_mut(&mut self) -> &mut Self::Target {
1605        &mut self.buf_view
1606    }
1607}
1608
1609impl<BUF: DmaTxBuffer, Dm: DriverMode> Drop for ParlIoTxTransfer<'_, BUF, Dm> {
1610    fn drop(&mut self) {
1611        // There's no documented way to cancel the PARL IO transfer, so we'll just stop
1612        // the DMA to stop the memory access.
1613        self.parl_io.tx_channel.stop_transfer();
1614
1615        // SAFETY: This is Drop, we know that self.parl_io and self.buf_view
1616        // won't be touched again.
1617        let view = unsafe {
1618            ManuallyDrop::drop(&mut self.parl_io);
1619            ManuallyDrop::take(&mut self.buf_view)
1620        };
1621        let _ = BUF::from_view(view);
1622    }
1623}
1624
1625impl<'d, Dm> ParlIoRx<'d, Dm>
1626where
1627    Dm: DriverMode,
1628{
1629    /// Perform a DMA read.
1630    ///
1631    /// This will return a [ParlIoRxTransfer]
1632    ///
1633    /// When the number of bytes is specified, the maximum amount of data is
1634    /// 32736 bytes and the transfer ends when the number of specified bytes
1635    /// is received.
1636    ///
1637    /// When the number of bytes is unspecified, there's no limit the amount of
1638    /// data transferred and the transfer ends when the enable signal
1639    /// signals the end or the DMA buffer runs out of space.
1640    pub fn read<BUF>(
1641        mut self,
1642        number_of_bytes: Option<usize>,
1643        mut buffer: BUF,
1644    ) -> Result<ParlIoRxTransfer<'d, BUF, Dm>, (Error, Self, BUF)>
1645    where
1646        BUF: DmaRxBuffer,
1647    {
1648        PCR::regs()
1649            .parl_clk_rx_conf()
1650            .modify(|_, w| w.parl_rx_rst_en().set_bit());
1651        PCR::regs()
1652            .parl_clk_rx_conf()
1653            .modify(|_, w| w.parl_rx_rst_en().clear_bit());
1654
1655        Instance::clear_rx_interrupts();
1656        if let Some(number_of_bytes) = number_of_bytes {
1657            if number_of_bytes > MAX_DMA_SIZE {
1658                return Err((Error::MaxDmaTransferSizeExceeded, self, buffer));
1659            }
1660            Instance::set_rx_bytes(number_of_bytes as u16);
1661            Instance::set_eof_gen_sel(EofMode::ByteLen);
1662        } else {
1663            Instance::set_eof_gen_sel(EofMode::EnableSignal);
1664        }
1665
1666        let result = unsafe {
1667            self.rx_channel
1668                .prepare_transfer(DmaPeripheral::ParlIo, &mut buffer)
1669                .and_then(|_| self.rx_channel.start_transfer())
1670        };
1671        if let Err(err) = result {
1672            return Err((Error::DmaError(err), self, buffer));
1673        }
1674
1675        Instance::set_rx_reg_update();
1676
1677        Instance::set_rx_start(true);
1678
1679        Ok(ParlIoRxTransfer {
1680            parl_io: ManuallyDrop::new(self),
1681            buf_view: ManuallyDrop::new(buffer.into_view()),
1682            dma_result: None,
1683        })
1684    }
1685}
1686
1687/// Represents an ongoing (or potentially finished) transfer using the PARL_IO
1688/// TX.
1689pub struct ParlIoRxTransfer<'d, BUF: DmaRxBuffer, Dm: DriverMode> {
1690    parl_io: ManuallyDrop<ParlIoRx<'d, Dm>>,
1691    buf_view: ManuallyDrop<BUF::View>,
1692    // Needed to use DmaRxFuture, which clear the bits we check in is_done()
1693    dma_result: Option<Result<(), DmaError>>,
1694}
1695
1696impl<'d, BUF: DmaRxBuffer, Dm: DriverMode> ParlIoRxTransfer<'d, BUF, Dm> {
1697    /// Returns true when [Self::wait] will not block.
1698    pub fn is_done(&self) -> bool {
1699        if self.dma_result.is_some() {
1700            return true;
1701        }
1702        let ch = &self.parl_io.rx_channel;
1703        ch.is_done() || ch.has_eof_error() || ch.has_dscr_empty_error()
1704    }
1705
1706    /// Waits for the transfer to finish and returns the peripheral and buffer.
1707    pub fn wait(mut self) -> (Result<(), DmaError>, ParlIoRx<'d, Dm>, BUF) {
1708        while !self.is_done() {}
1709
1710        Instance::set_rx_start(false);
1711
1712        // Stop the DMA as it doesn't know that the parl io has stopped.
1713        self.parl_io.rx_channel.stop_transfer();
1714
1715        let dma_result = self.dma_result.take();
1716        let (parl_io, view) = self.release();
1717
1718        let result = if parl_io.rx_channel.has_error() {
1719            Err(DmaError::DescriptorError)
1720        } else {
1721            dma_result.unwrap_or(Ok(()))
1722        };
1723
1724        (result, parl_io, BUF::from_view(view))
1725    }
1726
1727    fn release(mut self) -> (ParlIoRx<'d, Dm>, BUF::View) {
1728        let (parl_io, view) = unsafe {
1729            (
1730                ManuallyDrop::take(&mut self.parl_io),
1731                ManuallyDrop::take(&mut self.buf_view),
1732            )
1733        };
1734        core::mem::forget(self);
1735        (parl_io, view)
1736    }
1737}
1738
1739impl<BUF: DmaRxBuffer, Dm: DriverMode> Deref for ParlIoRxTransfer<'_, BUF, Dm> {
1740    type Target = BUF::View;
1741
1742    fn deref(&self) -> &Self::Target {
1743        &self.buf_view
1744    }
1745}
1746
1747impl<BUF: DmaRxBuffer, Dm: DriverMode> DerefMut for ParlIoRxTransfer<'_, BUF, Dm> {
1748    fn deref_mut(&mut self) -> &mut Self::Target {
1749        &mut self.buf_view
1750    }
1751}
1752
1753impl<BUF: DmaRxBuffer, Dm: DriverMode> Drop for ParlIoRxTransfer<'_, BUF, Dm> {
1754    fn drop(&mut self) {
1755        // There's no documented way to cancel the PARL IO transfer, so we'll just stop
1756        // the DMA to stop the memory access.
1757        self.parl_io.rx_channel.stop_transfer();
1758
1759        // SAFETY: This is Drop, we know that self.parl_io and self.buf_view
1760        // won't be touched again.
1761        let view = unsafe {
1762            ManuallyDrop::drop(&mut self.parl_io);
1763            ManuallyDrop::take(&mut self.buf_view)
1764        };
1765        let _ = BUF::from_view(view);
1766    }
1767}
1768
1769/// Creates a TX channel
1770pub struct TxCreator<'d, Dm>
1771where
1772    Dm: DriverMode,
1773{
1774    tx_channel: ChannelTx<'d, Dm, PeripheralTxChannel<PARL_IO>>,
1775    _guard: GenericPeripheralGuard<{ system::Peripheral::ParlIo as u8 }>,
1776}
1777
1778/// Creates a RX channel
1779pub struct RxCreator<'d, Dm>
1780where
1781    Dm: DriverMode,
1782{
1783    rx_channel: ChannelRx<'d, Dm, PeripheralRxChannel<PARL_IO>>,
1784    _guard: GenericPeripheralGuard<{ system::Peripheral::ParlIo as u8 }>,
1785}
1786
1787/// Creates a TX channel
1788pub struct TxCreatorFullDuplex<'d, Dm>
1789where
1790    Dm: DriverMode,
1791{
1792    tx_channel: ChannelTx<'d, Dm, PeripheralTxChannel<PARL_IO>>,
1793    _guard: GenericPeripheralGuard<{ system::Peripheral::ParlIo as u8 }>,
1794}
1795
1796/// Creates a RX channel
1797pub struct RxCreatorFullDuplex<'d, Dm>
1798where
1799    Dm: DriverMode,
1800{
1801    rx_channel: ChannelRx<'d, Dm, PeripheralRxChannel<PARL_IO>>,
1802    _guard: GenericPeripheralGuard<{ system::Peripheral::ParlIo as u8 }>,
1803}
1804
1805#[doc(hidden)]
1806pub mod asynch {
1807    use core::task::Poll;
1808
1809    use procmacros::handler;
1810
1811    use super::{private::Instance, ParlIoRxTransfer, ParlIoTxTransfer};
1812    use crate::{
1813        asynch::AtomicWaker,
1814        dma::{asynch::DmaRxFuture, DmaRxBuffer, DmaTxBuffer},
1815    };
1816
1817    static TX_WAKER: AtomicWaker = AtomicWaker::new();
1818
1819    #[must_use = "futures do nothing unless you `.await` or poll them"]
1820    struct TxDoneFuture {}
1821
1822    impl TxDoneFuture {
1823        pub fn new() -> Self {
1824            Self {}
1825        }
1826    }
1827
1828    impl core::future::Future for TxDoneFuture {
1829        type Output = ();
1830
1831        fn poll(
1832            self: core::pin::Pin<&mut Self>,
1833            cx: &mut core::task::Context<'_>,
1834        ) -> Poll<Self::Output> {
1835            if Instance::is_tx_done_set() {
1836                Poll::Ready(())
1837            } else {
1838                TX_WAKER.register(cx.waker());
1839                Instance::listen_tx_done();
1840                Poll::Pending
1841            }
1842        }
1843    }
1844
1845    impl Drop for TxDoneFuture {
1846        fn drop(&mut self) {
1847            Instance::unlisten_tx_done();
1848        }
1849    }
1850
1851    #[handler]
1852    pub(super) fn interrupt_handler() {
1853        if Instance::is_tx_done_set() {
1854            Instance::unlisten_tx_done();
1855            TX_WAKER.wake()
1856        }
1857    }
1858
1859    impl<BUF: DmaTxBuffer> ParlIoTxTransfer<'_, BUF, crate::Async> {
1860        /// Waits for [Self::is_done] to return true.
1861        pub async fn wait_for_done(&mut self) {
1862            let future = TxDoneFuture::new();
1863            future.await;
1864        }
1865    }
1866
1867    impl<BUF: DmaRxBuffer> ParlIoRxTransfer<'_, BUF, crate::Async> {
1868        /// Waits for [Self::is_done] to return true.
1869        pub async fn wait_for_done(&mut self) {
1870            if self.dma_result.is_some() {
1871                return;
1872            }
1873            let future = DmaRxFuture::new(&mut self.parl_io.rx_channel);
1874            self.dma_result = Some(future.await);
1875        }
1876    }
1877}
1878
1879mod private {
1880    use super::{BitPackOrder, Error, SampleEdge};
1881    use crate::peripherals::PARL_IO;
1882
1883    pub trait FullDuplex {}
1884
1885    pub trait NotContainsValidSignalPin {}
1886
1887    pub trait ContainsValidSignalPin {}
1888
1889    pub trait TxPins {}
1890
1891    pub trait RxPins {}
1892
1893    pub trait TxClkPin {
1894        fn configure(&mut self);
1895    }
1896
1897    pub trait RxClkPin {
1898        fn configure(&mut self);
1899    }
1900
1901    pub trait ConfigurePins {
1902        fn configure(&mut self) -> Result<(), Error>;
1903    }
1904
1905    #[cfg(esp32c6)]
1906    pub(super) enum WidSel {
1907        Bits16 = 0,
1908        Bits8  = 1,
1909        Bits4  = 2,
1910        Bits2  = 3,
1911        Bits1  = 4,
1912    }
1913
1914    #[cfg(esp32h2)]
1915    pub(super) enum WidSel {
1916        Bits8 = 3,
1917        Bits4 = 2,
1918        Bits2 = 1,
1919        Bits1 = 0,
1920    }
1921
1922    pub(super) enum SampleMode {
1923        ExternalLevel          = 0,
1924        ExternalPulse          = 1,
1925        InternalSoftwareEnable = 2,
1926    }
1927
1928    /// Generation of GDMA SUC EOF
1929    pub(super) enum EofMode {
1930        /// Generate GDMA SUC EOF by data byte length
1931        ByteLen,
1932        /// Generate GDMA SUC EOF by the external enable signal
1933        EnableSignal,
1934    }
1935
1936    pub(super) struct Instance;
1937
1938    #[cfg(esp32c6)]
1939    impl Instance {
1940        pub fn set_tx_bit_width(width: WidSel) {
1941            let reg_block = PARL_IO::regs();
1942
1943            reg_block
1944                .tx_cfg0()
1945                .modify(|_, w| unsafe { w.tx_bus_wid_sel().bits(width as u8) });
1946        }
1947
1948        pub fn set_tx_idle_value(value: u16) {
1949            let reg_block = PARL_IO::regs();
1950            reg_block
1951                .tx_cfg1()
1952                .modify(|_, w| unsafe { w.tx_idle_value().bits(value) });
1953        }
1954
1955        pub fn set_tx_sample_edge(value: SampleEdge) {
1956            let reg_block = PARL_IO::regs();
1957            reg_block
1958                .tx_cfg0()
1959                .modify(|_, w| w.tx_smp_edge_sel().bit(value as u8 == 1));
1960        }
1961
1962        pub fn set_tx_bit_order(value: BitPackOrder) {
1963            let reg_block = PARL_IO::regs();
1964            reg_block
1965                .tx_cfg0()
1966                .modify(|_, w| w.tx_bit_unpack_order().bit(value as u8 == 1));
1967        }
1968
1969        pub fn clear_tx_interrupts() {
1970            let reg_block = PARL_IO::regs();
1971
1972            reg_block.int_clr().write(|w| {
1973                w.tx_fifo_rempty()
1974                    .clear_bit_by_one()
1975                    .tx_eof()
1976                    .clear_bit_by_one()
1977            });
1978        }
1979
1980        pub fn set_tx_bytes(len: u16) {
1981            let reg_block = PARL_IO::regs();
1982
1983            reg_block
1984                .tx_cfg0()
1985                .modify(|_, w| unsafe { w.tx_bytelen().bits(len) });
1986        }
1987
1988        pub fn is_tx_ready() -> bool {
1989            let reg_block = PARL_IO::regs();
1990
1991            reg_block.st().read().tx_ready().bit_is_set()
1992        }
1993
1994        pub fn set_tx_start(value: bool) {
1995            let reg_block = PARL_IO::regs();
1996
1997            reg_block.tx_cfg0().modify(|_, w| w.tx_start().bit(value));
1998        }
1999
2000        pub fn is_tx_eof() -> bool {
2001            let reg_block = PARL_IO::regs();
2002
2003            reg_block.int_raw().read().tx_eof().bit_is_set()
2004        }
2005
2006        pub fn tx_valid_pin_signal() -> crate::gpio::OutputSignal {
2007            crate::gpio::OutputSignal::PARL_TX_DATA15
2008        }
2009
2010        pub fn set_tx_hw_valid_en(value: bool) {
2011            let reg_block = PARL_IO::regs();
2012
2013            reg_block
2014                .tx_cfg0()
2015                .modify(|_, w| w.tx_hw_valid_en().bit(value));
2016        }
2017
2018        pub fn set_rx_bit_width(width: WidSel) {
2019            let reg_block = PARL_IO::regs();
2020
2021            reg_block
2022                .rx_cfg0()
2023                .modify(|_, w| unsafe { w.rx_bus_wid_sel().bits(width as u8) });
2024        }
2025
2026        pub fn rx_valid_pin_signal() -> crate::gpio::InputSignal {
2027            crate::gpio::InputSignal::PARL_RX_DATA15
2028        }
2029
2030        pub fn set_rx_sw_en(value: bool) {
2031            let reg_block = PARL_IO::regs();
2032
2033            reg_block.rx_cfg0().modify(|_, w| w.rx_sw_en().bit(value));
2034        }
2035
2036        pub fn clear_rx_interrupts() {
2037            let reg_block = PARL_IO::regs();
2038
2039            reg_block
2040                .int_clr()
2041                .write(|w| w.rx_fifo_wovf().clear_bit_by_one());
2042        }
2043
2044        pub fn set_rx_bytes(len: u16) {
2045            let reg_block = PARL_IO::regs();
2046
2047            reg_block
2048                .rx_cfg0()
2049                .modify(|_, w| unsafe { w.rx_data_bytelen().bits(len) });
2050        }
2051
2052        pub fn set_rx_sample_mode(sample_mode: SampleMode) {
2053            let reg_block = PARL_IO::regs();
2054
2055            reg_block
2056                .rx_cfg0()
2057                .modify(|_, w| unsafe { w.rx_smp_mode_sel().bits(sample_mode as u8) });
2058        }
2059
2060        pub fn set_eof_gen_sel(mode: EofMode) {
2061            let reg_block = PARL_IO::regs();
2062
2063            reg_block.rx_cfg0().modify(|_, w| {
2064                w.rx_eof_gen_sel()
2065                    .bit(matches!(mode, EofMode::EnableSignal))
2066            });
2067        }
2068
2069        pub fn set_rx_pulse_submode_sel(sel: u8) {
2070            let reg_block = PARL_IO::regs();
2071
2072            reg_block
2073                .rx_cfg0()
2074                .modify(|_, w| unsafe { w.rx_pulse_submode_sel().bits(sel) });
2075        }
2076
2077        pub fn set_rx_level_submode_sel(sel: u8) {
2078            let reg_block = PARL_IO::regs();
2079
2080            reg_block
2081                .rx_cfg0()
2082                .modify(|_, w| w.rx_level_submode_sel().bit(sel == 1));
2083        }
2084
2085        pub fn set_rx_clk_edge_sel(edge: SampleEdge) {
2086            let reg_block = PARL_IO::regs();
2087
2088            reg_block
2089                .rx_cfg0()
2090                .modify(|_, w| w.rx_clk_edge_sel().bit(edge as u8 == 1));
2091        }
2092
2093        pub fn set_rx_start(value: bool) {
2094            let reg_block = PARL_IO::regs();
2095
2096            reg_block.rx_cfg0().modify(|_, w| w.rx_start().bit(value));
2097        }
2098
2099        pub fn set_rx_reg_update() {
2100            let reg_block = PARL_IO::regs();
2101
2102            reg_block
2103                .rx_cfg1()
2104                .modify(|_, w| w.rx_reg_update().bit(true));
2105        }
2106
2107        pub fn set_rx_bit_order(value: BitPackOrder) {
2108            let reg_block = PARL_IO::regs();
2109            reg_block
2110                .rx_cfg0()
2111                .modify(|_, w| w.rx_bit_pack_order().bit(value as u8 == 1));
2112        }
2113
2114        pub fn set_rx_timeout_ticks(value: Option<u16>) {
2115            let reg_block = PARL_IO::regs();
2116            reg_block.rx_cfg1().modify(|_, w| unsafe {
2117                w.rx_timeout_en()
2118                    .bit(value.is_some())
2119                    .rx_timeout_threshold()
2120                    .bits(value.unwrap_or(0xfff))
2121            });
2122        }
2123
2124        pub fn listen_tx_done() {
2125            let reg_block = PARL_IO::regs();
2126
2127            reg_block.int_ena().modify(|_, w| w.tx_eof().set_bit());
2128        }
2129
2130        pub fn unlisten_tx_done() {
2131            let reg_block = PARL_IO::regs();
2132
2133            reg_block.int_ena().modify(|_, w| w.tx_eof().clear_bit());
2134        }
2135
2136        pub fn is_tx_done_set() -> bool {
2137            let reg_block = PARL_IO::regs();
2138
2139            reg_block.int_raw().read().tx_eof().bit()
2140        }
2141
2142        pub fn clear_is_tx_done() {
2143            let reg_block = PARL_IO::regs();
2144
2145            reg_block.int_clr().write(|w| w.tx_eof().clear_bit_by_one());
2146        }
2147    }
2148
2149    #[cfg(esp32h2)]
2150    impl Instance {
2151        pub fn set_tx_bit_width(width: WidSel) {
2152            let reg_block = PARL_IO::regs();
2153
2154            reg_block
2155                .tx_data_cfg()
2156                .modify(|_, w| unsafe { w.tx_bus_wid_sel().bits(width as u8) });
2157        }
2158
2159        pub fn set_tx_idle_value(value: u16) {
2160            let reg_block = PARL_IO::regs();
2161            reg_block
2162                .tx_genrl_cfg()
2163                .modify(|_, w| unsafe { w.tx_idle_value().bits(value) });
2164        }
2165
2166        pub fn set_tx_sample_edge(value: SampleEdge) {
2167            let reg_block = PARL_IO::regs();
2168            reg_block.tx_clk_cfg().modify(|_, w| {
2169                w.tx_clk_i_inv()
2170                    .bit(value == SampleEdge::Invert)
2171                    .tx_clk_o_inv()
2172                    .bit(value == SampleEdge::Invert)
2173            });
2174        }
2175
2176        pub fn set_tx_bit_order(value: BitPackOrder) {
2177            let reg_block = PARL_IO::regs();
2178            reg_block
2179                .tx_data_cfg()
2180                .modify(|_, w| w.tx_data_order_inv().bit(value as u8 == 1));
2181        }
2182
2183        pub fn clear_tx_interrupts() {
2184            let reg_block = PARL_IO::regs();
2185
2186            reg_block.int_clr().write(|w| {
2187                w.tx_fifo_rempty()
2188                    .clear_bit_by_one()
2189                    .tx_eof()
2190                    .clear_bit_by_one()
2191            });
2192        }
2193
2194        pub fn set_tx_bytes(len: u16) {
2195            let reg_block = PARL_IO::regs();
2196
2197            reg_block
2198                .tx_data_cfg()
2199                .modify(|_, w| unsafe { w.tx_bitlen().bits((len as u32) * 8) });
2200        }
2201
2202        pub fn is_tx_ready() -> bool {
2203            let reg_block = PARL_IO::regs();
2204
2205            reg_block.st().read().tx_ready().bit_is_set()
2206        }
2207
2208        pub fn set_tx_start(value: bool) {
2209            let reg_block = PARL_IO::regs();
2210
2211            reg_block
2212                .tx_start_cfg()
2213                .modify(|_, w| w.tx_start().bit(value));
2214        }
2215
2216        pub fn is_tx_eof() -> bool {
2217            let reg_block = PARL_IO::regs();
2218
2219            reg_block.int_raw().read().tx_eof().bit_is_set()
2220        }
2221
2222        pub fn tx_valid_pin_signal() -> crate::gpio::OutputSignal {
2223            crate::gpio::OutputSignal::PARL_TX_DATA7
2224        }
2225
2226        pub fn set_tx_hw_valid_en(value: bool) {
2227            let reg_block = PARL_IO::regs();
2228
2229            reg_block
2230                .tx_genrl_cfg()
2231                .modify(|_, w| w.tx_valid_output_en().bit(value));
2232        }
2233
2234        pub fn set_rx_bit_width(width: WidSel) {
2235            let reg_block = PARL_IO::regs();
2236
2237            reg_block
2238                .rx_data_cfg()
2239                .modify(|_, w| unsafe { w.rx_bus_wid_sel().bits(width as u8) });
2240        }
2241
2242        pub fn rx_valid_pin_signal() -> crate::gpio::InputSignal {
2243            crate::gpio::InputSignal::PARL_RX_DATA7
2244        }
2245
2246        pub fn set_rx_sw_en(value: bool) {
2247            let reg_block = PARL_IO::regs();
2248
2249            reg_block
2250                .rx_mode_cfg()
2251                .modify(|_, w| w.rx_sw_en().bit(value));
2252        }
2253
2254        pub fn clear_rx_interrupts() {
2255            let reg_block = PARL_IO::regs();
2256
2257            reg_block
2258                .int_clr()
2259                .write(|w| w.rx_fifo_wovf().clear_bit_by_one());
2260        }
2261
2262        pub fn set_rx_bytes(len: u16) {
2263            let reg_block = PARL_IO::regs();
2264
2265            reg_block
2266                .rx_data_cfg()
2267                .modify(|_, w| unsafe { w.rx_bitlen().bits((len as u32) * 8) });
2268        }
2269
2270        pub fn set_rx_sample_mode(sample_mode: SampleMode) {
2271            let reg_block = PARL_IO::regs();
2272
2273            reg_block
2274                .rx_mode_cfg()
2275                .modify(|_, w| unsafe { w.rx_smp_mode_sel().bits(sample_mode as u8) });
2276        }
2277
2278        pub fn set_eof_gen_sel(mode: EofMode) {
2279            let reg_block = PARL_IO::regs();
2280
2281            reg_block.rx_genrl_cfg().modify(|_, w| {
2282                w.rx_eof_gen_sel()
2283                    .bit(matches!(mode, EofMode::EnableSignal))
2284            });
2285        }
2286
2287        pub fn set_rx_pulse_submode_sel(sel: u8) {
2288            let reg_block = PARL_IO::regs();
2289
2290            reg_block
2291                .rx_mode_cfg()
2292                .modify(|_, w| unsafe { w.rx_pulse_submode_sel().bits(sel) });
2293        }
2294
2295        pub fn set_rx_level_submode_sel(_sel: u8) {
2296            // unsupported, always high
2297        }
2298
2299        pub fn set_rx_clk_edge_sel(value: SampleEdge) {
2300            let reg_block = PARL_IO::regs();
2301
2302            reg_block.rx_clk_cfg().modify(|_, w| {
2303                w.rx_clk_i_inv()
2304                    .bit(value == SampleEdge::Invert)
2305                    .rx_clk_o_inv()
2306                    .bit(value == SampleEdge::Invert)
2307            });
2308        }
2309
2310        pub fn set_rx_start(value: bool) {
2311            let reg_block = PARL_IO::regs();
2312
2313            reg_block
2314                .rx_start_cfg()
2315                .modify(|_, w| w.rx_start().bit(value));
2316        }
2317
2318        pub fn set_rx_reg_update() {
2319            let reg_block = PARL_IO::regs();
2320
2321            reg_block
2322                .reg_update()
2323                .write(|w| w.rx_reg_update().bit(true));
2324        }
2325
2326        pub fn set_rx_bit_order(value: BitPackOrder) {
2327            let reg_block = PARL_IO::regs();
2328            reg_block
2329                .rx_data_cfg()
2330                .modify(|_, w| w.rx_data_order_inv().bit(value as u8 == 1));
2331        }
2332
2333        pub fn set_rx_timeout_ticks(value: Option<u16>) {
2334            let reg_block = PARL_IO::regs();
2335            reg_block.rx_genrl_cfg().modify(|_, w| unsafe {
2336                w.rx_timeout_en()
2337                    .bit(value.is_some())
2338                    .rx_timeout_thres()
2339                    .bits(value.unwrap_or(0xfff))
2340            });
2341        }
2342
2343        pub fn listen_tx_done() {
2344            let reg_block = PARL_IO::regs();
2345
2346            reg_block.int_ena().modify(|_, w| w.tx_eof().set_bit());
2347        }
2348
2349        pub fn unlisten_tx_done() {
2350            let reg_block = PARL_IO::regs();
2351
2352            reg_block.int_ena().modify(|_, w| w.tx_eof().clear_bit());
2353        }
2354
2355        pub fn is_tx_done_set() -> bool {
2356            let reg_block = PARL_IO::regs();
2357
2358            reg_block.int_raw().read().tx_eof().bit()
2359        }
2360
2361        pub fn clear_is_tx_done() {
2362            let reg_block = PARL_IO::regs();
2363
2364            reg_block.int_clr().write(|w| w.tx_eof().clear_bit_by_one());
2365        }
2366    }
2367}