miryoku_zmk/miryoku-zmk.org
2022-06-02 16:03:50 +10:00

27 KiB

Miryoku (ZMK) https://raw.githubusercontent.com/manna-harbour/miryoku/master/data/logos/miryoku-roa-32.png

https://raw.githubusercontent.com/manna-harbour/miryoku/master/data/layers/miryoku-legends_keycodes.png

Miryoku is an ergonomic, minimal, orthogonal, and universal keyboard layout.

This document describes miryoku for ZMK only. For the development branch, general documentation, and other implementations see github.com/manna-harbour/miryoku.

Layout

Layers

The layers are maintained in tables, with the thumb keys on the bottom row. X_NP indicates the key is not present and is used to fill in the table around the thumb keys. The grid arrangement of the tables does not imply a particular physical layout.

Basic keycodes are entered without the KC_ prefix. Symbols can be entered as-is, except for '-' (MINS), '.' (DOT), '|' (PIPE), and '"' (DQUO). Empty cells are unused.

The base layer has both halves of the layout joined for convenience. Other layers are specified as a single hand.

Base (BASE)

The base layer is maintained as separate tap and hold tables and are combined into the corresponding tap-hold keycodes for mods and layer change. Mods (and reset) will be available on sub layers on the same hand as the layer change thumb key. Unknown names are considered to be layer names.

Base layer alphas are Colemak-DHm. Thumb keys are backspace, enter, delete on the right and space, tab, escape on the left. Dot, comma and apostrophe are included for prose, dot and slash for file and directory names.

Tap
Q W F P B J L U Y '
A R S T G M N E I O
Z X C D V K H , DOT /
X_NP X_NP ESC SPC TAB ENT BSPC DEL X_NP X_NP
Hold
RESET RESET
LGUI LALT LCTL LSFT LSFT LCTL LALT LGUI
ALGR ALGR
X_NP X_NP MEDR NAVR MOUR NSSL NSL FUNL X_NP X_NP

Navigation (NAVR)

Primary right-hand layer (left home thumb) is navigation and editing. Cursor keys are on the home position, line and page movement below, clipboard above, caps lock and insert on the inner column. Thumb keys are duplicated from the base layer to avoid having to layer change mid edit and to enable auto-repeat.

AGIN UNDO CUT COPY PSTE
CAPS LEFT DOWN UP RGHT
INS HOME PGDN PGUP END
ENT BSPC DEL X_NP X_NP

Mouse (MOUR)

Secondary right-hand layer is mouse emulation. Mouse movement mirrors cursor navigation on home and wheel mirrors line / page movement below. Buttons are on the thumbs (L, M, R). Mouse movement, click, and drag with modifiers can be performed from the home position. Unused keys are available for other related functions.

MS_L MS_D MS_U MS_R
WH_L WH_D WH_U WH_R
BTN1 BTN3 BTN2 X_NP X_NP
Mouse Buttons Overlay (MBO)

Available for automatic activation depending on keyboard hardware and configuration. Not activated manually.

X_NP X_NP BTN1 BTN3 BTN2 X_NP X_NP

Media (MEDR)

Tertiary right-hand layer is media control, with volume up / down and next / prev mirroring the navigation keys. Pause, stop and mute are on thumbs. RGB control is on the top row (combine with shift to invert). Unused keys are available for other related functions.

RGB_TOG RGB_MOD RGB_HUI RGB_SAI RGB_VAI
MPRV VOLD VOLU MNXT
MSTP MPLY MUTE X_NP X_NP

Numerals and Symbols (NSL)

Primary left-hand layer (right home thumb) is numerals and symbols. Numerals are in the standard numpad locations with symbols in the remaining positions. Dot is duplicated from the base layer.

