use embassy_stm32::gpio::{AnyPin, Flex, Pull, Speed};
use embassy_stm32::i2c::{I2c, Master};
use embassy_stm32::mode::Blocking;
use embassy_stm32::Peri;
use embassy_time::Timer;
pub fn bias_int_low(int_pin: Peri<'static, AnyPin>) -> Flex<'static> {
let mut int = Flex::new(int_pin);
int.set_as_output(Speed::Low);
int.set_low();
int
}
#[derive(Clone, Copy)]
pub struct TouchPoint {
pub count: u8,
pub x: u16,
pub y: u16,
}
pub struct Touch {
addr: Option<u8>,
}
impl Touch {
pub async fn new(i2c: &mut I2c<'_, Blocking, Master>, mut int: Flex<'static>) -> Self {
Timer::after_millis(50).await;
int.set_as_input(Pull::None);
Timer::after_millis(50).await;
core::mem::forget(int);
let mut addr = None;
for a in [0x5Du8, 0x14] {
let mut id = [0u8; 4]; if i2c.blocking_write_read(a, &[0x81, 0x40], &mut id).is_ok() {
defmt::info!("touch: GT9147 @ {=u8:#04x} id {=[u8]:a}", a, id);
addr = Some(a);
break;
}
}
if let Some(a) = addr {
let _ = i2c.blocking_write(a, &[0x80, 0x40, 0x00]); Timer::after_millis(25).await;
let _ = i2c.blocking_write(a, &[0x81, 0x4E, 0x00]); } else {
defmt::info!("touch: GT9147 not responding on 0x5d/0x14");
}
Self { addr }
}
pub fn detected(&self) -> bool {
self.addr.is_some()
}
pub fn poll(&self, i2c: &mut I2c<'_, Blocking, Master>) -> Option<TouchPoint> {
let addr = self.addr?;
let mut st = [0u8; 1];
i2c.blocking_write_read(addr, &[0x81, 0x4E], &mut st).ok()?;
if st[0] & 0x80 == 0 {
return None; }
let count = st[0] & 0x0F;
let mut pt = [0u8; 8]; let read = if count > 0 {
i2c.blocking_write_read(addr, &[0x81, 0x4F], &mut pt)
} else {
Ok(())
};
let _ = i2c.blocking_write(addr, &[0x81, 0x4E, 0x00]); read.ok()?;
if count == 0 {
return None;
}
let raw_x = u16::from_le_bytes([pt[1], pt[2]]);
let raw_y = u16::from_le_bytes([pt[3], pt[4]]);
Some(TouchPoint {
count,
x: raw_y, y: raw_x, })
}
}