2011.12.9
前へ
次へ
目次へ戻る
ホームページトップへ戻る

ワンボードマイコンをつくろう!(パソコンの原点はここから始まった) TK80ソフトコンパチブル!8080、Z80マシン語からBASICまでこれ1台でこなせます

[第130回]


●電子サイレンプログラム(2)

前回はもともとTK−80用に書かれた「電子サイレンプログラム」をND80ZV用に書き直したものをお見せしました。
TK−80とND80ZVとはスピーカ出力回路のI/Oアドレスと出力ビットが異なっているため、そこを直したのです。
前回は時間がなくなってしまいましたので、そこまでで終わってしまったのですが、実はそのほかにも直さなければいけないところがあるのです。

いえ。
前回のプログラムでも、もちろんちゃんとND80ZV上で実行され、スピーカからしっかりサイレン音が出力されます。
ただ音が違います(TK−80で実行したときの音を聞いたわけではありませんが、確かな理由から、違うと思います)。

どうして音が違うかといいますと、それはCPUクロックの周波数が違うからです。
TK−80のCPUクロックは手元の資料によりますと約2MHz(2.048MHz)です。
ND80ZVのCPUクロックはその3倍の6MHzです。
つまりND80ZVではTK−80の3倍の速度でプログラムが実行されます。

電子サイレンプログラムは、音の高さ(周波数)をWAITサブルーチンで特定の命令を一定回数実行することで作り出しています。
命令の実行速度が上がれば、WAITサブルーチンの実行時間がそれだけ短くなり、そこで作り出される音の周波数が上がって、高い音が出力されることになります。

電子サイレンプログラムは高い音から段階的に低い音になり、それからまた高い音まで段階的に変化することを繰り返します。
その音がTK−80での場合よりも周波数で3倍高くなるとともに、実はその音の高→低→高のピッチも3倍速くなっていると考えられます。

まあ、ことはただのサイレン音ですから、この高さの音でなければならない、ということはありませんし、またこのピッチでなければならない、ということもないでしょうから、そこまでこだわることもないとは思いますが。

なに。
それほど難しいことでもありませんから。
こだわってしまいました。
これがそのプログラムです。

2011/12/8  21:33  SIREN_2.TXT
END=823B
              ;;; SIREN from "maikon nyumon" for ND80Z3
              ;;;
              ;;; 11.12.8
              ;
              	ORG $8200
              ;
8200 0650     START:MVI B,50
8202 3EFF     LOOP1:MVI A,FF   ;TK-80 02
8204 D398     	OUT 98   ;TK-80 02
8206 CD2F82   	CALL WAIT
8209 3EDF     	MVI A,DF ;TK-80 00
820B D398     	OUT 98   ;TK-80 02
820D CD2F82   	CALL WAIT
8210 0B       	DCX B
8211 78       	MOV A,B
8212 FE40     	CPI 40
8214 C20282   	JNZ LOOP1
8217 3EFF     LOOP2:MVI A,FF   ;TK-80 02
8219 D398     	OUT 98   ;TK-80 02
821B CD2F82   	CALL WAIT
821E 3EDF     	MVI A,DF ;TK-80 00
8220 D398     	OUT 98   ;TK-80 02
8222 CD2F82   	CALL WAIT
8225 03       	INX B
8226 78       	MOV A,B
8227 FE50     	CPI 50
8229 C21782   	JNZ LOOP2
822C C30082   	JMP START
              ;
822F CD3582   WAIT:CALL WAIT1
8232 CD3582   	CALL WAIT1
8235 C5       WAIT1:PUSH B
8236 05       WAIT2:DCR B
8237 C23682   	JNZ WAIT2
823A C1       	POP B
823B C9       	RET
              ;
LOOP1        =8202  LOOP2        =8217  START        =8200  
WAIT         =822F  WAIT1        =8235  WAIT2        =8236  

どこを直したのかといいますと、WAITサブルーチンを直しただけです。
オリジナルのプログラムで1回CALLしていたサブルーチンを、1回のCALLで3回実行するように直したのです。

