前回に引き続き、今回もBad Apple!!の話題を書いてみる!
今回も文章多めだ!(^-^;;
前回作ったBad Apple!!は、いろいろと工夫をしたけれども、最終的には妥協をした部分もあった。
RaspberryPi PicoでBad Apple!!
— PocketGriffon (@GriffonPocket) 2021年11月29日
過去にM5Stackでだいぶ苦労したけど、データの圧縮方式と表示アプローチを変えたら、Picoでも余裕を持って表示出来た!(^_^)
Core0でSDカードの読み込みと表示、Core1で圧縮データの展開やってます!#RaspberryPiPico#BadApple pic.twitter.com/01A4B3DBfh
苦労はした、工夫もした、でも妥協もした、というのが前回。
今回は、あんま苦労しなかった、工夫もしなかった、でもフル画像で出来た!
この違いはなんだろう…(^^;;
その辺り、詳しく書いていってみようと思う。
SDカードからの読み込み速度改善
絵が240x180から320x240の大きさになるということは、すなわち画像サイズに直結するという事。圧縮しているので単純に1.7倍というわけではないが、平均して3割ほどデータが大きくなっている。
SDカードに載せたデータサイズは、前回が約7MBだったのに対し、今回は10MB弱だ。
データサイズが大きくなるということはSDカードからの読み込み速度も厳しくなる。しかし、実は前回のBad Apple!!よりもSDカードの読み込み速度が著しく向上しているのだ!
元のライブラリは200KB/秒くらいの速度だったが、それを375KB/秒に改善して挑んだのが前回のBad Apple!! 。そして今は900KB/秒くらいまで速度が上がっている!
あお氏(@hd61yukimizake)と共に、日夜ライブラリの最適化に勤しんだ結果だ(^^)
このおかげで、前回よりも読み込むデータ量が増えているにも関わらず、速度は速くなったという逆転現象が起きている!
表示速度向上のチャレンジと挫折
少し前にTwitterへ「表示をDMAで行うと速くなった」という旨の投稿をした。
RaspberryPi Picoで、DMAを使って画面更新が出来るようになった!
— PocketGriffon (@GriffonPocket) 2021年11月30日
「四角を描いてるのがDMA」じゃなくて「画面全体を更新してるのがDMA」という分かりにくい動画w
秒間40回くらい再描画出来るみたい!
よし、どんどん使えてるね、Pico(^O^)#RaspberryPiPico pic.twitter.com/Ejx80R9c9g
LovyanGFXなどでもスプライトの描画は(条件があえば)DMA転送をしていると読んだ事がある。RaspberryPi PicoでもDMA機能はあるし、チャンネルもたくさんあることから、同じように表示で使えるのではないか?と思って実験を繰り返していた。
RaspberryPi Picoで画面表示にDMAを使用する例を探してみたが、ネット上ではどうしても見つけることが出来ず、RP2040のデータシートとにらめっこをしながら独自で作り上げた(^^;
画面いっぱいを表示するのに掛かる時間は21msと、それまでの50ms以上掛かっていた状態に比べると、だいぶ速くなる事が分かった(^-^)
しかし…いざ、Bad Apple!!に組み込もうとしたら、DMAの初期化不良なのかなんなのか、画像がズレていく現状が出て悩まされた。
これはデータが送りきれていないか、逆に送りすぎてしまうと起きる現象だ。
こういうおかしな現象は、表示系のライブラリを改造してる流れで何度も見たことがある(^^; 単純にデータの転送数を間違う場合とか、SPI側のFIFOがFULLの時に書き込みをしてデータを喪失した場合も起きる!(^^;;;
SDカードからの読み込みを止めるとピタっと現象が収まることから、同じSPIを利用した周辺機器との関連である事は間違いなさそうなのだが、今回はどうしても原因を突き止める事が出来なかった。
DMAに関しては完全玉砕だ!(TOT)
別アプローチで表示速度向上
これは…正直やって良い事はどうかわからないので詳しくは書けないのだけれども、一言で言えば「SPIの速度をあげた」。
このBad Apple!!のプログラムではgfx->drawなんとか系の関数は使わず、独自でSPI転送をして描画速度を上げる事をしている。
Picoの表示ライブラリ内では「SPIのFIFOに空きが出来るまで待つ」をしてからデータを書き込んでいる。これを「SPIのFIFOが全て空になった」状態から、何個のデータまでを突っ込んでも大丈夫なんだろう…とか、FIFOサイズを意識したプログラムに変更してみたりしてた。
表示の汎用ライブラリを作ってるワケではないのでやりたい放題だ(^^;;
そんな極端な実験をしている最中に、DMA側の設定をOFFにし忘れてSPI速度を上げたまま動かしてしまった(つまり間違いから発覚した)ところ、描画速度が上がる事に気がついた。
実は以前にも同じようなテストはしているのだが、その時は思ったような改善が見られなかったため、ハードへの負担も考えて禁忌としていた。
しかし…今回分かったことだが、これをするとDMA並の速度まで上がるのだ。画面全体を更新して21ms、ほぼ同じだ。うーん、DMAがうまく動かない現状でこれは捨てがたい……。
ハード側への負担を理解した上で、自分の元でのみ使う事にした(^^)
圧縮データの扱い
前回は圧縮されたデータを、モノクロデータ(1バイト8ドット)のデータとして展開をし、これを表示時にRGB565に展開しながらSPIへ送り込んでいた。
今回はDMAを使う意思があったため、全体をRGB565に展開したフレームバッファを用意する必要性が出てきていた。データの展開速度はどうあれ、320x240で150KBもあるメモリへの展開、時間がかかるだろうなぁ…と予測していた。
それが……実際にはものすごく軽かった!想像していたよりも1/5くらいの時間で終わってる!この手の処理で想定を外すことは滅多にないんだけど、なんか想像よりも速いぞPico!
そう、なんとなくだけどPicoは良い方向に期待が外れる事が多い。なんでこんな速いんだろう…ベアメタルがゆえにいろんなサービスが走ってないからだろうか…。
結局、データの展開とRGB565への変換処理が3.5msで処理が終わる事が分かった。
コアを分ける意味が…
SDカードからの読み込みに5ms以下
データ展開に3.5ms
フレームバッファを表示するのに21ms…。
前回はSDカードの読み込みと表示をコア0、データ展開をコア1に処理させていたのだけど、今は全ての処理時間を合わせても1/30秒(33.33ms)以下で終わってしまう事が判明。
むしろ時間を待つ処理をいれないとイケナイ!(^^;;
コアを2つに分けたとしても単純に処理量が2倍にならないというのは理解されてる事と思うけど、前回のBad Apple!!でもお互いのコアが終わるのを待つ処理がいくつか入ってた。SDカードを読み終わるまで展開処理に移らない、とか(^^)
そういうコードも全部外す事になったので、結果的に1つのコアが目一杯動けるようになった気がする。とてもエレガントなコードになったね!!(自画自賛w
終わりに…
なんとなくBad Apple!!に注目してRaspberryPi Picoの最適化をしてきたけど、びっくりするのはPicoの潜在能力の高さ!
133MHz(Arduino IDE上では125MHzでビルド)でここまで動くとは!
ちょっと皆さん、Pico触りましょう、Pico!(^-^)/
まだまだ余裕がある状態なので、M5Stackの時に諦めたグレイスケールなBadも挑戦出来ちゃうほどだなぁ…とか思っちゃう(^^;
ぎりぎり動いてたFM-7も、きっと余裕で動く気がしてきた(^^;;
うーん、これだけ使っても夢が広がってくる…Picoの限界を見てみたいね!
ではまた次回!(^-^)ノ