2024年5月10日金曜日

YM3812 (OPL2)の使い方

現在執筆中です。内容がちょくちょく変更されますので、ご注意ください。

YM3812の使い方

注意:このサイトの内容を鵜呑みにし、事故や損失を招いた場合でも当方は一切の責任は負いかねます。自己責任でお願いします。


PSR11に内蔵されていた艶ありYM3812 (左)
PSS460内蔵されていたYM3812 (右)


YM3812は4オペレータのFM音源IC (OPL2)です。(LSIですが便宜上ICと呼びます。)

YAMAHAのポータートーンやアーケードゲームなどによく用いられていました。
中古品も割と豊富に出回っているため、入手は比較的容易です。
ただし、某オークションサイト等では偽物も多く出回っているため、注意が必要です。

確実に本物のYM3812を入手したい場合、YAMAHAのポータートーンやアーケード基板を購入して部品取りをして利用すると良いでしょう。


余談ですが、このYM3812のパッケージの見た目と印字の種類は意外と多く、DIPパッケージのものだけでも少なくとも5種類以上はあります。

よく見かけるのが、印字が中央揃えのIC方向切りかけありで艶なしのもの(トップ画像右のタイプ)と、印字が左揃えのIC方向切りかけありで艶なしのものでしょうか。
たまに印字が左揃えのIC方向切りかけなしで艶なしのものや、印字が左揃えのIC方向切りかけなしで艶なしのもので「OPL」の商標が入ったものも見かけます。
あまり見かけないタイプとして、印字が中央揃えのIC方向切りかけありで艶ありのもの(トップ画像左のタイプ)もあります。
まだ見たことは無いですが、販売初期に作られるであろうセラミックパッケージのものもあるかもしれません。

パッケージをみただけでは偽物との判別はしにくいです。印字のフォントの違いを見て判別するのが良さそうです。


YM3812単体では、音を出すことはできず、YM3014などの専用のDACが必要です。


・YM3812の特徴


・2オペレータ2アルゴリズム、同時発音数 : 9
・24ピンDIP
・ハードウェアエンベロープ
・ハードウェアLFO (ビブラート、振幅変調)
・リズムモード

・YM3812のブロック図

YM3812のデータシートより抜粋



・ピン配置



ピン番号名称I/O機能
1VCC(+5V)-電源端子です。
+5Vの電源へ接続します。

2~IRQO割り込み要求端子です。

内部タイマーカウンタにより、割り込み要求が出力されるようです。

3~ICIリセット端子です。
この端子がLの期間、内部レジスタを初期化します。

4A0Iアドレス / データセレクト端子です。

この端子がLの場合、D0~D7はアドレス入力端子となります。

Hの場合、D0~D7はデータ入力端子となります。
5~WRIライト端子です。

この端子がLでかつ、「~CS」がLの期間、
D0~D7端子の状態が内部レジスタへラッチされます。

6~RDIリード端子です。

この端子がLでかつ、「A0」がHでかつ、「~CS」がLの期間、
内部ステータスレジスタの状態がD0~D7端子へラッチされます。

7~CSIチップセレクト端子です。

この端子がLの期間、「~WR」または「~RD」端子がLの時、
書き込み・読み込みができます。

8NC-無接続です。
9NC-無接続です。
10D0I/Oデータピンです。
11D1I/Oデータピンです。
12VSS(GND)-グランド端子です。
13D2I/Oデータピンです。
14D3I/Oデータピンです。
15D4I/Oデータピンです。
16D5I/Oデータピンです。
17D6I/Oデータピンです。
18D7I/Oデータピンです。
19NC-無接続です。
20SHOサンプルホールド端子です。
データラッチ信号としても使います。

YM3014などのDACへ接続します。
21MOOシリアルデータ出力端子です。

YM3014などのDACへ接続します。
22NC-無接続です。
23ΦSYOクロック出力端子です。

YM3014などのDACへ接続します。
24ΦMIクロック入力端子です。

標準で3.58MHzを入力します。
入力可能なクロック周波数範囲は2.0MHz~4.0MHzです。




・YM3812のレジスタ(書き込み専用)

YM3812は8ビットアドレス空間中に123バイト分のレジスタを持っています。


アドレス
レジスタ名 機能
$00 - 未使用
$01 TEST TEST
テスト用のレジスタです。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
TEST_6TEST_5W_SEL_ENTEST_4TEST_3TEST_2TEST_1TEST_0

TEST_0 ~ TEST_6 には常に0を書き込んだ状態にしてください。

W_SEL_EN:
このビットをHにすると、WAVE_SELECT($E0~$F5)レジスタによりオペレータの基本波形を選択できるようになります。
このビットをLにすると、YM3526 (OPL)モードとなります。

W_SEL_EN = H : オペレータの基本波形選択を有効
W_SEL_EN = L : オペレータの基本波形選択を無効(YM3526 (OPL)モード)

$02 TIMER_1 TIMER1
内部タイマー1の設定値8bitです。


bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
TIM1_7TIM1_6TIM1_5TIM1_4TIM1_3TIM1_2TIM1_1TIM1_0


TIM1:
タイマー1の設定値です。

  Tov1  = 0.288 * (256 - TIM1) / ΦM    [ms]

Tov1 : タイマー1オーバーフロー周期m[s]
TIM1 = 0~255(0x00~0xFF) :タイマー周期決定ビット
ΦM : 入力クロック周波数[Hz]

$03 TIMER_2 TIMER2
内部タイマー2の設定値8bitです。


bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
TIM2_7TIM2_6TIM2_5TIM2_4TIM2_3TIM2_2TIM2_1TIM2_0


TIM2:
タイマー2の設定値です。

  Tov2  = 1.152 * (256 - TIM2) / ΦM    [ms]

Tov2 : タイマー2オーバーフロー周期m[s]
TIM2 = 0~255(0x00~0xFF) :タイマー周期決定ビット
ΦM : 入力クロック周波数[Hz]

$04 TIM_CONF IRQ RESET/MASK/ST
内部タイマーの動作設定ビット群です。


bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
IRQ_RESETMASK_T1MASK_T2---ST2ST1

