use super::io_pin::*; #[cfg(any(tsc_v2, tsc_v3))] use super::pin_groups::G7; #[cfg(tsc_v3)] use super::pin_groups::G8; use super::pin_groups::{pin_roles, G1, G2, G3, G4, G5, G6}; use super::types::{Group, GroupStatus}; use super::TSC_NUM_GROUPS; /// Represents a collection of TSC (Touch Sensing Controller) pins for an acquisition bank. /// /// This struct holds optional `tsc::IOPin` values for each TSC group, allowing for flexible /// configuration of TSC acquisition banks. Each field corresponds to a specific TSC group /// and can be set to `Some(tsc::IOPin)` if that group is to be included in the acquisition, /// or `None` if it should be excluded. #[allow(missing_docs)] #[derive(Default)] pub struct AcquisitionBankPins { pub g1_pin: Option>, pub g2_pin: Option>, pub g3_pin: Option>, pub g4_pin: Option>, pub g5_pin: Option>, pub g6_pin: Option>, #[cfg(any(tsc_v2, tsc_v3))] pub g7_pin: Option>, #[cfg(tsc_v3)] pub g8_pin: Option>, } impl AcquisitionBankPins { /// Returns an iterator over the pins in this acquisition bank. /// /// This method allows for easy traversal of all configured pins in the bank. pub fn iter(&self) -> AcquisitionBankPinsIterator { AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self)) } } /// Iterator for TSC acquisition banks. /// /// This iterator allows traversing through the pins of a `AcquisitionBankPins` struct, /// yielding each configured pin in order of the TSC groups. pub struct AcquisitionBankIterator<'a> { pins: &'a AcquisitionBankPins, current_group: u8, } impl<'a> AcquisitionBankIterator<'a> { fn new(pins: &'a AcquisitionBankPins) -> Self { Self { pins, current_group: 0 } } fn next_pin(&mut self) -> Option { while self.current_group < TSC_NUM_GROUPS as u8 { let pin = match self.current_group { 0 => self.pins.g1_pin.map(IOPinWithRole::get_pin), 1 => self.pins.g2_pin.map(IOPinWithRole::get_pin), 2 => self.pins.g3_pin.map(IOPinWithRole::get_pin), 3 => self.pins.g4_pin.map(IOPinWithRole::get_pin), 4 => self.pins.g5_pin.map(IOPinWithRole::get_pin), 5 => self.pins.g6_pin.map(IOPinWithRole::get_pin), #[cfg(any(tsc_v2, tsc_v3))] 6 => self.pins.g7_pin.map(IOPinWithRole::get_pin), #[cfg(tsc_v3)] 7 => self.pins.g8_pin.map(IOPinWithRole::get_pin), _ => None, }; self.current_group += 1; if pin.is_some() { return pin; } } None } } /// Iterator for TSC acquisition bank pins. /// /// This iterator yields `tsc::IOPin` values for each configured pin in the acquisition bank. pub struct AcquisitionBankPinsIterator<'a>(AcquisitionBankIterator<'a>); impl<'a> Iterator for AcquisitionBankPinsIterator<'a> { type Item = IOPin; fn next(&mut self) -> Option { self.0.next_pin() } } impl AcquisitionBankPins { /// Returns an iterator over the available pins in the bank pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator { AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self)) } } /// Represents a collection of TSC pins to be acquired simultaneously. /// /// This struct contains a set of pins to be used in a TSC acquisition with a pre-computed and /// verified mask for efficiently setting up the TSC peripheral before performing an acquisition. /// It ensures that only one channel pin per TSC group is included, adhering to hardware limitations. pub struct AcquisitionBank { pub(super) pins: AcquisitionBankPins, pub(super) mask: u32, } impl AcquisitionBank { /// Returns an iterator over the available pins in the bank. pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator { self.pins.pins_iterator() } /// Returns the mask for this bank. pub fn mask(&self) -> u32 { self.mask } /// Retrieves the TSC I/O pin for a given group in this acquisition bank. /// /// # Arguments /// * `group` - The TSC group to retrieve the pin for. /// /// # Returns /// An `Option` containing the pin if it exists for the given group, or `None` if not. pub fn get_pin(&self, group: Group) -> Option { match group { Group::One => self.pins.g1_pin.map(|p| p.pin), Group::Two => self.pins.g2_pin.map(|p| p.pin), Group::Three => self.pins.g3_pin.map(|p| p.pin), Group::Four => self.pins.g4_pin.map(|p| p.pin), Group::Five => self.pins.g5_pin.map(|p| p.pin), Group::Six => self.pins.g6_pin.map(|p| p.pin), #[cfg(any(tsc_v2, tsc_v3))] Group::Seven => self.pins.g7_pin.map(|p| p.pin), #[cfg(tsc_v3)] Group::Eight => self.pins.g8_pin.map(|p| p.pin), } } } /// Represents the status of all TSC groups in an acquisition bank #[derive(Default)] pub struct AcquisitionBankStatus { pub(super) groups: [Option; TSC_NUM_GROUPS], } impl AcquisitionBankStatus { /// Check if all groups in the bank are complete pub fn all_complete(&self) -> bool { self.groups .iter() .all(|&status| status.map_or(true, |s| s == GroupStatus::Complete)) } /// Check if any group in the bank is ongoing pub fn any_ongoing(&self) -> bool { self.groups.iter().any(|&status| status == Some(GroupStatus::Ongoing)) } /// Get the status of a specific group, if the group is present in the bank pub fn get_group_status(&self, group: Group) -> Option { let index: usize = group.into(); self.groups[index] } /// Iterator for groups present in the bank pub fn iter(&self) -> impl Iterator + '_ { self.groups.iter().enumerate().filter_map(|(group_num, status)| { status.and_then(|s| Group::try_from(group_num).ok().map(|group| (group, s))) }) } } /// Represents the result of a Touch Sensing Controller (TSC) acquisition for a specific pin. /// /// This struct contains a reference to the `tsc::IOPin` from which a value was read, /// along with the actual sensor reading for that pin. It provides a convenient way /// to associate TSC readings with their corresponding pins after an acquisition. #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Clone, Copy, Debug)] pub struct ChannelReading { /// The sensor reading value obtained from the TSC acquisition. /// Lower values typically indicate a detected touch, while higher values indicate no touch. pub sensor_value: u16, /// The `tsc::IOPin` associated with this reading. /// This allows for easy identification of which pin the reading corresponds to. pub tsc_pin: IOPin, } /// Represents the readings from all TSC groups #[derive(Default)] pub struct AcquisitionBankReadings { pub(super) groups: [Option; TSC_NUM_GROUPS], } impl AcquisitionBankReadings { /// Get the reading for a specific group, if the group is present in the bank pub fn get_group_reading(&self, group: Group) -> Option { let index: usize = group.into(); self.groups[index] } /// Iterator for readings for groups present in the bank pub fn iter(&self) -> impl Iterator + '_ { self.groups.iter().filter_map(|&x| x) } }