PSoC5LP Prototyping Kitで作るUSBオーディオI/F(I2S出力対応)
PSoC5にはCE95390 - USB Audio with PSoC 3/5LPというUSBオーディオの公式サンプルがありますが、32kHz 8ビット モノラルなんですよねー。ということで、これを96kHz 16ビット ステレオに拡張しつつ、内蔵の8bit DACだけでなく外部DACも利用できるように、I2S出力にも対応してます(*´▽`*)
今回のPSoC内の回路は、大まかに
というMHz帯のクロックが必要になっちゃうのでした。でも、PSoC5LPで使えるクロックは最大でも64MHzで、これを分周してビットクロックを生成しようとすると
Σ (゚Д゚;)えーっと・・・
分周比が1変わるだけでこんなに周波数が変わるんじゃ、2.82MHzや6.14MHzなんて生成できるはずがないじゃないですかーやだぁ(´・ω・`)
じゃぁI2Sを使ったオーディオ回路を作ってる皆さんはどうしてるのー?と思って調べたのですが、一般的には、USBホストから1ms周期(1kHz)で送られてくるSOF(Start of Frame)パケットを基準に、PLL(Phase Lock Loop)というアナログ回路を使って、これに同期するような所望のクロックを生成するようです。
PLLの仕組みも調べたのですが、VCO(Voltage Controlled Oscillator)という電圧で周波数を変更できる回路を使って、「入力周波数」と「生成した周波数を分周したもの」を比較し、その位相差をVCOの電圧にフィードバックして、入力波とぴったり同期した逓倍波を生成するようです。ということで、あまり外部部品は導入したくなかったのですが、Cypress公式にあったVCOのサンプルを参考に、充電用コンデンサ(C1=100pF)とPWMを平滑化するLPF(R1=100kΩ、C2=1μF)を追加して、VCOを作りましたヽ(´▽`)ノこれは、
あとは、所望の周波数になるようにVCOの電圧を制御すれば出来上がりです!ね、簡単でしょう?
・・・
( ・ω・)∩センセー
その制御はどうするんですかー?
はい、これこそが最大の問題で(´;ω;`)ウッ…
コンデンサと抵抗の精度や温度変化のため、どの電圧にすればどの周波数になるのかは動かしてみないと分からないので、狙った周波数になるように電圧を常に調整する制御アルゴリズムが必要なのでした(´・ω・`)
今も試行錯誤してるのですが、とにかく、現在の成果を是非ご覧くださいヽ(´▽`)ノ
44.1kHz用の2.82MHzクロック
96kHz用の6.14MHzクロック
どうでしょう、うまく出てますかにゃー((=゚Д゚=)
前置きはいいからとりあえず鳴らしてみたい!という方は、下記のダウンロード先に最小限の説明があるので、それを見て試してみてね(●´ω`●)
PSoC Creator用プロジェクトのダウンロード
必要な部品
必須パーツ
- PSoC5LP Prototyping Kit(CY8CKIT-059)
- コンデンサ:C1(100pF), C2(1uF)
- 抵抗:R1(100kΩ)
オプションパーツ(無くてもOKです)
- I2S DACボード
マスタークロックを自己生成できるのものが使えます。信号電圧が3.3Vならそのまま使えますが、5V駆動の場合はTopDesign.cysch内のI2Sコンポーネントの出力先を変更して、3.3V生成部分を使わずピン直接出力すればOKです。私は、PCM5102A搭載のちっこいボードを買いました(送料込み512円)。
Interface I2S PCM5102 DAC Decoder GY-PCM5102 I2S Player Module For Raspberry Pi - 16x2 LCD(LCD1602)
I2C接続で信号電圧が5Vのもの。よくあるArduino用のが使えます。繋いでおくと、Audio出力のON/OFF状態と現在の再生周波数が表示されます。 - アンプボード
アンプ内蔵スピーカーで鳴らす場合は不要ですが、私は持っていなかったので、お安いD級アンプボードを買いました(送料込み71円)。
new 1pcs PAM8403 mini 5V digital amplifier board with switch potentiometer can be USB powered - スピーカー
D級アンプって、ヘッドフォン端子のように左右のマイナス端子を共通にできないんですね(゜ロ゜)ということで、左右のマイナス端子が独立してるちいさめのボックススピーカーを買いました。千円ちょいくらいのを3種類買って聴き比べてみましたが、下記の1,168円のが一番気に入りました(≧∇≦)b
AIYIMA 2Pcs Audio Speakers 10045 LED TV Speaker 8Ohm 5W Double diaphragm Speaker Bass 10045
ところで、D級アンプの出力ってどうなってるの!?
D級アンプの出力は原理的にBTL(「Balanced Transformer Less」,「Bridged Transformer Less」,「Bridge-Tied Load」)になるようで、例えば5V駆動なら、スピーカーのマイナス端子とプラス端子を「0Vと5V」「0Vと0V」「5Vと0V」の3つの組み合わせに高速に切り替え、3値(+5V、0V、-5V)のPWMで鳴らすような仕組みのようです。そのため、プラス端子だけでなくマイナス端子も0Vと5Vの間で高速に切り替わっていて、さらにステレオ音源なら左右でパルスの位相があわない期間(左スピーカーのマイナス端子0V、右スピーカーのマイナス端子5Vとか)があるので、「ヘッドフォンに繋ぎたいから左右のマイナス端子同士をつないでGNDにしよう(*´▽`*)」とかすると、おもいっきりショートします(((( ;゚д゚)))アワワワワ(というか、させました(*ノノ))一応、ヘッドフォン端子にもつなげられるように、マイナス端子を共通化(アンバランス化)する方法はあるようです(゜◇゜)
ピンアウトと部品の接続
ピンアウトと部品の接続は下記のとおりです。
P0[7] --- 内蔵DACのスピーカー出力(右)
P1[6] --- LCD1602 I2C SDA
P1[7] --- LCD1602 I2C SCL
P12[2] --- I2S SCK (BCLKという表記の場合もあります)
P12[3] --- I2S WS (LRCLKという表記の場合もあります)
P12[4] --- I2S SDO (SDATAという表記の場合もあります)
P15[0] --- C1(100pF) --- GND
P15[2] --+
R1(100kΩ)
P15[5] --+-- C2(1uF) --- GND
- C2は容量的に電解コンデンサになりますが、PSoC側を+にしてください。
- PSoCの基板にはUSB端子が2つありますが、microUSBのほうがUSBオーディオI/Fとして認識されます。標準サイズのほうは、デバッグ用のシリアル出力やEZI2Cを使った内部モニタリングに使用しています。
P0[7] --- 内蔵DACのスピーカー出力(右)
P1[6] --- LCD1602 I2C SDA
P1[7] --- LCD1602 I2C SCL
P12[2] --- I2S SCK (BCLKという表記の場合もあります)
P12[3] --- I2S WS (LRCLKという表記の場合もあります)
P12[4] --- I2S SDO (SDATAという表記の場合もあります)
P15[0] --- C1(100pF) --- GND
P15[2] --+
R1(100kΩ)
P15[5] --+-- C2(1uF) --- GND
I2Sコンポーネント用のビットクロックについて
今回のPSoC内の回路は、大まかに
- USBインターフェース
- I2Sのビットクロック生成用のVCO(Voltage Controlled Ocsillator)
- 内蔵DAC部
- I2S出力部
- 44.1kHzなら44100Hz*32*2=2.82MHz
- 96.0kHzなら96000Hz*32*2=6.14MHz
というMHz帯のクロックが必要になっちゃうのでした。でも、PSoC5LPで使えるクロックは最大でも64MHzで、これを分周してビットクロックを生成しようとすると
- 2.8224MHzを作りたい場合:64MHz/23=2.78MHz or 64MHz/22=2.91MHz
- 6.1440MHzを作りたい場合:64MHz/11=5.82MHz or 64MHz/10=6.40MHz
Σ (゚Д゚;)えーっと・・・
分周比が1変わるだけでこんなに周波数が変わるんじゃ、2.82MHzや6.14MHzなんて生成できるはずがないじゃないですかーやだぁ(´・ω・`)
じゃぁI2Sを使ったオーディオ回路を作ってる皆さんはどうしてるのー?と思って調べたのですが、一般的には、USBホストから1ms周期(1kHz)で送られてくるSOF(Start of Frame)パケットを基準に、PLL(Phase Lock Loop)というアナログ回路を使って、これに同期するような所望のクロックを生成するようです。
PLLの仕組みも調べたのですが、VCO(Voltage Controlled Oscillator)という電圧で周波数を変更できる回路を使って、「入力周波数」と「生成した周波数を分周したもの」を比較し、その位相差をVCOの電圧にフィードバックして、入力波とぴったり同期した逓倍波を生成するようです。ということで、あまり外部部品は導入したくなかったのですが、Cypress公式にあったVCOのサンプルを参考に、充電用コンデンサ(C1=100pF)とPWMを平滑化するLPF(R1=100kΩ、C2=1μF)を追加して、VCOを作りましたヽ(´▽`)ノこれは、
- IDACで生成した定電流を外付けコンデンサに入れ、コンデンサを充電する
- コンデンサの電圧とPWMで生成した電圧をコンパレータで比較し、コンデンサの電圧がPWMで生成した電圧に達したらコンデンサを放電する
あとは、所望の周波数になるようにVCOの電圧を制御すれば出来上がりです!ね、簡単でしょう?
・・・
( ・ω・)∩センセー
その制御はどうするんですかー?
はい、これこそが最大の問題で(´;ω;`)ウッ…
コンデンサと抵抗の精度や温度変化のため、どの電圧にすればどの周波数になるのかは動かしてみないと分からないので、狙った周波数になるように電圧を常に調整する制御アルゴリズムが必要なのでした(´・ω・`)
今も試行錯誤してるのですが、とにかく、現在の成果を是非ご覧くださいヽ(´▽`)ノ
44.1kHz用の2.82MHzクロック
96kHz用の6.14MHzクロック
どうでしょう、うまく出てますかにゃー((=゚Д゚=)
最後に、既知の問題(*ノノ)
何かを再生したままWindowsのスピーカーのプロパティでサンプリングレートを変更すると、VCOの周波数が追従して安定するまでの間、ちょっとだけ「ぎゅぅぅん」ってなります(´・ω・`)周波数が安定するまでミュートするとかできればいいんですが、今後のバージョンで対応したいと思います( `・ω・)ノ
コメント
コメントを投稿