平成26年4月 5日
シリアルポートのプログラム
シリアルポートはz80CTCとz80SIOの二つの機能を使用しています。CTCはSIOの通信速度を決めるボーレートジェネレータとして機能しています。これらの機能を使用するために必要な情報を書いていきます。先にご紹介した
z80周辺LSIユーザーズマニュアルやネットから情報を集めてきました。
ボーレートジェネレータとしての要求仕様
SuperAKI-80ではCTC3をボーレートジェネレータに割り当てています。入力クロックは2分周後にCTC内部で更に1/16に分周します。9600bpsには64カウント、19200bpsには32カウントで指定のボーレートを得ます。割り込みは不要です。
CTCの構成
CTCには4個の8ビットタイマ/カウンタが実装されています。各chはほぼ同等の機能を持ち、1バイトのIOアドレスを占有しています。また各chには3つの8ビットレジスタがあり、全てのビットが読み書き可能です。と書いてあります。
レジスタの機能割り当て
・コントロールレジスタ
CTCの動作を決めるレジスタで、各ビットはそれぞれ下記の意味を持ちます。
ビット7: 割り込みを有効にする(1で有効)
ビット6: タイマ/カウンタを選択(1でカウンタ)
ビット5: タイマプリスケール選択(1で1/256, 0で1/16)
ビット4: CLK/TRIGエッジ選択(1で立ち上がり, 0で立下り)
ビット3: タイマ開始方法選択(注1参照)
ビット2: タイマレジスタ選択(注2参照)
ビット1: タイマリセットを選択(1でリセット)
ビット0: コントロール/ベクタレジスタ選択(1でコントロールレジスタ)
注1)1のときはCLK/TRGのパルスがきた段階で動作を開始。0のときはタイムコンスタントレジスタに値が設定された段階で動作を開始する。
注2)タイムコンスタントレジスタに書き込みするためには、その前に一旦このビットを1に書き込みます。次のこのアドレスに対する書き込み動作はタイムコンスタントレジスタに対して行われます。このビットを1にするときはビット1も1に設定します
正直、非常に理解しにくい仕様になっています。原因は3個あるレジスタを1個のアドレスに押し込んだためです。
全体として、書き込み動作時にはビット0がコントロールレジスタとベクタレジスタの選択ビットになっています。更にコントロールレジスタ選択時にはビット2が1なら次の書き込み動作はタイムコンスタントレジスタに対して行われます。この書き込み動作ではビット0の値はレジスタ選択には使われません。
・タイムカウントレジスタ
ここに書き込んだ値にカウント数が達すると外部出力にパルスを出力します。このパルスによってボーレートが決まります。ボーレートジェネレータとしての要求仕様で示したカウント数を設定します。カウント数は自動的に再設定されます。
・ベクタレジスタ
割り込みを使用する場合ベクタアドレスのビット7〜3を設定します。ビット2と1はDon't care(書き込んでも無効)です。ビット0は必ず0です。このレジスタだけはCTC0にのみ設定可能で他のchは(ch0のベクタアドレス+2*ch番号)でアドレスされます。
わき道にそれますが,,,,
さらっと書くとこうなりますが、上記のほとんどは書き込み動作のみしか書かれていません。では読み出し動作ではどうなるのか?全てのレジスタはRW可能と書かれていますので、これが正しいとするとビット0とビット2のレジスタ選択は内部的に記憶されているかもしれません。つまり、ベクタレジスタを読み出すには一旦ビット0を0の状態にしてベクタレジスタに書き込んだ後でないと読み出しできない。逆にベクタレジスタに書き込んだ直後にはコントロールレジスタの値を読み出す手段はないということかもしれません(その前に再度コントロールレジスタへの書き込みが必要になる)。非常に意味のない仕様になります。
実際に動かしてみないと本当の所は分かりません。実際にはリードできない可能性もありそうです。
CTCの初期化
SuperAKI-80での通信仕様を8ビット、パリティなし、1ストップビット、9600bpsの標準的な仕様とすると、
・ コントロールレジスタへは0x07(次の書き込みでタイムコンスタント指定を含む)、
・ タイムコンスタントレジスタには0x40(64)を設定すればいいことになります。
・ 割り込みは使用しないのでベクタレジスタへの設定は行いません。
(平成26年4月6日追記)
見事に間違えました。タイムコンスタントレジスタへの設定数値は0x40ではなく0x04にします。SIOは入力されたクロックをそのまま使用することも出来るのですが、通常は16倍や32倍のクロックを入力することで入力信号のサンプリング回数を稼ぎます。SIO側に16倍のクロックを入力するとして、タイムコンスタントレジスタでのカウント数を1/16の0x04にします。
(追記ここまで)
ここでもう一つ注意が必要なのは、コントロールレジスタの設定には直前の書き込みによってコントロールレジスタとタイムコンタントレジスタが選択されます。初期化の書き込み動作以前にこのレジスタに書き込み動作があった可能性は否定できないので、確実にコントロールレジスタに書き込むには二度書きが必要になります。
以上の検討からCTC3の初期化関数は下記になります。初期化さえすれば後は連続的に動作してくれます。
#include <stdio.h>
#include "myint.h"
uchar inp(void);
void main(void)
{
volatile uchar c;
for(;;){
c=inp();
}
}
次はz80SIOについてですが、こちらはかなり複雑なので別項にします。