キーマップで楽しむ自作キーボードのお話

# はじめに
こんにちは。
ココネ株式会社でサーバーエンジニアをしているkkuchiです。

突然ですが、みなさんはどんなキーボードをお使いでしょうか？
配列の日本語/英語、サイズ(テンキーレス/60%等)、キースイッチなどなど、
様々なこだわりがあることかと思います。

今回は私が自作キーボードに詰め込んだこだわりポイントについて、
QMK Firmwareのコードと合わせてご紹介します。
雰囲気を感じ取ったり、カスタマイズの参考にして頂ければ幸いです。

# 自作キーボードを始めたきっかけ
私はかれこれ10年ほど `Topre Realforce 108UD-A` を愛用しています。
だいぶ使い込んでいますがまだまだ現役。
打鍵感も印字(昇華印刷)も各種キーのサイズも、全てがお気に入りのキーボードです。

私物のPCにはAutoHotKeyやKarabiner-Elementsを入れ、
WindowsでもMacでもほぼ同じ使用感で快適に使用しています。

しかし、社会人になって少し状況が変わりました。

愛用のRealforceはフルサイズなので、会社へ持って行くのは大変。
それに、こまごましたカスタマイズのために
会社支給のPCにKarabiner-Elementsを入れるのは如何なものか...
と、ちょっと気が引けていました。

そんな時、ふと
>せや！自作キーボードでキーマップをあれこれいじって快適にすればええんや！

と思い至ったわけです。
諸々のカスタマイズがキーボードに収まっていれば、PC移行等も楽になるはず。

# QMK Firmwareをちょっとだけ説明
自作キーボードのファームウェアには、**QMK Firmware**が広く使われています。
詳細は割愛しますが、今回紹介する機能以外にも色々なことが出来ます。

ちょこちょこ更新されているので、最新の情報についてはリポジトリをご確認下さい。
(久々にチェックしたら色々変わっていて私もびっくりしました)

https://github.com/qmk/qmk_firmware

上記リポジトリの`keyboards`ディレクトリ下には、
さまざまなキーボード (PCB) のデフォルトキーマップが入っています。

カスタマイズの際は、
自分が使っているキーボードのデフォルトキーマップが入っているディレクトリを探し、
コピーして編集してください。

# 実際のキーマップ
私が[7sPro](https://shop.yushakobo.jp/products/7spro)で実際に使っているキーマップをGitHubで公開しました。
全体を見たい方はこちらからどうぞ。

https://github.com/kkuchi/7spro_my_keymap

:::note warn
使用しているQMK Firmwareやjtu_custom_keycodesが古いため、
最新のQMKの環境ではビルドに失敗します。ご注意ください。
:::

このキーマップには、
- ホームポジションからの移動を減らすため、記号・テンキーのレイヤーを作成する
- WindowsでUNIXキーバインドのよく使うものを再現する
- PC側は日本語配列の設定のまま、英語配列のキーを入力できるようにする
- Windows/Mac両方で概ね使用感を揃える

といったこだわりが詰まっています。
1つずつ見ていきましょう。

## 記号・テンキーレイヤー
左手親指キーを長押ししている間は_NUMPAD(テンキー)レイヤーが、
右手親指キーを長押ししている間は_SYMBOL(記号)レイヤーが有効化されます。

### テンキーレイヤー
テンキーは右手で入力したかったので、左手親指にレイヤー有効化を割り当てました。
計算に使う記号もこのレイヤーに入れています。

このレイヤーで_QWERTY(デフォルト)レイヤーのピリオドを潰してしまうため、
小数を入力するときに少し煩雑なのがネックです。
```c
  [_NUMPAD] = LAYOUT(
  //,-----------------------------------------------------|   |--------------------------------------------------------------------------------.
      _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,     XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------+--------|
      _______, XXXXXXX, XXXXXXX, JP_ASTR, XXXXXXX, XXXXXXX,     XXXXXXX,   KC_P7,   KC_P8,   KC_P9, XXXXXXX, XXXXXXX, XXXXXXX, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------|
      _______, XXXXXXX, XXXXXXX, JP_PLUS,  KC_TAB, XXXXXXX,     JP_SLSH,   KC_P4,   KC_P5,   KC_P6, JP_MINS,  JP_EQL, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
      _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,       KC_P0,   KC_P1,   KC_P2,   KC_P3, XXXXXXX, _______, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
               _______, _______, _______, _______,              _______, _______,          _______, _______ 
          //`---------------------------------------------|   |--------------------------------------------'
  ),
