MZ-1500 SN76489ANのウェイト

 PSG(正確にはDCSGですが)のチップであるSN76489ANをアクセスすると、19〜34クロックのウェイトがかかります。なるべく高速にPSGをアクセスしたい場合、PSGのアクセス特性に合わせた書き込みを行う必要があります。PSGとCPUに入っているクロックは共通ですので、CPUの命令実行にかかるクロックを数えることでPSGと同期して動くプログラムを書くことができます。

 PSGのアクセス特性は、ソフトウェア(CPU)から見て

 となっています。

 まず、最初のI/Oライトについてはタイミングの取りようがないので、適当に出力するしかありません。一度出力を行えば、ウェイトによって同期が取られるため、2回目以降のI/Oライトに関して上記のアクセス特性に従ってタイミングを合わせることができるようになります。

・例1 - OUT (0F2h),A を連続して並べる場合


    LD      A, 9Fh          
    OUT     (0F2h), A       
    OUT     (0F2h), A       
1つ目のOUT命令にかかるウェイトは不明ですが、命令終了時点でPSG側のタイミングと同期が完了します。
この場合、2つ目のOUT命令は
4(M1サイクル) + 3(メモリリードサイクル) + 2+23(I/Oライトサイクル)
というふうに実行されます。I/Oライトサイクル間の実行時間が9クロック未満(7クロック)ですので、残り2クロックはI/Oライトサイクルのウェイトとして消費されます。
よって、32クロック周期で1バイトを書き込むことができます。
(ただし、同じ値しか書き込めないので実用性はありません)

・例2 - OUT (C),r を連続して並べる場合


    LD      C, 0F2h         
    OUT     (C), A          
    OUT     (C), B          
この場合、2つ目のOUT命令は
4(M1サイクル) + 4(M1サイクル) + 1+23(I/Oライトサイクル)
というふうに実行されます。I/Oライトサイクル間の実行時間が1クロック増えましたが、まだ9クロック未満(8クロック)ですので、I/Oライトサイクルの追加ウェイトが1に減るだけで、全体の実行時間は例1と変わりません。
よって、例1と同じく、32クロック周期で1バイトを書き込むことができます。

・例3 - OUT (0F2h),A の間にNOPを入れた場合


    LD      A, 9Fh          
    OUT     (0F2h), A       
    NOP                     
    OUT     (0F2h), A       
この場合、NOP以降は
4(M1サイクル:NOP) + 4(M1サイクル:OUT) + 3(メモリリードサイクル) + 14+23(I/Oライトサイクル)
というふうに実行されます。I/Oライトサイクル間の実行時間が9クロックを超えてしまったため、2つ目のI/Oライトサイクルが+16クロック分後ろにずれ、その結果ウェイトで消費されるクロックが増えてしまいました。よって、48クロック周期で1バイトを書き込むことになります。

・例4 - OUT (0F2h),A の間にさらに命令を入れた場合


    LD      A, 9Fh          
    OUT     (0F2h), A       
    NOP                     
    NOP                     
    NOP                     
    INC     HL              
    OUT     (0F2h), A       
この場合、NOP以降は
18(NOP×3,INC HL) + 4(M1サイクル:OUT) + 3(メモリリードサイクル) + 23(I/Oライトサイクル)
というふうに実行されます。例3よりも命令が増えていますが、例3ではウェイトで消費されていたクロックを命令実行に充てているため、例3と同じく48クロック周期で1バイトを書き込むことができます。

・例5 - OUT (0F2h),A の間にさらに1クロック追加した場合


    LD      A, 9Fh          
    OUT     (0F2h), A       
    OR      A               
    RET     C               
    NOP                     
    INC     HL              
    OUT     (0F2h), A       
例4にさらに1クロック追加しました。この場合、
19 + 4(M1サイクル:OUT) + 3(メモリリードサイクル) + 15+23(I/Oライトサイクル)
というふうに実行されます。I/Oライトサイクル間の実行時間が9+16クロックを超えてしまったため、2つ目のI/Oライトサイクルがさらに+16クロック分後ろにずれ、ウェイトで消費されるクロックが増えて、64クロック周期で1バイトを書き込むことになります。

・例6 - OTIR を使った場合


    OTIR                    
OTIR命令は 12+4(I/Oライト)+5 のサイクルで実行されます。PSGアクセスでは
17 + 8+23(I/Oライトサイクル)
というふうに実行されます。48クロック周期で1バイトを書き込むことができます。
※この方法でタイミングを合わせられるのは、ポート F2h, F3h を介して各PSGに単体アクセスを行ったときだけです。ポート E9h を使って2つのPSGに同時にアクセスした場合、タイミングは不定です。
戻る