
前回TinyGoを使って mico:bit(v1.5)のLEDに所望のパターンを光らせることができました。しかしダイナミック駆動のためにプログラムが回り続けています。光らせるだけ。これでは何もできませぬ。しかしTinyGoの御本を読んだので知っています。goroutineを使えばLED駆動関数を並行処理できるっと。
※「GoにいればGoに従え」Go関連記事の総Index
TinyGoでもコンカレント処理ができる
パソコン上の「フルサイズ」のGoは勿論、TinyGoでも goroutine というものが使えるようです。多分「コンテンポラリー」な言語処理系でありがちな「コルーチン」使った「プリエンプティブでない」並行処理じゃないかと思います。知らんけど。
最近頼り切りの以下の御本を参考に、前回のTinyGoプログラムを goroutine化してみましたぜ。
高砂様著、「TinyGoの組み込み開発」
コンカレント処理化したmain関数
折角の並行処理化なので、メインループ内で4つのパターンを5秒おきに切り替えるようにしてみました。
-
- 第1パターン、暗黒(全消灯)
- 第2パターン、バッテン
- 第3パターン、マル(ちょっと四角いケド)
- 第4パターン、全点灯
そして goroutine化したディスプレイドライバ?関数の中で3個のROW信号を次々にファイヤして5x5のディスプレイをダイナミック駆動、見掛け上はちゃんとパターンが光っているように見せようというのです。なお、ROW信号の駆動周期は前回同様 10ms にしてみました。実際 15ms にしたらちょっとチラツキが気になったからです。前回の設定、意外といい線行っていた?
main関数のファイルが以下に。
package main
import (
"time"
)
func main() {
InitLED()
var dispPattern [4]uint32
dispPattern[0] = 0x00000000
dispPattern[1] = 0x01151151
dispPattern[2] = 0x00E8C62E
dispPattern[3] = 0x01FFFFFF
var pat = 0
var row = 1
go func() {
for {
switch row {
case 1:
DispLED1(dispPattern[pat])
case 2:
DispLED2(dispPattern[pat])
case 3:
DispLED3(dispPattern[pat])
}
row++
if row > 3 {
row = 1
}
time.Sleep(time.Millisecond * 10)
}
}()
for {
pat++
if pat > 3 {
pat = 0
}
time.Sleep(time.Second * 5)
}
}
コンカレント処理対応版のLEDインタフェース関数群
main関数のファイルの「横に」同じパッケージのファイルとしておいてあるものが以下に。前回と大きく異なるのは、DispLED関数をDispLED1, 2, 3 という3つの関数に分離したことです。これは並行処理される点灯処理内で各ROWを順に呼び出すため。
ファイルが以下に。
package main
import (
"machine"
)
func InitLED() {
machine.LED_ROW_1.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_ROW_2.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_ROW_3.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_COL_1.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_COL_2.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_COL_3.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_COL_4.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_COL_5.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_COL_6.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_COL_7.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_COL_8.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_COL_9.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LED_ROW_1.Low()
machine.LED_ROW_2.Low()
machine.LED_ROW_3.Low()
}
func SetLED(arg uint32) {
if (arg & 0x0404001) != 0 {
machine.LED_COL_1.Low()
} else {
machine.LED_COL_1.High()
}
if (arg & 0x1000404) != 0 {
machine.LED_COL_2.Low()
} else {
machine.LED_COL_2.High()
}
if (arg & 0x0101010) != 0 {
machine.LED_COL_3.Low()
} else {
machine.LED_COL_3.High()
}
if (arg & 0x0080022) != 0 {
machine.LED_COL_4.Low()
} else {
machine.LED_COL_4.High()
}
if (arg & 0x0040048) != 0 {
machine.LED_COL_5.Low()
} else {
machine.LED_COL_5.High()
}
if (arg & 0x0820080) != 0 {
machine.LED_COL_6.Low()
} else {
machine.LED_COL_6.High()
}
if (arg & 0x0210100) != 0 {
machine.LED_COL_7.Low()
} else {
machine.LED_COL_7.High()
}
if (arg & 0x0008200) != 0 {
machine.LED_COL_8.Low()
} else {
machine.LED_COL_8.High()
}
if (arg & 0x0002800) != 0 {
machine.LED_COL_9.Low()
} else {
machine.LED_COL_9.High()
}
}
func DispLED1(arg uint32) {
machine.LED_ROW_1.Low()
machine.LED_ROW_2.Low()
machine.LED_ROW_3.Low()
if (arg & 0x00F8815) != 0 {
SetLED(arg & 0x00F8815)
machine.LED_ROW_1.High()
}
}
func DispLED2(arg uint32) {
machine.LED_ROW_1.Low()
machine.LED_ROW_2.Low()
machine.LED_ROW_3.Low()
if (arg & 0x0A0540A) != 0 {
SetLED(arg & 0x0A0540A)
machine.LED_ROW_2.High()
}
}
func DispLED3(arg uint32) {
machine.LED_ROW_1.Low()
machine.LED_ROW_2.Low()
machine.LED_ROW_3.Low()
if (arg & 0x15023E0) != 0 {
SetLED(arg & 0x15023E0)
machine.LED_ROW_3.High()
}
}
実機実行結果
例によって BBC micro:bit (V1.5) をUSBポートに接続し、
$ tinygo flash -target=microbit
これで4つのパターンが点灯するようになりました。
goroutine便利。
