docs: expand CLAUDE.md with K17 Max, branch names, and EEPROM notes
- Rename dev branch references from q5_dev to dev/q5; add dev/k17 for K17 Max work - Add K17 Max build/flash commands using the correct rgb subvariant path (keychron/k17_max/ansi_encoder/rgb) to distinguish from the white LED variant - Add EEPROM Layout Notes section documenting the Q5 Max address map, VIA_EEPROM_MAGIC_ADDR pinning rules, and EECONFIG_KB_DATA_SIZE #undef requirement - Add Keychron RGB section capturing lessons from the persistence work: when to call eeconfig_init_custom_rgb(), version stamp placement, kc_rgb_save() mode persistence, retail_demo_enable 0xFF bug, and extern array requirements - Add DIP Switch section explaining the frame overlay approach and why direct rgb_matrix_mode() calls must be avoided
This commit is contained in:
@@ -1,13 +1,16 @@
|
|||||||
# CLAUDE.md - QMK Development (Keychron Q5 Max)
|
# CLAUDE.md - QMK Development (Keychron Q5 Max / K17 Max)
|
||||||
|
|
||||||
Guidelines and commands for the customized Keychron Q5 Max firmware project based on the `wireless_playground` fork.
|
Guidelines and commands for the customized Keychron firmware project based on the `wireless_playground` fork.
|
||||||
|
|
||||||
## Project Scope
|
## Project Scope
|
||||||
|
|
||||||
* **Origin:** [git.rootiest.dev/rootiest/qmk_firmware](https://git.rootiest.dev/rootiest/qmk_firmware)
|
* **Origin:** [git.rootiest.dev/rootiest/qmk_firmware](https://git.rootiest.dev/rootiest/qmk_firmware)
|
||||||
* **Upstream:** [github.com/Keychron/qmk_firmware](https://github.com/Keychron/qmk_firmware) (branch: `wireless_playground`)
|
* **Upstream:** [github.com/Keychron/qmk_firmware](https://github.com/Keychron/qmk_firmware) (branch: `wireless_playground`)
|
||||||
* **Primary Keyboard:** Keychron Q5 Max (ANSI Encoder)
|
* **Primary Keyboard:** Keychron Q5 Max (ANSI Encoder)
|
||||||
* **Development Workflow:** Work is performed on the `q5_dev` branch before merging to `main`.
|
* **Secondary Keyboard:** Keychron K17 Max (occasionally)
|
||||||
|
* **Development Branches:**
|
||||||
|
* `dev/q5` — Q5 Max work-in-progress, merges to `main`
|
||||||
|
* `dev/k17` — K17 Max work-in-progress, merges to `main`
|
||||||
* **Feature Goals:** Tap-Dance, expanded layers, advanced Chording, Unicode support, and Auto-correct.
|
* **Feature Goals:** Tap-Dance, expanded layers, advanced Chording, Unicode support, and Auto-correct.
|
||||||
|
|
||||||
## Build and Flash Commands
|
## Build and Flash Commands
|
||||||
@@ -28,6 +31,9 @@ Every `qmk` command below assumes the venv is active (or prefix each with
|
|||||||
```bash
|
```bash
|
||||||
# Build the Q5 Max ANSI Encoder firmware
|
# Build the Q5 Max ANSI Encoder firmware
|
||||||
qmk compile -kb keychron/q5_max/ansi_encoder -km via
|
qmk compile -kb keychron/q5_max/ansi_encoder -km via
|
||||||
|
|
||||||
|
# Build the K17 Max firmware (rgb variant; separate 'white' LED variant exists)
|
||||||
|
qmk compile -kb keychron/k17_max/ansi_encoder/rgb -km via
|
||||||
```
|
```
|
||||||
|
|
||||||
### Flashing
|
### Flashing
|
||||||
@@ -35,6 +41,9 @@ qmk compile -kb keychron/q5_max/ansi_encoder -km via
|
|||||||
```bash
|
```bash
|
||||||
# Flash the Q5 Max (requires the board to be in bootloader mode)
|
# Flash the Q5 Max (requires the board to be in bootloader mode)
|
||||||
qmk flash -kb keychron/q5_max/ansi_encoder -km via
|
qmk flash -kb keychron/q5_max/ansi_encoder -km via
|
||||||
|
|
||||||
|
# Flash the K17 Max (requires the board to be in bootloader mode)
|
||||||
|
qmk flash -kb keychron/k17_max/ansi_encoder/rgb -km via
|
||||||
```
|
```
|
||||||
|
|
||||||
### Environment Setup
|
### Environment Setup
|
||||||
@@ -58,16 +67,41 @@ qmk config user.keymap=via
|
|||||||
|
|
||||||
## Development Workflow
|
## Development Workflow
|
||||||
|
|
||||||
1. Verify the current branch is `q5_dev`.
|
1. Verify the current branch is `dev/q5` (Q5 Max) or `dev/k17` (K17 Max).
|
||||||
2. Implement features in `keyboards/keychron/q5_max/ansi_encoder/keymaps/via/`.
|
2. Implement features in the relevant keymap directory:
|
||||||
|
* Q5 Max: `keyboards/keychron/q5_max/ansi_encoder/keymaps/via/`
|
||||||
|
* K17 Max: `keyboards/keychron/k17_max/ansi_encoder/rgb/keymaps/via/`
|
||||||
3. Test compilation locally before committing.
|
3. Test compilation locally before committing.
|
||||||
4. Ensure `rules.mk` has the necessary flags enabled (e.g., `TAP_DANCE_ENABLE = yes`, `UNICODE_ENABLE = yes`).
|
4. Ensure `rules.mk` has the necessary flags enabled (e.g., `TAP_DANCE_ENABLE = yes`, `UNICODE_ENABLE = yes`).
|
||||||
|
|
||||||
## Git Conventions
|
## Git Conventions
|
||||||
|
|
||||||
* Use conventional commits (`feat:`, `fix:`, `docs:`, `chore:`, etc.) scoped to the keyboard where relevant (e.g. `feat(q5_max):`).
|
* Use conventional commits (`feat:`, `fix:`, `docs:`, `chore:`, etc.) scoped to the keyboard where relevant (e.g. `feat(q5_max):`, `fix(k17_max):`).
|
||||||
* Do **not** include `Co-Authored-By: Claude` trailers in commit messages.
|
* Do **not** include `Co-Authored-By: Claude` trailers in commit messages.
|
||||||
|
|
||||||
### Chained / Stacked PRs
|
### Chained / Stacked PRs
|
||||||
|
|
||||||
When merging a chain of PRs (e.g. `A → main`, `B → A`, `C → B`), always **delete the branch after each merge**. Gitea (and GitHub) will automatically retarget any open PRs pointing at the deleted branch to the branch it was merged into. This keeps the chain collapsing cleanly into `main` without manual retargeting or cleanup PRs.
|
When merging a chain of PRs (e.g. `A → main`, `B → A`, `C → B`), always **delete the branch after each merge**. Gitea (and GitHub) will automatically retarget any open PRs pointing at the deleted branch to the branch it was merged into. This keeps the chain collapsing cleanly into `main` without manual retargeting or cleanup PRs.
|
||||||
|
|
||||||
|
## EEPROM Layout Notes
|
||||||
|
|
||||||
|
The Q5 Max uses wear-leveling EEPROM (STM32F401). Key layout facts:
|
||||||
|
|
||||||
|
* `EECONFIG_RGB_MATRIX` is at bytes 24–31; byte 0 packs `mode[7:2] | enable[1:0]`.
|
||||||
|
* Keychron custom RGB data (effect list, regions, per-key colours, retail demo flag) lives in `EECONFIG_KB_DATABLOCK` immediately after `EECONFIG_BASE_SIZE` (37 bytes).
|
||||||
|
* `VIA_EEPROM_MAGIC_ADDR` is pinned to **544** in `ansi_encoder/config.h`. Do not lower this value — it must stay above `EECONFIG_BASE_SIZE + EECONFIG_KB_DATA_SIZE`. If Keychron EEPROM grows, raise 544 accordingly and clear EEPROM on the board.
|
||||||
|
* `EECONFIG_KB_DATA_SIZE` is computed in `eeconfig_kb.h` and requires an `#undef` before the `#define` to suppress QMK's default-zero value.
|
||||||
|
|
||||||
|
## Keychron RGB (`KEYCHRON_RGB_ENABLE`)
|
||||||
|
|
||||||
|
Enabled via `KEYCHRON_RGB_ENABLE = yes` in `rules.mk`. Key behavioural notes:
|
||||||
|
|
||||||
|
* `eeconfig_init_custom_rgb()` **loads** Keychron RGB state from EEPROM into RAM. It must be called in `keyboard_post_init_kb()` and in `wireless_enter_connected_kb()`; without it the arrays are zero-initialised and Launcher settings are lost on every boot or transport change.
|
||||||
|
* `eeconfig_reset_custom_rgb()` **writes** defaults to EEPROM and stamps the version. The version stamp (`eeprom_update_dword(EECONFIG_KEYBOARD, ...)`) belongs here only — not in the load path.
|
||||||
|
* `kc_rgb_save()` must call `eeconfig_update_rgb_matrix()` to persist the QMK RGB mode alongside the Keychron custom data; otherwise `rgb_matrix_init()` (triggered on every transport change by `REINIT_LED_DRIVER = 1`) reloads the compile-time default `RGB_MATRIX_TYPING_HEATMAP`.
|
||||||
|
* `retail_demo_enable` is a single byte. A bug in the original Keychron code used `eeprom_read_block` instead of `eeprom_update_block` in `eeconfig_reset_custom_rgb()`, leaving `0xFF` on freshly-flashed boards. `retail_demo_task()` treats any non-zero value as "demo active" and forces `CUSTOM_MIXED_RGB` every scan. The load path now clamps `> 1` to `0` and re-writes the byte as a one-time recovery.
|
||||||
|
* `default_per_key_led[]` and `default_region[]` must be defined in board-specific code (e.g. `ansi_encoder.c`) — `keychron_rgb.c` declares them `extern`.
|
||||||
|
|
||||||
|
## DIP Switch (Win/Mac)
|
||||||
|
|
||||||
|
The Win-side dip switch uses a **frame overlay** rather than calling `rgb_matrix_mode()`. A `dip_win_active` flag is set on switch change; `rgb_matrix_indicators_advanced_user()` paints all LEDs white each frame when the flag is set. This avoids writing to EEPROM and preserves the Launcher-configured effect, which would otherwise be overwritten by the direct mode call.
|
||||||
|
|||||||
Reference in New Issue
Block a user