aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEekle <[email protected]>2024-06-30 11:03:29 +0200
committerEekle <[email protected]>2024-06-30 11:03:29 +0200
commit1d1fc9afeac268a4b6d2cd9b9e5788226c79eca8 (patch)
tree445969b15e14aa18a272783c16373832d03ff0e2
parent7eb605d1165eaf4cdf90453d1ed2d6976dd514af (diff)
Add async and blocking variants
-rw-r--r--embassy-stm32/src/tsc/mod.rs203
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
97pub struct Async;
98/// Blocking acquisition API marker
99pub struct Blocking;
100
101trait SealedDriverKind {}
102
103impl SealedDriverKind for Async {}
104impl SealedDriverKind for Blocking {}
105
106#[allow(private_bounds)]
107/// Driver variant marker for the TSC peripheral
108pub trait DriverKind: SealedDriverKind {}
109
110impl DriverKind for Async {}
111impl DriverKind for Blocking {}
112
96/// TSC interrupt handler. 113/// TSC interrupt handler.
97pub struct InterruptHandler<T: Instance> { 114pub struct InterruptHandler<T: Instance> {
98 _phantom: PhantomData<T>, 115 _phantom: PhantomData<T>,
@@ -505,7 +522,7 @@ pub enum G7 {}
505pub enum G8 {} 522pub enum G8 {}
506 523
507/// TSC driver 524/// TSC driver
508pub struct Tsc<'d, T: Instance> { 525pub 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
524impl<'d, T: Instance> Tsc<'d, T> { 542impl<'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
632impl<'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
706impl<'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
935impl<'d, T: Instance> Drop for Tsc<'d, T> { 972impl<'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 }