167 lines
4.8 KiB
Rust
167 lines
4.8 KiB
Rust
//! TSC Peripheral Interface
|
|
//!
|
|
//! This module provides an interface for the Touch Sensing Controller (TSC) peripheral.
|
|
//! It supports both blocking and async modes of operation, as well as different TSC versions (v1, v2, v3).
|
|
//!
|
|
//! # Key Concepts
|
|
//!
|
|
//! - **Pin Groups**: TSC pins are organized into groups, each containing up to four IOs.
|
|
//! - **Pin Roles**: Each pin in a group can have a role: Channel, Sample, or Shield.
|
|
//! - **Acquisition Banks**: Used for efficient, repeated TSC acquisitions on specific sets of pins.
|
|
//!
|
|
//! # Example (stm32)
|
|
//!
|
|
//! ```rust
|
|
//! let device_config = embassy_stm32::Config::default();
|
|
//! let context = embassy_stm32::init(device_config);
|
|
//!
|
|
//! let config = tsc::Config {
|
|
//! ct_pulse_high_length: ChargeTransferPulseCycle::_4,
|
|
//! ct_pulse_low_length: ChargeTransferPulseCycle::_4,
|
|
//! spread_spectrum: false,
|
|
//! spread_spectrum_deviation: SSDeviation::new(2).unwrap(),
|
|
//! spread_spectrum_prescaler: false,
|
|
//! pulse_generator_prescaler: PGPrescalerDivider::_16,
|
|
//! max_count_value: MaxCount::_255,
|
|
//! io_default_mode: false,
|
|
//! synchro_pin_polarity: false,
|
|
//! acquisition_mode: false,
|
|
//! max_count_interrupt: false,
|
|
//! };
|
|
//!
|
|
//! let mut g2: PinGroupWithRoles<embassy_stm32::peripherals::TSC, G2> = PinGroupWithRoles::new();
|
|
//! g2.set_io1::<tsc_pin_roles::Sample>(context.PB4);
|
|
//! let sensor_pin = g2.set_io2::<tsc_pin_roles::Channel>(context.PB5);
|
|
//!
|
|
//! let pin_groups = PinGroups {
|
|
//! g2: Some(g2.pin_group),
|
|
//! ..Default::default()
|
|
//! };
|
|
//!
|
|
//! let mut touch_controller = tsc::Tsc::new_blocking(
|
|
//! context.TSC,
|
|
//! pin_groups,
|
|
//! config,
|
|
//! ).unwrap();
|
|
//!
|
|
//! let discharge_delay = 5; // ms
|
|
//!
|
|
//! loop {
|
|
//! touch_controller.set_active_channels_mask(sensor_pin.pin.into());
|
|
//! touch_controller.start();
|
|
//! touch_controller.poll_for_acquisition();
|
|
//! touch_controller.discharge_io(true);
|
|
//! Timer::after_millis(discharge_delay).await;
|
|
//!
|
|
//! match touch_controller.group_get_status(sensor_pin.pin.group()) {
|
|
//! GroupStatus::Complete => {
|
|
//! let group_val = touch_controller.group_get_value(sensor_pin.pin.group());
|
|
//! // Process the touch value
|
|
//! // ...
|
|
//! }
|
|
//! GroupStatus::Ongoing => {
|
|
//! // Handle ongoing acquisition
|
|
//! // ...
|
|
//! }
|
|
//! }
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! # Async Usage
|
|
//!
|
|
//! For async operation, use `Tsc::new_async` and `pend_for_acquisition` instead of polling.
|
|
|
|
#![macro_use]
|
|
|
|
/// Configuration structures and enums for the TSC peripheral.
|
|
pub mod config;
|
|
|
|
/// Definitions and implementations for TSC pin groups.
|
|
pub mod pin_groups;
|
|
|
|
/// Definitions and implementations for individual TSC I/O pins.
|
|
pub mod io_pin;
|
|
|
|
/// Structures and implementations for TSC acquisition banks.
|
|
pub mod acquisition_banks;
|
|
|
|
/// Core implementation of the TSC (Touch Sensing Controller) driver.
|
|
pub mod tsc;
|
|
|
|
/// Type definitions used throughout the TSC module.
|
|
pub mod types;
|
|
|
|
/// Error types and definitions for the TSC module.
|
|
pub mod errors;
|
|
|
|
use core::marker::PhantomData;
|
|
|
|
pub use acquisition_banks::*;
|
|
pub use config::*;
|
|
use embassy_sync::waitqueue::AtomicWaker;
|
|
pub use errors::*;
|
|
pub use io_pin::*;
|
|
pub use pin_groups::*;
|
|
pub use tsc::*;
|
|
pub use types::*;
|
|
|
|
use crate::rcc::RccPeripheral;
|
|
use crate::{interrupt, peripherals, Peripheral};
|
|
|
|
#[cfg(tsc_v1)]
|
|
const TSC_NUM_GROUPS: usize = 6;
|
|
#[cfg(tsc_v2)]
|
|
const TSC_NUM_GROUPS: usize = 7;
|
|
#[cfg(tsc_v3)]
|
|
const TSC_NUM_GROUPS: usize = 8;
|
|
|
|
/// Error type defined for TSC
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub enum Error {
|
|
/// Test error for TSC
|
|
Test,
|
|
}
|
|
|
|
/// TSC interrupt handler.
|
|
pub struct InterruptHandler<T: Instance> {
|
|
_phantom: PhantomData<T>,
|
|
}
|
|
|
|
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
|
|
unsafe fn on_interrupt() {
|
|
T::regs().ier().write(|w| w.set_eoaie(false));
|
|
T::waker().wake();
|
|
}
|
|
}
|
|
|
|
pub(crate) trait SealedInstance {
|
|
fn regs() -> crate::pac::tsc::Tsc;
|
|
fn waker() -> &'static AtomicWaker;
|
|
}
|
|
|
|
/// TSC instance trait
|
|
#[allow(private_bounds)]
|
|
pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {
|
|
/// Interrupt for this TSC instance
|
|
type Interrupt: interrupt::typelevel::Interrupt;
|
|
}
|
|
|
|
foreach_interrupt!(
|
|
($inst:ident, tsc, TSC, GLOBAL, $irq:ident) => {
|
|
impl Instance for peripherals::$inst {
|
|
type Interrupt = crate::interrupt::typelevel::$irq;
|
|
}
|
|
|
|
impl SealedInstance for peripherals::$inst {
|
|
fn regs() -> crate::pac::tsc::Tsc {
|
|
crate::pac::$inst
|
|
}
|
|
fn waker() -> &'static AtomicWaker {
|
|
static WAKER: AtomicWaker = AtomicWaker::new();
|
|
&WAKER
|
|
}
|
|
}
|
|
};
|
|
);
|