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