Coder Social home page Coder Social logo

zmk-config's Introduction

urob's zmk-config

This is my personal ZMK firmware configuration. It consists of a 34-keys base layout that is re-used for various boards, including my Corneish Zen and my Planck.

This branch is updated for the latest ZMK using Zephyr 3.5. A legacy version compatible with Zephyr 3.0 is available here.

Highlights

  • clean keymap + unicode setup using helper macros from zmk-helpers
  • the base keymap and combo setup are independent of the physical location of keys and are re-used for multiple keyboards. The configuration is fit onto larger boards by padding it via a modular structure of "extra keys"
  • "timeless" homerow mods
  • combos replacing the symbol layer
  • smart numbers and smart mouse layers that automatically toggle off when done
  • sticky shift on right thumb, double-tap (or shift + tap)1 activates caps-word
  • arrow-cluster doubles as home, end, begin/end of document on long-press
  • more intuitive shift-actions: , ;, . : and ? !
  • shift + space morphs into dotspacesticky-shift
  • "Greek" layer for mathematical typesetting (activated as sticky-layer via a combo)
  • modified Github Actions workflow that recognizes git-submodules
  • automated build-scripts for local and Docker-based building (independently of VS Code)

Timeless homerow mods

Homerow mods (aka "HRMs") can be a game changer -- at least in theory. In practice, they require some finicky timing: In its most naive implementation, in order to produce a "mod", they must be held longer than tapping-term-ms. In order to produce a "tap", they must be held less than tapping-term-ms. This requires very consistent typing speeds that, alas, I do not possess. Hence my quest for a "timer-less" HRM setup.2

After months of tweaking, I eventually ended up with a HRM setup that is essentially timer-less, resulting in virtually no misfires. Yet it provides a fluent typing experience with mostly no delays.

Let's suppose for a moment we set tapping-term-ms to something ridiculously large, say 5 seconds. This makes the configuration timer-less of sorts. But it has two problems: (1) To activate a mod we will have to hold the HRM keys for what feels like eternity. (2) During regular typing, there are delays between the press of a key and the time it appears on the screen.3 Enter two my favorite ZMK features:

  • To address the first problem, I use ZMK's balanced flavor, which produces a "hold" if another key is both pressed and released within the tapping-term. Because that is exactly what I normally do with HRMs, there is virtually never a need to wait past my long tapping term (see below for two exceptions).
  • To address the typing delay, I use ZMK's require-prior-idle-ms property, which immediately resolves a HRM as "tap" when it is pressed shortly after another key has been tapped. This all but completely eliminates the delay.

This is great but there are still a few rough edges:

  • When rolling keys, I sometimes unintentionally end up with "nested" key sequences: key 1 down, key 2 down and up, key 1 up. Because of the balanced flavor, this would falsely register key 1 as a mod. As a remedy, I use ZMK's positional hold-tap feature to force HRMs to always resolve as "tap" when the next key is on the same side of the keyboard. Problem solved.
  • ... or at least almost. By default, positional-hold-tap performs the positional check when the next key is pressed. This is not ideal, because it prevents combining multiple modifiers on the same hand. To fix this, I use the hold-trigger-on-release setting, which delays the positional-hold-tap decision until the next key's release. With the setting, multiple mods can be combined when held, while I still get the benefit from positional-hold-tap when keys are tapped.
  • So far, nothing of the configuration depends on the duration of tapping-term-ms. In practice, there are two reasons why I don't set it to infinity:
    1. Sometimes, in rare circumstances, I want to combine a mod with a alpha-key on the same hand (e.g., when using the mouse with the other hand). My positional hold-tap configuration prevents this within the tapping term. By setting the tapping term to something large but not crazy large (I use 280ms), I can still use same-hand mod + alpha shortcuts by holding the mod for just a little while before tapping the alpha-key.
    2. Sometimes, I want to press a modifier without another key (e.g., on Windows, tapping Win opens the search menu). Because the balanced flavour only kicks in when another key is pressed, this also requires waiting past tapping-term-ms.
  • Finally, it is worth noting that this setup works best in combination with a dedicated shift for capitalization during normal typing (I like sticky-shift on a home-thumb). This is because shifting alphas is the one scenario where pressing a mod may conflict with require-prior-idle-ms, which may result in false negatives when typing fast.

Here's my configuration (I use a bunch of helper macros to simplify the syntax, but they are not necessary):

/* use helper macros to define left and right hand keys */
#include "zmk-helpers/key-labels/36.h"                                      // key-position labels
#define KEYS_L LT0 LT1 LT2 LT3 LT4 LM0 LM1 LM2 LM3 LM4 LB0 LB1 LB2 LB3 LB4  // left-hand keys
#define KEYS_R RT0 RT1 RT2 RT3 RT4 RM0 RM1 RM2 RM3 RM4 RB0 RB1 RB2 RB3 RB4  // right-hand keys
#define THUMBS LH2 LH1 LH0 RH0 RH1 RH2                                      // thumb keys

