tshohe's memo

おぼえたことをかく

今更やるHelixのキーマップカスタマイズ

Helixというキーボードキットがあるのですが、こちらを購入し作成したのが去年の2月頃。 しかし作成したはいいものの、デフォルトのキーマップに全く慣れることができずにそれから1年半ほど光る飾りと化していました。
流石に2万くらいしたし勿体ないから有効活用したいなと思い自分なりに使いやすいようにカスタマイズしてみました。本記事はその記録です。

キーマップ設定

既に情報が大量にあるので準備作業については省略しますが、やることとしては下記をforkしてkeymap.cを書き換えてビルド&書き込みという流れです。

github.com

keymap.cを書き換える前にどういうキーマップにするのか設計する必要があったので最初はKeyboard Layout Editorというツールでレイアウトを検討していました。しかしこのツール、並び替えなどもなかなかしづらく管理がなかなかに苦行だったので使うことを早々に辞めました。

そもそもQMK Configuratorというキーマップのjsonファイルを出力するところまでやってくれるツールがあるようなのでそちらを利用することに。

私が所持しているものはHelixの5行OLED, Underglowなので下記の設定をロードしキーマップを変更していきます。

config.qmk.fm

キーマップは下記点を重視し検討しました。

  • MBPのキーボードとの差異を少なくしラップトップ利用時の違和感を減らす
    • デフォルトだと方向キーが一列になっていたり(vimライク)、Esc/Optionキーの位置だったりが既存のものとは大きく異なるので慣れたら慣れたで内蔵キーボードが使いにくくなるリスクがある
  • 利用しないキーを削減し、想定外の動作を防ぐ
    • デフォルトのキーマップだとQWERTY配列以外にもDVORAK、COLEMAKといった指の移動が少ない配列も登録されているのですが、全く覚えられないですし、誤って切り替えてしまったときに予期しないキーを押してしまいそうなのでバッサリ無くす(レイヤー自体を消してしまっても良いが一応残して、レイヤー移動キーの削除を実施)
  • 利用頻度の低いキーはAdjustレイヤーに追い出す
    • フルサイズのキーボードにしかないようなやつは基本使わないので移動

具体的なキーマップは下記の通り

QWERTYレイヤー

MBPの配置に寄せれる範囲で寄せています。列が若干足りないのでスラッシュとかは別レイヤーになってしまってはいますが、ある程度違和感なく使えるようになりました。

f:id:tshohe:20200719003525p:plain
layer0

RAISEレイヤー

利用頻度の高い記号などを配置。Raise/Lower + Shiftとかは辛いと思ったのでShift無しでも打てるように既にカバーできているキーも配置しています。

f:id:tshohe:20200719004358p:plain
layer4

LOWERレイヤー

Raiseでほぼほぼカバーできてしまいましたが、演算系の記号はごっちゃになりやすい気がしたのでこちらにまとめています。

f:id:tshohe:20200719004414p:plain
layer3

戯れに、P(PlayのP)には記憶させたMacroを実行できるkeycodeを割り当てています。(面白そうだったのでDynamic Macro機能有効化しました)

DYN_REC_START1 -> DYN_REC_STOP -> DYN_MACRO_PLAY1 でSTOPするまでに打ったキーを再入力させることができます。

beta.docs.qmk.fm

ADJUSTレイヤー

Adjustキーは押しにくいですし、Dynamic Macroのレコードキーとか各種設定変更等の基本使わないタイプのキーを集約させています。

f:id:tshohe:20200719004428p:plain
layer5

ファームウェアコンパイル

QMK Configuratorでもファームウェアコンパイルする機能はあるのですが、エラーが発生してしまいます。こちらは既知の問題らしいですが、まだ対応はされていないようです。

Linking: .build/helix_rev2_oled_under_tsts_custom.elf                                               
 | 
 | .build/obj_helix_rev2_oled_under_tsts_custom/keyboards/helix/rev2/rev2.o: In function `matrix_init_kb':
 | /qmk_compiler/qmk_firmware/keyboards/helix/rev2/rev2.c:25: undefined reference to `is_helix_master'
 | collect2: error: ld returned 1 exit status
 |

