この記事では TinyGo + Wio Terminal を用いて sago35/tinygo-keyboard を使った自作キーボードを作るための情報をまとめます。
sago35/tinygo-keyboard は TinyGo で自作キーボードを作るための package です。レイヤー対応や各種スイッチ読み取り方式への対応、 Vial 対応等が含まれます。
前提知識
以下の書籍 「基礎から学ぶ TinyGoの組込み開発」を読んでおくとスムーズです。
※電子書籍は 2024/01/22 まで 40% オフで購入することができます
最低限の情報は以下にも記載していますので、適宜参照してください。
あるいは Go Conference mini 2023 Winter IN KYOTO でも自作キーボードについてトークしています。sago35/tinygo-keyboard にはほとんど触れていませんが、ライブコーディングもしているので基礎知識として見ておくと良いかもしれません。
Go / TinyGo のプロジェクトを作成する
まずは go mod init
を実行して、 go.mod
というファイルを作成します。これは Go でも TinyGo でも共通のプロジェクト開始のための手順です。
$ mkdir mykeyboard
$ cd mykeyboard
$ go mod init main
go: creating new go.mod: module main
$ ls
go.mod
go.mod
を作ったあとは、このあと必要となる sago35/tinygo-keyboard を go get しておきましょう。なお、Version 指定なしで go get するとその時点の最新版が取り込まれるため、 Version 表記などは異なる場合があります。
$ go get github.com/sago35/tinygo-keyboard
go: added github.com/bgould/tinygo-rotary-encoder v0.0.0-20231106003644-94bb14d88946
go: added github.com/sago35/tinygo-keyboard v0.0.0-20231226123717-7246a4ef8c39
go: added tinygo.org/x/drivers v0.25.0
ソースコードの作成
次に sago35/tinygo-keyboard を import してキーボードを作り始めます。
以下のあたりのコードをコピーして雛形にするのも良いでしょう。
- https://github.com/sago35/tinygo-keyboard/tree/main/tutorial
- https://github.com/sago35/tinygo-keyboard/tree/main/targets
ここでは以下のソースコードを作成します。完全なソースコードは以下のリポジトリの basic branch にあります。
package main
import (
"context"
"machine"
keyboard "github.com/sago35/tinygo-keyboard"
"github.com/sago35/tinygo-keyboard/keycodes/jp"
)
func main() {
d := keyboard.New()
gpioPins := []machine.Pin{
machine.WIO_KEY_A,
machine.WIO_KEY_B,
machine.WIO_KEY_C,
}
for c := range gpioPins {
gpioPins[c].Configure(machine.PinConfig{Mode: machine.PinInput})
}
d.AddGpioKeyboard(gpioPins, [][]keyboard.Keycode{
{
// layer 0
jp.KeyA,
jp.KeyB,
jp.KeyMod1,
},
{
// layer 1
jp.Key1,
jp.KeyBackspace,
jp.KeyMod1,
},
})
d.Loop(context.Background())
}
Flash
Wio Terminal に書き込みます。
$ tinygo flash --target wioterminal --size short .
code data bss | flash ram
39076 684 9316 | 39760 10000
動作確認
書き込みが終わると、 Wio Terminal の上部のボタンがそれぞれ a
、b
、レイヤー 1
として動作します。レイヤー 1
を押している間は 1
、 BackSpace
として動作します。
ソースコードの解説
sago35/tinygo-keyboard の基本的な使い方は keyboard.New()
して、 AddXXXXKeyboard()
して Loop()
をコール、という流れです。Wio Terminal のボタンはすべて GPIO ピンに直接つながっているので AddGpioKeyboard()
を使います。
d := keyboard.New()
d.AddGpioKeyboard(gpioPins, [][]keyboard.Keycode{
{
// layer 0
jp.KeyA,
jp.KeyB,
jp.KeyMod1,
},
{
// layer 1
jp.Key1,
jp.KeyBackspace,
jp.KeyMod1,
},
})
d.Loop(context.Background())
上記で jp.XXX
と書かれている部分は、キー設定になります。
jp.KeyMod1
は特殊なキーでレイヤーを使うためのものです。レイヤー関連のキーは以下の通りです。なお、 KeyModX
については、レイヤー移動先にも同じキーを設定する必要があります。
sago35/tinygo-keyboard では、現時点でレイヤー 0 から 5 までの合計 6 レイヤーを使うことができます。
キー名 | 動作 |
---|---|
KeyMod0 〜 KeyMod5 | 押してる間だけレイヤー 0 〜 5 に切り替える |
KeyTo0 〜 KeyTo5 | レイヤー 0 〜 5 に切り替える (離しても戻らない) |
sago35/tinygo-keyboard が対応している入力方式
sago35/tinygo-keyboard では、以下の入力方式に対応しています。対応形式は必要に応じて追加することができます。一般的な呼び名と異なっている可能性がありますので、詳細は回路図を参考にしてください。
DuplexMatrixKeyboard
倍マトリクスとか Duplex Matrix とか Japanese Duplex Matrix とか言われるものです。普通のマトリクスに対して、 2 倍の入力を扱うことができます。
AddDuplexMatrixKeyboard(colPins, rowPins []machine.Pin, keys [][]Keycode)
以下の回路が対象です。 targets/sgkb/left-0.3.0 などで使用されています。
以下の 「倍マトリクス」 の説明を読むと良いです。
GpioKeyboard
GPIO に直接接続されたピンを用いたキーボードです。opt によりボタン押下時の極性を設定することができます。
AddGpioKeyboard(pins []machine.Pin, keys [][]Keycode, opt ...Option)
MatrixKeyboard
おそらく自作キーボードで一番使われている方式だと思います。行と列のピンを作ることにより、少ないピン数で多くの入力を扱うことができます。opt によりダイオードの向きを設定することができます。
AddMatrixKeyboard(colPins, rowPins []machine.Pin, keys [][]Keycode, opt ...Option)
以下の回路が対象です。 targets/sgkey などで使用されています。
以下の 「通常のマトリクス」 の説明を読むと良いです。
RotaryKeyboard
ロータリーエンコーダーを扱うことができます。
AddRotaryKeyboard(rotA, rotB machine.Pin, keys [][]Keycode)
以下の回路が対象です。 targets/xiao-kb01 や macropad-rp2040 で使用されています。
ShifterKeyboard
シフトレジスターを扱うことができます。 pybadge / gobadge に使われている 74165TSSOP (74HC165 互換?) のために作成されました。 opt によりボタン押下時の極性を設定することができます。
AddShifterKeyboard(shifterDevice shifter.Device, keys [][]Keycode, opt ...Option)
SquaredMatrixKeyboard
改良二乗マトリクスを扱うことができます。非常にピン効率が良く、例えば 5 ピンで 5 x 4 = 20 ピンの入力を扱うことができます。
AddSquaredMatrixKeyboard(pins []machine.Pin, keys [][]Keycode)
以下の回路が対象です。 targets/sgh60 や targets/xiao-kb01 などで使用されています。
以下の 「改良二乗マトリクス」 の説明を読むと良いです。
UartKeyboard
UART 経由で送られてきたキー情報を扱うことができます。主に分割キーボードのために作成されました。
AddUartKeyboard(size int, uart *machine.UART, keys [][]Keycode)
targets/sgkb などで使用されています。
Vial 対応を行う
Vial は Web ブラウザ等からキーマップを設定するためのプロジェクトです。 sago35/tinygo-keyboard から使うためには keyboard.KeyboardDef []byte
を設定する必要があります。自分でマニュアル作成することもできますが、基本的には vial.json
を用意して、 gen-def
により def.go
を作成すると良いです。この辺りは後述します。
正しく設定できていると以下の画面のように Web ブラウザから設定を行うことができます。
Vial は以下です。
vial.json を作成する
vial.json の作り方の詳細は以下を参照してください。とはいえ、 sago35/tinygo-keyboard で使用する項目はごく一部であるため、既存の vial.json を参考にすると良いです。
既存の vial.json は targets/ 以下にあります。
layouts.keymap については KLE / Keyboard Layout Editor の </>Raw data
から JSON をコピーすることで作成できます。
今回は Wio Terminal の上部の 3 ボタンのみを使用するため、以下のようになります。 sago35/tinygo-keyboard に必要な最低限の設定は以下の通りです。なお、 name / vendorId / productId は何を設定しても良いです。
{
"name": "tinygo-wioterminal",
"vendorId": "0x2886",
"productId": "0x802D",
"matrix": {"rows": 1, "cols": 3},
"layouts": {
"keymap": [
["0,2","0,1","0,0"]
]
}
}
上記を vial.json
という名前で保存したら gen-def
を実行します。
$ ls
go.mod go.sum main.go vial.json
# gen-def をインストール
# `go env GOPATH` で表示される場所にインストールされます
$ go install github.com/sago35/tinygo-keyboard/cmd/gen-def@latest
# vial.json から def.go を生成する
$ gen-def vial.json
$ ls
def.go go.mod go.sum main.go vial.json
自動生成された def.go
は以下のようになっています。ここで定義される loadKeyboardDef()
をコールすることで Vial 対応が完了します。
package main
import keyboard "github.com/sago35/tinygo-keyboard"
func loadKeyboardDef() {
keyboard.KeyboardDef = []byte{
// 省略
}
}
以下のように d.Loop()
をコールするまでに実行してください。
loadKeyboardDef()
d.Loop(context.Background())
ソースコードの完全な例は、以下の main.go
にあります。
うまくソースコードを作ることが出来たら、 Vial にアクセスしてみてください。
※ブラウザは Chrome もしくは Edge を使用してください
まとめ
TinyGo + Wio Terminal を用いて sago35/tinygo-keyboard を使った自作キーボードを作るための情報をまとめました。不明点がある場合などは、以下のリポジトリの Issue に書いていただくか、 Twitter/X からメンションしてください。サポートしますのでお気軽にどうぞ。