[ 7 8 9 ]
; 4 5 6 =
` 1 2 3 \
X_NP X_NP DOT 0 MINS

Shifted Numerals and Symbols (NSSL)

Secondary left-hand layer has shifted symbols in the same locations to reduce chording when using mods with shifted symbols. Open parenthesis is duplicated next to close parenthesis.

{ & * ( }
: $ % ^ +
~ ! @ # PIPE
X_NP X_NP ( ) _

Function and System (FUNL)

Tertiary left-hand layer has function keys mirroring the numerals on the primary layer with extras on the pinkie column, plus system keys on the inner column. App (menu) is on the tertiary thumb key and other thumb keys are duplicated from the base layer to enable auto-repeat.

F12 F7 F8 F9 PSCR
F11 F4 F5 F6 SLCK
F10 F1 F2 F3 PAUS
X_NP X_NP APP SPC TAB

Alternative Layouts

The defaults are recommended, but alternative layouts are provided to accommodate existing muscle memory.

Base Layer Alphas

To select, append the corresponding option to the make command line when building, e.g. MIRYOKU_ALPHAS=QWERTY.

Colemak

MIRYOKU_ALPHAS=COLEMAK

Q W F P G J L U Y '
A R S T D H N E I O
Z X C V B K M , DOT /
X_NP X_NP ESC SPC TAB ENT BSPC DEL X_NP X_NP
Colemak Mod-DH

MIRYOKU_ALPHAS=COLEMAKDH

Q W F P B J L U Y '
A R S T G K N E I O
Z X C D V M H , DOT /
X_NP X_NP ESC SPC TAB ENT BSPC DEL X_NP X_NP
Dvorak

MIRYOKU_ALPHAS=DVORAK

' , DOT P Y F G C R L
A O E U I D H T N S
/ Q J K X B M W V Z
X_NP X_NP ESC SPC TAB ENT BSPC DEL X_NP X_NP
Halmak

MIRYOKU_ALPHAS=HALMAK

W L R B Z ' Q U D J
S H N T , DOT A E O I
F M V C / G P X K Y
X_NP X_NP ESC SPC TAB ENT BSPC DEL X_NP X_NP
Workman

MIRYOKU_ALPHAS=WORKMAN

Q D R W B J F U P '
A S H T G Y N E O I
Z X M C V K L , DOT /
X_NP X_NP ESC SPC TAB ENT BSPC DEL X_NP X_NP
QWERTY

MIRYOKU_ALPHAS=QWERTY

Q W E R T Y U I O P
A S D F G H J K L '
Z X C V B N M , DOT /
X_NP X_NP ESC SPC TAB ENT BSPC DEL X_NP X_NP
vi-Style Navigation

To select, append MIRYOKU_NAV=VI to the make command line when building.

Navigation (NAVR)
AGIN UNDO CUT COPY PSTE
LEFT DOWN UP RGHT CAPS
HOME PGDN PGUP END INS
ENT BSPC DEL X_NP X_NP
Mouse (MOUR)
MS_L MS_D MS_U MS_R
WH_L WH_D WH_U WH_R
BTN1 BTN3 BTN2 X_NP X_NP
Media (MEDR)
RGB_TOG RGB_MOD RGB_HUI RGB_SAI RGB_VAI
MPRV VOLD VOLU MNXT
MSTP MPLY MUTE X_NP X_NP

COMMENT Templates

X_NP X_NP X_NP X_NP

Duplicate base layer tap keys on thumbs rather than trans to enable auto-repeat.

ENT BSPC DEL X_NP X_NP
X_NP X_NP ESC SPC TAB

Code Generation

Table Conversion Scripts

table-map-taphold

Produce base layer from separate tap and hold tables.

width = 14
mods_dict = dict.fromkeys(mods_table[0])
nonkp_tuple = tuple(nonkp_table[0])
layers_dict = dict.fromkeys(layers_table[0])
symbol_names_dict = {}
for symbol, name, shifted_symbol, shifted_name in symbol_names_table:
  symbol_names_dict[symbol] = name
  symbol_names_dict[shifted_symbol] = shifted_name
keycode_translation_dict = {}
for standard, local in keycode_translation_table:
  keycode_translation_dict[standard] = local
results = ''
for tap_row, hold_row in map(None, tap_table, hold_table):
  for tap, hold in map(None, tap_row, hold_row):
    if tap == '':
      code = 'X_NU'
    elif tap in symbol_names_dict:
      code = symbol_names_dict[tap]
    else:
      code = tap
    if code in keycode_translation_dict:
      code = keycode_translation_dict[code]
    if hold in mods_dict:
      if hold in keycode_translation_dict:
        hold = keycode_translation_dict[hold]
      code = '&hm ' + str(hold) + ' ' + code
    elif hold in layers_dict:
      code = '&lt ' + str(hold) + ' ' + code
    elif not str(code).startswith(nonkp_tuple):
      code = '&kp ' + str(code)
    results += (code + ', ').ljust(width)
  results = results.rstrip(' ') + '\n'
results = results.rstrip('\n, ')
return results
&kp Q,        &kp W,        &kp F,        &kp P,        &kp B,        &kp J,        &kp L,        &kp U,        &kp Y,        &kp QUOT,
&hm LGUI A,   &hm LALT R,   &hm LCTL S,   &hm LSFT T,   &kp G,        &kp M,        &hm LSFT N,   &hm LCTL E,   &hm LALT I,   &hm LGUI O,
&kp Z,        &hm RALT X,   &kp C,        &kp D,        &kp V,        &kp K,        &kp H,        &kp CMMA,     &hm RALT DOT, &kp FSLH,
X_NP,         X_NP,         &lt MEDR ESC, &lt NAVR SPC, &lt MOUR TAB, &lt NSSL RET, &lt NSL BKSP, &lt FUNL DEL, X_NP,         X_NP

table-map-half

Produce sub layers given layer name and corresponding table for single hand and incorporating mods and reset from base layer. Layer names must end with 'R' or 'L'. A layer with shifted symbols can also be generated.

width = 13
mods_dict = dict.fromkeys(mods_table[0])
layers_dict = dict.fromkeys(layers_table[0])
nonkp_tuple = tuple(nonkp_table[0])
symbol_names_dict = {}
shifted_symbol_names_dict = {}
for symbol, name, shifted_symbol, shifted_name in symbol_names_table:
  symbol_names_dict[symbol] = name
  symbol_names_dict[shifted_symbol] = shifted_name
  shifted_symbol_names_dict[symbol] = shifted_name
keycode_translation_dict = {}
for standard, local in keycode_translation_table:
  keycode_translation_dict[standard] = local
length = len(half_table[0])
results = ''
for half_row, hold_row in map(None, half_table, hold_table):
  hold_row_l, hold_row_r = hold_row[:length], hold_row[length:]
  for lr, hold_row_lr in ('l', hold_row_l), ('r', hold_row_r):
    if lr == mode:
      for half in half_row:
        if half == '':
          code = 'X_NU'
        elif shift == "true" and half in shifted_symbol_names_dict:
          code = shifted_symbol_names_dict[half]
        elif half in symbol_names_dict:
          code = symbol_names_dict[half]
        else:
          code = half
        if code in keycode_translation_dict:
          code = keycode_translation_dict[code]
        if not str(code).startswith(nonkp_tuple):
          code = '&kp ' + str(code)
        results += (str(code) + ', ').ljust(width)
    else:
      for hold in hold_row_lr:
        if hold in mods_dict:
          if hold in keycode_translation_dict:
            hold = keycode_translation_dict[hold]
          code = '&kp ' + str(hold)
        else:
          if hold in keycode_translation_dict:
            hold = keycode_translation_dict[hold]
          if hold == '' or hold in layers_dict:
            code = 'X_NA'
          elif str(hold).startswith(nonkp_tuple):
            code = hold
          else:
            code = '&kp ' + str(hold)
        results += (str(code) + ', ').ljust(width)
  results = results.rstrip(' ') + '\n'
results = results.rstrip('\n, ')
return results
&bootloader, X_NA,        X_NA,        X_NA,        X_NA,        X_NU,        &kp UNDO,    &kp CUT,     &kp COPY,    &kp PSTE,
&kp LGUI,    &kp LALT,    &kp LCTL,    &kp LSFT,    X_NA,        &kp CLCK,    &kp LARW,    &kp DARW,    &kp UARW,    &kp RARW,
X_NA,        &kp RALT,    X_NA,        X_NA,        X_NA,        &kp INS,     &kp HOME,    &kp PGDN,    &kp PGUP,    &kp END,
X_NP,        X_NP,        X_NA,        X_NA,        X_NA,        &kp RET,     &kp BKSP,    &kp DEL,     X_NP,        X_NP

table-map-full

Produce full layer from single table. Fill for unused keys is configurable.

width = 10
symbol_names_dict = {}
nonkp_tuple = tuple(nonkp_table[0])
for symbol, name, shifted_symbol, shifted_name in symbol_names_table:
  symbol_names_dict[symbol] = name
  symbol_names_dict[shifted_symbol] = shifted_name
keycode_translation_dict = {}
for standard, local in keycode_translation_table:
  keycode_translation_dict[standard] = local
results = ''
for row in table:
  for key in row:
    if key == '':
      code = fill
    elif key in symbol_names_dict:
      code = symbol_names_dict[key]
    else:
      code = key
    if code in keycode_translation_dict:
      code = keycode_translation_dict[code]
    if not str(code).startswith(nonkp_tuple):
      code = '&kp ' + str(code)
    results += (code + ', ').ljust(width)
  results = results.rstrip(' ') + '\n'
results = results.rstrip('\n, ')
return results
&trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,
&trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,
&trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,   &trans,
X_NP,     X_NP,     &trans,   &trans,   &trans,   X_NU,     X_NU,     X_NU,     X_NP,     X_NP

table-layer-defines

Produce layer defines from layer names in hold table.

width = 5
layers_list = layers_table[0]
results = ''
i = 0
for layer in layers_list:
  results += '#define ' + ( layer + ' ').ljust(width) + str(i) + '\n'
  i += 1
return results
#define BASE 0
#define MBO  1
#define NAVR 2
#define MOUR 3
#define MEDR 4
#define NSL  5
#define NSSL 6
#define FUNL 7

Data

layers

BASE TAP MBO NAVR MOUR MEDR NSL NSSL FUNL

symbol-names

Symbol, name, and shifted symbol mappings for use in tables.

` GRV ~ TILD
"-" MINS _ UNDS
= EQL + PLUS
[ LBRC { LCBR
] RBRC } RCBR
\ BSLS PIPE PIPE
; SCLN : COLN
' QUOT DQUO DQUO
, COMM < LT
"." DOT > GT
/ SLSH ? QUES
1 1 ! EXLM
2 2 @ AT
3 3 # HASH
4 4 $ DLR
5 5 % PERC
6 6 ^ CIRC
7 7 & AMPR
8 8 * ASTR
9 9 ( LPRN
0 0 ) RPRN

