AVR ATtiny2313 ビデオ出力 ブロック崩し
2008年11月 前回のAVR ATtiny2313 ビデオ出力テストの続きで、AVRを使ったビデオ信号出力が テーマの製作です。アプリとしてブロック崩しを作りながら、何が問題になるのか、 どう解決したかを紹介します。ブロック崩しはスイッチ操作で、アナログコントロールの 研究は次回の予定です。 回路図と部品一覧、ソフトを公開しています。 ※画像拡大はここをクリック。 |
ビデオ出力テストの続き
↓ビデオキャプチャ画像 ↓クリックで拡大 |
|
ATtiny2313内蔵8MHz セラロック20MHz |
コンポジットビデオ信号(NTSCビデオ信号)を作るにあたり、まずはクロックをAVR内蔵クロックから外部供給へ変更します。動作速度を速くしたいことと、安定したクロックを供給することが目的です。 AVR ATtiny2313 ビデオ出力テストの映像をPCでビデオキャプチャしたものが左・上の画像です(6行表示に変更)。ATtiny2313内蔵クロック8MHz。なんとなく規則性があるギザギザで乱れています。 20MHzのセラロック(セラミック発振子)に変更したものが左・下の画像です。乱れなく文字が出力されます。クロック任せで処理能力も上がり、1行で6文字表示は余裕でした。 ビデオ信号の出力には比較的シビアなタイミング制御が必要です。 時計や周波数カウンタやUSB制御など、特に安定したクロックが必要なときはクリスタル(水晶振動子)/クリスタル発振器を使いますが、ビデオ信号の出力ではセラロックで十分目的を果たせるようです。 ※クリスタル+コンデンサより安価なセラロックを使いたかった。 |
「A」の乱れが目立つ 右へ行くほど乱れる 1行3文字が読める限度か 読めそうにない文字も |
ここまでで表示していたソフトの内容を整理し、作り直し、改めて出力実験したものが左・1番目の画像です。 1文字出力する処理を変更して、これまでより文字幅が狭くなっています。幅を決める具体的な制御はしていません。処理時間がそのまま幅表現となって現れます。 ここで微妙な文字の乱れに気付きます。 文字は5x5のフォントで「A」は下図のようになっていますが、 □□■□□ :1ライン目 □■□■□ :2ライン目 □■■■□ :3ライン目 ■□□□■ :4ライン目 ■□□□■ :5ライン目 出力された映像では3,4,5ライン目が1,2ライン目より狭いです。 走査線1ライン毎にもわずかなブレが見えます。 これをハッキリ見るため、ソフト側で文字幅を広げる調整をしたものが左・2番目の画像です。1行10文字にしました。 映像の右へ行くほど乱れが大きくなります。しかもズレ方がわかりません。例えば同じ色が続くと狭くなるとか、白は広がるとか分かれば対策できるかもしれませんが、そういったルールが見えません。 走査線1ライン毎のブレも1番目の画像とちょっと様子が違うようです。 「A」「V」「R」ばかりで飽きたので数字、アルファベットA-Z、記号のフォントを作ってテスト表示したものが左・3,4番目の画像です。 1行3文字くらいなら乱れが目立ちません。全部出力してみると、やはり乱れがひどく、右半分くらいでは読めそうにない文字、記号があります。 1行10文字5行表示にして、TVメッセージボードや、マイコン開発のデバッグ出力をTVに、などと考えていたのですが、これでは役に立ちません。お手上げ、放置か? ……実は最初から、WinAVRの強力な最適化が原因だろうと見当は付いていました。 ここまで最適化オプションを「-Os」か「-O2」にしていました。最適化を切って比較したいところですが、「-O0」だとプログラムサイズが2KBを軽く超え、ATtiny2313に書き込めません。 アセンブラを使わず何とかCでねじ伏せようとソフトをいじくり回した結果、やはりCで記述してるだけでは解決できないという結論に至りました。 ※一週間くらい格闘したが、無駄な時間とは思っていない。 |
ブロック崩しを作る
回路図とプログラム
この先アナログコントロールの実験があるので、現段階では基板で作らずブレッドボード上に組んで完成としています。 回路図はここをクリック。 部品一覧はこのページの一番下にあります。 プログラムはここをクリック。(VBlock ver1.10) プログラムはZIPで圧縮してあります。解凍するとVBlock.c(プログラム本体)、aryPaint.s(ブロックの描画関数)が出てきます。 AVR StudioでVBlockというプロジェクトを新規作成し、2つのソースをプロジェクトに加え、最適化オプション「-O2」でビルドしてください。ソースが不要な人は同梱のVBlock.hexをATtiny2313に書き込めばok. |
|||||||||||||||||||||
ブレッドボード上に組んだ回路 拡大 (動画) ビデオ出力 ブロック崩し (*2)…次回製作予定のアナログコンパレータ(を応用したA/Dコンバータ)利用時にもう一つ割り込みを使いそうで、そうするとスリープを利用する方法は使えなくなります。描画タイミングと関係なしに、アナログコンパレータ用の割り込み発生時点でスリープが解除されてしまうからです。 それを見越してスリープを使わなかったのですが、今回は今回、次回は次回で割り切りました。 さてアナログコンパレータ、多重割り込みで行けるか、割り込みを使わずに応用できる方法があるか……どうなりますかね。 |
回路について ・白レベル1.0V(これ以下でこの付近の値。例えば0.9V) ・黒レベル0.286V(これ以上でこの付近の値。例えば0.3V) ビデオ信号を生成する抵抗2本の値はVCCを5Vとして決めています。3V(乾電池2本)で動かすならR1=680Ω、R2=220Ωでどうでしょうか。試していませんが。 [Video Output] H=3v, L=0v
現段階ではボリューム(可変抵抗)ではなくスイッチにしています。操作性は良好、ハードもソフトも簡単です。 プログラムについて 水平同期周波数15.734kHz→1ラインの周期は63.56us、これをタイマ/カウンタ割り込みで作り、描画処理しています。走査線1ラインの開始でまず描画、続いてデータ処理(ボールやバーの移動、ブロックとの当たり判定)、の繰り返しです。 データ処理後、次のラインの描画開始(割り込み発生)までスリープ状態にしています。実は開発後期までスリープを使わず、割り込み処理完了時にフラグを立て、main()側while(1)内でフラグ監視という方法をやっていました。(*2) しかし最適化の影響なのか、それだと描画タイミングが不揃いになり、画面が細かくブレました。ブレを抑えることはできましたが消すことはできませんでした。 コンポジットビデオ信号は本来なら偶数フィールド/奇数フィールドで1画面(525ライン)を構成しますが、この開発では1フィールド(262ライン)で1画面としています。そのためTV画面で見ると走査線の隙間がよく分かります。 アセンブラのソースはブロックを描画する関数です。配列に格納した色番号を見て、その値によらず出力までのタイミングが等しくなるよう調整してポートに出力する、という処理内容です。 この関数ではプログラムの対称性がポイントになります。 配列には色番号「0,1,2」が格納されていて、この判定を次のようにしています。 if (値==0) 色番号0の処理へジャンプ →出力処理へ if (値==1) 色番号1の処理へジャンプ →出力処理へ if (値==2) 色番号2の処理へジャンプ →出力処理へ それ以外の値は出力処理へジャンプ 値が0,1,2どれでも同じ判定でその後の処理経路も同様です。この判定順では値が小さいほど先に出力処理へ到着することになりますが、対称性のおかげで時間差が等しくなるのでタイミング待ちの処理が簡単になります。 一方、次のように判定した場合… if (値==0) 色番号0の処理へジャンプ →出力処理へ if (値==1) 色番号1の処理へジャンプ →出力処理へ それ以外の値は色番号2として出力処理へジャンプ 値が0,1のときと2のときでは判定と処理経路が異なり(対称性が損なわれた)、出力処理のタイミングが合わせにくくなります。 |
||||||||||||||||||||
ゲーム内容的には ボールの斜め反射が45度だけなので、単調なプレイになります。若干の小細工はしてありますが。 今回の製作においてゲームの作り込みは二の次です。次回製作時に余力があれば改良しましょう。 |
参考回路(予告編?)
ボリューム(可変抵抗) |
スイッチではなくボリューム(可変抵抗)で操作する回路も作って試しました。ATtiny2313のアナログコンパレータ機能を使ってみる実験です。 ボリュームを左へ回すとバーはずーっと左端まで動き、右へ回すとずーっと右端まで動きます。A/Dコンバータではないので、途中の位置で止めることはできません。ゲームとして問題ありです。 回路図はここをクリック。 ボリュームはBカーブのものを使います。軸の回転量に比例して抵抗値が変化するものです。 ちなみに音量調節で使うタイプはAカーブです。これは抵抗値が対数的に変化します。 PB0(AIN0)に5V(VCCの電圧)を二分した電圧を入力します。これが基準電圧になります。 PB1(AIN1)にはボリュームで0〜5Vまでの電圧が入力されるようにします。 これで2.5Vを境に左/右の判定ができます。 |
プログラムを変更します。 ポートやタイマ/カウンタの設定をしている付近でアナログコンパレータの設定をします。 //アナログコンパレータの設定 ACSR = 0b00000000; キー入力判定のところを次のように変更します。 //アナログコンパレータで操作判定 barDirecX = DIREC_NEUTRAL; if ((ACSR & _BV(ACO)) && 0 < barX) //if (AIN0 > AIN1), _BV(ACO)→(1<<5) { barX--; barDirecX = DIREC_LEFT; } if (!(ACSR & _BV(ACO)) && barX < FIELD_W - BAR_W) { barX++; barDirecX = DIREC_RIGHT; } |
部品について
基板ではなくブレッドボード上に組むとします。 そのため電源コネクタやISP用のピンヘッダは部品一覧には書きませんが、 必要に応じて用意してください。 抵抗は R2 470Ω [黄紫茶金] の値を確かめるときに注意することがあります。 抵抗に印刷された色で紫と茶の区別が付きません。光にあててよーく見ないと分かりません。 お店のケースの中に間違った値の物が混ざっていることは無いと思いますが、 買うときに念のため確認してください。 クリスタル発振用のコンデンサの値はATtiny2313のデータシートを参考にしてください。 22pFでよいと思います。 ただのセラミックコンデンサと積層セラミックコンデンサのどちらでも構いません。 今回の製作物においてコンデンサ内蔵のセラロックで正常に動作しています。 コストの面からこちらをお勧めします。 回路図の点線囲みの部分、「クリスタル+コンデンサ2個」をセラロックに置き換えてください。 RCAジャックはお馴染みの黄色いビデオケーブルを差し込むジャックです。 基板実装用やケース取り付け用などの形状がありますが、 ブレッドボードに取り付けるならどっちもどっちです。好みで決めてください。 |
部品名 | 部品番号 | 値 | 個数 | 参考価格/備考 |
AVR(マイコン) | ATTINY2313 | ATtiny2313 | 1 | 100円(秋月電子) |
抵抗 | R1 | 1.2kΩ [茶赤赤金] | 1 | 1個5円/100個100円 |
抵抗 | R2 | 470Ω [黄紫茶金] | 1 | 1個5円/100個100円 |
抵抗 | R3 | 75Ω [紫緑黒金] | 1 | 1個5円/100個100円 |
積層セラミックコンデンサ | C | 0.1uF [104] | 1 | 10個100円 |
タクトスイッチ | SW1,SW2 | 2 | 10個180円 (千石電商 店頭価格) |
|
RCAジャック | J | 黄色 | 1 | 30円 |
クリスタル | XTAL | 20MHz | 1 | 10個500円(秋月電子) |
(積層)セラミックコンデンサ | クリスタル発振用 | 22pF | 2 | 1個20円 |
セラロック | 点線囲み部分 | 20MHz | 1 | 40円 |
【参考】ボリューム操作のテスト | ||||
ボリューム(可変抵抗) | VR | Bカーブ10kΩ | 1 | 90円 |
抵抗 | R4,R5 | 10kΩ [茶黒橙金] | 2 | 1個5円/100個100円 |
次回は… ATMEL社のサイト内、Application Notesのページに、 アナログコンパレータをA/Dコンバータに応用する方法が紹介されています。 http://www.atmel.com/dyn/products/app_notes.asp?family_id=607#General%20Purpose AVR400: Low Cost A/D Converter 次回はこれに挑戦する予定です。上手く応用できるかどうか楽しみです。 |