2024年6月2日日曜日

DCSGで音を鳴らす

パソピア7には、2つのSN76489Aが搭載されており、ボート3Ahと3Bhで操作する

テクニカルマニュアル61ページに周波数の計算式が示されており、
周波数f(Hz)=1.9968MHz/(16×n×2)
nは10bitのトーンカウンタ値で、n=1.9968MHz/(16×f×2)=62400/f

トーンカウンタ値n(D9-D0)をSN76489Aに設定する際には、2回に分けてポート設定。

R2とR1で、トーン番号 or ノイズを設定
R2R1
00Tone 0
01Tone 1
10Tone 2
11Noise

R0で、周波数 or アッテネーション(減衰)を設定
R0
0周波数
1Attenuation

例えば、トーン1に周波数440Hzをセットする場合、
トーンカウンタ値n=62400/440Hz=142=8Eh(00 1000 1110)
1回目(D3-D0)→2回目(D9-D4)の順番で2回続けてポート設定する必要がある
(1) 1回目(D3-D0:1110) =AEh(1010 1110)
(2) 2回目(D9-D4:001000) =08h(0000 1000)

あと音を出すにはVolumeの設定も必要。
Attenuation設定とVolumeの相関は、以前の記事を参照
例えば、トーン1にVolume=15(最大値)をセットする場合、B0h(1011 0000)
Volume=0(無音)をセットする場合、BFh(1011 1111)

BASICだと以下のようになる
10 ' Set 440Hz to Tone1
20 OUT &H3A, &HAE
30 OUT &H3A, &H08
40 ' Max Volume
50 OUT &H3A, &HB0
60 ' Wait
70 FOR I=0 TO 1000:NEXT
80 ' Stop Sound
90 OUT &H3A, &HBF

一般的にスピーカーON/OFFのパルス幅を変えることで音を鳴らすが、そのパルス幅をCPUクロックで調整して音の高さを変えるロジックから、DCSGの波形への変換を考えてみる。

例えば、以下のようにAレジスタにループ回数(n)を入れてパルス幅を調整している場合、パルス幅は16clock×n回になる
LOOP:
  DEC A            ; 4clock
  JR NZ,LOOP    ; 12clock(Jumpする場合)
スピーカーONとOFFが同じパルス幅で音を出している場合、パルス周期は16clock×n回×2

Z80の4MHzでこの周期を作る場合、音の周波数f(Hz)=4MHz/(16clock×n回×2)。
n=4MHz/(16×f×2)=125000/f
例えば周波数1000Hzの場合、n=125000/1000=125
それに対してDCSGで1000Hzを出す場合、トーンカウンタ値n=62400/1000=62.4

微妙な誤差はあるが、ループ回数の1/2をDCSGのトーンカウンタ値としてセットすると、おおむね同じ周波数で音がでるはず。

たぶん

0 件のコメント:

コメントを投稿