Issues with QMK configurator when compiling Helix firmware. · Issue #26 · MakotoKurauchi/helix · GitHub

QMK Keymap JSONをExportしローカルでコンパイルしていきます。

% qmk json2c [exportしたjsonファイル]

#include QMK_KEYBOARD_H

/* THIS FILE WAS GENERATED!
 *
 * This file was generated by qmk json2c. You may or may not want to
 * edit it directly.
 */

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_BSPC, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_NO, KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC, KC_RBRC, KC_N, KC_M, KC_COMM, KC_DOT, KC_UP, KC_RSFT, MO(5), KC_LALT, KC_GRV, KC_LGUI, KC_LANG2, MO(3), KC_SPC, KC_SPC, MO(4), KC_LANG1, KC_RGUI, KC_LEFT, KC_DOWN, KC_RGHT),
...(キーマップ設定がkeymap.cに記載できる形式で出力される)
};

keymap.cを編集しキーマップを設定していきます。(既存のkeymap.cはdefaultあたりから持ってくる) このときMO(レイヤー番号)となっているものはそれぞれ既存のlayer_numberに合わせて変更しておきます。

% vi keymap.c
(#if MATRIX_ROWS == 10 // HELIX_ROWS == 5の下に記載)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [_QWERTY] = LAYOUT(KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_NUBS, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC, KC_RBRC, KC_N, KC_M, KC_COMM, KC_DOT, KC_UP, KC_RSFT, ADJUST, KC_LALT, KC_CAPS, KC_LGUI, KC_HANJ, LOWER, KC_SPC, KC_SPC, RAISE, KC_LANG1, KC_RGUI, KC_LEFT, KC_DOWN, KC_RGHT),
    [_COLEMAK] = LAYOUT(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, 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, 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, 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),
    [_DVORAK] = LAYOUT(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, 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, 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, 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),
    [_LOWER] = LAYOUT(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, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, DM_PLY1, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_PAST, KC_PSLS, KC_PEQL, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LPRN, KC_RPRN, KC_CIRC, 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_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
    [_RAISE] = LAYOUT(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, KC_TRNS, KC_TRNS, KC_QUOT, KC_DQUO, KC_GRV, KC_PIPE, KC_TRNS, KC_DEL, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TILD, KC_MINS, KC_EQL, KC_BSLS, KC_SLSH, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LCBR, KC_RCBR, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, ADJUST, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_MPLY),
    [_ADJUST] =  LAYOUT(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, RESET, KC_TRNS, KC_TRNS, DM_REC1, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_INS, KC_HOME, KC_PGUP, KC_NLCK, KC_TRNS, DM_RSTP, AU_ON, AU_OFF, AG_NORM, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_END, KC_PGDN, KC_CAPS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, RGB_HUI, RGB_SAI, RGB_VAI, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_MOD, RGB_HUD, RGB_SAD, RGB_VAD)
};

Dynamic Macroを利用するために下記設定も有効にします。

% vi rules.mk
+DYNAMIC_MACRO_ENABLE = yes

後はmakeして作成されるhexをQMK ToolkitでFlashすれば完了です。

% make helix/rev2/oled/under:tsts_custom  
QMK Firmware 0.9.38
Making helix/rev2/oled/under with keymap tsts_custom

avr-gcc (Homebrew AVR GCC 8.4.0) 8.4.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Compiling: keyboards/helix/local_drivers/serial.c                                                   [OK]
Compiling: keyboards/helix/rev2/matrix.c                                                            [OK]
Compiling: keyboards/helix/rev2/split_util.c                                                        [OK]
Compiling: keyboards/helix/rev2/split_scomm.c                                                       [OK]
Compiling: keyboards/helix/local_drivers/i2c.c                                                      [OK]
Compiling: keyboards/helix/local_drivers/ssd1306.c                                                  [OK]
Compiling: keyboards/helix/helix.c                                                                  [OK]
Compiling: keyboards/helix/rev2/rev2.c                                                              [OK]
Compiling: keyboards/helix/rev2/keymaps/tsts_custom/keymap.c                                        [OK]
Compiling: quantum/quantum.c                                                                        [OK]
Compiling: quantum/keymap_common.c                                                                  [OK]
Compiling: quantum/keycode_config.c                                                                 [OK]
Compiling: quantum/debounce/sym_g.c                                                                 [OK]
Compiling: quantum/color.c                                                                          [OK]
Compiling: quantum/rgblight.c                                                                       [OK]
Compiling: quantum/process_keycode/process_rgb.c                                                    [OK]
Compiling: drivers/avr/ws2812.c                                                                     [OK]
Compiling: quantum/led_tables.c                                                                     [OK]
Compiling: quantum/process_keycode/process_space_cadet.c                                            [OK]
Compiling: quantum/process_keycode/process_magic.c                                                  [OK]
Compiling: quantum/process_keycode/process_grave_esc.c                                              [OK]
Compiling: quantum/process_keycode/process_dynamic_macro.c                                          [OK]
Archiving: .build/obj_helix_rev2_oled_under_tsts_custom/local_drivers/serial.o                      [OK]
Compiling: tmk_core/common/host.c                                                                   [OK]
Compiling: tmk_core/common/keyboard.c                                                               [OK]
Compiling: tmk_core/common/action.c                                                                 [OK]
Compiling: tmk_core/common/action_tapping.c                                                         [OK]
Compiling: tmk_core/common/action_macro.c                                                           [OK]
Compiling: tmk_core/common/action_layer.c                                                           [OK]
Compiling: tmk_core/common/action_util.c                                                            [OK]
Compiling: tmk_core/common/print.c                                                                  [OK]
Compiling: tmk_core/common/debug.c                                                                  [OK]
Compiling: tmk_core/common/sendchar_null.c                                                          [OK]
Compiling: tmk_core/common/util.c                                                                   [OK]
Compiling: tmk_core/common/eeconfig.c                                                               [OK]
Compiling: tmk_core/common/report.c                                                                 [OK]
Compiling: tmk_core/common/avr/suspend.c                                                            [OK]
Compiling: tmk_core/common/avr/timer.c                                                              [OK]
Compiling: tmk_core/common/avr/bootloader.c                                                         [OK]
Assembling: tmk_core/common/avr/xprintf.S                                                           [OK]
Compiling: tmk_core/common/magic.c                                                                  [OK]
Compiling: tmk_core/protocol/lufa/lufa.c                                                            [OK]
Compiling: tmk_core/protocol/usb_descriptor.c                                                       [OK]
Compiling: tmk_core/protocol/lufa/outputselect.c                                                    [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Class/Common/HIDParser.c                                       [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c                                        [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c                                [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c                                      [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c                                          [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c                                    [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c                                          [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c                                 [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c                                  [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/ConfigDescriptors.c                                       [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/DeviceStandardReq.c                                       [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/Events.c                                                  [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/HostStandardReq.c                                         [OK]
Compiling: lib/lufa/LUFA/Drivers/USB/Core/USBTask.c                                                 [OK]
Linking: .build/helix_rev2_oled_under_tsts_custom.elf                                               [OK]
Creating load file for flashing: .build/helix_rev2_oled_under_tsts_custom.hex                       [OK]
Copying helix_rev2_oled_under_tsts_custom.hex to qmk_firmware folder                                [OK]
Checking file size of helix_rev2_oled_under_tsts_custom.hex                                         [OK]
 * The firmware size is fine - 26176/28672 (91%, 2496 bytes free)

感想

  • ようやく少ない違和感で使えるようになった
  • 方向キーはとりあえずMBPに合わせたけど、ホームポジションからの距離が明らかに遠くて効率が悪いのでvimの位置にもキーを持ってくるか、PCゲームっぽくWASDとかで移動できるようにしてもいいのかなと思った
  • Dynamic Macro機能は汎用性高いので色々なシーンで使えそう

とりあえずしばらくお試し期間ということで使っていこうと思います。