PIC AVR 工作室->TopPage->実験くん->マイコンで64色アナログコンポーネントビデオ表示
マイコンで64色アナログコンポーネントビデオ表示
今回の目論見
以前、 TINY2313とかから出力したRGB信号をオペアンプでコンポーネント信号(YCbCr信号)に変換してテレビにカラー表示する実験 をしましたが、 今回はその続き。
RGBを各1ビットずつ増やしてトータル6ビットカラー(64色)の表示に挑戦しようという目論見です。 64色といえばRGB各2ビットずつ。PC上でシミュレーションしてみると、こんな感じになります。
ちなみに、丸印がついているところは白~灰~黒のいわゆる「色彩が無い色」。 グレーで4段階の階調が得られる訳ですが…果たしてゼビウスが表現できるのかどうか…難しい???
でも、橙やピンクが表示できるってことは、「グズタ」や「ピンキー」は表示できるって事。ok、ok。 8ビットマイコン程度でゲームとか作るなら64色程度出ればそこそこでしょうし、8ビットを超えると1命令で出力できなくなっちゃう (タイムラグが出る)。それ以上を求めるならむしろCPLDやFPGAって事になるでしょうから、6ビットでいいことにします。 6ビットなら、残りの2ビットを使って「スプライトと背景の合成」用とかの制御にも使えるだろうし…。
RGB信号の生成用マイコンには何を使ってもいいんですが、今回は過去資産を使いまわしする意味でTINY2313を使うことにしました。 TINY2313の出力ピンから6ビットのRGB信号を出力し、オペアンプでコンポーネントビデオ信号にしてしまおうという作戦です。
せっかく何か作るなら、もっとメモリの大きいmegaシリーズとかPIC24シリーズとか使って、 動くアナログカラー映像に応用した方がぜったい楽しいと思います。オペアンプ周りの回路は静止画も動画もちゃんと動くので、 動画にしたい人はアナログRGBの動画出力用に使ってください。
今回の作戦
課題
以前の8色表示の実験では、 YCbCr信号の生成にオペアンプを使って4入力とか5入力とかの加減算回路を組んだわけですが、 オペアンプ1個でこの位の入力数で加減算回路を組もうとすると、物凄く大変な計算をしないといけないのは周知の通り。
まぁ、デジタルRGBなら各1ビットなら3ビットなので、 それにシンクロやバースト信号を混ぜても4~5入力だからなんとかゴリ押しが利くレベルでした。
一方アナログRGBともなると一般にはビット数が大量になっちゃうので、あまりビット数が多くなるともはや非現実的になっちゃう… ビット数が程々に少なくて、かつオペアンプの加減算回路で処理出来ちゃう程度で、マイコンとの親和性がよければある程度使いものになるかと。
マイコンで扱える程度のビット数でアナログRGBが実現でき、かつ複雑怪奇な加減算回路が出来ること。両立できなければいけません。
作戦
キーワードはリニア回路。比例関係が成り立つ回路のこと。 以前の8色RGBでやっとこさ計算したオペアンプ周りの抵抗値をリニア回路と見なして利用します。
リニア回路なら重ね合わせの理が成り立つので、RGBの各入力側抵抗を2つ(2ビット分)に分割して多ビット入力が可能としつつ、 合成したら元の8色用と同じ抵抗値と同じになるようにすればよい、という考え。 具体的には抵抗値を1対2の比率にしておいて、その抵抗を並列接続にしたら元の抵抗値とするわけ。
回路と抵抗計算
何と言っても、今回の最大のポイントはオペアンプ周りの抵抗計算。そのあたりをいかに手抜きするか…です。
まずは復習から
以前の8色表示の実験で書いたあの回路図の復習から。(クリックで別窓に開きます)
この様に、RGB各1ビットの情報がマイコンから出力されてます。色の出力ありなら5V、無しなら0Vがオペアンプの入力側抵抗に掛かりますが、 これをオペアンプの加減算回路を通してY、Cb、Crの各信号に変換している訳です。
2ビット化の考え方
今回はこのRGB信号を2ビット化します。RGBの各出力信号を2ビット化しつつ、それを入力する側の抵抗値を1対2の比率となるようにします。 (クリックで別窓に拡大表示)
例えば、Y信号の入力に繋がっているR(赤)用の抵抗は11.6kΩとなっていますが、 これをおよそ16kΩと33kΩの2つの抵抗に分け、16kΩの方を上位ビット、33kオームの方を下位ビットとして接続します。
(16kΩと33kΩを並列接続とすると合成抵抗は16×33÷(16+33)=10.8kΩとなるわけ… まぁ、ちょっと誤差があるけどE24系列で纏めちゃいました)
同様にY信号用のG(緑)は8.2kΩと16kΩで合成5421Ω(≒5685Ω)といった具合に、 各信号のRGBすべての入力側抵抗を2つの抵抗値に按分していったのが上記の回路図というわけ。
言うまでも無く、シンクロ信号は1ビットのままでokです。
実際に実験で使った抵抗値
なお、今回実はコンポーネントビデオの表示をするのがゴールではなく、言うまでも無くSビデオやコンポジットで表示したいわけです。
するとバースト信号や3.58MHzの変調(14.3MHzでMUXを切り替える)用クロック等も必要になるので、 ソフトウェア上はその辺の配慮も必要ですが、一方今回買いこんで来た抵抗はコンポジット用に計算したものだけなので、 このコンポジット用の抵抗から近いものをチョイスして流用してみました。
なにしろ近い値の物を適当に選んだだけなので、結構誤差があるものの多少発色が狂うのを覚悟の上、実験と割り切ってこんな抵抗値で実験です。↓
2つの43kΩ抵抗だけはコンポジット用の中から流用できなかったので、別途用意しました。
マイコン周りの回路
マイコン周りはこんな感じになります。
RGBが各2ビットずつになっています。クロック出力とバースト信号はコンポジット表示の実験をする時に使うものです。 PWM出力ピンがRGB出力で塞がってしまったので、PWM出力を使ったチャージポンプの負電源生成がつかえないのが残念。 まぁ、どうせならもっとピン数の多いマイコン使って、ちゃんとした映像を出力したほうが楽しいでしょう。MEGA168とか。
マイコンにしてもオペアンプにしても、電源ラインには適宜パスコンを入れておいてください。
抵抗計算のまとめ
基本は、1ビット用に計算した抵抗値を1:2に配分することです。そして、その抵抗2つを並列で合成すると元の1ビット用抵抗の値に戻る…と。
考え方自体は結構単純かと…。
サンプルソフト
64色カラー出力デモ(tiny2313用)
冒頭の64色を順に表示するだけのプログラムです。これまでに散々作ったカラーバープログラムの焼き直しです。
左上が白。白の色コードは10進数で63です。そこから右や下に移動するにつれて1ずつ少なくなっていて、右下で黒=0になります。
ちなみに緑が上位ビットの2つ、次が赤の2ビット、最後が青の下位2ビットというプログラムになっています。 右クリックでダウンロードして使ってください。って言うか、動く映像を出力するプログラムに書き直したほうが楽しいと思います。
出力結果
実際に表示してみた結果です。
冒頭の写真です。テレビのD端子に繋いで表示した画面をデジカメで撮ったもの。 (コンポーネント信号は普通のビデオキャプチャーボードで取り込めないって言うのが難点…)
計算通りの抵抗値ではなく、上述の通りコンポジット用に買ってきた抵抗から近い値の物を流用して実験してみたので、 左上が「白」より水色っぽいなど少し発色が狂っている感がありますが、まぁおよそ思ったとおりの発色が出て一安心。
考察とまとめ
考察
今回はRGB各2ビットずつの6ビットRGB=64色同時発色としました。
発色数については色々考えてみたんだけど、結局64色ということにしました。理由は幾つかあります。
理由その1:精度
ビット数を増やせば増やすにしたがって、理論上発色数は幾らでも増やしていけます。 でも現実的には発色数のメリットよりもデメリットの方が大きくなります。その一つは、重み付け抵抗による電圧値の生成。
抵抗値の比率で電圧が生成される訳ですが、その抵抗値には誤差があり、 最上位ビットの持つ誤差が下位ビットの大きさを上回るとそれより小さなビットは誤差の範囲に入ってしまって意味をなさなくなります。 R-2R抵抗や重み付け抵抗を使う場合、これは避けられないデメリットとなります。
今回はE24系列のカーボン抵抗(誤差5%)を使ったんですが、RGB各2ビットずつなら埋もれることも無いだろう…と。
理由その2:データ量
ビット数を増やせば発色数が増えますが、同時にデータ量も増えます。 まぁ、マイコンに入りきるデータ量ならどれだけビット数を増やしても良いといえば良いんですが、実際はもっと現実的な壁にぶち当たります。
PICやAVRなどのラインナップのうち、8ビットマイコンでは一度に出力できるビット幅はせいぜい8ピン以内。 例えばAT-MEGA168ならDポートのPD0~PD7の8ピンなら1命令で出力が出来る…という意味です。
逆にいえば、8ビット以上のデータを出力しようとしたら1クロックに収まらないということになります。
1ドットの色が2クロック以上に跨るということは、発色が異常な状態が1クロック分存在することになります。 まぁ、外部にラッチ回路などを組んで上手く制御してやれば何とかなるかもしれませんが、 そこまでメンドウなことやるなら最初からCPLDを持ち出したほうがラク。ってことで、8ビット以内で現実的な出力幅を考える必要があるでしょう。
で、8ビット丸々発色用に費やしてもいいんですが、スプライト表示と背景表示を別チップに負荷分散させるとか考えると、 信号合成のことを考えないといけなくなるので合成用の制御信号も必要になってきます。 (白黒映像ならOR回路で合成すれば済みますが、カラー信号はそういうわけに行きませんからね)
具体的には、8ビットのうち1ビットを「黒」なのか「透明」なのか識別する信号に充てるようにしてしまいます。 そしてこの信号を外部のロジックIC(具体的にはマルチプレクサIC)で入力し、 スプライトを表示するのか背景を表示するのかという切り替えに使うことにします。
あともう1ビット。スプライトと背景のどちらが近くてどちらが遠くにあるのかというZ軸を表す制御するビット。 これを使うと、背景の手前側に表示したり背景の背後に隠れるように表示したりという制御が可能になります。 これらの2ビットを確保すると残りは6ビット。なんだか予定調和のようにRGB各2ビット確保できました。
というわけで、2つ以上のカラー信号を一旦合成処理してからオペアンプを通すという流れで考えると、 RGB各2ビットずつで6ビット、それに制御用2ビットを加えて計8ビット以内で留めると言うのが吉のようです。
まとめ
言うまでも有りませんが、今回のプログラムは動画ではなく静止画しか出力しない「つまらないプログラム」です。 オペアンプ周りについては静止画/動画は問うてはいないので、プログラムで動画を出力すれば普通に動画が出ます。
目指すのは動画です。念頭にあるのはスプライトや背景表示のカラー版を出力して、映像を合成して、 それをコンポジットでグリグリ動かすこと。かつてのファミコン程度の表示ができることを目指したいところ。
ということで、コンポーネントはそのための一つのステップの位置付け。カラーコンポジットで背景を表示しながら、 沢山のスプライトをグリグリ動かせる様にしたいわけです。黄金の80年代が現代のマイコンで蘇るってわけ。(黄金ってなんだ?)
録画やキャプチャーに拘らなければコンポーネント出力にしてD端子でテレビに繋ぐのが一番簡単なので、 今回の回路を使っちゃうのが一番ラクチン。5Vマイコンで単純に何か表示するだけならこの抵抗値をそのまま使っちゃえばok。
コンポーネントとコンポジットをダブルで用意しておけば、用途ごとに選択肢が増えていいかな…と。
なんにせよ、オペアンプ周りの抵抗計算はリニア回路ってことで抵抗値を按分すればいいってことが判ったのが最大の成果。 これさえ判ってしまえばコンポジットのCb、Cr、-Cb、-Crの計算も同様に出来るわけで、 ようやくカラースプライト表示への技術的見通しが。
今回はコンポーネントでアナログ64色表示の確認が出来たという結果を以って「成功成功」と自画自賛して締めくくります。