1#![doc = crate::before_snippet!()]
18#![doc = crate::before_snippet!()]
72use 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#[derive(Debug, EnumSetType)]
168#[cfg_attr(feature = "defmt", derive(defmt::Format))]
169pub enum ParlIoInterrupt {
170 TxFifoReEmpty,
173 RxFifoWOvf,
176 TxEof,
178}
179
180#[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 DmaError(DmaError),
187 MaxDmaTransferSizeExceeded,
189 UnreachableClockRate,
191}
192
193impl From<DmaError> for Error {
194 fn from(value: DmaError) -> Self {
195 Error::DmaError(value)
196 }
197}
198
199#[derive(Debug, Clone, Copy, PartialEq)]
201#[cfg_attr(feature = "defmt", derive(defmt::Format))]
202pub enum SampleEdge {
203 Normal = 0,
205 Invert = 1,
207}
208
209#[derive(Debug, Clone, Copy, PartialEq)]
211#[cfg_attr(feature = "defmt", derive(defmt::Format))]
212pub enum BitPackOrder {
213 Msb = 0,
215 Lsb = 1,
217}
218
219#[cfg(esp32c6)]
220#[derive(Debug, Clone, Copy, PartialEq)]
222#[cfg_attr(feature = "defmt", derive(defmt::Format))]
223pub enum EnableMode {
224 HighLevel,
226 LowLevel,
228 PulseMode1,
231 PulseMode2,
234 PulseMode3,
237 PulseMode4,
240 PulseMode5,
242 PulseMode6,
244 PulseMode7,
247 PulseMode8,
250 PulseMode9,
253 PulseMode10,
256 PulseMode11,
258 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#[derive(Debug, Clone, Copy, PartialEq)]
302#[cfg_attr(feature = "defmt", derive(defmt::Format))]
303pub enum EnableMode {
304 HighLevel,
306 PulseMode1,
309 PulseMode2,
312 PulseMode3,
315 PulseMode4,
318 PulseMode5,
320 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
353impl 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
365pub struct ClkOutPin<'d> {
367 pin: PeripheralRef<'d, OutputConnection>,
368}
369impl<'d> ClkOutPin<'d> {
370 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
383pub struct ClkInPin<'d> {
385 pin: PeripheralRef<'d, InputConnection>,
386}
387impl<'d> ClkInPin<'d> {
388 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) }); self.pin.init_input(crate::gpio::Pull::None);
401 crate::gpio::InputSignal::PARL_TX_CLK.connect_to(&mut self.pin);
402 }
403}
404
405pub struct RxClkInPin<'d> {
407 pin: PeripheralRef<'d, InputConnection>,
408 sample_edge: SampleEdge,
409}
410impl<'d> RxClkInPin<'d> {
411 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) }); 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
433pub 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 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
471pub 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 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 #[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
612pub 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 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
669pub 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 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 #[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 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 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#[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 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 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#[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
1066pub struct ParlIoFullDuplex<'d, Dm>
1070where
1071 Dm: DriverMode,
1072{
1073 pub tx: TxCreatorFullDuplex<'d, Dm>,
1076 pub rx: RxCreatorFullDuplex<'d, Dm>,
1079}
1080
1081impl<'d> ParlIoFullDuplex<'d, Blocking> {
1082 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 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 #[instability::unstable]
1163 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1164 internal_set_interrupt_handler(handler);
1165 }
1166
1167 pub fn listen(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1169 internal_listen(interrupts.into(), true);
1170 }
1171
1172 pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1174 internal_listen(interrupts.into(), false);
1175 }
1176
1177 pub fn interrupts(&mut self) -> EnumSet<ParlIoInterrupt> {
1179 internal_interrupts()
1180 }
1181
1182 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 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
1213pub struct ParlIoTxOnly<'d, Dm>
1215where
1216 Dm: DriverMode,
1217{
1218 pub tx: TxCreator<'d, Dm>,
1221}
1222
1223impl<'d> ParlIoTxOnly<'d, Blocking> {
1224 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 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 #[instability::unstable]
1295 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1296 internal_set_interrupt_handler(handler);
1297 }
1298
1299 pub fn listen(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1301 internal_listen(interrupts.into(), true);
1302 }
1303
1304 pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1306 internal_listen(interrupts.into(), false);
1307 }
1308
1309 pub fn interrupts(&mut self) -> EnumSet<ParlIoInterrupt> {
1311 internal_interrupts()
1312 }
1313
1314 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 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
1341pub struct ParlIoRxOnly<'d, Dm>
1343where
1344 Dm: DriverMode,
1345{
1346 pub rx: RxCreator<'d, Dm>,
1349}
1350
1351impl<'d> ParlIoRxOnly<'d, Blocking> {
1352 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 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 #[instability::unstable]
1423 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1424 internal_set_interrupt_handler(handler);
1425 }
1426
1427 pub fn listen(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1429 internal_listen(interrupts.into(), true);
1430 }
1431
1432 pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<ParlIoInterrupt>>) {
1434 internal_listen(interrupts.into(), false);
1435 }
1436
1437 pub fn interrupts(&mut self) -> EnumSet<ParlIoInterrupt> {
1439 internal_interrupts()
1440 }
1441
1442 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 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); 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); 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 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
1549pub 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 pub fn is_done(&self) -> bool {
1559 Instance::is_tx_eof()
1560 }
1561
1562 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 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 self.parl_io.tx_channel.stop_transfer();
1614
1615 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 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
1687pub struct ParlIoRxTransfer<'d, BUF: DmaRxBuffer, Dm: DriverMode> {
1690 parl_io: ManuallyDrop<ParlIoRx<'d, Dm>>,
1691 buf_view: ManuallyDrop<BUF::View>,
1692 dma_result: Option<Result<(), DmaError>>,
1694}
1695
1696impl<'d, BUF: DmaRxBuffer, Dm: DriverMode> ParlIoRxTransfer<'d, BUF, Dm> {
1697 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 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 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 self.parl_io.rx_channel.stop_transfer();
1758
1759 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
1769pub 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
1778pub 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
1787pub 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
1796pub 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 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 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 pub(super) enum EofMode {
1930 ByteLen,
1932 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 }
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}