mods

Modifiers usable in hold table. Need to have the same name for KC_ and _T versions.

LSFT LCTL LALT LGUI ALGR

nonkp

Keycodes that match any of these prefixes will not have KC_ automatically prepended.

X_ &

keycode-translation

standard keycode to implementation equivalent

0 NUM_0
1 NUM_1
2 NUM_2
3 NUM_3
4 NUM_4
5 NUM_5
6 NUM_6
7 NUM_7
8 NUM_8
9 NUM_9
AGIN X_NU
ALGR RALT
AMPR X_NU
APP X_NU
ASTR X_NU
AT X_NU
BSLS BSLH
BSPC BKSP
BTN1 X_NU
BTN2 X_NU
BTN3 X_NU
CAPS CLCK
CIRC X_NU
COLN X_NU
COMM CMMA
COPY COPY
CUT CUT
DEL DEL
DLR X_NU
DOT DOT
DOWN DARW
DQUO X_NU
END END
ENT RET
EQL EQL
ESC ESC
EXLM X_NU
F1 F1
F10 F10
F11 F11
F12 F12
F2 F2
F3 F3
F4 F4
F5 F5
F6 F6
F7 F7
F8 F8
F9 F9
GRV GRAV
GT X_NU
HASH X_NU
HOME HOME
INS INS
LALT LALT
LBRC LBKT
LCBR X_NU
LCTL LCTL
LEFT LARW
LGUI LGUI
LPRN X_NU
LSFT LSFT
LT X_NU
MINS MINUS
MNXT M_NEXT
MPLY M_PLAY
MPRV M_PREV
MS_D X_NU
MS_L X_NU
MS_R X_NU
MSTP M_STOP
MS_U X_NU
MUTE M_MUTE
PAUS PAUS
PERC X_NU
PGDN PGDN
PGUP PGUP
PIPE X_NU
PLUS X_NU
PSCR PRSC
PSTE PSTE
QUES X_NU
QUOT QUOT
RBRC RBKT
RCBR X_NU
RESET &bootloader
RGB_HUI X_NU
RGB_MOD X_NU
RGB_SAI X_NU
RGB_TOG X_NU
RGB_VAI X_NU
RGHT RARW
RPRN X_NU
SCLN SCLN
SLCK SCLK
SLSH FSLH
SPC SPC
TAB TAB
TILD X_NU
UNDO UNDO
UNDS X_NU
UP UARW
VOLD VOLD
VOLU VOLU
WH_D X_NU
WH_L X_NU
WH_R X_NU
WH_U X_NU