```
### 記号レイヤー
右手親指のキーを押しながらの打鍵になるので、
主要な記号は左手側に収めました。

`どの記号をどこに配置するか` は覚えやすさ重視で決めています。
エンジニアであれば、普段書いている言語によって配置を決めるのも面白いかもしれません。
```c
  [_SYMBOL] = LAYOUT(
  //,-----------------------------------------------------|   |--------------------------------------------------------------------------------.
      _______, _______, _______, _______, _______, _______,     _______, _______, _______, _______, _______, _______, _______, _______, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------+--------|
      _______, JP_EXLM, JP_QUES,  JP_DLR, JP_PERC, JP_AMPR,     _______, _______,   JP_AT, _______, _______, _______, _______, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------|
      _______, JP_LBRC, JP_LCBR, JP_LPRN, JP_UNDS,  JP_YEN,     _______,  JP_GRV,  JP_YEN, _______, _______, _______, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
      _______, JP_RBRC, JP_RCBR, JP_RPRN, JP_HASH, JP_PIPE,     JP_TILD, _______, _______, _______, _______, _______, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
               _______, _______, _______, _______,              _______, _______,          _______, _______ 
          //`---------------------------------------------|   |--------------------------------------------'
  ),
```

## UNIXキーバインドの再現
_UNIXレイヤーを用意することで、
WindowsでもUNIXキーバインド(っぽいもの)が使用できるようにしています。

### _UNIXレイヤー
上下左右のカーソル移動、バックスペースとデリート、
トグルでの全角/半角切り替えもここに入っています。
```c
  [_UNIX] = LAYOUT(
  //,-----------------------------------------------------|   |--------------------------------------------------------------------------------.
      _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,     XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------+--------|
      _______, XXXXXXX, XXXXXXX,  KC_END, XXXXXXX, XXXXXXX,     XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,   KC_UP, XXXXXXX, XXXXXXX, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------|
      _______, KC_HOME, XXXXXXX,  KC_DEL,KC_RIGHT, XXXXXXX,     KC_BSPC, XXXXXXX,CK_CTROW, XXXXXXX, XXXXXXX, XXXXXXX, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
      _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_LEFT,     KC_DOWN, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
               XXXXXXX, _______, _______, JP_ZKHK,              _______, _______,          _______, _______ 
          //`---------------------------------------------|   |--------------------------------------------'
  ),
```

### カスタムキーコード
_UNIXレイヤーのKキーには`カーソルから行末までを削除するカスタムキーコード`を配置しています。
- Shfit+Endを入力 (押して離す)
- Deleteを入力 (押して離す)

という動作を登録することで、Windows使用時にもMacに近い挙動を実現しました。
( コマンドプロンプトやWSLなどでは機能しないので注意です )
```c
    case CK_CTROW:
      if (record->event.pressed) {
        // shift+end
        // down
        register_code(KC_LSFT);
        register_code(KC_END);
        // up
        unregister_code(KC_END);
        unregister_code(KC_LSFT);

        // delete
        register_code(KC_DEL);
        unregister_code(KC_DEL);
      }
      return false;
```

## 日本語キーボード設定で英語配列のキー入力
koktoh様の`jtu_custom_keycodes`を使用しました。大感謝です。
PCがJISキーボードとして認識しているキーボードで、
US配列と同じキーマップを実現するためのキーコードが入っています。

https://qiita.com/koktoh/items/874be0e4d058aae54180

https://github.com/koktoh/jtu_custom_keycodes

`default/README.md`に従ってファイルをコピーし`keymap.c`を書き換えれば使えます。
あとは日本語と英語配列で配置が異なるキーに`JU_〇〇`を割り当てるだけ。簡単！

## Windows/Macでの使用感を合わせる
私はMacのキー配置が好みなので、Windowsのキー配置をMacに合わせます。
Ctrlキーを親指で打鍵できる位置に、_UNIXレイヤーを有効化するキーをAの左に配置します。

なお物理的なキー数の都合上、
Windowsで言うところの「左右Ctrlと変換/無変換」を同じキーに収めるため
||Windows|Mac|
|---|---|---|
|タップ(短押し)|変換/無変換|かな/英数|
|ホールド(長押し)|Ctrl|Command|

といった形で設定しています。

### カスタムキーコード定義
```c
#define CK_MHLC RCTL_T(JP_MHEN) // 短く押して無変換, 長押しでCtrl
#define CK_HKRC RCTL_T(JP_HENK) // 短く押して変換, 長押しでCtrl

