From 0cb6461c6ab38c6ab049500ef860ba84890eabc3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2026 21:30:44 +0100 Subject: [PATCH 01/14] Bump actions/cache from 5 to 6 (#26293) Bumps [actions/cache](https://github.com/actions/cache) from 5 to 6. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci_build_major_branch_keymap.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_build_major_branch_keymap.yml b/.github/workflows/ci_build_major_branch_keymap.yml index 085643f570..2beebc604c 100644 --- a/.github/workflows/ci_build_major_branch_keymap.yml +++ b/.github/workflows/ci_build_major_branch_keymap.yml @@ -105,7 +105,7 @@ jobs: - name: Restore Cache id: cache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: ${{ env.CCACHE_CONFIGPATH }} key: compile-${{ inputs.keymap }}-${{ matrix.target }} @@ -136,7 +136,7 @@ jobs: fi - name: Save Cache - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: ${{ env.CCACHE_CONFIGPATH }} key: compile-${{ inputs.keymap }}-${{ matrix.target }} From b1093e9da5f27253f3db692352daf5cf4ad5b98d Mon Sep 17 00:00:00 2001 From: Trent Piepho <35062987+xyzzy42@users.noreply.github.com> Date: Fri, 26 Jun 2026 06:20:10 -0700 Subject: [PATCH 02/14] Fix VERBOSE make flag (#26289) The docs say set this to true to enable verbose output, but setting it to anything, even "false", would enable verbose mode. The qmk python build program actually does this, supplying "VERBOSE=false" to make, which turns verbose mode on, not off! The reason it's not verbose is that the wrapper also adds the "-s" switch that has the same effect as turning verbose mode back off. After fixing the flag, there's no reason to add the "-s", so remove that code. --- Makefile | 2 +- builddefs/build_keyboard.mk | 2 +- builddefs/build_test.mk | 2 +- lib/python/qmk/build_targets.py | 3 --- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 2a992845ce..2dbb085f96 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -ifndef VERBOSE +ifneq ($(VERBOSE),true) .SILENT: endif diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk index acfad61e7d..50411e952a 100644 --- a/builddefs/build_keyboard.mk +++ b/builddefs/build_keyboard.mk @@ -4,7 +4,7 @@ # responsible for determining which folder is being used and doing the # corresponding environment setup. -ifndef VERBOSE +ifneq ($(VERBOSE),true) .SILENT: endif diff --git a/builddefs/build_test.mk b/builddefs/build_test.mk index ccdad1b4e7..1f1a9fbea8 100644 --- a/builddefs/build_test.mk +++ b/builddefs/build_test.mk @@ -1,4 +1,4 @@ -ifndef VERBOSE +ifneq ($(VERBOSE),true) .SILENT: endif diff --git a/lib/python/qmk/build_targets.py b/lib/python/qmk/build_targets.py index 35a5f89f91..1d4f82c767 100644 --- a/lib/python/qmk/build_targets.py +++ b/lib/python/qmk/build_targets.py @@ -113,9 +113,6 @@ class BuildTarget: 'builddefs/build_keyboard.mk', ] - if not cli.config.general.verbose: - compile_args.append('-s') - verbose = 'true' if cli.config.general.verbose else 'false' color = 'true' if cli.config.general.color else 'false' From cf93bbb78fe0bbf994663555de41372c4b5e59fe Mon Sep 17 00:00:00 2001 From: Pascal Getreuer <50221757+getreuer@users.noreply.github.com> Date: Thu, 2 Jul 2026 20:48:28 -0700 Subject: [PATCH 03/14] [Docs] Tap-hold doc improvements and suggest an HRMs starter recipe (#26284) * Enhance tap-hold docs. * Minor edits. * Move note on Quick Tap to a sub bullet for visibility. Co-authored-by: Drashna Jaelre --------- Co-authored-by: Drashna Jaelre --- docs/feature_layers.md | 3 ++- docs/features/tap_dance.md | 4 ++++ docs/mod_tap.md | 4 +++- docs/tap_hold.md | 27 +++++++++++++++++++++++++-- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/docs/feature_layers.md b/docs/feature_layers.md index 9aa453c763..83337d6dbb 100644 --- a/docs/feature_layers.md +++ b/docs/feature_layers.md @@ -16,7 +16,8 @@ These functions allow you to activate layers in various ways. Note that layers a * `OSL(layer)` - momentarily activates *layer* until the next key is pressed. See [One Shot Keys](one_shot_keys) for details and additional functionality. * `TG(layer)` - toggles *layer*, activating it if it's inactive and vice versa * `TO(layer)` - activates *layer* and de-activates all other layers (except your default layer). This function is special, because instead of just adding/removing one layer to your active layer stack, it will completely replace your current active layers, uniquely allowing you to replace higher layers with a lower one. This is activated on keydown (as soon as the key is pressed). -* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps. +* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps. + * Note: toggling behavior requires that [Quick Tap](tap_hold#quick-tap-term) is enabled (`QUICK_TAP_TERM` not set to `0`), or if `QUICK_TAP_TERM_PER_KEY` is defined, that `get_quick_tap_term()` returns a non-zero value for the `TT` key. See also the [Layer Lock key](features/layer_lock), which locks the highest active layer until pressed again. diff --git a/docs/features/tap_dance.md b/docs/features/tap_dance.md index 688241a16b..6c880f9dc3 100644 --- a/docs/features/tap_dance.md +++ b/docs/features/tap_dance.md @@ -375,6 +375,10 @@ In this configuration "hold" takes place **after** tap dance timeout. To achieve Tap dance can be used to emulate `MT()` and `LT()` behavior when the tapped code is not a basic keycode. This is useful to send tapped keycodes that normally require `Shift`, such as parentheses or curly braces—or other modified keycodes, such as `Control + X`. +::: tip +For simply sending a non-basic keycode on tap while functioning as a modifier or layer switch on hold, a simpler (and often superior) alternative is to use a Mod-Tap or Layer-Tap key and intercept its tap function in `process_record_user()`. This avoids the complexity of Tap Dance, and allows the key to benefit from advanced Tap-Hold options. See [Intercepting Mod-Taps](../mod_tap#intercepting-mod-taps) for details. +::: + Below your layers and custom keycodes, add the following: ```c diff --git a/docs/mod_tap.md b/docs/mod_tap.md index 67922c0915..efd5018f66 100644 --- a/docs/mod_tap.md +++ b/docs/mod_tap.md @@ -72,9 +72,11 @@ It can also be mitigated by increasing [`TAP_CODE_DELAY`](config_options#behavio ## Intercepting Mod-Taps +This technique works for both Mod-Tap (`MT`) and Layer-Tap (`LT`) keys. + ### Changing tap function -The basic keycode limitation with Mod-Tap can be worked around by intercepting it in `process_record_user`. For example, shifted keycode `KC_DQUO` cannot be used with `MT()` because it is a 16-bit keycode alias of `LSFT(KC_QUOT)`. Modifiers on `KC_DQUO` will be masked by `MT()`. But the following custom code can be used to intercept the "tap" function to manually send `KC_DQUO`: +The basic keycode limitation with Mod-Tap and Layer-Tap can be worked around by intercepting it in `process_record_user`. For example, shifted keycode `KC_DQUO` cannot be used with `MT()` because it is a 16-bit keycode alias of `LSFT(KC_QUOT)`. Modifiers on `KC_DQUO` will be masked by `MT()`. But the following custom code can be used to intercept the "tap" function to manually send `KC_DQUO`: ```c bool process_record_user(uint16_t keycode, keyrecord_t *record) { diff --git a/docs/tap_hold.md b/docs/tap_hold.md index 8fe81cfe1d..13e2f0b367 100644 --- a/docs/tap_hold.md +++ b/docs/tap_hold.md @@ -1,8 +1,12 @@ # Tap-Hold Configuration Options +These options let you modify the behavior of the tap-hold keys, applying primarily to Mod-Tap `MT` and Layer-Tap `LT` keys. They also affect layer tap-toggle `TT`, one-shot `OSM`, `OSL`, and Swap Hands `SH_T`, `SH_TT` keys. + While Tap-Hold options are fantastic, they are not without their issues. We have tried to configure them with reasonable defaults, but that may still cause issues for some people. -These options let you modify the behavior of the tap-hold keys. +::: info +Besides the tapping term, tap-hold options do **not** apply to Tap Dance keys. Tap Dance implements a separate, simpler decision logic to track when keys are tapped vs. held, and it does not support advanced tap-hold configurations like Permissive Hold, Chordal Hold, etc. +::: ## Tapping Term @@ -148,6 +152,25 @@ uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { The reason is that `TAPPING_TERM` is a macro that expands to a constant integer and thus cannot be changed at runtime, whereas `g_tapping_term` is a variable whose value can be changed at runtime. If you want, you can temporarily enable `DYNAMIC_TAPPING_TERM_ENABLE` to find a suitable tapping term value and then disable that feature and revert back to using the classic syntax for per-key tapping term settings. In case you need to access the tapping term from elsewhere in your code, you can use the `GET_TAPPING_TERM(keycode, record)` macro. This macro will expand to whatever is the appropriate access pattern given the current configuration. +## Configuring Home Row Mods + +"Home row mods" (HRMs) is a popular layout technique where modifiers are placed as Mod-Tap keys on the home row (A, S, D, F and J, K, L, ;, supposing QWERTY layout). This reduces hand movement and can increase comfort. However, because these keys are also used for fast typing, they are prone to accidental modifier triggers (when rolling keys) or accidental typed letters (when trying to use a modifier). + +There is no single perfect configuration for home row mods, as it depends heavily on your typing speed and habits. However, a good starting point in QMK is (added in your `config.h`): + +```c +#define TAPPING_TERM 250 +#define PERMISSIVE_HOLD // Triggers mod if you tap another key while holding. +#define CHORDAL_HOLD // Constrains holds to opposite-hand combinations. +// Consider also: +// #define FLOW_TAP_TERM 150 // Disables holds when typing quickly. +``` + +See [Permissive Hold](#permissive-hold), [Chordal Hold](#chordal-hold), and [Flow Tap](#flow-tap) below for details on what they do and how to fine-tune them. + +Additionally, [Speculative Hold](#speculative-hold) is useful to eliminate lag when combining a home row mod with mouse clicks (e.g., Shift + Click), as standard mod-tap keys do not send the modifier until the tap-hold decision is finalized. + + ## Tap-Or-Hold Decision Modes The code which decides between the tap and hold actions of dual-role keys supports three different modes, in increasing order of preference for the hold action: @@ -824,7 +847,7 @@ bool get_speculative_hold(uint16_t keycode, keyrecord_t* record) { } ``` -Some operating systems or applications assign actions to tapping a modifier key by itself, e.g., tapping GUI to open a start menu. Because Speculative Hold sometimes sends a lone modifier key press, it can falsely trigger these actions (known as the "flashing mods" problem). How such an input is handled depends on the OS and application, so unfortunately, there is no universal solution. +Some operating systems or applications assign actions to tapping a modifier key by itself, e.g., tapping GUI to open a start menu. Because Speculative Hold sends a lone modifier key press in some cases, it can falsely trigger these actions (known as the "flashing mods" problem). How such an input is handled depends on the OS and application, so unfortunately, there is no universal solution. To mitigate this issue, you can set `DUMMY_MOD_NEUTRALIZER_KEYCODE` (and optionally `MODS_TO_NEUTRALIZE`) in your `config.h`, as described above for [Retro Tapping](#retro-tapping). From 7a15cd24824dc625b0752c6d17be2bebc11aaca7 Mon Sep 17 00:00:00 2001 From: Harry Cutts Date: Mon, 6 Jul 2026 21:08:39 +0100 Subject: [PATCH 04/14] Add "handwired" TwentyPad macro pad (#26264) * Add "handwired" TwentyPad macro pad TwentyPad is 20-key macro pad I created as a hobby project. Its configuration is based on ez_maker/directpins/teensy_2, with the bootloader and layout changed. * Host the image on Imgur Co-authored-by: Joel Challis --------- Co-authored-by: Joel Challis --- keyboards/handwired/twentypad/keyboard.json | 54 +++++++++++++++++++ .../twentypad/keymaps/default/keymap.json | 14 +++++ keyboards/handwired/twentypad/readme.md | 26 +++++++++ 3 files changed, 94 insertions(+) create mode 100644 keyboards/handwired/twentypad/keyboard.json create mode 100644 keyboards/handwired/twentypad/keymaps/default/keymap.json create mode 100644 keyboards/handwired/twentypad/readme.md diff --git a/keyboards/handwired/twentypad/keyboard.json b/keyboards/handwired/twentypad/keyboard.json new file mode 100644 index 0000000000..0de0ed1cb9 --- /dev/null +++ b/keyboards/handwired/twentypad/keyboard.json @@ -0,0 +1,54 @@ +{ + "manufacturer": "Harry Cutts", + "keyboard_name": "TwentyPad", + "maintainer": "HarryCutts", + "bootloader": "atmel-dfu", + "features": { + "bootmagic": true, + "extrakey": true, + "mousekey": true + }, + "matrix_pins": { + "direct": [ + ["B7", "D5", "B5", "F6"], + ["B3", "D3", "B4", "F7"], + ["B2", "D2", "D7", "C7"], + ["B1", "D1", "D6", "C6"], + ["B0", "D0", "D4", "B6"] + ] + }, + "processor": "atmega32u4", + "url": "https://github.com/HarryCutts/twentypad/", + "usb": { + "device_version": "1.0.0", + "pid": "0x209D", + "vid": "0xFEED" + }, + "community_layouts": ["ortho_5x4"], + "layouts": { + "LAYOUT_ortho_5x4": { + "layout": [ + {"label": "B7", "matrix": [0, 0], "x": 0, "y": 0}, + {"label": "D5", "matrix": [0, 1], "x": 1, "y": 0}, + {"label": "B5", "matrix": [0, 2], "x": 2, "y": 0}, + {"label": "F6", "matrix": [0, 3], "x": 3, "y": 0}, + {"label": "B3", "matrix": [1, 0], "x": 0, "y": 1}, + {"label": "D3", "matrix": [1, 1], "x": 1, "y": 1}, + {"label": "B4", "matrix": [1, 2], "x": 2, "y": 1}, + {"label": "F7", "matrix": [1, 3], "x": 3, "y": 1}, + {"label": "B2", "matrix": [2, 0], "x": 0, "y": 2}, + {"label": "D2", "matrix": [2, 1], "x": 1, "y": 2}, + {"label": "D7", "matrix": [2, 2], "x": 2, "y": 2}, + {"label": "C7", "matrix": [2, 3], "x": 3, "y": 2}, + {"label": "B1", "matrix": [3, 0], "x": 0, "y": 3}, + {"label": "D1", "matrix": [3, 1], "x": 1, "y": 3}, + {"label": "D6", "matrix": [3, 2], "x": 2, "y": 3}, + {"label": "C6", "matrix": [3, 3], "x": 3, "y": 3}, + {"label": "B0", "matrix": [4, 0], "x": 0, "y": 4}, + {"label": "D0", "matrix": [4, 1], "x": 1, "y": 4}, + {"label": "D4", "matrix": [4, 2], "x": 2, "y": 4}, + {"label": "B6", "matrix": [4, 3], "x": 3, "y": 4} + ] + } + } +} diff --git a/keyboards/handwired/twentypad/keymaps/default/keymap.json b/keyboards/handwired/twentypad/keymaps/default/keymap.json new file mode 100644 index 0000000000..ed963a29cd --- /dev/null +++ b/keyboards/handwired/twentypad/keymaps/default/keymap.json @@ -0,0 +1,14 @@ +{ + "keyboard": "handwired/twentypad", + "keymap": "default", + "layout": "LAYOUT_ortho_5x4", + "layers": [ + [ + "KC_CALCULATOR", "KC_KP_SLASH", "KC_KP_ASTERISK", "KC_KP_MINUS", + "KC_KP_7", "KC_KP_8", "KC_KP_9", "KC_KP_PLUS", + "KC_KP_4", "KC_KP_5", "KC_KP_6", "KC_LEFT_PAREN", + "KC_KP_1", "KC_KP_2", "KC_KP_3", "KC_RIGHT_PAREN", + "KC_KP_0", "KC_KP_DOT", "KC_KP_EQUAL", "KC_KP_ENTER" + ] + ] +} diff --git a/keyboards/handwired/twentypad/readme.md b/keyboards/handwired/twentypad/readme.md new file mode 100644 index 0000000000..6984c5947c --- /dev/null +++ b/keyboards/handwired/twentypad/readme.md @@ -0,0 +1,26 @@ +# TwentyPad + +![TwentyPad](https://i.imgur.com/e1Bsg1M.jpeg) + +A simple twenty-key macro pad, built to learn PCB design. + +* Keyboard Maintainer: [Harry Cutts](https://github.com/HarryCutts) +* Hardware Supported: ATMEGA32U4 on a [custom PCB](https://github.com/HarryCutts/twentypad/) + +Make example for this keyboard (after setting up your build environment): + + qmk compile -kb handwired/twentypad -km default + +Flashing example for this keyboard: + + qmk flash -kb handwired/twentypad -km default + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). + +## Bootloader + +Enter the bootloader in 3 ways: + +* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (the top left key) and plug in the keyboard +* **Physical reset button**: Press the button marked `SWR1` in the top-left of the PCB +* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available From 2dc5e397985102f4aa18b7e9cc81ee5d06afba74 Mon Sep 17 00:00:00 2001 From: "Alexis \"Horgix\" Chotard" <4584397+Horgix@users.noreply.github.com> Date: Wed, 8 Jul 2026 00:14:50 +0200 Subject: [PATCH 05/14] docs(features): Add missing inline code syntax for `KC_ESC` (#26314) --- docs/features/grave_esc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/grave_esc.md b/docs/features/grave_esc.md index 09d098ee4e..9d4438dd62 100644 --- a/docs/features/grave_esc.md +++ b/docs/features/grave_esc.md @@ -8,7 +8,7 @@ Replace the `KC_GRV` key in your keymap (usually to the left of the `1` key) wit ## What Your OS Sees -If Mary presses `QK_GESC` on her keyboard, the OS will see an KC_ESC character. Now if Mary holds Shift down and presses `QK_GESC` it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple ` character. +If Mary presses `QK_GESC` on her keyboard, the OS will see an `KC_ESC` character. Now if Mary holds Shift down and presses `QK_GESC` it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple ` character. ## Keycodes From 99b8f3bf4e69cf82b33c9abdae743af860808ead Mon Sep 17 00:00:00 2001 From: Assem Mohamed <126217978+ToYoNiX@users.noreply.github.com> Date: Sat, 11 Jul 2026 08:19:17 +0300 Subject: [PATCH 06/14] Add handwired keyboard "handwired/tnx_corne_f401" (#26032) --- keyboards/handwired/tnx_corne_f401/config.h | 12 +++ keyboards/handwired/tnx_corne_f401/halconf.h | 9 ++ .../handwired/tnx_corne_f401/keyboard.json | 102 ++++++++++++++++++ .../tnx_corne_f401/keymaps/default/keymap.c | 64 +++++++++++ .../tnx_corne_f401/keymaps/default/rules.mk | 1 + keyboards/handwired/tnx_corne_f401/mcuconf.h | 8 ++ keyboards/handwired/tnx_corne_f401/readme.md | 26 +++++ 7 files changed, 222 insertions(+) create mode 100644 keyboards/handwired/tnx_corne_f401/config.h create mode 100644 keyboards/handwired/tnx_corne_f401/halconf.h create mode 100644 keyboards/handwired/tnx_corne_f401/keyboard.json create mode 100644 keyboards/handwired/tnx_corne_f401/keymaps/default/keymap.c create mode 100644 keyboards/handwired/tnx_corne_f401/keymaps/default/rules.mk create mode 100644 keyboards/handwired/tnx_corne_f401/mcuconf.h create mode 100644 keyboards/handwired/tnx_corne_f401/readme.md diff --git a/keyboards/handwired/tnx_corne_f401/config.h b/keyboards/handwired/tnx_corne_f401/config.h new file mode 100644 index 0000000000..90d1dd71e1 --- /dev/null +++ b/keyboards/handwired/tnx_corne_f401/config.h @@ -0,0 +1,12 @@ +// Copyright 2026 ToYoNiX +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +// Split configuration +#define SPLIT_HAND_PIN_LOW_IS_LEFT + +// Enable full duplex operation mode +#define SERIAL_USART_FULL_DUPLEX +#define SERIAL_USART_TX_PIN B6 +#define SERIAL_USART_RX_PIN B7 diff --git a/keyboards/handwired/tnx_corne_f401/halconf.h b/keyboards/handwired/tnx_corne_f401/halconf.h new file mode 100644 index 0000000000..ae24733a80 --- /dev/null +++ b/keyboards/handwired/tnx_corne_f401/halconf.h @@ -0,0 +1,9 @@ +// Copyright 2024 zvecr +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once +#define HAL_USE_SERIAL TRUE + +#define SERIAL_USB_BUFFERS_SIZE 256 + +#include_next diff --git a/keyboards/handwired/tnx_corne_f401/keyboard.json b/keyboards/handwired/tnx_corne_f401/keyboard.json new file mode 100644 index 0000000000..39d5cf8439 --- /dev/null +++ b/keyboards/handwired/tnx_corne_f401/keyboard.json @@ -0,0 +1,102 @@ +{ + "manufacturer": "Assem Mohamed", + "keyboard_name": "handwired/tnx_corne_f401", + "maintainer": "ToYoNiX", + "development_board": "blackpill_f401", + "bootloader": "tinyuf2", + "diode_direction": "COL2ROW", + "encoder": { + "rotary": [ + {"pin_a": "B9", "pin_b": "B8", "resolution": 2} + ] + }, + "split": { + "enabled": true, + "handedness": { + "pin": "C13" + }, + "serial": { + "driver": "usart" + }, + "transport": { + "watchdog": true + }, + "encoder": { + "right": { + "rotary": [ + {"pin_a": "B9", "pin_b": "B8", "resolution": 2} + ] + } + } + }, + "features": { + "bootmagic": true, + "extrakey": true, + "encoder": true, + "mousekey": true, + "nkro": true + }, + "host": { + "default": { + "nkro": true + } + }, + "matrix_pins": { + "cols": ["A8", "B15", "B14", "B13", "B12"], + "rows": ["B0", "A5", "A4", "A3"] + }, + "usb": { + "device_version": "1.0.0", + "pid": "0x544E", + "vid": "0x4B42" + }, + "layouts": { + "LAYOUT_split_3x5_3": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0.3}, + {"matrix": [0, 1], "x": 1, "y": 0.1}, + {"matrix": [0, 2], "x": 2, "y": 0}, + {"matrix": [0, 3], "x": 3, "y": 0.1}, + {"matrix": [0, 4], "x": 4, "y": 0.2}, + + {"matrix": [4, 4], "x": 8, "y": 0.2}, + {"matrix": [4, 3], "x": 9, "y": 0.1}, + {"matrix": [4, 2], "x": 10, "y": 0}, + {"matrix": [4, 1], "x": 11, "y": 0.1}, + {"matrix": [4, 0], "x": 12, "y": 0.3}, + + {"matrix": [1, 0], "x": 0, "y": 1.3}, + {"matrix": [1, 1], "x": 1, "y": 1.1}, + {"matrix": [1, 2], "x": 2, "y": 1}, + {"matrix": [1, 3], "x": 3, "y": 1.1}, + {"matrix": [1, 4], "x": 4, "y": 1.2}, + + {"matrix": [5, 4], "x": 8, "y": 1.2}, + {"matrix": [5, 3], "x": 9, "y": 1.1}, + {"matrix": [5, 2], "x": 10, "y": 1}, + {"matrix": [5, 1], "x": 11, "y": 1.1}, + {"matrix": [5, 0], "x": 12, "y": 1.3}, + + {"matrix": [2, 0], "x": 0, "y": 2.3}, + {"matrix": [2, 1], "x": 1, "y": 2.1}, + {"matrix": [2, 2], "x": 2, "y": 2}, + {"matrix": [2, 3], "x": 3, "y": 2.1}, + {"matrix": [2, 4], "x": 4, "y": 2.2}, + + {"matrix": [6, 4], "x": 8, "y": 2.2}, + {"matrix": [6, 3], "x": 9, "y": 2.1}, + {"matrix": [6, 2], "x": 10, "y": 2}, + {"matrix": [6, 1], "x": 11, "y": 2.1}, + {"matrix": [6, 0], "x": 12, "y": 2.3}, + + {"matrix": [3, 2], "x": 3, "y": 3.7}, + {"matrix": [3, 3], "x": 4, "y": 3.7}, + {"matrix": [3, 4], "x": 5, "y": 3.2, "h": 1.5}, + + {"matrix": [7, 4], "x": 7, "y": 3.2, "h": 1.5}, + {"matrix": [7, 3], "x": 8, "y": 3.7}, + {"matrix": [7, 2], "x": 9, "y": 3.7} + ] + } + } +} diff --git a/keyboards/handwired/tnx_corne_f401/keymaps/default/keymap.c b/keyboards/handwired/tnx_corne_f401/keymaps/default/keymap.c new file mode 100644 index 0000000000..c21ecce172 --- /dev/null +++ b/keyboards/handwired/tnx_corne_f401/keymaps/default/keymap.c @@ -0,0 +1,64 @@ +// Copyright 2026 ToYoNiX +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H + +// Home Row Mods - custom modifier order +#define HM_A LSFT_T(KC_A) // Shift +#define HM_S LCTL_T(KC_S) // Ctrl +#define HM_D LGUI_T(KC_D) // Win/GUI +#define HM_F LALT_T(KC_F) // Alt + +#define HM_J LALT_T(KC_J) // Alt +#define HM_K LGUI_T(KC_K) // Win/GUI +#define HM_L LCTL_T(KC_L) // Ctrl +#define HM_SCLN RSFT_T(KC_SCLN) // Shift + +// Keymap +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* BASE Layer: QWERTY */ + [0] = LAYOUT_split_3x5_3( + //A8 B15 B14 B13 B12 B12 B13 B14 B15 A8 + KC_Q, KC_W, KC_E, KC_R, KC_T, /*B0*/ KC_Y, KC_U, KC_I, KC_O, KC_P, + HM_A, HM_S, HM_D, HM_F, KC_G, /*A5*/ KC_H, HM_J, HM_K, HM_L, HM_SCLN, + KC_Z, KC_X, KC_C, KC_V, KC_B, /*A4*/ KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, + KC_ESC, KC_SPC, MO(1), /*A3*/ MO(2), KC_BSPC, KC_ENT + ), + [1] = LAYOUT_split_3x5_3( + KC_TAB, KC_7, KC_8, KC_9, KC_0, KC_GRV, KC_QUOT, KC_MINS, KC_EQL, KC_NO, + KC_LSFT, KC_4, KC_5, KC_6, KC_PSCR, KC_HOME, KC_LBRC, KC_RBRC, KC_BSLS, KC_RSFT, + KC_LGUI, KC_1, KC_2, KC_3, KC_DEL, KC_END, KC_COMM, KC_DOT, KC_SLSH, KC_NO, + _______, _______, _______, _______, _______, _______ + ), + [2] = LAYOUT_split_3x5_3( + QK_BOOT, KC_F7, KC_F8, KC_F9, KC_F10, TO(3), KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_F4, KC_F5, KC_F6, KC_F11, KC_NO, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, + QK_RBT, KC_F1, KC_F2, KC_F3, KC_F12, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + _______, _______, _______, _______, _______, _______ + ), + // Gaming Layers + [3] = LAYOUT_split_3x5_3( + KC_TAB, KC_Q, KC_W, KC_E, KC_R, TO(0), KC_NO, KC_NO, KC_NO, KC_NO, + KC_LSFT, KC_A, KC_S, KC_D, KC_F, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_ESC, KC_SPC, LT(4, KC_LGUI), KC_NO, KC_NO, KC_NO + ), + [4] = LAYOUT_split_3x5_3( + KC_NO, KC_7, KC_8, KC_9, KC_0, TO(0), KC_NO, KC_NO, KC_NO, KC_NO, + KC_M, KC_4, KC_5, KC_6, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_B, KC_1, KC_2, KC_3, KC_F3, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + _______, _______, _______, KC_NO, KC_NO, KC_NO + ) +}; + +// Encoders +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = { + [0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(MS_WHLD, MS_WHLU) }, + [1] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_BRIU, KC_BRID) }, + [2] = { ENCODER_CCW_CW(KC_PGUP, KC_PGDN), ENCODER_CCW_CW(KC_NO, KC_NO) }, + [3] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_NO, KC_NO) }, + [4] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, + // Encoder 1 Encoder 2 +}; +#endif diff --git a/keyboards/handwired/tnx_corne_f401/keymaps/default/rules.mk b/keyboards/handwired/tnx_corne_f401/keymaps/default/rules.mk new file mode 100644 index 0000000000..ee32568148 --- /dev/null +++ b/keyboards/handwired/tnx_corne_f401/keymaps/default/rules.mk @@ -0,0 +1 @@ +ENCODER_MAP_ENABLE = yes diff --git a/keyboards/handwired/tnx_corne_f401/mcuconf.h b/keyboards/handwired/tnx_corne_f401/mcuconf.h new file mode 100644 index 0000000000..949178684b --- /dev/null +++ b/keyboards/handwired/tnx_corne_f401/mcuconf.h @@ -0,0 +1,8 @@ +// Copyright 2024 zvecr +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include_next +#undef STM32_SERIAL_USE_USART1 +#define STM32_SERIAL_USE_USART1 TRUE diff --git a/keyboards/handwired/tnx_corne_f401/readme.md b/keyboards/handwired/tnx_corne_f401/readme.md new file mode 100644 index 0000000000..e52fde920a --- /dev/null +++ b/keyboards/handwired/tnx_corne_f401/readme.md @@ -0,0 +1,26 @@ +# handwired/tnx_corne_f401 + +![handwired/tnx_corne_f401](https://i.imgur.com/rHiwS60.jpeg) + +*A handwired Corne keyboard using STM32 microcontrollers, with encoder support.* + +* Keyboard Maintainer: [Assem Mohamed](https://github.com/ToYoNiX) +* Hardware Supported: STM32F401, STM32F411, or STM32F103 development boards with USB HID support +* Hardware Availability: Commonly available Blackpill F401 and Bluepill F103 boards, plus EC11 encoders and a TRRS cable + +Make example for this keyboard (after setting up your build environment): + + make handwired/tnx_corne_f401:default + +Flashing example for this keyboard: + + make handwired/tnx_corne_f401:default:flash + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). + +## Bootloader + +Enter the bootloader in 2 ways: + +* **Physical reset button**: Double-press the reset button on the dev board to enter DFU mode +* **Keycode in layout**: Press the key mapped to `QK_BOOT` From a738fad372c1e72e10c47f560c8d167d233416ad Mon Sep 17 00:00:00 2001 From: yi chen <87560781+94xhn@users.noreply.github.com> Date: Sat, 11 Jul 2026 13:32:34 +0800 Subject: [PATCH 07/14] [Docs] Clarify Python HID package name in Raw HID docs (#26318) The PyPI package for the Python HID library used here is called `hid` (https://pypi.org/project/hid/), but the docs called it "pyhidapi" while linking to the `hid` package page. There is also a separate, unrelated, unmaintained package literally named `pyhidapi` on PyPI, so a reader following the doc text as written can end up installing the wrong package. Update the library list and prose to say `hid`, and add a short tip covering the install/import command and calling out the package to avoid. Fixes #26047 --- docs/features/rawhid.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/features/rawhid.md b/docs/features/rawhid.md index c3ecfbe099..ee57d19bc7 100644 --- a/docs/features/rawhid.md +++ b/docs/features/rawhid.md @@ -28,10 +28,14 @@ To send data to the keyboard, you must first find a library for communicating wi * **Node.js:** [node-hid](https://github.com/node-hid/node-hid) * **C/C++:** [hidapi](https://github.com/libusb/hidapi) * **Java:** [purejavahidapi](https://github.com/nyholku/purejavahidapi) and [hid4java](https://github.com/gary-rowe/hid4java) -* **Python:** [pyhidapi](https://pypi.org/project/hid/) and [pywinusb](https://pypi.org/project/pywinusb) +* **Python:** [hid](https://pypi.org/project/hid/) and [pywinusb](https://pypi.org/project/pywinusb) Please refer to these libraries' own documentation for instructions on usage. Remember to close the device once you are finished with it! +::: tip +The `hid` package is installed with `pip install hid` and imported as `import hid`. Avoid installing the unrelated `pyhidapi` package from PyPI, which is a different, unmaintained project despite the similar name. +::: + Next, you will need to know the USB Vendor and Product IDs of the device. These can easily be found by looking at your keyboard's `info.json`, under the `usb` object (alternatively, you can also use Device Manager on Windows, System Information on macOS, or `lsusb` on Linux). For example, the Vendor ID for the Planck Rev 6 is `0x03A8`, and the Product ID is `0xA4F9`. It's also a good idea to narrow down the list of potential HID devices the library may give you by filtering on the usage page and usage ID, to avoid accidentally opening the interface on the same device for the keyboard, or mouse, or media keys, etc. @@ -72,7 +76,7 @@ void raw_hid_receive(uint8_t *data, uint8_t length) { } ``` -On the host side (here we are using Python and the `pyhidapi` library), the HID device is opened by enumerating the interfaces on the USB device, then filtering on the usage page and usage ID. Then, a report containing a single ASCII "A" (hex `0x41`) is constructed and sent. +On the host side (here we are using Python and the `hid` package), the HID device is opened by enumerating the interfaces on the USB device, then filtering on the usage page and usage ID. Then, a report containing a single ASCII "A" (hex `0x41`) is constructed and sent. For demonstration purposes, the manufacturer and product strings of the device, along with the request and response, are also printed. From b8bf40eb9632ad0ffe5f24dc7ec1211dde1c0deb Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sat, 18 Jul 2026 01:06:00 +0100 Subject: [PATCH 08/14] Avoid computing `_get_default_distrib_path` when QMK_DISTRIB_DIR is set (#26339) --- lib/python/qmk/cli/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py index ca816ba0b7..ef393cd1d6 100644 --- a/lib/python/qmk/cli/__init__.py +++ b/lib/python/qmk/cli/__init__.py @@ -28,7 +28,7 @@ def _get_default_distrib_path(): # Ensure the QMK distribution is on the `$PATH` if present. This must be kept in sync with qmk/qmk_cli. -QMK_DISTRIB_DIR = Path(os.environ.get('QMK_DISTRIB_DIR', _get_default_distrib_path())) +QMK_DISTRIB_DIR = Path(os.environ['QMK_DISTRIB_DIR'] if 'QMK_DISTRIB_DIR' in os.environ else _get_default_distrib_path()) if QMK_DISTRIB_DIR.exists(): os.environ['PATH'] = str(QMK_DISTRIB_DIR / 'bin') + os.pathsep + os.environ['PATH'] From dbd9b0a379ce0fcea85c4c420a306c9f34e940d9 Mon Sep 17 00:00:00 2001 From: yiancar Date: Sun, 19 Jul 2026 04:54:32 +0100 Subject: [PATCH 09/14] NK65 Gen2 Keyboard (#26334) * Initial commit * Cleanup * Update keyboards/novelkeys/nk65_gen2/keymaps/default/keymap.c Co-authored-by: Joel Challis * Update keyboards/novelkeys/nk65_gen2/config.h Co-authored-by: Joel Challis * Update keyboards/novelkeys/nk65_gen2/mcuconf.h Co-authored-by: Joel Challis * Update keyboards/novelkeys/nk65_gen2/readme.md Co-authored-by: Joel Challis * Update keyboards/novelkeys/nk65_gen2/halconf.h Co-authored-by: Joel Challis * Update keyboards/novelkeys/nk65_gen2/keymaps/default/keymap.c Co-authored-by: Joel Challis * Simplify RGB matrix color settings in keymap.c * Update keyboards/novelkeys/nk65_gen2/readme.md Co-authored-by: Joel Challis * Update keyboards/novelkeys/nk65_gen2/readme.md Co-authored-by: Joel Challis --------- Co-authored-by: yiancar Co-authored-by: Joel Challis --- keyboards/novelkeys/nk65_gen2/config.h | 10 + keyboards/novelkeys/nk65_gen2/halconf.h | 8 + keyboards/novelkeys/nk65_gen2/keyboard.json | 228 ++++++++++++++++++ .../nk65_gen2/keymaps/default/keymap.c | 35 +++ keyboards/novelkeys/nk65_gen2/mcuconf.h | 9 + keyboards/novelkeys/nk65_gen2/readme.md | 32 +++ 6 files changed, 322 insertions(+) create mode 100755 keyboards/novelkeys/nk65_gen2/config.h create mode 100644 keyboards/novelkeys/nk65_gen2/halconf.h create mode 100755 keyboards/novelkeys/nk65_gen2/keyboard.json create mode 100755 keyboards/novelkeys/nk65_gen2/keymaps/default/keymap.c create mode 100644 keyboards/novelkeys/nk65_gen2/mcuconf.h create mode 100755 keyboards/novelkeys/nk65_gen2/readme.md diff --git a/keyboards/novelkeys/nk65_gen2/config.h b/keyboards/novelkeys/nk65_gen2/config.h new file mode 100755 index 0000000000..5d6de3897a --- /dev/null +++ b/keyboards/novelkeys/nk65_gen2/config.h @@ -0,0 +1,10 @@ +// Copyright 2026 Yiancar +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#define WS2812_PWM_DRIVER PWMD3 +#define WS2812_PWM_CHANNEL 3 +#define WS2812_PWM_PAL_MODE 1 +#define WS2812_PWM_DMA_STREAM STM32_DMA1_STREAM3 +#define WS2812_PWM_DMA_CHANNEL 3 diff --git a/keyboards/novelkeys/nk65_gen2/halconf.h b/keyboards/novelkeys/nk65_gen2/halconf.h new file mode 100644 index 0000000000..bf838f7ad9 --- /dev/null +++ b/keyboards/novelkeys/nk65_gen2/halconf.h @@ -0,0 +1,8 @@ +// Copyright 2026 Yiancar +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#define HAL_USE_PWM TRUE + +#include_next diff --git a/keyboards/novelkeys/nk65_gen2/keyboard.json b/keyboards/novelkeys/nk65_gen2/keyboard.json new file mode 100755 index 0000000000..19051375c9 --- /dev/null +++ b/keyboards/novelkeys/nk65_gen2/keyboard.json @@ -0,0 +1,228 @@ +{ + "keyboard_name": "NK65 Gen2", + "manufacturer": "Yiancar-Designs", + "url": "www.yiancar-designs.com", + "maintainer": "Yiancar", + "usb": { + "vid": "0x8968", + "pid": "0x4E56", + "device_version": "0.0.1" + }, + "features": { + "bootmagic": true, + "extrakey": true, + "mousekey": true, + "nkro": true, + "rgb_matrix": true + }, + "ws2812": { + "pin": "B0", + "driver": "pwm" + }, + "rgb_matrix": { + "animations": { + "alphas_mods": true, + "band_pinwheel_sat": true, + "band_pinwheel_val": true, + "band_sat": true, + "band_spiral_sat": true, + "band_spiral_val": true, + "band_val": true, + "breathing": true, + "cycle_all": true, + "cycle_left_right": true, + "cycle_out_in": true, + "cycle_out_in_dual": true, + "cycle_pinwheel": true, + "cycle_spiral": true, + "cycle_up_down": true, + "digital_rain": true, + "dual_beacon": true, + "gradient_left_right": true, + "gradient_up_down": true, + "hue_breathing": true, + "hue_pendulum": true, + "hue_wave": true, + "jellybean_raindrops": true, + "multisplash": true, + "pixel_flow": true, + "pixel_fractal": true, + "pixel_rain": true, + "rainbow_beacon": true, + "rainbow_moving_chevron": true, + "rainbow_pinwheels": true, + "raindrops": true, + "solid_multisplash": true, + "solid_reactive": true, + "solid_reactive_cross": true, + "solid_reactive_multicross": true, + "solid_reactive_multinexus": true, + "solid_reactive_multiwide": true, + "solid_reactive_nexus": true, + "solid_reactive_simple": true, + "solid_reactive_wide": true, + "solid_splash": true, + "splash": true, + "typing_heatmap": true + }, + "driver": "ws2812", + "layout": [ + {"matrix": [0,14], "flags":1, "x":224, "y":0}, + {"matrix": [0,13], "flags":1, "x":202, "y":0}, + {"matrix": [0,12], "flags":4, "x":179, "y":0}, + {"matrix": [0,11], "flags":4, "x":164, "y":0}, + {"matrix": [0,10], "flags":4, "x":149, "y":0}, + {"matrix": [0,9], "flags":4, "x":134, "y":0}, + {"matrix": [0,8], "flags":4, "x":119, "y":0}, + {"matrix": [0,7], "flags":4, "x":105, "y":0}, + {"matrix": [0,6], "flags":4, "x":90, "y":0}, + {"matrix": [0,5], "flags":4, "x":75, "y":0}, + {"matrix": [0,4], "flags":4, "x":60, "y":0}, + {"matrix": [0,3], "flags":4, "x":45, "y":0}, + {"matrix": [0,2], "flags":4, "x":30, "y":0}, + {"matrix": [0,1], "flags":4, "x":15, "y":0}, + {"matrix": [0,0], "flags":1, "x":0, "y":0}, + {"matrix": [1,0], "flags":1, "x":4, "y":16}, + {"matrix": [1,1], "flags":4, "x":22, "y":16}, + {"matrix": [1,2], "flags":4, "x":37, "y":16}, + {"matrix": [1,3], "flags":4, "x":52, "y":16}, + {"matrix": [1,4], "flags":4, "x":67, "y":16}, + {"matrix": [1,5], "flags":4, "x":82, "y":16}, + {"matrix": [1,6], "flags":4, "x":97, "y":16}, + {"matrix": [1,7], "flags":4, "x":112, "y":16}, + {"matrix": [1,8], "flags":4, "x":127, "y":16}, + {"matrix": [1,9], "flags":4, "x":142, "y":16}, + {"matrix": [1,10], "flags":4, "x":157, "y":16}, + {"matrix": [1,11], "flags":4, "x":172, "y":16}, + {"matrix": [1,12], "flags":4, "x":187, "y":16}, + {"matrix": [2,12], "flags":4, "x":205, "y":16}, + {"matrix": [1,14], "flags":1, "x":224, "y":16}, + {"matrix": [2,14], "flags":1, "x":224, "y":32}, + {"matrix": [2,13], "flags":1, "x":200, "y":32}, + {"matrix": [2,11], "flags":4, "x":175, "y":32}, + {"matrix": [2,10], "flags":4, "x":161, "y":32}, + {"matrix": [2,9], "flags":4, "x":146, "y":32}, + {"matrix": [2,8], "flags":4, "x":131, "y":32}, + {"matrix": [2,7], "flags":4, "x":116, "y":32}, + {"matrix": [2,6], "flags":4, "x":101, "y":32}, + {"matrix": [2,5], "flags":4, "x":86, "y":32}, + {"matrix": [2,4], "flags":4, "x":71, "y":32}, + {"matrix": [2,3], "flags":4, "x":56, "y":32}, + {"matrix": [2,2], "flags":4, "x":41, "y":32}, + {"matrix": [2,1], "flags":4, "x":26, "y":32}, + {"matrix": [2,0], "flags":1, "x":11, "y":24}, + {"matrix": [3,0], "flags":1, "x":9, "y":48}, + {"matrix": [3,2], "flags":4, "x":34, "y":48}, + {"matrix": [3,3], "flags":4, "x":49, "y":48}, + {"matrix": [3,4], "flags":4, "x":63, "y":48}, + {"matrix": [3,5], "flags":4, "x":78, "y":48}, + {"matrix": [3,6], "flags":4, "x":93, "y":48}, + {"matrix": [3,7], "flags":4, "x":108, "y":48}, + {"matrix": [3,8], "flags":4, "x":123, "y":48}, + {"matrix": [3,9], "flags":4, "x":138, "y":48}, + {"matrix": [3,10], "flags":4, "x":153, "y":48}, + {"matrix": [3,11], "flags":4, "x":168, "y":48}, + {"matrix": [3,12], "flags":1, "x":189, "y":48}, + {"matrix": [3,13], "flags":1, "x":209, "y":48}, + {"matrix": [3,14], "flags":1, "x":224, "y":48}, + {"matrix": [4,14], "flags":1, "x":224, "y":64}, + {"matrix": [4,13], "flags":1, "x":209, "y":64}, + {"matrix": [4,12], "flags":1, "x":194, "y":64}, + {"matrix": [4,11], "flags":1, "x":168, "y":64}, + {"matrix": [4,6], "flags":4, "x":105, "y":64}, + {"matrix": [4,2], "flags":1, "x":41, "y":64}, + {"matrix": [4,1], "flags":1, "x":22, "y":64}, + {"matrix": [4,0], "flags":1, "x":4, "y":64}, + {"matrix": [4,0], "flags":8, "x":0, "y":0}, + {"matrix": [4,0], "flags":8, "x":0, "y":0} + ], + "max_brightness": 130, + "sleep": true + }, + "matrix_pins": { + "cols": ["B12", "B13", "B14", "B15", "A8", "A10", "A14", "A15", "B3", "B4", "B5", "B6", "B7", "B8", "B9"], + "rows": ["B10", "B2", "B1", "A9", "A5"] + }, + "diode_direction": "COL2ROW", + "processor": "STM32F072", + "bootloader": "stm32-dfu", + "layout_aliases": { + "LAYOUT": "LAYOUT_65_ansi_blocker_tsangan" + }, + "layouts": { + "LAYOUT_65_ansi_blocker_tsangan": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0}, + {"matrix": [0, 1], "x": 1, "y": 0}, + {"matrix": [0, 2], "x": 2, "y": 0}, + {"matrix": [0, 3], "x": 3, "y": 0}, + {"matrix": [0, 4], "x": 4, "y": 0}, + {"matrix": [0, 5], "x": 5, "y": 0}, + {"matrix": [0, 6], "x": 6, "y": 0}, + {"matrix": [0, 7], "x": 7, "y": 0}, + {"matrix": [0, 8], "x": 8, "y": 0}, + {"matrix": [0, 9], "x": 9, "y": 0}, + {"matrix": [0, 10], "x": 10, "y": 0}, + {"matrix": [0, 11], "x": 11, "y": 0}, + {"matrix": [0, 12], "x": 12, "y": 0}, + {"matrix": [0, 13], "x": 13, "y": 0, "w": 2}, + {"matrix": [0, 14], "x": 15, "y": 0}, + + {"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5}, + {"matrix": [1, 1], "x": 1.5, "y": 1}, + {"matrix": [1, 2], "x": 2.5, "y": 1}, + {"matrix": [1, 3], "x": 3.5, "y": 1}, + {"matrix": [1, 4], "x": 4.5, "y": 1}, + {"matrix": [1, 5], "x": 5.5, "y": 1}, + {"matrix": [1, 6], "x": 6.5, "y": 1}, + {"matrix": [1, 7], "x": 7.5, "y": 1}, + {"matrix": [1, 8], "x": 8.5, "y": 1}, + {"matrix": [1, 9], "x": 9.5, "y": 1}, + {"matrix": [1, 10], "x": 10.5, "y": 1}, + {"matrix": [1, 11], "x": 11.5, "y": 1}, + {"matrix": [1, 12], "x": 12.5, "y": 1}, + {"matrix": [2, 12], "x": 13.5, "y": 1, "w": 1.5}, + {"matrix": [1, 14], "x": 15, "y": 1}, + + {"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75}, + {"matrix": [2, 1], "x": 1.75, "y": 2}, + {"matrix": [2, 2], "x": 2.75, "y": 2}, + {"matrix": [2, 3], "x": 3.75, "y": 2}, + {"matrix": [2, 4], "x": 4.75, "y": 2}, + {"matrix": [2, 5], "x": 5.75, "y": 2}, + {"matrix": [2, 6], "x": 6.75, "y": 2}, + {"matrix": [2, 7], "x": 7.75, "y": 2}, + {"matrix": [2, 8], "x": 8.75, "y": 2}, + {"matrix": [2, 9], "x": 9.75, "y": 2}, + {"matrix": [2, 10], "x": 10.75, "y": 2}, + {"matrix": [2, 11], "x": 11.75, "y": 2}, + {"matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25}, + {"matrix": [2, 14], "x": 15, "y": 2}, + + {"matrix": [3, 0], "x": 0, "y": 3, "w": 2.25}, + {"matrix": [3, 2], "x": 2.25, "y": 3}, + {"matrix": [3, 3], "x": 3.25, "y": 3}, + {"matrix": [3, 4], "x": 4.25, "y": 3}, + {"matrix": [3, 5], "x": 5.25, "y": 3}, + {"matrix": [3, 6], "x": 6.25, "y": 3}, + {"matrix": [3, 7], "x": 7.25, "y": 3}, + {"matrix": [3, 8], "x": 8.25, "y": 3}, + {"matrix": [3, 9], "x": 9.25, "y": 3}, + {"matrix": [3, 10], "x": 10.25, "y": 3}, + {"matrix": [3, 11], "x": 11.25, "y": 3}, + {"matrix": [3, 12], "x": 12.25, "y": 3, "w": 1.75}, + {"matrix": [3, 13], "x": 14, "y": 3}, + {"matrix": [3, 14], "x": 15, "y": 3}, + + {"matrix": [4, 0], "x": 0, "y": 4, "w": 1.5}, + {"matrix": [4, 1], "x": 1.5, "y": 4, "w": 1}, + {"matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.5}, + {"matrix": [4, 6], "x": 4, "y": 4, "w": 7}, + {"matrix": [4, 11], "x": 11, "y": 4, "w": 1.5}, + {"matrix": [4, 12], "x": 13, "y": 4}, + {"matrix": [4, 13], "x": 14, "y": 4}, + {"matrix": [4, 14], "x": 15, "y": 4} + ] + } + } +} diff --git a/keyboards/novelkeys/nk65_gen2/keymaps/default/keymap.c b/keyboards/novelkeys/nk65_gen2/keymaps/default/keymap.c new file mode 100755 index 0000000000..acff5f36d9 --- /dev/null +++ b/keyboards/novelkeys/nk65_gen2/keymaps/default/keymap.c @@ -0,0 +1,35 @@ +// Copyright 2026 Yiancar +// SPDX-License-Identifier: GPL-2.0-or-later +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { +[0] = LAYOUT_65_ansi_blocker_tsangan( /* Base */ + QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_HOME, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP, + KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END, + KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, MO(1), KC_LEFT, KC_DOWN, KC_RGHT), + +[1] = LAYOUT_65_ansi_blocker_tsangan( /* FN */ + KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, QK_BOOT, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, RM_TOGG, RM_NEXT, RM_HUED, RM_HUEU, RM_SATD, RM_SATU, RM_VALD, RM_VALU, RM_SPDD, RM_SPDU, KC_TRNS, KC_TRNS, KC_TRNS, + KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS), +}; + +bool rgb_matrix_indicators_user(void) { + if (host_keyboard_led_state().caps_lock) { + rgb_matrix_set_color(66, 5, 2, 1); + } else { + rgb_matrix_set_color(66, 0, 0, 0); + } + + if (get_highest_layer(layer_state|default_layer_state) == 1) { + rgb_matrix_set_color(67, 3, 1, 5); + } else { + rgb_matrix_set_color(67, 0, 0, 0); + } + + return false; +} diff --git a/keyboards/novelkeys/nk65_gen2/mcuconf.h b/keyboards/novelkeys/nk65_gen2/mcuconf.h new file mode 100644 index 0000000000..ba586e3a06 --- /dev/null +++ b/keyboards/novelkeys/nk65_gen2/mcuconf.h @@ -0,0 +1,9 @@ +// Copyright 2026 Yiancar +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include_next + +#undef STM32_PWM_USE_TIM3 +#define STM32_PWM_USE_TIM3 TRUE diff --git a/keyboards/novelkeys/nk65_gen2/readme.md b/keyboards/novelkeys/nk65_gen2/readme.md new file mode 100755 index 0000000000..5725c85156 --- /dev/null +++ b/keyboards/novelkeys/nk65_gen2/readme.md @@ -0,0 +1,32 @@ +# NK66 Gen2 + +This is a tsangan fixed layout 65% PCB. It supports full per-key RGB. + +* Keyboard Maintainer: [Yiancar](http://yiancar-designs.com/) and on [GitHub](https://github.com/yiancar) +* Hardware Supported: A 65% keyboard with STM32F072CB +* Hardware Availability: https://novelkeys.com/ + +Make example for this keyboard (after setting up your build environment): + + make novelkeys/nk65_gen2:default + +Flashing example for this keyboard: + + make novelkeys/nk65_gen2:default:flash + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). + +### Reset + +- Unplug +- Hold Escape +- Plug In +- Unplug +- Release Escape + +### Flash + +- Unplug +- Hold Escape +- Plug In +- Flash using QMK Toolbox or CLI (`make novelkeys/nk65_gen2::flash`) From 95b9016a3b1f7bb90ccee8c0d841d77232ac9541 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 19 Jul 2026 21:55:20 +0100 Subject: [PATCH 10/14] Fix STM32G0B1 not booting after ChibiOS update (#26342) --- platforms/chibios/boards/GENERIC_STM32_G0B1XB/configs/mcuconf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/chibios/boards/GENERIC_STM32_G0B1XB/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_G0B1XB/configs/mcuconf.h index c13e69c7cd..b1083f405d 100644 --- a/platforms/chibios/boards/GENERIC_STM32_G0B1XB/configs/mcuconf.h +++ b/platforms/chibios/boards/GENERIC_STM32_G0B1XB/configs/mcuconf.h @@ -41,7 +41,7 @@ #define STM32_NO_INIT FALSE #define STM32_CLOCK_DYNAMIC TRUE #define STM32_VOS STM32_VOS_RANGE1 -#define STM32_PWR_CR2 (STM32_PVDRT_LEV0 | STM32_PVDFT_LEV0 | STM32_PVDE_DISABLED) +#define STM32_PWR_CR2 PWR_CR2_PVMEN_USB #define STM32_PWR_CR3 (PWR_CR3_EIWUL) #define STM32_PWR_CR4 (0U) #define STM32_PWR_PUCRA (0U) From 3ef9860ee172cfbb9cbf19d98a5c9512d8400dac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 00:41:55 +0100 Subject: [PATCH 11/14] Bump actions/labeler from 6 to 7 (#26351) Bumps [actions/labeler](https://github.com/actions/labeler) from 6 to 7. - [Release notes](https://github.com/actions/labeler/releases) - [Commits](https://github.com/actions/labeler/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/labeler dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 0e9f29908e..f442bf3f71 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -10,4 +10,4 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v6 + - uses: actions/labeler@v7 From f0e090f67a90f9b653faeddbf5a1c4f75e24e91a Mon Sep 17 00:00:00 2001 From: Linn <65576637+mycelialinn@users.noreply.github.com> Date: Thu, 23 Jul 2026 20:30:34 -0500 Subject: [PATCH 12/14] Update `emerge-webrsync` to `emaint sync` (#26352) Gentoo users using git to sync cannot use `emerge-webrsync` command, but it seems like `emaint sync` still works with the webrsync method. Furthermore, running the version with `emerge-webrsync` on my Gentoo computer, which syncs with git, seemed to break syncing until manually fixed (by deleting and reinstalling the gentoo repository) --- .github/workflows/bootstrap_testing.yml | 2 +- util/env-bootstrap.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bootstrap_testing.yml b/.github/workflows/bootstrap_testing.yml index 9e35399ed2..76aa29e83f 100644 --- a/.github/workflows/bootstrap_testing.yml +++ b/.github/workflows/bootstrap_testing.yml @@ -99,7 +99,7 @@ jobs: zypper --non-interactive install sudo git shadow findutils tar # findutils=xargs ;; *gentoo*) - emerge-webrsync + emaint sync emerge --noreplace --ask=n sudo dev-vcs/git shadow findutils # findutils=xargs ;; *archlinux*|*cachyos*|*manjaro*) diff --git a/util/env-bootstrap.sh b/util/env-bootstrap.sh index e845d8dc64..47238a78df 100755 --- a/util/env-bootstrap.sh +++ b/util/env-bootstrap.sh @@ -359,7 +359,7 @@ __EOT__ *gentoo*) echo "It will also install the following system packages using 'emerge':" >&2 print_package_manager_deps_and_delay - $(nsudo) emerge-webrsync + $(nsudo) emaint sync $(nsudo) emerge --noreplace --ask=n $(get_package_manager_deps | tr ' ' '\n') || signal_execution_failure exit_if_execution_failed ;; From a53ce75641beee6623667a1982b4decd4930f1fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20San=20F=C3=A9lix?= Date: Fri, 24 Jul 2026 22:32:16 +0200 Subject: [PATCH 13/14] [Keyboard] Add Mithril (#26212) --- keyboards/mithril/config.h | 6 ++ keyboards/mithril/info.json | 82 ++++++++++++++ keyboards/mithril/keymaps/default/keymap.c | 30 ++++++ keyboards/mithril/keymaps/sanfeps/keymap.c | 93 ++++++++++++++++ keyboards/mithril/keymaps/sanfeps/rules.mk | 1 + keyboards/mithril/readme.md | 29 +++++ keyboards/mithril/rev1/keyboard.json | 118 +++++++++++++++++++++ 7 files changed, 359 insertions(+) create mode 100644 keyboards/mithril/config.h create mode 100644 keyboards/mithril/info.json create mode 100644 keyboards/mithril/keymaps/default/keymap.c create mode 100644 keyboards/mithril/keymaps/sanfeps/keymap.c create mode 100644 keyboards/mithril/keymaps/sanfeps/rules.mk create mode 100644 keyboards/mithril/readme.md create mode 100644 keyboards/mithril/rev1/keyboard.json diff --git a/keyboards/mithril/config.h b/keyboards/mithril/config.h new file mode 100644 index 0000000000..e4885dd7f2 --- /dev/null +++ b/keyboards/mithril/config.h @@ -0,0 +1,6 @@ +// Copyright 2024 sanfeps (@sanfeps) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#define EE_HANDS diff --git a/keyboards/mithril/info.json b/keyboards/mithril/info.json new file mode 100644 index 0000000000..923ff400df --- /dev/null +++ b/keyboards/mithril/info.json @@ -0,0 +1,82 @@ +{ + "manufacturer": "sanfeps", + "maintainer": "sanfeps", + "build": { + "lto": true + }, + "features": { + "bootmagic": true, + "extrakey": true, + "mousekey": true, + "nkro": true, + "rgb_matrix": true + }, + "rgb_matrix": { + "driver": "ws2812", + "max_brightness": 120 + }, + "url": "https://github.com/sanfeps/mithril_kb", + "usb": { + "vid": "0x8371" + }, + "layouts": { + "LAYOUT": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0}, + {"matrix": [0, 1], "x": 1, "y": 0}, + {"matrix": [0, 2], "x": 2, "y": 0}, + {"matrix": [0, 3], "x": 3, "y": 0}, + {"matrix": [0, 4], "x": 4, "y": 0}, + {"matrix": [0, 5], "x": 5, "y": 0}, + {"matrix": [5, 5], "x": 9, "y": 0}, + {"matrix": [5, 4], "x": 10, "y": 0}, + {"matrix": [5, 3], "x": 11, "y": 0}, + {"matrix": [5, 2], "x": 12, "y": 0}, + {"matrix": [5, 1], "x": 13, "y": 0}, + {"matrix": [5, 0], "x": 14, "y": 0}, + {"matrix": [1, 0], "x": 0, "y": 1}, + {"matrix": [1, 1], "x": 1, "y": 1}, + {"matrix": [1, 2], "x": 2, "y": 1}, + {"matrix": [1, 3], "x": 3, "y": 1}, + {"matrix": [1, 4], "x": 4, "y": 1}, + {"matrix": [1, 5], "x": 5, "y": 1}, + {"matrix": [6, 5], "x": 9, "y": 1}, + {"matrix": [6, 4], "x": 10, "y": 1}, + {"matrix": [6, 3], "x": 11, "y": 1}, + {"matrix": [6, 2], "x": 12, "y": 1}, + {"matrix": [6, 1], "x": 13, "y": 1}, + {"matrix": [6, 0], "x": 14, "y": 1}, + {"matrix": [2, 0], "x": 0, "y": 2}, + {"matrix": [2, 1], "x": 1, "y": 2}, + {"matrix": [2, 2], "x": 2, "y": 2}, + {"matrix": [2, 3], "x": 3, "y": 2}, + {"matrix": [2, 4], "x": 4, "y": 2}, + {"matrix": [2, 5], "x": 5, "y": 2}, + {"matrix": [7, 5], "x": 9, "y": 2}, + {"matrix": [7, 4], "x": 10, "y": 2}, + {"matrix": [7, 3], "x": 11, "y": 2}, + {"matrix": [7, 2], "x": 12, "y": 2}, + {"matrix": [7, 1], "x": 13, "y": 2}, + {"matrix": [7, 0], "x": 14, "y": 2}, + {"matrix": [3, 0], "x": 0, "y": 3}, + {"matrix": [3, 1], "x": 1, "y": 3}, + {"matrix": [3, 2], "x": 2, "y": 3}, + {"matrix": [3, 3], "x": 3, "y": 3}, + {"matrix": [3, 4], "x": 4, "y": 3}, + {"matrix": [3, 5], "x": 5, "y": 3}, + {"matrix": [8, 5], "x": 9, "y": 3}, + {"matrix": [8, 4], "x": 10, "y": 3}, + {"matrix": [8, 3], "x": 11, "y": 3}, + {"matrix": [8, 2], "x": 12, "y": 3}, + {"matrix": [8, 1], "x": 13, "y": 3}, + {"matrix": [8, 0], "x": 14, "y": 3}, + {"matrix": [4, 4], "x": 3, "y": 4}, + {"matrix": [4, 5], "x": 4, "y": 4}, + {"matrix": [4, 6], "x": 5, "y": 4}, + {"matrix": [9, 6], "x": 9, "y": 4}, + {"matrix": [9, 5], "x": 10, "y": 4}, + {"matrix": [9, 4], "x": 11, "y": 4} + ] + } + } +} diff --git a/keyboards/mithril/keymaps/default/keymap.c b/keyboards/mithril/keymaps/default/keymap.c new file mode 100644 index 0000000000..a135da6c32 --- /dev/null +++ b/keyboards/mithril/keymaps/default/keymap.c @@ -0,0 +1,30 @@ +// Copyright 2024 sanfeps (@sanfeps) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = LAYOUT( + KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS, + KC_LSFT, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, + KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_EQL, + KC_LALT, KC_BSPC, MO(1), KC_ENT, KC_SPC, KC_RGUI + ), + + [1] = LAYOUT( + KC_F12, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, + KC_TAB, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_LBRC, KC_RBRC, KC_PLUS, XXXXXXX, KC_GRV, + _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, XXXXXXX, XXXXXXX, + _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_DEL, + XXXXXXX, XXXXXXX, _______, MO(2), KC_ENT, XXXXXXX + ), + + [2] = LAYOUT( + RM_TOGG, RM_PREV, RM_NEXT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + XXXXXXX, RM_SPDD, RM_SPDU, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, RM_HUED, RM_VALD, RM_VALU, RM_HUEU, XXXXXXX, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, RM_SATD, RM_SATU, XXXXXXX, XXXXXXX, QK_BOOT, + XXXXXXX, XXXXXXX, XXXXXXX, _______, XXXXXXX, XXXXXXX + ), +}; diff --git a/keyboards/mithril/keymaps/sanfeps/keymap.c b/keyboards/mithril/keymaps/sanfeps/keymap.c new file mode 100644 index 0000000000..987174dbbc --- /dev/null +++ b/keyboards/mithril/keymaps/sanfeps/keymap.c @@ -0,0 +1,93 @@ +// Copyright 2024 sanfeps (@sanfeps) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H +#include "keymap_spanish.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* + * Layer 0 — Base (Spanish) + * ┌─────┬─────┬─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┬─────┬─────┐ + * │ ESC │ 1 │ 2 │ 3 │ 4 │ 5 │ │ 6 │ 7 │ 8 │ 9 │ 0 │ ?/¿ │ + * ├─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┤ + * │ TAB │ Q │ W │ E │ R │ T │ │ Y │ U │ I │ O │ P │ !/¡ │ + * ├─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┤ + * │LSFT │ A │ S │ D │ F │ G │ │ H │ J │ K │ L │ Ñ │ @/| │ + * ├─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┤ + * │LALT │ Z │ X │ C │ V │ B │ │ N │ M │ , │ . │ -/_ │ #/~ │ + * └─────┴─────┴─────┴─────┴─────┴─────┘ └─────┴─────┴─────┴─────┴─────┴─────┘ + * │LGUI │BSPC │MO(1)│ │ ENT │ SPC │RCTL │ + * └─────┴─────┴─────┘ └─────┴─────┴─────┘ + */ + [0] = LAYOUT( + KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, ES_QUES, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, ES_EXLM, + KC_LSFT, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, ES_NTIL, ES_AT, + KC_LALT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, ES_MINS, ES_HASH, + KC_LGUI, KC_BSPC, MO(1), KC_ENT, KC_SPC, KC_RCTL + ), + + /* + * Layer 1 — Symbols / Function / Nav + * ┌─────┬─────┬─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┬─────┬─────┐ + * │ F12 │ F1 │ F2 │ F3 │ F4 │ F5 │ │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ + * ├─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┤ + * │ TAB │ │ │ │ │ │ │ │ {/[ │ }/] │ + * │ │ ` │ + * ├─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┤ + * │ ___ │ │ │ │ │ │ │ ← │ ↓ │ ↑ │ → │ │ ´ │ + * ├─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┤ + * │ ___ │ │ │ │ │ │ │ │ ' │ < │ │ │ DEL │ + * └─────┴─────┴─────┴─────┴─────┴─────┘ └─────┴─────┴─────┴─────┴─────┴─────┘ + * │ │ │ ___ │ │MO(2)│ ENT │ │ + * └─────┴─────┴─────┘ └─────┴─────┴─────┘ + */ + [1] = LAYOUT( + KC_F12, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, + KC_TAB, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, ES_LCBR, ES_RCBR, ES_PLUS, XXXXXXX, ES_GRV, + _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, XXXXXXX, ES_ACUT, + _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, ES_QUOT, ES_LABK, XXXXXXX, XXXXXXX, KC_DEL, + XXXXXXX, XXXXXXX, _______, MO(2), KC_ENT, XXXXXXX + ), + + /* + * Layer 2 — RGB control + * ┌─────┬─────┬─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┬─────┬─────┐ + * │TOGG │PREV │NEXT │ │ │ │ │ │ │ │ │ │ │ + * ├─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┤ + * │ │SPD↓ │SPD↑ │ │ │ │ │ │ │ │ │ │ │ + * ├─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┤ + * │ │ │ │ │ │ │ │HUE↓ │VAL↓ │VAL↑ │HUE↑ │ │ │ + * ├─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┤ + * │ │ │ │ │ │ │ │ │SAT↓ │SAT↑ │ │ │BOOT │ + * └─────┴─────┴─────┴─────┴─────┴─────┘ └─────┴─────┴─────┴─────┴─────┴─────┘ + * │ │ │ │ │ ___ │ │ │ + * └─────┴─────┴─────┘ └─────┴─────┴─────┘ + */ + [2] = LAYOUT( + RM_TOGG, RM_PREV, RM_NEXT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + XXXXXXX, RM_SPDD, RM_SPDU, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, RM_HUED, RM_VALD, RM_VALU, RM_HUEU, XXXXXXX, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, RM_SATD, RM_SATU, XXXXXXX, XXXXXXX, QK_BOOT, + XXXXXXX, XXXXXXX, XXXXXXX, _______, XXXXXXX, XXXXXXX + ), +}; + +// Shifted-key overrides for the Spanish layout. +// Pressing the key gives the first symbol; holding Shift gives the second. +const key_override_t ques_to_ique = ko_make_basic(MOD_MASK_SHIFT, ES_QUES, ES_IQUE); // ? → ¿ +const key_override_t exlm_to_iexl = ko_make_basic(MOD_MASK_SHIFT, ES_EXLM, ES_IEXL); // ! → ¡ +const key_override_t lcbr_to_lbrc = ko_make_basic(MOD_MASK_SHIFT, ES_LCBR, ES_LBRC); // { → [ +const key_override_t rcbr_to_rbrc = ko_make_basic(MOD_MASK_SHIFT, ES_RCBR, ES_RBRC); // } → ] +const key_override_t plus_to_astr = ko_make_basic(MOD_MASK_SHIFT, ES_PLUS, ES_ASTR); // + → * +const key_override_t at_to_pipe = ko_make_basic(MOD_MASK_SHIFT, ES_AT, ES_PIPE); // @ → | +const key_override_t hash_to_tild = ko_make_basic(MOD_MASK_SHIFT, ES_HASH, ES_TILD); // # → ~ + +const key_override_t *key_overrides[] = { + &ques_to_ique, + &exlm_to_iexl, + &lcbr_to_lbrc, + &rcbr_to_rbrc, + &plus_to_astr, + &at_to_pipe, + &hash_to_tild, +}; diff --git a/keyboards/mithril/keymaps/sanfeps/rules.mk b/keyboards/mithril/keymaps/sanfeps/rules.mk new file mode 100644 index 0000000000..90c9b36df0 --- /dev/null +++ b/keyboards/mithril/keymaps/sanfeps/rules.mk @@ -0,0 +1 @@ +KEY_OVERRIDE_ENABLE = yes diff --git a/keyboards/mithril/readme.md b/keyboards/mithril/readme.md new file mode 100644 index 0000000000..a7d28038b4 --- /dev/null +++ b/keyboards/mithril/readme.md @@ -0,0 +1,29 @@ +# mithril + +![mithril](https://i.imgur.com/F0h5OY6.jpg) + +*A custom split ortholinear keyboard (4x6 + 3 thumb keys per half) with per-key RGB.* + +* Keyboard Maintainer: [Javier San Félix Guajardo](https://github.com/sanfeps) +* Hardware Supported: Mithril rev1 PCB, ATmega32U4 (Caterina bootloader), split halves with serial sync +* Hardware Availability: PCB design, plate files and case at [github.com/sanfeps/mithril_kb](https://github.com/sanfeps/mithril_kb) + +Make example for this keyboard (after setting up your build environment): + + make mithril/rev1:default + +Flashing example for this keyboard: + + make mithril/rev1:default:flash + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). + +## Bootloader + +Enter the bootloader in 3 ways: + +* **Bootmagic reset**: + * **Left half**: hold down `Esc` (matrix position `0,0` — top-outer key) and plug in the keyboard. + * **Right half**: hold down the top-outer key (`?` on the base layer, matrix position `5,0`) and plug in the keyboard. +* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead +* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available (mapped to the bottom-right key on layer 2 of the default keymap) diff --git a/keyboards/mithril/rev1/keyboard.json b/keyboards/mithril/rev1/keyboard.json new file mode 100644 index 0000000000..ce1817c09d --- /dev/null +++ b/keyboards/mithril/rev1/keyboard.json @@ -0,0 +1,118 @@ +{ + "keyboard_name": "mithril", + "bootloader": "caterina", + "diode_direction": "COL2ROW", + "matrix_pins": { + "cols": ["F0", "F1", "F4", "F5", "F6", "F7", "D7"], + "rows": ["C7", "C6", "B6", "B5", "B4"] + }, + "processor": "atmega32u4", + "rgb_matrix": { + "animations": { + "breathing": true, + "gradient_up_down": true, + "pixel_flow": true, + "rainbow_beacon": true, + "rainbow_moving_chevron": true, + "solid_reactive": true, + "solid_reactive_simple": true, + "splash": true, + "typing_heatmap": true + }, + "default": { + "animation": "typing_heatmap", + "hue": 128 + }, + "sat_steps": 8, + "sleep": true, + "speed_steps": 10, + "val_steps": 8, + "layout": [ + {"matrix": [0, 5], "x": 84, "y": 5, "flags": 4}, + {"matrix": [0, 4], "x": 67, "y": 2, "flags": 4}, + {"matrix": [0, 3], "x": 50, "y": 0, "flags": 4}, + {"matrix": [0, 2], "x": 33, "y": 2, "flags": 4}, + {"matrix": [0, 1], "x": 16, "y": 4, "flags": 4}, + {"matrix": [0, 0], "x": 0, "y": 4, "flags": 1}, + {"matrix": [1, 0], "x": 0, "y": 15, "flags": 1}, + {"matrix": [1, 1], "x": 16, "y": 15, "flags": 4}, + {"matrix": [1, 2], "x": 33, "y": 13, "flags": 4}, + {"matrix": [1, 3], "x": 50, "y": 10, "flags": 4}, + {"matrix": [1, 4], "x": 67, "y": 14, "flags": 4}, + {"matrix": [1, 5], "x": 84, "y": 16, "flags": 4}, + {"matrix": [2, 5], "x": 84, "y": 27, "flags": 4}, + {"matrix": [2, 4], "x": 67, "y": 25, "flags": 4}, + {"matrix": [2, 3], "x": 50, "y": 21, "flags": 4}, + {"matrix": [2, 2], "x": 33, "y": 24, "flags": 4}, + {"matrix": [2, 1], "x": 16, "y": 26, "flags": 4}, + {"matrix": [2, 0], "x": 0, "y": 26, "flags": 1}, + {"matrix": [3, 0], "x": 0, "y": 37, "flags": 1}, + {"matrix": [3, 1], "x": 16, "y": 37, "flags": 4}, + {"matrix": [3, 2], "x": 33, "y": 35, "flags": 4}, + {"matrix": [3, 3], "x": 50, "y": 32, "flags": 4}, + {"matrix": [3, 4], "x": 67, "y": 36, "flags": 4}, + {"matrix": [3, 5], "x": 84, "y": 36, "flags": 4}, + {"matrix": [4, 4], "x": 67, "y": 47, "flags": 1}, + {"matrix": [4, 5], "x": 87, "y": 53, "flags": 1}, + {"matrix": [4, 6], "x": 98, "y": 63, "flags": 1}, + {"matrix": [5, 5], "x": 138, "y": 5, "flags": 4}, + {"matrix": [5, 4], "x": 155, "y": 2, "flags": 4}, + {"matrix": [5, 3], "x": 172, "y": 0, "flags": 4}, + {"matrix": [5, 2], "x": 189, "y": 2, "flags": 4}, + {"matrix": [5, 1], "x": 206, "y": 4, "flags": 4}, + {"matrix": [5, 0], "x": 223, "y": 4, "flags": 1}, + {"matrix": [6, 0], "x": 223, "y": 15, "flags": 1}, + {"matrix": [6, 1], "x": 206, "y": 15, "flags": 4}, + {"matrix": [6, 2], "x": 189, "y": 13, "flags": 4}, + {"matrix": [6, 3], "x": 172, "y": 10, "flags": 4}, + {"matrix": [6, 4], "x": 155, "y": 14, "flags": 4}, + {"matrix": [6, 5], "x": 138, "y": 16, "flags": 4}, + {"matrix": [7, 5], "x": 138, "y": 27, "flags": 4}, + {"matrix": [7, 4], "x": 155, "y": 25, "flags": 4}, + {"matrix": [7, 3], "x": 172, "y": 21, "flags": 4}, + {"matrix": [7, 2], "x": 189, "y": 24, "flags": 4}, + {"matrix": [7, 1], "x": 206, "y": 26, "flags": 4}, + {"matrix": [7, 0], "x": 223, "y": 26, "flags": 1}, + {"matrix": [8, 0], "x": 223, "y": 37, "flags": 1}, + {"matrix": [8, 1], "x": 206, "y": 37, "flags": 4}, + {"matrix": [8, 2], "x": 189, "y": 35, "flags": 4}, + {"matrix": [8, 3], "x": 172, "y": 32, "flags": 4}, + {"matrix": [8, 4], "x": 155, "y": 36, "flags": 4}, + {"matrix": [8, 5], "x": 138, "y": 38, "flags": 4}, + {"matrix": [9, 4], "x": 155, "y": 47, "flags": 1}, + {"matrix": [9, 5], "x": 135, "y": 53, "flags": 1}, + {"matrix": [9, 6], "x": 124, "y": 63, "flags": 1} + ], + "split_count": [27, 27] + }, + "split": { + "enabled": true, + "bootmagic": { + "matrix": [5, 0] + }, + "matrix_pins": { + "right": { + "cols": ["F0", "F1", "F4", "F5", "F6", "F7", "C7"], + "rows": ["D7", "B4", "B5", "B6", "C6"] + } + }, + "serial": { + "pin": "D0" + }, + "transport": { + "sync": { + "matrix_state": true + } + }, + "usb_detect": { + "enabled": true + } + }, + "usb": { + "device_version": "1.0.0", + "pid": "0x4D52" + }, + "ws2812": { + "pin": "D2" + } +} From 4ffb1ab16c443f2def5949d39b56057c0c88c88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20A=2E=20Volpato?= Date: Mon, 27 Jul 2026 22:19:04 -0300 Subject: [PATCH 14/14] Adds support for mode M65V2 (#26049) Co-authored-by: Joel Challis --- keyboards/mode/m65v2/config.h | 25 ++++ keyboards/mode/m65v2/halconf.h | 21 +++ keyboards/mode/m65v2/keyboard.json | 135 ++++++++++++++++++ keyboards/mode/m65v2/keymaps/default/keymap.c | 35 +++++ keyboards/mode/m65v2/m65v2.c | 33 +++++ keyboards/mode/m65v2/mcuconf.h | 22 +++ keyboards/mode/m65v2/readme.md | 23 +++ 7 files changed, 294 insertions(+) create mode 100644 keyboards/mode/m65v2/config.h create mode 100644 keyboards/mode/m65v2/halconf.h create mode 100644 keyboards/mode/m65v2/keyboard.json create mode 100644 keyboards/mode/m65v2/keymaps/default/keymap.c create mode 100644 keyboards/mode/m65v2/m65v2.c create mode 100644 keyboards/mode/m65v2/mcuconf.h create mode 100644 keyboards/mode/m65v2/readme.md diff --git a/keyboards/mode/m65v2/config.h b/keyboards/mode/m65v2/config.h new file mode 100644 index 0000000000..c34b7e5a8b --- /dev/null +++ b/keyboards/mode/m65v2/config.h @@ -0,0 +1,25 @@ +/* + Copyright 2025 Gondolindrim + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#define WS2812_PWM_COMPLEMENTARY_OUTPUT +#define WS2812_PWM_DRIVER PWMD1 +#define WS2812_PWM_CHANNEL 3 +#define WS2812_PWM_PAL_MODE 1 +#define WS2812_PWM_DMA_STREAM STM32_DMA2_STREAM5 +#define WS2812_PWM_DMA_CHANNEL 6 diff --git a/keyboards/mode/m65v2/halconf.h b/keyboards/mode/m65v2/halconf.h new file mode 100644 index 0000000000..6c98f31f9b --- /dev/null +++ b/keyboards/mode/m65v2/halconf.h @@ -0,0 +1,21 @@ +/* Copyright 2025 Gondolindrim + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#define HAL_USE_PWM TRUE + +#include_next diff --git a/keyboards/mode/m65v2/keyboard.json b/keyboards/mode/m65v2/keyboard.json new file mode 100644 index 0000000000..ec9c4a807f --- /dev/null +++ b/keyboards/mode/m65v2/keyboard.json @@ -0,0 +1,135 @@ +{ + "manufacturer": "Mode", + "keyboard_name": "Mode M65 V2", + "maintainer": "Gondolindrim", + "bootloader": "stm32-dfu", + "diode_direction": "COL2ROW", + "eeprom": { + "wear_leveling": { + "backing_size": 4096 + } + }, + "features": { + "bootmagic": true, + "extrakey": true, + "mousekey": true, + "rgblight": true + }, + "matrix_pins": { + "cols": ["C8", "C7", "C6", "B14", "B12", "A10", "B5", "C10", "C12", "B3", "C9", "B8", "B9", "C15", "C13", "C14"], + "rows": ["B0", "B1", "C5", "B10", "C4", "A8"] + }, + "processor": "STM32F401", + "qmk": { + "locking": { + "enabled": true, + "resync": true + } + }, + "rgblight": { + "animations": { + "alternating": true, + "breathing": true, + "christmas": true, + "knight": true, + "rainbow_mood": true, + "rainbow_swirl": true, + "snake": true, + "static_gradient": true, + "twinkle": true + }, + "default": { + "animation": "rainbow_swirl", + "hue": 23, + "sat": 219, + "val": 140 + }, + "led_count": 36, + "led_map": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 31, 32, 33, 34, 35, 29, 30] + }, + "usb": { + "device_version": "0.0.1", + "pid": "0x6665", + "vid": "0x00DE" + }, + "ws2812": { + "driver": "pwm", + "pin": "B15" + }, + "layouts": { + "LAYOUT": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0}, + {"matrix": [0, 1], "x": 1, "y": 0}, + {"matrix": [0, 2], "x": 2, "y": 0}, + {"matrix": [0, 3], "x": 3, "y": 0}, + {"matrix": [0, 4], "x": 4, "y": 0}, + {"matrix": [0, 5], "x": 5, "y": 0}, + {"matrix": [0, 6], "x": 6, "y": 0}, + {"matrix": [0, 7], "x": 7, "y": 0}, + {"matrix": [0, 8], "x": 8, "y": 0}, + {"matrix": [0, 9], "x": 9, "y": 0}, + {"matrix": [0, 10], "x": 10, "y": 0}, + {"matrix": [0, 11], "x": 11, "y": 0}, + {"matrix": [0, 12], "x": 12, "y": 0}, + {"matrix": [0, 13], "x": 13, "y": 0}, + {"matrix": [0, 14], "x": 14, "y": 0}, + {"matrix": [0, 15], "x": 15, "y": 0}, + {"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5}, + {"matrix": [1, 1], "x": 1.5, "y": 1}, + {"matrix": [1, 2], "x": 2.5, "y": 1}, + {"matrix": [1, 3], "x": 3.5, "y": 1}, + {"matrix": [1, 4], "x": 4.5, "y": 1}, + {"matrix": [1, 5], "x": 5.5, "y": 1}, + {"matrix": [1, 6], "x": 6.5, "y": 1}, + {"matrix": [1, 7], "x": 7.5, "y": 1}, + {"matrix": [1, 8], "x": 8.5, "y": 1}, + {"matrix": [1, 9], "x": 9.5, "y": 1}, + {"matrix": [1, 10], "x": 10.5, "y": 1}, + {"matrix": [1, 11], "x": 11.5, "y": 1}, + {"matrix": [1, 12], "x": 12.5, "y": 1}, + {"matrix": [1, 14], "x": 13.5, "y": 1, "w": 1.5}, + {"matrix": [1, 15], "x": 15, "y": 1}, + {"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75}, + {"matrix": [2, 1], "x": 1.75, "y": 2}, + {"matrix": [2, 2], "x": 2.75, "y": 2}, + {"matrix": [2, 3], "x": 3.75, "y": 2}, + {"matrix": [2, 4], "x": 4.75, "y": 2}, + {"matrix": [2, 5], "x": 5.75, "y": 2}, + {"matrix": [2, 6], "x": 6.75, "y": 2}, + {"matrix": [2, 7], "x": 7.75, "y": 2}, + {"matrix": [2, 8], "x": 8.75, "y": 2}, + {"matrix": [2, 9], "x": 9.75, "y": 2}, + {"matrix": [2, 10], "x": 10.75, "y": 2}, + {"matrix": [2, 11], "x": 11.75, "y": 2}, + {"matrix": [2, 13], "x": 12.75, "y": 2}, + {"matrix": [2, 14], "x": 13.75, "y": 2, "w": 1.25}, + {"matrix": [2, 15], "x": 15, "y": 2}, + {"matrix": [3, 0], "x": 0, "y": 3, "w": 1.25}, + {"matrix": [3, 1], "x": 1.25, "y": 3}, + {"matrix": [3, 2], "x": 2.25, "y": 3}, + {"matrix": [3, 3], "x": 3.25, "y": 3}, + {"matrix": [3, 4], "x": 4.25, "y": 3}, + {"matrix": [5, 5], "x": 5.25, "y": 3}, + {"matrix": [5, 6], "x": 6.25, "y": 3}, + {"matrix": [5, 7], "x": 7.25, "y": 3}, + {"matrix": [5, 8], "x": 8.25, "y": 3}, + {"matrix": [5, 9], "x": 9.25, "y": 3}, + {"matrix": [5, 10], "x": 10.25, "y": 3}, + {"matrix": [5, 11], "x": 11.25, "y": 3}, + {"matrix": [5, 12], "x": 12.25, "y": 3, "w": 1.75}, + {"matrix": [5, 14], "x": 14, "y": 3}, + {"matrix": [5, 15], "x": 15, "y": 3}, + {"matrix": [4, 0], "x": 0, "y": 4, "w": 1.25}, + {"matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25}, + {"matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25}, + {"matrix": [4, 6], "x": 3.75, "y": 4, "w": 6.25}, + {"matrix": [4, 10], "x": 10, "y": 4, "w": 1.25}, + {"matrix": [4, 11], "x": 11.25, "y": 4, "w": 1.25}, + {"matrix": [4, 13], "x": 13, "y": 4}, + {"matrix": [4, 14], "x": 14, "y": 4}, + {"matrix": [4, 15], "x": 15, "y": 4} + ] + } + } +} diff --git a/keyboards/mode/m65v2/keymaps/default/keymap.c b/keyboards/mode/m65v2/keymaps/default/keymap.c new file mode 100644 index 0000000000..7423d300c5 --- /dev/null +++ b/keyboards/mode/m65v2/keymaps/default/keymap.c @@ -0,0 +1,35 @@ +/* +Copyright 2025 Gondolindrim + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = LAYOUT( + KC_ESC , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_MINS, KC_EQL , KC_BSPC, KC_BSPC, KC_DEL , + KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP, + KC_CAPS, KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT , KC_PGDN, + KC_LSFT, KC_NUBS, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM, KC_DOT , KC_SLSH, KC_RSFT, KC_UP , KC_END , + KC_LCTL, KC_LGUI, KC_LALT, KC_SPC , KC_RALT, MO(1) , KC_LEFT, KC_DOWN, KC_RGHT + ), + [1] = LAYOUT( + QK_BOOT, KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 , KC_F12 , KC_TRNS, KC_TRNS, KC_MUTE, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLU, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLD, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + ) +}; diff --git a/keyboards/mode/m65v2/m65v2.c b/keyboards/mode/m65v2/m65v2.c new file mode 100644 index 0000000000..616a348846 --- /dev/null +++ b/keyboards/mode/m65v2/m65v2.c @@ -0,0 +1,33 @@ +/* Copyright 2025 Gondolindrim + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "quantum.h" + +void keyboard_post_init_kb(void) { + led_update_kb(host_keyboard_led_state()); + rgblight_set_effect_range(0, 34); + keyboard_post_init_user(); +} + +bool led_update_kb(led_t led_state) { + bool res = led_update_user(led_state); + if (res) { + hsv_t current_color = rgblight_get_hsv(); + led_state.caps_lock ? rgblight_sethsv_at(current_color.h, current_color.s, current_color.v, 34) : rgblight_sethsv_at(HSV_OFF, 34); + led_state.caps_lock ? rgblight_sethsv_at(current_color.h, current_color.s, current_color.v, 35) : rgblight_sethsv_at(HSV_OFF, 35); + } + return res; +} diff --git a/keyboards/mode/m65v2/mcuconf.h b/keyboards/mode/m65v2/mcuconf.h new file mode 100644 index 0000000000..ff2280716d --- /dev/null +++ b/keyboards/mode/m65v2/mcuconf.h @@ -0,0 +1,22 @@ +/* Copyright 2020 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include_next + +#undef STM32_PWM_USE_TIM1 +#define STM32_PWM_USE_TIM1 TRUE diff --git a/keyboards/mode/m65v2/readme.md b/keyboards/mode/m65v2/readme.md new file mode 100644 index 0000000000..046b5128d5 --- /dev/null +++ b/keyboards/mode/m65v2/readme.md @@ -0,0 +1,23 @@ +# Mode M65 PCB V2 + +![Image Gallery](https://i.imgur.com/D2hUT7y.jpeg) + +The Mode M65 V2 is 65% PCB for the Mode line of keyboards. As of march 2026, the models compatible with this PCB are the Encore Envoy and SixtyFive. This firmware fits both solderable and hotswap variants. + +* Keyboard Maintainer: [Gondolindrim](https://github.com/gondolindrim) +* Hardware Supported: proprietary PCB using STM32F401 controller +* Hardware Availability: at the Mode Designs website. + +## Flashing instructions + +First you need to put the PCB in DFU mode through the bootloader. This is done in 3 ways: + +* **Bootmagic reset**: Hold down the key ESC key and plug in the keyboard (top Left most switch) +* **Keycode in layout**: Press the key mapped to `QK_BOOT` if available +* **Physical Reset Button**: hold down the button on the back of the PCB for at least five seconds. + +Flashing example for this keyboard: + + make mode/m65v2:default:flash + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).