百科.dev
全部条目AI 编程趋势榜开源项目技术资讯提交条目
登录
< 返回工具列表
Q

qmk_userspace

> 编程语言
开源

个人 QMK 固件用户空间

100 stars0 点赞0 次浏览
访问官网GitHub

工具介绍

个人 QMK 固件用户空间

Summary

This is my personal self-contained QMK keymap repository that can be built in the userspace folder or using GitHub Actions with its workflow.

Custom Features

  • Contextual mod-taps
  • Layout wrapper macros
  • Combos with preprocessors
  • Autocorrect word processing
  • RGB matrix indicators and custom effects

   

Contextual Mod-Taps

Home row mods are especially useful on compact split keyboards, and their accuracy can be improved through context-aware settings. By evaluating the keys pressed before and after a mod-tap key, we can refine QMK's Tap-Hold functionality using these simple rules:

  1. When the mod-tap key is pressed immediately after a letter key, it registers as a tap.
  2. When the mod-tap key is immediately followed by another key on the same hand, it registers as a tap.
  3. In all other cases, the mod-tap key registers as a hold when used in combination with any other key.

Mod-Tap Decision Macros

Define the following boolean macros, which serve as the primary decision logic for contextual mod-tap behaviour. These macros simplify and centralize the rules that determine tap-hold actions based on keyboard context within QMK’s key event processing functions.

…

Shift is excluded from the home row modifier match to allow for quicker capitalization. This behaviour can also be accomplished with flow tap, but it requires significantly more code.

Strict Unilateral Tap

To prevent accidental modifier activation when overlapping keys are pressed on the same hand, the mod-tap key will register as a tap if the next key pressed is also on the same side of the keyboard. This behaviour is handled by the get_hold_on_other_key_press function:

c
bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) {
    if (IS_UNILATERAL_INPUT(record, inter_record)) {
        // Flag key as tapped and update the key record tap count.
        tap_bit_t tap = TAP_BIT_FROM_KEYCODE(keycode);
        pressed_keys[tap.index] |= tap.bitmask;
        record->tap.interrupted = false;
        record->tap.count++;
        return true;
    }
    // Any tap-hold code handling beyond this point
    // will be considered opposite hand or bilateral.

    return false;
}

The unilateral conditional statement can be adjusted to allow activation of two or more modifiers on the same hand. Alternatively, this can be achieved—though with a much larger code size—by using chordal hold.

Permissive bilateral hold

With the previous unilateral tap configured, all other overlapping hold-tap combinations will be considered opposite hand or bilateral. Applying permissive hold to these cases allows modifiers to be registered more easily:

c
bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) {
    // Register modifier with a nested tap on the opposite hand.
    return IS_QK_MOD_TAP(keycode);
}

Permissive hold can be tailored to match specific modifiers for frequent use cases, such as Shift, or to exclude destructive ones like Ctrl.

Integration Summary

The contextual implementation uses the keycode container in the keyrecord_t structure, which requires either the REPEAT_KEY_ENABLE or COMBO_ENABLE feature. These functions will have no effect after the TAPPING_TERM delay. The output experience will be similar to ZMK's require-prior-idle-ms option and positional hold tap feature.

   

Layout Wrapper Macros

A single keymap layout can be shared across multiple keyboards using C preprocessor macros. These macros are referenced in the keyboard JSON files, and the build process expands them into a transient keymap.c file at compile time.

Basic setup

The split_3x5_2 layout serves as the base, with layers defined in layout.h. Here is an example of a default layer:

c
#define BASE \
    KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,      KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    \
    KC_A,    KC_S,    KC_D,    KC_F,    KC_G,      KC_H,    KC_J,    KC_K,    KC_L,    KC_QUOT, \
    KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,      KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, \
                  LT(SYM,KC_TAB), LCA_T(KC_ENT),   RSFT_T(KC_SPC), LT(NUM,KC_BSPC)

Next, define a wrapper alias for the layout used by the keyboard in the layout.h file. For example, the following creates a wrapper alias for the Cradio layout:

c
#define LAYOUT_34key_w(...) LAYOUT_split_3x5_2(__VA_ARGS__)

Macros are not replaced recursively in a single step. A wrapper alias is required for the compiler to expand them over multiple iterations.

Both layout and layer macros are referenced in the keyboard JSON file (cradio.json) as follows:

c
{
    "keyboard": "cradio",
    "keymap": "filterpaper",
    "layout": "LAYOUT_34key_w",
    "layers": [
        [ "BASE" ],
        [ "NUMB" ],
        [ "SYMB" ],
        [ "FUNC" ]
    ]
}

To include the layout macros from layout.h, add the following line to the config.h file:

