FT6336U Capacitive Touch Controller Driver (ft6336u-dd)
This crate provides a no_std driver for the FocalTech FT6336U capacitive touch controller, a self-capacitance touch panel controller supporting up to 2 simultaneous touch points. The driver leverages the device-driver crate with a declarative YAML manifest (device.yaml) for a type-safe register map definition covering 27 registers.
Overview
The ft6336u-dd driver offers:
- Declarative Configuration: The FT6336U register map is defined in
device.yaml, enablingdevice-driverto generate a type-safe, low-level register access API. - Unified Async/Blocking API: Uses the
bisynccrate to provide both asynchronous (Ft6336uAsync) and blocking (Ft6336u) drivers from the same codebase, with no feature flags required. - High-Level and Low-Level APIs:
- High-level methods simplify tasks like scanning touch points and configuring thresholds.
- Low-level API (via the
llfield) offers direct, type-safe access to all registers defined indevice.yaml.
- Efficient I2C:
scan()reads 2 touch points in a single 13-byte I2C transaction. no_stdandno-alloc: Optimized for bare-metal and RTOS environments.- Optional Logging: Supports
defmtand thelogfacade for debugging.
Getting Started
-
Add
ft6336u-ddtoCargo.toml:[] = "0.1.0" # For blocking usage (Ft6336u): = "1.0.0" # For async usage (Ft6336uAsync): = "1.0.0"Note: Add the relevant
embedded-halcrate for your use case, no need for both. -
Instantiate the driver and scan for touches:
-
Blocking:
use ; let mut touch = new; let data = touch.scan?; for point in &data.points -
Async:
use ; let mut touch = new; let data = touch.scan.await?; for point in &data.points
-
Configuration
use PowerModeEnum;
// Set touch sensitivity (lower = more sensitive)
touch.write_touch_threshold?;
// Set report rate in active mode (Hz)
touch.write_active_rate?;
// Enter hibernate mode
touch.write_power_mode?;
Low-Level API Usage
The driver provides direct access to all FT6336U registers through the low-level API via touch.ll. This API is automatically generated from device.yaml and provides type-safe access to all register fields.
Reading Registers
Use .read() to read a register and access its fields:
// Read chip ID
let chip_id = touch.ll.chip_id.read?;
assert_eq!; // FT6336U
// Read power mode
let power = touch.ll.power_mode.read?;
let mode = power.mode; // Returns PowerModeEnum
Writing Registers
Use .write() with a closure to set register fields:
// Set touch threshold
touch.ll.threshold.write?;
// Set interrupt mode to trigger
touch.ll.g_mode.write?;
Modifying Registers
Use .modify() to read-modify-write, preserving other fields:
touch.ll.device_mode.modify?;
Async Low-Level API
The low-level API has async versions for use with Ft6336uAsync. Simply append _async to the method name:
let chip_id = touch.ll.chip_id.read_async.await?;
touch.ll.threshold.write_async.await?;
Finding Register/Field Names
- Check
device.yaml- All registers and fields are documented there - Use IDE autocomplete - Type
touch.ll.to see all available registers - Read a register - Use
.read()then autocomplete to see available field getters - Write a register - The closure parameter has autocomplete for all setters
Scan Behavior
scan() performs a single 13-byte I2C read (registers 0x02-0x0E) and returns TouchData containing:
touch_count: number of active touch points (0-2)points: array of 2TouchPoints, each with:status:Touch(new press),Stream(continued contact), orReleasex,y: 12-bit coordinates
The driver tracks touch state internally: the first scan detecting a finger reports Touch, subsequent scans report Stream, and when the finger lifts, Release.
Register Map
The FT6336U register map is defined in device.yaml, which device-driver uses to generate Rust code. This file specifies:
- Register names, addresses, and sizes
- Field names, bit positions, and access modes (Read-Only, Read-Write)
- Enumerations for field values (e.g., gesture IDs, power modes, touch events)
- Descriptions based on the datasheet
Hardware Notes
- I2C address:
0x38(available asFT6336U_I2C_ADDRESS) - I2C speed: up to 400kHz
- Supply voltage: 2.8V-3.3V
- The driver does not manage reset or interrupt pins. Handle these in your application/BSP according to your board's wiring (GPIO, PMIC, I2C expander, etc.)
- Reset sequence: pull RST low for at least 5ms, release, wait at least 300ms before communicating
Feature Flags
default = []: No default features; async and blocking drivers are always available.std: Enablesstdfeatures forthiserror.log: Enableslogfacade logging.defmt: Enablesdefmtlogging anddefmt::Formatderives on all types.
License
This project is dual-licensed under the MIT License or Apache License 2.0, at your option.