Skip to the content
PCBKitNew board
2 layers88 × 55 mmKbdrelay carrier v0.1, the printed circuit board in 3D

Kbdrelay carrier v0.1

mdthorpe/kbdrelay

Project for replicating USB HID messages over SPI

Size
88 × 55 mm
Copper layers
2
Thickness
1.6 mm
Parts
22
Nets
41
Pads
74
Tracks, vias
73, 0
Pours
1
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
10 Aug 2026
Updated
19 Sep 2026

Overview

Kbdrelay carrier v0.1 is an open-source printed circuit board by mdthorpe, from the mdthorpe/kbdrelay repository on GitHub. It is a 2-layer board of 88 × 55 mm with 22 parts on 41 nets, routed with 73 tracks and 0 vias.

Its parts include 9 resistors, 3 connectors, 2 capacitors, 2 ICs and 1 diode. It belongs with the ESP32 boards of this library.

README

README.md

kbdrelay — USB HID keyboard bridge

A transparent two-board bridge that lets any USB keyboard type into a target device as if it were a plain USB 1.1 boot-protocol keyboard. Two cheap single-USB-controller boards, joined by a short SPI harness.

  • KBD — keyboard-facing board (USB host, SPI master). The keyboard plugs into it; it reads key events and forwards them.
  • TGT — target-facing board (USB device, SPI slave). It plugs into the target machine and presents as a vanilla boot keyboard, replaying what KBD sends.

Boards are named for what they face. "Sender/receiver" is banned vocabulary here — both boards send and receive over the bidirectional SPI link.

See spec.md (what/why), plan.md (how), and tasks.md (build log / progress).

Status

v1 achieved on the bench — typing crosses the bridge, Caps/Num Lock LEDs round-trip, hot-plug recovers, and the whole chain was validated on a Commodore Amiga 1200 (1992) via a USB keyboard adapter, with modern and vintage keyboards. Verified: AC1–AC5 (see tasks.md for caveats).

Hardware

  • 2× Waveshare ESP32-S3-Zero (one KBD, one TGT).
  • Onboard WS2812 status LED (GPIO21, RGB order).
  • Power: KBD from a dedicated 5 V feed (bus power / USB-PD); TGT from the target machine's USB. Grounds common; 5 V never merged (FR5).
  • Keyboard-power inrush needs a bulk cap (~220–1000 µF) on KBD's 5 V.

SPI harness (wire same-name to same-name — SPI names encode direction)

SignalKBD (master)TGT (slave)Notes
SCKGPIO4 (GP4)GPIO41 MHz
MOSIGPIO5 (GP5)GPIO5key reports, heartbeats →
MISOGPIO6 (GP6)GPIO6← LED reports
CSGPIO7 (GP7)GPIO7
DATA_READYGPIO8 (in)GPIO8 (out)TGT signals a queued LED report
GNDGNDGNDcommon

Put ~470 Ω (→2.2 kΩ recommended) in series on each signal line — limits backfeed between boards when one is unpowered (FR5.4) and tames ringing.

Firmware

ESP-IDF 6.x via PlatformIO (framework = espidf). Shared framing + CRC lives in components/bridge_proto (also unit- tested on the host). One project, one env per firmware:

envboard rolewhat it is
kbdKBDUSB host → reads keyboard → SPI master forwards KEY_REPORTs
tgtTGTSPI slave → replays as boot keyboard; watchdog releases keys
mock_kbdtestSPI-master stand-in (scaffold)
mock_tgttestSPI-slave stand-in (scaffold)
nativehostbridge_proto unit tests (no hardware)

SPI protocol

Fixed 12-byte frames, full-duplex: SYNC(0xA5) TYPE SEQ PAYLOAD[8] CRC8. Types: IDLE, KEY_REPORT (KBD→TGT), LED_REPORT (TGT→KBD), HEARTBEAT. KBD sends on key change or every 25 ms; TGT releases all keys if no valid frame for 75 ms (FR4.1).

Build / flash / test

sh
make build ENV=kbd        # compile (kbd | tgt | mock_kbd | mock_tgt)
make upload ENV=kbd       # flash over USB-C (see flashing quirks below)
make monitor              # serial monitor on the USB-UART adapter
make test                 # host unit tests (native, no hardware)
make reconfigure ENV=kbd  # clean rebuild of one env

