新版FM音源プログラム (7)

前回までの話は BSP (Board Support Package) ライブラリの「固定部分」を組み込むための手順でした。
手順 5. はユーザ・アプリケーションから API (Application Programming Interface) 関数を介して BSP ライブラリを利用する方法で、手順 6. は BSP ライブラリの一部であるけれどもユーザ・アプリケーションでの DMA バッファの実現方法に依存する部分の記述に関するものです。
オーディオ DAC から常に出力し続けるという利用方法では、使用する API は次の 2 つだけです。

BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)

BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)

オーディオ出力の一時停止/再開や停止のための API

BSP_AUDIO_OUT_Pause()
BSP_AUDIO_OUT_Resume()
BSP_AUDIO_OUT_Stop() 

も用意されていますが、それらは使用する必要がありません。
BSP_AUDIO_OUT_Init() 関数の呼び出しで、出力端子、出力アンプのボリューム、サンプリング周波数を指定して初期化を行います。
第一引数 OutputDevice が DAC CS43L22 の出力端子の指定ですが、STM32F4-Discovery ボードではヘッドフォン出力しか引き出されていないので、定数 OUTPUT_DEVICE_SPEAKER (整数値としては「1」) を指定するとヘッドフォン端子には出力されなくなります。 それ以外の値ならヘッドフォン端子に出力されます。
第二引数 Volume は、出力アンプのボリュームを設定します。
CS43L22 はチャージ・ポンプを内蔵していて、アンプの電源として自前で負電圧を作り出します。 そのため、出力に直流阻止コンデンサを付けなくても、出力直結で対 GND で正負に振れる出力電圧を得ることができます。
しかし、出力が「クリップ」しないのは電源電圧 (+1.65 V 〜 +2.63 V) に比例する範囲に限られます。
STM32F4-Discovery では、 CS43L22 のヘッドフォン・アンプ部には 2.5 V の電源が供給されていて、この電源電圧でフルスケール出力がクリップしないのは Volume 値が 85 前後の値までです。
第三引数 AudioFreq には Hz 単位のサンプリング周波数を与えます。
これは、システム PLL および I2S PLL のリファレンス周波数が 1 MHz の場合に指定のサンプリング周波数に近い値となるような設定になっています。
STM32F4-Discovery のデフォルトのハードウェア設定では、HSE (High Speed External) クロックとして外部 8 MHz クロックを使う仕様になっており、システム PLL のリファレンス周波数として 8 分周した 1 MHz から CPU クロック 168 MHz をシステム PLL で生成します。
したがって、当然 I2S PLL のリファレンス周波数は 1 MHz になります。
いくつかのサンプリング周波数に対してテーブルを持っていて、次の表のような各種の周波数に設定されます。

AudioFreq
指定
I2S PLL
[MHz]
I2S クロック
[MHz]
実 fs 誤差
(ppm)
8000 256 51.2 8000 0
11025 429 107.25 11024.9 -123
16000 213 53.25 16000.6 +38
22050 429 107.25 22049.8 -123
32000 426 106.5 32001.2 +38
44100 271 45.17 44108.1 +183
48000 258 86.0 47991.1 -186
96000 344 344 95982.1 -186

AudioFreq の値が上の表にない値の場合は、fs = 48 kHz と見なされて AudioFreq == 48000 と同じ設定になります。
誤差がゼロなのは fs = 8 kHz の場合だけで、ディジタル・オーディオで使われる fs = 44.1 kHz や 48 kHz では ±180 ppm 程度の誤差が生じます。
誤差ゼロで fs = 44.1 kHz / 48 kHz を実現するために、外部クロックとして 12.096 MHz や 28.224 MHz を使って、I2S PLL のリファレンス周波数を 1.344 MHz にする場合などは、「自前」の I2S PLL 設定ルーチンを書いて再設定してやる必要があります。