ついに画像表示機能が出来上がりました。
https://github.com/ikedam/m5paper-ikedamclock/releases/tag/v0.3.0
出来上がったものの詳細はこちら: イケダム in イケダム時計
ミニダム1日1絵でアップした画像をサーバーに置いて、
それをランダムで返す CGI をサーバーに置いて、定期的にアクセスして画像を表示しています。
M5Paper には SDK でオンラインの画像を表示する API があるのですが、「指定の URL の JPEG を表示する」「指定の URL の PNG を表示する」という形になっています。
イケダム時計では JPEG, PNG 混在でサイトで画像を出力するので、アクセスするまで画像が JPEG、PNG が分からず API が使用できません。
このため、これらの API が使用している TJpgDec, pngle を直接使うこととなりました。これらのライブラリはデータを読み込ませると、コールバックでピクセルの情報が返ってきます。それに対して API で提供される描画処理 (fillRect) を呼べば良いというわけです。
副産物として、SDK 標準の JPEG 画像表示の API は画像の表示サイズを任意サイズに伸縮させられなかったのですが、描画処理を自分でやるので、そこも自由にできるようになりました。
伸縮処理は単純に座標と幅を目的のサイズに単純変換して行っています。多分バイリニアと呼ばれる手法のはず。
基本的に表示する元画像は M5Paper の画面サイズよりもずっと大きいので、縮小して表示されます。
そうすると元画像の異なるピクセルが、M5Paper の画面上の同じピクセルに被ることになります。
単純に後勝ちで上書きしていっているので、縮小処理としてはかなり雑なことになります。
本当は重ね塗りされた色のマージなどが必要だと思います。
ただ見た限り、特に違和感なく表示できています。
きっと1日1絵の画像がそこまで精密でないということによる功績でしょう。
画像データはインターネットからダウンロードしつつ、適宜ライブラリに流し込んで描画処理を行うという形になっています。
つまり一度全部読み込んだ後、ライブラリにわたすという作りにはなっていません。
本当は一度全部読み込む方式にしたのですが、メモリが足りなくてクラッシュしました。
画像ファイルが 1MB あるのに対して、eps32 のメモリは 520 KB とのことです。
これはとても足りないですね。
TJpgDec, pngle は組み込み用に設計されているので、画像データがすべて同時にメモリに置かなくてもストリームで処理できるような設計になっているようです。
※最初は WiFi の接続の通知があったら、その通知のコールバック内で画像を読み込もうとしたのですが、さらにもっと手前の段階でクラッシュしました。
コールバック類は別スレッドで呼ばれて、スタック領域が小さいみたいです。
コールバックでは接続状態の更新のみ行い、メインループで接続状態の検知を持って画像の描画を行うようにしました。
その後調べたところ、 PSRAM という仕組みがあって、ビルドの設定を適切に行えば外付けのメモリを使えるみたいです。
M5Paper には 8MB くらい積まれているらしい。
platformio.ini の build_flags で -DBOARD_HAS_PSRAM と -mfix-esp32-psram-cache-issue を指定すればいいみたい。
試していなけれど。
なおダウンロードした画像の展開処理には 40 秒くらいかかっています。
「毎分表示する時間を更新する」という時計の役目から考えると結構ギリです。