さて、そのように直して実行してみたのですが…。
これでオリジナルの電子サイレンの音に近くなったはずなのですが、私にはなんだかちょっとゆっくりすぎるように思えます。

実はこの電子サイレンプログラムはさすがプロだけあって実に巧妙なプログラムになっています。
それはDCX B、INX Bを使ったところにあります。
ふつうDCR B、INR Bを使いたくなるところをあえてそのようにしています。
そのココロは?
こうすることでBレジスタが±1変化する間にCレジスタが256回カウントされます(Cレジスタが256回カウントアップまたはカウントダウンしてはじめてBレジスタが±1します)。

Bレジスタの値によって、音の高さが決まりますから、ここでDCX B、INX Bを使うことによって、同じ高さの音が256回出力されることになり、それなりの効果音になっています。
これは実に巧妙なプログラムなのですが、逆にそれが弱点ともなります。

つまり同じ周波数の音を256波出力することしかできませんから、ピッチの速度もそれで決まってしまいます。
少しゆっくりしすぎかなあ、という感じになってしまうのはそのためかもしれません。

●ちょっと工夫してみました

そのように、なかなかにうまく作られたプログラムなので、それにケチをつける気は毛頭ありません。
しかし、このプログラムを見ていると、私ならばこうしたいなあ、というところが出てきます。

もともとこのプログラムは初心者にもわかるように、入門書として書かれたものですから、そういうところがあっても当然といえば当然なのですが。

ちょっと気になるのは音が低くなっていく過程と逆に高くなっていく過程とで、ほとんど同じパルス出力プログラムが書かれているところです。
やっぱりここはサブルーチンにしてしまいたいと思います。
そうすることで、外部出力という特殊な部分が1個のサブルーチンになってしまいます。

2011/12/8  22:5  SIREN_3.TXT
END=8238
              ;;; SIREN from "maikon nyumon" for ND80Z3
              ;;;
              ;;; 11.12.8
              ;
              	ORG $8200
              ;
8200 0650     START:MVI B,50
8202 CD1982   LOOP1:CALL OUTSB
8205 05       	DCR B
8206 78       	MOV A,B
8207 FE40     	CPI 40
8209 C20282   	JNZ LOOP1
820C CD1982   LOOP2:CALL OUTSB
820F 04       	INR B
8210 78       	MOV A,B
8211 FE50     	CPI 50
8213 C20C82   	JNZ LOOP2
8216 C30282   	JMP LOOP1
              ;
8219 3EFF     OUTSB:MVI A,FF   ;TK-80 02
821B D398     	OUT 98   ;TK-80 02
821D CD2C82   	CALL WAIT
8220 3EDF     	MVI A,DF ;TK-80 00
8222 D398     	OUT 98   ;TK-80 02
8224 CD2C82   	CALL WAIT
8227 0D       	DCR C
8228 C21982   	JNZ OUTSB
822B C9       	RET
              ;
822C CD3282   WAIT:CALL WAIT1
822F CD3282   	CALL WAIT1
8232 C5       WAIT1:PUSH B
8233 05       WAIT2:DCR B
8234 C23382   	JNZ WAIT2
8237 C1       	POP B
8238 C9       	RET
              ;
LOOP1        =8202  LOOP2        =820C  OUTSB        =8219  
START        =8200  WAIT         =822C  WAIT1        =8232  
WAIT2        =8233  

OUTSBがそのサブルーチンです。

もっともこのようにしたために、巧妙だったDCX B、INX Bが使えなくなってしまいました。
逆に考えれば、DCX B、INX Bを使ったために、ここをサブルーチンにすることができなかった、とも言えます。
私はここはオーソドックスに、Cレジスタをサブルーチン内で使う方が好きです。

なおオリジナルでは一回の高→低→高のサイクルが完了してもとに戻って繰り返すときに、STARTに戻っていますが、これはやはり冗長です。
ここは上のリストのように、LOOP1に戻るべきだと思います。

ワンボードマイコンをつくろう![第130回]
2011.12.9upload

前へ
次へ
目次へ戻る
ホームページトップへ戻る