YAMAHA YMZ294音源

秋月電商で販売しているヤマハ音源IC(YMZ294)を Arduinoで制御して音出してみます。このLSIの発売日は2002年と10年以上前のモノになります。YMZ294で検索すると、何件かの ホームページを見つけることができます。いくつか参考とさせていただきました。


回路図

ArduinoはLeonardoを想定しています。 YMZ294の8ビットのデータバスに、LeonardoのD2,D3,...D9を接続します。 また、制御ピンWrite(/WR)、Chip Select(/CS)、AOにそれぞれ、D10、D13,D1を接続します。 リセット(/IC)にD12を接続します。 なを、Arduino Unoでも同じ接続で良いです。



秋月で購入したYMZ294には、4MHzの水晶発信子が付属していました。いつも接続に戸惑ってしまうので、下に実物の写真と共に掲載しておきます。 上から見て黒丸がNCで、左周りにGround, Output, +VDDです。



ピン番号とGPIOの対応づけをログラムに定義しておきます。

// データバス
#define PIN_D0  2
#define PIN_D1  3
#define PIN_D2  4
#define PIN_D3  5
#define PIN_D4  6
#define PIN_D5  7
#define PIN_D6  8
#define PIN_D7  9
// 制御ピン
#define PIN_WR 10
#define PIN_A0 11
#define PIN_IC 12
#define PIN_CS 13

初期設定

各ピンを初期設定します。

void setup() {
    pinMode(PIN_WR, OUTPUT);
    pinMode(PIN_A0, OUTPUT);
    pinMode(PIN_IC, OUTPUT);
    pinMode(PIN_CS, OUTPUT);
    
    pinMode(PIN_D0, OUTPUT);
    pinMode(PIN_D1, OUTPUT);
    pinMode(PIN_D2, OUTPUT);
    pinMode(PIN_D3, OUTPUT);
    pinMode(PIN_D4, OUTPUT);
    pinMode(PIN_D5, OUTPUT);
    pinMode(PIN_D6, OUTPUT);
    pinMode(PIN_D7, OUTPUT);
データを書き込む

8ビットのデータをYMZ294に書き込むには、データを1ビットづつGPIOに設定します。

// Set 8bit data to 8 Pins
void send(uint8_t d)
{
    uint8_t c=d&0x01;
    digitalWrite(PIN_D0,c);
    d>>=1; c=d&0x01;
    digitalWrite(PIN_D1,c);
    d>>=1; c=d&0x01;
    digitalWrite(PIN_D2,c);
    d>>=1; c=d&0x01;
    digitalWrite(PIN_D3,c);
    d>>=1; c=d&0x01;
    digitalWrite(PIN_D4,c);
    d>>=1; c=d&0x01;
    digitalWrite(PIN_D5,c);
    d>>=1; c=d&0x01;
    digitalWrite(PIN_D6,c);
    d>>=1; c=d&0x01;
    digitalWrite(PIN_D7,c);

    init294();  //YMZ294の初期化(後述)
}                

YMZ294のレジスタにデータを書き込むには2つの値(アドレスとデータ)、をそれぞれ書き込みます。書き込みはA0, /CS, /WRの3つのピンを使います。 ちなみに、"/"は通常は正、使いたい時にゼロに設定するピンであることを示しています。A0が0の時レジスタのアドレスを設定、 A0が1の時、レジスタにデータを書き込みます。 書き込みの手順(シーケンス)は次の図を見て下さい。

// Set Address and Data
// a  : address
// d  : data
void set_address_data(uint8_t cs, uint8_t a, uint8_t d){
    digitalWrite(PIN_A0,0);
    digitalWrite(PIN_WR,0);
    digitalWrite(PIN_CS,0);
    send(a);    delay(1);
    digitalWrite(PIN_CS,1);
    digitalWrite(PIN_WR,1);
    delay(1);
      
    digitalWrite(PIN_A0,1);
    digitalWrite(PIN_WR,0);
    digitalWrite(PIN_CS,0);
    send(d);    delay(1);
    digitalWrite(PIN_CS,1);
    digitalWrite(PIN_WR,1);
    delay(1);
    }

レジスタの初期値設定

YMZ294をリセットし、各レジスタのレジスタに初期値を設定します。

void init294() {
    // Reset
    digitalWrite(PIN_IC,0);
    delay(100);
    digitalWrite(PIN_IC,1);

    // YMZ294 Register Initialize
    // 楽音周波数
    send_data(0x00,0x00);    //Channel A Low
    send_data(0x01,0x00);    //Channel A High
    send_data(0x02,0x00);    //Channel B Low
    send_data(0x03,0x00);    //Channel B High
    send_data(0x04,0x00);    //Channel C Low
    send_data(0x05,0x00);    //Channel C High
    delay(10);

    send_data(0x06,0x00);    //ノイズ周波数の設定
    // ミキサーの設定
    send_data(0x07,0x38);    //楽音ChannelA,B,C ON
    delay(10);
  
    // 音量コントロールどDAC
    send_data(0x08,0x00);    //Channel A
    send_data(0x09,0x00);    //Channel B
    send_data(0x0A,0x00);    //Channel C
    delay(10);
  
    // エンベロープ周波数
    send_data(0x0B,0x00);   //Low
    send_data(0x0C,0x00);   //High
    // エンベロープの形状
    send_data(0x0D,0x0D);
}
音を出す

音を出すには周波数を設定し、音量を上げます。ここでは、MIDIのキーコードを与えると音が出る void NoteOn(uint8_t keycode)関数を示します。Channel Aの周波数を設定し、音量を上げています。

// Convert MIDI Note Number to Frequency Register Value 
uint16_t mCoef[128]= {
 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4050,
 3822, 3608, 3405, 3214, 3034, 2863, 2703, 2551,
 2408, 2273, 2145, 2025, 1911, 1804, 1703, 1607,
 1517, 1432, 1351, 1276, 1204, 1136, 1073, 1012,
  956,  902,  851,  804,  758,  716,  676,  638,
  602,  568,  536,  506,  478,  451,  426,  402,
  379,  358,  338,  319,  301,  284,  268,  253,
  239,  225,  213,  201,  190,  179,  169,  159,
  150,  142,  134,  127,  119,  113,  106,  100,
   95,   89,   84,   80,   75,   71,   67,   63,
   60,   56,   53,   50,   47,   45,   42,   40,
   38,   36,   34,   32,   30,   28,   27,   25,
   24,   22,   21,   20,   19,   18,   17,   16,
   15,   14,   13,   13,   12,   11,   11,   10 };
void NoteOn(uint8_t keycode)
{
    uint16_t x = mCoef[keycode];
    uint8_t hb=(x>>8)&0x0F;
    uint8_t lb=(x&0xFF);
    send_data(0x00,lb);
    send_data(0x01,hb);
    send_data(0x08,0x08);   //音量を上げる
}

音を止める時は、音量をゼロにします。

void NoteOn()
{
    send_data(0x08,0x00);   //音量を下げる
}
デモビデオ