PSoC5LP Prototyping Kit (20) --- SPDIF_Tx と DMA (8)

久しぶりに SPDIF_Tx コンポーネントと DMA (と Filter コンポーネント) の話題に戻ります。
PSoC Creator の PSOC5LP 用の、Filter コンポーネントを使ったサンプル・プロジェクトのひとつとして、「Filter_ADC_VDAC01」があります。
そのトップの回路図の一部を下に示します。

これは、デルタシグマ ADC を 48 kHz / 8 ビットで動作させ、カットオフ周波数 6 kHz の Filter コンポーネント (85 タップ FIR、Blackman ウィンドウによる設計) でフィルタリングし、VDAC8 に出力するものです。
ADC 出力 — Filter コンポーネント入力間は DMA でデータ転送を行い、Filter コンポーネント出力 — VDAC8 入力間は割り込みでデータ転送を行なっています。
VDAC8 への出力に DMA を使っていないのは、Filter コンポーネントの出力が「2 の補数」形式であるのに対し、VDAC8 は「ストレート・バイナリ」形式なので (MSB を反転するだけですが) フォーマット変換に CPU の介入が必要となるためです。
「Filter_ADC_VDAC01」とほぼ同一内容のプロジェクトですが、CPU の介入を割り込みではなく、main() 関数内のポーリングで行なう部分だけが異なる、「Filter_ADC_VDAC_poll01」サンプル・プロジェクトも存在しています。
この構成では、ハードウェアによる厳密に「ジッタレス」なサンプリングを受けた信号としては、デルタシグマ ADC の出力しかありません。
それ以降は、

という「将棋倒し」の連鎖でデータが渡っていき、サンプリング周波数で同期を「取り直す」部分がありません。
各部分でサンプリング周期に比べれば小さいものの、バス・クロック単位で見ればジッタが生じる可能性があります。
DMA は、バス使用権の調停に打ち勝てば、調停開始から 4 BUS_CLK で 1 回の転送が完了します。 このサンプル・プロジェクトでは DMA はひとつしか使っておらず、他の DMA に邪魔される可能性はないのですが、実際の複雑なプロジェクトの場合を考えると、他の DMA の転送中にデルタシグマ ADC の DMA リクエストが発生し、数 BUS_CLK 待たされる可能性を否定できません。
また、この Filter コンポーネントではフィルタ・チャネル A しか使っておらず、「入力待ち」の部分は 1 命令で実現されていて、フィルタの実行クロック数に変動が生じることはありません。 しかし、フィルタ・チャネル A / B 両方を使うフィルタ・プログラムでは、入力待ちループは一巡で 3 クロックかかるので、入力タイミングによっては実行クロック数にジッタが生じる可能性があります。
さらに CPU (Cortex-M3) では割り込み応答クロック数を一定にキープするメカニズムが採用されていますが、プログラム中で割り込み禁止状態を使用すると、それを原因とする割り込み応答遅れが生じる可能性があります。
このサンプル・プロジェクトのプログラムの規模では、ジッタは発生しないか、あるいは無視できるレベルになると思われ、サンプルという目的に対しては十分だろうと思います。
filter コンポーネントでは

  • 入力ステージング・レジスタへの書き込みコヒーレンシの完成を検出
  • フィルタ・プログラムを実行
  • 出力ホールディング・レジスタへ結果を書き込む
  • DMA リクエストやインタラプト発生

という動作をするので、「データ発生側」→「データ消費側」という向きで「タイミング」を伝達するのは自然な流れです。
それに対して、データの消費側である SPDIF_Tx コンポーネントからはデータ発生側に対して DMA や割り込みの「データ要求」を出します。 SPDIF_Tx は UDB (Universal Digital Block) で実現されているので、入力には FIFO があり、データの消費に間に合いさえすれば、入力データの転送タイミングにジッタがあっても問題ありません。 
ただし、FIFO 容量は 4 バイトなので、何も考えずにデータをどんどん突っ込めるわけではなく、FIFO が空にならず、あふれもしないように制御しながらデータ転送しなければなりません。
SPDIF_Tx コンポーネントが「律速」となり、データ要求を「逆向き」、つまり出力側から入力側に向かって

の順で伝えていかなければなりません。
公開予定のプロジェクト「spdif_4x」のトップ回路図を下に再掲します。

このプロジェクトでは、Filter コンポーネントは DMA ではなく、ソフトウェアのポーリングにより扱うことにしました。 
以前に示した、SPDIF_Tx と DMA だけを使ったプロジェクトの構成を活かし、ソフトウェアで DMA バッファに「素」のオーディオ・データを書き込むのではなく、ソフト的に Filter コンポーネントを叩いてフィルタリングした結果を読み込んでから DMA バッファに書き込むようにしました。
Filter コンポーネントのポーリング部分のプログラムについては次回説明します。