c
#ifndef __ASSEMBLER__
#    include layout.h
#endif

The assembler definition prevents this file from being included in builds where C opcodes are not valid.

Running qmk compile cradio.json will cause the build process to construct a transient keymap.c using the wrapper macros for compilation.

Wrapping home row modifiers

Home row mods can be added to the layout macros in the same way. The order of the home row modifiers is defined by these two macros:

c
#define HRML(k1,k2,k3,k4)  LCTL_T(k1), LALT_T(k2), LGUI_T(k3), LSFT_T(k4)
#define HRMR(k1,k2,k3,k4)  RSFT_T(k1), RGUI_T(k2), RALT_T(k3), RCTL_T(k4)

Both are then used to transform the home row elements in the following HRM wrapper macro for the split_3x5_2 layout:

c
#define HRM(k) HRM_TAPHOLD(k)
#define HRM_TAPHOLD( \
      l01, l02, l03, l04, l05,    r01, r02, r03, r04, r05,       \
      l06, l07, l08, l09, l10,    r06, r07, r08, r09, r10,       \
      l11, l12, l13, l14, l15,    r11, r12, r13, r14, r15,       \
                     l16, l17,    r16, r17                       \
) \
      l01, l02, l03, l04, l05,    r01, r02, r03, r04, r05,       \
HRML(l06, l07, l08, l09), l10,    r06, HRMR(r07, r08, r09, r10), \
      l11, l12, l13, l14, l15,    r11, r12, r13, r14, r15,       \
                     l16, l17,    r16, r17

The HRM() macro can now be used in the JSON file to add home row modifiers for layers that require them. For example:

c
"layers": [
    [ "HRM(BASE)" ],
    [ "HRM(COLE)" ],
    [ "NUMB" ],
    [ "SYMB" ],
    [ "FUNC" ]
],

With this setup, the home row modifier order can be easily changed in the HRML and HRMR macros.

Adapting for a different layout

The base layout can be adapted for other split keyboards by expanding it with macros. The following example expands the split_3x5_2 layout to Corne's 42-key 3x6_3 layout (6 columns, 3 thumb keys) using a wrapper to add keys to the outer columns:

…

The JSON file for Corne (corne.json) will use the conversion and HRM macro in the following format:

c
{
    "keyboard": "crkbd/rev1",
    "keymap": "filterpaper",
    "layout": "LAYOUT_corne_w",
    "layers": [
        [ "C_42(HRM(BASE))" ],
        [ "C_42(NUMB)" ],
        [ "C_42(SYMB)" ],
        [ "C_42(FUNC)" ]
    ]
}

   

Code Snippets

Light configured layers keys

c
bool rgb_matrix_indicators_user(void) {
    if (get_highest_layer(layer_state) > 0) {
        uint8_t const layer = get_highest_layer(layer_state);
        for (uint8_t row = 0; row  Pro Micro GND
USBasp RST   Pro Micro RST
USBasp VCC   Pro Micro VCC
USBasp SCLK  Pro Micro 15/B1 (SCLK)
USBasp MISO  Pro Micro 14/B3 (MISO)
USBasp MOSI  Pro Micro 16/B2 (MOSI)

Atmel DFU bootloader

To replace the Pro Micro's default Caterina bootloader with Atmel-DFU, use the following USBasp command and fuses parameter:

c
avrdude -c usbasp -P usb -p atmega32u4 \
-U flash:w:bootloader_atmega32u4_1.0.0.hex:i \
-U lfuse:w:0x5E:m -U hfuse:w:0xD9:m -U efuse:w:0xF3:m

See the QMK ISP Flashing Guide for more details.

Command line flashing

To flash firmware to an AVR controller with Atmel DFU bootloader on macOS, use the following bash or zsh shell alias. It requires dfu-programmer from Homebrew to be installed:

…

   

Useful Links

  • Paroxysm PCB
  • Split Keyboard database
  • Sockets
  • Git Purr
  • Data in Program Space

Hardware Parts

  • Helios RP2040 clone
  • Adafruit KB2040
  • Elite-Pi
  • Mill-Max 315-43-112-41-003000 low profile sockets
  • Mill-Max 315-43-164-41-001000 mid profile sockets
  • Mill-Max connector pins
  • PJ320A jack
  • TRRS cable
  • Silicone bumpers feet
  • Kailh gchoc v1 switches

Issues· 0 开放

查看全部 Issues在 GitHub 打开

暂无开放 Issues,或尚未同步最近议题。

> 标签

Ckeyboardqmkqmk-keymap

暂无评论,来聊聊你的看法吧

> 工具信息

发布日期2026年8月1日
最后更新2026年9月18日
分类编程语言
定价开源

> 相关工具

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言