STM32F446RE 内蔵の SAI モジュールの SPDIF 出力
STM32F446RE などに内蔵されている SAI (Serial Audio Interface) モジュールでは、通常の 2 チャネル・ステレオ・オーディオ DAC/ADC とのインターフェースに加えて、 3 ch 以上のマルチ・チャネル構成や、AC97 や SPDIF などのプロトコルに対応しています。
リファレンス・マニュアルでは、SPDIF モードの場合には SAI モジュールには 64 fs クロックを入力すると解釈できる記述がありますが、実際に試してみたところ、128 fs や 512 fs などのクロックが必要でした。
SAI モジュールに入力されたクロックは、まず「クロック・ジェネレータ」に入力され、クロック・ジェネレータの設定に応じて分周されて内部のコア部分に供給されています。
SPDIF モードでは、クロック・ジェネレータ部分の動作が他のモードとは違うようですが、リファレンス・マニュアルにははっきりとは記載されていません。
SPDIF モードでクロック分周に関係するレジスタ設定は、SAI_ACR1 (ブロック A) あるいは SAI_BCR1 (ブロック B) の
- MCKDIV [b23:b20]
- NODIV [b19]
のフィールドです。 MCKDIV は「Master ClocK DIVider」、NODIV は「NO DIVider」の意です。
式で表すと、
- CLK_SAI = 128 × fs (NODIV == 1、MCKDIV == 任意)
- CLK_SAI = 512 × fs (NODIV == 0、MCKDIV == 0)
- CLK_SAI = 1024 × MCKDIV × fs (NODIV == 0、MCKDIV != 0)
表で表すと、
NODIV | MCKDIV | CLK_SAI |
---|---|---|
1 | X | 128 fs |
0 | 0 | 512 fs |
0 | 1 | 1024 fs |
0 | 2 | 2048 fs |
0 | 3 | 3072 fs |
となります。 (MCKDIV = 4 ~ 15 は省略しました。)
オーディオ・データは SAI_ADR あるいは SAI_BDR レジスタの下位 24 ビットに格納します。
ハードウェアでは、16 ビット・データ、20 ビット・データに対するサポートは特になく、ソフトウェアで未使用ビットを「0」にマスクする必要があります。
Nucleo-F446RE のプログラム中で 24 ビット幅のテーブルから読み出して作成した 997 Hz のサイン波を SPDIF 経由で送り、PC でキャプチャし WaveSpectra で観測した結果を下に示します。
WaveSpectra では振幅の表示レンジが 180 dB までに限られているので、ノイズフロアを良く見るために基本波のレベルが +18 dB 程度になるようにゲタをはかせており、ピーク値はグラフの範囲をはみ出しています。
2016 年 1 年 15 日付けの記事 (→こちら) で PSoC5LP を使った場合と同じ波形データを使用しており、結果の S/N 比も同じ値になっています。
また、キャプチャしたデータを数値として、元の波形データと突き合せた結果、1 ビットの差異もなく、完全に一致しました。