IRQ_RESET:
このビットにHを書き込むと、タイマー1とタイマー2のオーバーフロービットをクリアします。


MASK_T:
このビットをHにすると、タイマーがオーバーフローした時の割り込みフラグをLにロックします。

MASK_T1 = H : タイマー1による割り込みフラグを常にLする
MASK_T2 = H : タイマー2による割り込み
フラグを常にLする


ST:
このビットをHにすると、タイマーが動作します。Lにすると、停止します。

ST2 = H : タイマー2を動作させる
ST1 = H : タイマー1を動作させる

$05~$07 - 未使用
$08 CSM_SEL CSM音声合成モードおよびNOTE select設定ビットです。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
CSMNOTE_SEL------

CSM:
このビットをHにすると、音声合成モードとなります。


NOTE_SEL:
Fナンバー値によるキースケールの区分の挙動を決定します。
詳細はF-NUM_L($A0~$A8)にあるので参照してください。

NOTE_SEL = H : Fナンバー値のMSB($B0~$B8の第1bit)の値がキースケールの区分となります。
NOTE_SEL = L : Fナンバー値のMSBの右のビット($B0~$B8の第0bit)の値がキースケールの区分となります。(Fナンバー値のMSB=Hの時限定)

$09~$1F - 未使用
$20~$25,
$28~$2D,
$30~$35,
($26,$27,$2E,$2Fは未使用)
AM_VIB_EGTYP_KSR_MUL AM / VIBRATO / EG-TYP / Key Scaling Rate / MULTIPLE
LFOによる振幅変調およびビブラートのON/OFF、エンベロープの種類の選択、キースケールレートの選択、スロット倍率設定レジスタです。

$20~$25にSLOT1~SLOT6、$28~$2DにSLOT7~SLOT12、$30~$35にSLOT13~SLOT18が割り当てられています。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
AMVIBEG_TYPKSRMUL_3MUL_2MUL_1MUL_0

AM:
このビットをHにすると、該当のスロットのオペレータ出力の振幅変調が有効になります。
振幅変調の周波数は次の通りとなります。
  Fam  = 1.0278μ * ΦM    [Hz]

Fam :該当のスロットのオペレータ出力の振幅変調の周波数[Hz]
ΦM : 入力クロック周波数[Hz]

AM = H : オペレータ出力の振幅変調を有効にする
AM = L : オペレータ出力の振幅変調を無効にする


VIB:
このビットをHにすると、該当のスロットのオペレータ出力の周波数変調(ビブラート)が有効になります。
ビブラートの周波数は次の通りとなります。
  Fpm  = 1.778μ * ΦM = (1/562500) * ΦM  [Hz]

Fpm : 該当のスロットのオペレータ出力のビブラートの周波数[Hz]
ΦM : 入力クロック周波数[Hz]

VIB = H : オペレータ出力のビブラートを有効にする
VIB = L : オペレータ出力のビブラートを無効にする


EG_TYP:
該当のスロットのオペレータ出力のエンベロープ波形の種類を選択するビットです。

EG_TYP = H : 持続音に設定します。ディケイ中のエンベロープ出力がサスティーンレベルに到達後、キーオフされるまでサスティーンレベル維持します。オルガンやストリングス、管楽器等の音色のイメージです。
EG_TYP = L : 減衰音に設定します。ディケイ中のエンベロープ出力がサスティーンレベルに到達後、キーオン・キーオフの状態に関係なくリリースへと移行します。ピアノやギター、打楽器の音色のイメージです。


KSR:
該当のスロットのオペレータのエンベロープのキースケールレート選択ビットです。
このビットをHにすると、キースケールによるADRレートの変化率が大きくなります。

  RATE  = ADR * 4 + Rof    (ADR≠0)
  RATE  = 0   (ADR=0)

ADR : レジスタにて設定したAR,DR,RRの値(0~15)
RATE : YM3812内部で使用する実際のA,D,Rのレート値
Rof : キースケール値により決まるオフセット値(KSR = Hの時Rof=キースケール値、KSR = Lの時Rof=(キースケール値>>2) )



MUL:
該当のスロット周波数の倍率設定ビットです。

MUL = 0~15 (0x0 ~ 0xF) :スロット倍率レジスタにセットできる値

   Ns = MUL    (MUL ≠ 0)
   Ns = 1/2     (MUL = 0)

Ns : スロットに適用される、該当チャンネルの基本周波数からの倍率[倍]

$36~$3F - 未使用
$40~$45,
$48~$4D,
$50~$55,
($46,$47,$4E,$4Fは未使用)
KSL_TL Key Scaling Level / Total Level
キースケールレベル、オペレータ出力レベル設定レジスタです。

$40~$45にSLOT1~SLOT6、$48~$4DにSLOT7~SLOT12、$50~$55にSLOT13~SLOT18が割り当てられています。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
KSL_1KSL_0TL_5TL_4TL_3TL_2TL_1TL_0

KSL:
該当のスロットのオペレータのキースケールレベルを設定します。

KSL = 0~3 (0x0 ~ 0x3) : キースケールレベルレジスタにセットできる値

KSL_1KSL_0キースケールによる減衰度 [dB/oct] 
LL0
LH3
HL1.5
HH6


TL:
該当のスロットのエンベロープ出力レベル設定レジスタです。
TL = 0で最大信号レベル、63で最小信号レベルとなります。

Atl = 0.75 * TL    [dB]

TL = 0~63 (0x00 ~ 0x3F) : 出力レベルレジスタにセットできる値
Atl : エンベロープ出力の減衰量

$56~$5F - 未使用
$60~$65,
$68~$6D,
$70~$75,
($66,$67,$6E,$6Fは未使用)
AR_DR ATTACK RATE / DECAY RATE
エンベロープ・アタックレート、エンベロープ・ディケイレート設定レジスタです。

$60~$65にSLOT1~SLOT6、$68~$6DにSLOT7~SLOT12、$70~$75にSLOT13~SLOT18が割り当てられています。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
AR_3AR_2AR_1AR_0DR_3DR_2DR_1DR_0

AR:
出力レベルのエンベロープ制御する際のアタック時間を設定するビットです。
この値が小さいほどアタック時間が長くなります。

