Raspberry Pi Pico 2が発売されましたねー。今回はPico2の新機能を使った実験です。
表示遅延計測と言っても、Pico2では1080p60や2160p60等は出力できずフルHDや4Kのモニタのネイティブ解像度で表示できないので、どれほどの実用性かは不明。
なお、HDMI接続と言っても出力する信号自体はDVI-D信号です。HDMIはDVI-Dに対して上位互換性があるので、HDMI接続でもDVI-D信号を表示できます。
先にソースコードと.uf2ファイルを置いておきます、コンパイルしなくても.uf2ファイルをPico2に入れれば動くと思います。
hstx_dvi_out_lag_test.zip - Google ドライブ
Raspberry Pi公式のHSTX機能のサンプルdvi_out_hstx_encoderがプログラムのベースです。
開発環境はWindows 11とVS Code、PlatformIOでArduino-Picoを使用してます。Arduinoの機能はシリアル通信くらいしか使ってません。Pico SDKのシリアル通信よりArduinoの方が使い慣れてたので。
- Pico2の新機能、HSTXとTMDSエンコーダー
- HDMIとPico2を繋ぐ
- DVI出力の解像度はPico DVIの時より大きくできるのか
- 実際に出力解像度を上げてみる
- 信号出力から映像表示までの遅延を計測する
- 最後に
Pico2の新機能、HSTXとTMDSエンコーダー
Raspberry Pi Pico 2の新機能で興味深かったのが、HSTXとTMDSエンコーダー。
HSTX(high-speed serial transmit)はDDR(double data rate)出力、つまりクロックの2倍の周波数でデータを出力することができます。Pico2のシステムクロックが150MHzならHSTXは300MHzで出力可能。ただしHSTX対応GPIOは固定の8ピンに限定されています。ちなみにTXの名前のとおり送信のみで受信不可。出力専用。
TMDSエンコーダーは、8bitのデータをTMDS(DVI-DやHDMIで使用される映像信号出力形式)用の10bitデータにエンコードする機能です。SIO(Single-cycle IO)とHSTXにそれぞれ付いてます。
ところで、Pico(2じゃない方)発売当初PicoDVIというプロジェクトがありました。Picoのシステムクロックを2倍近い252MHzまで大幅にオーバークロックして、640x480のTMDSの映像信号を出力するというものです。Pico DVI Sockという、PicoのMicro USB端子の反対側にHDMI端子を生やすような基板もあります、PicoDVIでHDMI接続するのに最適。
使用GPIOはMicro USB端子の反対側の端の方の合計10ピン、GP12~GP19の8ピンとGND2ピン。
ここで話を戻しますが、前述の通りHSTXはクロックの2倍のデータを出力できます。HSTXが使用できる固定のGPIO8ピンというのはPico DVI Sockと同じGP12~GP19の8ピンです。そしてHSTXとセットになっているTMDSエンコーダーによりTMDSの8b/10bエンコードにCPUを使わなくてよくなります。
つまり、Pico2では大幅なオーバークロックなしにPIOも使わずCPUの使用もだいぶ抑えてDVI-D・HDMI出力ができるということになるわけです。しかもPico DVI Sockがそのまま使える。
かなり「DVI-D出力をやりやすくするぞ」という意思を感じるピンポイントな機能追加です。
とはいえHSTXはDVI出力にしか使えないような機能ばかりというわけでもなく、
- クロックジェネレータ:指定したGPIOをnクロックごとにHIGHとLOWを反転させて出力
- シフトレジスタとビットクロスバー:FIFOからnビット取り出してGPnに出力・次はnビット取り出してGPnに出力、というような設定をレジスタで指定可能。RGB565をRGBそれぞれのGPIO3つに分配、みたいにビット処理を自動化できる
- コマンドエクスパンダー:同じデータをn回繰り返し出力する、TMDSエンコードする、等をコマンドで指定できる
と、今まではPIOで専用のプログラムを用意する必要があるような処理が可能です。TMDSエンコーダーは…まぁこっちは8b/10bエンコードにしか使えないでしょうけど。
HDMIとPico2を繋ぐ
HDMI接続するためにPico DVI Sock的な物を買う必要があるな、ということでAliExpressを物色してたらセールで300円ちょっとで買える物を発見("Choice"という、合計1,500円以上なら送料無料で1週間ほどで配達されるサービスの対象)。この商品です。
SpotpearというメーカーのHDMIボード。Pico DVI Sockと違ってPicoの全てのピンをボード側のソケットに差し込むタイプで、使用するGPIOもPico DVI SockのGP12~GP19と違いGP8~GP15ですが、元々Pico2をブレッドボードに挿してHDMIボードとの接続はジャンプワイヤ経由で使うつもりだったのでこの商品でも別に問題なし。ということで購入。
メーカーのユーザーガイドどおりにHDMIボードにPico2を挿し込んで、古いフルHD液晶テレビ(REGZA ZP2)でHDMI接続してサンプルの.uf2ファイルの映像がちゃんと映るのを確認。
次はブレッドボードに挿したPico2からジャンプワイヤでHDMIボードに繋いで、Pico2のHSTX機能のサンプルdvi_out_hstx_encoderを試す。映らない。えっ?ジャンプワイヤの接続をGP8~GP15に戻してSpotpearのユーザーガイドのサンプルを試すもこっちも映らなくなってる。
そういえばPico DVI Sockの回路図に「DVIの仕様で5Vを供給する必要がある、でもほとんどのモニターは気にしないみたい。問題がある場合はVBUSから5V繋いで」みたいなことが書かれてたのを思い出し、SpotpearのHDMIボードの回路図でHDMI端子の18ピン目「HDMI 5V」にPico向けソケット側のVBUSが繋がれてるのを確認してPico2のVBUSをHDMIボードのソケットのVBUSの部分に接続して実行。やっぱり映らない。えぇーっ?
Pico2を直接挿し込んだ時は映ったのにジャンプワイヤ経由だと映らない、いよいよ意味がわからない。次に、試しにVBUSに加えVSYS(Micro USB接続中はこっちからも5Vが出ている)も繋いでみる。…映った!?あっ、つまりこれHDMIボードの回路図ではVBUSって書いてあるけど実際はVSYSが繋がってるってことじゃん!嘘つき!
…接続をGP12~GP19に変えてHSTXのサンプルをテスト、こちらも無事映った。
結果的に余計な遠回りをしてしまいましたが、とりあえずこれでPico2からHSTXでDVI出力ができることを確認しました。
DVI出力の解像度はPico DVIの時より大きくできるのか
dvi_out_hstx_encoderでは640x480のリフレッシュレート60Hz、つまり480p60の映像を出力します。Pico DVIの場合は、125~133MHzのPicoを2倍近くオーバークロックしてなんとか480p60の周波数252MHzを実現していましたが、Pico2はデフォルトのクロックが150MHzに上がって更にHSTXで転送速度が2倍になります。じゃあPico2ではもっと解像度を上げられるのでは?
初期状態でHSTXのクロックはシステムクロック(デフォルトで150MHz)に同期してます、そこから更にDDRで300MHz。解像度640x480だとシステムクロックを126MHzにするとHSTXの転送速度が252MHzになり、リフレッシュレートが60Hzになります。
まずシステムクロックがどこまで上げられるかテスト。…およそ309MHz?コア電圧を上げたらもっと行けるかもしれないけどとりあえずコア電圧はいじらず。DDRで2倍の618MHzになるので、720p30(1280x720 30Hz)の371.25MHzは超えるが720p50(50Hz)の603.75MHzがギリギリ、720p60(60Hz)の742.5MHzには届かない。
742.5MHzは720p60の他にも1080i60や1080p30の周波数でもあるので、できれば742.5MHzを超えたい。
Pico2のクロックについて
ここでちょっとPico2のクロック設定について。
以下はRP2350 Datasheetの"Chapter 8. Clocks 8.1. Overview"にある概要図です。
Pico2の初期設定では、クロック周波数がシステムPLLは150MHz、USB PLLは48MHz。
クロックソース設定はclk_sys・clk_peri・clk_hstxがシステムPLLを、clk_usb・clk_adcがUSB PLLを使用しています。
表にするとこう。
システムPLL 150MHz | USB PLL 48MHz | |
clk_sys(CPUやメモリ等) | 150MHz | |
clk_usb(USB) | 48MHz | |
clk_adc(ADC) | 48MHz | |
clk_peri(UARTとSPI) | 150MHz | |
clk_hstx(HSTX) | 150MHz |
この状態ではHSTXのクロックを上げようとシステムPLLを高速にするとCPUやメモリのクロックも上がってしまい、HSTXにまだクロックを上げられる余地があってもCPUやメモリが先に動作しなくなってしまいます。
一方のUSB PLLも、clk_usbは48MHzにしないとUSBで通信ができなくなるのでこのままでは48MHz以外には変更できません。
そこで、片方をHSTXに占有させる設定。
システムPLL 144MHz | USB PLL 400MHz | |
clk_sys(CPUやメモリ等) | 144MHz | |
clk_usb(USB) | (÷3) 48MHz | |
clk_adc(ADC) | (÷3) 48MHz | |
clk_peri(UARTとSPI) | 144MHz | |
clk_hstx(HSTX) | 400MHz |
こうするとHSTXのクロックだけを自由に変更できます。
Pico2はクロックソースを選択する時に、周波数をクロックソースの周波数 ÷ n にするという設定ができます(先ほどのクロックの概要図の[ ÷ ]マークの部分)。これを使って、システムPLLを48MHzの倍数、今回は3倍にしつつclk_usbをシステムPLL ÷ 3と設定することによって、clk_usbの48MHzを維持できます。もちろん3倍以外も可能です、6倍(288MHz)までは行けました。
HSTXのクロックソースにUSB PLLも使えるのを知ってこの方法を思いついたんですが、それに伴いPLLについて調べるべくRP2350 DatasheetのPLLの章 "8.6. PLL" を見ていたら8.6.1. Overviewに全く同じ方法がすでに書かれてました、システムPLLを144MHzにしてUSBを144MHz / 3 = 48MHzにすればUSB PLLはHSTXやGPIO等に自由に使えるよ、と。
この設定で試したところ、USB PLLは420MHzくらいまで上げることができました。HSTXのDDRで840MHzなので。720p60の742.5MHzを超えます。
実際に出力解像度を上げてみる
では720p60や1080p30を試していきましょう。
解像度を変えるにはH SyncやV Sync等のタイミング設定を知る必要があります。Video Timings Calculatorという、解像度を入力するとクロックやタイミングを確認できるページがあったので、このCEA-861(現在はCEAがCTAに改名したのでCTA-861)のタイミングの値を使ってみます。
480p60 | 720p60 | 1080p30 | |
H Total | 800 | 1650 | 2200 |
H Active | 640 | 1280 | 1920 |
H Front Porch | 16 | 110 | 88 |
H Sync | 96 | 40 | 44 |
H Back Porch | 48 | 220 | 148 |
V Total | 525 | 750 | 1125 |
V Active | 480 | 720 | 1080 |
V Front Porch | 10 | 5 | 4 |
V Sync | 2 | 5 | 5 |
V Back Porch | 33 | 20 | 36 |
ちなみに1080pのタイミングを図にするとこう。
V Front Porch + V Sync(垂直同期信号) + V Back PorchがV Blank(垂直ブランキング期間)、V Blank + V ActiveがV Totalとなります。H(水平)も同様。
前述の古いフルHD液晶テレビで先程のタイミングの値を試したところ、720p60も1080p30もちゃんと映りました。
ただ、480p60の時はHSTXのクロックをぴったり252MHzにできてリフレッシュレート60.0Hzになったんですが、720p60や1080p30だとクロックが742.5MHzではなく744.0MHzになってしまいます、720pで60.121212...Hz。
Pico2のPLL設定はあまり細かい周波数調整はできず、371.25MHz(HSTXの方はDDRなので742.5MHz)にしたくても少し上の372.0MHzか少し下の369.0MHzにするしかありません。
この60.12Hzだと液晶テレビの表示は「映像は60Hz表示で8秒くらいに1回の頻度で1フレームスキップされる」になるのか「映像は60.12Hz表示」になるのかが気になる、ということで1フレーム点滅を表示させてみましたが、特に1フレームスキップされる様子はなし。59.94Hzを60Hzではなく59.94Hzで表示するように、多少なら上下しても合わせてくれるということでしょうか。
ちなみに61Hzにしたらティアリング起こしながらちょくちょく1フレーム繰り返したりスキップされたりしました。61Hz表示ではなく多分60Hz表示。ティアリングは起きるけど意外とちゃんと表示される。じゃあ120Hz、つまり60Hz信号の周波数を2倍にしたら?と試してみたところ、表示されてびっくり。1フレーム点滅を映してみると白いままだったり黒いままだったりで点滅してる時間は少ない。120Hz点滅が止まって見えるということは表示はおよそ60Hz?リフレッシュレートが変でもH-SYNCやV-SYNCの割合があってれば表示してくれるのかこのテレビ…。
60.1212..Hzではなく60Hzぴったりにする方法として、PLLに設定できる周波数にするためにFront PorchやBack Porchを増減させるという手もあります。例えばH Totalを1650から1640に(H Front PorchとH Back Porchからそれぞれ-5したり)すると、周波数がPLLに設定できる369MHzになってリフレッシュレートを60Hzぴったりにできます。これでも映りましたが、規格のタイミングからから外れるほど映らないモニタが増えるかもしれません。試してるフルHD液晶テレビでもH Totalを1650から1624まで減らした所で映らなくなりました、1625ではまだ映りました。
次にメインで使ってる4K液晶テレビ(REGZA Z730X)でテスト。こちらも映りました。が、720p60と1080p30で度々映像が途切れます。480p60なら問題なし。これは…と1mのHDMIケーブルから別の0.3mのケーブルに変更したら途切れが一気に減少。
つまり640p60の252MHzより3倍近い742.5MHzだとノイズに弱くて、ケーブルが長いほど辛い。恐らくジャンプワイヤ経由してるからですね~これは。素直にGP12~GP19の8ピン使うタイプのPico DVI Sock買ってジャンプワイヤ使わず直接繋げる方が良かった?
なお720pの60.12Hzを1フレーム点滅を表示してもフレームスキップなどは起こらず問題ありませんでした、こっちも60Hz表示ではなく60.12Hz表示できてるっぽい。480pの61Hzも試しましたが、これは映らず。ケーブルノイズといい、古い方のフルHD液晶テレビと比べてこっちの4K液晶テレビは少しシビアな気が。メーカー同じなのに。
最後にVRR対応ディスプレイ(Acer XV275K P3)でテスト。HDMI端子の方はVRRで144Hzまで対応しています。480p60が映ったので信号の周波数を単に2倍(120Hz)にしてみましたが無事120Hzで映りました。ただ、2.4倍の144Hzだと画面下半分が少し崩れる。
そして、てっきり苦も無く映ると思っていた720p60と1080p30が映らず。CVT-RB(VESA策定のタイミング仕様であるCVTの一種で、ブランキング時間を少し短くしたもの)と同じにすると映りました、先程の480pの144Hzも、CVT-RBのタイミングにすると画面下半分も正常に映るように。
これもしかしてEDID確認しなきゃいけないやつ?と思いMonitor Asset Managerを使ってEDIDを確認。「CE video identifiers (VICs) - timing/formats supported」の欄に720p60や1080p60等に対応してる表記と共に1440pのタイミング表記が。これがV Back Porch以外1440p60のCVT-RBと一致してます(V Back Porchだけ33ではなく77)。この各タイミングをそのまま1/2にして1440pから720pにすると、確かに映る。3/4倍にして1440pから1080pにしてみるも、こっちは映らない。対応一覧に1080p60はあっても1080p30は無かったのでそのせいですかね。でもV Back PorchをCVT-RBと同じにしたら映った。
つまりは、ちゃんとEDID確認しないとダメってことでしょうかねぇ…。今回はそこまでやるつもりはないので、解像度切り替えは720p60や1080p30の場合にCTA-861とCVT-RBを選べるという形にして逃げることにします。つまりCVTっぽいタイミングを要求するディスプレイとかがあった場合は対応できない。
信号出力から映像表示までの遅延を計測する
Raspberry Pi 4やRaspberry Pi Zeroを使用する、HDMIの表示遅延測定ツール piLagTester PROという物があります。画面の一部を黒から白に変化させて、その変わり方を光センサーで捉えて遅延を測定します。
で、ここまで書いた通りRaspberry Pi Pico 2は自力でDVI-D信号を出せますが、自力ということは信号内容をDMAでHSTXにいつ送ってるのかのタイミングまで把握できるということになります。ならばPico2に光センサー付けて信号出力のタイミングと比較したらpiLagTesterPROみたいなことができるのでは?
ということで、piLagTesterPRO同様光センサーで映像が表示されるタイミングを測れるようにしてみましょう。
光センサーの類はCdSセル(フォトレジスタ)を持ってましたが、これは応答速度が20msとこの用途に全然向いてません、反応し終わった頃には1フレーム(16.666..ms)過ぎてます。
なのでフォトトランジスタ NJL7502L を買いました。応答速度10µs。欲を言えばもう1桁速い方がいいですが、安くて(50円前後)入手性も良さそうだったのでこれにしました。
これをPico2の3.3VとADCに繋ぎます。回路図だとこんな感じ。
フォトトランジスタから流れる電圧をADCで計測します。
この図では抵抗値が300KΩになっていますが、別に300Kじゃなくてもいいです。ADCで計測した電圧が高すぎる場合は抵抗値をより低く、電圧が低すぎる場合は抵抗値をより高くしてください。測定するモニタの輝度によるので、可変抵抗を使って調節できるようにした方が便利かも。
Pico2のADCはデフォルトでは48MHzで動作し、1度の値の読み取りに96クロック必要です。48MHz÷96でサンプリングレートは500KHzになります(周波数は変更可能)。free-running capture modeという、CPUから命令しなくても自動的にADC用FIFOに測定値を次々に入れ続ける機能があるのでそれを使用します。
最初はフォトトランジスタで測定開始するタイミングでfree-running capture modeを開始して必要な分サンプリングしたらADCを止めていたんですが、それだとどうも電圧が低めだと最初の数サンプルの電圧値の立ち上がりが遅れたり、電圧が高いと最初の数msほどの電圧が高めに出たりの影響があったので、今はfree-running capture modeを止めずにADCを動作させっぱなしにしています。
今回は、2サンプルを平均化してメモリに記録(500KHz÷2で250KHz)・それを25,000回続ける(250KHzだと1s÷250Kで1回4μs、4μs×25,000で100ms=0.1s)、という形で0.1秒間分サンプリングします。
画面に白い横長のバーを1秒間に1回点滅させて(白表示0.5秒→黒表示0.5秒を繰り返す)、それを光センサーで測定します。0.1秒サンプリングするタイミングは1秒の内に3回。
- 白表示にして1/4秒経過後:白への変化が落ち着いた後に白の輝度レベルを測る
- 黒表示にして1/4秒経過後:黒への変化が落ち着いた後に黒の輝度レベルを測る
- 白表示にした瞬間:白の輝度レベルに変化するまでの時間を測る
の3回です。これを更に、3.は2サンプルの平均、1.と2.は50サンプル(一瞬だけ変動するようなスパイクを排除するためサンプル数多め)の平均を取って、上下の変動を均してます。1.と2.は均した0.1秒間の内の最大値を白と黒の輝度レベルの基準としています。黒の輝度レベルの基準が最小値や平均値ではなく最大値なのはpiLagTesterPROに合わせたため。
測定する遅延時間の誤差要素として、
- 白いバー部分の信号出力と同時にADC開始ではなくその前からADC回しっぱなしなので、測定値の記録開始タイミングに若干ゆらぎがある
- 白いバー部分の信号データのHSTXへのDMA転送が始まっても、そのデータが即HSTXから出力されるわけではなくHSTXのFIFOにまだ残ってるデータを出力し終えてからになる
この2つがありますが、1.は計測したところ最大0.0004ms、2.は多分0.0002ms程度なので、有効数字(x.xx ms)の桁の外ということで今回は考慮していません。1.の方は一度は補正してみたものの、他の誤差要素の中に埋もれて有効なのかわからないので外しました。
使い方
こういう映像が出力されます(720p60の場合の画面)。
上端に点滅するバー、下にADCの測定結果のグラフを表示します。光センサーは点滅するバーに当ててください。
下のグラフは縦100ピクセル固定の8bit(R2・G3・B3bit)フレームバッファです、1280x720x8bitで900KByte、1920x1080x8bitで2,025KByteとPico2のメモリ520KByteに全く収まらないのでフレームバッファは全画面分ではなく縦100ピクセル分です。
左下部分(時間にして1フレームちょっと)を拡大。暗くて見づらいですがグレーの横破線は黒レベルと白レベル、グレーの縦線は1フレーム毎の時間の区切り、グレーの縦点線は5msずつの区切り、赤い縦線は輝度が(黒を0%、白を100%とした場合)5%を超えた瞬間、黄色い縦線は輝度が80%を超えた瞬間、画面右下の数字は輝度が5%と80%を超えた時間です。5%赤表示と80%黄色表示はpiLagTesterPROに合わせてます。
USB経由のシリアル通信でPico2へ文字を送信(キーボードのキーを押す、Enter押さないと送信されないタイプでは1文字入力後Enterを押す)することで表示設定を変更できます。Tera Term等のシリアル通信ソフトでPico2のUSB経由のCOMポートに115200bpsで接続してください。開発中はVS CodeのSerial Monitor使ってました。
'1'~'6'のどれかを送信すると表示解像度を変更できます。[1]キーを押して480p60に切り替え、みたいな感じで変更します。'1'で480p60、'2'で480p120、'3'で720p60(CTA-861準拠)、'4'で720p60(CVT-RB準拠)、'5'で1080p30(CTA-861準拠)、'6'で1080p30(CVT-RB準拠)。
'P'(アルファベットは小文字でもOK)で点滅するバーの位置を変更できます。上か真ん中か下の3箇所。
'F'で1フレームごとに点滅する縦長のバーを右端に表示します。もう一度'F'で非表示。
'Z'で測定開始タイミングを変更します、詳しくは後述。初期状態は白いバー(の左上)、次にV Blank開始位置、次にV Sync開始位置、次にActive Video開始位置。
'B'でフレームバッファ部分をPico2からシリアル通信でBMPファイルのバイナリとして出力します。このブログ記事用にグラフのスクショが必要だったので付けた機能。Tera TermでPico2のUSB接続のCOMポートに接続→バイナリ形式でログ記録開始→キーボードのBを押す→ログ記録終了→ログファイルの拡張子をBMPに変更、という感じで保存しました。
'C'でPico2からシリアル通信でCVSファイル形式でサンプリングデータを出力します。経過時間(単位はms)と電圧(単位は0~3.3V)、100msの内の全25,000サンプルは多すぎるので間引いて100ms中1,000サンプル(0.1msごと×1,000で100ms)。それと黒レベルと白レベルの電圧、そして5%、10%、20%、以降10%刻みで100%までの輝度到達時間も一緒に出力します。
これは出力したCVSファイルの最初の方(13/1,000)。
time_ms | voltage | black_voltage | white_voltage | time_ms | percentage | |
0.000 | 0.387 | 0.383 | 2.253 | 1.628 | 5% | |
0.100 | 0.395 | 2.000 | 10% | |||
0.200 | 0.383 | 2.612 | 20% | |||
0.300 | 0.401 | 3.152 | 30% | |||
0.400 | 0.393 | 3.692 | 40% | |||
0.500 | 0.367 | 4.308 | 50% | |||
0.600 | 0.366 | 5.004 | 60% | |||
0.700 | 0.382 | 5.804 | 70% | |||
0.800 | 0.378 | 6.852 | 80% | |||
0.900 | 0.378 | 8.332 | 90% | |||
1.000 | 0.396 | 12.772 | 100% | |||
1.100 | 0.405 | |||||
1.200 | 0.414 |
入力ラグではなく応答速度を測るなら [90%になった時間] - [10%になった時間] 、みたいな見方もできます。
遅延時間が変動するというか、5%・80%のタイミングと波形が形を変えずに一緒に一方向に少しずつズレていき、ズレきったら一気に戻る場合は、信号のリフレッシュレートとモニタの駆動周波数があっていません。
それを解消できる可能性がある方法として(まぁそうそう解消できないというか、ほとんど自分が実験するためだけに付けた機能ですが)、'W''S''A''D'でHかVのFront PorchとBack Porchを増減させることができます。'W'でVを-1、'S'でVを+1、'A'でHを-1、'S'でHを+1します。増減した値を元に戻したい場合は解像度変更('1'~'6')を使ってください。
測定方式による差異
piLagTesterPROは画面の測定場所が上中下の3箇所あるんですが、
測定すると大抵のモニタで遅延時間が3箇所それぞれで違います、下に行くほど遅延時間が増えます。他のHDMI遅延測定機でも同様だと思います。
これは画面を上から下へ順に更新していくためです。
より正確には、一番上を左端から右へ順に更新して、右端まで行ったら1ピクセル下に改行してまた左端から右へ更新、を繰り返します。以下、Wikipediaより、Raster scanの画像。
ブラウン管ではこのVertical retrace(垂直帰線)で示されている戻っていく動作がV Blank(V Front Porch ~ V Back Porchまで)の間に行われます。H(水平)も同様。
映像信号の出力も左から右、上から下へ出力しています。ここで一度貼った信号タイミングの図をもう一度。
測定場所3箇所の話に戻りますが、例えばこの図の一番左上、つまり映像領域が終わりV Blankが始まったタイミングを基準の0秒(0.00ms)として各場所の信号が出力されるまでの時間を計算すると、
このようになります(1080p60の場合)。白いバーの上中下3箇所の違いだけでなく、1つのバーの左上か左下かでもこれだけ違います。HDMIの遅延測定機でも、例えば上のバーならどこに光センサー当てても同じなように見えて実はバーのどこに当てるかで結構変わるかもしれません。モニタのレビュー記事でHDMIの遅延測定機使っててもこのバーのどこに当てるかについてはあまり触れられない。同じ測定機使っててもレビューによって結果が違うとしたらこの理由の可能性も。
HDMIの遅延を測定するにしても、「白レベル何%になったら変化したとみなすか」とか「測定開始基準をどこにするのか」次第で測定値は変わります。同じモニタを別のHDMI遅延測定機で測定したら結果が変わるかもしれません。
そして今回のPico2用のプログラムの場合ですが、白いバーの表示場所を上中下のどれか1箇所を選択して表示します(表示場所を切り替える方法は”使い方”で説明したとおりシリアル通信で'P'を送信)。他のHDMI遅延測定機との違いとして、測定開始基準位置(0秒になる位置)もその白いバーに追随してます。
これは「白いバー部分の信号を出力し始めた瞬間から実際に表示されるまでの時間を測定する」という目的に基づきこうしています。入力した信号をシンプルにそのまま画面に表示するモニタなら上中下3箇所どこで遅延測定しても同じになると思います。
60Hz入力でも倍速(120Hz)駆動とか、上から下への更新とは別にバックライトが点滅してたり(画面全体を同時に黒挿入していたり)とかで、3箇所の測定場所によって遅延時間が変わることもあります。
なお白いバーが真ん中の場合の縦の位置は、画面の真ん中ではなく、白いバーの上端が真ん中に来ています。なので白いバーの上端を光センサーで測定するとちょうど真ん中の表示遅延を測定できます。
一応他のHDMI遅延測定機同様に測定開始タイミングを白いバーに追随させない設定もできます。”使い方”で少し説明しましたが、'Z'を送信すると変更できます。
タイミング図の左上を拡大。この4箇所です。初期状態は①、白いバーの左上。'Z'を送信する度に変わり、④の次は①に戻ります。②か③どちらかでpiLagTesterPROの測定値に近い値になるかも。いややっぱりならないかも(持ってなくて確認できないので)。
最後に
最近の機種ではあまり無いようですが、モニタのネイティブ解像度(フルHDモニタなら1920x1080、4Kモニタなら3840x2160)の映像じゃないとスケーリング処理分の遅延が増えるという場合がときどきあります。
Pico2のHSTXだと60Hzでは720pが最大で1080p60や2160p60は無理なので、フルHDモニタや4Kモニタで720p60で遅延を測定しても、ネイティブ解像度じゃないのでそれがそのモニタの真価と言い切れないところがあります。
そんなわけで実用性には疑問符が付くところではありますが、いろいろ試していろいろ知ったりいろいろ楽しかったです。今回は信号入力から表示までの遅延時間計測を試しましたが、Pico2ならこれとはまた別の遅延時間計測とかもできそう。
300円ちょっとのHDMIボードと50円前後のフォトトランジスタ、とだいぶ安上がりで済んだ実験でした。ただHDMIボードはジャンプワイヤ使わない方式の方がノイズ少ないという点で良かったかも。こういうのとか。
Raspberry Pi Pico用DVIアダプタ基板www.switch-science.com
ジャンプワイヤ使うならこっちの方が安上がり。
Adafruit DVIブレークアウトボード(HDMI機器用)www.switch-science.com
そういや720p60のクロック742.5MHzって、1080p30や1080i60に加え、YUV420の1080p60とも同じなんですよね。YUV420ならPico2で1080p60が出力可能?
ただYUV420となるとDVI-DではなくHDMIの領域?YUV420であることを表示機器側に伝えるには?AVI(Auxiliary Video Information) InfoFrameとか送ればいいんでしょうかね?
YUV420なのを伝えられても今度は映像内容をRGBからYUV420に変換するのが間に合うのだろうか。Pico2のinterpolator使ったらUV成分まとめられるだろうか。いっそカラー諦めてY8bitだけ使うモノクロなら…?