/* left-hand HRMs */
ZMK_HOLD_TAP(hml,
    flavor = "balanced";
    tapping-term-ms = <280>;
    quick-tap-ms = <175>;                // repeat on tap-into-hold
    require-prior-idle-ms = <150>;
    bindings = <&kp>, <&kp>;
    hold-trigger-key-positions = <KEYS_R THUMBS>;
    hold-trigger-on-release;             // delay positional check until key-release
)

/* right-hand HRMs */
ZMK_HOLD_TAP(hmr,
    flavor = "balanced";
    tapping-term-ms = <280>;
    quick-tap-ms = <175>;                // repeat on tap-into-hold
    require-prior-idle-ms = <150>;
    bindings = <&kp>, <&kp>;
    hold-trigger-key-positions = <KEYS_L THUMBS>;
    hold-trigger-on-release;             // delay positional check until key-release
)

Required firmware

After a recent round of patches, the above configuration now works with upstream ZMK.

Other parts of my configuration still require a few PRs that aren't yet in upstream ZMK. My personal ZMK fork includes all PRs needed to compile my configuration. If you prefer to maintain your own fork with a custom selection of PRs, you might find this ZMK-centric introduction to Git helpful.

Troubleshooting

Hopefully, the above configuration "just works". If it doesn't, here's a few smaller (and larger) things to try.

  • Noticeable delay when tapping HRMs: Increase require-prior-idle-ms. As a rule of thumb, you want to set it to at least 10500/x where x is your (relaxed) WPM for English prose.4
  • False negatives (same-hand): Reduce tapping-term-ms (or disable hold-trigger-key-positions)
  • False negatives (cross-hand): Reduce require-prior-idle-ms (or set flavor to hold-preferred -- to continue using hold-trigger-on-release, you must also patch ZMK or use an already patched branch)
  • False positives (same-hand): Increase tapping-term-ms
  • False positives (cross-hand): Increase require-prior-idle-ms (or set flavor to tap-preferred, which requires holding HRMs past tapping term to activate)

Using combos instead of a symbol layer

I am a big fan of combos for all sort of things. In terms of comfort, I much prefer them over accessing layers that involve lateral thumb movements to be activated, especially when switching between different layers in rapid succession.

One common concern about overloading the layout with combos is that they lead to misfires. Fortunately, the above-mentioned require-prior-idle-ms option also works for combos, which in my experience all but completely eliminates the problem -- even when rolling keys on the home row!

My combo layout aims to place the most used symbols in easy-to-access locations while also making them easy to remember. Specifically:

  • the top vertical-combo row matches the symbols on a standard numbers row (except + and & being swapped)
  • the bottom vertical-combo row is symmetric to the top row (subscript _ aligns with superscript ^; minus - aligns with +; division / aligns with multiplication *; logical-or | aligns with logical-and &)
  • parenthesis, braces, brackets are set up symmetrically as horizontal combos with <, >, { and } being accessed from the Navigation layer (or when combined with Shift)
  • left-hand side combos for tap, esc, enter, cut (on X + D), copy and paste that go well with right-handed mouse usage
  • L + Y switches to the Greek layer for a single key press, L + U + Y activates one-shot shift in addition
  • W + P activates the smart mouse layer

Smart layers and other gimmicks

Numword

Inspired by Jonas Hietala's Numword for QMK, I implemented my own version of Smart-layers for ZMK. It is triggered via a single tap on "Smart-Num". Numword continues to be activated as long as I type numbers, and deactivates automatically on any other keypress (holding it activates a non-sticky num layer).

After using Numword for more than a year now, I have been overall very happy with it. When typing single digits, it effectively is a sticky-layer but with the added advantage that I can also use it to type multiple digits.

The main downside is that if a sequence of numbers is immediately followed by any of the letters on which my numpad is located (WFPRSTXCD), then the automatic deactivation won't work. But this is rare -- most number sequences are terminated by space, return or some form of punctuation/delimination. To deal with the rare cases where they aren't, there is a CANCEL key on the navigation-layer that deactivates Numword, Capsword and Smart-mouse. (It also toggles off when pressing Numword again, but I find it cognitively easier to have a dedicated "off-switch" than keeping track of which modes are currently active.)

Smart-Mouse

Similarly to Numword, I have a smart-mouse layer (activated by comboing W + P), which replaces the navigation cluster with scroll and mouse-movements, and replaces the right thumbs with mouse buttons. Pressing any other key automatically deactivates the layer.

Capsword

My right thumb triggers three variations of shift: Tapping yields sticky-shift (used to capitalize alphas), holding activates a regular shift, and double-tapping (or equivalently shift + tap) activates ZMK's Caps-word behavior.

One minor technical detail: While it would be possible to implement the double-tap functionality as a tap-dance, this would add a delay when using single taps. To avoid the delays, I instead implemented the double-tap functionality as a mod-morph.

Multi-purpose Navigation cluster

