1#![no_std]
13#![no_main]
14
15pub mod constant;
16
17#[cfg(feature = "gesture")]
18use heapless::Vec;
19
20use crate::constant::*;
21use core::marker::PhantomData;
22use embedded_hal as hal;
23use hal::blocking::{
24 delay::{DelayMs, DelayUs},
25 i2c,
26};
27use hal::digital::v2::OutputPin;
28
29#[derive(Copy, Clone, Debug)]
30pub struct Ft6x06Capabilities {
31 #[allow(dead_code)]
32 multi_touch: bool,
33 #[allow(dead_code)]
34 gesture: bool,
35 #[allow(dead_code)]
36 max_touch: u8,
37 #[allow(dead_code)]
38 max_x_length: u16,
39 #[allow(dead_code)]
40 may_y_length: u16,
41}
42
43const TRUE: bool = true;
44const FALSE: bool = false;
45
46const FT6X06_CAPABILITIES: Ft6x06Capabilities = Ft6x06Capabilities {
47 multi_touch: TRUE,
48 gesture: FALSE,
50 max_touch: FT6X06_MAX_NB_TOUCH as u8,
51 max_x_length: FT6X06_MAX_X_LENGTH,
52 may_y_length: FT6X06_MAX_Y_LENGTH,
53};
54
55#[derive(Copy, Clone, Debug, PartialOrd, Ord, Eq, PartialEq)]
66pub struct TouchState {
67 pub detected: bool,
69 pub x: u16,
71 pub y: u16,
73 pub weight: u8,
75 pub misc: u8,
77}
78
79pub struct MultiTouch {
81 pub detected: bool,
82 pub touch_x: [u16; 2],
84 pub touch_y: [u16; 2],
86 pub touch_weight: [u16; 2],
88 pub touch_area: [u16; 2],
90}
91
92#[derive(Debug)]
93pub enum GestureKind {
95 None,
97 Up,
99 Right,
101 Down,
103 Left,
105 ZoomIn,
107 ZoomOut,
109 Fault,
111}
112
113#[allow(dead_code)]
132pub struct GestureInit<I2C> {
133 addr: u8,
134 i2c: PhantomData<I2C>,
135
136 pub radian: u8,
138 pub offset_left_right: u8,
140 pub offset_up_down: u8,
142 pub distance_left_right: u8,
144 pub distance_up_down: u8,
146 pub distance_zoom: u8,
148}
149
150pub struct Ft6X06<I2C, TouchInterruptPin> {
153 i2c: PhantomData<I2C>,
154 addr: u8,
155 interrupt: TouchInterruptPin,
156}
157
158pub fn long_hard_reset<'a, RST, DELAY>(
165 rst: &'a mut RST,
166 delay: &'a mut DELAY,
167) -> Result<(), &'a str>
168where
169 RST: OutputPin,
170 DELAY: DelayUs<u32>,
171{
172 rst.set_low().map_err(|_| "rst.set_low failed")?;
173 delay.delay_us(10_000);
174 rst.set_high().map_err(|_| "rst.set_high failed")?;
175
176 Ok(())
177}
178
179impl<I2C, TouchInterruptPin: hal::digital::v2::InputPin, E> Ft6X06<I2C, TouchInterruptPin>
180where
181 I2C: i2c::WriteRead<Error = E> + i2c::Write<Error = E>,
182 E: core::fmt::Debug,
183{
184 pub fn new(_i2c: &I2C, addr: u8, interrupt: TouchInterruptPin) -> Result<Self, E> {
188 let ft6x06 = Ft6X06 {
189 i2c: PhantomData,
190 addr: addr,
191 interrupt,
192 };
193 Ok(ft6x06)
194 }
195
196 pub fn init(&mut self, i2c: &mut I2C, delay_source: &mut impl DelayMs<u32>) {
199 if FT6X06_AUTO_CALIBRATION_ENABLED {
201 self.ts_calibration(i2c, delay_source).unwrap();
202 }
203 }
206
207 pub fn delay_ms(&mut self, delay_source: &mut impl DelayMs<u32>, delay: u32) {
210 delay_source.delay_ms(delay);
211 }
212
213 pub fn get_capabilities(&self) -> Ft6x06Capabilities {
216 FT6X06_CAPABILITIES
217 }
218
219 pub fn dev_mode_r(&self, i2c: &mut I2C) -> Result<u8, E> {
221 let mut buf: [u8; 1] = [0];
222
223 i2c.write_read(self.addr, &[FT6X06_DEV_MODE_REG], &mut buf)?;
224
225 let mut value = buf[0];
226 value &= FT6X06_DEV_MODE_BIT_MASK;
227 value &= FT6X06_DEV_MODE_BIT_POSITION;
228
229 Ok(value)
230 }
231
232 pub fn dev_mode_w(&self, i2c: &mut I2C, value: u8) -> Result<bool, E> {
234 let mut buf: [u8; 1] = [0];
235
236 i2c.write_read(self.addr, &[FT6X06_DEV_MODE_REG], &mut buf)?;
237
238 let mut tmp = buf[0];
239
240 tmp &= !FT6X06_DEV_MODE_BIT_MASK;
241 tmp |= value << FT6X06_DEV_MODE_BIT_POSITION;
242
243 i2c.write(self.addr, &[tmp])?;
244
245 Ok(value == 0)
246 }
247
248 pub fn get_u8_reg(&self, i2c: &mut I2C, reg: u8) -> Result<u8, E> {
250 let mut ibuf: [u8; 1] = [0];
251 i2c.write_read(self.addr, &[reg], &mut ibuf)?;
252 Ok(ibuf[0])
253 }
254
255 pub fn set_u8_reg(&self, i2c: &mut I2C, reg: u8, val: u8) -> Result<(), E> {
257 let obuf: [u8; 2] = [reg, val];
258 i2c.write(self.addr, &obuf)?;
259 Ok(())
260 }
261
262 pub fn wait_touch_interrupt(&self) {
264 while self
265 .interrupt
266 .is_high()
267 .unwrap_or_else(|_| panic!("trouble checking interrupt"))
268 {}
269 }
270
271 pub fn ts_calibration(
273 &mut self,
274 i2c: &mut I2C,
275 delay_source: &mut impl DelayMs<u32>,
276 ) -> Result<bool, &str> {
277 let mut _ret = FT6X06_OK;
279 let mut _nbr_attempt: u32;
280 let mut _read_data: u8;
281 let mut _end_calibration: u8;
282
283 let _result = self.dev_mode_w(i2c, FT6X06_DEV_MODE_FACTORY);
284
285 delay_source.delay_ms(300);
286
287 for _attempt in 0..100 {
288 match self.dev_mode_r(i2c) {
289 Err(_e) => return Err("Bad comms in ts_calibration"),
290 Ok(n) => {
291 if n == FT6X06_DEV_MODE_WORKING {
292 return Ok(true);
293 }
294 }
295 }
296 delay_source.delay_ms(200);
297 }
298 Err("Calibration does not return")
299 }
300
301 pub fn td_status(&self, i2c: &mut I2C) -> Result<u8, E> {
303 let mut buf: [u8; 1] = [0];
304 i2c.write_read(self.addr, &[FT6X06_TD_STAT_REG], &mut buf)?;
305 Ok(buf[0])
306 }
307
308 pub fn chip_id(&self, i2c: &mut I2C) -> Result<u8, &str> {
311 let mut buf: [u8; 1] = [0];
312 match i2c.write_read(self.addr, &[FT6X06_CHIP_ID_REG], &mut buf) {
313 Err(_e) => Err("Chip ID call failed"),
314 Ok(_a) => {
315 if buf[0] != FT6X06_ID {
316 Err("error in chip ID")
317 } else {
318 Ok(buf[0])
319 }
320 }
321 }
322 }
323
324 pub fn detect_touch(&mut self, i2c: &mut I2C) -> Result<u8, E> {
326 let ntouch = loop {
327 let n = self.td_status(i2c)?;
328 if n > 0 {
329 break n;
330 }
331 };
332 assert!(ntouch <= FT6X06_MAX_NB_TOUCH as u8);
333 Ok(ntouch)
334 }
335
336 pub fn firmware_id(&mut self, i2c: &mut I2C) -> Result<u8, &str> {
338 let mut buf: [u8; 1] = [0];
339 match i2c.write_read(self.addr, &[FT6X06_FIRMID_REG], &mut buf) {
340 Err(_e) => Err("Error getting firmware ID"),
341 Ok(_d) => Ok(buf[0]),
342 }
343 }
344
345 pub fn gesture_radian_read(&mut self, i2c: &mut I2C) -> Result<u8, &str> {
347 let mut buf: [u8; 1] = [0];
348 match i2c.write_read(self.addr, &[FT6X06_RADIAN_VALUE_REG], &mut buf) {
349 Err(_e) => Err("Error getting Gesture Init: RADIAN VALUE REG"),
350 Ok(_d) => Ok(buf[0]),
351 }
352 }
353
354 pub fn gesture_radian_write(&self, i2c: &mut I2C, value: u8) -> Result<bool, E> {
356 let mut buf: [u8; 1] = [value];
357
358 i2c.write_read(self.addr, &[FT6X06_RADIAN_VALUE_REG], &mut buf)?;
359
360 Ok(value == 0)
361 }
362
363 pub fn get_touch(&mut self, i2c: &mut I2C, touch_i: u8) -> Result<TouchState, E> {
366 let mut buf: [u8; 6] = [0; 6];
367 i2c.write_read(self.addr, &[FT6X06_P1_XH_REG + 6 * (touch_i - 1)], &mut buf)?;
368
369 let x: u16 = (FT6X06_P1_XH_TP_BIT_MASK & buf[0]) as u16 * 256 + buf[1] as u16;
371 let y: u16 = (FT6X06_P1_YH_TP_BIT_MASK & buf[2]) as u16 * 256 + buf[3] as u16;
372
373 Ok(TouchState {
374 detected: true,
375 x,
376 y,
377 weight: buf[4],
378 misc: buf[5],
379 })
380 }
381
382 pub fn get_multi_touch(&mut self, i2c: &mut I2C, touch_i: u8) -> Result<MultiTouch, E> {
385 let mut buf: [u8; 12] = [0; 12];
386 i2c.write_read(self.addr, &[FT6X06_P1_XH_REG + 6 * (touch_i - 1)], &mut buf)?;
387
388 let mut x: [u16; FT6X06_MAX_NB_TOUCH] = [0; FT6X06_MAX_NB_TOUCH];
389 let mut y: [u16; FT6X06_MAX_NB_TOUCH] = [0; FT6X06_MAX_NB_TOUCH];
390 let mut weight: [u16; FT6X06_MAX_NB_TOUCH] = [0; FT6X06_MAX_NB_TOUCH];
391 let mut misc: [u16; FT6X06_MAX_NB_TOUCH] = [0; FT6X06_MAX_NB_TOUCH];
392
393 let mut it: usize = 0;
394 for i in 0..FT6X06_MAX_NB_TOUCH {
395 x[i] = (FT6X06_P1_XH_TP_BIT_MASK & buf[0 + it]) as u16 * 256 + buf[1 + it] as u16;
396 y[i] = (FT6X06_P1_YH_TP_BIT_MASK & buf[2 + it]) as u16 * 256 + buf[3 + it] as u16;
397 weight[i] = buf[4 + it] as u16;
398 misc[i] = buf[5 + it] as u16;
399 it = it + 6;
400 }
401
402 Ok(MultiTouch {
403 detected: true,
404 touch_x: x,
405 touch_y: y,
406 touch_weight: weight,
407 touch_area: misc,
408 })
409 }
410
411 pub fn get_gesture(&mut self, i2c: &mut I2C) -> Result<GestureKind, E> {
413 let mut buf: [u8; 1] = [0];
414 i2c.write_read(self.addr, &[FT6X06_GEST_ID_REG], &mut buf)?;
415
416 let g: GestureKind = match buf[0] {
417 FT6X06_GEST_ID_NO_GESTURE => GestureKind::None,
418 FT6X06_GEST_ID_MOVE_UP => GestureKind::Up,
419 FT6X06_GEST_ID_MOVE_RIGHT => GestureKind::Right,
420 FT6X06_GEST_ID_MOVE_DOWN => GestureKind::Down,
421 FT6X06_GEST_ID_MOVE_LEFT => GestureKind::Left,
422 FT6X06_GEST_ID_ZOOM_IN => GestureKind::ZoomIn,
423 FT6X06_GEST_ID_ZOOM_OUT => GestureKind::ZoomOut,
424 _ => GestureKind::Fault,
425 };
426 Ok(g)
427 }
428
429 pub fn get_coordinates(&mut self, i2c: &mut I2C) -> Result<(u16, u16), E> {
430 self.wait_touch_interrupt();
431 let _ntouch = self.detect_touch(i2c)?;
432 let pt = self.get_touch(i2c, 1)?;
433 Ok((pt.x, pt.y))
434 }
435
436 }