ディジタルオーディオ用 DAC をマイコンにつなぐ(9) -- MCF52233 + TDA1543A (2)

ColdFire も含めて、これまで使ってきたマイコンでは、SPI ハードウェアのシフトレジスタ長は 8 〜 16 ビットであり、いっぺんに 24 ビットの転送はできません。
したがって、24 ビットを

  • 8 ビット + 16 ビット
  • 8 ビット + 8 ビット + 8 ビット

のように分割して、2回あるいは3回に分けて転送する必要があります。
シンプルさを求めるなら、最初の 8 ビット転送が終了するまでループして待てばいいのですが、CPU クロックを 40 MHz、SPI クロックを 3 MHz とすると、その待ち時間は CPU クロックにして約 100 クロック分にもなってしまいます。
無駄な待ち時間を過ごしたくないのであれば、ATmega の場合のプログラムのように、SPI 転送完了割り込みを使ったプログラムにする必要があります。
これに対して、ColdFire の QSPI モジュールでは、キューにあらかじめ最大 16 ワードの SPI 転送のセットアップをしておいて、ハードウェアを起動すれば、後はソフトウェアの介入なしに、一気に連続的に SPI 転送を行うことが可能です。
具体的なプログラムとしては、まず、QSPI の初期化部は次のようになります。

  MCF_QSPI_QMR   = 0x800A; 
  MCF_QSPI_QDLYR = 0x0000;  // use standard delay
  MCF_QSPI_QWR   = 0x0100;  // queue size = 2 (ENDQP = 1, NEWQP = 0)
  MCF_QSPI_QIR   = 0x0000;  // disable interrupts
  MCF_QSPI_QAR   = 0x20;    // select command RAM (QCR0)
  MCF_QSPI_QDR   = 0x0000;  // BITSE = 0 (select 8 bit)
  MCF_QSPI_QDR   = 0x4000;  // BITSE = 1 (select 16 bit)

ピン機能の設定部は全く一緒なので省略してあります。
以前と違うのは、まず、QWR の設定が ENDQP = 1、つまりキューサイズが 2 になっていることです。
また、8 ビット転送を示すコマンドを QCR0 に書き込み、以前は QCR0 に書き込んでいた 16 ビット転送のコマンドを、ひとつ後ろにズラした QCR1 に書き込んでいることが以前との違いです。
次に、サンプリング周期 (実際にはステレオなので2倍のレート) での割り込み処理は下のようになります。

void __attribute__((interrupt_handler)) 
dtim0_handler() {
  MCF_DTIM0_DTER &= 0x03; // clear REF, CAP flag
  if (lrck ) { // left channel timing
    short int w;
    ...
//    w に出力データが入っているものとします
    MCF_QSPI_QAR    = 0x01;   // select xmit RAM1 (QTR1)
    MCF_QSPI_QDR    = w;      // write 16 bit data
    MCF_QSPI_QDLYR |= 0x8000; // start QSPI
  } else { // R ch
    MCF_QSPI_QDLYR |= 0x8000; // start QSPI
  }
  lrck ^= 0x01;
} // void dtim0_handler()

以前との違いは、L ch の処理で QAR に「1」を書き込んで QTR1 をアクセスしていることと、R ch の処理が追加されていることです。
L ch の処理については、書き込むアドレスが違うだけで、処理量は BU9480F の場合と変わりありません。
R ch の処理が増えていますが、これは TDA1543A では L/R 両チャンネル出力しないと出力がミュートされてしまうからで、処理が増えたというより、BU9480F では手抜きができたと言った方が正確です。
ステレオ DAC ですが、L/R 両方に同じ値を出力させるため、オーディオデータは L ch の処理の時に書き込んだ値をそのまま利用しており、R ch については QSPI ハードウェアを起動するだけで済んでいます。

プログラムを動作させて、DAC の信号波形をディジタルオシロで観測した写真を下に示します。

一番上のトレースが「LRCK」、真ん中が「BCLK」、一番下が「SDAT」です。
2入力のディジタルオシロを使っているので、実際のリアルタイム入力は下側の2つのトレースだけで、上の「LRCK」は事前にメモリに記録しておいた波形を表示しています。
BCLK が 8 個のパルスと 16 個のパルスに分離しているのが分かります。
これは、QSPI では、各転送の前後での「CS」信号の変化までのディレイ量がプログラマブルになっているのですが、その値の最小値を選択しても、実際のディレイ量はゼロにはならないためです。
下の写真は、一番下のトレースを TDA1543A の DAC 出力波形に変えたものです。

これを見ると、TDA1543A の DAC 出力のアナログ値は LRCK の立ち上がりの後の最初の BCLK のエッジに同期して変化していることが分かります。
LRCK はハードウェアで作り出しているのでジッタはないのですが、BCLK は割り込み応答ルーチンで作り出しているので、割り込み応答時間の変動を受けてジッタが乗ってしまいます。
したがって、残念ながら、TDA1543A の場合オーディオ出力にもジッタが乗ることになります。
CV 出力として使う場合には、このような細かいジッタは問題にはなりません。
下の写真は、同様に一番下のトレースを BU9480F の DAC 出力波形に変えたものです。

これを見ると、 BU9480F の DAC 出力のアナログ値は LRCK のエッジに同期して変化していることが分かります。
したがって、BU9480F の場合には、ジッタの心配はありません。