QMK firmware for a 62-key split ergonomic keyboard built on the Cosmos platform with Lemon Wired (RP2040) controllers and Pumpkin Patch PCBs. Uses Vial for runtime key remapping.
QMK uses multiple config files at two levels. Settings at the keymap level override the keyboard level.
| File | Purpose |
|---|---|
keyboard.json |
Primary hardware config: matrix pins, USB IDs, processor, split settings, enabled features, and physical key positions (x/y coordinates + matrix mapping). This is the "data-driven" config — QMK's modern approach. |
config.h |
C #defines for settings that don't have JSON equivalents: USART serial config (SERIAL_USART_FULL_DUPLEX, TX/RX pins), split handedness (EE_HANDS), and newer QMK features (SPECULATIVE_HOLD). |
rules.mk |
Makefile variables for build flags. Currently empty since all features are set in keyboard.json. |
| File | Purpose |
|---|---|
keymap.c |
The actual key assignments — what each key does on each layer. This is the default keymap compiled into firmware (Vial overrides it at runtime via EEPROM). |
keymap.json |
Community module configuration. Lists which QMK community modules to include in the build. |
config.h |
Vial-specific C defines: VIAL_KEYBOARD_UID and VIAL_UNLOCK_COMBO_*. These must be C preprocessor defines — no JSON equivalent. |
rules.mk |
Build flags for Vial (VIA_ENABLE, VIAL_ENABLE, LTO_ENABLE). These are Vial-fork-specific and can't move to keyboard.json. |
vial.json |
Visual layout definition consumed by the Vial desktop app. Tells Vial how to render the keyboard in its GUI. |
keyboard.json, config.h, and rules.mk overlap in concept but not in practice:
keyboard.jsonhandles everything QMK's data-driven system supports (pins, USB, features, physical layout).config.his required for settings that only exist as C#defines — especially USART serial configuration and features likeSPECULATIVE_HOLDthat haven't been added to the JSON schema yet.rules.mkis required for Vial-fork build flags that aren't part of QMK's feature system.
The physical layout appears in three places, each serving a different consumer:
| File | What It Defines | Consumed By |
|---|---|---|
keyboard.json → layouts |
Physical key positions + matrix wiring | QMK compiler (maps LAYOUT() macro args to the electrical matrix) |
vial.json → layouts |
Visual key positions | Vial GUI app (renders the keyboard on screen) |
keymap.c |
Logical key assignments | QMK compiler (what each key does) |
If the physical layout changes (keys added/removed, matrix rewired), both keyboard.json and vial.json must be updated. keymap.c only changes when key assignments change.
Firmware is built automatically via GitHub Actions on every push. Release artifacts (UF2 files) are published:
# One-time setup: clones vial-qmk, symlinks keyboard config, installs community modules
./scripts/setup.sh
# Build both halves
./scripts/build.sh
# → build/csmos-left.uf2, build/csmos-right.uf2Requires the QMK CLI (qmk). The setup script clones vial-qmk to .vial-qmk/ and installs getreuer's community modules to .vial-qmk/modules/getreuer/.
Double-tap the reset button on the controller to enter bootloader mode or hold the bootmagic key (lower left-most key), then copy the .uf2 file to the mounted drive. Flash each half separately.
The default keymap in keymap.c is what the keyboard loads when EEPROM is empty (e.g., after a fresh flash). At runtime, Vial stores your remapped layout in EEPROM, overriding keymap.c.
To make a Vial layout the new compiled default:
- Export your layout from Vial as a
.vilfile (save tolayout.vilin the project root) - Run
python3 scripts/vil2c.pyto generate the new keymap - Replace
keyboards/cosmos/csmos/keymaps/default/keymap.cwith the output:python3 scripts/vil2c.py > keyboards/cosmos/csmos/keymaps/default/keymap.c
