PIC AVR 工作室->TopPage->VHDL->CPLDでコンポジットビデオ表示(ネコ8)

CPLDでコンポジットビデオ ”ネコ8”

以前作ったコンポーネントビデオ表示の実験をしましたが、 そこからさらに一歩進んで、ようやくコンポジットビデオの表示もできるようになりました。

小規模のCPLD(XC9536XLやXC9572XL)を使って、デジタルRGB(8色)のビデオ信号をコンポジットビデオ信号、 Sビデオ信号に変換してしまおうという目論見です。

デジタル8色RGBをコンポジット信号に変換するVHDL、名づけて”ネコ8”。

高価な高速オペアンプやビデオアンプなど使わずに最小限の部品代(CPLDに数個の抵抗とビデオ端子)だけで コンポジットビデオのカラー表示が出来てしまうのがいいところ。動物の鳴きまねは出来ませんが…

AVRやPICなどの適当なマイコンから8色RGBの信号を受け取って、NTSCのSビデオやコンポジットビデオ の信号に変換してしまうVHDLを作っていきます。CXA1645のデジタルRGB版といったところでしょうか。

このキャプチャー画像がその実行結果です。AVRで縞々模様のRGBカラーバーを出力して、それをCPLDで カラーコンポジット信号に変換してみた結果です。マイコン側でもっと複雑な色と模様をつけて表示させれば、 1ドット単位で色をつけてテレビに表示することが出来るわけです。

これまで私の頭の中で理解していたカラーコンポジット信号やSビデオ信号の規格について理解が正しいのかどうかを 確認する意味合いが強い工作物です。(マイコンで同じことをやろうとすると少々スペック不足でやる気が起きなかったんですが、 CPLDなら簡単に作れるだろう…と)

というわけで、実用性は”?”ですが、部品代が安く済みつつビデオデッキやビデオキャプチャーボードで 簡単に録画も出来るようになるので、使い道を探すせばいろいろ有りそうです。

ビデオ信号の復習

まずは以前マイコンとオペアンプを使ってカラーコンポーネントビデオの表示を やった時のお話の復習から入ります。垂直同期や水平同期のタイミングなどといった基本的なことはある程度理解して頂いている前提で進めるので、 その辺も知りたいという方はひとまず白黒ビデオの信号を作るプログラムの解説 に目を通していただければと思います。

三原色からRGB、そしてコンポーネントへ

まずはコンポーネントビデオの表示でも使ったこの図から復習。

この図は、光の三原色からRGB信号…コンポーネント信号、Sビデオ信号、コンポジット信号といったビデオにまつわる 各種信号規格の関係を簡単に表したものです。

これら4つの信号は、隣同士で相互に変換することができます。なので、順々に変換を掛けていけば、 RGB信号をコンポジット信号に変換することも、コンポジット信号をRGB信号に戻すことも出来るって訳です。

コンポーネントビデオ表示の時にはこのうち左側の2つ…RGB信号と コンポーネント信号について触れましたが、これらに付いてもう一度振り返ってみます。