Toolchain: PlatformIO Core (Python 3.13 penv) + ESP-IDF 6.x, board def boards/waveshare_esp32_s3_zero.json (the official platform doesn't ship it).

S3-Zero flashing quirks

  • Download mode: hold RESET + BOOT, release RESET, pause, release BOOT.
  • After flashing, physically reset (unplug/replug or RESET) — a software reset over native USB does not boot the app.
  • Logs go over UART (TX/RX pads, 3.3 V USB-UART adapter, 115200): the USB-C is used by the app (host on KBD, device on TGT), and USB-Serial/JTAG shares the S3's USB PHY. Console is forced to UART (CONFIG_ESP_CONSOLE_UART_DEFAULT).
  • Power-up order on the bench: power TGT (into the target) before KBD.

License

TBD.

Parts

22
QtyValueFootprintReferences
52.2kResistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR1, R2, R3, R4, R5
41kResistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR6, R7, R8, R9
4MountingHole_3.2mm_M3MountingHole_3.2mm_M3H1, H2, H3, H4
2ESP32-S3-Zerokbdrelay:ESP32-S3-Zero-SocketedU1, U2
1100nFCapacitor_THT:C_Disc_D5.0mm_W2.5mm_P5.00mmC2
11N5817Diode_THT:D_DO-201AD_P12.70mm_HorizontalD1
1470uF/16VCapacitor_THT:CP_Radial_D10.0mm_P5.00mmC1
15V_INConnector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_VerticalJ3
1PPTC 0.9A 60R090kbdrelay:PPTC_Littelfuse_60R_P5.08mmF1
1UART_KBDConnector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_VerticalJ1
1UART_TGTConnector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_VerticalJ2

Questions

How big is the Kbdrelay carrier v0.1 PCB?

It measures 88 × 55 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Kbdrelay carrier v0.1 use?

22 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Kbdrelay carrier v0.1 KiCad files?

From the mdthorpe/kbdrelay repository on GitHub, at the commit this page was made from: the board is hardware/pcb-carrier/kbdrelay-carrier/kbdrelay-carrier-v0.1.kicad_pcb and its schematic hardware/pcb-carrier/kbdrelay-carrier/kbdrelay-carrier.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Kbdrelay carrier v0.1 design in my own project?

Its repository states no licence, so its author keeps all rights: ask mdthorpe before reusing the design.

Similar boards

  • 2 layers158 × 11 mmDaylight Matchstick, the printed circuit board in 3D

    Daylight Matchstick

    VoronDesign/Voron-Hardware

    Cool Hardware designed by the Voron Design group

    22 parts1.1kGPL-3.0
  • 2 layers57 × 65 mmRgb to hdmi, the printed circuit board in 3D

    Rgb to hdmi

    hoglet67/RGBtoHDMI

    Bare-metal Raspberry Pi project that provides pixel-perfect sampling of Retro Computer RGB/YUV video and conversion to HDMI

    22 parts1kGPL-3.0
  • 2 layers81 × 57.2 mmRP2040-Macropad, the printed circuit board in 3D

    RP2040-Macropad

    hackclub/OnBoard

    💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

    22 parts915
  • 2 layers54.6 × 70.9 mmBeagleLogic Cape, the printed circuit board in 3D

    BeagleLogic Cape

    abhishek-kakkar/BeagleLogic

    A Software Suite that implements a logic analyzer with the PRU on the BeagleBone / BeagleBone Black.

    22 parts479GPL-3.0
  • 2 layers66.4 × 24.5 mmConnecting piece, the printed circuit board in 3D

    Connecting piece

    Chrismettal/flipper-zero-backpacks

    Backpack-style addon boards for the Flipper Zero!

    22 parts456
  • 2 layers51 × 70 mmDMG A04-01, the printed circuit board in 3D

    DMG A04-01

    HDR/NintendoPCBs

    Replacement pcb's for Nintendo games.

    22 parts321
  • 2 layers27.8 × 16 mmSpi 1v8 level shifter, the printed circuit board in 3D

    Spi 1v8 level shifter

    CRImier/MyKiCad

    My KiCad boards. Can't be bothered uploading individually anymore, so here you go.

    22 parts253GPL-3.0