tt21100_async/
lib.rs

1//! TT21100 Multi-Touch Touchscreen Controller
2
3#![no_std]
4
5use core::{array::TryFromSliceError, fmt::Debug};
6
7use bondrewd::Bitfields;
8use embedded_hal_async::{digital::Wait, i2c::I2c};
9
10// Default I²C address for the TT21100
11const I2C_ADDR: u8 = 0x24;
12
13/// Any type of error which may occur while interacting with the device
14#[derive(Debug)]
15pub enum Error<E> {
16    /// Some error originating from the communication bus
17    BusError(E),
18    /// The message length did not match the expected value
19    InvalidMessageLen(usize),
20    /// Reading a GPIO pin resulted in an error
21    IOError,
22    /// Tried to read a touch point, but no data was available
23    NoDataAvailable,
24    /// Error converting a slice to an array
25    TryFromSliceError,
26}
27
28impl<E> From<TryFromSliceError> for Error<E> {
29    fn from(_: TryFromSliceError) -> Self {
30        Self::TryFromSliceError
31    }
32}
33
34/// An event emitted by the device
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum Event {
37    /// A touch event
38    Touch {
39        report: TouchReport,
40        touches: (Option<TouchRecord>, Option<TouchRecord>),
41    },
42    /// A button press event
43    Button(ButtonRecord),
44}
45
46/// Prelude data for one or more touch events
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Bitfields)]
48#[bondrewd(default_endianness = "le")]
49pub struct TouchReport {
50    /// Total length of the data; should be 7, 17, or 27
51    pub data_len: u16,
52    /// ID of the report
53    pub report_id: u8,
54    /// Timestamp
55    pub time_stamp: u16,
56    #[bondrewd(bit_length = 2)]
57    padding0: u8,
58    #[bondrewd(bit_length = 1)]
59    pub large_object: u8,
60    #[bondrewd(bit_length = 5)]
61    pub record_num: u8,
62    #[bondrewd(bit_length = 2)]
63    pub report_counter: u8,
64    #[bondrewd(bit_length = 3)]
65    padding1: u8,
66    #[bondrewd(bit_length = 3)]
67    pub noise_effect: u8,
68}
69
70/// Data for a touch event
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Bitfields)]
72#[bondrewd(default_endianness = "le")]
73pub struct TouchRecord {
74    #[bondrewd(bit_length = 5)]
75    padding0: u8,
76    #[bondrewd(bit_length = 3)]
77    pub touch_type: u8,
78    #[bondrewd(bit_length = 1)]
79    pub tip: u8,
80    #[bondrewd(bit_length = 2)]
81    pub event_id: u8,
82    #[bondrewd(bit_length = 5)]
83    pub touch_id: u8,
84    pub x: u16,
85    pub y: u16,
86    pub pressure: u8,
87    pub major_axis_length: u16,
88    pub orientation: u8,
89}
90
91/// Data for a button press event
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Bitfields)]
93#[bondrewd(default_endianness = "le")]
94pub struct ButtonRecord {
95    /// Length of the record; always `14`
96    pub length: u16,
97    /// ID of the report; always `3`
98    pub report_id: u8,
99    /// Timestamp in units of 100us
100    pub time_stamp: u16,
101    /// Button value; only use bits[3..0]
102    pub btn_val: u8,
103    /// Button signals
104    pub btn_signal: [u16; 4],
105}
106
107/// TT21100 driver
108pub struct TT21100<I2C, IRQ> {
109    /// Underlying I²C peripheral
110    i2c: I2C,
111    /// Interrupt pin
112    irq: IRQ,
113}
114
115impl<I2C, IRQ, E> TT21100<I2C, IRQ>
116where
117    I2C: I2c<Error = E>,
118    IRQ: Wait,
119    E: Debug,
120{
121    /// Create a new instance of the driver and initialize the device
122    pub fn new(i2c: I2C, irq: IRQ) -> Self {
123        Self { i2c, irq }
124    }
125
126    /// Is there data available to read from the device?
127    pub async fn data_available(&mut self) -> Result<(), Error<E>> {
128        self.irq.wait_for_low().await.map_err(|_| Error::IOError)
129    }
130
131    /// Read an event from the device
132    ///
133    /// There are two types of events, [Event::Touch] and [Event::Button].
134    pub async fn event(&mut self) -> Result<Event, Error<E>> {
135        let message_length = self.read_message_length().await?;
136
137        let mut data = [0u8; 32];
138        self.read_bytes(&mut data[0..][..message_length]).await?;
139
140        match message_length {
141            2 => Err(Error::NoDataAvailable),
142            7 | 17 | 27 => touch_event(&data[0..][..message_length]),
143            14 => button_event(&data[0..][..message_length]),
144            n => Err(Error::InvalidMessageLen(n)),
145        }
146    }
147
148    // -----------------------------------------------------------------------
149    // PRIVATE
150
151    async fn read_message_length(&mut self) -> Result<usize, Error<E>> {
152        let mut buffer = [0u8; 2];
153        self.read_bytes(&mut buffer).await?;
154
155        let message_length = u16::from_le_bytes(buffer);
156
157        Ok(message_length as usize)
158    }
159
160    async fn read_bytes(&mut self, buffer: &mut [u8]) -> Result<(), Error<E>> {
161        self.i2c
162            .write_read(I2C_ADDR, &[], buffer)
163            .await
164            .map_err(|e| Error::BusError(e))
165    }
166}
167
168fn touch_event<E>(message: &[u8]) -> Result<Event, Error<E>>
169where
170    E: Debug,
171{
172    debug_assert!(message.len() == 7 || message.len() == 17 || message.len() == 27);
173
174    let report = message[0..][..7].try_into()?;
175    let report = TouchReport::from_bytes(report);
176
177    let record0 = if message.len() >= 17 {
178        let record = message[7..][..10].try_into()?;
179        let record = TouchRecord::from_bytes(record);
180
181        Some(record)
182    } else {
183        None
184    };
185
186    let record1 = if message.len() == 27 {
187        let record = message[17..][..10].try_into()?;
188        let record = TouchRecord::from_bytes(record);
189
190        Some(record)
191    } else {
192        None
193    };
194
195    Ok(Event::Touch {
196        report,
197        touches: (record0, record1),
198    })
199}
200
201fn button_event<E>(message: &[u8]) -> Result<Event, Error<E>>
202where
203    E: Debug,
204{
205    debug_assert_eq!(message.len(), 14);
206
207    let message = message.try_into()?;
208    let record = ButtonRecord::from_bytes(message);
209
210    Ok(Event::Button(record))
211}