YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

qmkコマンドでkeymap.cからキーマップの図を生成する

はじめに

こんにちは、Google Cloud Operations担当者です。最近のCloud Ops関連のリリースではCloud ProfilerのHistory Viewがお気に入りです。

最近は自作キーボードのパーツショップの開店に向けて仕入れなどをほそぼそと行っています。海外からの仕入れはいろいろと難しいことがたくさんある!今月末には開店したいなと思います。

それとは別に自作キーボードエンジョイ勢として、新しいキーボードを組み立てたり、キーマップの変更を楽しんだりしています。

キーマップの作成は普段は直接エディターで keymap.c を編集しているんですが、大胆に変更を加えたあとはキーマップを覚えきれておらず、いちいち keymap.c を確認しにいっていました。しかしそれが非常に面倒だと思っていたところ、こちらのPull Requestがあったので、早くmasterに入らないかなと思っていたところ、ついに取り込まれたので早速試してみました。

qmk c2json コマンド

github.com

このPull Reqeustによって qmk_firmware に取り込まれているキーボードの標準的なキーマップ(コンボやマクロを多用していないようなもの)の keymap.cQMK Configuratorで使用できる keymap.json に変換できるようになりました。まだPyPIでダウンロードできる qmk コマンドには取り込まれていないので、本記事執筆時のmasterのHEAD(bc79e51)で試してみます。

$ cd ${QMK_FIRMWARE_ROOT}
$ python -m venv .venv
$ .venv/bin/pip install -r requirements.txt
$ .venv/bin/python ./bin/qmk c2json -o keymap.json -km ymotongpoo -kb crkbd/rev1 keyboards/crkbd/keymaps/ymotongpoo/keymap.c
Ψ Wrote keymap to /home/ymotongpoo/personal/qmk_firmware/keymap.json

venvのくだりは個人の趣味でOS直に入っているPythonの環境を汚したくないだけなので、気にしない人はこのあたり無視していきなり pip install して大丈夫です。ここで生成した keymap.json を QMK Configurator に読み込ませてみると表示されました!これは助かる!

f:id:ymotongpoo:20201007122030p:plain

これをPDFにするなり印刷するなりして見えるところに置いておけばいつでもキーマップを確認できますね。

f:id:ymotongpoo:20201007121613p:plain

参照

config.qmk.fm

QMK FirmwareでバックライトLEDを制御する

はじめに

こんにちは、Google Cloud Operations担当者です。もうStackdriverという名前は忘れてください。最近はキーボードをたくさん作っていますが、Helix 4行ではじめてバックライトLEDなキーボードを作って、その後foobarやLet's SplitをテープLEDでアンダーグロー化しました。最初はプリセットのアニメーションで遊んでただけだったんですが、どうせならちゃんとレイヤーやキーに応じてバックライトの色を変えたいと思ったので実際にやってみました。

HelixはバックライトLEDでより多くの制御が可能で、キートップからも見えて楽しいので、以下Helix 4行での実装となります。ただしRGB Lightingをつかっている実装であればどれでも同様に可能です。

QMK RGB Lighting

docs.qmk.fm

QMKにはいくつかのLEDの制御方法がありますが、HelixはバックライトがシリアルLEDとして動作していることもあり、RGB Lightingを使って制御するのが良さそうです。(ドキュメント見ながら調べていたらSMKIJのscrapboxにそう書いてあったので、そのまま参考にした)

rules.mk

RGB Lightingを使うときはいくつかのフラグを有効にしたりヘッダファイルをincludeしてあげる必要があります。LEDを制御する場合は次のフラグを有効にします。

RGBLIGHT_ENABLE = yes

Helixの場合はデフォルトでいろいろ設定されていて、 LED_ANIMATIONS = yes とすれば諸々アニメーションに関するフラグが設定されます。このフラグはプリセットのLEDアニメーション(グラデーションで色が時間変化していくとか)を動かすためのフラグで、それ以外に必要なフラグはHelixでは上の階層の rules.mklocal_features.mk で設定してくれています。

config.h

