|
|
@@ -0,0 +1,170 @@
|
|
|
+# Impact 80 Zone-Aware Lighting Effects Design
|
|
|
+
|
|
|
+## Status
|
|
|
+
|
|
|
+Approved design for implementing the complete Impact 80 VIA lighting catalog in the CLI.
|
|
|
+
|
|
|
+## Goals
|
|
|
+
|
|
|
+- Expose every effect documented by the Impact 80 VIA definition.
|
|
|
+- Apply RGB commands to Logo, Backlight, and Side lighting by default.
|
|
|
+- Allow `--zone logo`, `--zone backlight`, or `--zone side` to target one zone.
|
|
|
+- Keep effect IDs channel-specific and prevent generic QMK IDs from being sent to the wrong zone.
|
|
|
+- Preserve machine-readable output and existing top-level `rgb info` fields.
|
|
|
+
|
|
|
+## Non-goals
|
|
|
+
|
|
|
+- No EEPROM save command or persistent profile storage.
|
|
|
+- No macOS or Windows HID backend.
|
|
|
+- No completion of an independent Rainy 75 effect catalog.
|
|
|
+- No changes to the QMK v12 Raw HID transport.
|
|
|
+
|
|
|
+## Zone model
|
|
|
+
|
|
|
+The Impact 80 has three VIA lighting channels:
|
|
|
+
|
|
|
+| Zone | CLI name | VIA channel | Effect catalog |
|
|
|
+|---|---|---:|---|
|
|
|
+| Logo | `logo` | 2 | 7 effects |
|
|
|
+| Backlight | `backlight` | 3 | 46 effects including `none` |
|
|
|
+| Side | `side` | 4 | 7 effects |
|
|
|
+
|
|
|
+The `--zone` flag is persistent on the `rgb` command. If omitted, commands target all three zones in this order: Logo, Backlight, Side.
|
|
|
+
|
|
|
+## Effect catalog
|
|
|
+
|
|
|
+The canonical effect table is zone-aware. Logo and Side use:
|
|
|
+
|
|
|
+| ID | Name |
|
|
|
+|---:|---|
|
|
|
+| 0 | `none` |
|
|
|
+| 1 | `wave` |
|
|
|
+| 2 | `fixed_wave` |
|
|
|
+| 3 | `spectrum` |
|
|
|
+| 4 | `breathing` |
|
|
|
+| 5 | `light` |
|
|
|
+| 6 | `shutdown` |
|
|
|
+
|
|
|
+Backlight uses the complete official catalog:
|
|
|
+
|
|
|
+| ID | Name | ID | Name |
|
|
|
+|---:|---|---:|---|
|
|
|
+| 0 | `none` | 23 | `flower_blooming` |
|
|
|
+| 1 | `solid_color` | 24 | `raindrops` |
|
|
|
+| 2 | `alphas_mods` | 25 | `jellybean_raindrops` |
|
|
|
+| 3 | `gradient_up_down` | 26 | `hue_breathing` |
|
|
|
+| 4 | `gradient_left_right` | 27 | `hue_pendulum` |
|
|
|
+| 5 | `breathing` | 28 | `hue_wave` |
|
|
|
+| 6 | `band_sat` | 29 | `pixel_flow` |
|
|
|
+| 7 | `band_val` | 30 | `digital_rain` |
|
|
|
+| 8 | `band_pinwheel_sat` | 31 | `solid_reactive` |
|
|
|
+| 9 | `band_pinwheel_val` | 32 | `solid_reactive_wide` |
|
|
|
+| 10 | `band_spiral_sat` | 33 | `solid_reactive_multiwide` |
|
|
|
+| 11 | `band_spiral_val` | 34 | `solid_reactive_cross` |
|
|
|
+| 12 | `cycle_all` | 35 | `solid_reactive_multicross` |
|
|
|
+| 13 | `cycle_left_right` | 36 | `solid_reactive_nexus` |
|
|
|
+| 14 | `cycle_up_down` | 37 | `solid_reactive_multinexus` |
|
|
|
+| 15 | `cycle_out_in` | 38 | `splash` |
|
|
|
+| 16 | `cycle_out_in_dual` | 39 | `multisplash` |
|
|
|
+| 17 | `rainbow_moving_chevron` | 40 | `solid_splash` |
|
|
|
+| 18 | `cycle_pinwheel` | 41 | `solid_multisplash` |
|
|
|
+| 19 | `cycle_spiral` | 42 | `starlight` |
|
|
|
+| 20 | `dual_beacon` | 43 | `starlight_dual_hue` |
|
|
|
+| 21 | `rainbow_beacon` | 44 | `starlight_dual_sat` |
|
|
|
+| 22 | `rainbow_pinwheels` | 45 | `riverflow` |
|
|
|
+
|
|
|
+The Backlight catalog follows the QMK RGB Matrix effect names. ID 41 is exposed as `solid_multisplash`, distinct from `multisplash` at ID 39.
|
|
|
+
|
|
|
+## Name resolution
|
|
|
+
|
|
|
+`rgb effect <name>` resolves a canonical name or alias independently for each target zone.
|
|
|
+
|
|
|
+Supported compatibility aliases:
|
|
|
+
|
|
|
+- `off` → `none`
|
|
|
+- `breathe` → `breathing`
|
|
|
+- `rainbow_wave` → `wave` for Logo/Side
|
|
|
+- `rainbow` → `spectrum` for Logo/Side and `rainbow_moving_chevron` for Backlight
|
|
|
+- `solid` → `light` for Logo/Side and `solid_color` for Backlight
|
|
|
+
|
|
|
+If no `--zone` is supplied and an effect is unsupported by one or more zones, the supported zones receive the command and a warning names every skipped zone. If `--zone` is supplied and the effect is unsupported there, the command fails without sending a report.
|
|
|
+
|
|
|
+Unknown effect names fail before opening the device.
|
|
|
+
|
|
|
+## CLI behavior
|
|
|
+
|
|
|
+All zone-aware commands use the same target resolver:
|
|
|
+
|
|
|
+```text
|
|
|
+wobkey rgb effect breathing
|
|
|
+wobkey rgb effect rainbow_moving_chevron
|
|
|
+wobkey rgb effect rainbow_moving_chevron --zone backlight
|
|
|
+wobkey rgb brightness 160
|
|
|
+wobkey rgb brightness 160 --zone logo
|
|
|
+wobkey rgb color 00ff00
|
|
|
+wobkey rgb speed 2 --zone side
|
|
|
+wobkey rgb disable
|
|
|
+wobkey rgb enable
|
|
|
+```
|
|
|
+
|
|
|
+- `effect`: sends the zone-specific Effect value (`0x02`).
|
|
|
+- `brightness`: sends Brightness (`0x01`) to selected zones.
|
|
|
+- `speed`: sends Effect Speed (`0x03`) to selected zones.
|
|
|
+- `color`: sends Color (`0x04`) to selected zones.
|
|
|
+- `disable`: sends Effect `0` and Brightness `0` to selected zones.
|
|
|
+- `enable`: enables each selected zone with its default breathing effect: Logo `4`, Backlight `5`, Side `4`, then Brightness `160`.
|
|
|
+- `mode <index>` remains a raw numeric escape hatch and applies the supplied ID to selected zones; names are preferred because IDs differ by zone.
|
|
|
+
|
|
|
+## Info output
|
|
|
+
|
|
|
+`rgb info` queries all selected zones and emits a `zones` array. Each entry contains:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "zone": "logo",
|
|
|
+ "channel": 2,
|
|
|
+ "enabled": true,
|
|
|
+ "effect": "breathing",
|
|
|
+ "effectId": 4,
|
|
|
+ "brightness": 160,
|
|
|
+ "speed": 2,
|
|
|
+ "color": {"hue": 0, "saturation": 255}
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+The existing top-level `enabled`, `mode`, `brightness`, and `speed` fields remain as a compatibility summary of the first selected zone (Logo when no zone is specified). If a zone cannot be queried, its entry contains an `error` string and the process exits non-zero after preserving the other zone results in JSON.
|
|
|
+
|
|
|
+## Component boundaries
|
|
|
+
|
|
|
+- `internal/rgb`: zone names, canonical effect definitions, aliases, and zone-specific value lookup.
|
|
|
+- `internal/via`: Raw HID transport and channel/value writes; no CLI policy or effect names.
|
|
|
+- `cmd/wobkey/rgb`: Cobra flag parsing, target-zone selection, warnings, JSON presentation, and exit status.
|
|
|
+- `keyboards.json`: remains device identity/configuration metadata; effect definitions are code-owned because they are protocol semantics, not user preferences.
|
|
|
+
|
|
|
+## Error handling
|
|
|
+
|
|
|
+- Invalid `--zone`, unknown effect names, and unsupported explicit-zone effects return errors before any HID write.
|
|
|
+- Read timeouts remain bounded by the existing 500 ms hidraw timeout.
|
|
|
+- Set acknowledgements are validated for command, channel, and value ID.
|
|
|
+- Default-target warnings go to stderr; machine-readable stdout remains valid JSON for `info`.
|
|
|
+
|
|
|
+## Testing strategy
|
|
|
+
|
|
|
+Implementation follows TDD:
|
|
|
+
|
|
|
+1. Table-driven tests for every canonical Backlight effect and the Logo/Side catalog.
|
|
|
+2. Alias resolution tests for all supported aliases and zone-specific aliases.
|
|
|
+3. Target resolver tests for default-all, explicit-zone, invalid-zone, and unsupported-effect behavior.
|
|
|
+4. Fake-transport tests asserting one 32-byte report per selected zone and the correct channel/value.
|
|
|
+5. CLI tests for inherited `--zone` and warning/error behavior.
|
|
|
+6. Full `go test ./...`, `go vet ./...`, `gofmt`, and `go build` verification.
|
|
|
+7. Hardware smoke tests on the connected Impact 80: discovery, `effect`, `info`, `color`, `disable`, and `enable`.
|
|
|
+
|
|
|
+## Acceptance criteria
|
|
|
+
|
|
|
+- Every official Impact 80 effect name can be selected.
|
|
|
+- A command without `--zone` reaches all compatible zones.
|
|
|
+- A command with `--zone` reaches exactly one zone.
|
|
|
+- Unsupported effects never produce a wrong-zone report.
|
|
|
+- `rgb info` reports all selected zones and retains the compatibility summary.
|
|
|
+- Existing hardware smoke tests continue to pass.
|