1#![cfg_attr(esp32, doc = "")]
18#![cfg_attr(
19 esp32,
20 doc = "I2S0 does not support true 8bit parallel output, so if you want to do 8bit"
21)]
22#![cfg_attr(
23 esp32,
24 doc = "you should use I2S1. If you have to use I2S0, it will only output the even"
25)]
26#![cfg_attr(esp32, doc = "bytes! so [A, B, C, D] will be output as [A, C]!!!!")]
27#![cfg_attr(esp32, doc = "")]
28#![doc = crate::before_snippet!()]
42use core::{
101 mem::ManuallyDrop,
102 ops::{Deref, DerefMut},
103};
104
105use crate::{
106 Async,
107 Blocking,
108 DriverMode,
109 dma::{
110 Channel,
111 ChannelTx,
112 DmaChannelFor,
113 DmaEligible,
114 DmaError,
115 DmaTxBuffer,
116 PeripheralTxChannel,
117 asynch::DmaTxFuture,
118 },
119 gpio::{
120 OutputConfig,
121 OutputSignal,
122 interconnect::{self, PeripheralOutput},
123 },
124 i2s::{AnyI2s, AnyI2sInner},
125 pac::i2s0::RegisterBlock,
126 peripherals::{I2S0, I2S1},
127 system::PeripheralGuard,
128 time::Rate,
129};
130
131#[doc(hidden)]
132pub trait TxPins<'d> {
133 fn bus_width(&self) -> u8;
134 fn configure(&mut self, instance: &(impl Instance + 'd));
135}
136
137pub struct TxSixteenBits<'d> {
140 pins: [interconnect::OutputSignal<'d>; 16],
141}
142
143impl<'d> TxSixteenBits<'d> {
144 #[allow(clippy::too_many_arguments)]
145 pub fn new(
147 pin_0: impl PeripheralOutput<'d>,
148 pin_1: impl PeripheralOutput<'d>,
149 pin_2: impl PeripheralOutput<'d>,
150 pin_3: impl PeripheralOutput<'d>,
151 pin_4: impl PeripheralOutput<'d>,
152 pin_5: impl PeripheralOutput<'d>,
153 pin_6: impl PeripheralOutput<'d>,
154 pin_7: impl PeripheralOutput<'d>,
155 pin_8: impl PeripheralOutput<'d>,
156 pin_9: impl PeripheralOutput<'d>,
157 pin_10: impl PeripheralOutput<'d>,
158 pin_11: impl PeripheralOutput<'d>,
159 pin_12: impl PeripheralOutput<'d>,
160 pin_13: impl PeripheralOutput<'d>,
161 pin_14: impl PeripheralOutput<'d>,
162 pin_15: impl PeripheralOutput<'d>,
163 ) -> Self {
164 Self {
165 pins: [
166 pin_0.into(),
167 pin_1.into(),
168 pin_2.into(),
169 pin_3.into(),
170 pin_4.into(),
171 pin_5.into(),
172 pin_6.into(),
173 pin_7.into(),
174 pin_8.into(),
175 pin_9.into(),
176 pin_10.into(),
177 pin_11.into(),
178 pin_12.into(),
179 pin_13.into(),
180 pin_14.into(),
181 pin_15.into(),
182 ],
183 }
184 }
185}
186
187impl<'d> TxPins<'d> for TxSixteenBits<'d> {
188 fn bus_width(&self) -> u8 {
189 self.pins.len() as u8
190 }
191
192 fn configure(&mut self, instance: &(impl Instance + 'd)) {
193 let bits = self.bus_width();
194 for (i, pin) in self.pins.iter_mut().enumerate() {
195 pin.apply_output_config(&OutputConfig::default());
196 pin.set_output_enable(true);
197 instance.data_out_signal(i, bits).connect_to(pin);
198 }
199 }
200}
201
202pub struct TxEightBits<'d> {
205 pins: [interconnect::OutputSignal<'d>; 8],
206}
207
208impl<'d> TxEightBits<'d> {
209 #[allow(clippy::too_many_arguments)]
210 pub fn new(
212 pin_0: impl PeripheralOutput<'d>,
213 pin_1: impl PeripheralOutput<'d>,
214 pin_2: impl PeripheralOutput<'d>,
215 pin_3: impl PeripheralOutput<'d>,
216 pin_4: impl PeripheralOutput<'d>,
217 pin_5: impl PeripheralOutput<'d>,
218 pin_6: impl PeripheralOutput<'d>,
219 pin_7: impl PeripheralOutput<'d>,
220 ) -> Self {
221 Self {
222 pins: [
223 pin_0.into(),
224 pin_1.into(),
225 pin_2.into(),
226 pin_3.into(),
227 pin_4.into(),
228 pin_5.into(),
229 pin_6.into(),
230 pin_7.into(),
231 ],
232 }
233 }
234}
235
236impl<'d> TxPins<'d> for TxEightBits<'d> {
237 fn bus_width(&self) -> u8 {
238 self.pins.len() as u8
239 }
240
241 fn configure(&mut self, instance: &(impl Instance + 'd)) {
242 let bits = self.bus_width();
243 for (i, pin) in self.pins.iter_mut().enumerate() {
244 pin.apply_output_config(&OutputConfig::default());
245 pin.set_output_enable(true);
246 instance.data_out_signal(i, bits).connect_to(pin);
247 }
248 }
249}
250
251pub struct I2sParallel<'d, Dm>
253where
254 Dm: DriverMode,
255{
256 instance: AnyI2s<'d>,
257 tx_channel: ChannelTx<Dm, PeripheralTxChannel<AnyI2s<'d>>>,
258 _guard: PeripheralGuard,
259}
260
261impl<'d> I2sParallel<'d, Blocking> {
262 pub fn new(
264 i2s: impl Instance + 'd,
265 channel: impl DmaChannelFor<AnyI2s<'d>>,
266 frequency: Rate,
267 mut pins: impl TxPins<'d>,
268 clock_pin: impl PeripheralOutput<'d>,
269 ) -> Self {
270 let channel = Channel::new(channel.degrade());
271 channel.runtime_ensure_compatible(&i2s);
272
273 let i2s = i2s.degrade();
274
275 let guard = PeripheralGuard::new(i2s.peripheral());
276
277 i2s.setup(frequency, pins.bus_width());
279 let clock_pin = clock_pin.into();
281
282 clock_pin.apply_output_config(&OutputConfig::default());
283 clock_pin.set_output_enable(true);
284
285 i2s.ws_signal().connect_to(&clock_pin);
286
287 pins.configure(&i2s);
288 Self {
289 instance: i2s,
290 tx_channel: channel.tx,
291 _guard: guard,
292 }
293 }
294
295 pub fn into_async(self) -> I2sParallel<'d, Async> {
297 I2sParallel {
298 instance: self.instance,
299 tx_channel: self.tx_channel.into_async(),
300 _guard: self._guard,
301 }
302 }
303}
304
305impl<'d> I2sParallel<'d, Async> {
306 pub fn into_blocking(self) -> I2sParallel<'d, Blocking> {
308 I2sParallel {
309 instance: self.instance,
310 tx_channel: self.tx_channel.into_blocking(),
311 _guard: self._guard,
312 }
313 }
314}
315
316impl<'d, Dm> I2sParallel<'d, Dm>
317where
318 Dm: DriverMode,
319{
320 pub fn send<BUF: DmaTxBuffer>(
322 mut self,
323 mut data: BUF,
324 ) -> Result<I2sParallelTransfer<'d, BUF, Dm>, (DmaError, Self, BUF)> {
325 self.instance.tx_reset();
326 self.instance.tx_fifo_reset();
327 let result = unsafe {
328 self.tx_channel
329 .prepare_transfer(self.instance.dma_peripheral(), &mut data)
330 }
331 .and_then(|_| self.tx_channel.start_transfer());
332 if let Err(err) = result {
333 return Err((err, self, data));
334 }
335 self.instance.tx_start();
336 Ok(I2sParallelTransfer {
337 i2s: ManuallyDrop::new(self),
338 buf_view: ManuallyDrop::new(data.into_view()),
339 })
340 }
341}
342
343pub struct I2sParallelTransfer<'d, BUF, Dm>
346where
347 BUF: DmaTxBuffer,
348 Dm: DriverMode,
349{
350 i2s: ManuallyDrop<I2sParallel<'d, Dm>>,
351 buf_view: ManuallyDrop<BUF::View>,
352}
353
354impl<'d, BUF, Dm> I2sParallelTransfer<'d, BUF, Dm>
355where
356 BUF: DmaTxBuffer,
357 Dm: DriverMode,
358{
359 pub fn is_done(&self) -> bool {
361 self.i2s.instance.is_tx_done()
362 }
363
364 pub fn wait(mut self) -> (I2sParallel<'d, Dm>, BUF) {
366 self.i2s.instance.tx_wait_done();
367 let i2s = unsafe { ManuallyDrop::take(&mut self.i2s) };
368 let view = unsafe { ManuallyDrop::take(&mut self.buf_view) };
369 core::mem::forget(self);
370 (i2s, BUF::from_view(view))
371 }
372
373 fn stop_peripherals(&mut self) {
374 self.i2s.instance.tx_stop();
375 self.i2s.tx_channel.stop_transfer();
376 }
377}
378
379impl<BUF> I2sParallelTransfer<'_, BUF, Async>
380where
381 BUF: DmaTxBuffer,
382{
383 pub async fn wait_for_done(&mut self) -> Result<(), DmaError> {
385 DmaTxFuture::new(&mut self.i2s.tx_channel).await
386 }
387}
388
389impl<BUF, Dm> Deref for I2sParallelTransfer<'_, BUF, Dm>
390where
391 BUF: DmaTxBuffer,
392 Dm: DriverMode,
393{
394 type Target = BUF::View;
395
396 fn deref(&self) -> &Self::Target {
397 &self.buf_view
398 }
399}
400
401impl<BUF, Dm> DerefMut for I2sParallelTransfer<'_, BUF, Dm>
402where
403 BUF: DmaTxBuffer,
404 Dm: DriverMode,
405{
406 fn deref_mut(&mut self) -> &mut Self::Target {
407 &mut self.buf_view
408 }
409}
410
411impl<BUF, Dm> Drop for I2sParallelTransfer<'_, BUF, Dm>
412where
413 BUF: DmaTxBuffer,
414 Dm: DriverMode,
415{
416 fn drop(&mut self) {
417 self.stop_peripherals();
418
419 let view = unsafe {
422 ManuallyDrop::drop(&mut self.i2s);
423 ManuallyDrop::take(&mut self.buf_view)
424 };
425 let _ = BUF::from_view(view);
426 }
427}
428
429#[doc(hidden)]
430#[derive(Debug)]
431pub struct I2sClockDividers {
432 pub mclk_divider: u32,
433 pub bclk_divider: u32,
434 pub denominator: u32,
435 pub numerator: u32,
436}
437
438fn calculate_clock(sample_rate: Rate, data_bits: u8) -> I2sClockDividers {
439 let sclk = crate::soc::constants::I2S_SCLK; let rate = sample_rate.as_hz();
448
449 let mclk = rate * 2;
450 let bclk_divider: u32 = if data_bits == 8 { 2 } else { 1 };
451 let mut mclk_divider = sclk / mclk;
452
453 let mut ma: u32;
454 let mut mb: u32;
455 let mut denominator: u32 = 0;
456 let mut numerator: u32 = 0;
457
458 let freq_diff = sclk.abs_diff(mclk * mclk_divider);
459
460 if freq_diff != 0 {
461 let decimal = freq_diff as u64 * 10000 / mclk as u64;
462 if decimal > 1250000 / 126 {
465 mclk_divider += 1;
466 } else {
467 let mut min: u32 = !0;
468
469 for a in 2..=crate::i2s::master::I2S_LL_MCLK_DIVIDER_MAX {
470 let b = (a as u64) * (freq_diff as u64 * 10000u64 / mclk as u64) + 5000;
471 ma = ((freq_diff as u64 * 10000u64 * a as u64) / 10000) as u32;
472 mb = (mclk as u64 * (b / 10000)) as u32;
473
474 if ma == mb {
475 denominator = a as u32;
476 numerator = (b / 10000) as u32;
477 break;
478 }
479
480 if mb.abs_diff(ma) < min {
481 denominator = a as u32;
482 numerator = b as u32;
483 min = mb.abs_diff(ma);
484 }
485 }
486 }
487 }
488
489 I2sClockDividers {
490 mclk_divider,
491 bclk_divider,
492 denominator,
493 numerator,
494 }
495}
496#[doc(hidden)]
497#[allow(private_bounds)]
498pub trait PrivateInstance: DmaEligible {
499 fn regs(&self) -> &RegisterBlock;
500 fn peripheral(&self) -> crate::system::Peripheral;
501 fn ws_signal(&self) -> OutputSignal;
502 fn data_out_signal(&self, i: usize, bits: u8) -> OutputSignal;
503
504 fn rx_reset(&self) {
505 self.regs().conf().modify(|_, w| w.rx_reset().set_bit());
506 self.regs().conf().modify(|_, w| w.rx_reset().clear_bit());
507 }
508
509 fn rx_dma_reset(&self) {
510 self.regs().lc_conf().modify(|_, w| w.in_rst().set_bit());
511 self.regs().lc_conf().modify(|_, w| w.in_rst().clear_bit());
512 }
513
514 fn rx_fifo_reset(&self) {
515 self.regs()
516 .conf()
517 .modify(|_, w| w.rx_fifo_reset().set_bit());
518 self.regs()
519 .conf()
520 .modify(|_, w| w.rx_fifo_reset().clear_bit());
521 }
522
523 fn tx_reset(&self) {
524 self.regs().conf().modify(|_, w| w.tx_reset().set_bit());
525 xtensa_lx::timer::delay(100);
529 self.regs().conf().modify(|_, w| w.tx_reset().clear_bit());
530 }
531
532 fn tx_dma_reset(&self) {
533 self.regs().lc_conf().modify(|_, w| w.out_rst().set_bit());
534 self.regs().lc_conf().modify(|_, w| w.out_rst().clear_bit());
535 }
536
537 fn tx_fifo_reset(&self) {
538 self.regs()
539 .conf()
540 .modify(|_, w| w.tx_fifo_reset().set_bit());
541 self.regs()
542 .conf()
543 .modify(|_, w| w.tx_fifo_reset().clear_bit());
544 }
545
546 fn tx_clear_interrupts(&self) {
547 self.regs().int_clr().write(|w| {
548 w.out_done().clear_bit_by_one();
549 w.out_total_eof().clear_bit_by_one()
550 });
551 }
552
553 fn tx_start(&self) {
554 while self.regs().int_raw().read().tx_rempty().bit_is_clear() {
556 }
558
559 xtensa_lx::timer::delay(1);
561
562 self.regs().conf().modify(|_, w| w.tx_start().set_bit());
563
564 while self.regs().state().read().tx_idle().bit_is_set() {
565 }
567 }
568
569 fn tx_stop(&self) {
570 self.regs().conf().modify(|_, w| w.tx_start().clear_bit());
571 }
572
573 fn is_tx_done(&self) -> bool {
574 self.regs().state().read().tx_idle().bit_is_set()
575 }
576
577 fn tx_wait_done(&self) {
578 while self.regs().state().read().tx_idle().bit_is_clear() {
579 }
581
582 self.regs().conf().modify(|_, w| w.tx_start().clear_bit());
583 self.regs().int_clr().write(|w| {
584 w.out_done().clear_bit_by_one();
585 w.out_total_eof().clear_bit_by_one()
586 });
587 }
588
589 fn set_clock(&self, clock_settings: I2sClockDividers) {
590 self.regs().clkm_conf().modify(|r, w| unsafe {
591 w.bits(r.bits() | (crate::soc::constants::I2S_DEFAULT_CLK_SRC << 21))
592 });
594
595 #[cfg(esp32)]
596 self.regs()
597 .clkm_conf()
598 .modify(|_, w| w.clka_ena().clear_bit());
599
600 self.regs().clkm_conf().modify(|_, w| unsafe {
601 w.clk_en().set_bit();
602 w.clkm_div_num().bits(clock_settings.mclk_divider as u8)
603 });
604
605 self.regs().clkm_conf().modify(|_, w| unsafe {
606 w.clkm_div_a().bits(clock_settings.denominator as u8);
607 w.clkm_div_b().bits(clock_settings.numerator as u8)
608 });
609
610 self.regs().sample_rate_conf().modify(|_, w| unsafe {
611 w.tx_bck_div_num().bits(clock_settings.bclk_divider as u8);
612 w.rx_bck_div_num().bits(clock_settings.bclk_divider as u8)
613 });
614 }
615
616 fn setup(&self, frequency: Rate, bits: u8) {
617 self.set_clock(calculate_clock(frequency, bits));
618
619 self.rx_reset();
621 self.tx_reset();
622 self.rx_fifo_reset();
623 self.tx_fifo_reset();
624 self.rx_dma_reset();
625 self.tx_dma_reset();
626
627 self.regs().conf2().write(|w| {
629 w.lcd_tx_wrx2_en().bit(bits == 8);
631 w.lcd_en().set_bit()
632 });
633
634 self.regs().sample_rate_conf().modify(|_, w| unsafe {
635 w.rx_bits_mod().bits(bits);
636 w.tx_bits_mod().bits(bits)
637 });
638
639 self.regs().fifo_conf().write(|w| unsafe {
640 w.rx_fifo_mod_force_en().set_bit();
641 w.tx_fifo_mod_force_en().set_bit();
642 w.rx_fifo_mod().bits(1);
643 w.tx_fifo_mod().bits(1);
644 w.rx_data_num().bits(32);
645 w.tx_data_num().bits(32);
646 w.dscr_en().set_bit()
647 });
648
649 self.regs().conf1().write(|w| {
650 w.tx_stop_en().set_bit();
651 w.rx_pcm_bypass().set_bit();
652 w.tx_pcm_bypass().set_bit()
653 });
654
655 self.regs().conf_chan().write(|w| unsafe {
656 w.rx_chan_mod().bits(1);
657 w.tx_chan_mod().bits(1)
658 });
659
660 self.regs().conf().modify(|_, w| {
661 w.rx_mono().set_bit();
662 w.tx_mono().set_bit();
663 w.rx_right_first().set_bit();
664 w.tx_right_first().set_bit()
665 });
666 self.regs().timing().reset();
667
668 self.regs().pd_conf().modify(|_, w| {
669 w.fifo_force_pu().set_bit();
670 w.fifo_force_pd().clear_bit()
671 });
672 }
673}
674
675impl PrivateInstance for I2S0<'_> {
676 fn regs(&self) -> &RegisterBlock {
677 unsafe { &*I2S0::PTR.cast::<RegisterBlock>() }
678 }
679
680 fn peripheral(&self) -> crate::system::Peripheral {
681 crate::system::Peripheral::I2s0
682 }
683
684 fn ws_signal(&self) -> OutputSignal {
685 OutputSignal::I2S0O_WS
686 }
687 fn data_out_signal(&self, i: usize, bits: u8) -> OutputSignal {
688 assert!(
689 bits == 8 || bits == 16,
690 "Number of bits must be 8 or 16, got {}",
691 bits
692 );
693
694 match i + 8 {
697 0 => OutputSignal::I2S0O_DATA_0,
698 1 => OutputSignal::I2S0O_DATA_1,
699 2 => OutputSignal::I2S0O_DATA_2,
700 3 => OutputSignal::I2S0O_DATA_3,
701 4 => OutputSignal::I2S0O_DATA_4,
702 5 => OutputSignal::I2S0O_DATA_5,
703 6 => OutputSignal::I2S0O_DATA_6,
704 7 => OutputSignal::I2S0O_DATA_7,
705 8 => OutputSignal::I2S0O_DATA_8,
706 9 => OutputSignal::I2S0O_DATA_9,
707 10 => OutputSignal::I2S0O_DATA_10,
708 11 => OutputSignal::I2S0O_DATA_11,
709 12 => OutputSignal::I2S0O_DATA_12,
710 13 => OutputSignal::I2S0O_DATA_13,
711 14 => OutputSignal::I2S0O_DATA_14,
712 15 => OutputSignal::I2S0O_DATA_15,
713 16 => OutputSignal::I2S0O_DATA_16,
714 17 => OutputSignal::I2S0O_DATA_17,
715 18 => OutputSignal::I2S0O_DATA_18,
716 19 => OutputSignal::I2S0O_DATA_19,
717 20 => OutputSignal::I2S0O_DATA_20,
718 21 => OutputSignal::I2S0O_DATA_21,
719 22 => OutputSignal::I2S0O_DATA_22,
720 23 => OutputSignal::I2S0O_DATA_23,
721 other => panic!("Invalid I2S0 Dout pin {}", other),
722 }
723 }
724}
725
726impl PrivateInstance for I2S1<'_> {
727 fn regs(&self) -> &RegisterBlock {
728 unsafe { &*I2S1::PTR.cast::<RegisterBlock>() }
729 }
730
731 fn peripheral(&self) -> crate::system::Peripheral {
732 crate::system::Peripheral::I2s1
733 }
734
735 fn ws_signal(&self) -> OutputSignal {
736 OutputSignal::I2S1O_WS
737 }
738 fn data_out_signal(&self, i: usize, bits: u8) -> OutputSignal {
739 assert!(
740 bits == 8 || bits == 16,
741 "Number of bits must be 8 or 16, got {}",
742 bits
743 );
744
745 let pin_offset = if bits == 16 { 8 } else { 0 };
747
748 match i + pin_offset {
749 0 => OutputSignal::I2S1O_DATA_0,
750 1 => OutputSignal::I2S1O_DATA_1,
751 2 => OutputSignal::I2S1O_DATA_2,
752 3 => OutputSignal::I2S1O_DATA_3,
753 4 => OutputSignal::I2S1O_DATA_4,
754 5 => OutputSignal::I2S1O_DATA_5,
755 6 => OutputSignal::I2S1O_DATA_6,
756 7 => OutputSignal::I2S1O_DATA_7,
757 8 => OutputSignal::I2S1O_DATA_8,
758 9 => OutputSignal::I2S1O_DATA_9,
759 10 => OutputSignal::I2S1O_DATA_10,
760 11 => OutputSignal::I2S1O_DATA_11,
761 12 => OutputSignal::I2S1O_DATA_12,
762 13 => OutputSignal::I2S1O_DATA_13,
763 14 => OutputSignal::I2S1O_DATA_14,
764 15 => OutputSignal::I2S1O_DATA_15,
765 16 => OutputSignal::I2S1O_DATA_16,
766 17 => OutputSignal::I2S1O_DATA_17,
767 18 => OutputSignal::I2S1O_DATA_18,
768 19 => OutputSignal::I2S1O_DATA_19,
769 20 => OutputSignal::I2S1O_DATA_20,
770 21 => OutputSignal::I2S1O_DATA_21,
771 22 => OutputSignal::I2S1O_DATA_22,
772 23 => OutputSignal::I2S1O_DATA_23,
773 other => panic!("Invalid I2S1 Dout pin {}", other),
774 }
775 }
776}
777
778impl PrivateInstance for AnyI2s<'_> {
779 delegate::delegate! {
780 to match &self.0 {
781 AnyI2sInner::I2s0(i2s) => i2s,
782 AnyI2sInner::I2s1(i2s) => i2s,
783 } {
784 fn regs(&self) -> &RegisterBlock;
785 fn peripheral(&self) -> crate::system::Peripheral;
786 fn ws_signal(&self) -> OutputSignal;
787 fn data_out_signal(&self, i: usize, bits: u8) -> OutputSignal ;
788 }
789 }
790}
791
792pub trait Instance: PrivateInstance + super::IntoAnyI2s {}
794
795impl Instance for I2S0<'_> {}
796#[cfg(i2s1)]
797impl Instance for I2S1<'_> {}
798impl Instance for AnyI2s<'_> {}