gt9x 0.1.0

A no_std driver for the GT9x series of capacitive touch screen controllers, supporting both async and blocking interfaces.
Documentation
# GT9x Touch Screen Controller Driver


[![](https://img.shields.io/crates/v/gt9x.svg)](https://crates.io/crates/gt9x)
[![](https://docs.rs/gt9x/badge.svg)](https://docs.rs/gt9x)

`no_std` driver for the GT9x series of capacitive touch screen controllers.

This crate provides a `no_std` driver for the GT9x series of capacitive touch screen controllers. It supports both asynchronous (`embedded-hal-async`) and blocking (`embedded-hal`) I2C communication. It also provides support for cache maintenance, which is useful for MCUs with data caches (like ARM Cortex-M7).

---

## English


### Supported Chips


- GT911 (5 points)
- GT928 (10 points)
- GT9147 (5 points)

### Features


- `async`: (Default) Enables the asynchronous driver based on `embedded-hal-async`.
- `blocking`: Enables the blocking driver based on `embedded-hal`.
- `defmt`: Enables logging with `defmt`.

### Usage


#### Asynchronous Driver


The asynchronous driver can be used with or without an interrupt pin.

##### Polling Mode


In polling mode, the driver will check the status register for new touch data in a loop.

```rust
// From example/src/bin/common.rs
use gt9x::{Gt911, Gt9x};

let mut gt9x = Gt9x::<Gt911, _, _, _>::new(i2c, &mut buf);
gt9x.init().await.unwrap();

loop {
    if let Ok(points) = gt9x.get_touches().await {
        // ... process points
    }
}
```

##### Interrupt Mode


In interrupt mode, the driver will wait for a rising edge on the interrupt pin before reading touch data. This is more efficient than polling.

```rust
// From example/src/bin/int.rs
use gt9x::{Gt911, Gt9x};

let mut gt9x_int = Gt9x::<Gt911, _, _, _>::new_int(i2c, &mut buf, int_pin);
gt9x_int.init().await.unwrap();

loop {
    if let Ok(points) = gt9x_int.get_touches().await {
        // ... process points
    }
}
```

#### Blocking Driver


The blocking driver polls the status register to get touch data.

```rust
// From example/src/bin/blocking.rs
use gt9x::{Gt911, Gt9xBlocking};

let mut gt9x = Gt9xBlocking::<Gt911, _>::new(i2c, &mut buf);
gt9x.init().unwrap();

loop {
    if let Ok(points) = gt9x.get_touches() {
        // ... process points
    }
}
```

#### Cache Maintenance


The buffer must be aligned to the cache line size, and its length must be a multiple of the alignment.

```rust
// From example/src/bin/int_cache.rs
use gt9x::{Gt9x, Gt9147, CacheMaintenance};

struct MyCache;
impl CacheMaintenance for MyCache {
    fn required_alignment(&self) -> Option<usize> {
        Some(32) // D-Cache line size for STM32H7
    }

    fn invalidate_dcache_by_slice(&self, slice: &mut [u8]) {
        // Invalidate D-Cache for the given slice
        // e.g., using cortex_m::SCB::invalidate_dcache_by_slice
    }
}

// Buffer needs to be aligned
#[repr(align(32))]

struct Aligned32<T>(T);
#[link_section = ".axisram"]

static mut BUF: Aligned32<[u8; 64]> = Aligned32([0; 64]);

let mut gt9x = Gt9x::new_int_cache(i2c, unsafe { &mut BUF.0 }, int_pin, MyCache);
```

See the [examples](example/src/bin) folder for more complete usage.

---

## 中文说明


### 支持的芯片


- GT911 (5点触摸)
- GT928 (10点触摸)
- GT9147 (5点触摸)

### 功能特性 (Features)


- `async`: (默认) 启用基于 `embedded-hal-async` 的异步驱动。
- `blocking`: 启用基于 `embedded-hal` 的阻塞驱动。
- `defmt`: 启用 `defmt` 日志。

### 使用方法


#### 异步驱动


异步驱动支持中断模式和轮询模式。

##### 轮询模式


在轮询模式下,驱动会循环查询状态寄存器以获取新的触摸数据。

```rust
// 来自 example/src/bin/common.rs
use gt9x::{Gt911, Gt9x};

let mut gt9x = Gt9x::<Gt911, _, _, _>::new(i2c, &mut buf);
gt9x.init().await.unwrap();

loop {
    if let Ok(points) = gt9x.get_touches().await {
        // ... 处理触摸点
    }
}
```

##### 中断模式


在中断模式下,驱动会等待中断引脚的上升沿信号,然后再读取触摸数据。这种方式比轮询更高效。

```rust
// 来自 example/src/bin/int.rs
use gt9x::{Gt911, Gt9x};

let mut gt9x_int = Gt9x::<Gt911, _, _, _>::new_int(i2c, &mut buf, int_pin);
gt9x_int.init().await.unwrap();

loop {
    if let Ok(points) = gt9x_int.get_touches().await {
        // ... 处理触摸点
    }
}
```

#### 阻塞驱动


阻塞驱动通过轮询状态寄存器来获取触摸数据。

```rust
// 来自 example/src/bin/blocking.rs
use gt9x::{Gt911, Gt9xBlocking};

let mut gt9x = Gt9xBlocking::<Gt911, _>::new(i2c, &mut buf);
gt9x.init().unwrap();

loop {
    if let Ok(points) = gt9x.get_touches() {
        // ... 处理触摸点
    }
}
```

#### 缓存维护 (Cache Maintenance)


对于带有数据缓存(Data Cache)的 MCU,提供给驱动所使用的缓冲区位于由缓存管理的内存区域时,可以实现 `CacheMaintenance` trait 来处理缓存失效操作。

缓冲区必须按缓存行大小对齐,并且其长度必须是该对齐值的倍数。

```rust
// 来自 example/src/bin/int_cache.rs
use gt9x::{Gt9x, Gt9147, CacheMaintenance};

struct MyCache;
impl CacheMaintenance for MyCache {
    fn required_alignment(&self) -> Option<usize> {
        Some(32) // STM32H7 的 D-Cache 行大小
    }

    fn invalidate_dcache_by_slice(&self, slice: &mut [u8]) {
        // 使给定的 slice 对应的 D-Cache 失效
        // 例如,使用 cortex_m::SCB::invalidate_dcache_by_slice
    }
}

// 缓冲区地址需要对齐
#[repr(align(32))]

struct Aligned32<T>(T);
#[link_section = ".axisram"]

static mut BUF: Aligned32<[u8; 64]> = Aligned32([0; 64]);// 缓冲区大小要对齐

// let i2c = ...;
// let int_pin = ...;

let mut gt9x = Gt9x::new_int_cache(i2c, unsafe { &mut BUF.0 }, int_pin, MyCache);
```

请参阅 [examples](example/src/bin) 目录以获取更完整的使用示例。