次に config.h でマクロ定数をいくつか定義します。ビルドガイドに何かしらフルカラーLEDに対応というようなことが書いてあれば、キーボードのデフォルトの config.h ですでに設定されていると思いますが、2017年かそれ以前に設計されたような基板ではまずProMicroのどのピンでLEDを制御するかのマクロ変数を定義します。次の例はfoobarでLEDテープを実装したときのものです。

#define RGB_DI_PIN B6

ここのピンの番号はProMicroのポートの番号です。

f:id:ymotongpoo:20200909213604p:plain

で、それ以外の細かな部分のマクロ変数を定義します。各変数の細かな説明は公式ドキュメントを読んでください。(非常に投げやりな説明)次の例はHelix 4行でのものです。

#define RGBLIGHT_LAYERS
#undef RGBLED_NUM
#define RGBLED_NUM 50
#define RGBLED_SPLIT {25, 25}
#define RGBLIGHT_MAX_LAYERS 8

#define LED_LAYOUT( \
    L00, L01, L02, L03, L04, L05,           R00, R01, R02, R03, R04, R05, \
    L10, L11, L12, L13, L14, L15,           R10, R11, R12, R13, R14, R15, \
    L20, L21, L22, L23, L24, L25,           R20, R21, R22, R23, R24, R25, \
    L30, L31, L32, L33, L34, L35, L36, R30, R31, R32, R33, R34, R35, R36 \
) { \
    L05, L04, L03, L02, L01, L00, \
    L10, L11, L12, L13, L14, L15, \
    L25, L24, L23, L22, L21, L20, \
    L30, L31, L32, L33, L34, L35, L36, \
    R00, R01, R02, R03, R04, R05, \
    R15, R14, R13, R12, R11, R10, \
    R20, R21, R22, R23, R24, R25, \
    R36, R35, R34, R33, R32, R31, R30 \
}

#define RGBLIGHT_LED_MAP LED_LAYOUT( \
   0,  1,  2,  3,  4,  5,            30, 29, 28, 27, 26, 25, \
   6,  7,  8,  9, 10, 11,            36, 35, 34, 33, 32, 31, \
  12, 13, 14, 15, 16, 17,            42, 41, 40, 39, 38, 37, \
  18, 19, 20, 21, 22, 23, 24,    49, 48, 47, 46, 45, 44, 43)

RGBLIGHT_LAYERS を呼ぶのを忘れると、次のようにエラーがでます。(ドキュメントにちゃんと書いてあったのに雰囲気でやったらはまった)

$ sudo ./util/docker_build.sh helix/rev2:ymotongpoo
QMK Firmware 0.9.55
Making helix/rev2 with keymap ymotongpoo

avr-gcc (GCC) 5.4.0
Copyright (C) 2015 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.

Size before:
   text    data     bss     dec     hex filename
      0   26300       0   26300    66bc .build/helix_rev2_ymotongpoo.hex

