gombeのブログ

マイコンの電子工作系PIC32/KiCad/C/C++/3D/

SPIx3でNTSC

PIC32でNTSCシグナルの生成に成功(?)したのでメモ。

こちらがけんけんさんがやってくださったものです。よく書けてるのでこっち見てください。

PIC32MK でNTSCシグナルを生成するとき、普通だったらタイミングに沿ってCPUで出力します。ただ、リソースの問題で、CPUの使用率は60%を越えるため、アプリケーションに割ける時間が少なくなってしまいます。

今回はSPIという通信規格で、シグナルを生成することに成功しました。SPIは、本来クロックに従ってデータ出力をします。その際、1ビットずつシフトするため、負荷が理論上は1ドット16サイクル3バイト出力と、減るはずです。今はまだCで書いているため重いですが、最適化次第でさらに軽くなると思います。

仮に1ビットだとすると以下のように使います。

1bitといってもアナログです(苦笑)。連続量を扱いたいときは2値だけではなく、実際はデルタシグマ方式でPWMみたいに出力します。ただ、速度が58MHzなんでさすがに1bitでは足りません。そこで今回は3bit同時に出力して、8段階で出力することにしました。実際のところ、なるべく時間分割できた方が、解像度を上げるより綺麗に映るようです。4bitでできればいいのですが、(スペック的には足りる)同期が面倒なので今回は3bitにしました。(回路も簡単!)

色はいまでも出ていますが、青は1ドットだけだと奇数ドットで潰れてしまうため、2ドット以上はあった方が良さそうです。これはDAのビット数不足が原因です。青はもともと輝度が高くなく、3bitだと潰れてしまいます。誤差を最小限に抑える演算をしても、1dotだけではしっかり色が出ません。4bitなら精度が十分に高く、色がずれずにすみます。そのため精度を保つためには4bit以上ということになります。

説明のため、2bitの図を示します。

SPIを同期させるとは、複数のSPIでクロック信号の位相を揃えることと、出力タイミング(ここではデータのビット)を揃える必要があります。そのために用いるのが拡張バッファモードです。このモードではSPIのバッファが拡張されて128bitのLIFOが付きます。このため8bitの場合は16段のバッファが積まれています。12byteづつ入れればタイミング的には間に合います。

そもそもNTSC使うのかってところですね。HDMI等のディジタル的に生成する際は差動出力が4ch必要です。さらに13.5MHzのピクセルクロック(480i)の場合でも(最小)その10倍の135Mhzで出力する必要があります。事実これは不可能です。

アナログ系でコンポーネント信号でもいいのですがD端子をはじめとしたコンポーネント信号も数が減ってるそうです。VGAはあまり見なくなりましたし。となるとマイコンで生成できるのはコンポジットまでとなるわけです。こいつはしばらく生きると思います。必要に応じて画質があげられる点にも注目ですね。(インターレースを利用した方式)240p,480iと余裕があればどんどん画質があげられます。

脱線しましたが、NTSCについて復習しましょう。大雑把に見れば主に2つの区間からなります。映像は左から右に行った後一つ下にずれてまた左から右に走査がずれます。一画面描画したらまた上に戻りまた描画を開始します。

1、水平同期

水平区間描画の際は水平同期が必要です。今の水平位置をリセットできます。1ラインごとに行います。

1.2 カラーバーストから映像区間

NTSCではカラーバーストから色を合成します。3.58MHzでカラーバースト信号を送り、波形の位相を記憶します。その後の映像区間ではその色に基づいた色が出力されます。

色差信号をもとにsin,cosで変調をかけます。詳しい説明は省きますが、3.58の整数倍の出力間隔なら結構簡単なようです。今回は16倍です。4、8でも認識はするようですが、今回は8出力で1ドットとしたため都合がいいです。

2、垂直同期

垂直方向での位置を一画面に一度リセットします。インターレース合成も含みますがめんどいのでここでは省略(;;

っといざ色を出してみると結構あっさり出ました。以外と簡単に色がでました。びっくりです。

こう書いている時にケンケンさんが色々試してくれました!twitterに色々載ってます。静的な表示だけだったのですがいつのまに動的な表示までやってます。いや、他の人のソース読んでこのスピードは早いですね

(⁰▿⁰)

↓うむ。。画像が動いてる。

https://twitter.com/KenKenMkIISR/status/914453401106354177