倍マトリクスかつ左右分割なキーボードのファームウェア書き方メモ

倍マトリクスかつ左右分割なキーボードのファームウェアをQMK Firmwareで書きました。
なんとなく理解はしたものの時間が経つと忘れてしまいそうなので、記事にまとめておきます。


目次


0. おことわり

私が試行錯誤を経てたどり着いた結果をまとめたものです。そのため、必ずしも正しい情報であるとは限りません。
「通常マトリクスのキーボードについて、ファームウェアをQMK Firmwareで書いた経験がある」ということを前提とした書き方になっていると思います。


1. 環境

以下の環境でファームウェアが作成できたことを確認しています。

  • QMK Firmware v0.23.2

なお、記事公開時点ではもっと新しいバージョンがあり、そちらは色々と違いがあるようです(info.jsonよりkeyboard.jsonを使う?など)。
info.jsonを修正している箇所は、keyboard.jsonに読み替えたほうがいいのかもしれません。
※未検証です


2. 対象キーボードの回路

倍マトリクスなので、Col0からCol2がダイオードの方向を変えて二重に使われています。
この基板を左右両方で使用します。


3. info.jsonの修正

qmk new-keyboard で生成されたinfo.jsonを修正します。


3-1. 倍マトリクスと関係なく修正が必要な箇所

ここは倍マトリクスと関係なく修正が必要なところです。
わかる方にはわかりきっている内容かと思います。

3-1-1. keyboard_name

"keyboard_name"を適宜変更します。

1
"keyboard_name": "alg0002/teihai24gx2",	 ➡️ "Teihai24Gx2",	// 例

3-1-2. usb

"device_version", "pid", "vid"を適宜変更します。

1
2
3
4
// 例
"device_version": "1.0.0", ➡️ "0.1.0", // 例
"pid": "0x0000", ➡️ "0xXXXX", // 例
"vid": "0xFEED" ➡️ "0xXXXX" // 例

3-1-3. split

分割キーボードなので、"split"を追加します。

1
2
3
4
"split": {
"enabled": true,
"soft_serial_pin": "GP1"
},

3-1-4. layoutの名称

(これは必須ではないです)
後々の混乱を避けるため、レイアウトの名称を変更しておきます。