Compiling: keyboards/helix/rev2/keymaps/ymotongpoo/keymap.c                                        keyboards/helix/rev2/keymaps/ymotongpoo/keymap.c:52:7: error: type defaults to 'int' in declaration of 'rgblight_segment_t' [-Werror=implicit-int]
 const rgblight_segment_t PROGMEM _default_layer[] = RGBLIGHT_LAYER_SEGMENTS(
       ^
keyboards/helix/rev2/keymaps/ymotongpoo/keymap.c:52:34: error: expected ',' or ';' before '_default_layer'
 const rgblight_segment_t PROGMEM _default_layer[] = RGBLIGHT_LAYER_SEGMENTS(
                                  ^
...(中略)...

keyboards/helix/rev2/keymaps/ymotongpoo/keymap.c:70:25: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token
 const rgblight_segment_t* const PROGMEM rgblight_layers[] = RGBLIGHT_LAYERS_LIST(
                         ^
cc1: all warnings being treated as errors
 [ERRORS]
 |
 |
 |
make[1]: *** [tmk_core/rules.mk:386: .build/obj_helix_rev2_ymotongpoo/keyboards/helix/rev2/keymaps/ymotongpoo/keymap.o] Error 1
Make finished with errors
make: *** [Makefile:584: helix/rev2:ymotongpoo] Error 1

シリアルLEDとして扱うので、LEDの長さと左右のキーボードでの分割のされ方を教えるために、RGBLED_NUM, RGBLED_SPLIT を設定します。またデフォルトだとLEDの番号は左手右上から始まり、そこからジグザグに番号がついていてわかりにくいので、番号のアサインを変更するために LED_LAYOUTRGBLIGHT_LED_MAP を設定します。 (下の図は参照のブログより転載)

f:id:ymotongpoo:20200824010006p:plain

これで下準備が完了です。

keymap.c

keymap.c ではまず上のように配置されたLEDを各々どのような色にするかの設定を RGBLIGHT_LAYER_SEGMENTS マクロで行います。マクロ内で指定する値は {LEDマップ名の番号, 連続して設定するLEDの数, 色} となります。たとえば {6, 4, HSV_GREEN} であれば、番号6から9までの4つを緑にします。

const rgblight_segment_t PROGMEM rgb_default_layer[] = RGBLIGHT_LAYER_SEGMENTS(
    {0, 1, HSV_GREEN}, // left
    {6, 1, HSV_GREEN},
    {12, 1, HSV_GREEN},
    {18, 4, HSV_GREEN},
    {22, 2, HSV_CHARTREUSE},
    {24, 1, HSV_PURPLE},

    {25, 1, HSV_GREEN}, // right
    {31, 1, HSV_GREEN},
    {37, 1, HSV_GREEN},
    {43, 4, HSV_WHITE},
    {48, 2, HSV_PURPLE}
);

const rgblight_segment_t PROGMEM rgb_lower_layer[] = RGBLIGHT_LAYER_SEGMENTS(
    {1, 5, HSV_PINK}, // left
    {6, 12, HSV_CORAL},

    {26, 5, HSV_PINK}, // right
    {31, 12, HSV_AZURE},
    {43, 4, HSV_BLUE}
);

const rgblight_segment_t PROGMEM rgb_raise_layer[] = RGBLIGHT_LAYER_SEGMENTS(
    {1, 5, HSV_CORAL}, // left
    {7, 4, HSV_WHITE},

    {26, 5, HSV_CORAL}, //right
    {32, 4, HSV_WHITE},
    {43, 4, HSV_BLUE}
);

ここでは3つのLED用のレイヤーを定義しました。これらのレイヤを使うことをRGBLIGHT_LAYERS_LISTを使って登録します。

const rgblight_segment_t* const PROGMEM rgb_layers[] = RGBLIGHT_LAYERS_LIST(
    rgb_default_layer,
    rgb_lower_layer,
    rgb_raise_layer
);

この状態ではLEDのレイヤーを使うことを定義して宣言したまでなので、次は実際にキーマップのレイヤーと対応させる必要があります。その対応は layer_state_set_user() 内で rgblight_set_layer_state() で行います。書き方は

rgblight_set_layer_state(RGBLIGHT_LAYER_SEGMENTSマクロで返される配列でのインデックス, 何かしらのbool条件)

キーマップのレイヤーの状態が state に入ってくるので、keymaps[] に指定した添字で対応させるのに layer_state_cmp() を使います。

layer_state_t layer_state_set_user(layer_state_t state) {
    rgblight_set_layer_state(0, layer_state_cmp(state, _QWERTY));
    rgblight_set_layer_state(1, layer_state_cmp(state, _LOWER));
    rgblight_set_layer_state(2, layer_state_cmp(state, _RAISE));
    return state;
}

これでレイヤーに応じて左右の両方のキーボードで異なるパターンのLEDを光らせられるようになり、ぱっと見ただけでレイヤーに配置した特殊キーの場所が把握できるようになりました。便利!

f:id:ymotongpoo:20200908235822j:plain

www.youtube.com

参照

rephtone.com

www.tnksoft.com

foobarのアンダーグローLEDの実装を左右対称に行ってみた

はじめに

こんにちは、Google Cloud Operations担当者です。Stackdriverという名前がドキュメントや変数名として出てきたら、歴史的経緯によるものだと理解してください。

最近このブログではキーボードの話しか書いてないので、仕事をしてないんじゃないかと思われていないか心配です。ちゃんとやってますよ。

さて先日foobarを作った後にアンダーグロー化しました。

ymotongpoo.hatenablog.com

このときは本家の実装にならって、メインのProMicroですべてのLEDを制御し、反対側はTRRSケーブルを通じてLEDの制御信号を送るように左右非対称の実装をしていました。(下の写真は本家より転載)

f:id:ymotongpoo:20200906213913j:plain

それにともなって、QMKの設定も RGBLIGHT_SPLITRGBLED_SPLIT といったマクロの定義をしないなど、左右非対称であるがゆえの注意などもありました。しかし他のキーボード(たとえばHelix)では左右対称にLEDを実装していて、LEDの左右での同期はQMKで行っていたので、同じ理屈でfoobarも左右対称に実装してQMKで制御するようにしたらいいのではないか、と思ったのでやってみました。

実装した

というわけで、ちょうど積みキーボードになっていたもう1組のfoobarがあったのでそちらであらたに左右対称にLEDテープを実装しました。*1

f:id:ymotongpoo:20200906222111j:plain

前回作成したfoobarでの実装も比較のために貼っておきます。

f:id:ymotongpoo:20200829112245j:plain

前回の実装は左手側はProMicroからGND、VCC、DINの3本に加えてDOUTからTRRSへの1本の計4本の配線と、右手側がProMicroからGNDとVCCの2本に加えてTRRSからDINへの1本の計3本という配線であるのに対して、今回の実装は左右ともにProMicroからGND、VCC、DINの3本の配線となっています。TRRSジャックにつながる配線はありません。

QMKの変更

上の実装の場合は前回使わなかった左右分離式キーボードでのLEDの制御に関する RGBLED_SPLITRGBLIGHT_SPLIT のそれぞれのマクロを定義してビルドします。といっても前回からの差分は config.h

#define RGBLED_SPLIT {5, 5}
#define RGBLIGHT_SPLIT

としただけです。

動かしてみた

www.youtube.com

ちゃんと期待通り動きました。これで左右対称に実装した場合にもQMKで対応できることが確認できました。

参考

ymotongpoo.hatenablog.com

www.40percent.club

*1:正確には左右対称ではないけれど、両方同様にProMicroから3本配線したという意味でそう書いています

ロープロファイルピンソケットでProMicroのソケット化をした

はじめに

こんにちは、Google Cloud Operations担当者です。Stackdriverという名前は歴史になりました。

さて、最近はどのキーボードキットを見てもたいていProMicroはコンスルーを同梱していたり、その使用を推奨していますが、PCBのスルーホールのサイズによっては使えなかったり、あと地味に高い。

yushakobo.jp

で、ProMicroのソケット化で探してみると、ソケットは丸ピンのICソケットとかを使っていて、リードダイオードの切り取った足を使ってソケット化するというような記事を多く見かけます。

しかし、自分はどうもそのピンの強度に不安を覚えたため、それとは別の方法でソケット化できないかと思って秋月電子のサイトを眺めたりしていたのですが、そこで良さそうな部品を見かけました。ロープロファイルピンソケットです。

akizukidenshi.com

これに、ProMicro付属のピンヘッダを普通にはんだ付けしてしまうとスペーサーが2つになり、高さが出てしまうため、ピンヘッダからピンを引き抜いて使おうという魂胆です。

やってみた

まず、先のピンソケットは1x20なので、これを1x12のサイズに切り離します。ニッパーで簡単に切れます。

f:id:ymotongpoo:20200822003149j:plain

次にProMicroに付属するピンヘッダからピンだけを抜き取ります。ラジオペンチで簡単に抜けます。

f:id:ymotongpoo:20200822004723j:plain

ピンソケットを基板にはんだ付けするために、マスキングテープで固定します。

f:id:ymotongpoo:20200822003312j:plain

はんだ付けしたら、そこにProMicroを載せて、上からピンを挿していきます。ピンを挿してから載せるのは至難の業になるので、先にProMicroをピンソケットに載せるのがポイントです。全部挿すと多少斜めに刺さったりしているものの、いい感じにはまります。あとは当たり前ですが、ProMicroの上下の向きには気をつけましょう。ただソケット化してるので片方だけなら間違えてもなんとかなりますね。

f:id:ymotongpoo:20200822010334j:plain

はんだ付けしたら飛び出したピンをきれいにカットしていきます。

f:id:ymotongpoo:20200822010655j:plain

見た目はかなり良い感じですね!高さも普通にピンヘッダを使って直接基板にはんだ付けしたときと変わりません。その後IC抜きなどを使って抜いてあげると....

f:id:ymotongpoo:20200822010735j:plain

良い感じにソケット化出来ました!ピンも普通のピンヘッダのピンを使っているので強度的にも安心です。

実際に使ってみて

懸念していたのは、このロープロファイルピンソケットが何回抜き差しに耐えうるかという点です。抜き差ししすぎてだめになったら、結局キースイッチを全部外さないと取り外せなくなってしまいます。データシートにも何回まで可能といった数字は書いてありませんでした。

とりあえず5回程度抜き差しした状態では普通に問題なく導通しているようので、しばらく様子を見ようと思います。しょっちゅう抜き差しするものでも無いと思いますし、万が一のときのための保険としては十分機能しているかなと思います。

foobarをアンダーグロー化した

はじめに

こんにちは、Google Cloud Operations担当者です。Stackdriverという名前はもう忘れてください。先日foobarを作りましたが、そのときにはまだ発注していたテープLEDが届いていなかったのでアンダーグローの実装はしていませんでした。

ymotongpoo.hatenablog.com

やっとテープLEDが到着したのでアンダーグロー化しようと思います。

LEDのはんだ付け

www.40percent.club

配線が見られる写真やビルドログがあまり見つからなかったのでとりあえず本家の写真を参考に配線をしました。

f:id:ymotongpoo:20200829112245j:plain

QMK Firmwareでの書き方によっては左右同じはんだ付けでいいのかもしれませんが、今回は本家のビルドログと同様にマスター側(左手)ですべて制御するような形にしました。

点灯しないのでデバッグ

全部配線を終えてファームウェアを焼いてみたものの、光らない。まずもう一度テスターでいろいろと導通チェックをしてみました。

f:id:ymotongpoo:20200830132711p:plain

f:id:ymotongpoo:20200830162451p:plain

まず導通チェックですが、上の図で同じ色の丸同士のどこを確認してもブザーが鳴り、導通していることの確認が取れました。

f:id:ymotongpoo:20200830163652p:plain

TRRSケーブルをつないで左手側のDOUTから右手側のDINまでTRRSケーブルを通じて導通していることも確認。導通は問題なさそうなので、今度は電圧を確認します。

f:id:ymotongpoo:20200830165147p:plain

f:id:ymotongpoo:20200830165224p:plain

左手側を確認するとどうも電圧が取れていない。右手側を確認すると正しく電圧が出ている。さてこれはどうしたものかなあと考えていたのですが、LEDが壊れているのかどうかが確証が取れず、方法もわからなかったのでSMKIJの皆さんにまたもや相談。*1

原因

甘いはんだ付け

症状を共有するとa_p_u_r_oさんから早速次のようなアドバイスをいただきました。

左手側のLEDストリップのVCCがPro MicroのVCCと導通しているかもう一度確認したいです。

この部分は最初に導通を確認したはずなんだけれども、なにか変わっているのかもしれないので念の為導通確認。黒のプローブをProMicroのVCCのピンヘッダに、赤のプローブをテープLEDの始端のVCCのランドにつけると、ブザーが....鳴らない...。もう一度配線をよくよく見てみると、ビニル線のスルーホールへのはんだ付けが甘くなっていました。

f:id:ymotongpoo:20200830171659p:plain

はんだの様子を見てはんだ付け時にビニル線の被覆の部分が当たっていてうまくハンダが乗らなかったのだと推測しました。最初に導通チェックしたときはたまたまうまく接触していたので鳴っただけでした。

ファームウェアでの関数の間違い

はんだ付けが無事に修正されると、左手側のテープLEDが点灯したのですが、右手側が引き続き点灯しません。しかしPCに接続した状態で再度右手のテープLEDのGNDとVCCの電圧を測ると4.66Vになっているし、中のWS2812B自体のDINとDOUTの部分の導通を見ても問題ないので、これはファームウェア側の問題と推測。しかしおかしな部分がどこか、勘所がわからないので見様見真似でいじっていると@mteiさんからアドバイスを頂けました。

修正点1: RGBLIGHT_SPLITやRGBLED_SPLITを使わない

これまで作ってきたキーボードでバックライト、アンダーグロー含めLED付けたのはHelixだけなんですが、Helixの場合左右で同じようにはんだ付けしていて、ファームウェア側で左右の基板にいくつずつLEDがあるかなどを制御してましたが、今回の配線ではマスター側でLED制御するようにしています。

そのためHelixを真似て書いていた RGBLIGHT_SPLITRGBLED_SPLIT があることで逆に制御ができなくなってしまいます。公式ドキュメントを確認するとちゃんと書いてありました。

RGBLIGHT_SPLIT: This option enables synchronization of the RGB Light modes between the controllers of the split keyboard. This is for keyboards that have RGB LEDs that are directly wired to the controller (that is, they are not using the "extra data" option on the TRRS cable).

RGBLED_SPLIT: This sets how many LEDs are directly connected to each controller. The first number is the left side, and the second number is the right side.

これらのオプションはTRRSケーブル経由でデータを送っていない場合でProMicroに直接LEDが配線されている場合に使う、と書いてありますね。完全にRTFM*2案件です。

修正点2: keyboard_post_init_user()内でrgblight_* 系の関数を呼ぶ

QMKのfoobarのデフォルトのkeymap.cをコピーしたら初期化系の関数が matrix_init_user() しか書かれていなかったので、雰囲気でそのままそこにLEDの初期化とアニメーションの設定を書いていました。

void matrix_init_user(void) {
    rgblight_enable_noeeprom();
    rgblight_mode_noeeprom(RGBLIGHT_MODE_RAINBOW_MOOD);
}

しかし公式ドキュメントによれば、これではなく keyboard_post_init_user を使うべきだそう。

These are the three main initialization functions, listed in the order that they're called.

  • keyboard_pre_init_* - Happens before most anything is started. Good for hardware setup that you want running very early.
  • matrix_init_* - Happens midway through the firmware's startup process. Hardware is initialized, but features may not be yet.
  • keyboard_post_init_* - Happens at the end of the firmware's startup process. This is where you'd want to put "customization" code, for the most part.

Note: For most people, the keyboard_post_init_user function is what you want to call. For instance, this is where you want to set up things for RGB Underglow.

他にもドキュメントを細かく見ると、直接は書いていないものの、ファームウェアの起動が終わった後にすべきようなことはすべて keyboard_post_init_user で行うべき、と書いてあります。LEDはまさにそうですね。したがって次のように書き換えました。

void keyboard_post_init_user(void) {
    rgblight_enable_noeeprom();
    rgblight_mode_noeeprom(RGBLIGHT_MODE_RAINBOW_MOOD);
}

void matrix_init_user(void) {

}

完成

以上の変更や修正を加えると無事にLEDが動作しました!

youtu.be

反省点

  • ビニル線をハンダ付けをする際は、被覆のビニルをしっかり剥がして余裕を持ってはんだ付けできる程度に中の線を出す
  • 導通確認は短い距離から増やして最大限まで長い距離まで複数回導通を見る。特にケーブルやジャンプしたハンダ付けに注意。
  • RTFM

おわりに

トラブルはあったものの、今回の実装でLEDに関してまた理解が深まったので、積みキーボードのもう1セットのfoobarやMinidox、また過去に作ったGherkinとLet's Splitに関してもアンダーグロー化したいと思います。

*1:相談する側から解決策を提示できる側に早く回れるようにしたいものです

*2:https://ja.wikipedia.org/wiki/RTFM