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 ビットの差異もなく、完全に一致しました。