From 0f8b3b8c65484a444d1dc9f6179ce3a60a63c06f Mon Sep 17 00:00:00 2001 From: Karun Date: Thu, 2 May 2024 13:30:30 -0400 Subject: [PATCH] Functional touch sensing --- embassy-stm32/src/tsc/enums.rs | 15 +- embassy-stm32/src/tsc/mod.rs | 356 ++++++++++++++++----------------- 2 files changed, 189 insertions(+), 182 deletions(-) diff --git a/embassy-stm32/src/tsc/enums.rs b/embassy-stm32/src/tsc/enums.rs index bdb384900..0d34a43ec 100644 --- a/embassy-stm32/src/tsc/enums.rs +++ b/embassy-stm32/src/tsc/enums.rs @@ -48,14 +48,25 @@ pub enum TscIOPin { impl BitOr for u32 { type Output = u32; fn bitor(self, rhs: TscIOPin) -> Self::Output { - self | rhs as u32 + let rhs: u32 = rhs.into(); + self | rhs + } +} + +impl BitOr for TscIOPin { + type Output = u32; + fn bitor(self, rhs: u32) -> Self::Output { + let val: u32 = self.into(); + val | rhs } } impl BitOr for TscIOPin { type Output = u32; fn bitor(self, rhs: Self) -> Self::Output { - self as u32 | rhs as u32 + let val: u32 = self.into(); + let rhs: u32 = rhs.into(); + val | rhs } } diff --git a/embassy-stm32/src/tsc/mod.rs b/embassy-stm32/src/tsc/mod.rs index 4b1987469..a37341b31 100644 --- a/embassy-stm32/src/tsc/mod.rs +++ b/embassy-stm32/src/tsc/mod.rs @@ -5,10 +5,12 @@ /// Enums defined for peripheral parameters pub mod enums; +use core::marker::PhantomData; + use embassy_hal_internal::{into_ref, PeripheralRef}; pub use enums::*; -use crate::gpio::{AFType, AnyPin, Pull}; +use crate::gpio::{AFType, AnyPin}; use crate::pac::tsc::Tsc as Regs; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; @@ -38,9 +40,6 @@ pub enum PinType { Shield, } -/// Unclear -pub struct TscGroup {} - /// Peripheral state #[derive(PartialEq, Clone, Copy)] pub enum State { @@ -58,6 +57,7 @@ pub enum State { /// For groups with multiple channel pins, may take longer because acquisitions /// are done sequentially. Check this status before pulling count for each /// sampled channel +#[derive(PartialEq)] pub enum GroupStatus { /// Acquisition for channel still in progress Ongoing, @@ -136,7 +136,7 @@ impl Default for Config { ct_pulse_high_length: ChargeTransferPulseCycle::_1, ct_pulse_low_length: ChargeTransferPulseCycle::_1, spread_spectrum: false, - spread_spectrum_deviation: SSDeviation::new(0).unwrap(), + spread_spectrum_deviation: SSDeviation::new(1).unwrap(), spread_spectrum_prescaler: false, pulse_generator_prescaler: PGPrescalerDivider::_1, max_count_value: MaxCount::_255, @@ -153,43 +153,165 @@ impl Default for Config { /// Pin struct that maintains usage #[allow(missing_docs)] -#[allow(dead_code)] -pub struct TscPin<'d, T> { - pin: PeripheralRef<'d, T>, - role: PinType, -} - -/// Input structure for constructor containing peripherals -#[allow(missing_docs)] -pub struct PeriPin { - pub pin: T, - pub role: PinType, +pub struct TscPin<'d, T, C> { + _pin: PeripheralRef<'d, AnyPin>, + _role: PinType, + phantom: PhantomData<(T, C)>, } /// Pin group definition /// Pins are organized into groups of four IOs, all groups with a /// sampling channel must also have a sampling capacitor channel. #[allow(missing_docs)] -pub struct PinGroup<'d, A> { - pub d1: Option>, - pub d2: Option>, - pub d3: Option>, - pub d4: Option>, +#[derive(Default)] +pub struct PinGroup<'d, T, C> { + d1: Option>, + d2: Option>, + d3: Option>, + d4: Option>, } +impl<'d, T: Instance, C> PinGroup<'d, T, C> { + /// Create new sensing group + pub fn new() -> Self { + Self { + d1: None, + d2: None, + d3: None, + d4: None, + } + } +} + +macro_rules! group_impl { + ($group:ident, $trait1:ident, $trait2:ident, $trait3:ident, $trait4:ident) => { + impl<'d, T: Instance> PinGroup<'d, T, $group> { + #[doc = concat!("Create a new pin1 for ", stringify!($group), " TSC group instance.")] + pub fn set_io1(&mut self, pin: impl Peripheral

> + 'd, role: PinType) { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af( + pin.af_num(), + match role { + PinType::Channel => AFType::OutputPushPull, + PinType::Sample => AFType::OutputOpenDrain, + PinType::Shield => AFType::OutputPushPull, + }, + ); + self.d1 = Some(TscPin { + _pin: pin.map_into(), + _role: role, + phantom: PhantomData, + }) + }) + } + + #[doc = concat!("Create a new pin2 for ", stringify!($group), " TSC group instance.")] + pub fn set_io2(&mut self, pin: impl Peripheral

> + 'd, role: PinType) { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af( + pin.af_num(), + match role { + PinType::Channel => AFType::OutputPushPull, + PinType::Sample => AFType::OutputOpenDrain, + PinType::Shield => AFType::OutputPushPull, + }, + ); + self.d2 = Some(TscPin { + _pin: pin.map_into(), + _role: role, + phantom: PhantomData, + }) + }) + } + + #[doc = concat!("Create a new pin3 for ", stringify!($group), " TSC group instance.")] + pub fn set_io3(&mut self, pin: impl Peripheral

> + 'd, role: PinType) { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af( + pin.af_num(), + match role { + PinType::Channel => AFType::OutputPushPull, + PinType::Sample => AFType::OutputOpenDrain, + PinType::Shield => AFType::OutputPushPull, + }, + ); + self.d3 = Some(TscPin { + _pin: pin.map_into(), + _role: role, + phantom: PhantomData, + }) + }) + } + + #[doc = concat!("Create a new pin4 for ", stringify!($group), " TSC group instance.")] + pub fn set_io4(&mut self, pin: impl Peripheral

> + 'd, role: PinType) { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af( + pin.af_num(), + match role { + PinType::Channel => AFType::OutputPushPull, + PinType::Sample => AFType::OutputOpenDrain, + PinType::Shield => AFType::OutputPushPull, + }, + ); + self.d4 = Some(TscPin { + _pin: pin.map_into(), + _role: role, + phantom: PhantomData, + }) + }) + } + } + }; +} + +group_impl!(G1, G1IO1Pin, G1IO2Pin, G1IO3Pin, G1IO4Pin); +group_impl!(G2, G2IO1Pin, G2IO2Pin, G2IO3Pin, G2IO4Pin); +group_impl!(G3, G3IO1Pin, G3IO2Pin, G3IO3Pin, G3IO4Pin); +group_impl!(G4, G4IO1Pin, G4IO2Pin, G4IO3Pin, G4IO4Pin); +group_impl!(G5, G5IO1Pin, G5IO2Pin, G5IO3Pin, G5IO4Pin); +group_impl!(G6, G6IO1Pin, G6IO2Pin, G6IO3Pin, G6IO4Pin); +group_impl!(G7, G7IO1Pin, G7IO2Pin, G7IO3Pin, G7IO4Pin); +group_impl!(G8, G8IO1Pin, G8IO2Pin, G8IO3Pin, G8IO4Pin); + +/// Group 1 marker type. +pub enum G1 {} +/// Group 2 marker type. +pub enum G2 {} +/// Group 3 marker type. +pub enum G3 {} +/// Group 4 marker type. +pub enum G4 {} +/// Group 5 marker type. +pub enum G5 {} +/// Group 6 marker type. +pub enum G6 {} +/// Group 7 marker type. +pub enum G7 {} +/// Group 8 marker type. +pub enum G8 {} + /// TSC driver pub struct Tsc<'d, T: Instance> { _peri: PeripheralRef<'d, T>, - _g1: Option>, - _g2: Option>, - _g3: Option>, - _g4: Option>, - _g5: Option>, - _g6: Option>, + _g1: Option>, + _g2: Option>, + _g3: Option>, + _g4: Option>, + _g5: Option>, + _g6: Option>, #[cfg(any(tsc_v2, tsc_v3))] - _g7: Option>, + _g7: Option>, #[cfg(tsc_v3)] - _g8: Option>, + _g8: Option>, state: State, config: Config, } @@ -198,156 +320,33 @@ impl<'d, T: Instance> Tsc<'d, T> { /// Create new TSC driver pub fn new( peri: impl Peripheral

+ 'd, - // g1_d1: Option> + 'd>>, - g1_d2: Option> + 'd>>, - g1_d3: Option> + 'd>>, - // g1_d4: Option> + 'd>>, - - // g2_d1: Option> + 'd>, - // g2_d2: Option> + 'd>, - g2_d3: Option> + 'd>>, - g2_d4: Option> + 'd>>, - - // g3_d1: Option> + 'd>, - // g3_d2: Option> + 'd>, - // g3_d3: Option> + 'd>, - // g3_d4: Option> + 'd>, - g4_d1: Option> + 'd>>, - g4_d2: Option> + 'd>>, - // g4_d3: Option> + 'd>, - // g4_d4: Option> + 'd>, - - // g5_d1: Option> + 'd>, - // g5_d2: Option> + 'd>, - // g5_d3: Option> + 'd>, - // g5_d4: Option> + 'd>, - - // g6_d1: Option> + 'd>, - // g6_d2: Option> + 'd>, - // g6_d3: Option> + 'd>, - // g6_d4: Option> + 'd>, - - // g7_d1: Option> + 'd>, - // g7_d2: Option> + 'd>, - // g7_d3: Option> + 'd>, - // g7_d4: Option> + 'd>, - - // g8_d1: Option> + 'd>, - // g8_d2: Option> + 'd>, - // g8_d3: Option> + 'd>, - // g8_d4: Option> + 'd>, + g1: Option>, + g2: Option>, + g3: Option>, + g4: Option>, + g5: Option>, + g6: Option>, + #[cfg(any(tsc_v2, tsc_v3))] g7: Option>, + #[cfg(tsc_v3)] g8: Option>, config: Config, ) -> Self { - let g1_d2 = g1_d2.unwrap(); - let g1_d2_pin = g1_d2.pin; - let g1_d3 = g1_d3.unwrap(); - let g1_d3_pin = g1_d3.pin; - let g2_d3 = g2_d3.unwrap(); - let g2_d3_pin = g2_d3.pin; - let g2_d4 = g2_d4.unwrap(); - let g2_d4_pin = g2_d4.pin; - let g4_d1 = g4_d1.unwrap(); - let g4_d1_pin = g4_d1.pin; - let g4_d2 = g4_d2.unwrap(); - let g4_d2_pin = g4_d2.pin; - into_ref!(peri, g1_d2_pin, g1_d3_pin, g2_d3_pin, g2_d4_pin, g4_d1_pin, g4_d2_pin); - - // Configure pins - match g1_d2.role { - PinType::Channel => g1_d2_pin.set_as_af_pull(g1_d2_pin.af_num(), AFType::OutputPushPull, Pull::None), - PinType::Sample => g1_d2_pin.set_as_af_pull(g1_d2_pin.af_num(), AFType::OutputOpenDrain, Pull::None), - PinType::Shield => g1_d2_pin.set_as_af_pull(g1_d2_pin.af_num(), AFType::OutputPushPull, Pull::None), - } - match g1_d3.role { - PinType::Channel => g1_d3_pin.set_as_af_pull(g1_d3_pin.af_num(), AFType::OutputPushPull, Pull::None), - PinType::Sample => g1_d3_pin.set_as_af_pull(g1_d3_pin.af_num(), AFType::OutputOpenDrain, Pull::None), - PinType::Shield => g1_d3_pin.set_as_af_pull(g1_d3_pin.af_num(), AFType::OutputPushPull, Pull::None), - } - let g1 = PinGroup { - d1: None, - d2: Some(TscPin { - pin: g1_d2_pin.map_into(), - role: g1_d2.role, - }), - d3: Some(TscPin { - pin: g1_d3_pin.map_into(), - role: g1_d3.role, - }), - d4: None, - }; - - match g2_d3.role { - PinType::Channel => g2_d3_pin.set_as_af_pull(g2_d3_pin.af_num(), AFType::OutputPushPull, Pull::None), - PinType::Sample => g2_d3_pin.set_as_af_pull(g2_d3_pin.af_num(), AFType::OutputOpenDrain, Pull::None), - PinType::Shield => g2_d3_pin.set_as_af_pull(g2_d3_pin.af_num(), AFType::OutputPushPull, Pull::None), - } - match g2_d4.role { - PinType::Channel => g2_d4_pin.set_as_af_pull(g2_d4_pin.af_num(), AFType::OutputPushPull, Pull::None), - PinType::Sample => g2_d4_pin.set_as_af_pull(g2_d4_pin.af_num(), AFType::OutputOpenDrain, Pull::None), - PinType::Shield => g2_d4_pin.set_as_af_pull(g2_d4_pin.af_num(), AFType::OutputPushPull, Pull::None), - } - let g2 = PinGroup { - d1: None, - d2: None, - d3: Some(TscPin { - pin: g2_d3_pin.map_into(), - role: g2_d3.role, - }), - d4: Some(TscPin { - pin: g2_d4_pin.map_into(), - role: g2_d4.role, - }), - }; - - match g4_d1.role { - PinType::Channel => g4_d1_pin.set_as_af_pull(g4_d1_pin.af_num(), AFType::OutputPushPull, Pull::None), - PinType::Sample => g4_d1_pin.set_as_af_pull(g4_d1_pin.af_num(), AFType::OutputOpenDrain, Pull::None), - PinType::Shield => g4_d1_pin.set_as_af_pull(g4_d1_pin.af_num(), AFType::OutputPushPull, Pull::None), - } - match g4_d2.role { - PinType::Channel => g4_d2_pin.set_as_af_pull(g4_d2_pin.af_num(), AFType::OutputPushPull, Pull::None), - PinType::Sample => g4_d2_pin.set_as_af_pull(g4_d2_pin.af_num(), AFType::OutputOpenDrain, Pull::None), - PinType::Shield => g4_d2_pin.set_as_af_pull(g4_d2_pin.af_num(), AFType::OutputPushPull, Pull::None), - } - let g4 = PinGroup { - d1: Some(TscPin { - pin: g4_d1_pin.map_into(), - role: g4_d1.role, - }), - d2: Some(TscPin { - pin: g4_d2_pin.map_into(), - role: g4_d2.role, - }), - d3: None, - d4: None, - }; - // Need to check valid pin configuration input Self::new_inner( peri, - Some(g1), - Some(g2), - None, - Some(g4), - None, - None, + g1, + g2, + g3, + g4, + g5, + g6, #[cfg(any(tsc_v2, tsc_v3))] - None, + g7, #[cfg(tsc_v3)] - None, + g8, config, ) } - // fn configure_pin<'b, G: Pin>(pin: PeripheralRef<'b, G>, role: PinType) { - // match role { - // PinType::Channel => pin.set_as_af_pull(pin.af_num(), AFType::OutputPushPull, Pull::None), - // PinType::Sample => {} - // PinType::Shield => {} - // } - // } - - // fn filter_group() -> Option> {} fn extract_groups(io_mask: u32) -> u32 { let mut groups: u32 = 0; for idx in 0..TSC_NUM_GROUPS { @@ -360,14 +359,14 @@ impl<'d, T: Instance> Tsc<'d, T> { fn new_inner( peri: impl Peripheral

+ 'd, - g1: Option>, - g2: Option>, - g3: Option>, - g4: Option>, - g5: Option>, - g6: Option>, - #[cfg(any(tsc_v2, tsc_v3))] g7: Option>, - #[cfg(tsc_v3)] g8: Option>, + g1: Option>, + g2: Option>, + g3: Option>, + g4: Option>, + g5: Option>, + g6: Option>, + #[cfg(any(tsc_v2, tsc_v3))] g7: Option>, + #[cfg(tsc_v3)] g8: Option>, config: Config, ) -> Self { into_ref!(peri); @@ -404,7 +403,7 @@ impl<'d, T: Instance> Tsc<'d, T> { // Disable Schmitt trigger hysteresis on all used TSC IOs T::REGS .iohcr() - .write(|w| w.0 = config.channel_ios | config.shield_ios | config.sampling_ios); + .write(|w| w.0 = !(config.channel_ios | config.shield_ios | config.sampling_ios)); // Set channel and shield IOs T::REGS.ioccr().write(|w| w.0 = config.channel_ios | config.shield_ios); @@ -592,8 +591,6 @@ impl<'d, T: Instance> Tsc<'d, T> { T::REGS.iogcr(index.into()).read().cnt() } - // pub fn configure_io() - /// Discharge the IOs for subsequent acquisition pub fn discharge_io(&mut self, status: bool) { // Set the touch sensing IOs in low power mode @@ -605,7 +602,6 @@ impl<'d, T: Instance> Tsc<'d, T> { impl<'d, T: Instance> Drop for Tsc<'d, T> { fn drop(&mut self) { - // Need to figure out what to do with the IOs T::disable(); } }