header

Header for tangled source files.

generated from miryoku_zmk.org  -*- buffer-read-only: t -*-

Subset Mapping

The keymap, build options, and configuration are shared between keyboards. The layout is mapped onto keyboards with different physical layouts as a subset.

miryoku include

/ClaytonWWilson/miryoku_zmk/src/commit/7ad8ccd19141550e53116568a0bbee5efb3ab420/miryoku.keymap

// <<header>>

//#include <behaviors.dtsi>
//#include <dt-bindings/zmk/keys.h>
//#include <dt-bindings/zmk/bt.h>

#define MIRYOKU_SUBMAP(\
      K00,  K01,  K02,  K03,  K04,         K05,  K06,  K07,  K08,  K09,\
      K10,  K11,  K12,  K13,  K14,         K15,  K16,  K17,  K18,  K19,\
      K20,  K21,  K22,  K23,  K24,         K25,  K26,  K27,  K28,  K29,\
      N30,  N31,  K32,  K33,  K34,         K35,  K36,  K37,  N38,  N39\
)\
&none K00   K01   K02   K03   K04          K05   K06   K07   K08   K09   &none \
&none K10   K11   K12   K13   K14          K15   K16   K17   K18   K19   &none \
&none K20   K21   K22   K23   K24          K25   K26   K27   K28   K29   &none \
                  K32   K33   K34          K35   K36   K37