To economize on keys, I am using hold-taps on my navigation cluster, which yield home, end, begin/end of document, and delete word forward/backward on long-presses. The exact implementation is tweaked so that Ctrl is silently absorbed in combination with home and end to avoid accidental document-wide operations (which are accessible via the dedicated begin/end document keys.)

Swapper

I am using Nick Conway's fantastic tri-state behavior for a one-handed Alt-Tab switcher (PWin and NWin).

Repeat

I recently switched to 25g-chocs on one of my keyboards. I already was very happy with my combos prior to that (even with heavy-ish MX-switches). But with the light chocs, I find that I can now even use them for regular typing. While I haven't yet tried placing alphas on combos, I am currently experimenting with a repeat combo on my home row that I use to reduce SFUs when typing double-letter words.

Issues and workarounds

Since I switched from QMK to ZMK I have been very impressed with how easy it is to set up relatively complex layouts in ZMK. For the most parts I don't miss any functionality (to the contrary, I found that ZMK supports many features natively that would require complex user-space implementations in QMK). Below are a few remaining issues:

  • ZMK does not yet support "tap-only" combos (#544), requiring a brief pause when wanting to chord HRMs that overlap with combo positions. As a workaround, I implemented all homerow combos as homerow-mod-combos. This is good enough for day-to-day, but does not address all edge cases (eg dynamically adding/removing mods doesn't work well). Having a native solution akin to QMK's "COMBO_MUST_TAP" property would be fantastic.
  • Another item on my wishlist are adaptive keys (#1624). This would open the door for things like spacespace becoming .spacesticky-shift. (Using tap-dance isn't really an option here due to the delay it adds)
  • A minor thing is that ZMK doesn't yet support any keys on the desktop-user-page; e.g., OS sleep (#1077, #1535)
  • Very minor: &bootloader doesn't work with stm32 boards like the Planck (#1086)

Footnotes

  1. Really what's happening is that Shift + my right home-thumb morph into caps-word. This gives me two separate ways of activating it: (1) Holding the homerow-mod shift on my left index-finger and then pressing my right home-thumb, which is my new preferred way. Or, (2) double-tapping the right home-thumb, which also works because the first tap yields sticky-shift, activating the mod-morph upon the second tap. But even when only activating via double-tapping, this implementation is advantageous compared to using tap-dance as it does not create any delay when single-tapping the key.

  2. I call it "timer-less", because the large tapping-term makes the behavior insensitive to the precise timings. One may say that there is still the require-prior-idle timeout. However, with both a large tapping-term and positional-hold-taps, the behavior is not actually sensitive to the require-prior-idle timing: All it does is reduce the delay in typing; i.e., variations in typing speed won't affect what is being typed but merely how fast it appears on the screen.

  3. The delay is determined by how quickly a key is released and is not directly related to the tapping-term. But regardless of its length, most people still find it noticable and disruptive.

  4. E.g, if your WPM is 70 or larger, then the default of 150ms (=10500/70) should work well. The rule of thumb is based on an average character length of 4.7 for English words. Taking into account 1 extra tap for space, this yields a minimum require-prior-idle-ms of (60 _ 1000) / (5.7 _ x) ≈ 10500 / x milliseconds. The approximation errs on the safe side, as in practice home row taps tend to be faster than average.

zmk-config's People

Contributors

urob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zmk-config's Issues

Question

How do you create/generate this beautiful image of your layout?

image

star and fslh combo is not working

The combo "star" and "flslh" does not work.

I am writing firmware for Ferris Sweep 34key based on your repository.

I copied and used the files like combos.dtsi, etc. and modified the base.keymap as follows.

I think it has something to do with the "RM2" key working up and down, but I can't find the exact reason.

Any help would be appreciated.
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#if CONFIG_WIRELESS
#include <dt-bindings/zmk/bt.h>
#define BT_SEL_KEYS &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_CLR
#else
#define BT_SEL_KEYS &trans &trans &trans &trans &trans
#endif

#include "helper.h"

#define DEF 0
#define NAV 1
#define FN 2
#define NUM 3
#define SYS 4
#define UC 5
#define MOUSE 6

#include "combos.dtsi" // requires layer aliases
#include "mouse.dtsi"
#include "extra_keys.h"

#define XXX &none
#define ___ &trans

/* Global settings */

#define QUICK_TAP_MS 175

&sk { // sticky-key config
release-after-ms = <600>; // release after 0.6s
quick-release; // no double capitalization when rolling keys
};

&sl { // sticky-layer config
ignore-modifiers; // allow chording sticky mods & layers
};

&lt { // layer-tap config
flavor = "balanced";
tapping-term-ms = <200>;
quick-tap-ms = <QUICK_TAP_MS>;
};

/* Homerow mods */

#define KEYS_L LT0 LT1 LT2 LT3 LT4 LM0 LM1 LM2 LM3 LM4 LB0 LB1 LB2 LB3 LB4 // left hand
#define KEYS_R RT0 RT1 RT2 RT3 RT4 RM0 RM1 RM2 RM3 RM4 RB0 RB1 RB2 RB3 RB4 // right hand
#define THUMBS LH1 LH0 RH0 RH1 // thumbs

#define MAKE_HRM(NAME, HOLD, TAP, TRIGGER_POS)
ZMK_BEHAVIOR(NAME, hold_tap,
flavor = "balanced";
tapping-term-ms = <280>;
quick-tap-ms = <QUICK_TAP_MS>;
global-quick-tap-ms = <150>;
bindings = , ;
hold-trigger-key-positions = <TRIGGER_POS>;
hold-trigger-on-release;
)
MAKE_HRM(hml, &kp, &kp, KEYS_R THUMBS) // left-hand HRMs
MAKE_HRM(hmr, &kp, &kp, KEYS_L THUMBS) // right-hand HRMs

MAKE_HRM(hml_repeat, &kp, &key_repeat, KEYS_R THUMBS) // used for HRM-combo
MAKE_HRM(hmr_lpar_lt, &kp, &lpar_lt, KEYS_L THUMBS) // " " " "
MAKE_HRM(hmr_rpar_gt, &kp, &rpar_gt, KEYS_L THUMBS) // " " " "

/* Nav cluster */

// long-tap action on hold, short-tap action on all interrupts
#define MT_CORE
flavor = "tap-preferred";
tapping-term-ms = <220>;
quick-tap-ms = <220>;
hold-trigger-key-positions = <0>;

&mt { MT_CORE };
ZMK_BEHAVIOR(mt_home, hold_tap, bindings = <&masked_home>, <&kp>; MT_CORE)
ZMK_BEHAVIOR(mt_end, hold_tap, bindings = <&masked_end>, <&kp>; MT_CORE)

#define NAV_LEFT &mt_home 0 LEFT // tap: left | long-tap: beginning of line
#define NAV_RIGHT &mt_end 0 RIGHT // tap: right | long-tap: end of line
#define NAV_UP &mt LC(HOME) UP // tap: up | long-tap: beginning of document
#define NAV_DOWN &mt LC(END) DOWN // tap: down | long-tap: end of document
#define NAV_BSPC &mt LC(BSPC) BSPC // tap: bspc | long-tap: delete word backward
#define NAV_DEL &mt LC(DEL) DEL // tap: del | long-tap: delete word forward

// mask CTRL when holding left/right to avoid accidental jumps to beginning/end of document
#define MASK_MODS(NAME, MODS, BINDING)
ZMK_BEHAVIOR(NAME, mod_morph,
bindings = , ;
mods = ;
)
MASK_MODS(masked_home, (MOD_LCTL), &kp HOME)
MASK_MODS(masked_end, (MOD_LCTL), &kp END)

/* Caps-word, num-word and smart-mouse */

// tap: sticky-shift | shift + tap/ double-tap: caps-word | hold: shift
ZMK_BEHAVIOR(smart_shft, mod_morph,
bindings = <&sk LSHFT>, <&caps_word>;
mods = <(MOD_LSFT)>;
)
&caps_word { // mods deactivate caps-word, requires PR #1441
/delete-property/ ignore-modifiers;
};

// tap: num-word | double-tap: sticky num-layer | hold: num-layer
#define SMART_NUM &smart_num NUM 0
ZMK_BEHAVIOR(smart_num, hold_tap,
flavor = "balanced";
tapping-term-ms = <200>;
quick-tap-ms = <QUICK_TAP_MS>;
bindings = <&mo>, <&num_dance>;
)
ZMK_BEHAVIOR(num_dance, tap_dance,
tapping-term-ms = <200>;
bindings = <&num_word>, <&sl NUM>; // reverse this for sticky-num on single tap
)
&num_word { // num-word, requires PR #1441
layers = ;
};

// smart-mouse, requires PR #1366
ZMK_BEHAVIOR(smart_mouse, tri_state,
bindings = <&tog MOUSE>, <&none>, <&tog MOUSE>;
ignored-key-positions = ;
ignored-layers = ;
)

/* Custom behaviors */

// Alt+Tab swapper, requires PR #1366
ZMK_BEHAVIOR(swapper, tri_state,
bindings = <&kt LALT>, <&kp TAB>, <&kt LALT>;
ignored-key-positions = ;
)

// Sticky layer + sticky shift (workaround for issue #1421)
ZMK_BEHAVIOR(sls, sticky_key,
release-after-ms = <1000>;
bindings = <&uc_shift>;
ignore-modifiers;
)
ZMK_BEHAVIOR(uc_shift, macro,
wait-ms = <0>;
tap-ms = <1>;
bindings = <&macro_press &mo UC &kp LSHFT>
, <&macro_pause_for_release>
, <&macro_release &mo UC &kp LSHFT>;
)

// tap: comma | shift + tap: semicolon | ctrl + shift + tap: <
ZMK_BEHAVIOR(comma_morph, mod_morph,
mods = <(MOD_LSFT|MOD_RSFT)>;
bindings = <&kp COMMA>, <&comma_inner_morph>;
)
ZMK_BEHAVIOR(comma_inner_morph, mod_morph,
bindings = <&kp SEMICOLON>, <&kp LESS_THAN>;
mods = <(MOD_LCTL|MOD_RCTL)>;
)

// tap: dot | shift + tap: colon | ctrl + shift + tap: >
ZMK_BEHAVIOR(dot_morph, mod_morph,
bindings = <&kp DOT>, <&dot_inner_morph>;
mods = <(MOD_LSFT|MOD_RSFT)>;
)
ZMK_BEHAVIOR(dot_inner_morph, mod_morph,
bindings = <&kp COLON>, <&kp GREATER_THAN>;
mods = <(MOD_LCTL|MOD_RCTL)>;
)

// tap: qmark | shift + tap: excl
ZMK_BEHAVIOR(qexcl, mod_morph,
bindings = <&kp QMARK>, <&kp EXCL>;
mods = <(MOD_LSFT|MOD_RSFT)>;
)

// tap: space | shift + tap: dot -> space -> sticky shift | hold: activate layer
ZMK_BEHAVIOR(lt_spc, hold_tap,
flavor = "balanced";
tapping-term-ms = <200>;
quick-tap-ms = <QUICK_TAP_MS>;
bindings = <&mo>, <&spc_morph>;
)
ZMK_BEHAVIOR(spc_morph, mod_morph,
bindings = <&kp SPACE>, <&dot_spc>;
mods = <(MOD_LSFT|MOD_RSFT)>;
)
ZMK_BEHAVIOR(dot_spc, macro,
wait-ms = <0>;
tap-ms = <5>;
bindings = <&kp DOT &kp SPACE &sk LSHFT>;
)

// tap: backspace | lshft + tap: delete | rshft + tap: shift-delete
ZMK_BEHAVIOR(bs_del, mod_morph,
bindings = <&kp BSPC>, <&kp DEL>;
mods = <(MOD_LSFT|MOD_RSFT)>;
keep-mods = <MOD_RSFT>;
)

// tap: left-parenthesis | shft + tap: less-than
ZMK_BEHAVIOR(lpar_lt, mod_morph,
bindings = <&kp LPAR>, <&kp LT>;
mods = <(MOD_LSFT|MOD_RSFT)>;
)

// tap: right-parenthesis | shft + tap: greater-than
ZMK_BEHAVIOR(rpar_gt, mod_morph,
bindings = <&kp RPAR>, <&kp GT>;
mods = <(MOD_LSFT|MOD_RSFT)>;
)

// tap: copy | double-tap: cut
ZMK_BEHAVIOR(copy_cut, tap_dance,
tapping-term-ms = <200>;
bindings = <&kp LC(INS)>, <&kp LC(X)>;
)

// Windows sleep key
ZMK_BEHAVIOR(win_sleep, macro,
wait-ms = <100>;
tap-ms = <5>;
bindings = <&kp LG(X) &kp U &kp S>;
)

// misc aliases
#define CANCEL &kp K_CANCEL // cancel caps-word, num-word and smart-mouse
#define DSK_PREV &hmr RSHFT LG(LC(LEFT)) // previous desktop
#define DSK_NEXT &hmr LALT LG(LC(RIGHT)) // next desktop
#define VOL_DOWN &hmr LCTRL C_VOL_DN

/* Keymap */

ZMK_CONDITIONAL_LAYER(DEF NAV, MOUSE) // FN + NAV --> MOUSE
ZMK_CONDITIONAL_LAYER(FN NUM, SYS) // FN + NUM --> SYS

ZMK_LAYER(base,
//╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮
X_LT &kp Q &kp W &kp E &kp R &kp T X_MT &kp Y &kp U &kp I &kp O &kp P X_RT
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LM &hml LGUI A &hml LALT S &hml LCTRL D &hml LSHFT F &kp G X_MM &kp H &hmr RSHFT J &hmr LCTRL K &hmr LALT L &hmr LGUI SQT X_RM
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LB &kp Z &kp X &kp C &kp V &kp B X_MB &kp N &kp M &comma_morph &dot_morph &qexcl X_RB
//├──────┤ ╰─────────────┼─────────────┴─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┴───────────────────────────╯ ├──────┤
X_LH &lt_spc NAV 0 &lt FN RET X_MH SMART_NUM &smart_shft X_RH
//╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯
)

ZMK_LAYER(nav,
//╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮
X_LT ___ ___ &kp LS(TAB) &swapper ___ X_MT &kp PG_UP NAV_BSPC NAV_UP NAV_DEL ___ X_RT
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LM &sk LGUI &sk LALT &sk LCTRL &sk LSHFT ___ X_MM &kp PG_DN NAV_LEFT NAV_DOWN NAV_RIGHT &kp RET X_RM
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LB ___ ___ ___ ___ ___ X_MB &kp INS &kp TAB &kp LT &kp GT ___ X_RB
//├──────┤ ╰─────────────┼─────────────┴─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┴───────────────────────────╯ ├──────┤
X_LH ___ ___ X_MH ___ CANCEL X_RH
//╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯
)

ZMK_LAYER(fn,
//╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮
X_LT &kp F12 &kp F7 &kp F8 &kp F9 ___ X_MT ___ &kp C_PREV &kp C_VOL_UP &kp C_NEXT &win_sleep X_RT
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LM &kp F11 &kp F4 &kp F5 &kp F6 ___ X_MM ___ DSK_PREV VOL_DOWN DSK_NEXT ___ X_RM
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LB &kp F10 &kp F1 &kp F2 &kp F3 ___ X_MB ___ ___ ___ ___ ___ X_RB
//├──────┤ ╰─────────────┼─────────────┴─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┴───────────────────────────╯ ├──────┤
X_LH ___ ___ X_MH &kp C_MUTE &kp C_PP X_RH
//╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯
)

ZMK_LAYER(num,
//╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮
X_LT ___ &kp N7 &kp N8 &kp N9 ___ X_MT ___ ___ ___ ___ ___ X_RT
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LM &hml LGUI N0 &hml LALT N4 &hml LCTRL N5 &hml LSHFT N6 ___ X_MM ___ ___ ___ ___ ___ X_RM
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LB ___ &kp N1 &kp N2 &kp N3 ___ X_MB ___ ___ ___ ___ ___ X_RB
//├──────┤ ╰─────────────┼─────────────┴─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┴───────────────────────────╯ ├──────┤
X_LH ___ ___ X_MH ___ ___ X_RH
//╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯
)

ZMK_LAYER(sys,
//╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮
X_LT BT_SEL_KEYS X_MT ___ ___ ___ ___ ___ X_RT
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LM ___ ___ ___ ___ &bootloader X_MM &bootloader ___ ___ ___ ___ X_RM
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LB ___ ___ ___ ___ &sys_reset X_MB &sys_reset ___ ___ ___ ___ X_RB
//├──────┤ ╰─────────────┼─────────────┴─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┴───────────────────────────╯ ├──────┤
X_LH ___ ___ X_MH ___ ___ X_RH
//╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯
)

ZMK_LAYER(mouse,
//╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭──────╮
X_LT ___ ___ ___ ___ ___ X_MT ___ U_WH_D U_MS_U U_WH_U ___ X_RT
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LM ___ ___ ___ ___ ___ X_MM ___ U_MS_L U_MS_D U_MS_R ___ X_RM
//├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├──────┤
X_LB ___ ___ ___ ___ ___ X_MB ___ ___ ___ ___ ___ X_RB
//├──────┤ ╰─────────────┼─────────────┴─────────────┼─────────────┼─────────────┤ ├──────┤ ├─────────────┼─────────────┼─────────────┴───────────────────────────╯ ├──────┤
X_LH ___ ___ X_MH U_BTN2 U_BTN1 X_RH
//╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯ ╰─────────────┴─────────────╯ ╰──────╯
)

/* vim: set ft=c tw=174: */

Mouse layer doesn't work over bluetooth

I'm using the Kinesis config as base but with urob/zmk adv360-led branch (using west.yaml).
I'm using Mac.

The mouse works but only over USB and not over bluetooth.
I saw in the zmk repo questions about that and everyone said that repairing fix this, but not in my case, so I wonder maybe something is special about the mouse support in this branch and/or due to me mixing Kinesis config with the adv-360 branch and that cause some issues?

Any ideas?

Problem with mouse (config undefined node label 'mmv')

Last month I could build my config with success but now even using the same commits that I used to build here with success I get this build error:

devicetree error: /keymap/layer_2: undefined node label 'mmv'

I have done no changes on the keymap includes nor west.yml

I see there is a recent commit that messes with mouse functionality. But I can't understand what is wrong. Is there missing a new config that I need to add but it is not on the README file or it can be other issue?

Thanks in advance.

Turning on LEDs

I came to know that LEDs are turned off. How can I enable that?

Thanks :)

Home row layer instead of mod

Hi there, I am using home row mods on other alpha keys as well. But I was wondering whether it is possible to use the advancements in this feature(differenciating between tap and hold) for a layer switch. Example: holding j would switch layer instead of making e.g. hold CMD/GUI.
I really appreciate what you are doing. Thank you for these repos and the guide how to use git for zmk.

Question: How to use the mouse layer?

First of all, thank you for the repository.

My question is as asked. I can't use the mouse layer on my MacBook with magic mouse. In other words, no keystrokes work.

I noticed that the official documentation of zmk says: only mouse clicks can be simulated now (although I can't even do that). Is there a step I'm overlooking, please?

Thanks!

360 build

I'm a total noob, I have no clue how to build the firmware.
Watched some tutorials so I have an idea,
but how do I build firmware actually?
I want to build for the 360 pro but there are also other files for other keyboards (planck etc.) and this is already too much to process for my brain ...

Suggestion for German Umlauts on Nav instead of the rudendant "<" and ">"

As per issue #13, having < and > on the combos works just fine. Therefore removing them from the Nav Layer allows all the German Umlauts to be placed there identically as they are currently only on the "Greek" layer. That's because ä and ö would replace < and > and the other 2 keys for ß and ü are coincidentally already free on the Nav layer as well.

This allows the German Umlauts to be typed much more easily, while keeping the same placement as they currently reside on the less efficient to activate Greekt layer and while only removing 2 redundant keys that cause issues with shortcuts anyways.

Combos around <E>-key

At first - thank you for sharing these great ideas!

I was wondering why all the combos worked except the <FSLH> combo.
Typing <RM2+RB2> resulted in <e><,>.
I had to add a line

CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY=6

to my board.conf file, now it works as expected.

COMBO_TERM_SLOW potentially causes false activations of mouse and Greek layers

Very often when typing the word "analysis" I seem to have activated some weird shortcuts. It happened so often that it got really annoying.

After "analysing" (sheesh) what's going on, I realized it's due to the "LY" bigram that is used to also activate the Greek layer as a combo. Now I don't think I noticed the same on the mouse layer, that is activated with the other hand on the W and P keys, but it's safe to say the "LY" bigram is not at all rare and thus causing false activations if pressed very quickly in succession.

When looking at the combos.dtsi, I noticed combos of horizontally adjacent keys use COMBO_TERM_FAST, while combos with vertically adjacent keys use COMBO_TERM_SLOW. That absolutely makes sense.

However, I noticed that COMBO_TERM_SLOW is also used for the combos for the mouse layer, the greek, the shifted greek layer and for cutting. These are combos that consist of keys that are on the same horizontal row as well but either not directly adjacent or require 3 keys.

Now, I would argue that it makes no difference in speed if I need to press a combo with the index finger + middle finger or if I have to press it with the index finger + ring finger. It can be done equally as fast and thus COMBO_TERM_SLOW is not necessarily needed here. Furthermore, since they are so qluick to press at the same time OR in succession when typing, it allows quickly typing bigrams such as "LY" to be mistakingly registered as a combo. Which is why I would highly suggest COMBO_TERM_FAST for these.

Now trigrams such as "LUY" in case of the Shifted Greek layer or even more so "XCD" in case of the cut combo are probably quite rare, so mistakingly activating those combos when typing should be less of an issue. But I feel like pressing 3 keys with the index, middle and ring finger at the same time is also quick and easy enough to do, that one could also comfortably use COMBO_TERM_FAST here as well.

Outdated png in readme

First of all, awesome config and awesome work, it was fun reading up on all the different features.

The keymap PNG in the README.md is slightly outdated.

At least the home row mod shift and control al reversed, this confused me for a bit after configuring my own keyboard.

I am also interested what tool you used to draw the image, since i made more changes in my own config. I would like to create my own similar image.

Support for nice_nano/kyria keyboard

Hi, im quite impressed by your work, wannted to give it a shot but i cannot force it to compile for nice nano v2, is it compatible?

i followed guide for scripts/readme.md and just migrated my config but it didnt work, so i decided to just use yours config but use nice_nano_v2 board(commit here, but it fails the same way...

log.txt

am i missing something ? ;0

Build script compat with shields

First off, if this isn't a goal of the project, please let me know and just close the issue :).

So, after some effort I got podman installed and figured out how the buildscript is intended to be used. I'm attempting to use the cradio layout (34k split) with nice_nano_v2. Since shields aren't supported in the local build script, I'm having to resort to using the gh actions script (not terrible, but quite annoying :) ). I tried to make a bash script with yq that used shields as well, but I'm no bash wizard, so I'll spare you the pain of the non-working code haha.

Nav + L keeps sending Backspaces

Not sure why but when I hit L while holding Nav, it keeps sending back spaces and it won't turn off unless I activate the combo for backspace. Is this intentional?

Attempting to use the local build script errors out

Running ./zmk_build.sh errors with the following output:

Building glove80_rh... 
-- west build: generating a build system
Loading Zephyr default modules (Zephyr base).
-- Application: /workspace/zmk/app
-- ZMK Config directory: /workspace/zmk-config/config
CMake Warning at cmake/ZephyrBuildConfig.cmake:199 (message):
  Failed to locate keymap file!
Call Stack (most recent call first):
  /workspace/zmk/zephyr/cmake/modules/zephyr_default.cmake:22 (find_package)
  /workspace/zmk/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:66 (include)
  /workspace/zmk/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:92 (include_boilerplate)
  CMakeLists.txt:15 (find_package)


-- Found Python3: /usr/bin/python3.8 (found suitable exact version "3.8.10") found components: Interpreter 
-- Cache files will be written to: /root/.cache/zephyr
-- Zephyr version: 3.2.0 (/workspace/zmk/zephyr)
-- Found west (found suitable version "0.14.0", minimum required is "0.7.1")
-- Board: glove80_rh
No board named 'glove80_rh' found.

2 things seem to be problematic here:

  • Zephyr not seeing the board's config? Although I am running the same code pushed to Github builds successfully
  • Board seems to be unsupported

Here is my west.yml file for context (maybe I'm messing up by not specifying the Zephyr version somehow? Note: I have tried adding -v main which errors differently):

manifest:
  remotes:
    - name: zmkfirmware
      url-base: https://github.com/zmkfirmware
    - name: urob
      url-base: https://github.com/urob
  projects:
    - name: zmk
      remote: urob
      revision: main-with-native-mouse
      import: app/west.yml
  self:
    path: config

Do you know of anyone who forked this for the glove 80?

Hello. Thank you for sharing your configs. It seems to be very good thought. I'm particularly attracted by the quick home row mods and the combos. I'm coming from qmk and I heavily rely on those.
I am in the process of moving to ZMK for my new globe80, but there is a lot to digest and configure. I was wondering if you know someone that is using your configs for the glove 80, so I can just steal their config 😁

Question: How do you type vertical combos?

Sorry this might sound stupid, as I have never tried a split keyboard yet, still waiting for mine to arrive.

I find the idea very interesting, but I can't quite get how can you type the vertical combos comfortably. For horizontal combo, it is obvious that you use 2 fingers. But do you also use 2 fingers for 2 keys on the same column, or do you, idk, swipe them, or just press on the edge to activate them both at once?

[qwerty] fork not building

I'm sorry as this is the upteenth issue I'm posting.

I've created a repo and basically imported your files.
Then I made minor changes to the layout [qwerty].

When trying to build, the files I modified (360) cannot be built and I get an error message.
Screenshot 2023-06-26 at 14 18 15

Is this a syntax error or is there anything specific I'm doing wrong?

PS: The action also builds the stuff for the other keyboard although I've deleted the respective files from the repo ...

Thanks again

no stroke recognition / flashing problem?

I think I successfully flashed the firmware, or so I thought.
My keyboard is being recognised but upon typing I don't see any output, alas. I'm wondering what could have gone wrong here

Issue with / combo on glove80

Hi im trying to get this config working on the glove80 and am having an issues that the / combo (RM2 RB2) is not working. Every other combo is working though. It just prints e, . I dont think it is an issue with keypress timing because all other keycombos seem to work fine.

Have you seen anything like this?

Thanks.

Ctrl + Shift + ; and Ctrl + ; are unavailable

This is more of a commentary than a necessity. I'm sure it's your personal build after all.

Google sheets, and I think excel, have the following shortcuts:

  1. To insert the current date: Ctrl + ;
  2. To insert the current time: Ctrl + Shift + ; (Ctrl + :)

Attempting these will produce < >.

If no longer in use, because < > are accessible with combos, I suggest they be removed.

My working snippet.

// tap: comma | shift + tap: semicolon | ctrl + shift + tap: <
ZMK_BEHAVIOR(comma_morph, mod_morph,
    mods = <(MOD_LSFT|MOD_RSFT)>;
    bindings = <&kp COMMA>, <&kp SEMICOLON>; // updated to semicolon on this line
)
// Not needed greater than is on a combo
// ZMK_BEHAVIOR(comma_inner_morph, mod_morph,
//     bindings = <&kp SEMICOLON>, <&kp LESS_THAN>;
//     mods = <(MOD_LCTL|MOD_RCTL)>;
// )

// tap: dot | shift + tap: colon | ctrl + shift + tap: >
ZMK_BEHAVIOR(dot_morph, mod_morph,
    bindings = <&kp DOT>, <&kp COLON>; // updated to colon on this line
    mods = <(MOD_LSFT|MOD_RSFT)>;
)
// Not needed greater than is on a combo
// ZMK_BEHAVIOR(dot_inner_morph, mod_morph,
//     bindings = <&kp COLON>, <&kp GREATER_THAN>;
//     mods = <(MOD_LCTL|MOD_RCTL)>;
// )

ZMK_UNICODE_PAIR prints the unicode value

Sorry for opening an issue for this matter, I really appreciate your work, have everything working but ñ.
I'm using your submodule in my configuration and merged with another fork you zmk fork in my repo.
I'm trying to print the Spanish special character ñ, but got the unicode printed instead.

ZMK_UNICODE_PAIR(n_tilde, N0, N0, F, N1, N0, N0, D, N1)

Using it like this:
&n_tilde

It's weird the fact that other special characters defined in your submodule are working fine.
Any ideas?

Selecting window from alt+tab (swapper)

How are you selecting a window with the current swapper implementation? Once I go into alt+tab mode, it requires me to send another key input to select a window, but the keypress affects selected window.

For example if I'm switching between windows and press enter while selecting notepad, a new line will be inserted.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.