diff options
Diffstat (limited to 'embassy-nrf/src/i2s.rs')
| -rw-r--r-- | embassy-nrf/src/i2s.rs | 176 |
1 files changed, 98 insertions, 78 deletions
diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs index 53de8deee..1bfa18491 100644 --- a/embassy-nrf/src/i2s.rs +++ b/embassy-nrf/src/i2s.rs | |||
| @@ -381,7 +381,7 @@ pub struct InterruptHandler<T: Instance> { | |||
| 381 | 381 | ||
| 382 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { | 382 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { |
| 383 | unsafe fn on_interrupt() { | 383 | unsafe fn on_interrupt() { |
| 384 | let device = Device::<T>::new(); | 384 | let device = Device::new(T::regs()); |
| 385 | let s = T::state(); | 385 | let s = T::state(); |
| 386 | 386 | ||
| 387 | if device.is_tx_ptr_updated() { | 387 | if device.is_tx_ptr_updated() { |
| @@ -405,8 +405,9 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | /// I2S driver. | 407 | /// I2S driver. |
| 408 | pub struct I2S<'d, T: Instance> { | 408 | pub struct I2S<'d> { |
| 409 | i2s: Peri<'d, T>, | 409 | r: pac::i2s::I2s, |
| 410 | state: &'static State, | ||
| 410 | mck: Option<Peri<'d, AnyPin>>, | 411 | mck: Option<Peri<'d, AnyPin>>, |
| 411 | sck: Peri<'d, AnyPin>, | 412 | sck: Peri<'d, AnyPin>, |
| 412 | lrck: Peri<'d, AnyPin>, | 413 | lrck: Peri<'d, AnyPin>, |
| @@ -416,10 +417,10 @@ pub struct I2S<'d, T: Instance> { | |||
| 416 | config: Config, | 417 | config: Config, |
| 417 | } | 418 | } |
| 418 | 419 | ||
| 419 | impl<'d, T: Instance> I2S<'d, T> { | 420 | impl<'d> I2S<'d> { |
| 420 | /// Create a new I2S in master mode | 421 | /// Create a new I2S in master mode |
| 421 | pub fn new_master( | 422 | pub fn new_master<T: Instance>( |
| 422 | i2s: Peri<'d, T>, | 423 | _i2s: Peri<'d, T>, |
| 423 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 424 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 424 | mck: Peri<'d, impl GpioPin>, | 425 | mck: Peri<'d, impl GpioPin>, |
| 425 | sck: Peri<'d, impl GpioPin>, | 426 | sck: Peri<'d, impl GpioPin>, |
| @@ -427,8 +428,12 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 427 | master_clock: MasterClock, | 428 | master_clock: MasterClock, |
| 428 | config: Config, | 429 | config: Config, |
| 429 | ) -> Self { | 430 | ) -> Self { |
| 431 | T::Interrupt::unpend(); | ||
| 432 | unsafe { T::Interrupt::enable() }; | ||
| 433 | |||
| 430 | Self { | 434 | Self { |
| 431 | i2s, | 435 | r: T::regs(), |
| 436 | state: T::state(), | ||
| 432 | mck: Some(mck.into()), | 437 | mck: Some(mck.into()), |
| 433 | sck: sck.into(), | 438 | sck: sck.into(), |
| 434 | lrck: lrck.into(), | 439 | lrck: lrck.into(), |
| @@ -440,15 +445,19 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 440 | } | 445 | } |
| 441 | 446 | ||
| 442 | /// Create a new I2S in slave mode | 447 | /// Create a new I2S in slave mode |
| 443 | pub fn new_slave( | 448 | pub fn new_slave<T: Instance>( |
| 444 | i2s: Peri<'d, T>, | 449 | _i2s: Peri<'d, T>, |
| 445 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 450 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 446 | sck: Peri<'d, impl GpioPin>, | 451 | sck: Peri<'d, impl GpioPin>, |
| 447 | lrck: Peri<'d, impl GpioPin>, | 452 | lrck: Peri<'d, impl GpioPin>, |
| 448 | config: Config, | 453 | config: Config, |
| 449 | ) -> Self { | 454 | ) -> Self { |
| 455 | T::Interrupt::unpend(); | ||
| 456 | unsafe { T::Interrupt::enable() }; | ||
| 457 | |||
| 450 | Self { | 458 | Self { |
| 451 | i2s, | 459 | r: T::regs(), |
| 460 | state: T::state(), | ||
| 452 | mck: None, | 461 | mck: None, |
| 453 | sck: sck.into(), | 462 | sck: sck.into(), |
| 454 | lrck: lrck.into(), | 463 | lrck: lrck.into(), |
| @@ -464,10 +473,13 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 464 | mut self, | 473 | mut self, |
| 465 | sdout: Peri<'d, impl GpioPin>, | 474 | sdout: Peri<'d, impl GpioPin>, |
| 466 | buffers: MultiBuffering<S, NB, NS>, | 475 | buffers: MultiBuffering<S, NB, NS>, |
| 467 | ) -> OutputStream<'d, T, S, NB, NS> { | 476 | ) -> OutputStream<'d, S, NB, NS> { |
| 468 | self.sdout = Some(sdout.into()); | 477 | self.sdout = Some(sdout.into()); |
| 478 | let p = self.build(); | ||
| 469 | OutputStream { | 479 | OutputStream { |
| 470 | _p: self.build(), | 480 | r: p.0, |
| 481 | state: p.1, | ||
| 482 | _phantom: PhantomData, | ||
| 471 | buffers, | 483 | buffers, |
| 472 | } | 484 | } |
| 473 | } | 485 | } |
| @@ -477,11 +489,14 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 477 | mut self, | 489 | mut self, |
| 478 | sdin: Peri<'d, impl GpioPin>, | 490 | sdin: Peri<'d, impl GpioPin>, |
| 479 | buffers: MultiBuffering<S, NB, NS>, | 491 | buffers: MultiBuffering<S, NB, NS>, |
| 480 | ) -> InputStream<'d, T, S, NB, NS> { | 492 | ) -> InputStream<'d, S, NB, NS> { |
| 481 | self.sdin = Some(sdin.into()); | 493 | self.sdin = Some(sdin.into()); |
| 494 | let p = self.build(); | ||
| 482 | InputStream { | 495 | InputStream { |
| 483 | _p: self.build(), | 496 | r: p.0, |
| 497 | state: p.1, | ||
| 484 | buffers, | 498 | buffers, |
| 499 | _phantom: PhantomData, | ||
| 485 | } | 500 | } |
| 486 | } | 501 | } |
| 487 | 502 | ||
| @@ -492,30 +507,33 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 492 | sdout: Peri<'d, impl GpioPin>, | 507 | sdout: Peri<'d, impl GpioPin>, |
| 493 | buffers_out: MultiBuffering<S, NB, NS>, | 508 | buffers_out: MultiBuffering<S, NB, NS>, |
| 494 | buffers_in: MultiBuffering<S, NB, NS>, | 509 | buffers_in: MultiBuffering<S, NB, NS>, |
| 495 | ) -> FullDuplexStream<'d, T, S, NB, NS> { | 510 | ) -> FullDuplexStream<'d, S, NB, NS> { |
| 496 | self.sdout = Some(sdout.into()); | 511 | self.sdout = Some(sdout.into()); |
| 497 | self.sdin = Some(sdin.into()); | 512 | self.sdin = Some(sdin.into()); |
| 513 | let p = self.build(); | ||
| 498 | 514 | ||
| 499 | FullDuplexStream { | 515 | FullDuplexStream { |
| 500 | _p: self.build(), | 516 | r: p.0, |
| 517 | state: p.1, | ||
| 518 | _phantom: PhantomData, | ||
| 501 | buffers_out, | 519 | buffers_out, |
| 502 | buffers_in, | 520 | buffers_in, |
| 503 | } | 521 | } |
| 504 | } | 522 | } |
| 505 | 523 | ||
| 506 | fn build(self) -> Peri<'d, T> { | 524 | fn build(self) -> (pac::i2s::I2s, &'static State) { |
| 507 | self.apply_config(); | 525 | self.apply_config(); |
| 508 | self.select_pins(); | 526 | self.select_pins(); |
| 509 | self.setup_interrupt(); | 527 | self.setup_interrupt(); |
| 510 | 528 | ||
| 511 | let device = Device::<T>::new(); | 529 | let device = Device::new(self.r); |
| 512 | device.enable(); | 530 | device.enable(); |
| 513 | 531 | ||
| 514 | self.i2s | 532 | (self.r, self.state) |
| 515 | } | 533 | } |
| 516 | 534 | ||
| 517 | fn apply_config(&self) { | 535 | fn apply_config(&self) { |
| 518 | let c = T::regs().config(); | 536 | let c = self.r.config(); |
| 519 | match &self.master_clock { | 537 | match &self.master_clock { |
| 520 | Some(MasterClock { freq, ratio }) => { | 538 | Some(MasterClock { freq, ratio }) => { |
| 521 | c.mode().write(|w| w.set_mode(vals::Mode::MASTER)); | 539 | c.mode().write(|w| w.set_mode(vals::Mode::MASTER)); |
| @@ -535,7 +553,7 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 535 | } | 553 | } |
| 536 | 554 | ||
| 537 | fn select_pins(&self) { | 555 | fn select_pins(&self) { |
| 538 | let psel = T::regs().psel(); | 556 | let psel = self.r.psel(); |
| 539 | psel.mck().write_value(self.mck.psel_bits()); | 557 | psel.mck().write_value(self.mck.psel_bits()); |
| 540 | psel.sck().write_value(self.sck.psel_bits()); | 558 | psel.sck().write_value(self.sck.psel_bits()); |
| 541 | psel.lrck().write_value(self.lrck.psel_bits()); | 559 | psel.lrck().write_value(self.lrck.psel_bits()); |
| @@ -544,10 +562,9 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 544 | } | 562 | } |
| 545 | 563 | ||
| 546 | fn setup_interrupt(&self) { | 564 | fn setup_interrupt(&self) { |
| 547 | T::Interrupt::unpend(); | 565 | // Interrupt is already set up in constructor |
| 548 | unsafe { T::Interrupt::enable() }; | ||
| 549 | 566 | ||
| 550 | let device = Device::<T>::new(); | 567 | let device = Device::new(self.r); |
| 551 | device.disable_tx_ptr_interrupt(); | 568 | device.disable_tx_ptr_interrupt(); |
| 552 | device.disable_rx_ptr_interrupt(); | 569 | device.disable_rx_ptr_interrupt(); |
| 553 | device.disable_stopped_interrupt(); | 570 | device.disable_stopped_interrupt(); |
| @@ -561,16 +578,16 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 561 | device.enable_stopped_interrupt(); | 578 | device.enable_stopped_interrupt(); |
| 562 | } | 579 | } |
| 563 | 580 | ||
| 564 | async fn stop() { | 581 | async fn stop(r: pac::i2s::I2s, state: &State) { |
| 565 | compiler_fence(Ordering::SeqCst); | 582 | compiler_fence(Ordering::SeqCst); |
| 566 | 583 | ||
| 567 | let device = Device::<T>::new(); | 584 | let device = Device::new(r); |
| 568 | device.stop(); | 585 | device.stop(); |
| 569 | 586 | ||
| 570 | T::state().started.store(false, Ordering::Relaxed); | 587 | state.started.store(false, Ordering::Relaxed); |
| 571 | 588 | ||
| 572 | poll_fn(|cx| { | 589 | poll_fn(|cx| { |
| 573 | T::state().stop_waker.register(cx.waker()); | 590 | state.stop_waker.register(cx.waker()); |
| 574 | 591 | ||
| 575 | if device.is_stopped() { | 592 | if device.is_stopped() { |
| 576 | trace!("STOP: Ready"); | 593 | trace!("STOP: Ready"); |
| @@ -586,7 +603,7 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 586 | device.disable(); | 603 | device.disable(); |
| 587 | } | 604 | } |
| 588 | 605 | ||
| 589 | async fn send_from_ram<S>(buffer_ptr: *const [S]) -> Result<(), Error> | 606 | async fn send_from_ram<S>(r: pac::i2s::I2s, state: &State, buffer_ptr: *const [S]) -> Result<(), Error> |
| 590 | where | 607 | where |
| 591 | S: Sample, | 608 | S: Sample, |
| 592 | { | 609 | { |
| @@ -596,22 +613,22 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 596 | 613 | ||
| 597 | compiler_fence(Ordering::SeqCst); | 614 | compiler_fence(Ordering::SeqCst); |
| 598 | 615 | ||
| 599 | let device = Device::<T>::new(); | 616 | let device = Device::new(r); |
| 600 | 617 | ||
| 601 | device.update_tx(buffer_ptr)?; | 618 | device.update_tx(buffer_ptr)?; |
| 602 | 619 | ||
| 603 | Self::wait_tx_ptr_update().await; | 620 | Self::wait_tx_ptr_update(r, state).await; |
| 604 | 621 | ||
| 605 | compiler_fence(Ordering::SeqCst); | 622 | compiler_fence(Ordering::SeqCst); |
| 606 | 623 | ||
| 607 | Ok(()) | 624 | Ok(()) |
| 608 | } | 625 | } |
| 609 | 626 | ||
| 610 | async fn wait_tx_ptr_update() { | 627 | async fn wait_tx_ptr_update(r: pac::i2s::I2s, state: &State) { |
| 611 | let drop = OnDrop::new(move || { | 628 | let drop = OnDrop::new(move || { |
| 612 | trace!("TX DROP: Stopping"); | 629 | trace!("TX DROP: Stopping"); |
| 613 | 630 | ||
| 614 | let device = Device::<T>::new(); | 631 | let device = Device::new(r); |
| 615 | device.disable_tx_ptr_interrupt(); | 632 | device.disable_tx_ptr_interrupt(); |
| 616 | device.reset_tx_ptr_event(); | 633 | device.reset_tx_ptr_event(); |
| 617 | device.disable_tx(); | 634 | device.disable_tx(); |
| @@ -623,9 +640,9 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 623 | }); | 640 | }); |
| 624 | 641 | ||
| 625 | poll_fn(|cx| { | 642 | poll_fn(|cx| { |
| 626 | T::state().tx_waker.register(cx.waker()); | 643 | state.tx_waker.register(cx.waker()); |
| 627 | 644 | ||
| 628 | let device = Device::<T>::new(); | 645 | let device = Device::new(r); |
| 629 | if device.is_tx_ptr_updated() { | 646 | if device.is_tx_ptr_updated() { |
| 630 | trace!("TX POLL: Ready"); | 647 | trace!("TX POLL: Ready"); |
| 631 | device.reset_tx_ptr_event(); | 648 | device.reset_tx_ptr_event(); |
| @@ -641,7 +658,7 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 641 | drop.defuse(); | 658 | drop.defuse(); |
| 642 | } | 659 | } |
| 643 | 660 | ||
| 644 | async fn receive_from_ram<S>(buffer_ptr: *mut [S]) -> Result<(), Error> | 661 | async fn receive_from_ram<S>(r: pac::i2s::I2s, state: &State, buffer_ptr: *mut [S]) -> Result<(), Error> |
| 645 | where | 662 | where |
| 646 | S: Sample, | 663 | S: Sample, |
| 647 | { | 664 | { |
| @@ -652,22 +669,22 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 652 | 669 | ||
| 653 | compiler_fence(Ordering::SeqCst); | 670 | compiler_fence(Ordering::SeqCst); |
| 654 | 671 | ||
| 655 | let device = Device::<T>::new(); | 672 | let device = Device::new(r); |
| 656 | 673 | ||
| 657 | device.update_rx(buffer_ptr)?; | 674 | device.update_rx(buffer_ptr)?; |
| 658 | 675 | ||
| 659 | Self::wait_rx_ptr_update().await; | 676 | Self::wait_rx_ptr_update(r, state).await; |
| 660 | 677 | ||
| 661 | compiler_fence(Ordering::SeqCst); | 678 | compiler_fence(Ordering::SeqCst); |
| 662 | 679 | ||
| 663 | Ok(()) | 680 | Ok(()) |
| 664 | } | 681 | } |
| 665 | 682 | ||
| 666 | async fn wait_rx_ptr_update() { | 683 | async fn wait_rx_ptr_update(r: pac::i2s::I2s, state: &State) { |
| 667 | let drop = OnDrop::new(move || { | 684 | let drop = OnDrop::new(move || { |
| 668 | trace!("RX DROP: Stopping"); | 685 | trace!("RX DROP: Stopping"); |
| 669 | 686 | ||
| 670 | let device = Device::<T>::new(); | 687 | let device = Device::new(r); |
| 671 | device.disable_rx_ptr_interrupt(); | 688 | device.disable_rx_ptr_interrupt(); |
| 672 | device.reset_rx_ptr_event(); | 689 | device.reset_rx_ptr_event(); |
| 673 | device.disable_rx(); | 690 | device.disable_rx(); |
| @@ -679,9 +696,9 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 679 | }); | 696 | }); |
| 680 | 697 | ||
| 681 | poll_fn(|cx| { | 698 | poll_fn(|cx| { |
| 682 | T::state().rx_waker.register(cx.waker()); | 699 | state.rx_waker.register(cx.waker()); |
| 683 | 700 | ||
| 684 | let device = Device::<T>::new(); | 701 | let device = Device::new(r); |
| 685 | if device.is_rx_ptr_updated() { | 702 | if device.is_rx_ptr_updated() { |
| 686 | trace!("RX POLL: Ready"); | 703 | trace!("RX POLL: Ready"); |
| 687 | device.reset_rx_ptr_event(); | 704 | device.reset_rx_ptr_event(); |
| @@ -699,12 +716,14 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 699 | } | 716 | } |
| 700 | 717 | ||
| 701 | /// I2S output | 718 | /// I2S output |
| 702 | pub struct OutputStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> { | 719 | pub struct OutputStream<'d, S: Sample, const NB: usize, const NS: usize> { |
| 703 | _p: Peri<'d, T>, | 720 | r: pac::i2s::I2s, |
| 721 | state: &'static State, | ||
| 704 | buffers: MultiBuffering<S, NB, NS>, | 722 | buffers: MultiBuffering<S, NB, NS>, |
| 723 | _phantom: PhantomData<&'d ()>, | ||
| 705 | } | 724 | } |
| 706 | 725 | ||
| 707 | impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> OutputStream<'d, T, S, NB, NS> { | 726 | impl<'d, S: Sample, const NB: usize, const NS: usize> OutputStream<'d, S, NB, NS> { |
| 708 | /// Get a mutable reference to the current buffer. | 727 | /// Get a mutable reference to the current buffer. |
| 709 | pub fn buffer(&mut self) -> &mut [S] { | 728 | pub fn buffer(&mut self) -> &mut [S] { |
| 710 | self.buffers.get_mut() | 729 | self.buffers.get_mut() |
| @@ -715,10 +734,9 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> OutputStream< | |||
| 715 | where | 734 | where |
| 716 | S: Sample, | 735 | S: Sample, |
| 717 | { | 736 | { |
| 718 | let device = Device::<T>::new(); | 737 | let device = Device::new(self.r); |
| 719 | 738 | ||
| 720 | let s = T::state(); | 739 | if self.state.started.load(Ordering::Relaxed) { |
| 721 | if s.started.load(Ordering::Relaxed) { | ||
| 722 | self.stop().await; | 740 | self.stop().await; |
| 723 | } | 741 | } |
| 724 | 742 | ||
| @@ -727,11 +745,11 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> OutputStream< | |||
| 727 | 745 | ||
| 728 | device.update_tx(self.buffers.switch())?; | 746 | device.update_tx(self.buffers.switch())?; |
| 729 | 747 | ||
| 730 | s.started.store(true, Ordering::Relaxed); | 748 | self.state.started.store(true, Ordering::Relaxed); |
| 731 | 749 | ||
| 732 | device.start(); | 750 | device.start(); |
| 733 | 751 | ||
| 734 | I2S::<T>::wait_tx_ptr_update().await; | 752 | I2S::wait_tx_ptr_update(self.r, self.state).await; |
| 735 | 753 | ||
| 736 | Ok(()) | 754 | Ok(()) |
| 737 | } | 755 | } |
| @@ -739,7 +757,7 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> OutputStream< | |||
| 739 | /// Stops the I2S transfer and waits until it has stopped. | 757 | /// Stops the I2S transfer and waits until it has stopped. |
| 740 | #[inline(always)] | 758 | #[inline(always)] |
| 741 | pub async fn stop(&self) { | 759 | pub async fn stop(&self) { |
| 742 | I2S::<T>::stop().await | 760 | I2S::stop(self.r, self.state).await |
| 743 | } | 761 | } |
| 744 | 762 | ||
| 745 | /// Sends the current buffer for transmission in the DMA. | 763 | /// Sends the current buffer for transmission in the DMA. |
| @@ -748,17 +766,19 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> OutputStream< | |||
| 748 | where | 766 | where |
| 749 | S: Sample, | 767 | S: Sample, |
| 750 | { | 768 | { |
| 751 | I2S::<T>::send_from_ram(self.buffers.switch()).await | 769 | I2S::send_from_ram(self.r, self.state, self.buffers.switch()).await |
| 752 | } | 770 | } |
| 753 | } | 771 | } |
| 754 | 772 | ||
| 755 | /// I2S input | 773 | /// I2S input |
| 756 | pub struct InputStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> { | 774 | pub struct InputStream<'d, S: Sample, const NB: usize, const NS: usize> { |
| 757 | _p: Peri<'d, T>, | 775 | r: pac::i2s::I2s, |
| 776 | state: &'static State, | ||
| 758 | buffers: MultiBuffering<S, NB, NS>, | 777 | buffers: MultiBuffering<S, NB, NS>, |
| 778 | _phantom: PhantomData<&'d ()>, | ||
| 759 | } | 779 | } |
| 760 | 780 | ||
| 761 | impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> InputStream<'d, T, S, NB, NS> { | 781 | impl<'d, S: Sample, const NB: usize, const NS: usize> InputStream<'d, S, NB, NS> { |
| 762 | /// Get a mutable reference to the current buffer. | 782 | /// Get a mutable reference to the current buffer. |
| 763 | pub fn buffer(&mut self) -> &mut [S] { | 783 | pub fn buffer(&mut self) -> &mut [S] { |
| 764 | self.buffers.get_mut() | 784 | self.buffers.get_mut() |
| @@ -769,10 +789,9 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> InputStream<' | |||
| 769 | where | 789 | where |
| 770 | S: Sample, | 790 | S: Sample, |
| 771 | { | 791 | { |
| 772 | let device = Device::<T>::new(); | 792 | let device = Device::new(self.r); |
| 773 | 793 | ||
| 774 | let s = T::state(); | 794 | if self.state.started.load(Ordering::Relaxed) { |
| 775 | if s.started.load(Ordering::Relaxed) { | ||
| 776 | self.stop().await; | 795 | self.stop().await; |
| 777 | } | 796 | } |
| 778 | 797 | ||
| @@ -781,11 +800,11 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> InputStream<' | |||
| 781 | 800 | ||
| 782 | device.update_rx(self.buffers.switch())?; | 801 | device.update_rx(self.buffers.switch())?; |
| 783 | 802 | ||
| 784 | s.started.store(true, Ordering::Relaxed); | 803 | self.state.started.store(true, Ordering::Relaxed); |
| 785 | 804 | ||
| 786 | device.start(); | 805 | device.start(); |
| 787 | 806 | ||
| 788 | I2S::<T>::wait_rx_ptr_update().await; | 807 | I2S::wait_rx_ptr_update(self.r, self.state).await; |
| 789 | 808 | ||
| 790 | Ok(()) | 809 | Ok(()) |
| 791 | } | 810 | } |
| @@ -793,7 +812,7 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> InputStream<' | |||
| 793 | /// Stops the I2S transfer and waits until it has stopped. | 812 | /// Stops the I2S transfer and waits until it has stopped. |
| 794 | #[inline(always)] | 813 | #[inline(always)] |
| 795 | pub async fn stop(&self) { | 814 | pub async fn stop(&self) { |
| 796 | I2S::<T>::stop().await | 815 | I2S::stop(self.r, self.state).await |
| 797 | } | 816 | } |
| 798 | 817 | ||
| 799 | /// Sets the current buffer for reception from the DMA. | 818 | /// Sets the current buffer for reception from the DMA. |
| @@ -803,18 +822,20 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> InputStream<' | |||
| 803 | where | 822 | where |
| 804 | S: Sample, | 823 | S: Sample, |
| 805 | { | 824 | { |
| 806 | I2S::<T>::receive_from_ram(self.buffers.switch_mut()).await | 825 | I2S::receive_from_ram(self.r, self.state, self.buffers.switch_mut()).await |
| 807 | } | 826 | } |
| 808 | } | 827 | } |
| 809 | 828 | ||
| 810 | /// I2S full duplex stream (input & output) | 829 | /// I2S full duplex stream (input & output) |
| 811 | pub struct FullDuplexStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> { | 830 | pub struct FullDuplexStream<'d, S: Sample, const NB: usize, const NS: usize> { |
| 812 | _p: Peri<'d, T>, | 831 | r: pac::i2s::I2s, |
| 832 | state: &'static State, | ||
| 813 | buffers_out: MultiBuffering<S, NB, NS>, | 833 | buffers_out: MultiBuffering<S, NB, NS>, |
| 814 | buffers_in: MultiBuffering<S, NB, NS>, | 834 | buffers_in: MultiBuffering<S, NB, NS>, |
| 835 | _phantom: PhantomData<&'d ()>, | ||
| 815 | } | 836 | } |
| 816 | 837 | ||
| 817 | impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> FullDuplexStream<'d, T, S, NB, NS> { | 838 | impl<'d, S: Sample, const NB: usize, const NS: usize> FullDuplexStream<'d, S, NB, NS> { |
| 818 | /// Get the current output and input buffers. | 839 | /// Get the current output and input buffers. |
| 819 | pub fn buffers(&mut self) -> (&mut [S], &[S]) { | 840 | pub fn buffers(&mut self) -> (&mut [S], &[S]) { |
| 820 | (self.buffers_out.get_mut(), self.buffers_in.get()) | 841 | (self.buffers_out.get_mut(), self.buffers_in.get()) |
| @@ -825,10 +846,9 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> FullDuplexStr | |||
| 825 | where | 846 | where |
| 826 | S: Sample, | 847 | S: Sample, |
| 827 | { | 848 | { |
| 828 | let device = Device::<T>::new(); | 849 | let device = Device::new(self.r); |
| 829 | 850 | ||
| 830 | let s = T::state(); | 851 | if self.state.started.load(Ordering::Relaxed) { |
| 831 | if s.started.load(Ordering::Relaxed) { | ||
| 832 | self.stop().await; | 852 | self.stop().await; |
| 833 | } | 853 | } |
| 834 | 854 | ||
| @@ -839,12 +859,12 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> FullDuplexStr | |||
| 839 | device.update_tx(self.buffers_out.switch())?; | 859 | device.update_tx(self.buffers_out.switch())?; |
| 840 | device.update_rx(self.buffers_in.switch_mut())?; | 860 | device.update_rx(self.buffers_in.switch_mut())?; |
| 841 | 861 | ||
| 842 | s.started.store(true, Ordering::Relaxed); | 862 | self.state.started.store(true, Ordering::Relaxed); |
| 843 | 863 | ||
| 844 | device.start(); | 864 | device.start(); |
| 845 | 865 | ||
| 846 | I2S::<T>::wait_tx_ptr_update().await; | 866 | I2S::wait_tx_ptr_update(self.r, self.state).await; |
| 847 | I2S::<T>::wait_rx_ptr_update().await; | 867 | I2S::wait_rx_ptr_update(self.r, self.state).await; |
| 848 | 868 | ||
| 849 | Ok(()) | 869 | Ok(()) |
| 850 | } | 870 | } |
| @@ -852,7 +872,7 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> FullDuplexStr | |||
| 852 | /// Stops the I2S transfer and waits until it has stopped. | 872 | /// Stops the I2S transfer and waits until it has stopped. |
| 853 | #[inline(always)] | 873 | #[inline(always)] |
| 854 | pub async fn stop(&self) { | 874 | pub async fn stop(&self) { |
| 855 | I2S::<T>::stop().await | 875 | I2S::stop(self.r, self.state).await |
| 856 | } | 876 | } |
| 857 | 877 | ||
| 858 | /// Sets the current buffers for output and input for transmission/reception from the DMA. | 878 | /// Sets the current buffers for output and input for transmission/reception from the DMA. |
| @@ -861,18 +881,18 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> FullDuplexStr | |||
| 861 | where | 881 | where |
| 862 | S: Sample, | 882 | S: Sample, |
| 863 | { | 883 | { |
| 864 | I2S::<T>::send_from_ram(self.buffers_out.switch()).await?; | 884 | I2S::send_from_ram(self.r, self.state, self.buffers_out.switch()).await?; |
| 865 | I2S::<T>::receive_from_ram(self.buffers_in.switch_mut()).await?; | 885 | I2S::receive_from_ram(self.r, self.state, self.buffers_in.switch_mut()).await?; |
| 866 | Ok(()) | 886 | Ok(()) |
| 867 | } | 887 | } |
| 868 | } | 888 | } |
| 869 | 889 | ||
| 870 | /// Helper encapsulating common I2S device operations. | 890 | /// Helper encapsulating common I2S device operations. |
| 871 | struct Device<T>(pac::i2s::I2s, PhantomData<T>); | 891 | struct Device(pac::i2s::I2s); |
| 872 | 892 | ||
| 873 | impl<T: Instance> Device<T> { | 893 | impl Device { |
| 874 | fn new() -> Self { | 894 | fn new(r: pac::i2s::I2s) -> Self { |
| 875 | Self(T::regs(), PhantomData) | 895 | Self(r) |
| 876 | } | 896 | } |
| 877 | 897 | ||
| 878 | #[inline(always)] | 898 | #[inline(always)] |