AR = 0~15 (0x0 ~ 0xF) : アタック時間レジスタにセットできる値

DR:
出力レベルのエンベロープ制御する際のディケイ時間を設定するビットです。
この値が小さいほどディケイ時間が長くなります。

DR = 0~15 (0x0 ~ 0xF) : ディケイ時間レジスタにセットできる値

$76~$7F - 未使用
$80~$85,
$88~$8D,
$90~$95,
($86,$87,$8E,$8Fは未使用)
SL_RR SUSTAIN LEVEL / RELEASE RATE
エンベロープ・サスティーンレベル、エンベロープ・リリースレート設定レジスタです。

$80~$85にSLOT1~SLOT6、$88~$8DにSLOT7~SLOT12、$90~$95にSLOT13~SLOT18が割り当てられています。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
SL_3SL_2SL_1SL_0RR_3RR_2RR_1RR_0

SL:
出力レベルのエンベロープ制御する際のサスティーンレベルを設定するビットです。
この値が小さいほどサスティーンレベルが大きくなります。

Atl = 0.75 * TL    [dB]

SL = 0~15 (0x0 ~ 0xF) : サスティーンレベルレジスタにセットできる値
Atl : サスティーンレベル


RR:
出力レベルのエンベロープ制御する際のリリース時間を設定するビットです。
この値が小さいほどリリース時間が長くなります。

RR = 0~15 (0x0 ~ 0xF) : リリース時間レジスタにセットできる値

$96~$9F - 未使用
$A0~$A8 F-NUM_L F-Number (L)
音程設定レジスタです。KON_BLK_F-NUM_H($B0~$B8)の第1ビットと第0ビットとペアで使用します。

$A0~$A8にチャンネル1~チャンネル9が割り当てられています。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
F_NUM_7F_NUM_6F_NUM_5F_NUM_4F_NUM_3F_NUM_2F_NUM_1F_NUM_0

F_NUM:
音程設定レジスタです。KON_BLK_F-NUM_H($A9~$9F)の第1ビットと第0ビットとペアで使用します。

発音したい周波数f_TONEからF_NUMを求める式
  F_NUM = f_TONE * (2^19) / ((ΦM/72) * (2^(BLOCK-1)))
           = f_TONE * (2^23) * 9 / (ΦM * (2^BLOCK))

F_NUM = 0~1023 (0x000 ~ 0x3FF) : 音程レジスタにセットできる値
ΦM : 入力クロック周波数[Hz]
BLOCK = 0~7 (0x0 ~ 0x7) : オクターブレジスタレジスタにセットできる値

ただし、F_NUMが1023を超えないようなBLOCK値を選ばなければいけません。
また、キースケールの区分点は、F_NUM_9のHとLの境目または、F_NUM_8のHとLの境目に設定できることを考えると、F_NUM_9のHとLまたは、F_NUM_8のHとLの境目を1オクターブ内の12音の中間付近になるようにF_NUMを算出します。
このキースケール区分点選択ビットNOTE_SEL($08:bit6)をどうするかは、音程の正確さかピッチベンドの可否かで決めると良さそうです。
NOTE_SEL($08:bit6)=Lにセットした場合、発音の音程はより正確に設定ができますが、高音域では、F_NUMが1023に近いため、ピッチベンドの計算が面倒になります。
NOTE_SEL($08:bit6)=Hにセットした場合、発音の音程の正確度は劣りますが、F_NUMの上限1023までに余裕が生まれるため、ピッチベンドの計算が少し楽になります。

発音する時は通常、1オクターブ内の12音のF_NUMを事前に計算しておいて、オクターブレジスタBLOCKによって、オクターブの変更を行います。


入力クロックΦM = 3.579545MHz、NOTE_SEL($08:bit6)=Hの場合
音程(A=440Hz)F_NUM (2進)、赤字はキースケール境界判定ビット
C#365 (0b 01 0110 1101)
D387 (0b 01 1000 0011)
D#410 (‭0b 01 1001 1010‬)
E435 (0b ‭01 1011 0011‬)
F460 (0b ‭01 1100 1100‬)
F#488 (0b ‭01 1110 1000‬)
G517 (0b ‭10 0000 0101‬)
G#547 (0b ‭10 0010 0011‬)
A580 (0b ‭10 0100 0100‬)
A#615 (0b 10 0110 0111‬)
B651 (0b ‭10 1000 1011‬)
C690 (0b 10 1011 0010‬)


入力クロックΦM = 3.579545MHz、NOTE_SEL($08:bit6)=Lの場合
※F_NUM_8のHとLの境目を1オクターブ内の12音の中間にしようとすると、F_NUMが1023を超えるため、C#とDの間を境界とする
音程(A=440Hz)F_NUM (2進)、赤字はキースケール境界判定ビット
G517 (0b ‭10 0000 0101‬)
G#547 (0b ‭10 0010 0011‬)
A580 (0b ‭10 0100 0100‬)
A#615 (0b 10 0110 0111‬)
B651 (0b ‭10 1000 1011‬)
C690 (0b 10 1011 0010‬)
C#731 (0b‭ 10 1101 1011‬‬)
D774 (0b‭ 11 0000 0110‬)
D#820 (0b‭ 11 0011 0100‬‬)
E869 (0b‭ 11 0110 0101‬)
F920 (0b‭ 11 1001 1000‬‬)
F#975 (0b ‭11 1100 1111‬‬)


入力クロックΦM = 4MHz、NOTE_SEL($08:bit6)=Hの場合
音程(A=440Hz)F_NUM (2進)、赤字はキースケール境界判定ビット
D#367 (0b‭ 01 0110 1111‬)
E389 (0b‭ 01 1000 0101‬)
F#412 (‭0b‭ 01 1001 1100‬)
F436 (0b‭ 01 1011 0100‬‬)
G462 (0b‭ 01 1100 1110‬‬)
G#490 (0b‭ 01 1110 1010‬‬)
A519 (0b 10 0000 0111‬‬)
A#550 (0b ‭‭10 0010 0110‬)
B583 (0b 10 0100 0111‬‬)
C617 (0b ‭10 0110 1001‬‬)
C#654 (0b ‭10 1000 1110‬‬)
D693 (0b ‭10 1011 0101‬)


