Claw44であそぼ。⑤(Rotary Encoder編)
はじめに
一日で一番手に触れているものはキーボードという思い込みから、不便さを克服することにより得られる快楽を毎日満喫するために小さなキーボードの導入を思い立ち、2022年12月にClaw44の購入を決意。プログラミングと自作キーボードの知識ゼロから始めた自作キーボード素人によるClaw44カスタマイズの奮闘記を綴っていきたいと思います。
Rotary Encoderとは
ロータリーエンコーダとは最近の市販キーボードにも搭載されるようになったボリュームを調整する時にあったら便利だなーとクルクル回すアレである。中にはプッシュスイッチ付きといって、クルクル回転に加えて、ポチッと押すとスイッチとしても機能する贅を尽くした物も存在する。ロータリーエンコーダを導入すると、今まではキースイッチの1次元の上下運動のみで対応していた入力方法が、クルクル回転機能とポチポチ機能という3次元の世界への広がりを意味し、キーボードの世界観そのものが変化します。クルクル回転についても時計回り/反時計回りで入力を切り替えることができるため、ひと粒3度美味しいというまさに不便さを克服することにより得られる快楽を味わうことができる夢の入力デバイスといえる。
Claw44には拡張プレートが準備されており、この拡張プレートを活用することで、最大左右2つずつ合計4つのロータリーエンコーダを搭載することができる。
猫山王のClaw44にもこの拡張プレートを活用して、左手側に2つのロータリーエンコーダを搭載することで夢のデバイスとして大活躍している。
Rotary Encoderの楽しみ方
1.ロータリーエンコーダを購入してキーボードにはんだ付けしよう
ロータリーエンコーダはClaw44の開発者のyfukuさんのショップ、自作キーボード会の萬屋的存在の遊舎工房やAliExpressで販売されている。またロータリーエンコーダとあわせてノブも購入する必要がある。ロータリエンコーダとノブを購入するときの注意点としては、軸の形状を合わせる必要があるということ。軸の形状はDの形状をしたものと丸い形状をしたものの2種類があります。また、ギターのノブにすることでひと味違うおしゃれ感が味わえます。猫山王の上のノブがギターのノブで、下のノブはyfukuさんのショップで購入したものになります。取付方法は、拡張プレートにロータリーエンコーダをはんだ付けして、ノブを取り付けるというすこぶる簡単で、Claw44 v3のビルドガイドにも丁寧に記載してあるので迷うことはないでしょう。
2.ロータリーエンコーダに命を吹き込もう
ロータリーエンコーダを拡張プレートにはんだ付けするだけでは、単なるお飾りで夢のデバイスとして全く機能しません。ロータリーエンコーダに命を吹き込むために変更が必要なファイルは、keymapsフォルダ下のrules.mkファイル、config.hファイルとkeymap.cファイルの3つです。それぞれのファイルを書き換える方法については、猫山王の設定を参考にひとつひとつ解説していきたいと思います。
3.rules.mkファイルの内容を書き換えよう
keymapsフォルダ下のrules.mkファイルにロータリーエンコーダマップを有効とする召喚呪文を追加します。info.jsonファイル内にも "encoder": trueとあるので、すでにロータリーエンコーダを使える状態ではありますが、ENCODER_MAP_ENABLEを有効にすることで、ロータリーエンコーダに関するキーマップの呪文を大幅に簡素化でき、Remap上でのロータリーエンコーダの設定変更が可能になります。
ENCODER_MAP_ENABLE = yes
4.config.hファイルの内容を書き換えよう
keymapsフォルダ下のconfig.hにロータリーエンコーダの感度を定義します。つまり、クルクル回転度に応じてどれだけボリュームを上げ下げするかを決める重要な数値です。ここではENCODER_RESOLUTIONの値を小さくすれば感度は高くなり、逆に大きくすれば感度を低くなります。猫山王の設定では4がしっくりきています。
/* enable action for endcoders */
#define ENCODER_RESOLUTION 4
5.keymap.cファイルの内容を書き換えよう(ENCODER_MAP_ENABLEのパターン)
keymapsフォルダ下のkeymap.cファイルにロータリーエンコーダの動作の呪文を記載します。キーマップ同様にレイヤーごとに各ロータリーエンコーダの動作を定義できるので、使う使わないはさておきキーマップのレイヤー数と合わせておくといいでしょう。レイヤーとの関連については、②レイヤー数拡大編にも記載していますので、導きの書として参照しましょう。また、猫山王のClaw44に搭載しているロータリーエンコーダは左側に2つですが、将来的にカルテット仕様にもスムーズに移行できるようにロータリーエンコーダ4つ仕様の呪文にしています。ちなみに、プッシュスイッチの動作についてはキーマップに記載することになります。クルクル回転殺法とポチポチ連打拳の動作については、Remap上でお手軽に変更できますし、何せRemap上で変更したほうがより多くのキーコードに対応しているのでkeymap.cファイルでのキーコードの記載はあまり神経質になる必要はなく全てKC_NOでも良いでしょう。例えば、RBG系のキーコードのうちRGB_HUIなどのキーコードは暗黒世界のコンパイル中にエラーになりますが、なぜかRemapでは設定できたりと猫山王もまだ解明できていない未解決問題です。ロータリーエンコーダの呪文の記載位置はキーマップの下が分かりやすくて良いでしょう。ちなみに、ENCODER_CCW_CW(KC_NO, KC_NO) のCCWは反時計回り、CWは時計回りを意味し、それぞれに対応するキーコードを記載しておけばOKという簡単親切仕様です。以下に猫山王の6レイヤー仕様のクルクル回転殺法の呪文と解読できるように簡単な日本語訳も記載しておきます。
/* ロータリーエンコーダの設定 ENCODER_MAP_ENABLEのパターン */
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { //2回転方向の数であってロータリーエンコーダの数ではない
[_10] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_WH_L, KC_WH_R), ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, //メインレイヤー10の動作
[_11] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_LEFT, KC_RGHT), ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, //レイヤー11の動作
[_12] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, //レイヤー11の動作
[_13] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, //レイヤー13の動作
[_14] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_WH_U, KC_WH_D), ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, //レイヤー14の動作
[_15] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, //レイヤー15の動作
};
#endif
6.keymap.cファイルの内容を書き換えよう(ENCODER_MAP_ENABLEを使用しないパターン)
最新のRemapはENCODER_MAP_ENABLEに対応していますが、旧バージョンのRemapはENCODER_MAP_ENABLEに対応していませんでした。その場合の呪文の記載方法についてもカルテット仕様を参考に記載しておきます。
/* ENCODER_ENABLEのパターン */
#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise){
if (index == 0) {
switch (get_highest_layer(layer_state)) {
case _10:
if (clockwise) { tap_code(KC_VOLU); } else { tap_code(KC_VOLD); };
break;
case _11:
if (clockwise) { tap_code(KC_VOLU); } else { tap_code(KC_VOLD); };
break;
case _12:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _13:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _14:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _15:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _16:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
}
}
else if (index == 1) {
switch (get_highest_layer(layer_state)) {
case _10:
if (clockwise) { tap_code(KC_WH_R); } else { tap_code(KC_WH_L); };
break;
case _11:
if (clockwise) { tap_code(KC_RGHT); } else { tap_code(KC_LEFT); };
break;
case _12:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _13:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _14:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _15:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _16:
if (clockwise) { tap_code(KC_WH_D); } else { tap_code(KC_WH_U); };
break;
}
}
else if (index == 2) {
switch (get_highest_layer(layer_state)) {
case _10:
if (clockwise) { tap_code(KC_WH_R); } else { tap_code(KC_WH_L); };
break;
case _11:
if (clockwise) { tap_code(KC_RGHT); } else { tap_code(KC_LEFT); };
break;
case _12:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _13:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _14:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _15:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _16:
if (clockwise) { tap_code(KC_WH_D); } else { tap_code(KC_WH_U); };
break;
}
}
else if (index == 3) {
switch (get_highest_layer(layer_state)) {
case _10:
if (clockwise) { tap_code(KC_WH_R); } else { tap_code(KC_WH_L); };
break;
case _11:
if (clockwise) { tap_code(KC_RGHT); } else { tap_code(KC_LEFT); };
break;
case _12:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _13:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _14:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _15:
if (clockwise) { tap_code(KC_NO); } else { tap_code(KC_NO); };
break;
case _16:
if (clockwise) { tap_code(KC_WH_D); } else { tap_code(KC_WH_U); };
break;
}
}
return false;
}
#endif
この呪文は最新のRemapのファームウェアとしても機能しますが、Remap上でキーコードを変更できないという欠点があります。すなわち、この呪文はクルクル回転殺法を変更したい場合には毎回ソースコードを書き換えてコンパイルするという修行をいとわない、いわば究極の不便さからくる快楽を好む賢者仕様になります。ただ、この賢者仕様にもENCODER_MAP_ENABLE仕様に比べてレイヤー数を1つ増やすことができるというまさに肉を切らせて骨を断つという捨て身で不便さを克服できるという利点があります。レイヤー中毒の修行僧にとって、プラス1のレイヤーというのは喉から手が出るほど欲しい秘薬といえるでしょう。
7.さあ、コンパイルしよう
ここまでくれば最後はQMK MSYSでのコンパイルです。呪文のコンパイルの成功は、暗黒世界の中で不便さを克服することにより得られる快楽を求める修行僧として極楽浄土に達したことを意味します。ただし、クルクル回転殺法とポチポチ連打拳の使い手となるためには更なる精進が必要で修業の日々に逆戻りです。
実際にRotary Encodeを利用してみて
ロータリーエンコーダは、反時計回り・時計回り・プッシュのクルクルポチッ、クルクルポチッの動きがあり、これら動きのそれぞれにキーコードを割り当てることができる夢のデバイスといえるでしょう。ロータリーエンコーダを活用することで、今までの上下運動のみのタイピングからクルクルポチッの直観による操作系をスパイスとして加えることができます。ロータリーエンコーダの使い方としてすぐに思いつくのは、クルクルポチッにボリュームとミュートを割り当てることでボリュームコントローラーであり、猫山王のClaw44にもこの機能を割り当てているレイヤーもあり非常に重宝しています。一方でこの直観による操作系というのが曲者で、使用者のセンスが問われる分野でもあります。例えば、Claw44に最大数の4つのロータリーエンコーダを搭載したカルテット仕様に、最大数の7レイヤーともなれば、なんと28通りの使用方法が可能となります。ここまでくると、クルクル回転殺法とポチポチ連打拳の達人でなければ、すべてのロータリーエンコーダを使いこなすことは決してできない悪夢のデバイスと化しています。この域に達するには記憶力も重要な要素となり、根性と体力と気合だけで克服できた今までの不便さとは明らかに異なる暗殺拳の修行も漏れなくついてきます。
ボリュームコントローラー以外の使用方法としては、進む・戻るを割り当てたYoutube快適仕様、拡大・縮小を割り当てた虫眼鏡仕様、上下や左右のスクロールを割り当てた通勤快速仕様、LEDのRGBの色やパターンの変更を割り当てた光の魔術師仕様、レイヤー切り替えを割り当てた世界一周仕様などが考えられますが、猫山王も夢のデバイスとしての実用的な使用方法がこれ以上思いつきません。画期的な使用方法があれば是非教えて欲しいです。
ロータリーエンコーダというものは、見た目のインパクトと直感的な操作性の分野では破壊力のある神器であり、ボリュームコントローラーとしては直感的かつ唯一無二の存在ではあるもののそれ以外の用途がなかなかないかもしれない諸刃の剣でもある。自作キーボードの初心者にとっては憧れのクルクル回転殺法とポチポチ連打拳の夢のデバイスではあるがその活躍の場は使用者の創造力によるところが非常に大きいといえよう。このことは夢のデバイスの活用方法を四六時中考えるという生みの苦しみと不便さの克服による快楽は毎日満喫できるという悪夢が保証されているといえる。
自作キーボードは敷居が高いと思われている方にとって、一日で一番手に触れているものはキーボードということで、不便さを克服することにより得られる快楽の世界への入門のための勇気づけとなれば幸いです。
次回
さて次回はLED導入の奮闘記をお届けします。LEDを搭載することで、キーボードに光の力を与えることができます。OLEDは一色だけの夜光虫仕様であるの対して、LEDは七色に光るまさしくレインボー仕様といえます。真っ暗な部屋の中でQMK MSYSの暗黒世界のとの格闘の最中、七色に光るキーボードを目の当たりにするとそれはまさしく天岩戸開きの瞬間であるかのような錯覚を引き起こします。七色に光る神秘的なキーボードを手に入れるためには、神器であるLEDを自由自在に使いこなす必要があり、そこにはさらなる苦悩が待ち受けています。不便さを克服することにより得られる快楽を求める修業はまだまだ続きます。