Skip to content

esp32_touch

Capacitive touch sensor: ten channels (T0–T9) sharing pads with GPIO.

Each channel measures a pad’s capacitance by counting how many fixed-slope charge/discharge cycles fit into a fixed measurement window: a finger adds capacitance, the pad charges slower, and the count drops. This driver covers the software-triggered, polled single measurement — configure once, trigger one conversion, wait for it, read the count — which is all a button poll or a self-test needs.

The FSM timer that scans channels on its own, the touch interrupt and its threshold comparators, and touch as a deep-sleep wake source (a separate RTC path, deferred alongside the other wake sources in soc_esp32::sleep). This is the on-demand measurement primitive; the rest builds on it.

  • Channels 8 and 9 are swapped in the enable mask, the status bits, and the readout — but not in the per-pad slope register. Channel::swapped applies the swap where the hardware wants it; getting it wrong reads the wrong pad for T8/T9 and is silent on T0–T7.
  • Even channel → high half-word, odd channel → low half-word of the shared SAR_TOUCH_OUT pair. A wrong half reads a neighbour’s count.

DR_REG_RTCIO_BASE = 0x3FF48400, DR_REG_SENS_BASE = 0x3FF48800, from esp-idf soc/soc.h. Fields from soc/sens_reg.h and soc/rtc_io_reg.h; the sequence from hal/esp32/include/hal/touch_sensor_ll.h and driver/esp32/touch_sensor.c. A SW single-shot touches only SENS and RTCIO — no RTCCNTL, no FSM timer, no interrupts.

Register Address Fields used
SENS_SAR_TOUCH_CTRL1 0x3FF48858 MEAS_DELAY [15:0], XPD_WAIT [23:16]
SENS_SAR_TOUCH_CTRL2 0x3FF48884 MEAS_DONE 10, START_FSM_EN 11, START_EN 12, START_FORCE 13
SENS_SAR_TOUCH_ENABLE 0x3FF4888C PAD_WORKEN [9:0]
SENS_SAR_TOUCH_OUT1..5 0x3FF48870+4k 16-bit count per channel, hi/lo half
RTC_IO_TOUCH_CFG 0x3FF48490 DREFL [28:27], DRANGE [26:25], DREFH [30:29]
RTC_IO_TOUCH_PAD0..9 0x3FF48494+4N DAC [25:23], TIE_OPT 21, MUX_SEL 19, FUN_IE 13, RUE 27, RDE 28
struct Touch { /* private fields */ }

The touch controller. One owner keeps the shared measurement registers consistent across channels.

enum Channel {
T0,
T1,
T2,
T3,
T4,
T5,
T6,
T7,
T8,
T9,
}

A touch channel, named by its Tn number. Each maps to one fixed GPIO.

Implements: Clone, Copy, Debug, Eq, PartialEq, StructuralPartialEq

enum TouchError {
Timeout,
}

A conversion could not be completed.

Implements: Clone, Copy, Debug, Eq, From, PartialEq, StructuralPartialEq