一体、何回作るんだ!?と思われてしまいそうなBad Apple!!
今回はRaspberryPi Picoで動かしてみた!(^-^)
検討から実験、実装までを書き記してみたい。
文章多めです!写真は適当w
実装の検討
今までも何度もやっているBad Apple!!を、何故またやってみようと思ったのか。
表示とSDアクセスとCPUの高負荷を同時にやろうと思うと、それなりの規模もモノを動かす必要がある。CPUと表示についてはゲームなどを動かしたら高負荷になりがちだけど、SDカードへの同時アクセスとなると、もはや動画くらいしか思いつかない。
mpegなどの表示もチャレンジしてみたいけれど、中でどんな計算をしているのかを把握していないので、正直それが重いのか軽いのか見当がつかない。
やはりここは全てを自前で書いてみたい衝動にかられる!かられた!(^^;
Picoでボトルネックとなるのはなんだろう?
M5Stackと比べて、表示も遅い、SD読み込みも速くない、CPUのクロックは半分だ!ボトルネックは全部!といいたくなるが、そうも言ってられないのでひとつずつ調べてみる事にした。
画像関連
Bad Apple!!は秒間30フレームの映像で出来ている。この転送速度に間に合うのかは、見栄えも含めて大きなファクターとなっている。
SMART Response XEなどは表示が全く間に合わず、そうそうに諦めてしまった。
実機が目の前にあるので、これは実験をしてみるのが早い。
RGB565フォーマットで320x240の画面全体を描き変えてみると、約57.5ms掛かった。
秒間17.4回くらいの画面書き換えが出来る計算だ。
うーん、これではかなーりゆっくりとした映像となってしまう(-_-;;
そういえばGFXライブラリのソースを見ている時に、モノクロキャンバスがある事に気がついた。今まで意識したことも存在も知らなかった(^^;;
単純計算でフレームバッファが1/8になるので、試してみる価値は高いだろう!
モノクロデータに変更して画面全体を描き変える速度を測ってみたところ、約130ms掛かるようになってしまった!まさかの秒間7.7回にダウン。
ライブラリのソースを確認してみたところ、データを1バイトずつ取り出してビットがONかOFFかでカラーを変えつつデータ出力している。うむむ…単純にCPU処理が増えたせいか??
今回の取り組みでは画面全体を出力する機能しか使わないのだから、SPIを直叩きして高速化をしてみる事に! さらに1色ずつデータを出力するのはもったいないので、横8ドット分のデータを一気に描画する事にしてみたところ、56.5ms、秒間17.7回の書き換えまで復活した!
しかし…これ以上がなかなか速くならない。いろいろ試してみたが、頑張った割に3%の速度アップとかそういう感じだったので、ここはもう!覚悟を決めて画像サイズを小さくする決断をした!(T^T)
画面全体は320x240ドットのサイズだけど、思い切って240x180ドットまで小さくしてみた。小さくなった分、フレームバッファのサイズも9600バイト→5400バイトとダウン。
その分、表示速度も速くなり約32msとなった!
これでなんとか秒間30回の書き換えが出来るメドがたった!(^-^)
SD読み込み関連
SDカードからの読み込みは、そのままデータ圧縮にも直結する。データを小さくすればするほどSDカードからの読み込みが速くなるからだ!
しかしあまりにも無茶な圧縮をしてしまうと、今度はデータを展開するのに時間がかかってしまい、本末転倒となる。この辺りのさじ加減がとても難しい。
SDカードからの読み込みは、前回のブログを書いた時には200KB/秒くらいが限界だったが、その後ライブラリの見直しをして375KB/秒くらいまで速度アップがなされた!
もちろんあお氏(@hd61yukimizake)の功績が大きい(^-^)
データの圧縮方式を説明すると長くなるので、可能な限り割愛しようと思う(^^;;
圧縮ツールは既存のものは使用せず、Bad Apple!!ごと独自で開発している。実を言えばこれもBad Apple!!に取り組む楽しみのひとつだ(^-^)
今回の方式を一言で言えば「ランレングス+無圧縮(マーキング方式)」とでも言うべきか…。バイト単位の圧縮で、圧縮率はそんなに良くないがデータ展開はすこぶる速い。PC-1600KのBad Apple!!でも似た方式を採用したが、おそらく今回の方が圧縮率が高い。
無圧縮で5400バイトのところ、今回の方式では一番サイズの大きなデータで2723バイト。最も小さいデータで87バイトだ。これらもろもろのデータが含まれて、全てのデータを合わせた合計サイズが約7MBとなっている。
もっとも条件の悪いタイミングであっても、データサイズは80KB/秒が上限。
SDカードからの読み込みとしてはかなり余裕があることが分かった(^-^)
動いてる速度を測ってみたが、1フレームの絵が5〜8msでデータを読めている。
CPUの負荷
PicoのCPUは133MHz動作だ。Arduino IDEではなぜか125MHzが標準となっていたため、この設定をそのまま使っている。
CPUコアが2つあるため、今回はコレを上手を使ってみる事を自分に課した(^^)
SDカードと画像(GFX)は、同じSPIを使っているためバラバラなタイミングで呼び出されると少々厄介だ。そのため、この2つの処理は1つのコアで実行させることとした。
具体的には、コア0にはSDカードの読み込みと、出来上がったフレームバッファのデータをLCDへ送る仕事を任せた。コア1はSDカードから読み込まれた圧縮データをフレームバッファに展開させている。
両方のコアを無駄なく動かすために、フレームバッファを2つ用意した。コア0で表示処理を行っている最中に、コア1でもうひとつのフレームバッファに展開する。おそらく、一番効率よくCPUが動く手法だろう。
出来上がってみて
ひとつずつ確実に積み重ねながら作っていったが、正直ここまでうまくいくとは思っていなかった。むしろまだ速度的に余裕があるくらいだ。
フレームバッファの格納方法を変更(RGB565→Mono)した事で、CPUの負荷がどどーんと下がったのかも知れない。8ビットのデータを展開するのではなく、16バイトのデータ列としてあらかじめ作っておき、それをそのままLCDへ転送したのだが、これもキャッシュなどの兼ね合いで良い結果を生んだのかも知れない。
ここまで動くようになると、やっぱりサウンドをなんとかしたいねぇ…。
でもPicoでこれ以上の負荷は…うーん(^^;;
ではまた次回!(^-^)ノ