Firmware Development
The PolyKybd firmware is a heavily customised QMK build that runs on the keyboard’s Raspberry Pi RP2040. Two hardware variants share a single firmware codebase: split72 (72-key, RGB matrix, Cirque trackpad, 128×64 status OLED) and split42 (42-key CRKBD footprint, no RGB/trackpad, 128×32 status OLED).
Repository structure
Section titled “Repository structure”The firmware lives on the PolyKybd branch of the QMK fork: github.com/thpoll83/qmk_firmware, under keyboards/polykybd/.
keyboards/polykybd/├── config.h — pin assignments, PROTOCOL_VERSION, feature flags├── halconf.h — HAL configuration (RP2040)├── mcuconf.h — MCU configuration├── rules.mk — build flags, enabled QMK features├── poly_keymap.c — shared keymap logic for BOTH variants:│ rendering, HID/overlay handling, language│ selection, idle/suspend, split-sync glue,│ firmware-update state machine, QMK callbacks├── hid_com.c — raw_hid_receive(): HID command dispatcher│ (21 command IDs, 0x01–0x15)├── fill_overlay.c — receives overlay segments, RLE decompress├── split_sync.c — CRC32-validated split-half synchronisation├── state.c — shared state structs (EEPROM-persisted)├── multicore_exec.c — core1 service loop: overlay decompression and region jobs├── base/│ ├── overlay.c — overlay image pool (600 × 360 B), addressed via│ │ 90 keys × 16 modifier variants│ └── disp_array.c — per-keycap OLED driver├── lang/│ └── lang_lut.c — language lookup table (code-generated via cog)├── split72/ — variant: keymaps/, header, layout data└── split42/ — variant: keymaps/, header, layout dataAll behaviour lives in the keyboard-level poly_keymap.c (compiled for both variants via rules.mk). Each variant’s <variant>/keymaps/default/keymap.c is data only — keymaps[], encoder_map[], and (on RGB variants) g_led_config. A feature added to poly_keymap.c applies to both keyboards at once, so they always stay the same. The legacy polykybd.c / polykybd.h still exist, but the bulk of the logic now lives in poly_keymap.c.
Setting up the dev environment
Section titled “Setting up the dev environment”# Clone and switch to the PolyKybd branchgit clone https://github.com/thpoll83/qmk_firmware.gitcd qmk_firmwaregit checkout PolyKybd
# Pull in the git submodules (empty in a fresh clone)make git-submodule
# Install the ARM toolchain (this is what `qmk setup` installs on Debian/Ubuntu)sudo apt-get install -y gcc-arm-none-eabi binutils-arm-none-eabi
# Install the QMK CLI (the pip package is just the bootstrapper;# the full CLI lives in this repo's lib/python)pip install qmkpip install -r requirements.txt
# Point QMK at this cloneqmk config user.qmk_home=$(pwd)Building
Section titled “Building”Build a specific variant — split72 or split42:
qmk compile -kb polykybd/split72 -km default# or equivalently:make polykybd/split72:defaultThe build writes the .uf2 to the repo root and .build/. The .uf2 is used for manual bootloader-drive recovery — see Flashing the Firmware.
Producing a .bin for HID flashing
Section titled “Producing a .bin for HID flashing”The deliverable for in-place flashing over HID (via PolyKybdHost’s firmware updater) is the raw RP2040 .bin, not the .uf2. Convert the build’s ELF:
arm-none-eabi-objcopy -O binary .build/polykybd_split72_default.elf \ .build/polykybd_split72_default.binPolyKybdHost flashes this raw image over the HID firmware-update protocol; the .uf2 is only needed if you have to recover through the RP2040 bootloader drive.
System clock
Section titled “System clock”The firmware runs the RP2040 at 200 MHz with the core voltage raised to 1.15 V. -e POLYKYBD_SYS_CLK=125 builds the old 125 MHz image. The measurements and how the build sets the clock are on 200 MHz System Clock.
Firmware signing
Section titled “Firmware signing”Released firmware is signed with Ed25519, and the keyboard checks the signature before it installs an update over HID. A build you compiled yourself is unsigned: either sign it with tools/sign_firmware.py, or flash it and press A on the keyboard when it asks. The full workflow, key rotation and the DOOM pack signature are on Firmware Signing.
Adding a new keymap
Section titled “Adding a new keymap”qmk new-keymap -kb polykybd/split72 -km my_keymap# Edit keyboards/polykybd/split72/keymaps/my_keymap/keymap.cqmk compile -kb polykybd/split72 -km my_keymapKeep keymap files data only — behaviour belongs in the shared poly_keymap.c so both variants stay in sync.
Display rendering
Section titled “Display rendering”The per-key OLED displays (72×40 px monochrome) are driven via a custom Adafruit GFX fork. The rendering and overlay logic lives in poly_keymap.c / base/disp_array.c.
See Display Graphics & Fonts for the rendering pipeline and the font-generation workflow.
QMK documentation
Section titled “QMK documentation”All standard QMK features are available. PolyKybd firmware v0.11.6 is built on QMK 0.33.13. Note that QMK’s documentation site is not versioned — there is one live copy — so when upstream behaviour has changed between releases, check the breaking-changes history rather than assuming a page matches your build.
The fork tracks upstream’s stable release tags, not master — merging a tag
means the base is a version people can look up, rather than an arbitrary commit.
To check the base of any checkout yourself, rather than trusting this page:
# The fork's own master is kept as an untouched mirror of upstream QMK,# so no extra remote is needed — the clone above already has it as origin.git fetch origin master --tagsbase="$(git merge-base HEAD origin/master)"[ -n "$base" ] || { echo "no merge base — unshallow the clone first" >&2; exit 1; }git describe --tags --abbrev=0 "$base"Refer to the official docs for: