2018年3月8日木曜日

電光掲示板

 久しぶりにLEDパネルで遊んでいます。


 制御基板はティアさんの頃のモノを流用しています。右下にちらっと写っているやつですが、そういえばこのブログでこの基板の写真って載せたたこと無いような…? ま、そのうち機会があれば。

 HUB75自体は、ライブラリ書くのも4回目くらいなので、結構スムーズに使えます。

 今回は、以前とは違い、かなりメモリを無駄遣いする構成になっています。
 以前は8bppIndexedと、それを展開するための大きなテーブルをRAMに持たせていました。その方法では、色の変更はVRAMにピクセル単位で書き込めばいい反面、パネルに転送する際に膨大なテーブルアクセスが発生するというデメリットが有りました。具体的には、96x96pxのパネルを50Hzで色深度3bitの表示を行った場合、1秒間に1.4^6回のデータ変換が必要です。データ変換はギリギリまで最適化しているので、1回の処理自体は大したことありませんが、回数が多いのでちりも積もればなんとやら、です。
 今回は、変換後のデータをRAMに展開しているため、set_pixel関数のコストがとても高いです。せめて転送時の計算コストが下がってくれれば、と思っていたのですが、実際にはかなり高負荷です。

 現在はGPIO.ODRにDMAで転送し、1回目の転送でデータを送り、2回目の転送でデータ+クロックを送り、これによりデータホールド期間を確保しています。
 が、DMAは代入しかできず、OR代入のような便利な機能はないので、あらかじめピクセルデータだけの配列から、クロックを含むデータへ変換し直す必要があります。この部分がかなり高負荷な感じです。
 この点は、例えば別のDMAでBSRRにクロックを書き込むとか、ビットバンドでODRを操作するとかすれば良いのかもしれませんが、現在はDMAをMEM2MEMでフリーランさせている状態なので、DMA間の同期が取れなくなってしまいます。
 今回の方法では、96x96pxであれば、VRAMは54KiB程度になります。これなら、2倍の領域(108KiB)をVRAMに割り当て、ここにクロックも埋め込んでしまうのも有りかな、と思っています。
 解像度を増やした時の余裕がありませんが、そもそも現状でも余裕が多い、という状況には程遠いですから、あまり解像度を増やすこともないでしょう。どうしても解像度がほしいというなら、マイコンを複数個並べたほうが楽でしょうし。

 以前はTIMでタイミングを作り、TIMのPWMをピクセルクロックとして使う、といったことも試しましたが、TIMとDMAの同期(位相)を取るのがかなり面倒なのと、適切な位置でTIMを止めるのも面倒で、あんまりあの方法はやりたくないなぁ、と思っています。


 今までの方法では、データソースは8bppIndexedであること、という制約がありました。8bppIdx画像はBitmapや、互換性のある特殊なPNGを使えば表現できますが、逆に言えばそれ以外のデータフォーマットがありません。
 一方で、今回はRGB888の上位3bitを取り出してVRAMに収納するので、大抵の画像フォーマットを扱うことができます。JPEGが使えるので、動画ファイルを扱うもよし、高圧縮ファイルをUSB経由で転送するもよし、いろいろな応用が効きます。


 ということで、実はまだset_pixelすらも作っていなかったりするわけですが、現状報告ということで。
// 64x32pxのパネルを1枚追加で買ってしまったので、はやく満足に使えるようにしなければ。

0 件のコメント:

コメントを投稿