#![no_std]
use core::{array::TryFromSliceError, fmt::Debug};
use bondrewd::Bitfields;
use embedded_hal::{
blocking::i2c::{Write, WriteRead},
digital::v2::InputPin,
};
const I2C_ADDR: u8 = 0x24;
#[derive(Debug)]
pub enum Error<E> {
BusError(E),
InvalidMessageLen(usize),
IOError,
NoDataAvailable,
TryFromSliceError,
}
impl<E> From<TryFromSliceError> for Error<E> {
fn from(_: TryFromSliceError) -> Self {
Self::TryFromSliceError
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Event {
Touch {
report: TouchReport,
touches: (Option<TouchRecord>, Option<TouchRecord>),
},
Button(ButtonRecord),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Bitfields)]
#[bondrewd(default_endianness = "le")]
pub struct TouchReport {
pub data_len: u16,
pub report_id: u8,
pub time_stamp: u16,
#[bondrewd(bit_length = 2)]
padding0: u8,
#[bondrewd(bit_length = 1)]
pub large_object: u8,
#[bondrewd(bit_length = 5)]
pub record_num: u8,
#[bondrewd(bit_length = 2)]
pub report_counter: u8,
#[bondrewd(bit_length = 3)]
padding1: u8,
#[bondrewd(bit_length = 3)]
pub noise_effect: u8,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Bitfields)]
#[bondrewd(default_endianness = "le")]
pub struct TouchRecord {
#[bondrewd(bit_length = 5)]
padding0: u8,
#[bondrewd(bit_length = 3)]
pub touch_type: u8,
#[bondrewd(bit_length = 1)]
pub tip: u8,
#[bondrewd(bit_length = 2)]
pub event_id: u8,
#[bondrewd(bit_length = 5)]
pub touch_id: u8,
pub x: u16,
pub y: u16,
pub pressure: u8,
pub major_axis_length: u16,
pub orientation: u8,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Bitfields)]
#[bondrewd(default_endianness = "le")]
pub struct ButtonRecord {
pub length: u16,
pub report_id: u8,
pub time_stamp: u16,
pub btn_val: u8,
pub btn_signal: [u16; 4],
}
pub struct TT21100<I2C, IRQ> {
i2c: I2C,
irq: IRQ,
}
impl<I2C, IRQ, E> TT21100<I2C, IRQ>
where
I2C: Write<Error = E> + WriteRead<Error = E>,
IRQ: InputPin,
E: Debug,
{
pub fn new(i2c: I2C, irq: IRQ) -> Result<Self, Error<E>> {
let mut me = Self { i2c, irq };
let mut message_length = 0;
for _ in 0..5 {
message_length = me.read_message_length()?;
if message_length == 2 {
break;
}
}
match message_length {
2 => Ok(me),
n => Err(Error::InvalidMessageLen(n)),
}
}
pub fn data_available(&self) -> Result<bool, Error<E>> {
self.irq.is_low().map_err(|_| Error::IOError)
}
pub fn event(&mut self) -> Result<Event, Error<E>> {
let message_length = self.read_message_length()?;
let mut data = [0u8; 32];
self.read_bytes(&mut data[0..][..message_length])?;
match message_length {
2 => Err(Error::NoDataAvailable),
7 | 17 | 27 => touch_event(&data[0..][..message_length]),
14 => button_event(&data[0..][..message_length]),
n => Err(Error::InvalidMessageLen(n)),
}
}
fn read_message_length(&mut self) -> Result<usize, Error<E>> {
let mut buffer = [0u8; 2];
self.read_bytes(&mut buffer)?;
let message_length = u16::from_le_bytes(buffer);
Ok(message_length as usize)
}
fn read_bytes(&mut self, buffer: &mut [u8]) -> Result<(), Error<E>> {
self.i2c
.write_read(I2C_ADDR, &[], buffer)
.map_err(|e| Error::BusError(e))
}
}
fn touch_event<E>(message: &[u8]) -> Result<Event, Error<E>>
where
E: Debug,
{
debug_assert!(message.len() == 7 || message.len() == 17 || message.len() == 27);
let report = message[0..][..7].try_into()?;
let report = TouchReport::from_bytes(report);
let record0 = if message.len() >= 17 {
let record = message[7..][..10].try_into()?;
let record = TouchRecord::from_bytes(record);
Some(record)
} else {
None
};
let record1 = if message.len() == 27 {
let record = message[17..][..10].try_into()?;
let record = TouchRecord::from_bytes(record);
Some(record)
} else {
None
};
Ok(Event::Touch {
report,
touches: (record0, record1),
})
}
fn button_event<E>(message: &[u8]) -> Result<Event, Error<E>>
where
E: Debug,
{
debug_assert_eq!(message.len(), 14);
let message = message.try_into()?;
let record = ButtonRecord::from_bytes(message);
Ok(Event::Button(record))
}