From 0072ffb788ff4838e7144889d828e6940c80e91d Mon Sep 17 00:00:00 2001 From: afiqzudinhadi Date: Wed, 1 Jul 2026 15:53:07 +0800 Subject: [PATCH] Add README for v1.0.0 --- README.md | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..aeb88b8 --- /dev/null +++ b/README.md @@ -0,0 +1,192 @@ +# zmk-rgb-effects + +Modular RGB effects for ZMK keyboards. Provides per-key per-layer RGB indicators and a framework for adding custom effects without forking ZMK. + +Requires: [ZMK fork](https://github.com/afiqzudinhadi/zmk) branch `rgb-modular-v1.0` (modular effect registration API). + +## Setup + +Add to your `west.yml`: + +```yaml +manifest: + remotes: + - name: afiqzudinhadi + url-base: https://github.com/afiqzudinhadi + projects: + - name: zmk + remote: afiqzudinhadi + revision: rgb-modular-v1.0 + import: app/west.yml + - name: zmk-rgb-effects + remote: afiqzudinhadi + revision: v1.0.0 +``` + +Enable in your `.conf`: + +``` +CONFIG_ZMK_RGB_UNDERGLOW=y +CONFIG_ZMK_RGB_EFFECT_LAYER=y +``` + +## Per-key layer effect + +Define per-key colors in your keymap/overlay using devicetree: + +```dts +#include + +/ { + underglow-layer { + compatible = "zmk,underglow-layer"; + pixel-lookup = < + 5 4 3 2 1 0 + 6 7 8 9 10 11 + 17 16 15 14 13 12 + >; + + layer0 { + layer-id = <0>; + bindings = < + &ugc RGB_RED &ugc RGB_RED &ugc RGB_OFF ... + >; + }; + + layer1 { + layer-id = <1>; + bindings = < + &ugc RGB_BLUE &ugc RGB_BLUE &ugc RGB_OFF ... + >; + }; + }; +}; +``` + +### Properties + +- `pixel-lookup` — maps LED chain index to key position +- `layer-id` — which keymap layer this color map applies to +- `bindings` — color per key using behaviors below + +### Behaviors + +| Behavior | Description | Params | +|----------|-------------|--------| +| `&ugc` | Static color | `param1` = RGB hex color | +| `&ubi` | Battery indicator | `param1` = low color, `param2` = ok color, `threshold` DT prop | +| `&ugi` | HID indicator (caps/num/scroll lock) | `param1` = off color, `param2` = on color, `indicator` DT prop | + +## Adding custom effects + +Create a `.c` file with `ZMK_RGB_EFFECT_DEFINE`: + +```c +#include + +static void my_render(struct zmk_rgb_effect_ctx *ctx) { + for (int i = 0; i < ctx->num_pixels; i++) { + struct zmk_led_hsb hsb = ctx->base_color; + hsb.h = (*ctx->animation_step + i * 30) % 360; + ctx->pixels[i] = zmk_rgb_hsb_to_rgb(zmk_rgb_hsb_scale_min_max(hsb)); + } + *ctx->animation_step += ctx->animation_speed; +} + +ZMK_RGB_EFFECT_DEFINE(my_effect, "My Effect", + my_render, 0, NULL, NULL); +``` + +Add to `CMakeLists.txt`: + +```cmake +target_sources(app PRIVATE src/effects/my_effect.c) +``` + +The effect auto-registers via linker section. Accessible by cycling with `RGB_EFF`. + +### As a separate module repo + +You can also create effects in their own repo without modifying this module: + +``` +my-zmk-rgb-rainbow/ +├── zephyr/ +│ └── module.yml +├── CMakeLists.txt +├── Kconfig +└── src/ + └── rainbow.c +``` + +`zephyr/module.yml`: +```yaml +build: + cmake: . + kconfig: Kconfig +``` + +`Kconfig`: +``` +config ZMK_RGB_EFFECT_RAINBOW + bool "Rainbow RGB effect" + depends on ZMK_RGB_UNDERGLOW + default y +``` + +`CMakeLists.txt`: +```cmake +if(CONFIG_ZMK_RGB_EFFECT_RAINBOW) + target_sources(app PRIVATE src/rainbow.c) +endif() +``` + +`src/rainbow.c` uses `ZMK_RGB_EFFECT_DEFINE` exactly as above. + +Add to your `west.yml`: +```yaml +- name: my-zmk-rgb-rainbow + remote: your-github-remote + revision: main +``` + +Requires the ZMK fork with the modular effect API (`rgb-modular-v1.0` or later). No dependency on this module. + +### Effect flags + +| Flag | Description | +|------|-------------| +| `0` | Animated — core runs render at 25ms tick | +| `ZMK_RGB_EFFECT_STATIC` | No periodic tick — render called on demand via `zmk_rgb_request_refresh()` | + +### Effect callbacks + +| Callback | When called | +|----------|-------------| +| `render` | Each tick (animated) or on refresh (static) | +| `on_select` | Effect becomes active | +| `on_deselect` | User cycles to different effect | + +### Render context + +| Field | Type | Description | +|-------|------|-------------| +| `pixels` | `struct led_rgb *` | LED buffer to write | +| `num_pixels` | `uint16_t` | Strip length | +| `base_color` | `struct zmk_led_hsb` | User-configured HSB color | +| `animation_step` | `uint16_t *` | Read/write animation counter | +| `animation_speed` | `uint8_t` | User-configured speed (1-5) | + +### Utility functions + +- `zmk_rgb_hsb_to_rgb(hsb)` — HSB to RGB conversion +- `zmk_rgb_hsb_scale_min_max(hsb)` — scale brightness to configured min/max +- `zmk_rgb_hsb_scale_zero_max(hsb)` — scale brightness from 0 to max +- `zmk_rgb_request_refresh()` — trigger re-render for static effects + +## Versioning + +`vX.Y.Z` where: +- **X** — major version (breaking API changes) +- **Y** — ZMK core dependency version (matches `rgb-modular-vX.Y`) +- **Z** — custom effects (0 = defaults only, 1+ = custom effects included)