Repository navigation
Conversation
The WS2812 strip on KBHE 75HE snakes back on every other row, so the rainbow wave ran backwards on half the board and host frames landed on the wrong keys. Keyboards can now declare led_index_map, led_position and key_to_led. The core, the effects and the RAW HID bridge address LEDs in one stable logical order and only the buffer handed to the backend is written in chain order; the rainbow wave spreads its phase along the board's X axis. Boards that declare none of the three keep the previous behaviour.
Owner
|
Thank you for submitting the PR. I'm not sure when I will have the time to review it, but can you help me split the PR into STM32F723 support -> gamepad -> RGB, so it is easier for me to review? |
Author
|
Yeah sure no problem |
This was referenced Aug 25, 2026
Author
|
Split as requested:
Both open replacement PRs include architecture, compatibility/migration details and Linux build measurements. I am closing this draft monolith as superseded; no work is being discarded. |
Author
|
Superseded by the split review series described above. |
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
This PR is a concrete, reviewable implementation of the two proposals discussed in #6 and #11:
The intent is to keep the library concerns small and explicit. RGB policy lives in a portable core, physical signaling lives behind a backend API, and keyboards without an
rgbsection do not compile the core, allocate its frame buffers, or schedule its task. HID gamepad is an alternative USB presentation of the existing gamepad model, not a second input engine.Important
This is opened as a Draft/RFC because both issue threads requested design discussion before adoption, the maintainer does not have this hardware, and the power/topology/configurator decisions below still need agreement. The branch is implemented so the proposal can be reviewed and measured concretely; Draft status is not a claim that the KBHE image is already safe to flash without bring-up.
This PR addresses #6 and #11. I am deliberately not using closing keywords because the hmkconf UI and physical KBHE bring-up should be agreed/validated before either issue is considered fully complete.
Scope at a glance
stm32f723xxhardware support andkeyboards/kbhe-75he/keyboard.json.How this answers the concerns raised in #6
gamepadApisand, when enabled, RGB LED count/protocol/effect capabilities. The RAW HID protocol also has explicit capability negotiation, so a host never guesses support from a VID/PID alone. I have kept the hmkconf UI out of this firmware PR so the firmware/API can be reviewed first. A separate hmkconf PR can consume the metadata and present per-key versus underglow UI appropriately. The protocol is already exercised by the KBHE configurator and a standalone Python client linked below.KBHE 75HE support
keyboards/kbhe-75he/keyboard.jsondescribes the production keyboard rather than a synthetic test target:9172:0004so this image cannot be confused with the KBHE native application or updater.The new STM32F723 driver provides board/clock/USB setup, ADC + DMA mux scanning, flash, CRC32, timer, bootloader jump, serial number, and the RGB backend. USB, ADC, and RGB IRQ priorities are explicit. Instruction cache is enabled; data cache is disabled by default to keep DMA coherency predictable, while the DMA buffers retain aligned cache maintenance for downstream boards that deliberately re-enable it.
This makes the target complete at the firmware/build level: it uses normal libhmk profiles, layers, calibration, advanced keys, macros, RAW HID configuration, and the selected gamepad API. It is not a wrapper around the native KBHE firmware.
RGB architecture
1. Compile-time opt-in and backend boundary
An optional
rgbobject inkeyboard.jsonsupplies:The generator defines
RGB_ENABLEand backend constants only for such keyboards.include/hardware/rgb_api.his intentionally small:The portable renderer never knows about WS2812 GRB wire order, timers, or DMA. The first backend converts logical RGB to GRB and uses TIM2 PWM + DMA. Supporting a different MCU or LED transport means implementing that four-function backend, not modifying the effect/command code.
Non-RGB builds retain only the six-byte persistent RGB slot introduced by the common v1.6 configuration layout; they do not contain the renderer, frame buffers, task, commands, or hardware backend. Keeping the slot in the common layout prevents firmware variants from interpreting the same stored configuration at different offsets.
2. Effects and persistence
Portable effect IDs are:
01237Enable state, brightness, autonomous effect, and base color use libhmk's existing configuration write path. A persistent write is completed before the runtime state is published, so a failed write does not leave RAM and storage reporting different values. Live mode remembers the previous autonomous effect for restore, but live pixels and live effect selection are never written to flash. Streaming therefore cannot create flash traffic or wear.
3. Host-controlled per-LED frames
The 64-byte RAW HID bridge uses byte 0 for the command, byte 1 for status/reserved, and payload from byte 2. Hosts must start with
GET_RGB_CAPABILITIES(0x7F), which returns protocol version, LED count, bytes per pixel, maximum chunk size, live-effect ID, capability bits, and logical color order.Commands cover:
An 82-pixel frame is 246 bytes and travels as four 60-byte chunks plus one six-byte chunk. Upload is transactional:
This prevents dropped, duplicated, reordered, or late reports from displaying a half-old/half-new frame. The shared protocol and reference client are documented in the KBHE repository:
HID gamepad architecture
The HID implementation deliberately shares libhmk's existing gamepad data rather than adding parallel mappings, as suggested in #11.
eeconfig_get_gamepad_api()resolves one of disabled, XInput, or HID.COMMAND_SET_OPTIONSrejects mutually enabled XInput/HID flags.layout_task()feeds the same button assignments and Hall-effect analog states for either API.For HID, the existing XInput model maps to four signed stick axes, two trigger axes, an eight-direction hat, and eleven buttons. Opposing D-pad directions cancel on each axis before hat conversion. HID Y axes use the conventional positive-down orientation. Duplicate physical button mappings are aggregated from scratch each matrix pass so releasing one key cannot release a still-held duplicate mapping.
USB descriptors expose exactly one optional gamepad interface in the final interface slot:
Changing the setting requires re-enumeration/reboot because it changes the USB descriptor set. The device advertises USB 2.1 only when the XInput BOS path is present and USB 2.0 otherwise. The XInput OUT endpoint is continuously re-armed so host rumble/output reports cannot get stuck retrying, even though rumble behavior itself remains out of scope.
Persistence, compatibility, and generation
mtime=0, then writes only when content changes. This removes random/generated churn and makes repeated builds reproducible.bIntervalnow uses the correct exponent encoding (4for one millisecond / 1 kHz); full-speed behavior is unchanged.Validation performed
All tests/builds below were run from commit
57074ac3e790ca5b1446aaa3aaef5b5f60afbabe:kbhe-75heSTM32F723 release build: 44,216 bytes Flash / 26,232 bytes RAM;he60STM32F446 non-RGB regression build: 38,848 bytes Flash / 14,420 bytes RAM;-Wall -Wextra -Werrorand passed;git diff --checkpasses.Opening this PR should also run the repository's complete keyboard build matrix on Linux.
Decisions requested before marking ready
keyboard.jsongain a board-specific maximum brightness or milliamp budget which the core clamps independently of host requests?Hardware validation still required
The KBHE image is compile-validated, but I have not marked the following as verified without a physical board:
Until those checks pass, this should be treated as a reviewable hardware port rather than a claim that flashing is risk-free. A recoverable ST-Link/ROM-DFU path should be used for first bring-up.
Suggested review order
include/rgb.h,include/hardware/rgb_api.h,src/rgb.c— portable contract and state machine.src/commands.c,include/commands.h— negotiated RAW HID surface.include/eeconfig.h,src/migration.c— compatibility and v1.6 migration.src/usb_descriptors.c,src/xinput.c— mutually exclusive XInput/HID presentation and shared data path.scripts/schema/keyboard.py,scripts/make.py,scripts/metadata.py— opt-in generation/metadata.src/hardware/stm32f723xx/,hardware/stm32f723xx/board_def.h,keyboards/kbhe-75he/keyboard.json— KBHE hardware port.I am happy to split the hardware target, generic RGB core, and HID gamepad into separate commits/PRs if that makes upstream review easier; they are kept modular in the code even though this branch demonstrates them together.