#028

【MSX,Z88DK】C言語でPSG入門【MSX,Z88DK】C言語でPSG入門戻る 設定


概要

 MSXは標準で3チャンネルのPSGを発生させることが出来ます。この制御はLSIのレジスタに値を書き込むことによって行ないます。BIOSにそのためのルーチンが用意されています。

【参考】1章 PSGと音声出力 - MSX Datapack wiki化計画(外部サイト)

ソース

void wrtpsg( unsigned char reg, unsigned char val )
{
#asm
    LD      IX, 2
    ADD     IX, SP
    LD      E, (IX)     ; val
    LD      A, (IX+2)   ; reg
    CALL    0093h       ; WRTPSG
#endasm
}

void main()
{
    wrtpsg( 8, 10 );                    //  音量
    wrtpsg( 0, 0xac );                  //  音階「ド」(L)
    wrtpsg( 1, 0x01 );                  //  音階「ド」(H)
    wrtpsg( 7, 0b00111110 );            //  出力開始
    for( int i = 0; i < 10000; i++ ){}  //  音の長さ
    wrtpsg( 0, 0x7d );                  //  音階「レ」(L)
    wrtpsg( 1, 0x01 );                  //  音階「レ」(H)
    for( int i = 0; i < 10000; i++ ){}  //  音の長さ
    wrtpsg( 0, 0x53 );                  //  音階「ミ」(L)
    wrtpsg( 1, 0x01 );                  //  音階「ミ」(H)
    for( int i = 0; i < 10000; i++ ){}  //  音の長さ
    wrtpsg( 7, 0b00111111 );            //  出力停止
}

解説

BIOSコール

 PSGを鳴らすためには、PSGレジスタへの書き込みを複数回行なう必要があります。ですので、まずはその処理を関数化しておきます。

 wrtpsg()関数は、PSGレジスタへ値を書き込む関数です。引数にはレジスタ番号と値を渡します。中身は全てアセンブリ言語で、BIOSコールのためのコードのみとなっています。

 Z88DKのC言語でインラインアセンブラを使用する場合、関数の引数はスタックから取得することが出来ます。関数の引数が複数ある場合、後ろから格納されます。

 AレジスタにPSGレジスタ番号、Eレジスタに書き込みたい値をセットして0093hをCALLすると、PSGレジスタへ値が書き込まれます。

音量

 PSGレジスタ8でチャンネルAの音量を制御します。bit0-3で音量を指定します。bit4はエンベロープ使用フラグで、0:使用しない、1:使用する、です。

音階

 PSGレジスタ0~5が、PSGチャンネルA~Cの音階に割り当てられています。

 分周比を12bitで指定することによって音階を変化させます。例えばチャンネルAであれば、PSGレジスタ0に下位8bit、レジスタ1に上位4bitを指定します。

 書き込むべき値の計算式は、以下の通りです。

 111860.78125 / 周波数

 例えば、「ラ」の音(440Hz)を鳴らしたい場合、111860.78125 / 440 = 254(0FEh)ですので、PSGレジスタ0に0xfe、PSGレジスタ1に0x00を書き込みます。

出力選択

 PSGレジスタ7で各チャンネルの出力を選択します。bit0-2で、チャンネルA-Cそれぞれのトーン出力を指定します。0:ON、1:OFFになります。bit3-5はノイズ出力の指定です。


関連記事

#025 【MSX,Z88DK】C言語でBeep音

#022 【MSX,Z88DK】C言語でキースキャン


最終更新日時:2022/05/03
戻る戻る back