,{t},{BSIZE:1 0|SIZE:100%} ,{BSIZE:0}←[[6章 マッパーRAMセグメント]] ,{BSIZE:0|RIGHT}[[8章 アプリケーション作成上の注意|8章 アプリケーション作成上の注意]] →  この章では、MSX turbo Rに新しく内蔵されているハードウェアについて説明します。 !!7.1 システムタイマー  R800は、命令の実行時間が一定ではないので、CPUの命令実行時間から、ウェイトのタイミングなどをとることができません。そこで、MSX turbo Rでは、数10μ秒〜数10m秒程度の短い時間の検出ができるように、システムタイマーが追加されました。  システムタイマーは、16ビットのクリア・データ読み出しが可能なカウンタで、10.738635MHzのシステムクロックを42分周(10.738635MHz/42=255.68KHz)したクロックでカウントアップされます。つまり、最下位ビットは3.911μ秒毎にカウントアップされることになります。なお、カウンタをクリアしてからカウントが1になるまでの時間は、0〜3.911μ秒の範囲です。  カウンタの読み出し時に、データのラッチ機能はありません。カウンタの上位・下位読み出しの間にクロックが入ると、正しいカウント値が読み出されないので注意して下さい。 表1.6 システムタイマーのI/Oポート ,{t},{BSIZE:1 0} ,{c},{BSIZE:1 0|SIZE:120},{BSIZE:1 0|SIZE:40},{BSIZE:1 0} ,I/Oポート番地,R/W,機能 ,{c},{BSIZE:0},{BSIZE:0},{BSIZE:0} ,0E6H ,W ,任意のデータを書き込むと、カウンタがクリアされる。 ,0E6H ,R ,カウンタデータの下位8ビットの読み出し。 ,0E7H ,R ,カウンタデータの上位8ビットの読み出し。  割り込みルーチンなどから呼ばれるプログラムは、カウンタをクリアすると、フォアグラウンドで動作しているプログラムに影響を与えるので、クリアしないで下さい。  具体的には、次のサンプルプログラムのようにします。 countlow equ 0e6h ; カウンタ下位8ビット counthigh equ 0e7h ; カウンタ上位8ビット .z80 ; ; Bレジスタで指定された時間待つ。 ; 待つ時間は、B*3.911μ秒 ; 誤差は、-3.911μ秒〜+0μ秒 ; 0を指定してはいけない。 ; 割り込みは禁止されていなければならない。 ; C,A,Fの各レジスタは破壊される。 ; wait: in a,(countlow) ; カウンタの現在値を得る ld c,a ; それを保存する wait_loop: in a,(countlow) ; カウンタの現在値を得る sub c ; 経過時間を算出する cp b ; 指定された時間経過したか? jr c,wait_loop ; 経過していなければループする ret !!7.2 PCM  ここでは、PCMのI/Oポートや録音・再生の手順などを解説します。 !7.2.1 PCMのI/Oポート  PCM録音・再生のためのI/Oポートは以下のとおりです。 表1.7 PCMのI/Oポート ,{t},{BSIZE:1 0} ,{c},{BSIZE:1 0|SIZE:120},{BSIZE:1 0|SIZE:70},{BSIZE:1 0|SIZE:70},{BSIZE:1 0|SIZE:70},{BSIZE:1 0|SIZE:70},{BSIZE:1 0|SIZE:70},{BSIZE:1 0|SIZE:70},{BSIZE:1 0|SIZE:70},{BSIZE:1 0|SIZE:70} ,番地 ,bit7,bit6,bit5,bit4,bit3,bit2,bit1,bit0 ,{c},{BSIZE:0},{BSIZE:0},{BSIZE:0},{BSIZE:0},{BSIZE:0},{BSIZE:0},{BSIZE:0},{BSIZE:0},{BSIZE:0} ,0A5H(Write) ,0 ,0 ,0 ,SMPL,SEL ,FILT,MUTE,ADDA ,0A5H(Read) ,COMP,0 ,0 ,SMPL,SEL ,FILT,MUTE,BUFF ,0A4H(Write) ,DA7 ,DA6 ,DA5 ,DA4 ,DA3 ,DA2 ,DA1 ,DA0 ,0A4H(Read) ,0 ,0 ,0 ,0 ,0 ,0 ,CT1 ,CT0 ,{t},{BSIZE:0|SIZE:100%} ,{c},{BSIZE:0|SIZE:140},{BSIZE:0|SIZE:20},{BSIZE:0|SIZE:30},{BSIZE:0} ,ADDA(BUFF),バッファモード{COLS:3}, , ,D/Aコンバータの出力をシングルバッファにするか、ダブルバッファにするかを指定します。D/A時にはダブルバッファに、A/D時にはシングルバッファにして下さい。{COLS:3}, , ,,0, シングルバッファ(A/D時、リセット時) , ,,1, ダブルバッファ(D/A時) ,MUTE ,ミューティング制御{COLS:3}, , ,システム全体の音声出力をON/OFFします。{COLS:3}, , ,,0, 音声出力OFF(リセット時) , ,,1, 音声出力ON ,FILT ,サンプル・ホールド回路入力信号の選択{COLS:3}, , ,A/D時にサンプル・ホールド回路に入力する信号を、フィルタの出力信号にするか、基準信号(ground level)にするかを選択します。{COLS:3}, , ,,0, 基準信号(リセット時) , ,,1, フィルタ出力信号 ,SEL ,フィルタ入力信号の選択{COLS:3}, , ,ローパスフィルタに入力する信号を、D/Aコンバータの出力信号にするか、マイクアンプの出力信号にするかを選択します。{COLS:3}, , ,,0, D/Aコンバータ出力信号(リセット時) , ,,1, マイクアンプ出力信号 ,SMPL ,サンプルホールド信号{COLS:3}, , ,入力信号をサンプルするか、ホールドするかを選択します。{COLS:3}, , ,,0, サンプル時(リセット時) , ,,1, ホールド時 , ,A/D時には、信号をホールドする前に、最低7μ秒はサンプルしなければなりません。{COLS:3}, ,COMP ,コンパレータの出力信号{COLS:3}, , ,サンプル・ホールドの出力信号と、D/Aコンバータの出力信号とをくらべて、どちらが大きいかを読み出すことができます。{COLS:3}, , ,,0, D/A出力>サンプル・ホールド出力 , ,,1, D/A出力<サンプル・ホールド出力 ,DA7〜DA0 ,D/A出力データ{COLS:3}, ,CT1、CT0 ,カウンタデータ{COLS:3}, , ,63.5μ秒ごとにカウントアップされます。{COLS:3}, , ,D/A時(ADDAが1)には、カウントアップに同期して、0A4H番地に書かれたデータが繰り返し出力されます。0A4H番地にデータを書き込むと、カウンタはクリアされます。{COLS:3}, , ,A/D時(ADDAが0)には、0A4H番地に書かれたデータはすぐに出力されます。0A4H番地にデータを書き込んでもカウンタはクリアされません。{COLS:3} !7.2.2 PCM再生  PCMは次の手順で再生します。 +ADDAを1に、MUTEを1に、SELを0にします(I/Oポートの0A5H番地に00000011Bを出力する)。 +CT1、CT0を読んで、サンプリング周期を検出します。 +PCMデータを出力します。このとき、カウンタは自動的にクリアされます。 +データの個数回、2と3とを繰り返します。 .z80 ; ; PCM再生 ; ; 入力 HL = PCMデータの開始アドレス ; BC = PCMデータの長さ ; E = 再生サンプリング周期 ; 1 15.75KHz ; 2 7.875KHz ; 3 5.25KHz ; 戻り値 なし pcmdac equ 0a4h ; D/A コンバータ (Write) pcmcnt equ 0a4h ; カウンタ (Read ) pcmcntl equ 0a5h ; PCMコントロール(Write) pcmstat equ 0a5h ; PCMステータス (Read ) pcmplay: ld a,00000011b out (pcmcntl),a ; D/Aモードに設定 di ; タイミングの正確さのために、 ; 割り込みを禁止する pcmplay_loop: in a,(pcmcnt) ; カウンタを読み取る sub e ; 希望の値になったか? jr c,pcmplay_loop ; そうでないならループする ld a,(hl) ; データを読み取る out (pcmdac),a ; DACに出力する inc hl ; 次にデータを指し示す dec bc ; カウンタを減らす ld a,c ; カウンタは0か? or b jr nz,pcmplay_loop ; そうでないならループする ei ; 割り込み禁止を解除 ret !7.2.3 PCM録音  PCM録音は次の手順で行います。 +ADDAを0に、MUTEを0に、FILTを1に、SELを1に、SMPLを0にします(I/Oポートの0A5H番地に00001100Bを出力して、入力アナログ信号をサンプルする)。 +CT1、CT0を読んで、サンプリング周期を検出します。 +最低7μ秒待ちます。この7μ秒が2に含まれていれば待つ必要はありません。 +SMPLを1にして(I/Oポートの0A5H番地に00011100Bを出力する)、入力アナログ信号をホールドします。 +逐次変換のシーケンスによって、D/Aコンバータのデータを上位ビットから変化させながら、D/Aコンバータ出力と入力アナログ信号との比較結果をCOMPから読み込んで、各ビットを決定し、データを格納します。 +SMPLを0にします(I/Oポートの0A5H番地に00001100Bを出力する)。 +2から6を繰り返します。 .z80 ; ; PCM録音 ; ; 入力 HL = PCMデータの開始アドレス ; BC = PCMデータの長さ ; E = 再生サンプリング周期 ; 1 15.75KHz ; 2 7.875KHz ; 3 5.25KHz ; 戻り値 なし pcmdac equ 0a4h ; D/A コンバータ pcmcnt equ 0a4h ; カウンタ pcmcntl equ 0a5h ; PCMコントロール pcmstat equ 0a5h ; PCMステータス ; 1ビットA/D変換マクロの定義 adconv macro next_bit,strip local adconv_not_change out (pcmdac),a ; データを出力 db 0edh,70h ; PCMSTATからデータを読み込み、 ; フラグにのみ反映させる jp m,adconv_not_change ; 入力アナログ信号の方が大きければ、 ; データはそのまま and strip ; 入力アナログ信号の方が小さいので、 ; ビットを0にする adconv_not_change: or next_bit ; 次のビットを1にする endm pcmrec: ld a,00001100b out (pcmcntl),a ; A/Dモードに設定 ld d,0 ; カウンタ検出の初期値を設定する di ; タイミングの正確さのために ; 割り込みを禁止する pcmrec_loop: in a,(pcmcnt) ; カウンタを読み取る cp d ; 希望の値になったか? jr nz,pcmrec_loop ; そうでないならループする add a,e ; 次のカウンタの値を作る and 11b ld d,a ; それを保存する ; 上記ループにより7μ秒を満足する exx ld a,00011100b out (pcmcntl),a ; データをホールドする ld c,pcmstat ; COMPビットのポートアドレスを設定する ld a,80h ; 出荷データを設定する adconv 01000000b,01111111b ; 順次ビットを変換する adconv 00100000b,00111111b adconv 00010000b,01011111b adconv 00001000b,01101111b adconv 00000100b,01110111b adconv 00000010b,01111011b adconv 00000001b,01111101b adconv 00000000b,01111110b exx ld (hl),a ; データを格納する ld a,00001100b out (pcmcntl),a ; データのホールドを解除する inc hl ; 次のデータを指し示す dec bc ; カウンタを減らす ld a,c ; カウンタは0か? or b jr nz,pcmrec_loop ; そうでないならループする ld a,00000011b out (pcmcntl),a ; D/Aモードに設定。MUTEを解除する ei ; 割り込み禁止を解除 ret ,{t},{BSIZE:0} ,注意{SIZE:100|CENTER},{BSIZE:0|SIZE:50},{BSIZE:0}このプログラムは、Z80では速度が間に合わない場合があります。 ,{t},{BSIZE:1 0|SIZE:100%} ,{BSIZE:0}←[[6章 マッパーRAMセグメント]] ,{BSIZE:0|RIGHT}[[8章 アプリケーション作成上の注意|8章 アプリケーション作成上の注意]] →