2009年1月20日火曜日

TinyでPONG!(ソフトウェア2)

映像出力の仕方を具体的に説明します。

映像データを出力ポートに滞りなく書きこまねばならないのですが、どのくらいの速度でなければならないのでしょう。水平方向192ドットを、水平映像期間48μs=384クロックで出力するので、1ドット当たり2クロックにすればよいのです。

この速度はプログラムをいくら効率よく書いてもループ(分岐)を使った時点で達成はできません。分岐命令は、後方分岐(ループ)の場合それだけで2クロックを消費してしまうからです。そこで、ループを「展開する」ことにしました。ループを展開するというのは同じ命令をループの回数だけずらっと並べて書くということで、当然プログラムの容量は増大します。

ループを展開するとはということです。簡単ですね。

ループの展開をすれば1ドット出力に2クロックを使うことができます。しかし2クロックしかありませんから、これとてもいくつかの工夫をしなくてはなりません。
  1. 汎用レジスタにあらかじめ映像データを用意しておく。
  2. 1つめのクロックでポート出力を完了させ、
  3. 次の1クロックで汎用レジスタ内の映像データを1ビット(左)シフトする。
直前の周期であらかじめ1行分の映像データを汎用レジスタ(群)に仕込んでおくことで上記のアイディアが実現できます。これは汎用レジスタが32本と多いAVRだからこそできる技で、そのうちの24本をこの目的のためにつかいます。24本×8ビット=192ドットですから。

また、出力命令のOUTは1クロックで完了するのですが、8ビットいっぺんに出力されます。8ビットマイコンなんで当たり前のことですね。その中の1ビットだけ出力したい(変化させたい)という場合、通常はポートを8ビットで読んで→狙ったビットをクリアし→狙ったビット以外の部分を0でマスクしたデータと論理和し→ポートに書き戻すとか、ビットクリア/ビットセット命令を分岐で使い分けたりと結構面倒なもので、とても1クロックで済むような話ではありません。

そこで、出力ポートの他のビットを無視すなわち未使用にすることにしました。そうすると面倒くさい1ビット書き換え処理が全く不要になり、単に8ビットいっぺんに出力するだけで済んでしまうのです。以前「映像出力がポートの最上位ビットであることと、同じポートの他のビットに出力が割り当てられていないことがとても重要」と書いたのはこのためだったのです。

これらを図で示すと下記のようになります。

プログラムの中でこの処理をやっているのはファイル"draw.asm"の以下の部分です。ループの展開はまだるっこしく読みにくいのでマクロを使っています。

8ビット分のループ展開(マクロ定義)

.macro vout8px
out PORTB, @0 ; +1=1 output bit7
lsl @0 ; +1=2
out PORTB, @0 ; +1=3 output bit6
lsl @0 ; +1=4
out PORTB, @0 ; +1=5 output bit5
lsl @0 ; +1=6
out PORTB, @0 ; +1=7 output bit4
lsl @0 ; +1=8
out PORTB, @0 ; +1=9 output bit3
lsl @0 ; +1=10
out PORTB, @0 ; +1=11 output bit2
lsl @0 ; +1=12
out PORTB, @0 ; +1=13 output bit1
lsl @0 ; +1=14
out PORTB, @0 ; +1=15 output bit0
clr @0 ; +1=16 clear this segment for next timing
.endmacro

24レジスタ分のループ展開

vout8px r0 ; 16*24=384cycles(visible period)
vout8px r1
vout8px r2
vout8px r3
vout8px r4
vout8px r5
vout8px r6
vout8px r7
vout8px r8
vout8px r9
vout8px r10
vout8px r11
vout8px r12
vout8px r13
vout8px r14
vout8px r15
vout8px r16
vout8px r17
vout8px r18
vout8px r19
vout8px r20
vout8px r21
vout8px r22
vout8px r23
out PORTB, r23 ; 0+1=1 set to blank level

最後のOUT命令は描画が終わったら背景の黒レベルにもどす処理です。これをやらないと右端のドットが1だった場合、白い線が画面の右端までびよ~んと尾を引いてしまいます。

0 件のコメント: