Ah, the Config Registers (0x8047 to 0x80FF). This is where the GT911 shows its personality. You want to change the refresh rate? Swap the X/Y coordinates? Adjust the sensitivity for a thick glass lens? You have to write a 184-byte configuration array.
But here is the trap: Register 0x80FE is the Checksum, and 0x80FF is the Refresh Flag.
The datasheet says, "Calculate the checksum of bytes 0x8047 to 0x80FD, then store the low byte at 0x80FE." Fine. But then you write 0x01 to 0x80FF... and the GT911 throws a tantrum if your checksum is wrong. It will simply ignore your config and revert to its internal "dumb" defaults. I spent two hours debugging why my X/Y axes were swapped until I realized I had a classic off-by-one in my checksum loop. The GT911 does not forgive. It does not forget.
Typical startup config area (example offsets):
| Offset | Field | Typical value |
|--------|-------|----------------|
| 0x8048-0x804D | X/Y resolution | Depends on display |
| 0x8060 | Touch threshold | 0x46 (70 raw) |
| 0x8061 | Filter coefficient | 0x05 |
| 0x807C | I2C watchdog | 0x09 (9 sec) |
Important: After writing config, write
0x00to0x80FE(soft reset) and send0x01to0x8040(config update flag). gt911 register map
Just when the community thought they had the map memorized, Goodix released an update. The chip was now labeled GT9110 (sometimes called the "Red" series firmware).
The register map changed. The configuration offset 0x6A (which previously set the number of touch points) moved. The checksum calculation method changed. Suddenly, old drivers broke.
This forced the open-source community (particularly contributors to the Linux Kernel and projects like ESP32 Arduino core) to write "auto-detect" routines. The code had to probe the registers, trying to read the "Goodix" ID (GT911, GT9110, etc.) stored in the read-only memory area (around 0x8140 to 0x8143) to decide which map to use.
| Register | Description | |----------|-------------| | 0x80FE | Config checksum (calculated by host) | | 0x80FF | Config update flag (write 0x01 to reload config from host) |
After writing a new configuration block to 0x8040–0x80FD, you must: Ah, the Config Registers (0x8047 to 0x80FF)
The GT911 will then reset its touch engine with the new settings.
If you’ve worked with capacitive touch screens on Raspberry Pi, ESP32, or STM32 projects, you’ve likely encountered the GT911. This popular touch controller from Goodix is everywhere—from cheap 7-inch LCD displays to industrial HMI panels.
While the driver code is often copy-pasted from GitHub, understanding the register map is what separates "it works" from "I can debug and optimize it."
Let’s pull back the curtain and map out the GT911’s internal memory.
When a small startup or a hobbyist bought a GT911 breakout board, they were effectively handed a black box. They knew the chip spoke I2C, and they knew it had an interrupt pin, but the instruction set was a mystery. Important: After writing config, write 0x00 to 0x80FE
The GT911 has a complex initialization sequence. It wasn't enough to just ask it for data. You had to write a long configuration block to specific memory addresses just to tell the controller how many touch points to support or how sensitive to be. Without the map, developers were flying blind.
The GT911 (by Goodix) is a 5-point capacitive touch controller commonly found in displays (LCDs, LVDS, HDMI panels). Understanding its register map is key for debugging, calibration, or bare-metal drivers.
Need the full 200+ register guide? Download the GT911 Programming Guide (Goodix official).
Have you run into any GT911 quirks in your projects? Share below 👇