lyricalmagical が 2025年03月04日20時39分07秒 に編集
初版
タイトルの変更
DIX9211の動作を試してみる(受信編)
タグの変更
DAC
SPDIF
記事種類の変更
製作品
ライセンスの変更
(CC BY-NC 4+) Creative Commons Attribution-NonCommercial CC BY-NC version 4.0 or later
本文の変更
以前書いた記事([TangNanoでS/PDIFミキサー(簡易版)を作る](https://elchika.com/article/cc77a576-4706-41de-a69f-94f0e03ea85f/))で触れたDIX9211の動作実験をしてみます。 ## 目標 1. S/PDIF信号からビット送信用(サンプリングレートの64倍)もしくはその逓倍クロックを取り出す 1. DACをつないで音を鳴らしてみる ## 準備 ### データシートを見る データシートは下記から入手できます。 https://www.ti.com/jp/lit/gpn/dix9211 まずざっと読んで、最低限必要な設定と、回路構成を調べます。 制御方法(初期設定)はSPIかI2Cが使えるようです。 どちらでも良いのですが、今回は必要な端子数が少ないI2Cにします。 また、出力として取り出したい信号は下記です。 ・クロック系 64fsクロック(もしくはその逓倍)→SCKO 逓倍率はPSCKレジスタで設定できるようです。 (データシート:Table 3. SCKO, BCKO and LRCKO Frequency Set by PSCK[2:0]) ・オーディオデータ(I2S) bit clock(BCK):48KHz x 32=1.576MHz LR Clock(LRCK):48KHz PCMデータ(DOUT) ・ついでに使いたいクロック 水晶発振クロック→XMCK(MPIO_A2) というわけで何をしたいかが明確になりましたので、どういう回路が必要かを調べてみます。 データシートの39PのDefault Routing Function (After RESET)を見ると、リセット解除後はどのような動作をするかの概要がわかります。ちなみにリセットはP13記載の通り内部Power on resetがありますので、RST端子をVDDに繋いでおくだけで自動で電源ON時にリセットがかかります。 オーディオデータ系としては、初期状態でRXIN2が選択されます。その後Clock/Data Recovery(以下CDRと記載)でクロック信号が作成されます。CDR(厳密にはそこにつながっているPLL)がLock状態(つまり正常な信号が入力されて安定した状態)ではRXIN2からの信号がその後に伝搬していき、SCKOやBCKなどから出力されることがわかります。なので、オーディオデータ系は何もしなくても所望の出力を得られそうです。 オーディオデータとは別に、水晶発振クロックも後々のことを考えて使用したいため、こちらも取り出します。 まあ現実的にはXTOからそのまま引き出せるのですが、データシートに「No loads other than the resonator should be used on the XTO pin」と記載がありますのでやめておきましょう。 正規に取り出す場合には、XMCKOから取り出せます。XMCKOはMPIO_A2から出力されるようですが、この出力を有効にするためにはレジスタ設定が必要のようです。 設定する必要があるレジスタは、 - Register 24h(Oscillation Circuit Control) MCKOを有効とするため、XMCKEN(bit4)を1にします。 - Register 6Eh(MPIO_C and MPIO_A Hi-Z Control) MPIO_A2を出力とするため、MPA2HZ(bit2)を0にします。 の2つのようです。そのため、I2CかSPIでの制御が必要です。I2C/SPIの選択はMODEピン(27ピン)で行うようです。 ### 回路図を書く 回路図を書くといっても、基本的にリファレンス通りの回路になります。 リファレンス回路はデータシートの49PのFigure 27にillustrates a typical circuit connection.として載っていますので、これを丸パクリして回路を書きますが、I2C/SPIの選択はI2Cに固定としておきます。 また、水晶振動子と発振器のどちらも使えるように回路図上は両方接続しておきます、 ただ、リファレンス回路をよく見るとどうみても誤記っている(VCCが0Vにつながっている等)ので、そのあたりはほぼ同機能のPCM9211の回路なども参考にしてみます。  データシートのリファレンスと今回作成した回路で部品番号が違いますが、以下データシートの部品番号でコメントします。 R1:データシート通り680Ω R2:水晶振動子に依存しますがとりあえず推奨値の100Ωとします。 R3/R4/C10/C11:同軸入力用なので不要 C7, C12, C13:0.1μFのセラミックと10μFの電解と指定あります。電解は電源回路側に持たせるので省略しています。 C5:0.068 mFと記載あります。mはミリ?かと思いましたが、microのことらしいので、0.068μFとします(データシート18P DIR and PLL Loop Filter Detailsに記載あり)。 C6:こちらも0.0047 mFと記載ありますが、同じく18Pに0.0047μF(=4700pF)と記載あります。 C8,C9:水晶振動子に依存しますがとりあえず推奨値の10pFとします。 ### 基板を作る QFPですので、実験するのであれば少なくともなにか基板を作らないとできません。 QFP48の変換基板を使ってもいいですが、そこそこのお値段がしますので、いっそのこと基板も外注してみます。  使いそうな信号線は2.54mmピッチ穴あき基板のそのまま乗せられる位置にスルーホール端子を作りました。その他使わなさそうな端子も一応信号の取り出しはしやすいようにテストポイントを作成しています。 信号名まで書く場所はありませんでした。 そしてこちらが実際に出来上がってきた基板です  作成はJLCPCBさん。5枚で$2です。送料含めても1000円以下で作成してくれます。 というわけで、こちらに部品を手実装して動かしてみます。 ## 動かしてみる ### レシーバとしての動作 動かしてみた様子がこちらです。  まず作成したボード単体で動かしています。I2C制御などはしていないので、作成した基板に単純に電源と光デジタルコネクタをつないだのみです。 この時点での動作を見てみます。  水色波形が光デジタルコネクタに入力されたS/PDIF信号、黄色波形がLRCKです。まず正しく48KHzを出力していることがわかります。 また、水色波形をよく見るとパルス幅が長いところが1か所ありますが(LRCKの立ち上がりの少し左)、ここがフレームの先頭になります。なぜここがフレームの先頭になるのかの説明は省略しますが、そういうものです。S/PDIFのフレームの構造は「[TangNanoでS/PDIFミキサー(簡易版)を作る](https://elchika.com/article/cc77a576-4706-41de-a69f-94f0e03ea85f/)」を参照してください。 なので、LRCKの変化点とS/PDIF信号のフレームの先頭が同期しているということは、このLRCK信号は水晶振動子基準ではなく、間違いなくS/PDIF信号から生成されたクロックだということがわかります。 フレームの先頭数bitは固定値となるためパターンは変化しませんが、後半はPCMデータが乗っているため変化していることがわかります(残像が残っている)。 次にSCKOを観測してみます。  紫がSCKOです。信号線やGNDを結構引き回しているので形がかなり崩れています。 また、時間軸が変わっていますが、水色と黄色は上記同様です。 S/PDIF信号の波形は、パルスの長さが3種類あり、幅の比率は3:2:1です。一番長いパルスはフレーム先頭にのみ存在します。 1フレーム(1サンプル分のデータ)は64bitありますが、一番短いパルス幅は1bitの半分の幅になります。 上図では短いパルスに2CLKありますので、サンプリングレートの256倍のクロックが出力されていることが確認できます。こちらも水晶振動子ではなく、S/PDIF信号に同期したクロックであることが確認できます。 なので、当初目的であった、 ・ S/PDIF信号からビット送信用(サンプリングレートの64倍)もしくはその逓倍クロックを取り出す は256倍クロックが取得できるということで、目的は達成できました。 ちなみにSCKOが256倍なのは、Register 30hのPSCKで変更できるようですが、デフォルトが256fsとなっています。 また、この状態でS/PDIF入力に有効なデータが入力されなくなると、LRCKやSCKOは水晶振動子に同期したデータが出力されました。 こちらについてもデータシートFigure 15. Default Routing Block Diagram記載の通り、CDRがLockしないため、後段にはXTIクロックが供給されていることになります。 この状態ではレジスタの設定をしていませんので、目標2のXMCKは出力されていません。 そのため、ArduinoをI2C接続して、レジスタ設定を行います。とりあえず手持ちにあってたArduino UNOをつなぎました。 GND/SCL/SDAをそのまま接続するだけです。DIX9211は3.3V動作ですが、I2C端子は5Vトレラントのため、5VのArduinoと直結しても問題ありません。  Arduino側のソースはI2Cでレジスタに書き込むだけなので、以下のような単純なソースになります。 ```arduino:I2Cレジスタ設定 #include "Wire.h" //A4:SDA //A5:SCL int addr = 0x40; void setup() { Wire.begin(); Wire.beginTransmission(addr); Wire.write(0x6e); Wire.write(0x0);//MPA2HZ=0 Wire.endTransmission(); Wire.beginTransmission(addr); Wire.write(0x24); Wire.write(0x10); Wire.endTransmission(); } void loop() { delay(500); } ``` このようにI2Cからレジスタを設定することで、XMCK(MPIO_A2)から、水晶発振のクロックが取り出せました。 ただ、出力周波数が200ppm程度ずれているので、水晶振動子周辺のRCの値は調整が必要のようです。まあ測定器側が構成されていないというのもありますが、水晶発振器を使うと24.576MHzが正確に出てきたので、おそらく水晶振動子を使った値が若干ずれているのでしょう。 ### 音を出してみる 当初の目的の、S/PDIF信号からクロックを復元するという目的は達成できましたが、せっかくなので音を鳴らしてみたいと思います。 手持ちにBU9480Fがあったので、こちらを使ってみたいと思います(ちなみに[デジット](https://eleshop.jp/shop/g/gN6U414/)で110円で売っています)。 BU9480Fは電源とI2Sを接続するだけで「とりあえずは」音が鳴ります。リファレンス回路ではREF(2pin)とGND間にコンデンサが記載されていますが、音質に影響するだけで省いても一応音はなります。 ではまずBU9480Fはどのようなフォーマットのデータを受け付けるのかデータシートを確認してみます。  いわゆる16bit右詰めフォーマットと言われるものになります。 これはどういうものかというと、LRCKの変化の直前の16bitのデータをMSBファーストで拾う、ということになります。 つまり、フォーマットでDIX9211から出力する必要があります。 DIX9211が対応している出力フォーマットは、データシートFigure 2. Audio Data Input/Output Formatより、以下の4つとなっています。  BU9480F に合わせるのであれば、MSB First, 16-bit Right-Justifiedで出力する必要があります。 出力形式を指定するレジスタは、 Register 2Fh(DIR Output Data Format)のRXFMT[2:0] になります。初期値では「24-bit MSB first, I2S」となっていますので、このままでは期待の出力が得られないため、設定値の変更が必要になります。今回は設定値として「011」を設定する必要があるため、先ほどと同様Arduinoからレジスタを変更します。 ```arduino:16bit右詰め設定 #include "Wire.h" //A4:SDA //A5:SCL int addr = 0x40; void setup() { Wire.begin(); Wire.beginTransmission(addr); Wire.write(0x2f); Wire.write(0x3);//16-bit MSB first, right-justified Wire.endTransmission(); } void loop() { delay(500); } ``` この設定をすることで、無事音を出すことができました。 実際に音を出したときはこのような感じで接続しています。かなり適当です。  ## 終わりに 今回実験で作った程度の回路で、超簡易な光デジタル入力のDACが作れることになります。 電源からして適当な上に、ノイズ対策などは全くしていないので、音質はまあ察してください。 以前書いた「[TangNanoでS/PDIFミキサー(簡易版)を作る](https://elchika.com/article/cc77a576-4706-41de-a69f-94f0e03ea85f/)」では、S/PDIF信号に正確に同期したビットクロックなどを取得できていないという問題がありました。それを対処するために専用ICを使用したかったのですが、その実験がこの記事となります。 DIX9211にはS/PDIF信号を送信する機能もあるようですが、今回は触れていません。