tinygo + koebitenを自作したGopherくん基板で動かしてみる
はじめに
koebiten はもともと ebiten というGoでゲームを作るためのライブラリを tinygo を利用してマイコン上で動くようにsago35さんが移植したものです。
koebiten自体は現在sago35さんが設計されたキーボード基板(zero-kb02)で動くようになっていますが、これを改造して自分で作成しているGopherくん基板で動かしてみました。
koebitenの改造
sago35さんが設計された zero-kb02 と僕のGopherくん基板ではHW構成や回路が異なります。
まず zero-kb02 では rp2040-zero というマイコンを利用していますが、Gopherくん基板は seeduino xiao を利用しています。
またzero-kb02はキースイッチやエンコーダが付いていて回路もマトリックス配線を利用してキーの押下状態を読み取りますが、僕のGopherくん基板はスイッチ6つをGPIO6本で読み取る単純な方式です。
zero-kb02の回路図
Gopherくん基板の回路図、とても単純
ひとまずリポジトリをforkして手元にclone, ソースを眺めて改造箇所は以下の2つだとわかりました。
- inpututil.go
- machine.go
inpututil.go
では自分の基板のスイッチ数に合わせて不要なものを消して調整します。
キースイッチとロータリエンコーダやJoyスティックなどzero-kb02用の定数は消して、KeyLeft
からにします。
const (
KeyMax = 6
)
const (
KeyLeft = iota
KeyRight
KeyUp
KeyDown
KeyA
KeyB
)
machine.go
では keyGpioUpdate
関数だけ動かせばよさそうと理解したので init
関数内の自分の基板にない不要な処理を消します。
OLED液晶用のI2Cとタクトスイッチに接続しているGPIOピンは自分の基板に合わせる形に直します。
func init() {
i2c := machine.I2C0
i2c.Configure(machine.I2CConfig{
Frequency: 2_800_000,
// rp2040
//SDA: machine.GPIO0,
//SCL: machine.GPIO1,
// xiao-samd21 or xiao-rp2040
SDA: machine.D4,
SCL: machine.D5,
})
d := ssd1306.NewI2C(i2c)
d.Configure(ssd1306.Config{
Address: 0x3C,
Width: 128,
Height: 64,
})
d.SetRotation(drivers.Rotation180)
d.ClearDisplay()
display = &d
// rp2040
//gpioPins = []machine.Pin{
// machine.GPIO4, // up
// machine.GPIO5, // left
// machine.GPIO6, // down
// machine.GPIO7, // right
// machine.GPIO27, // A
// machine.GPIO28, // B
//}
// xiao-samd21 or xiao-rp2040
gpioPins = []machine.Pin{
machine.D10, // up
machine.D9, // left
machine.D8, // down
machine.D7, // right
machine.D1, // A
machine.D2, // B
}
for _, p := range gpioPins {
p.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
}
state = make([]State, len(gpioPins))
cycle = make([]int, len(gpioPins))
duration = make([]int, len(gpioPins))
}
func keyUpdate() {
keyGpioUpdate()
}
実行
改造が済んだらレポジトリにあるサンプルプログラムを書き込んでみます。
blocks
はその名の通りテトリスゲームですが、書き込む前にblocks.go
でconst定義し直した自分のキーに変更しておきます。
$ git diff games/blocks/blocks/blocks.go
diff --git a/games/blocks/blocks/blocks.go b/games/blocks/blocks/blocks.go
index ab02bed..ea14293 100644
--- a/games/blocks/blocks/blocks.go
+++ b/games/blocks/blocks/blocks.go
@@ -300,7 +300,7 @@ func (g *Game) Update() error {
}
// Move down faster
- if koebiten.IsKeyJustPressed(koebiten.KeyRight) || koebiten.IsKeyJustPressed(koebiten.Key9) {
+ if koebiten.IsKeyJustPressed(koebiten.KeyRight) {
for g.isValidPosition(g.tetromino.x, g.tetromino.y+1, g.currentShape()) {
g.tetromino.y++
}
@@ -320,9 +320,9 @@ func (g *Game) Update() error {
}
// Rotate the block
- if koebiten.IsKeyJustPressed(koebiten.Key4) || koebiten.IsKeyJustPressed(koebiten.KeyRotaryRight) {
+ if koebiten.IsKeyJustPressed(koebiten.KeyA) {
g.rotateTetromino(true)
- } else if koebiten.IsKeyJustPressed(koebiten.Key8) || koebiten.IsKeyJustPressed(koebiten.KeyRotaryLeft) {
+ } else if koebiten.IsKeyJustPressed(koebiten.KeyB) {
g.rotateTetromino(false)
}
return nil
修正したらビルドして書き込みます。
$ cd games/blocks/
$ tinygo build -target xiao
$ tinygo build -target xiao -port /dev/ttyACM0
プログラムが正常に書き込まれると、スイッチをどれか押すとテトリスが開始されます。
次に flappygopher
というGopherがジャンプするゲームをビルドしようとしましたが、画像データ分でしょうか?メモリ不足でxiaoではビルドできませんでした。
$ tinygo build -target xiao
program uses too much static RAM on this chip (RAM overflowed by 13188 bytes)
zero-kb02で使っているrp2040と同じ、xiao-rp2040が手元にあったので、これを付けて target を変えてビルド、書き込むとプログラムが動きました。
seeduinoのシリーズはマイコンが変わっても、サイズとピン配置は同じなので便利ですね。
さいごに自分が改造したプログラムは以下にあります。
おわりに
TinyGo Keeb Tour 2024と称して全国でzero-kb02を利用してはんだ付けとtinygoを1日楽しめるワークショップイベントを開催しています。(僕も微力ながらお手伝い参加してます🙇♂️)
既に応募は締め切っていますが、今月は仙台と福岡で行います。
今後も各地でイベント検討中とのことですので、お近くで開催する場合は奮ってご参加ください。
Discussion