On this page

XPT2046 Controller & Calibration

Operating principle

The XPT2046 is a 4-wire resistive touch controller built around a 12-bit successive-approximation ADC. When the panel is pressed, the flexible top layer meets the rigid bottom layer and forms a resistive divider across the X and Y planes, which the controller digitises.

SPI control byte

The Pico sends one control byte per measurement:

  • 0xD0 reads the X plane, differential, 12-bit
  • 0x90 reads the Y plane, differential, 12-bit

The controller answers with two bytes carrying the 12-bit result (0 to 4095). Both targets read the bus at 1 MHz, mode 0, MSB first; the bus configuration is in Hardware.

Calibration table

The overlay has manufacturing tolerances, so raw ADC counts at the panel edges do not span the full 0 to 4095 range. The limits below were measured on a 4-wire panel and are shared by both targets:

AxisRaw ADC minimumRaw ADC maximumScreen range
X15037840 to 799
Y27737840 to 479

Mapping

The firmware maps a raw reading onto the screen range and clamps the result to the panel bounds:

ScreenX = (RawX - X_MIN) * 800 / (X_MAX - X_MIN),  clamped to 0..799
ScreenY = (RawY - Y_MIN) * 480 / (Y_MAX - Y_MIN),  clamped to 0..479

Recalibration

A different panel needs different limits. Turn on the UART debug output, touch each screen corner in turn and read the raw ADC values, then update X_MIN, X_MAX, Y_MIN and Y_MAX in the source file of the firmware being built. Each target carries its own copy of the constants, so a panel change means editing both. See Diagnostics for the serial setup.