#define MIRYOKU_SUPERMAP(\
      K00,  K01,  K02,  K03,  K04,         K05,  K06,  K07,  K08,  K09,\
      K10,  K11,  K12,  K13,  K14,         K15,  K16,  K17,  K18,  K19,\
      K20,  K21,  K22,  K23,  K24,         K25,  K26,  K27,  K28,  K29,\
      N30,  N31,  K32,  K33,  K34,         K35,  K36,  K37,  N38,  N39\
)\
LALT  K00   K01   K02   K03   K04          K05   K06   K07   K08   K09   LGUI  \
LCTL  K10   K11   K12   K13   K14          K15   K16   K17   K18   K19   LCTL  \
LSFT  K20   K21   K22   K23   K24          K25   K26   K27   K28   K29   LSFT  \
                  K32   K33   K34          K35   K36   K37

<<table-layer-defines()>>

#define X_NP &none // key is not present
#define X_NA &none // present but not available for use
#define X_NU &none // available but not used

/ {
  behaviors {
    hm: homerow_mods {
      compatible = "zmk,behavior-hold-tap";
      label = "HOMEROW_MODS";
      #binding-cells = <2>;
      tapping_term_ms = <200>;
      flavor = "tap-preferred";
      bindings = <&kp>, <&kp>;
    };
  };
  keymap {
    compatible = "zmk,keymap";
      BASE_layer {
        bindings = <
#if defined MIRYOKU_ALPHAS_COLEMAK
          MIRYOKU_SUBMAP(
<<table-map-taphold(tap_table=colemak)>>
          )
#elif defined MIRYOKU_ALPHAS_COLEMAKDH
          MIRYOKU_SUBMAP(
<<table-map-taphold(tap_table=colemakdh)>>
          )
#elif defined MIRYOKU_ALPHAS_DVORAK
          MIRYOKU_SUBMAP(
<<table-map-taphold(tap_table=dvorak)>>
          )
#elif defined MIRYOKU_ALPHAS_HALMAK
          MIRYOKU_SUBMAP(
<<table-map-taphold(tap_table=halmak)>>
          )
#elif defined MIRYOKU_ALPHAS_WORKMAN
          MIRYOKU_SUBMAP(
<<table-map-taphold(tap_table=workman)>>
          )
#elif defined MIRYOKU_ALPHAS_QWERTY
          MIRYOKU_SUBMAP(
<<table-map-taphold(tap_table=qwerty)>>
          )
#else
          MIRYOKU_SUBMAP(
<<table-map-taphold(tap_table=colemakdhm)>>
          )
#endif
        >;
      };
      TAP_layer {
        bindings = <
#if defined MIRYOKU_ALPHAS_COLEMAK
          MIRYOKU_SUPERMAP(
<<table-map-full(table=colemak)>>
          )
#elif defined MIRYOKU_ALPHAS_COLEMAKDH
          MIRYOKU_SUPERMAP(
<<table-map-full(table=colemakdh)>>
          )
#elif defined MIRYOKU_ALPHAS_DVORAK
          MIRYOKU_SUPERMAP(
<<table-map-full(table=dvorak)>>
          )
#elif defined MIRYOKU_ALPHAS_HALMAK
          MIRYOKU_SUPERMAP(
<<table-map-full(table=halmak)>>
          )
#elif defined MIRYOKU_ALPHAS_WORKMAN
          MIRYOKU_SUPERMAP(
<<table-map-full(table=workman)>>
          )
#elif defined MIRYOKU_ALPHAS_QWERTY
          MIRYOKU_SUPERMAP(
<<table-map-full(table=qwerty)>>
          )
#else
          MIRYOKU_SUPERMAP(
<<table-map-full(table=colemakdhm)>>
          )
#endif
        >;
      };
      MBO_layer {
        bindings = <
          MIRYOKU_SUBMAP(
<<table-map-full(table=mbo)>>
          )
        >;
      };
      NAVR_layer {
        bindings = <
#if defined MIRYOKU_NAV_VI
          MIRYOKU_SUBMAP(
<<table-map-half(mode="r", half_table=navr-vi)>>
          )
#else
          MIRYOKU_SUBMAP(
<<table-map-half(mode="r", half_table=navr)>>
          )
#endif
        >;
      };
      MOUR_layer {
        bindings = <
#if defined MIRYOKU_NAV_VI
          MIRYOKU_SUBMAP(
<<table-map-half(mode="r", half_table=mour-vi)>>
          )
#else
          MIRYOKU_SUBMAP(
<<table-map-half(mode="r", half_table=mour)>>
          )
#endif
        >;
      };
      MEDR_layer {
        bindings = <
#if defined MIRYOKU_NAV_VI
          MIRYOKU_SUBMAP(
<<table-map-half(mode="r", half_table=medr-vi)>>
          )
#else
          MIRYOKU_SUBMAP(
<<table-map-half(mode="r", half_table=medr)>>
          )
#endif
        >;
      };
      NSL_layer {
        bindings = <
          MIRYOKU_SUBMAP(
<<table-map-half(mode="l", half_table=nsl)>>
          )
        >;
      };
      NSSL_layer {
        bindings = <
          MIRYOKU_SUBMAP(
<<table-map-half(mode="l", half_table=nssl)>>
          )
        >;
      };
      FUNL_layer {
        bindings = <
          MIRYOKU_SUBMAP(
<<table-map-half(mode="l", half_table=funl)>>
          )
        >;
      };
    };
  };
};

Contact

https://raw.githubusercontent.com/manna-harbour/miryoku/master/data/logos/manna-harbour-boa-32.png