dsPIC33FJ64GP802 (8) --- DSP 命令と DSP ライブラリ (6)

 IIRCanonicStruct 構造体 (IIRTransposedStruct 構造体も同様) の「numSectionsLess1」 フィールドには、2 次セクションの段数を「S」としたとき、(S - 1) の値を設定します。 前回の 2 次セクション 1 段の場合には、(S - 1) = (1 - 1) = 0 を設定します。
 2 次セクションを 2 段とした場合の図を下に示します。 numSectionsLess1 は「1」となります。

 フィルタ係数の添え字は、たとえば、akn という表記の場合、「k」番目の 2 次セクションの z-n 次の係数を表すものとします。
 1 段目の出力は「外」つまり外部の 16 ビット・メモリには書き出さず、40 ビット・アキュムレータに 10.30 フォーマットで格納されたまま手を加えず 2 段目の入力として渡されます。
 最終段 (2 段目) の出力は、「finalShift」分のビット・シフトおよび 1 ビット左シフト (2 倍) 、さらに丸めを施して 1.15 の 16 ビット・データとして出力配列に書き出されます。
 遅延要素の配列の先頭アドレスは、IIRCanonicStruct 構造体の「delayBase」フィールドで指定しますが、必要なサイズは 2 次セクション 1 段あたり 2 ワードとなります。
 モジュロ・アドレッシングは使っていないので、配列のアライメントは要素が 16 ビット・ワードである配列に対して「自然」な値の、2 バイト以上にする必要はありません。
 フィルタ係数の配列の先頭アドレスは、「coeffsBase」で指定しますが、これもモジュロ・アドレッシングではないので、アライメントは「2 バイト」で十分です。
 フィルタ係数は 2 次セクション 1 段あたり 5 個で、1 段目から順に1.15 (Q15) フォーマットで

a12/2, a11/2, b12/2, b11/2, b10/2,
a22/2, a21/2, b22/2, b21/2, b20/2,

のように並べます。 (あるいは 2 で割らない元の数を Q14 フォーマットで記述)
 インクルード・ファイル "dsp.h" の中で「Q15」マクロが定義されているので、たとえば、C のソース・ファイルで、

  Q15(-0.9721889/2)

のように記述することができます。
 ちなみに、Q15(X) の中身は

#define Q15(X) \
   ((X < 0.0) ? (int)(32768*(X) - 0.5) : (int)(32767*(X) + 0.5)) 

となっていて、整数への変換結果を 0x8000 ~ 0x7fff に収めるために、引数の実数にかける変換係数が正側と負側とで異なっていて「歪む」ことになりますが、その量は量子化誤差と同レベルでほとんど問題になりません。
 FIR フィルタの場合と同様に、IIR フィルタでもフィルタ係数を X-データ・メモリ領域に置く場合と、PSV 機能を使ってプログラム領域に置く場合の 2 種の方法がとれます。
 IIRCanonicStruct 構造体の「coeffsPage」フィールドに「COEFFS_IN_DATA」を指定すれば X-データ・メモリに、PSV のページを指定すればプログラム領域に係数の配列を置くことになります。
 関数の実行サイクル数はフィルタ係数を X-データ・メモリに置く場合とプログラム領域に置く場合とで異なっていて、それぞれ次のようになっています。

  • X-データ領域にフィルタ係数を置く場合

38 + N * (8 + 7 * S)

  • プログラム領域にフィルタ係数を置く場合

41 + N * (9 + 12 * S)

 ここで、N は入出力サンプル数、S は 2 次セクションの段数です。
 2 次セクションひとつ当たりフィルタ係数は 5 個あるので、どの係数もゼロではないとすると、MAC 命令による積和計算が 5 回必要となり、理論上、5 サイクル未満で実行することはできません。
 X-データ・メモリに係数を置く場合、2 次セクションひとつ当たり 7 サイクルかかるので、(7 - 5) = 2 サイクルのオーバーヘッドが生じていることになります。
 その内訳は、

  • z-1 に相当する遅延要素からz-2 に相当する遅延要素への転送
  • z-1 に相当する遅延要素へのストア

の 2 命令です。 
 PSoC5LP の DFB (Digial Filter Block) では、2 次セクションひとつ当たり 10 サイクル、つまり (10 - 5) = 5 サイクルのオーバーヘッドがかかっていました。