Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.zerokeyusb.com/llms.txt

Use this file to discover all available pages before exploring further.

ZeroKeyUSB replaces mechanical buttons with five copper touch pads connected to a dedicated TS06 capacitive controller. The firmware polls this controller over I²C and translates touches into navigation events.

Hardware overview

ComponentDetail
ControllerTS06 — 6-channel capacitive touch IC
I²C address0xD2 >> 1 = 0x69
Pads used5 of 6 channels: Left, Right, Up, Down, Center
Status register0x25 — bitmask of currently touched channels
SensitivitySet to 0x3F (minimum) on channels 0–2 at boot to avoid false triggers
The controller handles baseline calibration internally and reports which channels are active via the status register.

Touch initialization

At startup (zerokey-setup.cpp), the firmware:
  1. Probes the TS06 at 0x69 with up to 5 retries (20 ms apart).
  2. If detected, writes minimum sensitivity (0x3F) to registers 0x00–0x02.
  3. Configures operation mode via registers 0x05–0x06.
  4. Sets ts06_ok = true — if the controller isn’t found, touch is disabled and the serial log shows "TS06 not found on I2C".

Polling cycle

The handleButtonChecker() method runs in the main loop:
  1. Reads STATUS_REGISTER (0x25) via readRegister() over I²C.
  2. For each channel bit:
    • Records pressStartTime when a channel first becomes active.
    • Applies a 80 ms debounce (DEBOUNCE_MS) — releases shorter than this are ignored.
    • Enforces a 150 ms channel lockout (CHANNEL_LOCKOUT_MS) — touching a different pad while one is active is ignored.
  3. On release:
    • If held > LONG_PRESS_THRESHOLD (800 ms) → dispatches long-press handler.
    • Otherwise → dispatches short-press handler.

Gesture mapping

GestureTriggerMain screenEditorMenu
Tap Left< 800 msPrevious slotMove cursor leftGo back / Exit submenu
Tap Right< 800 msNext slotMove cursor right / Enter keyboardEnter submenu / Exit to credentials
Tap Up< 800 msCycle to Site viewChange characterNavigate up
Tap Down< 800 msCycle to 2FA viewSwitch keyboard pageNavigate down
Tap Center< 800 msType credential to hostInsert characterSelect / Confirm
Hold Left≥ 800 msJump 10 slots back
Hold Right≥ 800 msJump 10 slots forward
Hold Center≥ 800 msEnter edit modeSave and exit editorAuthorize import/export

Long-press visual feedback

When a long press is in progress, drawLongPressProgress() renders a filling progress bar on the OLED screen. This gives the user visual confirmation that they should keep holding. Releasing before 800 ms cancels the action.

PIN screen controls

On the PIN entry screen, the controls change:
PadAction
Up / DownChange the current digit (0–9)
RightAdd the current digit to the PIN (up to 16 digits)
LeftDelete the last entered digit
CenterSubmit the PIN for verification
Long-press CenterType the device serial number

Error handling

  • If the TS06 is not detected at boot, ts06_ok is set to false and the status register read returns 0x00 — effectively disabling touch input.
  • The firmware does not show a touch error screen; instead, the serial log reports the issue for debugging.
  • Touch is silently disabled during lockout delays (waitFromEeprom()) and during long-running operations like credential erasure.
The TS06 operates independently of EEPROM or ATECC608A operations. Since all share the same I²C bus at 100 kHz, touch polling is interleaved with other I²C traffic in the cooperative main loop.