Lily58による.xmodmapのハードウェア実装
こんにちは、びしょ〜じょです。 これはWORDIAN Advent Calendar 2018の2日目の記事です。
12月2日といえば、翌3日は冴草きいちゃんの誕生日ですね!!!!!!!!!!! めでたいですね。 何度でも言うぞ。
さて今回はWORD部員協賛のもと、Lily58というキーボードを作りました。
寝ぼけてLily58ポチってしまった。
— びしょ〜じょ (@Nymphium) November 15, 2018
材料あつめ
上記のセットに加え、キースイッチとキーキャップを58個(とUSBケーブルとTRSケーブルを)揃える必要があります。
WORD編集部室には3x3で全色異なるキースイッチのサンプルがあるので、お手元が寂しくなるとつい手を動かしてしまうW部員達には重宝されている。 カチカチしまくった結果、緑軸が良いな〜と思ったので緑軸にしようとしたものの、ちょうどどこを探しても8000個から仕入れ可能みたいなものしかなかった。 仕方がないので、遊舎工房でKailhのロープロ白軸を買った。
カチカチとクリック感があり、青軸のようにうるさいのでパソコンカタカタオタク演ってる感がでて良いかな〜というのが選定理由だ。
作る
3月の引越しにつき祖父からもらったり実家からパチってきた激古はんだごてを全部捨ててしまったため、部員の@rizaudo氏にはんだごてを借り、ついでに編集部室で作業をおこなう。
ビルドガイドにしたがって作っていく。
pro micro事件1
が…
前回までのラブライブ! 逆に取り付けたので半田吸い取り機を使おうとするも半壊しているのでトーストでハンダを溶かそうとするもまたもや失敗。 pic.twitter.com/cww2frd9vB
— びしょ〜じょ (@Nymphium) November 20, 2018
ヘ タ ク ソ1
トーストによるハンダクラックは無事失敗。 部室にあったポンコツハンダ吸い取り器や、部員のハジョン氏にハンダ吸い取り線を借りるも難航。 rizaudo氏や部室を常時警備している@akkkix氏の協力のもとハンダを吸いまくるも取れる気配がない。 @NTSC_J氏にも部室にあるものよりも使えるハンダ吸い取り器を持ってきてもらい、交代しながらハンダを吸っていく。
日が変わり、そして―
100年プロジェクトが完成した。 pic.twitter.com/dFbRgmX33e
— びしょ〜じょ (@Nymphium) November 20, 2018
およそ5時間経過し、pro microを取り出すことに成功した。 作業員がこの時間で各々バイトをして発生した金で諸々買い直したほうが黒字だし早かったね、という話をした。 たしかにこの時点で人件費が材料費を上回ってしまっている。
くぅ〜疲れましたw これにてlily58完成です! とはいかず…。
pro micro事件2
基板に全部くっつけたのでファームウェア書き込んでおわりや!! というところで片方に全然書き込めない。 オーブンで焼いたほうは特定のキー列だけ入力を受け付けたり受け付けなかったりする。
後者の問題はpro microを剥がしたときにランドが1つお亡くなりになったことに起因すると推理し、rizaudo氏がハンダを盛りまくることで導通してくれた。 謝謝茄子。
問題は前者である。 pro microを使う他の自作キーボードを作ってるブログなどを見てみると、なんかpro microを非対称(?)に付ける必要があるっぽいな…???
(作ってる時には説明なかった)pro microを取り付ける部分はたしかになんか書いてありますねぇ!!
恐怖のハンダ吸いが再び始まり―
pro micro救出に成功 pic.twitter.com/h3GMcZt1NU
— びしょ〜じょ (@Nymphium) November 21, 2018
pro microを救いきれなかったので破棄そして新しいのを注文して明日再開…。
— びしょ〜じょ (@Nymphium) November 21, 2018
オワッ…
仕方がないのでハードウェア的に問題ない半分を完成させた。
半分完成!!!(16時間経過) pic.twitter.com/MUhWVl3TEv
— びしょ〜じょ (@Nymphium) November 21, 2018
早速代打を注文し、激戦の翌々日に届き、ネタが割れてしまえば爆速で完成。
lily58、pro microを一つ失って完成…!!!! pic.twitter.com/ybr8uP24Lo
— びしょ〜じょ (@Nymphium) November 23, 2018
tips
ロープロファイルだとアクリル板を止めるネジの頭にキーキャップが当たるので、キーキャップをちょっと削る必要がある(図2)。
そういえば昔WORDの記事でThinkPadのキートップを無刻印にすべくヤスリで削りまくった記憶がある。 今回はカッターでゴリゴリ削ってしまっているが、コチラのほうがはるかに作業時間が短い。
ハードウェアの実装は18時間くらいかかってしまった。 ご協力大変感謝いたします。
qmk firmware
xmodmapとはなんだったのか
まずはこちらをご覧ください。
settings/settingfiles/dots/.xmodmap
例えばキーボードの3
を押すと3
が入力され、Shift
も一緒に押すと#
が入力されたりする。
Shift
のように、一緒におすとキーの入力が変わるのを修飾キーと呼びます。
他にもCtrl
も修飾キー。
そしてアクセント記号付き文字を入力するためのAltGr
というキーも存在しますが、概ね皆さんが使ってるキーボードには備わってません。
xmodmapによってキーマップを変更し、AltGr
が使えるようになります。
AltGr
が使えるとどうなる?
修飾ない状態、Shift
修飾状態、AltGr
修飾状態、AltGr + Shift
修飾状態と1つのキー入力で最大4状態もたせる、つまり1つのキーと2つの修飾キーによって4通りの入力をおこなうことができる。
上記のキーマップでは無変換
をAltGr
にしてhjklで←↓↑→を入力できるようにしてます。
これはVの者にとっては非常に素晴らしいですね。
困る点
X11アプリケーションなのでX Window Systemが動いてないといけない。 なのでWindowsとかXのない状況では諦めざるを得ない。
もう一つ重大な問題としては、キーコードに対するマッピングでしかないということである。 詳細はウィキピージャ見てください。 なにかアプリケーションでキー入力を受け付けるとき、文字コードではなくキーコードを受け付けている場合非常に困る。
そこでファームウェア
qmk_firmwareは名前の通りファームウェアでして、こいつを使うことでキースイッチの入力に対応するキーコードをプログラムすることができる。
keyboards/以下に様々なキーボードのいろいろが突っ込まれてて正気の沙汰ではないですね。 サブモジュールって知ってますか?
qmkにはレイヤという概念があり、上記のAltGr
のような事を、レイヤを切り替えることによって実現している。
このレイヤはユーザによっていっぱい作れるので、様々なレイヤを定義、しよう。
そしてボクのキーマップはこんな感じになった。
https://github.com/Nymphium/qmk_firmware/blob/nymphium/keyboards/lily58/keymaps/nymphium/keymap.c
キーマップのレイヤごとにAAを書くというのが習慣らしい。 たしかに分かりやすい(実際の設定と一致してれば)。
/* DEFAULT
* ,-----------------------------------------. ,-----------------------------------------.
* | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | Tab | Q | W | E | R | T | | Y | U | I | O | P | |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* |Enter | A | S | D | F | G |-------. ,-------| H | J | K | L |Muhen | |
* |------+------+------+------+------+------| Y | | B |------+------+------+------+------+------|
* |LShift| Z | X | C | V | B |-------| |-------| N | M | | | |MOUSE |
* `-----------------------------------------/ / \ \-----------------------------------------'
* |Super | LAlt |LOWER | / Space / \ BSPC \ | Ctrl |MOUSE |Wdeflt|
* | | | |/ / \ \ | | | |
* `----------------------------' '------''--------------------'
*/
レイヤごとにキーコードを割り当てられる。
これはデフォルトレイヤーで次が上記のxmodmapのキーマップにおけるAltGr
を押した状態になる。
/* LOWER
* ,-----------------------------------------. ,-----------------------------------------.
* | | F1 | F2 | F3 | F4 | F5 | | | [ | ] | F12 | | |
* |------+-----+------+------+------+-------| |------+------+------+------+------+------|
* | | @ | + | ESC | ; | ^ | | | . | , | HOME | END | |
* |------+-----+------+------+------+-------| |------+------+------+------+------+------|
* | | - | % | \ | / | ' |-------. ,-------| Left | Down | Up |Right |Henkan| |
* |------+-----+------+------+------+-------| | | |------+------+------+------+------+------|
* | | F6 | F7 | F8 | F9 | F10 |-------| |-------| F11 | PgDn | PgUp | | | |
* `-----------------------------------------/ / \ \-----------------------------------------'
* | | | | / / \Delete\ | | | |
* | | | |/ / \ \ | | | |
* `----------------------------' '------''--------------------'
*/
qmkはマウスのエミュレーションができる。
これはAAを用意してないんで実際の実装になっており、LAYOUT
マクロに渡されているのはそれぞれキーコードに対応する。
_______
は1つ前のレイヤのキーコードを参照する。
[_MOUSE] = LAYOUT( \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
KC_BTN1, KC_BTN3, KC_BTN2, WHEEL, _______, _______, _______, _______ \
),
キー入力処理
キー入力をprocess_record_user
という関数で処理することができる。
レイヤ切り替えはcustom_keycode
というenumで新しく追加したレイヤ切り替え専用のキーコードの入力をprocess_record_user
で処理する(プログラム4)。
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
// ......
case LOWER:
if (record->event.pressed) {
layer_on(_LOWER);
update_tri_layer(_LOWER, _SHIFT, _LSHIFT);
} else {
layer_off(_LOWER);
update_tri_layer(_LOWER, _SHIFT, _LSHIFT);
}
return false;
break;
case KC_LSFT:
if (record->event.pressed) {
register_code(KC_LSFT);
layer_on(_SHIFT);
update_tri_layer(_LOWER, _SHIFT, _LSHIFT);
} else {
layer_off(_SHIFT);
update_tri_layer(_LOWER, _SHIFT, _LSHIFT);
unregister_code(KC_LSFT);
}
return false;
break;
// ......
case KC_GRV:
case KC_EQL:
case KC_ASTR:
unregister_code(KC_LSFT);
return true;
}
return true;
}
keycode
は文字通りキーコード、record
は入力してるときの状態を表し、record->event.pressed
でキーを押下したかどうかのブールを取れる。
関数の中を見てみると、keycode
でswitchして入力内容で分岐する。
LOWERレイヤへの切り替えは、layer_on(_LOWER)
とlayer_off(_LOWER)
のあたりでおこなっている。
LOWER+Shift
の修飾では第3のレイヤ_LSHIFT
になる。
KC_LSFT
というキーコードがShift
にあたる。
Shift+0
を押すと?
が出て欲しいなど、一部Shift
による修飾で送出される文字を変更したかったがお手軽な方法が一見してなさそうだった。
そのため、Shift
用に新たにレイヤを追加した。
また一部キーはShift
修飾を外さないと意図した入力がおこなわれないため、unregister_code(KC_LSFT)
でShift
の修飾を取り消している。
process_record_user
の戻り値は長押しキーリピートするかどうかである。
使ってみての所感
白軸カチャカチャして楽しい。 慣れるとだいぶ快適だし、Windowsでも使えるようにちょっとした工夫もしているためWindowsでも快適な入力ができる。 ウィンドウマネージャが変更できてフォントも綺麗に表示されてWSLがちゃんと動いてアレしてコレしたらWindowsでも快適に開発できそうですね!
ハードウェア的なところとしては概ね満足ですが、キーボードが格子状なのは慣れの問題なのか、なかなか打ちづらい。 あとパームレストがないと親指がキートップのエッジのせいでちょっと痛くなる。 というか上の行がちょっと打ちづらい? ともかくパームレストは遭ったほうが良いなこれは。
これでボクがArchを使ってから愛用してきた秘伝の.xmodmapをファームウェアレベルでエミュレーションできたんじゃないでしょうか。 とはいえキーボードを持ち運ぶのはだるいので、基本的には在宅ワークするときやお家でツイッタ〜するときのみ活躍します。
他にも状態のトグルなどちょっとした知見がコードに溜まってるので、qmk_firmwareを使ってなにかする人は上記のソースを見てみてください。
-
ビルドガイドがボクの失敗を見たためかどうか、失敗したポイントについて丁寧な解説が加えられている。みなさんは私の屍を超えて失敗レスに作ることができます。 ↩