1
2
3
"layouts": {
"LAYOUT_split_3x6_3": { ➡️ "LAYOUT": {
"layout": [

3-2. 倍マトリクスのための修正が必要な箇所

3-2-1. matrix_pins

"cols""rows"に同じGPIOを指定します。
ただし、"cols"には列のGPIOを先に、"rows"には行のGPIOを先に書きます。

1
2
3
4
"matrix_pins": {
"cols": ["C2", "C2", (略), "C2"], ➡️ ["GP12", "GP13", "GP14", "GP9", "GP8", "GP11", "GP10"],
"rows": ["D1", "D1", "D1", "D1"] ➡️ ["GP9", "GP8", "GP11", "GP10", "GP12", "GP13", "GP14"]
},

3-2-2. layout

さて、ここからがキモです。

まず、各GPIOのインデックス(ゼロから始まる順序番号)を整理します。
そのために、先ほど修正した"matrix"の記述を参照します。

1
2
3
//           0       1       2             3       4        5       6
"cols": ["GP12", "GP13", "GP14", "GP9", "GP8", "GP11", "GP10"],
// 列 列 列 行 行 行 行

"cols"がどうなっているか確認します。
列用のGPIOは"GP12", "GP13", "GP14"です。
これらのcolsにおけるインデックスは、それぞれ0,1,2です。
行用のGPIOは"GP9", "GP8", "GP11", "GP10"です。
これらのcolsにおけるインデックスは、それぞれ3,4,5,6です。

1
2
3
//          0       1        2       3              4       5       6
"rows": ["GP9", "GP8", "GP11", "GP10", "GP12", "GP13", "GP14"]
// 行 行 行 行 列 列 列

"rows"がどうなっているか確認します。
列用のGPIOは"GP12", "GP13", "GP14"です。
これらのrowsにおけるインデックスはそれぞれ4,5,6です。
行用のGPIOは"GP9", "GP8", "GP11", "GP10"です。
これらのrowsにおけるインデックスはそれぞれ0,1,2,3です。

このインデックスを踏まえて"matrix"を記述します。

1
2
3
4
"layouts": {
"LAYOUT": {
"layout": [
{ "matrix": [ 0, 0], "x": 0, "y": 0 },

"layout"の1行目は、"x": 0, "y": 0 なので左手側1行目1列目のキーです。
回路図によれば、ここは列がGP12・行がGP9につながっています。
"matrix"の内容はこのGPIOをcols,rowsの順に記述します。
colsにおけるGP12のインデックスは0、rowsにおけるGP9のインデックスは0、よって"matrix"の内容は [ 0, 0] となります。

"layout"の2行目と3行目、つまり1行目の2列目と3列目のキーも同様に考えます。
結果、"layout"の1~3行目は…

1
2
3
{ "matrix": [ 0, 0], "x":  0, "y": 0 },
{ "matrix": [ 0, 1], "x": 1, "y": 0 },
{ "matrix": [ 0, 2], "x": 2, "y": 0 },

こうなります。

続いて"layout"の4行目、これは左手側1行目4列目のキーです。
回路図によれば、ここは列がGP12・行がGP9につながっています。
ただし4~6列目はダイオードが逆方向に繋がれていますので、列と行を逆にして考えます。
つまり、列がGP9・行がGP12につながっている、とみなします。
そしてダイオードが逆であることから、"matrix"の内容はこのGPIOをrows,colsの順に記述します。
rowsにおけるGP12のインデックスは4、colsにおけるGP9のインデックスは3、よって内容は [ 4, 3] となります。

"layout"の5行目と6行目、つまり1行目の5列目と6列目のキーも同様に考えます。
結果、"layout"の4~6行目は…

1
2
3
{ "matrix": [ 4, 3], "x":  3, "y": 0 },
{ "matrix": [ 5, 3], "x": 4, "y": 0 },
{ "matrix": [ 6, 3], "x": 5, "y": 0 },

こうなります。

続いて、”layout”の7~12行目です。
これらは右手側1行目の1~6列目のキーです。
右手なので、"matrix"の内容は左手のものを少し修正するだけで済みます。
"matrix"の1番目の値を、rowsの要素数(つまり7)だけ増やしてやればよいです。

そうすると、こんな感じになります。
(”x”が6ではなく7から始まっているのは、Remapなどでの表示時に左右の間を1列あけて表示したいからです)

1
2
3
4
5
6
{ "matrix": [ 7, 0], "x":  7, "y": 0 },
{ "matrix": [ 7, 1], "x": 8, "y": 0 },
{ "matrix": [ 7, 2], "x": 9, "y": 0 },
{ "matrix": [11, 3], "x": 10, "y": 0 },
{ "matrix": [12, 3], "x": 11, "y": 0 },
{ "matrix": [13, 3], "x": 12, "y": 0 },


4. その他のファイルの変更

4-1. rules.mk

4-1-1. SERIAL_DRIVERの追加

分割キーボードなので?、SERIAL_DRIVERを追加します。

1
SERIAL_DRIVER = vendor

4-2. keymap.c

4-2-1. レイアウトの名称

3-1-4.でlayoutの名称を変更したので、これと同様にこちらのレイアウト名も変更します。

1
[0] = LAYOUT_split_3x6_3(	 ➡️     [0] = LAYOUT(

5. おわりに

実際にどこをどう変えたのかは、下のURLの内容を参照してください。


6. 参考情報

こちらの記事を自分用に咀嚼したのが当記事です。
記事を公開してくださったikejiさん、ありがとうございます🙇