Skip to content

feat: moonlight — light-control module for upcycled keyboards - #8

Open
ezuk wants to merge 17 commits into
mainfrom
feat/moonlight
Open

feat: moonlight — light-control module for upcycled keyboards#8
ezuk wants to merge 17 commits into
mainfrom
feat/moonlight

Conversation

@ezuk

@ezuk ezuk commented Jul 15, 2026

Copy link
Copy Markdown

Turns a broken ZSA keyboard into a USB-powered room light. The board lights up on any power source — wall charger, power bank, or computer — with no enumeration needed, and by default never sends a keystroke to a host, so a shorting matrix can't type garbage.

How: the module's config.h defines NO_USB_STARTUP_CHECK, compiling out the ChibiOS suspend trap that otherwise parks un-enumerated boards in suspend_power_down() forever. Everything else is hooks: 19 keycodes (MNL_ON/OFF, brightness, hue, animation start/stop/next/faster/slower, 8 preset color slots) driving the standard rgb_matrix API, a keyboard_post_init that guarantees the lamp always comes on at power-up (with a brightness floor and a snap away from stale/reactive EEPROM modes), runtime exclusion of all keypress-reactive animations, and a pre_process_record that swallows every non-moonlight keycode except QK_BOOT.

Ships with ready-to-compile example keymaps for Voyager and Moonlander (rev B) and CI that builds both against firmware25.

Test plan

  • Both examples compile against firmware25 (CI green, 2 runs)
  • Keymap-level config override proven (-DMOONLIGHT_LAMP_ONLY=0 compile)
  • Hardware: boots lit from dumb charger; all keycodes; persistence + always-on power-up; lamp-only on a computer; reflash

ezuk added 17 commits July 15, 2026 09:12
…e light on

Module config.h is included before keymap config.h in QMK's config
chain, so a keymap-level #define MOONLIGHT_LAMP_ONLY 0 collided with
the module's own #ifndef default under -Werror. Move the tunable
#ifndef blocks (MOONLIGHT_LAMP_ONLY, MOONLIGHT_MIN_BOOT_BRIGHTNESS,
MOONLIGHT_MIN_BRIGHTNESS) from config.h into moonlight.c, alongside
the other already-there tunables, so a keymap's config.h define wins
as intended. config.h now only carries NO_USB_STARTUP_CHECK.

Also make presets turn the light on (rgb_matrix_enable() before
rgb_matrix_mode()), matching MOONLIGHT_ANIM_START's symmetry: press a
color, get that color, even if the light was off.
- README: note that hand-rolled keymap.json files must keep
  "modules": ["zsa/defaults", "zsa/moonlight"] (zsa/defaults is
  required by ZSA board code, not optional).
- README: fix the indices 54-71 prose describing moonlander_lamp.json's
  layers formatting — the lines actually group 5/1/1/5/3/3 entries, not
  one KC_NO per line.
  bring both up to date with the config.h -> moonlight.c move: tunables
  now default in moonlight.c, and presets also turn the light on.
- CI: add timeout-minutes: 30 and strategy.fail-fast: false to the
  build_moonlight workflow so a hung job can't block the run indefinitely
  and one matrix leg failing doesn't cancel the other.
- Spec doc: correct the "keymap config is included after module config"
  claim (it's the reverse) and describe the actual mechanism — tunables
  default in moonlight.c under #ifndef — plus the preset-enables-light
  behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant