QMK Firmwareのキーマップレイヤー機能
Lunakey Mini やその他の自作キーボードたち、そして Ergodox EZ などの市販キーボードでは、ファームウェアを書き換えて、自分にあったキーマップを定義して利用することができます。そのファームウェアは、QMK Firmware という名前のオープンソースソフトウェアです。
qmk/qmk_firmware: Open-source keyboard firmware for Atmel AVR and Arm USB families
Lunakey Mini は 40% キーボードと言って、100個以上あるフルキーボードと比較して、キー数が44個しかありません。少ないキー数は、それだけ指の移動量が少ないという利点を生み出すのですが、その反面、単に打鍵した際に打ち込める文字数も少なくなります。
その欠点を補うために、「何かと何かを同時に押す」というキーの同時押しによって打ち込める文字数を増やすことになるのですが、QMK Firmwareでは「レイヤー」という機能によりそれを実現しています。例えば「アルファベットを配置したレイヤー」や「数字を配置したレイヤー」、「記号を配置したレイヤー」といったようにキーマップを何枚か定義しておいて、「右下にあるキーを押しながら何かを押すことで、数字レイヤーのキーが押されたことにする」っていうことができるようになります。
一度定義してしまえば、その後は微調整していく程度で自然に使えるのですが、レイヤー機能の概念はちょっとした難しさがあり、誰にとっても直感的か、というとそうではなさそうです。僕も正しくレイヤー機能がどういう仕組みで動作しているのかをちゃんと把握したかったので、QMK Firmware のドキュメントを読みました。その際に日本語訳をしていたので、ここでちょっと掲載しておきます。
以下は、 Keymap Overview の前半部分の勝手日本語訳となります。
キーマップ概要
QMKキーマップはC言語の中で定義されます。データ構造は、配列の配列です。外側の配列はレイヤー配列のリストであり、レイヤー配列の内部はキーのリストです。ほとんどのキーボードは、この配列の配列の作成を補助するために、LAYOUT()マクロによって定義されます。
キーマップとレイヤー
QMKにおいて、 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS]
は、 action code を持つ 16 ビットのデータにてキーマップ情報の複数のレイヤーを保持します。最大で 32 個のレイヤーを定義可能です。
ちょっとしたキー定義の場合、action code の上位 8 ビットはすべて 0 であり、下位 8 ビットは keycode としてキーにより生成される USB HID usage コードになります。
それぞれのレイヤーは、同時に検証されます。レイヤーは 0 から 31 までインデックスされていて、上位のレイヤーが優先されます。
Keymap: 32 Layers Layer: action code matrix
----------------- ---------------------
stack of layers array_of_action_code[row][column]
____________ precedence _______________________
/ / | high / ESC / F1 / F2 / F3 ....
31 /___________// | /-----/-----/-----/-----
30 /___________// | / TAB / Q / W / E ....
29 /___________/ | /-----/-----/-----/-----
: _:_:_:_:_:__ | : /LCtrl/ A / S / D ....
: / : : : : : / | : / : : : :
2 /___________// | 2 `--------------------------
1 /___________// | 1 `--------------------------
0 /___________/ V low 0 `--------------------------
キーマップが持つ action code は、TMK の歴史的問題のため、一部のドキュメントでは keycode と呼ばれている場合があります。
キーマップレイヤーステータス
キーマップレイヤーの状態は、2 つの 32 ビットパラメータにより決定されます。
-
default_layer_state
常に有効であり参照されるベースキーマップレイヤー(0 - 31)を示します(デフォルトレイヤー)。 -
layer_state
各レイヤーの現在の on/off 状態をビットで持っています。
キーマップレイヤー ‘0’ は通常 default_layer
であり、ファームウェアの起動時に他のレイヤーは初期処理として off になりますが、config.h
の中でこれを異なる設定にすることが可能です。例えば Qwerty の代わりに Colemak に切り替えたいといった、完全にキーレイアウトを変えたいときは、 default_layer
の変更が便利です。
Initial state of Keymap Change base layout
----------------------- ------------------
31 31
30 30
29 29
: :
: : ____________
2 ____________ 2 / /
1 / / ,->1 /___________/
,->0 /___________/ | 0
| |
`--- default_layer = 0 `--- default_layer = 1
layer_state = 0x00000001 layer_state = 0x00000002
一方、layer_state
を変更することで、ナビゲーションキー、ファンクションキー(F1 - F12)、メディアキー、そして特殊なアクションといった機能のために、ベースレイヤーを他のレイヤーで上書きすることができます。
Overlay feature layer
--------------------- bit|status
____________ ---+------
31 / / 31 | 0
30 /___________// -----> 30 | 1
29 /___________/ -----> 29 | 1
: : | :
: ____________ : | :
2 / / 2 | 0
,->1 /___________/ -----> 1 | 1
| 0 0 | 0
| +
`--- default_layer = 1 |
layer_state = 0x60000002 <-'
レイヤーの優先順位と透過性
レイヤーのスタックにおいては、上位のレイヤーは優先度が高くなることに注意してください。ファームウェアは、最も優先度が高いアクティブレイヤーから下に向かって、キーコードを検索するように機能します。アクティブレイヤ上の KC_TRNS(透明)以外のキーコードを見つけると、検索が止まり、下位のレイヤーは参照されません。
____________
/ / <--- Higher layer
/ KC_TRNS //
/___________// <--- Lower layer (KC_A)
/___________/
上記のシナリオでは、上位のレイヤー上の不透明なキーが使われますが、 `KC_TRNS` (または同等のもの) が定義されたときはいつでも、下位レイヤーのキーコード( `KC_A` )が使われます。
注意: 特定のレイヤーの透明度を示す有効な方法:
KC_TRANSPARENT
-
KC_TRANS
(エイリアス) -
________
(エイリアス)
これらのキーコードを使用することで、処理されるべき透明ではないキーコードの検索において、下位のレイヤーに処理をフォールスルーすることが可能になります。