入力クロックΦM = 4MHz、NOTE_SEL($08:bit6)=Lの場合
※F_NUM_8のHとLの境目を1オクターブ内の12音の中間にしようとすると、F_NUMが1023を超えるため、C#とDの間を境界とする
音程(A=440Hz)F_NUM (2進)、赤字はキースケール境界判定ビット
A519 (0b ‭10 0000 0111‬‬)
A#550 (0b ‭‭10 0010 0110‬)
B583 (0b ‭‭10 0100 0111‬‬)
C617 (0b ‭10 0110 1001‬‬)
C#654 (0b ‭10 1000 1110‬‬)
D693 (0b ‭10 1011 0101‬)
D#734 (0b‭ ‭10 1101 1110‬)
E778 (0b‭ ‭11 0000 1010‬‬)
F824 (0b‭ ‭11 0011 1000‬‬‬)
F#873 (0b‭ ‭11 0110 1001‬)
G925 (0b‭ ‭11 1001 1101‬‬‬)
G#980 (0b ‭‭11 1101 0100‬‬‬)


$A9~$9F - 未使用
$B0~$B8 KON_BLK_F-NUM_H Key ON / BLOCK / F-Number (H)
キーオンオフ、オクターブ指定、音程設定レジスタです。F_NUM(第1ビットと第0ビット)はF-NUM_L($A0~$A8)とペアで使用します。

$B0~$B8にチャンネル1~チャンネル9が割り当てられています。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
--KONBLOCK_2BLOCK_1BLOCK_0F_NUM_9F_NUM_8

KON:
キーオン・キーオフ制御ビットです。
このビットをL→Hにすると、該当のチャンネルのエンベロープのアタックが開始します。また、このビットをH→Lにすると、該当のチャンネルのエンベロープのリリースが開始します。
もし、リズムモードを有効にする場合、チャンネル7~9のKONを常にLにセットしなければいけません。

KON = H :該当のチャンネルのキーオン
KON = L :該当のチャンネルのキーオフ


BLOCK:
オクターブ指定レジスタです。
該当のチャンネルのオクターブを指定をします。
発音周波数とF_NUM値、BLOCK値の関係はF-NUM_L($A0~$A8)を参照してください。

BLOCK = 0~7 (0x0 ~ 0x7) : オクターブレジスタレジスタにセットできる値


F_NUM:
音程設定レジスタです。F-NUM_L($A0~$A8)とペアで使用します。
発音周波数とF_NUM値、BLOCK値の関係はF-NUM_L($A0~$A8)を参照してください。


$B9~$BC - 未使用
$BD DEP_RHYTHM AM・VIB Depth / Rhythm 
振幅変調・ビブラート深度設定、リズムモード関係レジスタです。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
DAMDVBRBDSDTOMTCHH

DAM:
振幅変調深度選択ビットです。1~9のチャンネルで共通です。

DAM = H : 振幅変調深度を4.8dBにする
DAM = L : 振幅変調深度を1dBにする


DVB:
ビブラート(周波数変調)深度選択ビットです。1~9のチャンネルで共通です。

DVB = H : 周波数変調深度を14セントにする
DVB = L : 周波数変調深度を7セントにする


R:
リズムモード選択ビットです。
このビットをHをセットすると、リズムモードとなります。
リズムモードを有効にすると、チャンネル7~9(スロット13~18)をリズム用に確保されます。もし、リズムモードを有効にする場合、チャンネル7~9のKONを常にLにセットしなければいけません。

R = H : リズムモードで使用(スロット13~18をリズム用に使用)
R = L : 通常モードで使用


BD:    バスドラム
SD:    スネアドラム
TOM:  タムタム
TC:    トップシンバル
HH:    ハイハット
各リズムチャンネルに対するキーオン・キーオフ制御ビットです。
リズムモードが有効の時に、このビットの操作が有効になります。もし、リズムモードを有効にする場合、チャンネル7~9のKONを常にLにセットしなければいけません。

リズムチャンネルと使用スロットの対応
BD :   13, 16 (チャンネル7、2OP FM音源)
SD :   17 (チャンネル8 OP2、ノイズジェネレータ)
TOM : 15 (チャンネル9 OP1、ノイズジェネレータ)
TC :   18 (チャンネル9 OP2、ノイズジェネレータ)
HH :   14 (チャンネル8 OP1、ノイズジェネレータ)


$BE,$BF - 未使用
$C0~$C8 FB_C FEEDBACK / CONNECTION
オペレータフィードバック量、アルゴリズム選択レジスタです。

$C0~$C8にチャンネル1~チャンネル9が割り当てられています。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
----FB_2FB_1FB_0C

FB:
該当するチャンネルのOP1のフィードバック変調度を設定するレジスタです。

FBM = π * (2^(FB-1)) / 16

FB = 0~7 (0x0 ~ 0x7) : フィードバック量指定レジスタにセットできる値
FBM : OP1のフィードバック変調度


C:
該当するチャンネルのアルゴリズムの選択を設定するビットです。

C = L :
シリアル2連モード
[OP1]→[OP2]→OUT
※[OP1]は自己フィードバックあり

C = H : 
パラレル合成モード
[OP1]→⊕→OUT
[OP2]↗
※[OP1]は自己フィードバックあり

$C9~$DF - 未使用
$E0~$E5,
$E8~$ED,
$F0~$F5,
($E6,$E7,$EE,$EFは未使用)
WS Wave Select
オペレータの基本波形選択レジスタです。

$E0~$E5にSLOT1~SLOT6、$E8~$EDにSLOT7~SLOT12、$F0~$F5にSLOT13~SLOT18が割り当てられています。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
------WS_1WS_0

WS:
オペレータの基本波形を設定するレジスタです。

WS = 0~3 (0x0 ~ 0x3) : 波形レジスタレジスタにセットできる値

WS_1WS_0波形
LL◠◡
LH◠--
HL
HH╭_╭_



$F6~$FF - 未使用



・YM3812のレジスタ(読み取り専用)

YM3812は内部に1バイトの読み取り専用レジスタを持っています。
セットしたアドレスによらず、YM3812のステータス情報を返します。

