ESP32-S3でUSBディスプレイでフルHD出力

概要

USBホストライブラリにUSBディスプレイアダプタのサンプル実装をしてみました。なんとか表示はされますがかなり遅いです。でもフルHDが表示できるのはかなり便利です。

USBディスプレイアダプタ

いろいろなUSBディスプレイアダプタがありますが、DisplayLink社DL-165で動作検証をしました。最新のやつは暗号化が入っていてプロトコルを独自実装することができません。

上記のような思ったより大きなアダプタになります。標準はDVIなのですがVGAとHDMIへの変換アダプタが付属しています。HDMIがないと不便なので現在新品で購入できてHDMIが使えるものではこのアダプタが価格と入手性ともによいです。

使い方

EspUsbHost/examples/Vendor/EspUsbHostDisplayDl1xx at main · tanakamasayuki/EspUsbHost
Library for using USB Host with ESP32. Contribute to tanakamasayuki/EspUsbHost development by creating an account on Git…

上記にコード例があります。ライブラリ本体への組み込みではなく、Vendor拡張の利用例として入れてあります。.hppで拡張部分を作ってありますので比較的再利用しやすい形になっていると思います。

制限

まず非常に遅いです。ESP32-S3はUSB経由で秒間1MB程度のデータ転送が可能です。そしてフルHDの画面が約4MBありますので、そのまま転送すると4秒かかります。

このUSBディスプレイアダプタは横方向はランレングス圧縮をして送信するプロトコルになっているようでして、同じ色が横に続く場合にはかなり早いです。逆に違ういろが続く場合にはRGBデータをそのまま送信するのではなく、ランレングス処理をしてから送信するので転送レートが上がりません。

いろいろ計測したろころESP32-P4だと秒間約33MB程度の転送が可能でした。しかしながらランレングスだけだとCPUが詰まって転送があまり伸びませんでした。転送方法が何種類かあるのでそのときのデータに応じて転送方法を変更しながら送らないと転送レートは向上しないようです。

そのため今回は最適化まではできていませんのでかなり遅いです。

ちらつき防止方法

さてフルHDを描画する場合、直接画面に書き込めるのですがちらつきがどうしてもでてしまいます。

GitHub – tanakamasayuki/LGFXVirtualCanvas
Contribute to tanakamasayuki/LGFXVirtualCanvas development by creating an account on GitHub.

そのために便利なのが上記ライブラリです。LovyanGFXやM5GFX(M5Unified)で仮想のダブルバッファを実現するライブラリです。

void drawScene(LGFXVirtualCanvas& g) {
    g.fillScreen(TFT_BLACK);
    g.fillCircle(g.width() / 2, g.height() / 2, 40, TFT_YELLOW);  // just draw full-screen
}

こんな感じで描画を描画用の関数上で表現します。そしてLGFXVirtualCanvas側で帯状に確保した小さいメモリ上でY座標をずらしながら何度も描画しては転送を繰り返します。画面上には上から帯で更新されていくのですが、ダブルバッファ的な処理ですので背景が消えるみたいな見え方にはなりません。

最大の特徴はデフォルトは20Kぐらいの小さいバッファしか確保しません。省メモリですがダブルバッファを実現可能です。ただし遅くなる可能性があります。

まず描画を帯状にやりますので、フルHDは1画面4MB程度必要で20Kのバッファだと200回以上描画を繰り返します。範囲外の描画はキャンセルされるのですが、細かい描画をしている場合にはオーバーヘッドとして遅くなります。逆に軽い描画の場合にはバックグラウンドの転送中に描画が終わるのでオーバーヘッドはほぼなくなります。

更新エリアのみの描画

このUSBディスプレイアダプタ向けに差分転送の機能を追加しました。

screen.setDiffMode(LGFXVirtualDiffMode::Tile);

デフォルトはOFFなのですが、有効化すると描画するタイル単位でハッシュを計算し、前回と同じであれば転送をスキップします。非常に単純な仕組みで高速化しています。この機能があるのでフルHDでもあまり更新されるエリアが広くない場合には実用速度で使える可能性もあります。

類似ライブラリ

GitHub – htlabnet/Pico_USB_Disp
Contribute to htlabnet/Pico_USB_Disp development by creating an account on GitHub.

Pico_USB_DispはRaspberry Pi Pico向けに見えますが、ESP32シリーズにも対応しています。

Raspberry Pi Pico USB Display Library
Raspberry Pi Pico USB Display Library Raspberry Pi PicoやESP32から真のFull HD映像出力を行うためのライブラリ「Pico_USB_Disp」を作りました。

日本語の解説記事もありますので、おすすめです。このライブラリの方が対応しているUSBディスプレイアダプタやLVGLなどの描画ライブラリなども充実しているのでおすすめです。ただし、汎用USBホストライブラリじゃないので、他のUSBと共存するのは面倒かもしれません。

LGFXVirtualCanvasはこのライブラリでも有効だと思います。高速化でいうとPSRAMとかを使ってピクセル単位とかで前回からの差分だけ書き込むとか、そもそもの描画範囲を狭くする方が有効だと思いますが、雑にちらつき防止ができるのはLGFXVirtualCanvasの利点となります。

まとめ

USBホストでいろいろなデバイスを動かすのは楽しいです。速度的には厳しいですがUSBディスプレイアダプタ経由でフルHDの画面を使える環境が手に入りました。

コメント