1use super::io_pin::*;
2#[cfg(any(tsc_v2, tsc_v3))]
3use super::pin_groups::G7;
4#[cfg(tsc_v3)]
5use super::pin_groups::G8;
6use super::pin_groups::{pin_roles, G1, G2, G3, G4, G5, G6};
7use super::types::{Group, GroupStatus};
8use super::TSC_NUM_GROUPS;
9
10/// Represents a collection of TSC (Touch Sensing Controller) pins for an acquisition bank.
11///
12/// This struct holds optional `tsc::IOPin` values for each TSC group, allowing for flexible
13/// configuration of TSC acquisition banks. Each field corresponds to a specific TSC group
14/// and can be set to `Some(tsc::IOPin)` if that group is to be included in the acquisition,
15/// or `None` if it should be excluded.
16#[allow(missing_docs)]
17#[derive(Default)]
18pub struct AcquisitionBankPins {
19 pub g1_pin: Option<IOPinWithRole<G1, pin_roles::Channel>>,
20 pub g2_pin: Option<IOPinWithRole<G2, pin_roles::Channel>>,
21 pub g3_pin: Option<IOPinWithRole<G3, pin_roles::Channel>>,
22 pub g4_pin: Option<IOPinWithRole<G4, pin_roles::Channel>>,
23 pub g5_pin: Option<IOPinWithRole<G5, pin_roles::Channel>>,
24 pub g6_pin: Option<IOPinWithRole<G6, pin_roles::Channel>>,
25 #[cfg(any(tsc_v2, tsc_v3))]
26 pub g7_pin: Option<IOPinWithRole<G7, pin_roles::Channel>>,
27 #[cfg(tsc_v3)]
28 pub g8_pin: Option<IOPinWithRole<G8, pin_roles::Channel>>,
29}
30
31impl AcquisitionBankPins {
32 /// Returns an iterator over the pins in this acquisition bank.
33 ///
34 /// This method allows for easy traversal of all configured pins in the bank.
35 pub fn iter(&self) -> AcquisitionBankPinsIterator {
36 AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self))
37 }
38}
39
40/// Iterator for TSC acquisition banks.
41///
42/// This iterator allows traversing through the pins of a `AcquisitionBankPins` struct,
43/// yielding each configured pin in order of the TSC groups.
44pub struct AcquisitionBankIterator<'a> {
45 pins: &'a AcquisitionBankPins,
46 current_group: u8,
47}
48
49impl<'a> AcquisitionBankIterator<'a> {
50 fn new(pins: &'a AcquisitionBankPins) -> Self {
51 Self { pins, current_group: 0 }
52 }
53
54 fn next_pin(&mut self) -> Option<IOPin> {
55 while self.current_group < TSC_NUM_GROUPS as u8 {
56 let pin = match self.current_group {
57 0 => self.pins.g1_pin.map(IOPinWithRole::get_pin),
58 1 => self.pins.g2_pin.map(IOPinWithRole::get_pin),
59 2 => self.pins.g3_pin.map(IOPinWithRole::get_pin),
60 3 => self.pins.g4_pin.map(IOPinWithRole::get_pin),
61 4 => self.pins.g5_pin.map(IOPinWithRole::get_pin),
62 5 => self.pins.g6_pin.map(IOPinWithRole::get_pin),
63 #[cfg(any(tsc_v2, tsc_v3))]
64 6 => self.pins.g7_pin.map(IOPinWithRole::get_pin),
65 #[cfg(tsc_v3)]
66 7 => self.pins.g8_pin.map(IOPinWithRole::get_pin),
67 _ => None,
68 };
69 self.current_group += 1;
70 if pin.is_some() {
71 return pin;
72 }
73 }
74 None
75 }
76}
77
78/// Iterator for TSC acquisition bank pins.
79///
80/// This iterator yields `tsc::IOPin` values for each configured pin in the acquisition bank.
81pub struct AcquisitionBankPinsIterator<'a>(AcquisitionBankIterator<'a>);
82
83impl<'a> Iterator for AcquisitionBankPinsIterator<'a> {
84 type Item = IOPin;
85
86 fn next(&mut self) -> Option<Self::Item> {
87 self.0.next_pin()
88 }
89}
90
91impl AcquisitionBankPins {
92 /// Returns an iterator over the available pins in the bank
93 pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator {
94 AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self))
95 }
96}
97
98/// Represents a collection of TSC pins to be acquired simultaneously.
99///
100/// This struct contains a set of pins to be used in a TSC acquisition with a pre-computed and
101/// verified mask for efficiently setting up the TSC peripheral before performing an acquisition.
102/// It ensures that only one channel pin per TSC group is included, adhering to hardware limitations.
103pub struct AcquisitionBank {
104 pub(super) pins: AcquisitionBankPins,
105 pub(super) mask: u32,
106}
107
108impl AcquisitionBank {
109 /// Returns an iterator over the available pins in the bank.
110 pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator {
111 self.pins.pins_iterator()
112 }
113
114 /// Returns the mask for this bank.
115 pub fn mask(&self) -> u32 {
116 self.mask
117 }
118
119 /// Retrieves the TSC I/O pin for a given group in this acquisition bank.
120 ///
121 /// # Arguments
122 /// * `group` - The TSC group to retrieve the pin for.
123 ///
124 /// # Returns
125 /// An `Option<tsc::IOPin>` containing the pin if it exists for the given group, or `None` if not.
126 pub fn get_pin(&self, group: Group) -> Option<IOPin> {
127 match group {
128 Group::One => self.pins.g1_pin.map(|p| p.pin),
129 Group::Two => self.pins.g2_pin.map(|p| p.pin),
130 Group::Three => self.pins.g3_pin.map(|p| p.pin),
131 Group::Four => self.pins.g4_pin.map(|p| p.pin),
132 Group::Five => self.pins.g5_pin.map(|p| p.pin),
133 Group::Six => self.pins.g6_pin.map(|p| p.pin),
134 #[cfg(any(tsc_v2, tsc_v3))]
135 Group::Seven => self.pins.g7_pin.map(|p| p.pin),
136 #[cfg(tsc_v3)]
137 Group::Eight => self.pins.g8_pin.map(|p| p.pin),
138 }
139 }
140}
141
142/// Represents the status of all TSC groups in an acquisition bank
143#[derive(Default)]
144pub struct AcquisitionBankStatus {
145 pub(super) groups: [Option<GroupStatus>; TSC_NUM_GROUPS],
146}
147
148impl AcquisitionBankStatus {
149 /// Check if all groups in the bank are complete
150 pub fn all_complete(&self) -> bool {
151 self.groups
152 .iter()
153 .all(|&status| status.map_or(true, |s| s == GroupStatus::Complete))
154 }
155
156 /// Check if any group in the bank is ongoing
157 pub fn any_ongoing(&self) -> bool {
158 self.groups.iter().any(|&status| status == Some(GroupStatus::Ongoing))
159 }
160
161 /// Get the status of a specific group, if the group is present in the bank
162 pub fn get_group_status(&self, group: Group) -> Option<GroupStatus> {
163 let index: usize = group.into();
164 self.groups[index]
165 }
166
167 /// Iterator for groups present in the bank
168 pub fn iter(&self) -> impl Iterator<Item = (Group, GroupStatus)> + '_ {
169 self.groups.iter().enumerate().filter_map(|(group_num, status)| {
170 status.and_then(|s| Group::try_from(group_num).ok().map(|group| (group, s)))
171 })
172 }
173}
174
175/// Represents the result of a Touch Sensing Controller (TSC) acquisition for a specific pin.
176///
177/// This struct contains a reference to the `tsc::IOPin` from which a value was read,
178/// along with the actual sensor reading for that pin. It provides a convenient way
179/// to associate TSC readings with their corresponding pins after an acquisition.
180#[cfg_attr(feature = "defmt", derive(defmt::Format))]
181#[derive(Clone, Copy, Debug)]
182pub struct ChannelReading {
183 /// The sensor reading value obtained from the TSC acquisition.
184 /// Lower values typically indicate a detected touch, while higher values indicate no touch.
185 pub sensor_value: u16,
186
187 /// The `tsc::IOPin` associated with this reading.
188 /// This allows for easy identification of which pin the reading corresponds to.
189 pub tsc_pin: IOPin,
190}
191
192/// Represents the readings from all TSC groups
193#[derive(Default)]
194pub struct AcquisitionBankReadings {
195 pub(super) groups: [Option<ChannelReading>; TSC_NUM_GROUPS],
196}
197
198impl AcquisitionBankReadings {
199 /// Get the reading for a specific group, if the group is present in the bank
200 pub fn get_group_reading(&self, group: Group) -> Option<ChannelReading> {
201 let index: usize = group.into();
202 self.groups[index]
203 }
204
205 /// Iterator for readings for groups present in the bank
206 pub fn iter(&self) -> impl Iterator<Item = ChannelReading> + '_ {
207 self.groups.iter().filter_map(|&x: Option| x)
208 }
209}
210