bit7
bit6
bit5
bit4
bit3
bit2
bit1
bit0
IRQFT1FT2-----


IEQ:
WRITE BUSY FLAG
割り込み要求フラグです。
FT1またはFT2がHとなるとIRQがHとなります。
TIM_CONF($04:bit7)をHにするとこのビットがLになります。


FT1:
タイマ1のオーバーフローフラグです。
タイマ1のカウンタがオーバーフローすると、Hとなります。
TIM_CONF($04:bit7)をHにするとこのビットがLになります。

FT2:
タイマ2のオーバーフローフラグです。
タイマ2のカウンタがオーバーフローすると、Hとなります。
TIM_CONF($04:bit7)をHにするとこのビットがLになります。




・タイミング図

YM3812への書き込みタイミング


アドレス・データの書き込みタイミングです。
アドレスを書き込む場合は4番ピンの「A0」をLにします。
データを書き込む場合は「A0」をHにします。

YM3812のステータスレジスタの読み取りタイミング



読み取りの場合、YM3812は常にステータスレジスタの内容を返すため、アドレスの書き込みは不要です。


YM3812のレジスタへ値をセットする



YM3812は、アドレスバスとデータバスを共用しています。
YM3812へアドレス値を書き込んでからデータ値を書き込むことで、任意の場所の内部レジスタへデータをセットできます。

YM2151などとは違いステータスレジスタにビジーフラグが無いため、連続書き込みを行うにはウェイトを入れる必要があります。

YM3812のアドレス値を書き込んでから12クロック分のウェイト(赤線部)後、YM3812のレジスタへデータ値を書き込むことができます。
また、YM3812のレジスタへデータを書き込むと、84クロック分のウェイトが必要です。

入力クロックΦM = 3.579545MHzの場合のウェイト時間はそれぞれ、3.4μs(12クロック)、23.5μs(84クロック)です。
入力クロックΦM = 4.0MHzの場合のウェイト時間はそれぞれ、3μs(12クロック)、21μs(84クロック)です。

-- YM3812のレジスタへのデータセット手順 --

①YM3812の84クロック分以上待機する(余裕をもって多く待機することをおすすめします。)
②~CSピンをLにする
③A0ピンをLにする
④書き込み先アドレスをD0~D7へセットする
⑤~WEピンをLにする
⑥~WEピンをHにする
⑦A0ピンをHにする
⑧YM3812の12クロック分以上待機する(余裕をもって多く待機することをおすすめします。)
⑨書き込むデータをD0~D7へセットする
⑩~WEピンをLにする
⑪~WEピンをHにする
⑫~CSピンをHにする



・使い方(制御)

YM3812は、123バイト分のレジスタを持ち、そのほとんどが発音に必要なレジスタとなっています。

音色の設定がほとんどできないPSG音源や、音色をレジスタでほとんど制御しないPCMサンプリング音源と比較するとレジスタ数が多いため、FM音源の難しさを感じます。

YM3812はレジスタ数こそは多いものの、特殊な用途のレジスタは少なめです。


-- レジスタの種類 --

大雑把に分けると、

・タイマー系レジスタ
・トーン出力・音程設定レジスタ
・LFO関連レジスタ
・コネクション(アルゴリズム)・倍率レジスタ
・エンベロープレジスタ

があります。


このうち、FM音源特有のレジスタは、
・LFO関連レジスタ
・コネクション(アルゴリズム)・倍率レジスタ
の2種類くらいなので、実はそんなに難しくないかもしれません。

・タイマー関系のレジスタ

TIMER_1 ($02 : bit0~7)   タイマー1のオーバーフロー周期8bit

TIMER_2 ($03 : bit0~7)   タイマー2のオーバーフロー周期8bit

・TIM_CONF($04) 
   IRQ_RESET ($04 : bit7)   オーバーフロービットをクリア
   MASK_T1 ($04 : bit6)   タイマー1の割り込みフラグ立ち有効無効
   MASK_T2 ($04 : bit5)   タイマー2の割り込みフラグ立ち有効無効
   ST2 ($04 : bit1)   タイマー2の動作の有効無効
   ST1 ($04 : bit0)   タイマー1の動作の有効無効

YM3812は、2つのタイマーを内蔵しています。
それぞれのタイマーを設定することで、一定時間ごとに割り込み要求信号を~IRQピン(2番ピン)から出力します。

YM3812をマイコンを用いて発音する場合、必ずしも使う必要がない機能です。

・トーン出力・音程設定系レジスタ

CSM_SEL ($08)
   CSM ($08 : bit7) 音声合成モードの設定(チャンネル1~9で共通)

KON_BLK_F-NUM_H ($B0~$B8)
   KON ($B0~$B8 : bit5) チャンネル1~9のキーオン・キーオフ
   BLOCK ($B0~$B8 : bit4~2) チャンネル1~9のオクターブ
   F_NUM ($B0~$B8 : bit1~0、$A0~$A8 : bit7~0) チャンネル1~9の音程設定

キーオン・キーオフは、チャンネルごとにセットできます。
YM3812の場合、チャンネル音量レジスタがありません。2つのオペレータのうち、キャリア出力部分のみ(アルゴリズムによって操作するTLレジスタの数が異なります)のスロット出力トータルレベルレジスタ(TL : $40~$55)を操作してください。

・LFO関連のレジスタ

AM_VIB_EGTYP_KSR_MUL ($20~$35)
   AM ($20~$35 : bit7) スロットのオペレータ出力の振幅変調の有効無効
   VIB ($20~$35 : bit6) スロットのオペレータ出力の周波数変調(ビブラート)の有効無効

DEP_RHYTHM ($BD)
   DAM ($BD : bit7) 振幅変調深度の選択(チャンネル1~9で共通)
   DVB ($BD : bit6) ビブラート(周波数変調)深度の選択(チャンネル1~9で共通)


・コネクション(アルゴリズム)・倍率関係のレジスタ

TEST ($01)
   W_SEL_EN ($01 : bit5) オペレータの基本波形選択を有効無効

AM_VIB_EGTYP_KSR_MUL ($20~$35)
   MUL ($20~$35 : bit3~0) スロットの周波数倍率設定

