# GT9x Touch Screen Controller Driver
[](https://crates.io/crates/gt9x)
[](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) 目录以获取更完整的使用示例。