TurboRのPCM機能

※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

TurboRのPCM機能は、8bitのAD/DAと15khzのサンプリング周波数をサポートする機能で
オーディオ用途というよりはちょっとした遊びや実験機能として搭載されている。
専用ソフトはエコーや波形編集機能を持つので当時としては興味深かった。

プログラミング的な使い方はBIOSで提供された録音再生サブルーチンAPIを使う方法と、
直接DA/ADをコントロールする方法がある。
(拡張BASICでもPCM録音再生はサポートされていたがこれはBIOS APIを使っているようだ)

PCM用BIOSサブルーチンは、PCMPLAY(0x0186)、PCMREC(0x0189)がMAIN ROMのエントリに新設された。
Aレジスタにサンプリング周波数指定、VRAM/MAINRAMエリア各種設定フラグを置いてコールする。

Aレジスタ内容
b7,b6,b5,b4,b3,b2,b1,b0
mem,0,0,0,0,0,frq1,frq0

記録開始アドレスは24bit指定で、BC,DE,HLを使うが、このとき、開始アドレスが、
E,H,L、終了アドレスがD,B,Cを使うやや変則的な割り当てとなる。
戻り値はフラグ(キャリー)、Aレジスタ、(EHLはエラーアドレス)を判定に使う。

このBIOSサブルーチンAPIだとPCMのデータはメモリ制限があるため別途拡張マッパーメモリを
使いたい場合は直接DA/ADを制御する必要がある。



PCM録音再生機能は若干説明不足なところがある。
基本性能は8bitDACで、サンプリング周波数は映像信号から発生させた15.75khzを(63uSec)
最小分解能として分周した周期となる。

15.75khz(63.5uSec)
7.8khz(126uSec)
5.25khz(190uSec)
3.937khz(0.254mSec)

サンプリング周波数タイミングを計る場合は、PCM専用の2bitカウンタと、TRで新規に追加された
カウンタを使う場合が考えられる。

ADC回路は現代の設計とは若干違いがあって、ADC処理のためのファームウエア部分の処理を
コーディングする必要がある。(この部分をBIOS APIで提供しているともいえる)
現在の半導体で設計製造されているADCは、内部にサンプルホールドとコンパレータ処理など
様々な処理をADC内部ロジック回路のシーケンサが自動実行してくれていて、
CPU側からは単にADCのスタート開始制御と、データの読み込みだけとなっている。

ところがTurboRに搭載されているADCはそうした手間を自動化してくれる機能はないので、
ソースコードにファームウエアとしてADC処理するコードを書く。
つまり、ADCのデータをサンプルホールドしたら、その電圧値をデジタル化するために
コンパレータで電圧比較する。そのためにDACの8bitレジスタへデータを出力してゆき
アナログ音声の電圧値をデジタル化する。
完全に素のAD/DA回路なので仕組みを理解するには良いが若干手間が必要。


回路で書くと、アナログ電圧をサンプルしてコンデンサに蓄電し維持[Sample/Hold]、
コンパレータでDAC出力電圧と比較[Comparator]、その結果を1bitのフラグで判定する。
これをサンプリング周波数のタイミングで処理してデータを得る。
この種のADCを逐次比較型ADC(SAR)という。


Analog IN ----> [Sample/Hold] ----> [Comparator] ---> [1bit flag]
+
|
[DAC Out]

最近のマイコンやADCだとこの一連のシーケンス処理は自動処理してくれる。

音声入出力部分の回路はフィルタとスイッチが組み合わされた回路。
フィルタはAD/DA回路に必ず入っているもので一般的なもの。
サンプリング周波数以上の信号をカットして正しい信号入力するためと、
DAC出力のエリアシングノイズをカットするためのもの。


Analog IN ---> [Select S/W] ---> [Analog Filter] ---> [ADC]
+
Analog OUT <---- [Select S/W] <----[Filter] <---- [DAC]


PCM関係のI/Oレジスタは、I/Oアドレス0xA4,0xA5に配置されている。


0xA4 #WRITE DA7,DA6,DA5,DA4,DA3,DA2,DA1,DA0
0xA4 #READ 0,0,0,0,0,0,CT1,CT0

0xA5 #WRITE 0,0,0,SAMPL/HOLD,SELECT,FILTER,MUTE,ADDA BUFFER
0xA5 #READ COMP,0,0,SAMPL/HOLD,SELECT,FILTER,MUTE,ADDA BUFFER



BUFFはレジスタは2ペア。DACへのデータ設定をダブルバッファにして
データ書き換え時のノイズを低減するもの。
シングルバッファだとDACレジスタの出力がそのままダイレクトに電圧値で出力される。
(ビデオ画面のシングルバッファ・ダブルバッファと同じ)
AD変換時はシングルバッファ、DA変換時はダブルバッファとする。


SMPLはADC内部の電圧蓄積コンデンサを使ってある瞬間のアナログ音声信号の電圧を
サンプルし、その電圧を確実に維持(ホールド)するタイミングの制御をする。

COMPは一旦サンプルホールドされたアナログ音声信号の電圧を読み取る際に、
DACラダー出力電圧と順次比較していって特定の電圧レベルを求める際のもの。

サンプルホールド回路でアナログ信号がコンデンサに蓄電しているから、
その電圧をDACを使って様々な電圧を出してコンパレータで比較してゆく。その結果が
このレジスタのビットで、DAC出力しながらこのビットを参照して特定の電圧を決定する。
DACの出力とコンパレータの電圧比較結果はコードを書く必要がある。

これら動作と変換アルゴリズムは一般的な逐次比較(SAR)型ADCの動作説明を参考にするとよいだろう。


CT0,CT1これはタイマー。
サンプリングしたりPCM再生する際にこのタイマービットをポーリングしつつ、
データの読み書きをする。


C言語で書くとたぶんこんな感じ。


#include <stdio.h>

extern unsigned char inp(unsigned char);
extern outp(unsigned char , unsigned char);

void main(void){

	outp(0xA5,0x3);		//MUTE=OFF,ADDABUFF=SINGLE
	outp(0xA4,0xff);	//DAC out

}

これをSINテーブルのデータを連続して動作させればシグナルジェネレータになる。
8bitのDA/ADは128が0となるsigned intで符号付き整数。


逐次比較アルゴリズムはちょっとややこしい

1,サンプルホールドで電圧値を一定に保つ。
2,測定対象Xに対してDACを0-255まで繰り返し出してコンパレータ比較し結果を得る。
3,DACの値が測定入力電圧Xとする。
4,サンプルホールド解除

ADCが0Vのとき、符号付整数で127になっているはずなので、DACを255から順に0へずらして
ゆき、コンパレータ出力が0から1(または1から0への変化かもしれないが)へ急に
変化した所が同じ電圧値ということで、DACへの比較出力結果がそのままADCの値となる。
理屈で言えば単純なのだが、色々とアルゴリズムを考えようとすると難しくなる。

R800は現在でもAVRやPICのような8bitのRISCマイコンと同じくらいかなり速いので
PCM処理のためのポーリング処理はさほど問題にはならないだろう。
場合によってはFFTやソフトウエアラジオ等様々な音声処理も可能だろう。

8bitのCPUだとこれらの処理はADC内部のシーケンサが自動処理してくれるほうが簡単だし
分散処理としても有効だが、TRではそうなっていないのでPCM処理を行う場合は
サンプリング周波数のタイミングは割り込みを使っていないので基本的にポーリング処理
となるためPCM処理に集中しなけれはいけない。
R800はかなり高速なので処理は十分だろう。
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。