前回、PCM5122オーディオステレオDACをブレッドボード上で組み、 botic driverを用いてI2S I/Fを介しBBBからテストサンプルを鳴動させた。
まがりなりにもハイレゾ対応のDACを入手できたことになる。
PCM5122にはハードウェアモードとソフトウェアモードがあり単に音を鳴らすだけであるならば、ハードウェアモードを選択する 方がシンプルな構成となる。
前回の実装ではソフトウェアモードの一つI2Cモードを選択した。
PCM5122にはソフトウェアモードでしか使用できない多くの機能があるためだ。
特にminiDSP audio platformというプログラマブルな環境があり、PurePath StudioというTIの提供するツールを用いて内部の構成や フィルタの係数を設定できるようだ。
ただし、敷居が高そうなのでそこまでは試す予定はない。
今回、簡単に試せそうな機能に関してI2C I/Fを用いて設定変更を試す。
以下の説明はPCM5122のデータシートの内容をベースとしている。
細かい説明はデータシート参照のこと。
PCM5122はI2Cモードの場合、デバイスアドレスのA6~A2までは固定でA1とA0はそれぞれ入力ピンのADR2/ADR1で指定できる。
よって一つのI2Cバスに最大4個までのPCM5122を接続でき、それぞれ0x4c~0x4fまでのデバイスアドレスとなる。
作例ではデバイスアドレスは0x4cとなるようにした。
また、PCM5122のレジスタは0,1,44~52,66~74のページがあり、各ページのレジスタアドレス0x00はページ切り替えレジスタとなっている。
miniDSP audio platformを用いないのならば、44~52,66~74のページは使用しないので、操作するページは0ページと1ページだけとなる。
とりあえず叩いてみる。
I2C関連の操作はroot権限が必要。
debian@bbb:~$ sudo -s [sudo] password for debian:
認識できているか確認。
root@bbb:/home/debian# i2cdetect -r -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- UU UU -- -- 4c -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- root@bbb:/home/debian#
0x4cとして認識されている。
ページ0を選択してみる。
root@bbb:/home/debian# i2cset -y 1 0x4c 0x00 0x00 b root@bbb:/home/debian#
値が0x00以外であるはずのレジスタをリードしてみる。
root@bbb:/home/debian# i2cget -y 1 0x4c 0x04 c 0x11 root@bbb:/home/debian#
PLCKは”1: The PLL is not locked”、PLLEは”1: Enable PLL”となっていることが判る。
root@bbb:/home/debian# i2cget -y 1 0x4c 0x0d c 0x00
SREFは”0: The PLL reference clock is SCK”。
ソフトウェアモードではSREFが”The PLL reference clock is SCK”であるので、デフォルトのままではSCKが必要となる。
ハードウェアモードでは自動でBCKリファレンスのPLLモードになるのでSCKが不要。
この点はハードウェアモードとの差分となっていて、ソフトウェアモードではPLL関連の設定が必要となる。
デフォルトのPLL設定を見てみる。
root@bbb:/home/debian# i2cset -y 1 0x4c 0x00 0x00 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x14 c 0x00 root@bbb:/home/debian# i2cget -y 1 0x4c 0x15 c 0x00 root@bbb:/home/debian# i2cget -y 1 0x4c 0x16 c 0x00 root@bbb:/home/debian# i2cget -y 1 0x4c 0x17 c 0x00 root@bbb:/home/debian# i2cget -y 1 0x4c 0x18 c 0x00 root@bbb:/home/debian#
PPDV[3:0] 0000: P=1 PJDV[5:0]000000: Prohibited (do not set this value) PDDV[13:0]0 (in decimal): D=0000 PRDV[3:0] 0000: R=1
PJDVの初期値が謎であるが、意味としてはSCKの等倍がPLLCKとなり、供給される事になるらしい。
現状では無意味にPLLが動作していることになる。
外部から供給されるSCKの信号が綺麗であるのならば、PLLは止めた方が余計なノイズを出さない為良い事になる。
試して見よう。
root@bbb:/home/debian# i2cset -y 1 0x4c 0x04 0x00 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x04 c 0x10 root@bbb:/home/debian# play /data/test/test_96k_24b.flac /data/test/test_96k_24b.flac: File Size: 4.96M Bit Rate: 2.41M Encoding: FLAC Info: Processed by SoX Channels: 2 @ 24-bit Samplerate: 96000Hz Replaygain: off Duration: 00:00:16.50 In:100% 00:00:16.50 [00:00:00.00] Out:1.58M [ =====|======] Hd:0.1 Clip:0 Done. root@bbb:/home/debian#
特に問題無く音の再生ができた。
逆にBCKをPLLCKINにして外部SCKを止めてみる。
PLLCKとPLLCKINの関係は以下の式となる。
$$PLLCK=\frac{PLLCKIN\times R\times j.D}{P}$$
BCKは48KHzサンプルの64fsなのでPLLCKINは3,072,000Hz、PLLCKを512fsの24,576,000Hzターゲットとすると、R=1、J=32、D=0、P=4が一つの候補となる。
root@bbb:/home/debian# i2cset -y 1 0x4c 0x00 0x00 b root@bbb:/home/debian# # PLLE 0: Disable PLL root@bbb:/home/debian# i2cset -y 1 0x4c 0x04 0x01 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x04 c 0x11 root@bbb:/home/debian# # SREF 1: The PLL reference clock is BCK root@bbb:/home/debian# i2cset -y 1 0x4c 0x0d 0x10 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x0d c 0x10 root@bbb:/home/debian# # PPDV[3:0] 0011: P=4 root@bbb:/home/debian# i2cset -y 1 0x4c 0x14 0x03 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x14 c 0x03 root@bbb:/home/debian# # PJDV[5:0] 100000: J=32 root@bbb:/home/debian# i2cset -y 1 0x4c 0x15 0x20 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x15 c 0x20 root@bbb:/home/debian# # PDDV[13:0] 0 : D=00000000000000 root@bbb:/home/debian# i2cset -y 1 0x4c 0x16 0x00 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x16 c 0x00 root@bbb:/home/debian# i2cset -y 1 0x4c 0x17 0x00 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x17 c 0x00 root@bbb:/home/debian# # PRDV[3:0] 0011: R=4 root@bbb:/home/debian# i2cset -y 1 0x4c 0x18 0x00 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x18 c 0x00 root@bbb:/home/debian# # IDSK 1: Ignore SCK detection root@bbb:/home/debian# # IDCH 1: Ignore SCK halt detection root@bbb:/home/debian# i2cset -y 1 0x4c 0x25 0x18 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x25 c 0x18 root@bbb:/home/debian#
この設定でSCKの入力は不要となりBCKリファレンスでPLLモードとなる。
設定前に一度電源を落とし、SCKを接地させる必要がある。
確かにSCK無しで音の再生ができる事を確認できた。
SCKの省略は音質の為と言うよりはシステム設計の自由度の為に有用だ。
SCKをDACに供給できない構成の場合はSCKを省略できるメリットは大きい。
次にボリュームの変更を試す。
root@bbb:/home/debian# i2cset -y 1 0x4c 0x00 0x00 b root@bbb:/home/debian# # PCTL[1:0] 01: Right channel volume follows left channel setting root@bbb:/home/debian# i2cset -y 1 0x4c 0x3c 0x01 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x3c c 0x01 root@bbb:/home/debian# # VOLL[7:0] root@bbb:/home/debian# i2cset -y 1 0x4c 0x3d 0x40 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x3c c 0x40
PCTLにより右チャネルの音を左チャネルボリュームに同期させる。
そしてVOLLにより左ボリュームの制御を行う。
VOLLは0x30が0dBで1減らす毎に0.5dB音が大きくなり、1増やす毎に0.5dB音が小さくなる。
0xffにした場合はmuteだ。
DACは0dBで再生し、後段にアンプを用意、出力最終段にボリュームを設けるのがあるべき姿であるが、上記レジスタを操作する 事によりDAC出力段で電子ボリュームとする事もできる。
ちなみに音量を上げてゆくと飽和したような音になる。
ギターのディストーションのようなエフェクトが欲しい場合有用かもしれない。
上のレジスタはデジタルでの音量変更であるが、LAGN/RAGNはアナログ音量を6dB下げる事ができ、AGBL/AGBRはアナログ音量を0.8dB上げる事ができる。
DAC出力を6dB下げたいユースケースはちょっと思いつかないが、0.8dBとはいえ少しでもゲインを稼ぎたい場合は有用かもしれない。
最後にインターポレーションフィルタの変更を試す。
PCM5122は48KHz/16bitサンプリングのデータを再生する場合でもインターポレーションを行い8fs/32bitを出力する事ができるようだ。
これはローレゾ音源であっても量子化ノイズを格段に下げる事ができる事を意味する。
また、インターポレーション時に適用するLPFがいくつか用意されていて自由に選択できる。
特にHigh-Attentuation x8 Interpolation Filterは1/2fs以上で急峻に-100dB以下まで減衰してゆく高次フィルタで特性が素晴らしい。
High-Attentuation x8 Interpolation Filterはソフトウェアモードでのみ選択できる。
※この図はhttp://www.ti.com/lit/ds/symlink/pcm5122.pdfからの引用。
デフォルトではNormal x8 Interpolation Filterが選択されていて、1/2fs以上で-60dB程度となっている。
これはこれで優秀なフィルタであるが、差を見てみたい。
※この図はhttp://www.ti.com/lit/ds/symlink/pcm5122.pdfからの引用。
High attenuation interpolation filterへの切り替え。
root@bbb:/home/debian# i2cset -y 1 0x4c 0x00 0x00 b root@bbb:/home/debian# # PSEL[4:0] 00011: High attenuation x8/x4/x2 interpolation filter with de-emphasis root@bbb:/home/debian# i2cset -y 1 0x4c 0x2b 0x03 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x2b c 0x03
Low latency IIR interpolation filterへの切り替え。
root@bbb:/home/debian# i2cset -y 1 0x4c 0x00 0x00 b root@bbb:/home/debian# # PSEL[4:0] 00010: 8x/4x/2x Low latency IIR interpolation filter with de-emphasis root@bbb:/home/debian# i2cset -y 1 0x4c 0x2b 0x02 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x2b c 0x02
FIR interpolation filter with de-emphasisへの切り替え。
root@bbb:/home/debian# i2cset -y 1 0x4c 0x00 0x00 b root@bbb:/home/debian# # PSEL[4:0] 00001: 8x/4x/2x FIR interpolation filter with de-emphasis root@bbb:/home/debian# i2cset -y 1 0x4c 0x2b 0x01 b root@bbb:/home/debian# i2cget -y 1 0x4c 0x2b c 0x01
それぞれ色々な曲を再生して聞き比べてみたがまったく違いが判らない。
レジスタが間違っているのか、私の耳がそれほど性能が良くないのかどちらかであろう。
なんにしてもそれなりに楽しめた。
思うに、I2S I/F DACは高音質を追い求めるのも良いが、チープな構成でそれなりの音質が得られるのが良いと思う。
時々勝手にリブートしてしまうので不安定ではある。
しばらく弄ってみようと思っている。