// Mac用
#define MK_ESLC LGUI_T(JP_MEISU) // 短く押して英数, 長押しでCommand
#define MK_KNRC RGUI_T(JP_MKANA) // 短く押してかな, 長押しでCommand
```

### Windows用のデフォルトレイヤー
```c
  [_QWERTY] = LAYOUT(
  //,-----------------------------------------------------|   |--------------------------------------------------------------------------------.
       KC_ESC,    KC_1,    JU_2,    KC_3,    KC_4,    KC_5,        JU_6,    JU_7,    JU_8,    JU_9,    JU_0, JU_MINS,  JU_EQL,  JP_YEN,  JU_GRV,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------+--------|
       KC_TAB,    KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,        KC_Y,    KC_U,    KC_I,    KC_O,    KC_P, JU_LBRC, JU_RBRC, KC_BSPC,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------|
    MO(_UNIX),    KC_A,    KC_S,    KC_D,    KC_F,    KC_G,        KC_H,    KC_J,    KC_K,    KC_L, JU_SCLN, JU_QUOT,  KC_ENT,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
      KC_LSFT,    KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,        KC_N,    KC_M, KC_COMM,  KC_DOT, KC_SLSH, KC_RSFT, MO(_FN),
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
               MO(_FN), KC_RALT, CK_MHLC, LT_NPSP,              LT_SBET, CK_HKRC,          KC_RALT, KC_RGUI
          //`---------------------------------------------|   |--------------------------------------------'
  ),
```

### Mac用レイヤー
_MACレイヤーを有効化すると、
`かな/英数とCommandのカスタムキーコード`と`Controlキー`が
デフォルトレイヤーを上書きするようになっています。
```c
  [_MAC] = LAYOUT(
  //,-----------------------------------------------------|   |--------------------------------------------------------------------------------.
      _______, _______, _______, _______, _______, _______,     _______, _______, _______, _______, _______, _______, _______, _______, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------+--------|
      _______, _______, _______, _______, _______, _______,     _______, _______, _______, _______, _______, _______, _______, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------+--------|
      KC_LCTL, _______, _______, _______, _______, _______,     _______, _______, _______, _______, _______, _______, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
      _______, _______, _______, _______, _______, _______,     _______, _______, _______, _______, _______, _______, _______,
  //|--------+--------+--------+--------+--------+--------|   |--------+--------+--------+--------+--------+--------+--------|
               _______, KC_LALT, MK_ESLC, _______,              _______, MK_KNRC,          _______, JP_CAPS
          //`---------------------------------------------|   |--------------------------------------------'
  ),
```

# まとめ・終わりに
少々長くなりましたが、自作キーボードのキーマップに詰め込んだこだわりと、
それを実現しているQMK Firmwareのコードをざっくり紹介してきました。

私はC言語を書いたことがなかったのですが、
このくらいならデフォルトのコード見て出来そう！という難易度で意外とお手軽です。
ちなみに今回はコードを書く前提のお話でしたが、
[Remap](https://remap-keys.app/)や[VIA](https://www.caniusevia.com/)など、コードを書かずにキーマップをカスタマイズできるソフトウェアもあります。

キーキャップやスイッチを変えて楽しむのも素敵ですが、
自作キーボードはキーマップを変えるのも楽しいよ！ということを
ちょっとでも感じて貰えれば嬉しいです。

あんまりカスタマイズしすぎると普通のキーボードに戻れなくなるので、
用法・用量にはご注意ください。

それでは。