m5stack_core/driver/ft6336u.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2//! FT6336U capacitive touch controller driver (I2C 0x38).
3//!
4//! Reads only touch point 1 (single-finger). Returns screen coordinates
5//! or None if no touch is active.
6//!
7//! Register map (FT6336U datasheet V1.0, §4 "Register Description"):
8//! 0x02 TD_STATUS [3:0] = number of touch points (0–2)
9//! 0x03 P1_XH [7:6] = event flag (00=down, 01=up, 10=contact, 11=reserved)
10//! [3:0] = X position high nibble
11//! 0x04 P1_XL [7:0] = X position low byte
12//! 0x05 P1_YH [7:6] = (reserved) [3:0] = Y position high nibble
13//! 0x06 P1_YL [7:0] = Y position low byte
14//!
15//! Ref: <https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/D-FT6336U-DataSheet-V1.020af.pdf>
16//! Also: FT6x06 Application Note (Adafruit) for FT6x36 family register compatibility.
17use crate::io::shared_i2c::SharedI2cBus;
18
19pub const ADDR: u8 = 0x38;
20
21const REG_TD_STATUS: u8 = 0x02; // burst-read 0x02..0x06 (5 bytes)
22
23/// Read first touch point. Returns `Some((x, y))` if touched, `None` otherwise.
24pub async fn read_touch(
25 i2c: &SharedI2cBus,
26) -> Result<Option<(u16, u16)>, esp_hal::i2c::master::Error> {
27 let mut buf = [0u8; 5]; // TD_STATUS, P1_XH, P1_XL, P1_YH, P1_YL
28 i2c.lock()
29 .await
30 .write_read_async(ADDR, &[REG_TD_STATUS], &mut buf)
31 .await?;
32
33 let touch_count = buf[0] & 0x0F; // TD_STATUS[3:0]
34 if touch_count == 0 {
35 return Ok(None);
36 }
37
38 let x = ((buf[1] & 0x0F) as u16) << 8 | buf[2] as u16; // P1_XH[3:0] : P1_XL
39 let y = ((buf[3] & 0x0F) as u16) << 8 | buf[4] as u16; // P1_YH[3:0] : P1_YL
40 Ok(Some((x, y)))
41}