標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第451回]
●実行速度について
前回の終わりのところで、Z80版TK80(ND80ZH)とTK80との互換性について、「まだ問題が残っていた」と書きました。
それは何かといいますと、CPUクロックの違いなのです。
TK80は18.432MHzのクリスタルを9分周して得られる2.048MHzをCPUクロックにしていました。
それに対してND80ZHの方は8MHzのクリスタルを2分周して得られる4MHzをCPUクロックにしています。
ND80ZHでTK80用に書かれたプログラムを実行させると、倍速で実行してしまうのです。
速ければいい、とは言いきれません。
プログラムによってはちょっと困る場合がでてきます。
たとえばMYCPU80のサンプルプログラムにもある、スピーカーから音を出すようなプログラムでは、音の高さが変わってしまいます。
ここまで書いてきて思い出しました。
当社がスタートするきっかけになった、TK80互換ボードND80のCPUクロックは2MHzだったのですが、その後にCPUを8080からZ80AにしたND80ZではCPUクロックを倍の4MHzにUPしました。
しかしボード上に設けたスイッチによって、CPUクロックの2MHzと4MHzを切り換えることができるようにしてありました。
むむむ。
ちゃんと互換性を確保していたのですねえ。
そんなことはすっかり忘れてしまっていました。
あ。MYCPU80はたまたまCPUクロックを2MHzにしましたので、この問題には遭遇することなく済んでしまいました。
ええ。MYCPU80の場合は、ほんとに、たまたま、でした。
当初は4MHzでスタートしたのですが、74HC03や74HC05の出力回路の遅れが原因で、クロックを半分の2MHzに落としたのですが、それはそういう理由からだったので、TK80との互換性を考慮したから、というわけではなかったのです。
まあ、しかし。
せっかく4MHzで実行できるZ80Aを、わざわざその半分の2MHzに落として使うというのも、なんだかなあ、という気がいたしますから、実行速度が関係するようなプログラムについては、CPUクロックに合わせてプログラムを書き換えていただく、ということで納得していただくことにいたしましょう。
それに。
Z80は8080の命令コードを全て実行できますが、実は命令によっては、実行クロック数が異なっているものもあるのです。
細かいことになりますが、そうすると、たとえCPUクロックをTK80と同じにしたとしても、CPUが8080からZ80になったことで、同じプログラムでも、実行速度が微妙に異なってくるということも有り得るのです。
そんな細かい点には全く気がついていなかったのですが、以下に説明する作業をする過程で、偶然ですが、そのことに気がつきました。
●チャタリングタイマー
さきほどの説明で、スピーカーから音を出すプログラムでは音の高さが変わってきてしまう、ということを書きましたが、そんなこと以前に、もっと根本的なところで、CPUクロックの違いが影響する部分があったのです。
TK80モニタプログラムにはカセットテープレコーダを使ってプログラムをSAVE、LOADする機能がありますが、その録音波形を生成するためのタイマールーチンがあって、その一部が、キーのチャタリング回避のタイマーとしても利用されていました。
TK80モニタプログラムのその部分のリストです。
; ;CHATTERING TIMER ; ORG $02DD 02DD 1624 D1:MVI D,24;WAIT 1/2 BIT TIME 4.5112MSEC 02DF 1E0C MVI E,0C 02E1 1D DCR E 02E2 C2E102 JNZ $-1 02E5 15 DCR D 02E6 C2DF02 JNZ $-7 02E9 C9 RET 02EA 1648 D2:MVI D,48;WAIT 1 BIT TIME 9.0176MSEC 02EC C3DF02 JMP D1+2 02EF 16D8 D3:MVI D,D8;WAIT 3 BIT TIME 27.0176MSEC 02F1 C3DF02 JMP D1+2[出典]NEC日本電気鰍sK80ユーザーズ・マニアル
アドレス02EAの9.0176MSECタイマールーチンがチャタリングタイマーです。
ここが倍速で実行されてしまうと、ちょっと都合が悪いことになります。
まあ、チャタリングタイマーとして9msecの時間が絶対に必要か、というとそうは言いきれないのですが、ここが余り短くなってしまうと、キーのチャタリングが回避できなくなってしまうかもしれません。
で、上のリストのコメントを参考にして、D2のルーチンが約9msecになるように、プログラムを変更しました。
ひょっとして、TK80用のアプリケーションプログラムで、この部分が(D2だけではなくて、D1やD3のタイマーも)使われているかもしれないということを考慮して、コアの部分の
02DF 1E0C MVI E,0C
のところを計算して変更することにしました。
そのようにしてタイマールーチンの部分を変更した、ND80ZHのモニタプログラムです。
; ;CHATTERING TIMER ; ORG $02DD 02DD 1624 D1:MVI D,24;=36 ck=7 127.75*36+(7+10)*0.25=4603.25microsec 02DF 1E23 D1_2:MVI E,23;=35 ck=7 7+14*35+14=511 0.25*511=127.75microsec 02E1 1D D1_3:DCR E; ck=4 02E2 C2E102 JNZ D1_3; ck=10 02E5 15 DCR D; ck=4 02E6 C2DF02 JNZ D1_2; ck=10 02E9 C9 RET; ck=10 02EA 1648 D2:MVI D,48;=72 127.75*72+(7+10+10)*0.25=9204.75microsec 02EC C3DF02 JMP D1_2 02EF 16D8 D3:MVI D,D8;=216 127.75*216+27*0.25=27600.75microsec 02F1 C3DF02 JMP D1_2
CPUクロックを4MHzとして計算した結果、02DFのMVI命令でEに与える値を23(十進数の35)に決めました。
D1〜D3の実行時間はTK80の値より少し大きくなりますが、チャタリングタイマーという目的から考えて、ここは大き目の方が安全サイドであると考えました。
E=22(十進数の34)の方がオリジナルにより近い値になるのですが、そうすると、オリジナルよりも実行時間が短くなってしまいます。
●テストプログラムで確認してみました
変更したタイマールーチンが、計算通りの値なのかどうか、簡単なテストプログラムを書いて確認してみました。
そのプログラムリストは、[第448回]で紹介しました、逆アセンブルリスト出力機能を利用してプリンタに出力して作成しました。
プログラムは簡単なものなので、キーから16進コードを直接入力して作成しました。
アドレス8000〜8014の短いプログラムです。
そのプログラムの逆アセンブルリストを出力するには、7セグメントLEDのアドレス表示部にプログラムの先頭アドレスの8000を表示させて、データ表示部に終了アドレスの8014を表示させたあとで、[*I/O]に続いてデータキーの[B]([DA])を押します。
キーから[8][0][0][0][ADRSSET][8][0][1][4]と入力したところです。
このあと[*I/O]に続いてデータキーの[B]([DA])を押すと、下のリストがプリンタに出力されました。
02EAのサブルーチン(9.2msecタイマールーチン)をCALLするごとに82C55のAポートからFFと00を交互に出力するだけの簡単なプログラムです。
Aポートからの出力波形をオシロで観測してみました。
確かに9.2msecです。
プログラムに間違いがないことが確認できました。
ところで、今回変更したモニタプログラムのタイマールーチンとオリジナルのTK80モニタプログラムの変更前のタイマールーチンとを比較していて。
あれえ?
ちょいとおかしなことに気がついてしまいました。
変更を行ったのはただ1ヶ所、アドレス02DFのMVI E,0Cを、MVI E,23にしただけだったのですけれど…?
そのどこが、あれえ?なのか。
さて、みなさま。おわかりになりますでしょうか?
本日は、時間がなくなってしまいましたので、そのことにつきましてはまた次回に説明することにいたします。
2010.3.8upload
前へ
次へ
ホームページトップへ戻る