色の三原色といえば[赤」「緑」「青」つまりRGBですが、これらの有り/無しを組み合わせると図の一番上の8色の帯 …白、黄色、水色、緑、紫、赤、青、黒…という8つの色が得られます((2の3乗=8ですね)。総天然色となると 当然8色だけじゃ済まないんですが、考え方は同じなので、シンプルな8色RGBだけを扱う前提で各信号について纏めます。

RGB信号

テレビがカラー表示をする際、結局RGBの3色の組み合わせで表現することになるので、最終的にはテレビ内部でRGB信号に 還元されて画面に表示することになります。そのRGBの情報をそのままI/F規格としているのがRGB信号というやつで、 この図の一番左がそれです。RGBだけでは当然同期が取れないので、シンクロ信号というものも一緒にI/Fすることに なります。シンクロ信号は便宜上黄色の小さい四角で描きました。(シンクオングリーンという信号規格もあるようですが、 一般的にはシンクロは別の線で送ります)

このRGB信号は、画面に表示する信号規格としては極めてシンプルでいいのですが、テレビの放送局から各ご家庭に 放送で使う電波に乗せる場合は信号数が多くて不便だったり、白黒放送時代の信号規格との互換性もないので、 この信号は1980年代の8ビットパソコンとパソコン専用ディスプレーを除くとあまり使われていません。(15Khzの話ですが)

コンポーネント信号(D端子)

このRGB信号と同じくらいの映像品質を持ちつつ、旧来の白黒ビデオとの互換性を保っているのがコンポーネントビデオ で、図の左から2番目の信号です。海外では緑、赤、青の3つのRCA端子で接続するのですが、日本ではD端子という 1個の端子で接続するのが一般的です。コンポーネント端子とD端子は形状の違いだけで、殆ど中身は一緒と考えてよいです。 (厳密には縦横比選択信号の有無というのがありますが…)

コンポーネント端子やD端子には、Y、Cb、Crという3つの信号が流れることになっています。

コンポーネント信号の緑端子、つまり「Y」の信号は「輝度信号」のことで、いわゆる白黒ビデオ信号のことです。 赤、青、緑の各色を、人間の目で見た感じに近くなるように、緑は明るく、青は暗く表示されるように調整してRGBを加重加算 したものです。

赤い端子=「Cr」信号は赤から輝度を引いた信号、つまりR-Yです。厳密にはその値に適当な定数を乗除することで 信号の振幅を調整して、伝送中に入り込むノイズの影響レベルを他の信号とあわせているようです。

青い端子=「Cb」信号も同様で、青から輝度を引いた信号、B-Yです。これらCbやCrは「色差信号」と呼ばれます。

これらの「輝度」と「色差」のYCbCr3つの信号を使うと単純な計算でRGB信号を復元することが出来つつ、 しかもY信号は旧来の輝度信号と互換があるので、放送局の機器などではこの信号が使われているようです。 もちろん、D端子やコンポーネント端子を登載したデッキやテレビもこの信号でやり取りしています。

輝度と色差に分ける理由は、人間の目で認識できる信号の密度の差を利用してデータ圧縮を掛けるなどといった 色々な観点もあるみたいですが、とりあえずそんな風に考えておいて大外れではないと思います。

ちなみにこのYCbCrという呼び方は15Khzのビデオ信号の場合(いわゆるD1規格)で、もっと解像度の 高い信号の場合はYPbPrという呼び方(かつ計算式も若干違う)だったり、PAL信号ではYUVと呼ぶようですが、 YCbCrもYPbPrもYUVも由来は色々ありつつも、色差信号という意味ではおおよそ同じモノを指していると思って いいと思います。

ご興味のある方は、「色空間」などのキーワードで検索を掛けてみてください。

ここまでの纏め

カラーでテレビ表示を行うために、入力された信号はテレビ内部でRGBに還元されるのですが、一方伝送手段としては 旧来の白黒信号との互換性を保っておく必要もあるため、RGBそのままではなく、輝度信号(Y信号=白黒信号)と「色差信号(Cb、Cr)」 を併せて使う「コンポーネント信号」というものが出来たわけです。

S信号とコンポジット信号

S信号やコンポジット信号も、これらの色差信号や輝度信号を元にして作られます。

S信号は輝度信号(Y信号)と色信号(C信号)で構成されますが、Y信号はコンポーネントのY信号と全く同じです。 一方C信号は、コンポーネント信号のCbとCr信号を「変調」して作られます。そしてコンポジット信号はこれらの Y信号とC信号を単純に足し算したものです。

…ということは、Cb、CrからC信号をどうやって作り出すかが解れば良いわけですね。

色差信号と色空間

Cb、Crの2つの信号は、そのままでは輝度信号に重ねて送ることが出来ません。単純に足しちゃったら最後、 もう元の輝度と色に分離することが出来なくなっちゃうからです。後々分離可能な状態にしておいてから輝度信号に色信号を重畳(足し算)し、 全体で1つの信号として送る必要があるわけです。そのための方法が「サブキャリア」による変調というものです。 Cb、Crをサブキャリアで変調して出来るC信号は、Y信号に単純加算することでコンポジット信号となり、逆にコンポジット信号を フィルター(BPFやBEF)に掛けることで元のY信号とC信号に分離することが出来ます。

サブキャリアの話をする前に、まずは色を角度と長さで表すことについてお話しします。

先ほどの図に出てきた8色分のCb、Crの値(計算の方法は後述)をそれぞれx座標、y座標としてグラフ上にプロットしてみましょう。 すると以下の図のように青がおよそ右向き、赤は上の方、緑は左下の方といった具合に描かれます。白と黒は中心座標(0,0)にあると 思ってください。(なお、図中に書き込んである座標とか黒い線とかは後で触れるのでひとまず無視してください)

この様に図に書き出すと、各色はグルッと1周して座標上のどこかに置くことが出来ます。8色以外の中間色も、 この座標のどこかに置くことが可能です。ちなみに、RGBからY、Cb、Crを算出する計算式はどこにでも転がっているので検索してみてください。 大体以下の式が見つかると思います。

Y = 0.587G + 0.114B + 0.299R
Cb = -0.587G + 0.886B - 0.299R
Cr = -0.587G - 0.114B + 0.701R

ちなみにRGBからYCbCrへの計算を行うことを「マトリックス処理」と呼びます。マトリックス処理で算出したCb、Crを 座標軸としてプロットしていくと、各色は原点(0,0)を中心にして角度と長さで表すことができます。

色の濃さ(色度)はこの各線の長さで表現することが出来ます。長ければ色が濃く(鮮やかに)、 短ければ灰色に近づいて行きます。そして色が付いていない「白」や「黒」は長さがゼロなので、この図でいう(0,0) の座標で表されることになります。(灰色も一緒)

そして角度。右方向を0度と捉えて、赤ならおよそ100度くらい、青ならおよそ350度くらいの角度に位置していることが お判りいただけるかと思います。

このように、色相と色の濃さを「角度と長さ」で表すことができるわけですが、その座標は一つの平面上の点に表現されます。 その平面のことを「色空間」と呼びます。平面なのになんで色空間っていうのかはよくわかりませんけど… あれかな? 輝度をZ軸に取ると空間になるのでしょうかね?

色空間というと、このCbCrで表現されるもの以外にも、sRGBやadobeRGBなど色々ありますが、 そのお話は端折ります。

で、色を「角度と長さ」で色空間上に表すことが出来ると、ようやくサブキャリアの話に繋がります。

色空間とサブキャリアによる変調

先ほどのグラフのように色を「角度と長さ」で表すことが出来るようになると、角度を「位相」に、長さを「振幅」に置き換えることで、 各色を正弦波で表すことができるようになります。そして、この色信号の波を輝度信号に足し合わせれば「一つの電波」 として放送電波に乗せて飛ばすことも出来るようになります。そしてテレビはそれを受け取ってから輝度と色度を分離(YC分離) すればカラーテレビの表示が出来るようになるという仕組みです。

もう少し眺めてみます。

実際に、8色の各色差信号を波に表したのが上の図です。この図の意味は後々よく解ると思いますが、ひとまず各波の「山と谷」 の位置を見比べて見てください。少しずつ横方向にズレているのが判るかと思いますが、その横方向のズレが「位相」 …つまりさっきの図でいう角度です。そして波の振幅がさっきの線の長さ…つまり「色の濃さ」を表しています。

(青や黄色よりも水色や赤の方が振幅が大きいですが、これは青や黄色の方が色の度合いが小さいという意味ではありません。 Y信号とC信号を足し合わせてコンポジット信号を作るときに、振幅を一定のレンジに押し込むための計算式(後述)によるものです)

ちなみに、NTSCコンポジット信号ではこの波の周波数は3.579545MHz(以後3.58MHz)が用いられています。この3.58MHzの波と振幅で 色を表現することを「変調」といい、この変調を掛けるための3.58MHzの波を「サブキャリア」といいます。上の図に出てくる波は すべて3.58MHzの波で表現されています。

テレビ側では、この3.58MHzの波だけを取り出すとC信号が得られ、3.58MHzの波を除去するとY信号が得られることになります。

バースト信号について

一つここで問題になるのは、何か基準になるものが無いとこれらの波の位相が何度なのか判らないということです。

そこで「位相の基準」になるものが必要となります。この位相の基準となるのがさっきの色空間のグラフで 180度のところに出てきた黒い短い線です。この黒い短い線も「長さと角度」を持っているので、一つの波として描き表すことが出来ます。 さっきの波形のグラフで、波がいっぱい重なっている中に黒い波が混ざっていますが、これのことです。

この基準となる黒い波のことを「バースト信号」と言います。

さて、黒い波とその他の波を見比べて見てください。黒い波の山と谷は、黄色い線の山と谷におおよそ近い位置にあるのが判るかと思います。 で、色空間の図をもう一度見てみるとやっぱり黒い線と黄色い線がほぼ同じ方向にあるのが判ります。要はそういう意味です。

といったことを踏まえて、改めてY信号とC信号を並べて眺めてみます。

Y信号とC信号を抜き出してみたイメージ図です。Sビデオ信号の走査線1本分だと思ってください。

Y信号の左端に水平同期信号がありますが、C信号上ではそれに続いてバースト信号が出ています。黒いギザギザのところです。 さっきの「位相の基準」になる信号のことですね。NTSCの規格では9個分の波をC信号に載せることになっています。

テレビは一旦バースト信号を受け取ると、その波の延長を自動的に覚えておいてくれます。自動的に暗唱しつづけてくれるって感じです。 この図で言う薄いグレーの波がそれです。

暗唱なので、実際にはこの薄いグレーの波はC信号に載っていません。受け取ったテレビ側の内部で「暗唱」しているイメージです。 バースト信号が切れてからも、バースト信号の延長となる波を暗唱していることをイメージしてみてください。テレビの内部で暗唱しつづけていると やがて少しずつズレちゃうので、走査線1本1本にバースト信号を載せてズレを随時補正出来るようにタイミングを教えてあげているわけです。

色信号について

続いてその右側のお話。Y信号上の輝度信号と並行して、C信号上には色信号の波が載ってきます。図の赤や青や黄色のギザギザのことです。 テレビがこの色信号を受信した時に、(暗唱している)薄いグレーの波形とこの色信号を比較し、波形の位相ズレを「角度」、 波の振幅を「長さ」という形で検知することで「色」を認識することが出来るわけです。

バースト信号はこんな風に「位相から色をデコード」するための「基準」として使われているわけです。

そして、SビデオのC信号には、このバースト信号と色信号の二つが時分割で載っているというわけです。

基準になる「バースト信号」の位相が0度じゃなくて180度になっているのが少しだけ解り難くさを醸し出しているのですが、 まぁ、そういうキマリなのでしかたない…

Sビデオ信号とコンポジット信号

C信号のことが解ったところで、改めてSビデオ信号とコンポジット信号のことを改めて整理してみます。

Sビデオ信号は、Y信号とC信号の2つの信号で構成されていて、コンポジット信号はY信号とC信号を合算したものです。 足す前がS信号、足した後がコンポジットです。

コンポジット信号は、いわゆるビデオ端子(黄色いRCA端子)で入出力する信号そのものですし、 これをさらに放送用の電波の周波数(東京のNHKなら91.25Mhzとか)で変調を掛けると1つの電波で飛ばすことが出来ます。 そしてテレビは受信した電波からコンポジット信号を取り出して、そのコンポジット信号からBPFやBEFでY信号とC信号に分離するというわけです。

ここまで仕組みが解ってしまえば、(Y信号を作るのは簡単なので)あとは具体的にどうやってC信号をCPLDに作らせればいいか を考えるだけですね。

まぁ細かいことを言うと規格上は色々厳密な定義があったりするんですが、今回はそれほど厳密な信号を作り出そうと 思っているわけでもないですし、それほど厳格でなくても色自体はひとまず出せるので今回は端折ります。 規格の詳細を知りたいと言う方は、私がビデオ信号関係のバイブルとして愛用している ビデオ信号の基礎とその操作法(CQ出版)あたりをご覧下さい。

作り始める前にもう1点

クロック源とサブキャリアの位相

作るべきものは大体見えてきたわけですが、あと1点考えておかないとならないことがあります。この微妙にアナログ的な位相の位置を どうやって作り出すかというお話です。

CPLDに接続するクロック源としては、ごく普通に手に入る周波数のオシレータ、14.31818Mhz(以後14.3Mhz)を使うわけですが、 これはサブキャリアの3.58MHzの1/4周期。ということは、サブキャリア1波形の間に4個のデジタルデータを出力 することが出来るわけです。これを元にしてサブキャリア信号を生成すると、単純に考えれば0度、90度、180度、270度の 4つの位相しか作り出せないことになります。

これじゃぁ、デジタル8色どころか中途半端な4色しか出せませんねぇ。考えないといけないことというのはこのことです。 どうやったら、好きな位相の波形(アナログ的な数値の角度)を作り出すことが出来るのか? クロックとクロックの中間位置(15°とか210°とか) に波の山や谷が来るような波形を作り出すことが出来るのか?

サンプリング定理と位相

1波形内に4個のデータしか出力できない状況で自由自在に位相を出力するためには、サンプリング定理(標本化定理)というものを応用します。

サンプリング定理の詳細はここでは詳説しませんのでwikipediaとかで調べていただきたいのですが、要は今回みたいに離散的なデータを 連続的に出力しながらアナログ波形を再生する時に、ある周波数以下の波形を再生するためにはその2倍の周波数でサンプリングを 行えば足りるとかいう定理です。代表例はCD、つまりコンパクトディスクですね。可聴音域22.05Khzまでを再生するためにCDの サンプリング周波数はその2倍の44.1Khzでサンプリングされています。

ただ、2倍のサンプリングレートでは周波数は再生できても位相までは再現できないので、位相までも再生するためには最低でもこの2倍より 細かい周波数が必要となります。(理論上どの程度多くサンプルすれば位相が厳密に再生できるのかは私の頭では説明できませんが) 簡単な繰り返し処理で済ませることを考えると、2.1倍とか2.2倍とかひねくれた周波数を使うと計算が面倒になったりしてお馬鹿さんなので、 普通は整数倍を使うでしょうね。

3倍、4倍、5倍、6倍あたりが候補に挙がりますが、とりあえずサブキャリア3.58Mhz の2倍に対して更に2倍の「4倍」にしておけば、 あとはそれをLPF(もしくはBPF)にかけることで位相まで再現できるはずです。市販の14.3Mhzクリスタルオシレータがそのままが使えるし… それ以外にももろもろのメリットが。

グラフにして可視化してみる

私の頭ではそのあたりのことを理屈で説明できないので、マンガで煙に巻くことにします。 このページによると、14.3Mhzで V、U、-V、-Vの順に出力するとサブキャリアで変調された波形が出力されるよ、とあるので、マトリックス処理で算出したVとU (NTSCではCbとCr)をこの4つの順序で並べてみます。それがこのグラフ。青い波は青用のCbとCr。赤い波は赤用のCbとCr。 黒い波はサブキャリアのCbとCrです。

こんな風にギザギザの波形になるわけですね。特に青や赤の線にご注目。ちょっと判り難いですが、0℃~360°の1波形の間に 4つに折れ曲がった線が連なっているのが判るかと思います。そしてこのギザギザの波をLPFに通して3.58Mhzだけを取り出すと…

こんな風にきれいな正弦波になって、赤の場合は100度、青は350度ほど位相がずれた波になります。(ちなみにバースト信号は180度ずれてますね)  これらの角度を、さっきのプロットしたグラフと見比べてみてください。各色とも同じ角度になってますよね。

これらの波形は、「f=sin(Θ+offset)」といった式で表すことができます。このoffsetの部分が上記の100度や350度にあたりますが、 マトリックス計算で求まったVとU(CbとCr)を順々に出力することによって、90°単位に限定されない微妙なoffsetの角度(位相) が表現されるって訳です。

というわけで、クロックとクロックの中間であれ、任意の位相の波を作り出すことが出来るようになりました。

なぜ、V、U、-V、-Uなのか?

ちなみになぜ、V、U、-V、-U(つまりCr、Cb、-Cr、-Cb)の順番に出力するのかというお話。

これは2行2列の行列式による回転計算(高校時代に習ったアレ)によるものです。各色の0°の時の座標(U,V) を90度ずつ回転させた時のY軸は

となるので、これら4つのY軸を順に出力すれば波形が再生されるって訳です。(Y軸なのは、offset=0°の時に正弦波となるからですね)

この90度ずつ回転という簡単な計算で済むのも、サンプリングレートを4倍の14.3Mhzにしたことによるメリットの一つです。 3倍とか6倍とか使っちゃうと回転する角度が120度とか60度とかになり、回転計算の結果に3の平方根とか出てきちゃいますからね。 とてもV、U、-V、-Uっていう簡単な繰り返しでは表現できません。(まぁ、3倍や6倍のクリスタルが簡単に手に入るかどうかは別として)

ご興味のある方は実際に計算してみてください。計算方法は、「行列 回転」などと検索してみると式が見つかります。

概要設計

扱う信号のしくみが解ってきたところで、どんな機能を盛り込んでいくのかを考えて行きます。細かいところは抜きにして、 とりあえず盛り込むべき大まかな機能を洗い出してみます。

機能洗い出し

概要図を書いてみました。まずは簡単な方を。Y、C分離のSビデオ信号バージョン。

大雑把に言うと、左側のマイコンから水平同期、垂直同期、RGB信号を受け取って、右側のテレビにY信号とC信号を送ります。 その間にある薄紫色がCPLD内部だと思ってください。

CPLD内部にはおおよそ3つの機能を持っています。一つは「マトリックス処理」。つまりY信号とC信号を生成する処理です。 残りの2つは1ライン中の「ドットクロックを数えるカウンタ」と、「サブキャリアの位相をカウントするカウンタ」。

マトリックス処理はその中身がさらに2つに分かれていて、一つは「Y信号」、つまり輝度の計算。 これはコンポーネントの時にも検討しました。計算方法は簡単ですね。

もう一つの「C信号」、つまり色信号の計算で今回の目玉。

C信号は2つの機能を持っています。一つは「バースト信号の生成」もう一つは「各位相に応じた色信号の生成」です。 バーストと色信号は同じC信号上に時分割で出力されることになります。 ラインの先頭付近でバースト信号が出力され、その後で色信号が出力される、といった具合です。なので1ラインのうち 「今どのあたりを表示しているの?」ということを認識する必要があるので、それを数えるのが図中のドットクロック用カウンタというわけです。

バースト信号出力のタイミングであればバースト信号用のV、U、-V、-U(つまりCr,Cb,-Cr、-Cb)を出力し、 色信号を出力するタイミングであれば各色に従ったV、U、-V、-U(Cr,Cb,-Cr、-Cb)を出力するわけですが、 その際、基準となる位相が何度なのかを認識するためのカウンタがサブキャリアのカウンタです。

これらの機能を設けておくことによって、RGB信号を元に輝度や色を生成したり、シンクロレベルを出力したりするというわけです。

もう一つ。Y、C混合のコンポジット信号バージョン。

大差はありません。違うのはY信号とC信号を内部で混合するということだけです。ちなみに混合といっても単なる足し算です。 今回は内部の計算・出力信号ともに5ビット精度で行っているので、CPLD内部で5ビットのフルアダーを使っています。(なぜ5ビットなのかは後述)

S信号とコンポジットでさらに違うところをあえて挙げるとすれば、コンポジットの場合は符号もつけて足し算する必要があるので C信号は2の補数表示による足し算を使いますが、一方S信号の場合は2の補数のまま出力すると正負が逆転して波形がグチャグチャになるので、 0以上の数(正数)になるようにシフトするということくらいでしょうか。(5ビットの半分なので16を足す)

といったわけで、「マトリックス処理」と「2つのカウンタ」を組み込むことにします。これらについてもう少し細かく見ていきます。

詳細設計

詳細というほどのレベルではないんですが、まぁ、VHDLを書いたり回路を組んだりするのに十分なレベルまで落とし込んでいきます。

サブキャリアの位相カウンタ

サブキャリアは、0°、90°、180°、270°…の4つのパターンの繰り返しとなります。4パターンなので2ビットで表現が出来ます。

クロック信号を入力して1パルス毎に1カウントアップし、0→1→2→3→0…とフリーランさせておきます。

ドットクロックのカウンタ

ドットクロックカウンタは、通常の3.58MhzのNTSCビデオ信号の場合、4倍の14.3Mhzで発振させると1ライン分で910クロックに相当します。

といっても実際は入力するマイコン側が1ラインの長さを生成しているので、”およそ910クロックになるだろう…”といった程度かと思います。 なので、910より少し多めにカウント出来れば足りるでしょう。10ビットカウンタなら1024カウントまで数えられるので、10ビットとします。

クロックを入力するごとにカウントアップし、水平同期信号でゼロクリアします。

Y信号計算(マトリックス処理-その1)

RGBの各信号を入力して、緑は明るめ、青は暗めに加重を掛けて輝度を出力します。といってもCPLD内部で逐次輝度の計算をするわけではなく、 事前に机上で計算した結果を「定数」化しておいて、入力が青なら青用の値を、赤なら赤用の値を、紫なら紫の値を…といった具合に出力します。

黒が入力された時には黒用の値を…といいたいところですが、もう少し細かく言うと、黒レベルとペデスタルレベルは区別しないことにします。 (つまりどちらもIRE=0)

Y信号といえばシンクロ信号が含まれてますから、H-SYNC、V-SYNCが入力された時にはシンクロレベルを出力します。 シンクロレベルを0Vとすると、黒レベルが約0.3V、白レベルが約1Vとなるようにします。

C信号計算(マトリックス処理-その2)

C信号にはバースト信号とカラー信号が載っています。ドットクロックの値を見ながらバースト信号のタイミングであればバースト信号を、 そうでなければRGB信号に従ってカラー信号を出力するようにします。

バースト信号もカラー信号も、サブキャリアのカウンタ値(=位相)に従って、V、U、-V、-U(Cr,Cb,-Cr、-Cb) のいずれかの値を出力します。各色用のVやUは事前に机上で計算しておいた値を「定数」化してVHDL上に直接指定することにします。

YC混合処理

YC混合といっても、Y信号にC信号を単純に足し算するだけです。フルアダーのライブラリを使用します。 Cは0を中心とした正負の値を取るので2の補数表示が必要になります。

一方、YC混合を行わないSビデオ出力の場合は2の補数表示で出力すると波形の上下がひっくり返った変な形で出力されて しまうことになるので、すべての値がプラス領域に入りきるようにプラス側にシフトしておいて、DA変換後にコンデンサを通して直流成分を カットすることにします。

DA変換の方法

カラーのビデオ信号幅は、シンクロレベル(-40IRE)から黄色の輝度+色信号(133IRE)の時に最大173IREとなりますが、 140IRE=1.0Vなので、電圧でいうと約1.24Vの振幅となります。

各ピンからの3.3V出力を以下のような重み付け抵抗回路でDA変換することを考えてみます。左側が最上位ビット、 右側が最下位ビットになります。

3.3VまでのレンジでDA変換すると最上位ビットが常時0でも1.65Vまでは表現できるので、1.24Vを表現するには 最上位ビットは常に0入力でOKということになります。なお、この最上位ビット用の抵抗75Ωはテレビ内部の75Ω抵抗を使うことを 前提に考えているんですが、この75Ω抵抗はテレビ内部で常時GNDに落ちているので、これを最上位ビットと考えれば 残りの抵抗は150Ω、300Ω、600Ω…と必要なビット数分だけ倍々に抵抗を増やしていけばいいことになります。

こういう風に考えることで、数個の抵抗を外付けにするだけでDAC回路が構成できるという意味で便利ですし、 もともとそんな風に手抜きをするための方便でもあります。(^_^) 上手いこと考えないと、出力回路にビデオアンプや 高速オペアンプを噛ましてインピーダンス変換をしないとならないので、テレビ内部の75Ω抵抗も上手い具合にDAC回路に 組み入れてしまうということが手抜きの最大のポイントなのでした。

DA変換の精度について

次に考えることはDACの精度…ビット数です。

マトリックス計算、及びCbCr→C信号の計算を机上で行ってみた結果、4ビットDACでは精度が少々不足するっぽいので、 5ビットDACを使ってみることにします。Y信号は4ビットで充分なんですが、いろいろ面倒なのでC信号の5ビットに合わせることにします。 (計算の式や数値は次項参照)

この5ビットDACには150Ωから2.4kΩの5個の抵抗を使います。正確に言うと、150Ωの上にさらに75Ω抵抗も DAC回路に含まれるのですが、この75Ω抵抗はテレビ内部に入っているヤツで、常時”0”固定(GNDに接続されている)なので、 実態は6ビットDACで最上位が0固定と同じ意味なので、最大電圧は1.65Vということになります。 (DAC回路を含む回路図の全体は後述)

1.65Vだと計算が少々面倒なので最大1.6Vくらいだな…とみなしてしまう事にします。多分このくらいの誤差は 許容されるんじゃないかと思います。4ビットDACなら1.6V÷16=0.1V幅、5ビットDACなら1.6V÷32=0.05V幅 となりますが、C信号は0.05V程度の精度は欲しいので、5ビットとしました。そうそう、 Y信号の中にはシンクロ信号も含まれることになる点にご留意を。

ちなみに、E24系列では600Ωの抵抗がないので、近い値として620Ωを使います。

以下に、実際にY信号とC信号を計算した値を0~31(5ビット)で表し、グラフにしたモノを記します。 まずはSビデオ。青がY信号、赤がC信号です。C信号は中心値として16を加えてシフトしています。

もう一つ。コンポジット信号です。CPLD内部でYC信号を混合したものです。

これらの数値は1ビットあたり0.05Vなので、電圧に換算すると先ほどの見積もりのとおりおよそ1.24V程度のレンジになります。 (ちょっと誤差がありますけどね)

さて、このビデオ信号をテレビに送った際に、テレビ内部でYCbCrからRGB信号に逆変換したらどの様な状態になるのか? ちょっと気になったので、表計算ソフトを使って逆変換の計算を机上で行ってみました。こんな感じになります。

そもそも0.05V精度で丸めた際の誤差があるので、それを元にテレビ側でRGBを元に戻せば誤差を含んだ発色になるはずですが、 この画を見る限り、おおよそRGBが元の色のまま表現できそうなことが判ります。ま、少し誤差がありますが… とりあえず5ビットでいいことにします。ご興味のある方は、4ビットDACでどの程度の再現性が期待できるか計算してみてください。

計算式と出力値

上述のとおり、Y信号、C信号はあらかじめ机上で計算したものを”定数”としてVHDL上に表現する必要があるので、 その数値を計算しておきます。

まず計算式ですが、まずは上でも触れたあの計算式を使ってY、Cb、Crの計算を行います。なお、RGBの値はLOWなら0V、 HIGHなら0.7Vです。

Y = 0.587G + 0.114B + 0.299R
Cb = -0.587G + 0.886B - 0.299R
Cr = -0.587G - 0.114B + 0.701R

ただし、この計算だけだとY・C合算後の電圧(+シンクロ分の0.3V)幅が先ほどの1.24Vレンジを大きくはみ出てしまうことになるため、 Cb、CRそれぞれに以下のような計算を行って、電圧のレンジ幅を狭める必要があります。

Cb’ = Cb ÷ 2.03 
Cr’ = Cr ÷ 1.14

こうすることで、Y信号にCb’、Cr’信号を加算したコンポジット信号が0V~1.24V(-40IRE~133IRE) のレンジに収まるようになります。こういう計算を行うのはコンポジット信号の時だけで、コンポーネントの時はまた別の方法で ±0.35V幅へのレンジの調整をしています。念のため。

なお、Y信号はシンクロ信号分もあわせて出力しないといけないので、各色用の電圧に対して事前に約0.3Vを加えることにします。 (ホントは黒が0V、シンクロは-0.3Vなんですが、テレビ側でペデスタルクランプを行う前提で0.3V嵩上げします。 その方が簡単に済ませられるので)

これらの計算式を踏まえて、まずは各色用の出力電圧を求めます。

次にこの電圧を0.05Vで割って、整数に丸めます。求まった数値がVHDLに定数として記載する数値になります。 縦軸横軸が逆になっちゃってたり、Pb、Prって書いてあったりと統一性が無く、判りにくくてすみません。いつも大雑把な作業なので…。

こんな感じ。これらに0.05Vを掛ければ出力電圧になるわけですね。なので、この数値をVHDL上に埋め込んでおいて クロック毎に順に出力すれば然るべき電圧が出るというわけです。

ご覧のとおりCb、Crは正負の数値(要は2の補数用)で表現しているので、Sビデオ用の出力データとしてはCb、Crを正の値にするために 16を足して使います。で、これらをグラフにすると先ほどの様なギザギザグラフの様になって出てくるわけですね。

表には書いていませんが、バースト信号の場合はV=0、U=-3です。つまり0、-3、0、3の順で繰り返し出力すればokです。

そう。このグラフにあるPb、Pr(つまりCb、CR)の数値がまさに冒頭で出てきたあのグラフ…

この座標というわけです。ん?バースト信号の座標書き間違えてますね。正しくは(-3,0)だな。まぁ、あまり細かいことは気にしないで下さい。

サブキャリアとドットクロックのカウンタの補足

実際にVHDLに落とし込んでいく前に、もう少しだけ整理しておかないとならないことがあります。

一つは、バースト信号はどんなタイミングで出力すればいいのかということです。C信号には各ドットに付随する色信号だけでなく、 各ラインの先頭部分でバースト信号を出力する必要があるんですが、どのタイミングで出力を開始すればよいのでしょうか?

この画は、水平同期信号とバースト信号のところだけを抜き出したものです。バースト信号はこの図のように、水平同期信号の立下り から数えて19サイクル経過後(14.3Mhzの場合19×4=76クロック経過後)から9サイクル分を出力することになっています。

しかし、VHDLの1モジュール内ではクロックとなる信号の立ち上がり/立下りエッヂを拾うアトリビュート('eventで)は 1個しか指定できないらしく、「1.43Mhzのクロック」と「水平同期パルス」の両方の立ち上がり/立下りを拾うことは出来ません。 モジュールを分けるか適当にごまかすかしなければならないでしょう。今回はあまり厳密なビデオ信号の生成を意図していませんので、 後者のごまかす方向で考えます。

でその方法ですが、水平同期は4.7usの長さのパルスなので、水平同期期間中(水平同期=LOWの間)はドットクロックのカウンタをゼロにしておき、 水平同期パルスが切れたところ(立ち上がり)からドットクロックをカウントする方向で考えてみます。

ここで面倒なのは、バースト信号のタイミングは「サイクル単位」で、水平同期信号のタイミングは「us単位」で規定されていることです。

タイミングの最小単位はクロック信号ですから、両方のタイミングをクロック単位に丸めてみるわけですが、多少換算誤差が生じてしまいます。 まぁ、少しくらいの誤差は目をつぶって先に進めることにします。具体的には、4.7usは(14.3Mhzで)約67クロックに相当するので、 これを引き算してタイミングを計ることにします。つまり、画の中の緑色の部分をカウントするという作戦で行きます。

先ほどの76クロックから67クロックを引き算すると緑色の長さになるわけですね。カウンタが緑の分だけ経過してから9サイクル分 (9×4=36クロック)の間バースト信号を出力すればいいわけです。

もう一つ。SCH(subcarrier phase to horizontal)と4フィールドシーケンスのお話。

SCHや4フィールドシーケンスのお話はひとまず省きますが、本来はこれらを厳格に守ろうとすると1ライン辺り910クロックとすることで ライン毎のカラー信号の位相を1ライン毎に反転させたり(1ラインあたり910クロックだと丁度1ライン毎に位相が逆転するので)、 さらには1フレームあたり4フィールド使ってフィールド間の色位相が相互に反転するように管理する必要があります。

今回はそこまでの厳格な管理は行いません。そもそもインターリーブもあっても無くても動作可能としたいし、1ラインのクロック数もマイコン側が 勝手に生成するので厳密なタイミング管理など不可能ですからね。なので、とりあえず色が出れば良いやという程度に収めます。

その範囲でも、1点だけ必要になることがあります。それは、バースト信号の連続性です。

上でもご説明しましたが、この図のように、バースト信号(赤い波線)が途切れてからも紫色の波線のように 仮想上のバースト信号は続いています。その紫色の波線と次のラインのバースト信号が図の矢印のところできちんと繋がっている必要があります。 この紫と赤の波線の位相がヘタにずれると、カラーキラーが働いて白黒の映像になってしまいます。現在のSMPTE規格によると、 位相のずれは10°以内と決められているようです。

実際のテレビではもう少しズレていても大丈夫っぽいですが、1クロックですらズレれば90°の誤差ですから、それはもうダメみたいです。 逆に、普通のクリスタル程度の精度なら、クロック単位でズレなければ大丈夫のようです。

この図では、上はOKですが下は180°ズレてしまって連続性がありません。上の「OK」の方の状態を作り出せばいいわけです。

というわけでズレを0クロックとするためには、サブキャリア位相用カウンタをライン毎に初期化してしまってはNGで、 サブキャリア位相用のカウンタがラインを跨いでフリーランしている必要があります。当然4フィールドシーケンスやSCHが 守れなくなるので、映像に(色信号起因の)シマなどが表示される恐れがありますが、 少なくともカラー信号としては有効に働けるようになります。というわけで、この方向で行きます。

ここまでくればもう簡単にVHDLが書けちゃいますし、RGB信号はOLD-PCでもいいし、AVRなどのマイコンで 適当にでっち上げてもいいので、ゴールはすぐそこです。強いて言えば、XC9536XLやXC9572XLなどに入りきるように手を抜いたので、 今回作ったVHDLでは変なタイミング(垂直同期期間)にバースト信号が出ちゃうことになるんですが、映像自体には問題がない(ビデオキャプチャーも 一応OKでした)ので、手抜きのままでOKとしました。もしかしたら、環境によって映像が崩れたりする恐れもありますが…。

VHDLや回路図など

今回作ったVHDLのスクリプトや、使用した回路図、RGB信号の生成に利用したマイコン側のプログラムなどをまとめておきます。

VHDLファイル

Sビデオ信号生成用VHDLファイル (XC9536XLではギリギリ入る感じ)

コンポジット信号生成用VHDLファイル (XC9572XLなら入ります)

これまでに長々と書いてきた内容を愚直にVHDLに書き出したのがこれらのスクリプトです。何の工夫も有りません(^_^)。

本当は定数を配列テーブルにするなどして、もっと簡単で分かりやすいスクリプトにしたいのですが、目下そこまでの技術力が伴ってません。 if文やcase文のカタマリになっちゃってます。コメント文も不十分だったり、少々変だったり…。

そのうちもっと綺麗なスクリプトに書き直したいと思います。いつになるか分かりませんけど。

Sビデオ版はY・C混合処理が不要な分規模が小さいので辛うじてXC9536XLに入りましたが、コンポジット信号版は入りきりませんでした。 どちらもXC9572XLの規模があれば余裕で入ります。

ピンアサインについて

CPLDですから普通ならお好きなようにピンアサイン出来るのですが、Sビデオ信号生成用VHDLをコンパイルしたところ XC9536XLでは規模的にギリギリで、ピンを好きなように配置出来ませんでした。というわけでC信号用の5ピンは ISEに勝手に配置させてあげることにしました。その他のピンはひとまず以下のように配置しました。

C信号は自動配置の結果、C4=43ピン、C3=8ピン、C2=33ピン、C1=12ピン、C0=22ピンといった散らかり様…。 うーん、バラバラだなぁ。まぁ、他のCPLDやFPGAにフィットさせる時にはお好きなように変えればいいし、今回は実験レベルなのでいい事にします。

なお、コンポジット信号用の方はXC9572XLを使ったので規模的には余裕があり、好きなように配置できました。こんな感じ。

RGB信号生成プログラム(AT-TINY2313、10Mhz用)

CPLDが入力するRGB信号は、TINY2313を3.3Vの10Mhzで動かして生成することにします。 以前コンポーネント信号生成で作ったプログラムを10Mhzで動くようにテクスチャーの 細かさを半分にしつつ、シンクロ信号の論理もこのVHDL用に合わせて修正しました。

RGB信号生成用ソースプログラム(TINY2313用)

RGB信号生成用hexファイル(TINY2313用)

回路図

まずはRGB信号を出力するTINY2313周りの回路図です。(縮小表示してます…クリックすると別窓で開きます)

つぎ、Sビデオ用の回路図です。先ほどのXC9536XL向けに自動ピン配置をした回路になっています。図の右下にあるのはテレビです。 テレビに対してY信号、C信号をS端子(ミニDIN4ピンコネクタ)経由で接続しているという意味の図です。

そしてコンポジットビデオ用の回路図です。こっちはXC9572XL用に手動でピン配置をした回路になっています。 右下のテレビにRCA端子で接続しているという意味の図です。

幾つか補足を。

まず、CPLDのクロック源ですが、XC95xxXLシリーズは5Vトレラントなので、5V用の14.3Mhzオシレータを使ってます。 ダンピング抵抗にはとりあえず工具箱を漁って出てきた75Ω抵抗を使いましたが、50Ω程度の抵抗を適当に繋いでください。

DAC回路はご覧のように150Ω~2.4kΩの5ビット構成の重み付け抵抗です。5ビット程度のDACなので精度的にもまぁ充分かと思います。 ちなみに、今回は実験なので±1%の金属皮膜抵抗を使いましたが、±5%のカーボン皮膜抵抗で辛うじて色は出るだろうと思います。

図をご覧になるとお判りのとおり、テレビ内部の75Ω抵抗に生じる電圧がビデオ信号になるわけです。 この75Ω抵抗も重み付け抵抗DAC回路に含めてしまう(75Ω抵抗の入力は常時=0と仮定)ことによって、オペアンプなどを使わず、 数個の抵抗だけでビデオ信号を作り出しています。

実行結果

今回作ったモノを組み合わせてみた実行結果を記します。今回はブレッドボードに適当に組んでみて、テレビに映したり、 PCのビデオキャプチャーボードで取り込んだりしてみました。

ビデオキャプチャー結果

ビデオキャプチャーボードで取り込んでみた結果です。

これはコンポジットビデオ入力の映像です。冒頭の写真と同一です。ちなみにうちのPCのビデオキャプチャーは、 テレビ側のビデオ出力端子と繋いであるので、Sビデオの映像も一旦テレビを経由して”コンポジット信号”として取り込む様になっているので、 Sビデオもコンポジットも同じようなクオリティーでしたが、テレビ画面で見たときにはさすがにSビデオの方が綺麗でした。

映像を良く見るとなんとなくフニャフニャした波が見えますが、これはTINY2313側のプログラムが出力する水平同期の間隔が規格より ちょっとズレているためのウネリが映像に載っているものと思われます。(規格上は水平同期=63.6usに対し、TINY2313のプログラム=64.3us)

あと、水色のバーが少し緑っぽい感じですが、これはキャプチャーボードの性格によるもののようです。テレビの映像はもっと水色なので。 というわけでデジカメでそこだけ撮って見た写真も貼っておきます。

実験風景

ブレッドボードで実験している風景です。上がコンポジット、下がSビデオです。意外とアッサリ。

考察と今後の展望

今回の実験を通して気付いたことなどを整理し、今後どんな風に展開していけるかとか、欠点をどうすればいいかなどを考えてみます。

ウネリについて

まずは一番目立つところから。先ほどのキャプチャー画像に載っているウネリの原因と対策について考えて見ます。

この画は、VHDLはそのままでTINY2313側のプログラムだけ少し修正した場合の映像です。ご覧のようにウネリが減少しています。

何を変えたかというと、水平同期期間の長さです。冒頭のウネリがたくさん出ている状態は水平同期が64.3us。 この映像は水平同期が63.4us。NTSCの規格ではおよそ63.4usなので、ほぼ規格どおりの長さにしてみた結果というわけです。

うねりは完全には消えてませんが、それはCPLD側が使っているクロック源とマイコン側が使っているクロック源が同一ではない と考えられます。つまり、2つのクロックの発振周波数が微妙にずれていることによって、色信号とバースト信号の波形が水平同期信号 との位置に微妙なウネリを生じさせ、それが色に影響していると考えられます。

ということは、このズレをゼロにすればウネリは消えると思われます。CPLD内部で映像信号自体を作り出すとか、 マイコン側が使っているクロックもコレを共用するなどが考えられます。(今回は面倒なのでそこまでの実験はしませんが)

なお、63.4usに近づければウネリが消え、遠ざかると大きくうねるという意味ではないと思います。カラーサブキャリア信号は 4クロックで1周するので、この4クロックの周期にマッチすれば良いということだろうと思います。 通常、色信号は1ラインごとに位相が反転するのですが、これは14.3Mhzでは2クロック分に相当します。 と考えると、この2クロックの単位でシンクロしていればウネリは消えるはずかとおもいます。もしかしたら1クロック単位で シンクロさせても消えるかもしれませんが、定かではありません。

ちなみに通常のNTSC信号で1ライン毎に色信号の位相が反転するのは、1ラインのドットクロック=910クロックを1位相分 (4クロック)で割ってみると、910÷4=227…余り2となることに起因します。この余り2というのは1波形4クロックの丁度半分、 つまり1ライン毎に半波形だけ自動的にずれるというわけです。

垂直同期信号の扱い

今回のVHDLでは、同期信号は「垂直」「水平」の2つを分けて使うことにしていますが、よーーーく考えたら 分ける必要は無かった気がします。

水平同期と垂直同期を分けた理由ですが、それはバースト信号を出力するタイミングに因ります。バースト信号は水平同期を 出力して数クロック後に出力することになるんですが、この水平同期のタイミングを検知するために水平同期信号を入力しているんですが、 実は垂直同期期間にバースト信号を出力しちゃっても悪影響は無いみたいです。

実際、CXA1645のデータシートを見ると「垂直同期期間にバースト信号が出力されるよ」という記載(図)がありました。 っていうわけで、垂直同期期間にバースト信号が出ちゃっても実害は無さそうだし、実は今回のVHDLでもすでに垂直同期期間に バースト信号が出ちゃっているので、あまり真剣に考える必要はありませんでした。

よって、マイコンで出力する同期信号はV/H別でも複合同期でもどちらでもいいです。ただ、複合同期信号の場合は 「水平同期信号側」に入力してください。あとは普通に動くと思います。(実験はしてませんけど)

いずれにしても、垂直同期期間中に意図しないバースト信号が載っていることには違いないので、厳密なNTSCの規格に則ってない という意味では注意が必要です。

Y信号とC信号の帯域について

今回作成したVHDLでは、入力したRGB信号をサブキャリアで変調する際14.3Mhzのクロックタイミングでそのまま行っています。 するとマイコン側から送られてくるRGB信号の周波数が高すぎる場合には、そのRGB信号をそのままサブキャリアで変調してしまい、 「3.58Mhzの波の形」にはならず、なんだか得体の知れない波形を作り出してしまうはずです。

早い話、あまり細かいドットの信号が入力されると、マトモな色が出なくなるということです。

3.58Mhzの波を再現するためには、普通に考えれば4個の連続したCr,Cb,-Cr、-Cbのデータを出力することで 1波形分となるはずですが、このページによると 半波形分でも色が付くと記載されているので、実際は2個連続するデータが並べば色が付くはずです。

今回はマイコン側からあまり細かいドットを出力していないので、変な発色になってしまうことは無かったのですが、 もしマイコン側からもっと細かいドットを出力する可能性があるとしたら、RGB信号を一旦ラッチしておいて、 最低でも2個の連続したデータがされるように連続性をVHDL内で保証してあげるなどといった対応が必要になるかと思います。 (例えば、ある色のCrを出力した直後に入力のRGB信号が変化しても、その変化する前のRGBを一旦ラッチしておいて、 実際に出力するのは変化前の色の-Cbとするなど)

そうして、C信号の帯域を落としてあげる必要があるわけです。なお、実はY信号も帯域が規定されている(4.2Mhz)んですが、 とりあえずC信号と一緒に処理しておけばいいのかな、という気がします。

これらによってドットの細かさという意味では劣化するんですが、マイコンが登載するメモリ量を考えるとそもそも そんなに細かいドット情報を保持していられないのでは?と。先ほどの写真、一番下のドットピッチでもきちんと色が載っていることを考えれば、 この程度でもそこそこの表現力があるってことで…

4フィールドシーケンスやSCH管理について

4フィールドシーケンスというのは、インターレース処理とサブキャリアによる変調を組み合わせた場合に考えないといけなくなる面倒なお話です。

インターレース表示(白黒)では、2フィールド1組で1フレームということになります。さらにカラー映像となるとカラーサブキャリア信号の 位相も加味する必要があり、連続する1フレームの先頭の位相が逆転するように信号が作られる必要があります。つまり、連続する2フレームの 映像…つまり4フィールドでようやく1枚のカラー映像になるということです。

このように連続するフレームで位相が逆転することによって、C信号に起因する輝度への影響が抑えられます。

また、2つの映像信号を切り貼りして編集するような場合(いわゆるA-Bロール)に、この4フィールドシーケンスがきちんと 管理されていないと、映像が切り替わった時にもう片方の映像の色相が逆転してしまうなどのエラーが生じます。

今回はただ「表示されればいいや」というレベルで作ったので、そんなことまで全然管理出来てません。

まぁ、そうは言っても昨今のビデオ編集環境といえばPCにキャプチャーしてノンリニア編集を行うことが一般的になっているでしょうし、 このようなPC上のデータではすでに(サブキャリア変調から)復調されているので、ノンリニア編集を行う上ではあまり気にしなくても よさそうです。

それよりも、インターレース表示された信号をPCに取り込んだ際の弊害の方が大きそうですよね。インターレースはいずれなくなっていく 運命にあるかもしれません。

もう一つのSCH管理ですが、SCHというのはバースト信号と水平同期信号の位置関係の話です。水平同期信号の立下りから バースト信号の開始までにどのくらいの時間間隔を設けるかというキマリなのですが、今回は結構適当に済ませてます。 でもまぁ色は出てますし、上記同様にPCにキャプチャーしてしまえば気にする必要もないでしょう。

これらを厳密に管理したいという場合は、水平解像度をきちんと910クロックとし、インターレースを行い、1フレームごとに サブキャリアの位相が反転するように保つ必要があります。しかもマイコンからの信号を受け取って…というやり方だとCPLDとマイコンの クロックにズレが生じてしまうので、映像信号自体もCPLD内部で生成する必要があるでしょう。さすがにそこまでやると XC9572XL程度ではとても入りきりません。

多色化について

今回はとりあえず8色のRGB信号を目指してみましたが、R・G・Bの各パラメータをもっと多段階に指定できれば いわゆる総天然色表示も可能なはずです。

まぁ、マイコンで総天然色というとメモリ容量的にアレなのであまり追求しても仕方ないのですが、せめてRGB各2ビット~3ビット 程度に多ビット化し、準アナログRGB的な表示には持っていきたいところ。これならマイコンでも辛うじて扱える範囲だろうと思うので。

XC9572XL程度の規模だと多ビット化するのは少々心許ないですねぇ。8色だと、case文のwhen節が8個で済むのに対し、 2ビット×3=64色だと64個。仮に「配列」を使ってもっとスマートに書いたとしても、スクリプトが短く見やすくなるだけで、 コンパイル後の規模が小さくなるという意味ではないでしょうから、やはりXC9572XL程度では太刀打ちできそうに無いな…。

やるとしたらもう少し大きな規模のCPLDを使って、単機能ではなくCPLD自体が映像を生成するようにしちゃうことでしょうか。

多色化するにあたってのDAC回路ですが、多分5ビットDACのままでもある程度はふんばれるのではないかと思ってます。 RGB各2~3ビット程度なら。もっとビット数を増やそうとすると、そもそも重み付け抵抗回路では不十分でしょう。

一方、アナログRGBについて。CPLDは直接アナログ信号を読み込めませんし、仮に超高速AD変換を噛ませたりしても あまり嬉しい結果にはなりそうにありません。それよりも、アナログ信号はアナログ信号のままオペアンプでマトリックス計算 してしまう方が楽でしょう。マトリックス計算をして出てきたCr,Cb,-Cr、-Cbの4つの信号をサブキャリア周波数で 変調する(アナログMUXなどで4つの信号を順々に切り替えるなど)という方が現実的です。いずれこの方法は試してみたいと思います。

VHDLの作りについて

マトモに何か作ったのは今回が初めてなので、ありあわせの知識を使ってとりあえず書いてみた、というレベルです。

見易さとか、動作安定性とか、テスト規模とか考えてないし、シミュレーションした結果を見ると、髭が生えているみたいです。

まぁ、後続にマイコンのI/F等が繋がっているわけではないし、映像自体はフィルター掛けた状態で取り込まれるはずなので、 あまり気にしないことにします。

いずれにしてももうちょっと上達したいな。

髭剃り

VHDLの動作をシミュレータで眺めると、1クロック毎に出力波形に髭が生えるのが見えて気持ち悪いと言う旨を ブログに書いたところ、A.C.さんからご指摘頂いて、 シンクロナイザを入れてみたら綺麗に剃れました。なので、そのVHDLも載せておきたいと思います。

改善版のVHDLファイル

シミュレーションの結果

使用前

使用後

A.C.さん、ありがとうございました。

ちなみにシンクロナイザをつけた場合のリソース消費量ですが、registersの使用量は増えますが、product termsの使用量は変わらないみたいです。

追記:alteraのMAX2で実験

コンポジットビデオ用のVHDLをそのまま使い、alteraのMAX2ボードでもカラーコンポジット表示が出来るか実験してみました。

テスト用のボードには、オプティマイズ製の MAX2CPLDボード(EPM570T100C5N登載)を使用しました。

実験風景

ブレッドボードでこんな感じ。結構すっきりした風景。

配線は、Quartus2の画面で適当にアサインしたピンにあわせてブレッドボード上で適当に済ませます。オシレータは、 手元に3.3V用が無かったので5V用のオシレータを3.3Vで無理矢理動かしました。一応発振していたようです。

ご覧の通り実験したのはコンポジットだけで、Sビデオは試してないんですが、多分Sビデオも同様動くかと思います。

実験結果

特に問題なく表示できました。

こんな感じ。XC95xxXLよりも綺麗に表示されている印象。例によって黄色と緑の間が黄緑色っぽく表示されてますが、 これはビデオキャプチャーのせいで、実際のテレビ映像は↓こんな風に水色です。(デジカメ画像)

波形をオシロで眺めてみる

この間せっかくpicoscopeを買ったので、波形を眺めてみました。

まずは、水平シンクロ付近~バースト信号のあたりのアップです。

ちょっとノイズが混じってますが、まぁ、想定どおりの波形でなにより。

次。走査線1本分の波形を取り出してみます。こんな感じ。

1Vより上がスパっと切れているのは、オシロのソフトの使い方に慣れてないせいです。波形が若干フニャフニャしているのは オシロの取り込み方のせいなのか、出力波形がホントにフニャフニャしているのか判別できないのですが、テレビ画面を眺めた感じでは 発色や輝度にノイズ的なものがあまり現れていないことを見ると、なんとなく前者のような気がします。 まぁ、映像を眺めた感じでは普通にRGB信号がカラーコンポジットに変換されている様子が見て取れます。

まとめ

以上、カラーNTSC信号の仕組みやその遊び方について長々と纏めてきましたが、何とか想像に近い映像信号を出力できるに至ったので、 ひとまずこの実験はこれで完了としたいと思います。

多色化、完全アナログ化とか、もうちょっと高画質化とか課題は幾つかありますが、今回書いたVHDLをちょこっと弄れば 色々応用は利くんじゃないかなという気がします。

あと、もう少しやるとしたら、やっぱりCPLD内でビデオ信号の生成から出力まで全部詰め込んでしまうということでしょうかね。

以上で実験をしめくくります。