🍻

tinygo + koebitenを自作したGopherくん基板で動かしてみる

2024/10/06に公開

はじめに

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のシリーズはマイコンが変わっても、サイズとピン配置は同じなので便利ですね。

さいごに自分が改造したプログラムは以下にあります。

https://github.com/sat0ken/koebiten/tree/rp2040

おわりに

TinyGo Keeb Tour 2024と称して全国でzero-kb02を利用してはんだ付けとtinygoを1日楽しめるワークショップイベントを開催しています。(僕も微力ながらお手伝い参加してます🙇‍♂️)
既に応募は締め切っていますが、今月は仙台と福岡で行います。

https://sendaigo.connpass.com/event/327533/
https://github.com/sago35/tinygo_keeb_workshop_2024

今後も各地でイベント検討中とのことですので、お近くで開催する場合は奮ってご参加ください。

Discussion