SH-2A 基板 (2)

インターフェース 2010 年 6 月号に付属の FRK-SH2A 基板用の FM 音源プログラムの名称は、何のひねりもなく「TGSH2A」にしようと思います。
いろいろ考えた末、今回は PWM による DAC 出力はサポートしないことにしました。
その理由としては、システム・クロックを分周した周辺クロックがタイマなどの内部クロックとして使われ、それとは独立なオーディオクロックがシリアルサウンドインターフェース (SSIF) や SPDIF モジュールのクロックとして使われるので、両者をサポートしようとすると複雑になるからです。
ディジタル・オーディオ用途に便利な周辺モジュールが豊富に集積されているので、それらを活かすために、タイマ/カウンタによる PWM 出力は切り捨てることにしました。
したがって、オーディオ・クロック用の水晶振動子あるいはクリスタル・オシレータの実装は必須となります。 (48 kHz サンプリングには 24.576 MHz、44.1 kHz サンプリングには 22.5792 MHz)
オーディオ出力としては、 SPDIF 出力と、シリアル・オーディオ DAC への直接出力との両方を同時にサポートします。
これらはオーディオ・クロック周波数から決定されるサンプリング周波数に固定されるわけですが、音源としてのサンプリング周波数/同時発音数の切り換え機能については、内蔵のサンプリングレートコンバータ (SRC) の利用を考えています。
SRC 自体は、入力されるデータ列に対しサンプリング周波数変換の演算を施し、その結果を「自分のタイミング」で出力するだけのもので、単体では、たとえば 16 kHz の一定のレートで入力したものを 44.1 kHz の一定のレートで出力してくれるような仕組みにはなっていません。
この「自分のタイミング」については、ハードウェア・マニュアルでは詳しく記述されていませんが、周辺クロック Pφ = 36 MHz の場合に SRC0 では最大 8 μs 間隔になることは書かれています。
FM 音源プログラムの場合には、波形発生はソフトウェア的に行い、出力はハード的なサンプリング周波数の一定のレートで行っているので、タイミング調節は波形発生側で行うことにします。
データの流れとしては、

   波形発生 → リングバッファ → SRC → SPDIF/SSIF 出力

ということになります。
サンプリングレート変換は、必ずアップサンプル方向とします。 つまり、出力サンプリング周波数が 48 kHz なら、入力は 48 kHz まで、出力が 44.1 kHz なら入力も 44.1 kHz までとし、 48 kHz → 44.1 kHz は考えないことにします。
出力側の SPDIF/SSIF で 48 kHz あるいは 44.1 kHz の一定レートでの割り込みを発生し、割り込みルーチン内で SRC の出力データを引取って出力します。
そこで同時に、SRC の入力 FIFO に空きがあるかどうかを確認し、空いていればリングバッファから 1 サンプル取り出して SRC に入力します。
アップサンプル方向と限定しましたので、必ず SRC の出力レートの方が入力レートより大きいか、または等しいので、出力のタイミングで入力をチェックし、必要があれば 1 サンプル補充することで過不足なく入力のレートを合わせることができます。
ここまでが割り込みルーチン内の処理で、メインの波形発生部では、リングバッファに空きがあるかどうかを監視し、空いていれば 1 サンプル分の波形を発生させ、リングバッファに書き込む動作により、全体としてのタイミングが合うことになります。
この考えでテスト用の簡単なプログラムを作成し、うまく動作することを確認しました。
最初は、SRC0 が全く動作しなくて悩みましたが、リセット後のデフォルトでは SRC0 モジュールへのクロック供給がされていないためでした。
同様に、SPDIF にもリセット後のデフォルトではクロック供給されていませんが、FRK-SH2A 基板では、ブートローダか、シリアル接続 HEW モニタかで SPDIF にクロック供給する設定になっていると思われ、プログラムをダウンロードして実行する段階で何もしなくても SPDIF モジュールが動作するようです。
したがって、前回の SPDIF モジュール動作のための最低限の設定プログラムは、正確には次のようになります。

    CPG.STBCR7.BIT.MSTP76 = 0; // enable SPDIF clock
    PORT.PFCR3.BIT.PF12MD = 5; // select SPDIF_OUT on PF12
    SPDIF.CTRL.BIT.TME    = 1; // SPDIF Tx Module Enable
    SPDIF.TLCA = 0x0000;       // L ch data
    SPDIF.TRCA = 0x0000;       // R ch data

同様に、SRC0 を動作させるための最低限の設定は、

    CPG.STBCR6.BIT.MSTP62  = 0; // enable SRC0 clock
    SRC0.SRCCTRL.BIT.IFS   = 0; // input  fs =  8 kHz
    SRC0.SRCCTRL.BIT.OFS   = 1; // output fs = 48 kHz
    SRC0.SRCCTRL.BIT.SRCEN = 1; // SRC enable    

のようになります。