Step-by-step guide
Build Instructions
Everything you need to assemble, wire, and install firmware — from parts list to first boot.
Parts List
Gather the following components. All parts are available from Adafruit, Digi-Key, or similar suppliers.
| Component | Details | Notes |
|---|---|---|
| Adafruit Feather ESP32-S3 Rev TFT | #5691 | Built-in 240×135 TFT display |
| 3.5mm Stereo Jack Breakout (×2) | TRRS or TRS, panel-mount | For A1 (nav) and A2 (select) |
| Accessibility switches (×1 or ×2) | Any 3.5mm momentary assistive switch | Wired to GND, normally open |
| Small enclosure | Any project box ≥ 80×50mm or 3D printed files | 3D print or off-the-shelf |
| USB-C cable | Data-capable | For firmware install and USB HID |
Wiring & Pin Connections
Both switch inputs use internal pull-up resistors — a pressed switch reads LOW (False).
| Pin | Role | Wiring | Logic |
|---|---|---|---|
| A1 | Navigate switch | Tip → A1, Sleeve → GND | Active LOW (Pull.UP) |
| A2 | Select / Single switch | Tip → A2, Sleeve → GND | Active LOW (Pull.UP) |
| GND | Ground reference | Sleeve of both jacks | – |
| D0 | Onboard — Direct Switch Interface | Built-in button | Active LOW (Pull.UP) |
| D1 | Onboard — single-switch mode | Built-in button | Active HIGH (Pull.DOWN) |
| D2 | Onboard — two-switch mode | Built-in button | Active HIGH (Pull.DOWN) |
Install CircuitPython
The firmware requires CircuitPython 10 or later.
- Download the latest
.UF2for Feather ESP32-S3 Rev TFT from circuitpython.org. - Enter bootloader by clicking the RESET button— the drive
FTHRS3BOOTappears. - Drag and drop the
.UF2file ontoFTHRS3BOOT. The board reboots automatically. - A drive named
CIRCUITPYappears — you're ready to copy files.
Install Libraries
Copy these from the CircuitPython Library Bundle into the lib/ folder on CIRCUITPY:
adafruit_st7789— TFT display driveradafruit_display_text— on-screen labelsadafruit_hid— USB HID keyboard emulation
Install Firmware Files
Download code.py from the GitHub repository and copy it to the root of CIRCUITPY. It runs automatically on every boot.
Video walkthrough
code.py — CircuitPython runs this filename on boot. Place config.py alongside it to override defaults (see Step 6).
Configuration (optional)
Without a config.py the device uses built-in defaults. To customise:
- Open the Shortcut Configurator in your browser.
- Select your OS and adjust shortcuts and timing as needed.
- Click Generate config.py then Download config.py.
- Copy the file to the root of
CIRCUITPY— the device reloads automatically.
The import block in code.py (placed after KEYCODES / KEY_SYMBOLS):
First Boot
Power via USB. The TFT shows the mode-select screen with three zones:
- Left — D0 — Direct Switch Mode (Mode 0)
- Centre — D1 / A2 — Single-switch scanning mode
- Right — D2 / A1 — Two-switch direct mode
Press the relevant onboard button or external switch to enter a mode. To return to the mode-select screen, press the board's RESET button. In Mode 0 you can also hold an external switch for 1.5 s to exit (useful when the onboard buttons aren't reachable).
Switch Modes Reference
Single-Switch (A2)
One switch controls everything — short press to select, hold to auto-scan.
Two-Switch (A1 + A2)
Separate navigate and select switches for faster, direct control.
Direct Switch Mode
Mode 0 maps each external switch directly to a single, immediate action — no scanning or navigation required. It is designed for users who need a simple, low-effort input method or who want to control mouse and media functions with their switches.
Direct Switch (Mode 0)
Each switch fires one action immediately on press. Default: Switch 1 = Enter, Switch 2 = Tab. Fully configurable in the Shortcut Configurator.
How to enter Mode 0
| Method | How | Best for |
|---|---|---|
| D0 | Press onboard D0 button at mode-select screen | Initial setup, tester access |
| Double-click | Double-click either external switch (A1 or A2) at the mode-select screen within 0.4 s | Users who cannot reach onboard buttons |
config.py | Run run_direct_switch_mode() as the first call in the main loop | Dedicated single-purpose device |
How to exit Mode 0
| Method | How | Best for |
|---|---|---|
| Hold a switch | Hold A1 or A2 for 1.5 s — a short tap still fires the action, only a long hold exits | Users who entered by double-click |
| RESET | Press the board's onboard RESET button | When the board is reachable |
Supported action types
| Type | What it does | Example |
|---|---|---|
| Keyboard key | Press (and release) any key or key combo | Enter, Tab, Ctrl+C, Cmd+Space |
| Mouse click | Left, right, or middle button click | Left click for activation |
| Mouse scroll | Scroll up or down by N ticks per press | Scroll down a page |
| Mouse move | Move pointer by X/Y pixels per press | Nudge cursor right |
| Media control | Play/pause, volume, track skip, mute, brightness | Play/pause music |
config.py onto your device.
Display (optional)
The Feather ESP32-S3 TFT has a small built-in display that shows the active shortcut, next shortcut and connection status. Users with low vision may benefit from the Display Tool as an alternative to the small onboard screen. The web app tool provides a larger, high contrast, more readable interface for displaying information and text to speech support if enabled.
Watch the walkthrough below for a live demo of the display in action.