QMK 0.19.2で改良二乗マトリクスのキーボードファームウェアを作っていく話
はじめに
この記事はキーボード #1 Advent Calendar 2022 17日目の記事です。
16日はyfukuさん『軸の秤』でChocスイッチ17種のフォースカーブを測定してみた – Daily Craft Keyboardでした。
ChocはRed以外ほぼ使ったことないで、Sunset Tactileが気になりますが付けるキーボードがないんですよね。
毎年恒例のこの時期がやってきましたね。
去年は、KEEB_PDのAdvent Calendarに参加しましたがネタがなくて、yohewiさんのM0ii0+十を光らせました。
光らぬなら光らしてしまえM0ii0+十
— ガチハム (@gachiham) 2021年11月28日
Keyboard:M0ii0+十
Switch: ghost (Stock)
Keycap: MDA Big Bone#KEEB_PD #KEEB_PD_R72 pic.twitter.com/lczBdU63Em
今年も、とりあえず参加してからネタを考えるスタイルにしたところ、なんと現在12/10で何もネタがないです。 特に思いつくものもなく、今から新しいものを作成するにしても時間が足りないので、以前Seeed Fusion DIY XIAO Mechanical Keyboard Contestで作成したGL516互換PCBのXR63GLを最新のQMK(0.19.2)に対応させていこうと思います。
2022年12月29日追記
この記事を書いてからQMKを確認したところ、0.19.4にバージョンが上がっていました。
また、プルリクエストを出して、マージされたバージョンは0.19.5でした。
改良二乗マトリクスとは
まず、二乗マトリクスですが、IKeJIさんが2019年頃に考案されたキーマトリクスです。
呼び方が複数あるので、いつも混乱するのですが、私は二乗マトリクスと呼んでいます。
(二乗マトリクス、総当たりマトリクス、square matrix、round-robin matrixなど)
標準的なキーマトリクスよりもダイオードを増やして、少ないGPIOでより多くのキーを使用出来るようになっています。
二乗マトリクスのほかにも倍マトリクス( Japanese duplex-matrix)などもあります。
ただ、使ったダイオードの仕様や使用環境などが影響して、押していないキーが入力されてしまうゴーストという現象が発生するデメリットも存在します。
改良二乗マトリクスは二乗マトリクスよりゴーストの発生率を抑えるように考案されたマトリクス方式となります。
たぶん私が説明するより、IKeJIさんの記事を見たほうが理解できると思うのでリンクを貼っておきます。
2019年 IKeJIさんのマトリクス記事
blog.ikejima.org
2022年 IKeJIさんマトリクス記事
blog.ikejima.org
KBD.newsで取り上げられた二乗マトリクスの記事
kbd.news
KBD.newsで取り上げられた改良二乗マトリクスの記事
kbd.news
キーボードについて
seeedのコンテストで作成したものを使用するため、既にPCBは手元にあります。 コンテストに参加した時の記事は細かく書いてないため、ちょっと説明しようと思います。
レイアウト
よくある65%はバックスペースやエンターの横にもキーがありますが、よく誤打するので私には不要かなと思っています。また、右シフトキーとアローキーも離れていないと誤打するので、右シフトキーを1.75Uから1.25Uに変更します。
回路図
改良二乗マトリクスでGPIOを9本使用すると9*(9-1)=72キーとなります。 以下が72キーの状態の回路図となります。
ここから不要なキーを消していきます。
まずは、PCB上にどういう配置するかを考えます。
余談ですが、コンテストの製造代のクーポン発行の締め切りを知らなくて、慌てて作るはめになりました。
結果、以下のようにしました。
次からデバッグしながら記事書くのでキーボード変えます。
ここまでは以下のキーボードで書きました。
Keyboard: GL516+XR63GL
Switch: DUROCK Full POM(Stock)
Keycap: IFK OG
QMKについて
12/11現在の最新バージョンは、0.19.2です。
QMKの破壊的変更で、内部で持っているキーコードが変更になったようです。
これにより、VIAとREMAPとの連携が取れなくなり、キーによっては動作がおかしくなっているようです。
現状、VIAまたはREMAPでキーマップを変更するなら0.19.2を使用しないほうがいいと思います。
QMKの変更点ですが、多すぎて全部の説明は出来ないのでリンクを貼っておきます。 docs.qmk.fm
新しいキーボード
QMK CLIでコマンドを実行するだけです。
以下のコマンドを実行すると対話式で実行されます。
qmk new-keyboard
まずは、キーボード名を聞かれます。
Ψ Generating a new QMK keyboard directory Name Your Keyboard Project For more infomation, see: https://docs.qmk.fm/#/hardware_keyboard_guidelines?id=naming-your-keyboardproject Keyboard Name?
今回はgl516フォルダの中にXR63GLのファームウェアを置きたいので、以下のように入力しエンターキーを押します。この時、キーボード名は必ず小文字を使用してください。
Keyboard Name? gl516/xr63gl
すると、以下のように聞かれるので、Github上の名前を入力してください。
表示されている名前でいいなら、何も入力せずエンターキーを押してください。
Attribution Used for maintainer, copyright, etc Your GitHub Username? [gachiham]
以下のようにリアルネーム聞かれますが、私はそのままエンターキーを押します。
More Attribution Used for maintainer, copyright, etc Your Real Name? [gachiham]
次に新しいキーボードのレイアウトを聞かれるので、一番近いレイアウトの番号を入力してください。
XR63GLは63キーなので一番近い6. 64_ansi
を選びます。
Pick Base Layout As a starting point, one of the common layouts can be used to bootstrap the process Default Layout? 1. 60_abnt2 2. 60_ansi 3. 60_ansi_arrow 4. 60_hhkb 5. 60_iso 6. 64_ansi 7. 64_iso 8. 65_ansi 9. 65_iso : : 48. tkl_ansi 49. tkl_iso 50. tkl_nofrow_ansi 51. tkl_nofrow_iso 52. none of the above Please enter your choice: [52]
6を入力してエンターキーを押します。
Please enter your choice: [52] 6
次に使用するマイコンの種類を選びます。
デフォルトでは25. atmega32u4
になっています。
PCBに直接atmega32u4を実装している場合は、何も入力せずにエンターキーを押してください。
ProMicroを使用する場合、10. promicro
を選択するために10
を入力してエンターキーを押してください。
What Powers Your Project For more infomation, see: https://docs.qmk.fm/#/compatible_microcontrollers MCU? 1. bit_c_pro 2. blackpill_f401 3. blackpill_f411 : 9. kb2040 10. promicro 11. promicro_rp2040 : : 32. MKL26Z64 33. RP2040 34. STM32F042 : 51. WB32F3G71 52. WB32FQ95 Please enter your choice: [25]
私は、今回XIAO RP2040を使用するため、33. RP2040
を選びます。
Please enter your choice: [25] 33
コマンドが終了すると以下の文字列が表示されます。
Ψ Created a new keyboard called gl516/xr63gl. Ψ To start working on things, `cd` into keyboards/gl516/xr63gl, Ψ or open the directory in your preferred text editor. Ψ And build with qmk compile -kb gl516/xr63gl -km default.
するとqmk_firmware\keyboards\gl516
の中に、xr63gl
というフォルダが作成されており、その中に、最低限のファイルが生成されています。
defaultのキーマップでコンパイルしたい場合は、コマンド終了時に表示されている通りqmk compile -kb gl516/xr63gl -km default
を実行します。
ファイル編集
12/12現在だとRP2040を使用している場合、new-keyboardコマンド実行直後にコンパイル出来ません。
理由は、info.jsonのmatrix_pinsの定義が RP2040の記述と異なるからです。
RP2040でのピンの記述はGP0~GP29です。
XIAO RP2040で使用出来るピン名は赤枠で囲った番号の頭文字にGを付けたものです。
info.json
ファイルを生成したままだと以下のようなマトリクスになっています。
{ "matrix_pins": { "cols": ["C2", "C2", "C2", "C2", "C2", "C2", "C2", "C2", "C2", "C2", "C2", "C2", "C2", "C2", "C2"], "rows": ["D1", "D1", "D1", "D1", "D1"] } }
XR63GLのXIAO RP2040のピンの割り当ては以下のようにしています。
改良二乗マトリクスの場合、colとrowに同じピンがくるため、どちらもPIN1~PIN9の順番で書きます。
{ "matrix_pins": { "cols": ["GP26", "GP27", "GP28", "GP29", "GP0", "GP3", "GP4", "GP2", "GP1"], "rows": ["GP26", "GP27", "GP28", "GP29", "GP0", "GP3", "GP4", "GP2", "GP1"] } }
次にレイアウトですが、新しいキーボードを作成する際に64_ansi
を選択しました。
キーマップは異なりますが、レイアウトは以下のようになっています。
{ "layouts": { "LAYOUT_64_ansi": { "layout": [ { "matrix": [0, 0], "x": 0, "y": 0 }, { "matrix": [0, 1], "x": 1, "y": 0 }, { "matrix": [0, 2], "x": 2, "y": 0 }, { "matrix": [0, 3], "x": 3, "y": 0 }, { "matrix": [0, 4], "x": 4, "y": 0 }, { "matrix": [0, 5], "x": 5, "y": 0 }, { "matrix": [0, 6], "x": 6, "y": 0 }, { "matrix": [0, 7], "x": 7, "y": 0 }, { "matrix": [0, 8], "x": 8, "y": 0 }, { "matrix": [0, 9], "x": 9, "y": 0 }, { "matrix": [0, 10], "x": 10, "y": 0 }, { "matrix": [0, 11], "x": 11, "y": 0 }, { "matrix": [0, 12], "x": 12, "y": 0 }, { "matrix": [0, 13], "w": 2, "x": 13, "y": 0 }, : : ] } } }
LAYOUT_64_ansi
をLAYOUT_63_ansi
に書き換えます。
また、右下のキーのサイズや位置が異なるため書き換えます。
{ "layouts": { "LAYOUT_63_ansi": { "layout": [ { "label":"ESC", "matrix": [0, 1], "x": 0, "y": 0 }, { "label":"1!", "matrix": [0, 2], "x": 1, "y": 0 }, { "label":"2@", "matrix": [0, 3], "x": 2, "y": 0 }, { "label":"3#", "matrix": [0, 4], "x": 3, "y": 0 }, { "label":"4$", "matrix": [0, 5], "x": 4, "y": 0 }, { "label":"5%", "matrix": [0, 6], "x": 5, "y": 0 }, { "label":"6^", "matrix": [0, 7], "x": 6, "y": 0 }, { "label":"7&", "matrix": [0, 8], "x": 7, "y": 0 }, { "label":"8*", "matrix": [1, 0], "x": 8, "y": 0 }, { "label":"9(", "matrix": [1, 2], "x": 9, "y": 0 }, { "label":"0)", "matrix": [1, 3], "x": 10, "y": 0 }, { "label":"-_", "matrix": [1, 4], "x": 11, "y": 0 }, { "label":"=+", "matrix": [1, 5], "x": 12, "y": 0 }, { "label":"Backspace", "matrix": [1, 6], "w": 2, "x": 13, "y": 0 }, : : ] } } }
"matrix": [0, 0],
の部分の補足をちょっとだけしようと思います。
この部分は、以前は、keyboard_name.h
に記載していたレイアウトの定義です。
キーマトリクス上の何処を使用するかを座標で記述します。
改良二乗マトリクスの場合、[0, 0]
はダイオードを入れているだけなので、スイッチとして使用出来ません。
そのため、[0, 1]
から始まっています。
キーマトリクスの座標は以下のようになっています。
keymap.c
ここもLAYOUT_64_ansi
をLAYOUT_63_ansi
に書き換えます。
また、アローキー横のMO(1)
はXR63GLには存在しないため、消します。
[0] = LAYOUT_64_ansi( KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_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, KC_UP, MO(1), KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT ),
[0] = LAYOUT_63_ansi( KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_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, KC_UP, KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT ),
マトリクスとキーマップが完成したので、一度コンパイルしてみます。
フォルダ作成時に表示されたqmk compile -kb gl516/xr63gl -km default
を実行します。
Ψ Compiling keymap with make --jobs=1 gl516/xr63gl:default QMK Firmware 0.19.2 Making gl516/xr63gl with keymap default arm-none-eabi-gcc.exe (GCC) 10.1.0 Copyright (C) 2020 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 26812 0 26812 68bc gl516_xr63gl_default.uf2 Compiling: quantum/keymap_introspection.c [OK] : : Linking: .build/gl516_xr63gl_default.elf [OK] Creating load file for flashing: .build/gl516_xr63gl_default.hex [OK] Creating UF2 file for deployment: .build/gl516_xr63gl_default.uf2 [OK] Copying gl516_xr63gl_default.uf2 to qmk_firmware folder [OK] (Firmware size check does not yet support RP2040; skipping)
コンパイルに成功したのでqmk_firmware
のフォルダの中にgl516_xr63gl_default.uf2
というファイルが生成されています。
なお、コンパイルが通るのかを確認したかっただけなので、ファイルの修正は続きます。
Bootmagic Lite
これは、決められたマトリクスのキーを押しながら、PCなどにUSB接続するとブートローダーが起動する機能です。主にファームウェアを書き換えたいが、物理的なリセットスイッチがない時やアクセスしにくい時に使用します。
info.json
のfeatures
に"bootmagic": true
と記述されている場合に機能が有効になります。
"features": { "bootmagic": true, },
config.h
に定義しない場合は、マトリクスの[0,0]が対象になりますが改良二乗マトリクスの場合、常に押されていると判定されてしまうので、マトリクスの[0.1]に変更します。
これで、ESCを押しながら、PCに接続するとブートローダーモードで起動するようになります。
#define BOOTMAGIC_LITE_ROW 0 #define BOOTMAGIC_LITE_COLUMN 1
詳細は公式ドキュメントを参照してください。
docs.qmk.fm
RP2040_BOOTLOADER_DOUBLE_TAP_RESET
これは、RP2040専用の機能でPCB上のリセットスイッチをダブルタップするとブートローダーモードで起動します。(正直、Bootmagic LiteやQK_BOOT
キーを使用しても同じことが出来るので個人的には不要かなと思っています。)
config.h
に以下を追加します。
#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET #define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 500U #define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED_MASK 0U
これも詳細は公式ドキュメントを参照してください。
docs.qmk.fm
MATRIX_MASKED
この仕様を知らなくて、以前PCがキーボードを認識しなくてハマりました。
改良二乗マトリクスのダイオードのみの交点が、常に押しっぱなしと判断されてしまいPCが認識しません。STM32やRP2040の場合には必須のようです。
IKeJIさんのブログに記載されていました。
blog.ikejima.org
MATRIX_MASKED
を有効にするために、config.h
に以下を追加します。
#define MATRIX_MASKED
2022年12月29日追記
次にkeymap.c
に以下の定義を追加します。
レビューでkeymap.c
ではなく、<keyboard_name.c>
に定義しなさいと指摘を受けました。
たしかに、keymap.c
に定義するとキーマップ毎に同じ定義を書いておかなければならないので、新しくxr63gl.c
を作り、ここに定義します。
これで、ダイオードのみの交点は無視されるため、PCがキーボードを認識するようになります。
#include QMK_KEYBOARD_H
const matrix_row_t matrix_mask[MATRIX_ROWS] = {
0b1111111111111110,
0b1111111111111101,
0b1111111111111011,
0b1111111111110111,
0b1111111111101111,
0b1111111111011111,
0b1111111110111111,
0b1111111101111111,
0b1111111011111111,
};
いつもの通り、詳細は公式ドキュメントを参照してください。
docs.qmk.fm
デバッグ
もう一度コンパイルして、XIAO RP2040にuf2ファイルを書き込み、VIAでキーテストを行います。
全部認識したので完成です。
あとは、readme.md
やinfo.json
の情報を書き換えたり、QMKのコーディング規約通りに体裁を整えるとプルリクエストを行えると思います。
最後に
いかがでしたか?
ここまで読んだ方は、もうお気づきかと思いますが、この記事はIKeJIさんのブログとQMKの公式ドキュメントで出来ています!
有用な情報を発信してくださる先駆者の方々には感謝しています。
せっかくここまで作ったので、もうちょっと作業してQMKにプルリクを出してみようと思います。
明日はsatromiさんです。
QMK編は以下のキーボードで書きました。
Keyboard: GL516+TH63GL
Switch: Akko CS Lavender Purple(Stock)
Keycap: KAT Iron
P.S.
コマンド調べてる時に気づきましたが、qmk compile -j 0 -kb <keyboard_name>
でコンパイルの高速化出来ます。(0が最速)
docs.qmk.fm