diff options
| author | Eekle <[email protected]> | 2024-06-30 11:03:29 +0200 |
|---|---|---|
| committer | Eekle <[email protected]> | 2024-06-30 11:03:29 +0200 |
| commit | 1d1fc9afeac268a4b6d2cd9b9e5788226c79eca8 (patch) | |
| tree | 445969b15e14aa18a272783c16373832d03ff0e2 | |
| parent | 7eb605d1165eaf4cdf90453d1ed2d6976dd514af (diff) | |
Add async and blocking variants
| -rw-r--r-- | embassy-stm32/src/tsc/mod.rs | 203 |
1 files changed, 120 insertions, 83 deletions
diff --git a/embassy-stm32/src/tsc/mod.rs b/embassy-stm32/src/tsc/mod.rs index d5da2529f..cd7ae4a53 100644 --- a/embassy-stm32/src/tsc/mod.rs +++ b/embassy-stm32/src/tsc/mod.rs | |||
| @@ -93,6 +93,23 @@ pub enum Error { | |||
| 93 | Test, | 93 | Test, |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | /// Async acquisition API marker | ||
| 97 | pub struct Async; | ||
| 98 | /// Blocking acquisition API marker | ||
| 99 | pub struct Blocking; | ||
| 100 | |||
| 101 | trait SealedDriverKind {} | ||
| 102 | |||
| 103 | impl SealedDriverKind for Async {} | ||
| 104 | impl SealedDriverKind for Blocking {} | ||
| 105 | |||
| 106 | #[allow(private_bounds)] | ||
| 107 | /// Driver variant marker for the TSC peripheral | ||
| 108 | pub trait DriverKind: SealedDriverKind {} | ||
| 109 | |||
| 110 | impl DriverKind for Async {} | ||
| 111 | impl DriverKind for Blocking {} | ||
| 112 | |||
| 96 | /// TSC interrupt handler. | 113 | /// TSC interrupt handler. |
| 97 | pub struct InterruptHandler<T: Instance> { | 114 | pub struct InterruptHandler<T: Instance> { |
| 98 | _phantom: PhantomData<T>, | 115 | _phantom: PhantomData<T>, |
| @@ -505,7 +522,7 @@ pub enum G7 {} | |||
| 505 | pub enum G8 {} | 522 | pub enum G8 {} |
| 506 | 523 | ||
| 507 | /// TSC driver | 524 | /// TSC driver |
| 508 | pub struct Tsc<'d, T: Instance> { | 525 | pub struct Tsc<'d, T: Instance, K: DriverKind> { |
| 509 | _peri: PeripheralRef<'d, T>, | 526 | _peri: PeripheralRef<'d, T>, |
| 510 | _g1: Option<PinGroup<'d, T, G1>>, | 527 | _g1: Option<PinGroup<'d, T, G1>>, |
| 511 | _g2: Option<PinGroup<'d, T, G2>>, | 528 | _g2: Option<PinGroup<'d, T, G2>>, |
| @@ -519,13 +536,103 @@ pub struct Tsc<'d, T: Instance> { | |||
| 519 | _g8: Option<PinGroup<'d, T, G8>>, | 536 | _g8: Option<PinGroup<'d, T, G8>>, |
| 520 | state: State, | 537 | state: State, |
| 521 | config: Config, | 538 | config: Config, |
| 539 | _kind: PhantomData<K>, | ||
| 522 | } | 540 | } |
| 523 | 541 | ||
| 524 | impl<'d, T: Instance> Tsc<'d, T> { | 542 | impl<'d, T: Instance> Tsc<'d, T, Async> { |
| 525 | /// Create new TSC driver | 543 | /// Create a Tsc instance that can be awaited for completion |
| 526 | pub fn new( | 544 | pub fn new_async( |
| 527 | peri: impl Peripheral<P = T> + 'd, | 545 | peri: impl Peripheral<P = T> + 'd, |
| 546 | g1: Option<PinGroup<'d, T, G1>>, | ||
| 547 | g2: Option<PinGroup<'d, T, G2>>, | ||
| 548 | g3: Option<PinGroup<'d, T, G3>>, | ||
| 549 | g4: Option<PinGroup<'d, T, G4>>, | ||
| 550 | g5: Option<PinGroup<'d, T, G5>>, | ||
| 551 | g6: Option<PinGroup<'d, T, G6>>, | ||
| 552 | #[cfg(any(tsc_v2, tsc_v3))] g7: Option<PinGroup<'d, T, G7>>, | ||
| 553 | #[cfg(tsc_v3)] g8: Option<PinGroup<'d, T, G8>>, | ||
| 554 | config: Config, | ||
| 528 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 555 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 556 | ) -> Self { | ||
| 557 | // Need to check valid pin configuration input | ||
| 558 | let g1 = g1.filter(|b| b.check_group().is_ok()); | ||
| 559 | let g2 = g2.filter(|b| b.check_group().is_ok()); | ||
| 560 | let g3 = g3.filter(|b| b.check_group().is_ok()); | ||
| 561 | let g4 = g4.filter(|b| b.check_group().is_ok()); | ||
| 562 | let g5 = g5.filter(|b| b.check_group().is_ok()); | ||
| 563 | let g6 = g6.filter(|b| b.check_group().is_ok()); | ||
| 564 | #[cfg(any(tsc_v2, tsc_v3))] | ||
| 565 | let g7 = g7.filter(|b| b.check_group().is_ok()); | ||
| 566 | #[cfg(tsc_v3)] | ||
| 567 | let g8 = g8.filter(|b| b.check_group().is_ok()); | ||
| 568 | |||
| 569 | match Self::check_shields( | ||
| 570 | &g1, | ||
| 571 | &g2, | ||
| 572 | &g3, | ||
| 573 | &g4, | ||
| 574 | &g5, | ||
| 575 | &g6, | ||
| 576 | #[cfg(any(tsc_v2, tsc_v3))] | ||
| 577 | &g7, | ||
| 578 | #[cfg(tsc_v3)] | ||
| 579 | &g8, | ||
| 580 | ) { | ||
| 581 | Ok(()) => Self::new_inner( | ||
| 582 | peri, | ||
| 583 | g1, | ||
| 584 | g2, | ||
| 585 | g3, | ||
| 586 | g4, | ||
| 587 | g5, | ||
| 588 | g6, | ||
| 589 | #[cfg(any(tsc_v2, tsc_v3))] | ||
| 590 | g7, | ||
| 591 | #[cfg(tsc_v3)] | ||
| 592 | g8, | ||
| 593 | config, | ||
| 594 | ), | ||
| 595 | Err(_) => Self::new_inner( | ||
| 596 | peri, | ||
| 597 | None, | ||
| 598 | None, | ||
| 599 | None, | ||
| 600 | None, | ||
| 601 | None, | ||
| 602 | None, | ||
| 603 | #[cfg(any(tsc_v2, tsc_v3))] | ||
| 604 | None, | ||
| 605 | #[cfg(tsc_v3)] | ||
| 606 | None, | ||
| 607 | config, | ||
| 608 | ), | ||
| 609 | } | ||
| 610 | } | ||
| 611 | /// Asyncronously wait for the end of an acquisition | ||
| 612 | pub async fn pend_for_acquisition(&mut self) { | ||
| 613 | poll_fn(|cx| match self.get_state() { | ||
| 614 | State::Busy => { | ||
| 615 | T::waker().register(cx.waker()); | ||
| 616 | T::regs().ier().write(|w| w.set_eoaie(true)); | ||
| 617 | if self.get_state() != State::Busy { | ||
| 618 | T::regs().ier().write(|w| w.set_eoaie(false)); | ||
| 619 | return Poll::Ready(()); | ||
| 620 | } | ||
| 621 | Poll::Pending | ||
| 622 | } | ||
| 623 | _ => { | ||
| 624 | T::regs().ier().write(|w| w.set_eoaie(false)); | ||
| 625 | Poll::Ready(()) | ||
| 626 | } | ||
| 627 | }) | ||
| 628 | .await; | ||
| 629 | } | ||
| 630 | } | ||
| 631 | |||
| 632 | impl<'d, T: Instance> Tsc<'d, T, Blocking> { | ||
| 633 | /// Create a Tsc instance that must be polled for completion | ||
| 634 | pub fn new_blocking( | ||
| 635 | peri: impl Peripheral<P = T> + 'd, | ||
| 529 | g1: Option<PinGroup<'d, T, G1>>, | 636 | g1: Option<PinGroup<'d, T, G1>>, |
| 530 | g2: Option<PinGroup<'d, T, G2>>, | 637 | g2: Option<PinGroup<'d, T, G2>>, |
| 531 | g3: Option<PinGroup<'d, T, G3>>, | 638 | g3: Option<PinGroup<'d, T, G3>>, |
| @@ -590,7 +697,14 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 590 | ), | 697 | ), |
| 591 | } | 698 | } |
| 592 | } | 699 | } |
| 700 | /// Wait for end of acquisition | ||
| 701 | pub fn poll_for_acquisition(&mut self) { | ||
| 702 | while self.get_state() == State::Busy {} | ||
| 703 | } | ||
| 704 | } | ||
| 593 | 705 | ||
| 706 | impl<'d, T: Instance, K: DriverKind> Tsc<'d, T, K> { | ||
| 707 | /// Create new TSC driver | ||
| 594 | fn check_shields( | 708 | fn check_shields( |
| 595 | g1: &Option<PinGroup<'d, T, G1>>, | 709 | g1: &Option<PinGroup<'d, T, G1>>, |
| 596 | g2: &Option<PinGroup<'d, T, G2>>, | 710 | g2: &Option<PinGroup<'d, T, G2>>, |
| @@ -754,6 +868,7 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 754 | _g8: g8, | 868 | _g8: g8, |
| 755 | state: State::Ready, | 869 | state: State::Ready, |
| 756 | config, | 870 | config, |
| 871 | _kind: PhantomData, | ||
| 757 | } | 872 | } |
| 758 | } | 873 | } |
| 759 | 874 | ||
| @@ -784,33 +899,6 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 784 | }); | 899 | }); |
| 785 | } | 900 | } |
| 786 | 901 | ||
| 787 | /// Start charge transfer acquisition with interrupts enabled | ||
| 788 | pub fn start_it(&mut self) { | ||
| 789 | self.state = State::Busy; | ||
| 790 | |||
| 791 | // Enable interrupts | ||
| 792 | T::regs().ier().modify(|w| { | ||
| 793 | w.set_eoaie(true); | ||
| 794 | w.set_mceie(self.config.max_count_interrupt); | ||
| 795 | }); | ||
| 796 | |||
| 797 | // Clear flags | ||
| 798 | T::regs().icr().modify(|w| { | ||
| 799 | w.set_eoaic(true); | ||
| 800 | w.set_mceic(true); | ||
| 801 | }); | ||
| 802 | |||
| 803 | // Set the touch sensing IOs not acquired to the default mode | ||
| 804 | T::regs().cr().modify(|w| { | ||
| 805 | w.set_iodef(self.config.io_default_mode); | ||
| 806 | }); | ||
| 807 | |||
| 808 | // Start the acquisition | ||
| 809 | T::regs().cr().modify(|w| { | ||
| 810 | w.set_start(true); | ||
| 811 | }); | ||
| 812 | } | ||
| 813 | |||
| 814 | /// Stop charge transfer acquisition | 902 | /// Stop charge transfer acquisition |
| 815 | pub fn stop(&mut self) { | 903 | pub fn stop(&mut self) { |
| 816 | T::regs().cr().modify(|w| { | 904 | T::regs().cr().modify(|w| { |
| @@ -831,57 +919,6 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 831 | self.state = State::Ready; | 919 | self.state = State::Ready; |
| 832 | } | 920 | } |
| 833 | 921 | ||
| 834 | /// Stop charge transfer acquisition and clear interrupts | ||
| 835 | pub fn stop_it(&mut self) { | ||
| 836 | T::regs().cr().modify(|w| { | ||
| 837 | w.set_start(false); | ||
| 838 | }); | ||
| 839 | |||
| 840 | // Set the touch sensing IOs in low power mode | ||
| 841 | T::regs().cr().modify(|w| { | ||
| 842 | w.set_iodef(false); | ||
| 843 | }); | ||
| 844 | |||
| 845 | // Disable interrupts | ||
| 846 | T::regs().ier().modify(|w| { | ||
| 847 | w.set_eoaie(false); | ||
| 848 | w.set_mceie(false); | ||
| 849 | }); | ||
| 850 | |||
| 851 | // Clear flags | ||
| 852 | T::regs().icr().modify(|w| { | ||
| 853 | w.set_eoaic(true); | ||
| 854 | w.set_mceic(true); | ||
| 855 | }); | ||
| 856 | |||
| 857 | self.state = State::Ready; | ||
| 858 | } | ||
| 859 | |||
| 860 | /// Wait for end of acquisition | ||
| 861 | pub fn poll_for_acquisition(&mut self) { | ||
| 862 | while self.get_state() == State::Busy {} | ||
| 863 | } | ||
| 864 | |||
| 865 | /// Asyncronously wait for the end of an acquisition | ||
| 866 | pub async fn pend_for_acquisition(&mut self) { | ||
| 867 | poll_fn(|cx| match self.get_state() { | ||
| 868 | State::Busy => { | ||
| 869 | T::waker().register(cx.waker()); | ||
| 870 | T::regs().ier().write(|w| w.set_eoaie(true)); | ||
| 871 | if self.get_state() != State::Busy { | ||
| 872 | T::regs().ier().write(|w| w.set_eoaie(false)); | ||
| 873 | return Poll::Ready(()); | ||
| 874 | } | ||
| 875 | Poll::Pending | ||
| 876 | } | ||
| 877 | _ => { | ||
| 878 | T::regs().ier().write(|w| w.set_eoaie(false)); | ||
| 879 | Poll::Ready(()) | ||
| 880 | } | ||
| 881 | }) | ||
| 882 | .await; | ||
| 883 | } | ||
| 884 | |||
| 885 | /// Get current state of acquisition | 922 | /// Get current state of acquisition |
| 886 | pub fn get_state(&mut self) -> State { | 923 | pub fn get_state(&mut self) -> State { |
| 887 | if self.state == State::Busy { | 924 | if self.state == State::Busy { |
| @@ -932,7 +969,7 @@ impl<'d, T: Instance> Tsc<'d, T> { | |||
| 932 | } | 969 | } |
| 933 | } | 970 | } |
| 934 | 971 | ||
| 935 | impl<'d, T: Instance> Drop for Tsc<'d, T> { | 972 | impl<'d, T: Instance, K: DriverKind> Drop for Tsc<'d, T, K> { |
| 936 | fn drop(&mut self) { | 973 | fn drop(&mut self) { |
| 937 | rcc::disable::<T>(); | 974 | rcc::disable::<T>(); |
| 938 | } | 975 | } |