KSL_TL ($40~$55
   TL ($40~$55 : bit5~0) スロットの出力レベル設定

FB_C ($C0~$C8
   FB ($C0~$C8 : bit3~1) チャンネルのOP1のフィードバックレベル設定
   C ($C0~$C8 : bit0) チャンネルのアルゴリズム(コネクション)の設定

WS ($E0~$F5 : bit1~0) オペレータの基本波形を設定

・キースケール、エンベロープ関係のレジスタ

CSM_SEL ($08)
   NOTE_SEL ($08 : bit6) Fナンバー値によるキースケールの区分の設定(チャンネル1~9で共通)

FB_C ($20~$35
   EG_TYP ($20~$35 : bit5) スロットのエンベロープ波形の種類の設定
   KSR ($20~$35 : bit4) スロットのキースケールレートの選択の設定

KSL_TL ($40~$55
   KSL ($40~$55 : bit7,bit6) スロットのキースケールレベルの選択の設定

AR_DR ($60~$75
   AR ($60~$75 : bit7~4) スロットのアタックレートの設定
   DR ($60~$75 : bit3~0) スロットのディケイレートの設定

SL_RR ($80~$95
   SL ($80~$95 : bit7~4) スロットのサスティーンレベルの設定
   RR ($80~$95 : bit3~0) スロットのリリースレートの設定

EG_TYP ($20~$35 : bit5) = L の時のエンベロープ波形


EG_TYP ($20~$35 : bit5) = H の時のエンベロープ波形



・リズムモード関係のレジスタ

DEP_RHYTHM ($BD)
   R ($BD : bit5) リズムモード選択ビット
   BD ($BD : bit4) バスドラムのキーオン・キーオフ
   SD ($BD : bit3) スネアドラムのキーオン・キーオフ
   TOM ($BD : bit2) タムタムのキーオン・キーオフ
   TC ($BD : bit1) トップシンバルのキーオン・キーオフ
   HH ($BD : bit0) ハイハットのキーオン・キーオフ


・使い方(制御)


--YM3812のリセット直後からの基本的な発音手順--
①音色を決定するパラメータ群をYM3812へセットする。
②音程設定レジスタに音程をセットする。
③キーオン・キーオフレジスタへキーオンしたいオペレータを選択してセットする。

ここでは、3段階のステップに分けていますが、①の音色パラメータ群のセットでは数十バイト分のパラメータがあります。音色を変更しない場合、YM3812の起動後に一度だけ書き込めばよいです。

①音色を決定するパラメータ群をYM3812へセットする。

FM音源は波形生成の原理上、多数のパラメータが必要です。
このパラメータの変化でどのような音が出るか予測することが難しく、FM音源ICへ手を出しにくくする要因となっています。

パラメータについては後述します。

②音程設定レジスタに音程をセットする。

発音に必要な音程設定レジスタは2つあります。

KON_BLK_F-NUM_H ($B0~$B8)
   BLOCK ($B0~$B8 : bit4~2) チャンネル1~9のオクターブ
   F_NUM ($B0~$B8 : bit1~0、$A0~$A8 : bit7~0) チャンネル1~9の音程設定

F_NUMとBLOCKレジスタで音程を決定します。
ですが、音程はF_NUMとBLOCKレジスタの値により一意に決まるわけではありません。
チャンネルの音程はF_NUM*(2^BLOCK)に比例します。1つの任意の周波数に設定したい場合でもF_NUMとBLOCKの組み合わせはいくつかある場合があります。

KSR:キースケールレート(音程によってエンベロープのレートを自動で変化させる機能)やKSL:キースケールレベル(音程によってトータルレベルを自動で変化させる機能)を使用しない場合は、F_NUMとBLOCKの組み合わせを意識する必要がありません。

しかし、KSRやKSLを用いる場合、F_NUMとBLOCKの組み合わせは一意に決めた方が望ましいです。

これは、キースケールの区分点がF_NUM_9のHとLの境目または、F_NUM_8のHとLの境目に設定されるという特性があるためです。
キースケールはYM3812の内部で0~15(4bit値)のキースケール値として生成されます。このキースケール値の上位3bitはBLOCKの値となり、残る1bitはF_NUM_9または、F_NUM_8によって決まります。F_NUM_9の状態を使うかF_NUM_8の状態を使うかはNOTE_SEL($08:bit6)レジスタにより選択します。
キースケール値の上位3bitはオクターブごとに均等に分割されることになりますが、キースケール値の残る下位1bitは、F_NUMをうまく決めてあげないと均等に分割されません。
もし、キースケールを音階によって均等に分割したい場合は、以下の表のように一意のF_NUMを用意する必要があります。

このキースケール区分点選択ビットNOTE_SEL($08:bit6)をどうするかは、音程の正確さかピッチベンドの可否かで決めると良さそうです。
NOTE_SEL($08:bit6)=Lにセットした場合、発音の音程はより正確に設定ができますが、高音域では、F_NUMが1023に近いため、ピッチベンドの計算が面倒になります。
NOTE_SEL($08:bit6)=Hにセットした場合、発音の音程の正確度は劣りますが、F_NUMの上限1023までに余裕が生まれるため、ピッチベンドの計算が少し楽になります。

以下の表は、入力クロックΦMが3.579545MHzまたは4MHzの時の場合と、NOTE_SEL($08:bit6)がHまたはLの場合のF_NUMの例を示しています。


入力クロックΦM = 3.579545MHz、NOTE_SEL($08:bit6)=Hの場合
音程(A=440Hz)F_NUM (2進)、赤字はキースケール境界判定ビット
C#365 (0b 01 0110 1101)
D387 (0b 01 1000 0011)
D#410 (‭0b 01 1001 1010‬)
E435 (0b ‭01 1011 0011‬)
F460 (0b ‭01 1100 1100‬)
F#488 (0b ‭01 1110 1000‬)
G517 (0b ‭10 0000 0101‬)
G#547 (0b ‭10 0010 0011‬)
A580 (0b ‭10 0100 0100‬)
A#615 (0b 10 0110 0111‬)
B651 (0b ‭10 1000 1011‬)
C690 (0b 10 1011 0010‬)


入力クロックΦM = 3.579545MHz、NOTE_SEL($08:bit6)=Lの場合
※F_NUM_8のHとLの境目を1オクターブ内の12音の中間にしようとすると、F_NUMが1023を超えるため、C#とDの間を境界とする
音程(A=440Hz)F_NUM (2進)、赤字はキースケール境界判定ビット
G517 (0b ‭10 0000 0101‬)
G#547 (0b ‭10 0010 0011‬)
A580 (0b ‭10 0100 0100‬)
A#615 (0b 10 0110 0111‬)
B651 (0b ‭10 1000 1011‬)
C690 (0b 10 1011 0010‬)
C#731 (0b‭ 10 1101 1011‬‬)
D774 (0b‭ 11 0000 0110‬)
D#820 (0b‭ 11 0011 0100‬‬)
E869 (0b‭ 11 0110 0101‬)
F920 (0b‭ 11 1001 1000‬‬)
F#975 (0b ‭11 1100 1111‬‬)


入力クロックΦM = 4MHz、NOTE_SEL($08:bit6)=Hの場合
音程(A=440Hz)F_NUM (2進)、赤字はキースケール境界判定ビット
D#367 (0b‭ 01 0110 1111‬)
E389 (0b‭ 01 1000 0101‬)
F#412 (‭0b‭ 01 1001 1100‬)
F436 (0b‭ 01 1011 0100‬‬)
G462 (0b‭ 01 1100 1110‬‬)
G#490 (0b‭ 01 1110 1010‬‬)
A519 (0b ‭10 0000 0111‬‬)
A#550 (0b ‭‭10 0010 0110‬)
B583 (0b ‭‭10 0100 0111‬‬)
C617 (0b ‭10 0110 1001‬‬)
C#654 (0b ‭10 1000 1110‬‬)
D693 (0b ‭10 1011 0101‬)


入力クロックΦM = 4MHz、NOTE_SEL($08:bit6)=Lの場合
※F_NUM_8のHとLの境目を1オクターブ内の12音の中間にしようとすると、F_NUMが1023を超えるため、C#とDの間を境界とする
音程(A=440Hz)F_NUM (2進)、赤字はキースケール境界判定ビット
A519 (0b ‭10 0000 0111‬‬)
A#550 (0b ‭‭10 0010 0110‬)
B583 (0b ‭‭10 0100 0111‬‬)
C617 (0b ‭10 0110 1001‬‬)
C#654 (0b ‭10 1000 1110‬‬)
D693 (0b ‭10 1011 0101‬)
D#734 (0b‭ ‭10 1101 1110‬)
E778 (0b‭ ‭11 0000 1010‬‬)
F824 (0b‭ ‭11 0011 1000‬‬‬)
F#873 (0b‭ ‭11 0110 1001‬)
G925 (0b‭ ‭11 1001 1101‬‬‬)
G#980 (0b ‭‭11 1101 0100‬‬‬)



これらの値は計算によって求めても良いですが、BLOCKとF_NUMのテーブルを用意すると楽に音程をYM3812へセットできます。



③キーオン・キーオフレジスタへキーオンしたいオペレータを選択してセットする。

キーオン・キーオフレジスタにキーオンしたいオペレータのON/OFFフラグを操作することで、キーオン・キーオフすることができます。

KON_BLK_F-NUM_H ($B0~$B8)
   KON ($B0~$B8 : bit5) チャンネル1~9のキーオン・キーオフ

キーオンすると、エンベロープ関連レジスタにセットされたパラメータに基づいて、各オペレータの出力振幅が時間的に変化を開始します。

キーオフするまでは、エンベロープ制御が持続するので、もう一度エンベロープ波形の先頭から振幅制御をしたい場合は、KONレジスタのオペレータON/OFFフラグをLにする必要があります。


・使い方(回路)


YM3812はCMOSのLSIであるため、最大電源電流は30mAとそれほど必要としません。
1、2個のYM3812を使った音源装置を製作する場合ではUSBなどからの給電も容易です。


YM3812のクロック源として基本的に3.58MHz(3.579545MHz)のクリスタルオシレータを使用します。


・DAC周り

YM3812は単体での音声出力はできず、基本的には専用の外付けDACが必要です。

YM3812で使用可能な外付けDAC
・YM3012 (ステレオDAC)
・YM3014 (モノラルDAC)

これらのDACもYM3812と同様に入手方法が限られるため、偽物に注意してください。


・YM3812とYM3014の接続例


YM3014を使う場合、YM3812から出力されるΦSY, MO,SH2の3種類の信号をYM3014のCLOCK, SD, LOADへ入力します。

ΦSYはシリアルデータのクロック信号出力、MOはシリアルデータ出力、SHはシリアルデータラッチとなります。

基本的には
MO -> SD
ΦSY -> CLOCK
SH -> LOAD
という感じで接続します。


YM3812のDACとしてYM3014を使う場合は、これらの信号を深く理解しなくても良いです。

上記の回路は、YAMAHAのPORTATONE「PSR11」、「PSS460」、「PSS560」のDAC周りの回路を元に作成しました。

PORTATONEの機種によってYM3014周りの回路が若干異なっています。
「PSR11」の場合、YM3812とYM3014のMO -> SD, ΦSY -> CLOCK, SH -> LOAD間の接続に抵抗1kΩを介しています。
「PSS460」「PSS560」の場合は抵抗1kΩを介さずに接続されている代わりにYM3014のVddとデジタル電源間にフェライトビーズが加えられています。
これらはおそらく、デジタル電源間とYM3812の信号間に流れる高周波成分を抑制しているのでしょうか?

DAC出力部では、「PSS560」の場合RCフィルタが追加されています。


YM3014は、外付けオペアンプが必要になります。
上記回路例では、基準電圧生成用に1回路、オーディオバッファ用に1回路分のオペアンプを使っています。

YM3014のデータシート上にはオペアンプの細かい指定はありませんが、一応072 (NJM072?)を使用した回路例が載っていあります。

ステレオDACであるYM3012の場合、オペアンプのスルーレートを割と気にして選んでいましたがモノラルDACであるYM3014の場合はスルーレートによる制約は緩いです。

NJM072のスルーレートは20V/μs、
YAMAHAのPORTATONE「PSR11」「PSS460」「PSS560」で使われているNJM4558のスルーレートは1V/μsです。
おおむね1V/μs以上のスルーレートのオペアンプが使えそうです。

YM3012基準で考えると基準電圧生成用やオーディオバッファ用のオペアンプは、スルーレートが2V/μs以上のものがいいかもしれません。

※参考  NJM4558族の標準スルーレート
NJM4558    SR:1V/μs  △
NJM4559    SR:2V/μs  ○
NJM4556A  SR:3V/μs  ○
NJM4560    SR:4V/μs  ○



YM3014の場合モノラルDACであるため、ホールド用コンデンサは必要ないと思いますがYAMAHAのPORTATONEシリーズのYM3014出力部にはホールド用コンデンサ?みたいなコンデンサ2200pFが追加されています。
YM3014のデータシート上の参考回路にはホールド用コンデンサの記述が無いので詳細は不明です。おそらくローパスフィルタなのでしょうか?

・LPFのカットオフ周波数

YM3812のサンプリングレートfs[Hz]は、

   fs = ΦM / 72   [Hz]

YM3812に入力するクロックΦMの周波数が3.58MHzの場合、サンプリング周波数は、

   fs = ΦM / 72
      = 3.58M / 72
      =49.7KHz

となります。

よって、クロックΦMの周波数が3.58MHzの時には、約25KHz(59.7/2 KHz)以上の周波数成分をカットする必要があります。
理想LPFであれば25KHz以上でカットできますが、基本的にアナログLPFのカット特性は理想LPFのカット特性からかけ離れているので、余裕をもってカットオフ周波数(フィルタ通過後に源信号が-3dBになる周波数)を15~20KHz付近にもつアナログLPF用意してあげます。

YAMAHA PSS560は10KHz付近にカットオフ周波数をもつフィルタを用意しています。


・YM3812と市販のDACとの接続例


YM3014などの専用DACがどうしても入手できなかった場合、市販のDACを用いる手段もあります。
そこで今回はYM3812の出力フォーマと市販のDACとの接続例を紹介します。


YM3812をはじめとするYAMAHAのFM音源ICは、DACを内蔵しているものと外部に専用のDACを接続しなければいけない物の2種類あります。

厄介なことに外付けDACを必要とするタイプのFM音源ICは独自フォーマットで音声データ出力しているため、基本的には市販のDACは使用できません。

市販のDACを接続して音を出すようにするには、音声データを変換する必要があります。



・YM3812の音声データ出力フォーマット

YM3812は1サンプル分の16bitデータを任意の数シフト(出力値の倍率だと1,1/2 , 1/4,1/8 …)し10bitのデータとして送り出します。
この10bitのデータのMSB(Bit9)は常に符号ビットとなります。
シフト数は0~6bitの7種類なので、3bitでシフト情報を送り出します。
つまり10bitのデータ+シフト情報3bitの計13bitが出力されます。


例えば-512 ~ 511の数値の場合、10bit以内の2進データなのでシフトせずに出力するのでデータは無劣化となります。
逆に-32768 ~ -16385 または 16384 ~ 32767の数値の場合、16bitの数値データとなるので6bit分シフトして10bitに丸め出力します。

かつての市販のDAC(MSBファースト2'コンプリメント右詰め16bitDAC)は1フレーム16bitのデータを受信してアナログ値を出力するので、YM3812が出力した値10bit+シフト3bitのデータを16bitへ変換する必要があります。

シフト回路が必要になるので、回路規模が少し増えます。
CPLDやFPGAを使うのが良いでしょう。


・データのシフト
YM3812は16bitのデータを10bitに丸めるため、任意の数だけシフトします。数値的にはx2^(-N)となります。
YM3812が送信する実際のシフトデータ3bitはどのようになっているかというと、1~7の値を取ります。0は送信しません。

アナログ値Vout[V]と入力データは次のような関係があります。

   Vout = ((1/2) * Vmax) + ((1/4) * Vmax * (-1 + D9 + D8*2^(-1) + D7*2^(-2) + … + D0*2^(-9) + 2^(-10)) * 2^(-N))   [V]

   N = ~S2*4 + ~S1*2 + ~S0      : 「~」はビット反転記号
      = 7 - (S2*4 + S1*2 + S0)

D0 ~ D9 : 入力データ10bit(D9は符号ビットでD9=1で正、D9=0で負、)
S0 ~ S2 : シフト数データ3bit  (S=1~7)


・変換回路

ロジックICを使用したYM3812 -> MSBファースト2'コンプリメント右詰め16bitDAC用変換回路を作ってみました。
μPD6376は過去に秋月電子で販売されていたステレオDACです。
スーパーファミコンにも使用されているので、部品取りなどして入手すると良さそうです。

上記回路例では、NJM4558の電源を単電源の5Vとしていますが、±10Vにした方がよいです。


変換する上でポイントとなるのが、符号ビットの扱いとシフト回路です。

・符号ビットの扱い
YM3812が出力するデータの符号はD9(MSB)=1で正値、D9(MSB)=0で負値となっています。
市販のDACは2の補数値を入力しなければいけないため、D15(MSB)=0で正値、D15(MSB)=1で負値となるように変換します。
幸いにもMSBのみビット反転をすれば良さそうです。


・シフト回路
10bitのデータを任意のビット数シフトするシフト回路を用意します。

パラレルのシフト回路を作成するとそれなりに回路規模が大きくなってしまうので、今回はDACへデータ送信する時にシリアルでシフト処理をしています。
今回作成した回路のシフト処理は、
変換後のデータを出力するシフトレジスタのシフトクロックを止める手法をとっています。


出力後のフィルタは、ポータートーンの回路と同様で良いでしょう。
上記回路例ではサレンキー型の3次ローパスフィルタを使っています。



・使用例 

ページサイズの都合上、使用例は別のページにしています。
YM3812 (OPL2)の使い方➁





現在執筆中です。内容がちょくちょく変更されますので、ご注意ください。








0 件のコメント:

コメントを投稿