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

 DSP ライブラリ中の (補間/間引き/格子型/適応型などを除く「普通」の) FIR 関係の関数には次の 3 つがあります。

void FIRStructInit (
  FIRStruct*  filter,
  int         numCoeffs,
  fractional* coeffsBase,
  int         coeffsPage,
  fractional* delayBase
);
void FIRDelayInit (
   FIRStruct* filter
);
fractional* FIR (
   int         numSamps,
   fractional* dstSamps,
   fractional* srcSamps,
   FIRStruct*  filter
);

 まず、最初の「FIRStructInit()」関数は、補間/間引き/格子型/適応型などのフィルタのタイプによらず、すべての FIR タイプに共通で、フィルタの「インスタンス」ごとに必要な FIRStruct 型の構造体の初期設定のための関数です。
 FIRStruct 中の coeffEnd / delayEnd / delay フィールドについては、FIRStructInit() 関数の中で計算して求めているので、引数として渡す必要はありません。
 これは「初期設定」なので、最初に 1 回呼び出せば良く、何度も呼ぶ必要はありません。
 フィルタ計算に先立って、遅延要素の配列をゼロ・クリアするのが「FIRDelayInit()」関数です。
 これはフィルタリングを開始する最初の 1 回だけではなく、入力データ系列を切り替える場合にも呼び出します。
 新たなデータ系列のフィルタリングを始める前に FIRDelayInit() を呼び出すと、それ以前に入力されたデータの影響を除去することができます。
 (「普通」の) FIR フィルタの計算は FIR() 関数で行います。
 第 1 引数の「numSamps」に入出力サンプル数を与えます。
 その数を「N」とすると、第 3 引数「srcSamps」に与える入力サンプルを読み出す配列と第 2 引数「dstSamps」に与える出力サンプルを書き込む配列との、配列要素数を共に N と指定することになります。
 N は FIR() 関数の呼び出し時に毎回指定するので、一定値である必要はなく、呼び出しごとに値が違っていてもかまいません。
 第 4 引数「filter」は、各フィルタのインスタンスごとに確保した FIRStruct 型の構造体へのポインタです。
 FIR() 関数の一番最初の呼び出し以前に、FIRStructInit() 関数などを使って初期化および FIRDelayInit() 関数などを使って遅延要素をゼロ・クリアしておく必要があります。
 FIR() 関数では、遅延要素側のモジュロ・アドレッシングのために、FIRStruct の「delay」フィールドに処理終了時の遅延要素ポインタの値をセーブしているので、不用意にその値を変更しないように配慮する必要があります。
 アプリケーション側から見ると、FIRStruct 構造体は初期化後は中身をいじる必要はありません。
 最後に、FIR() 関数を使うためのプログラム例として、最低限の記述を行った断片を示します。 まず、タップ係数を X-データ領域に確保する場合です。

#include <xc.h>
#include <dsp.h>
. . . . . <中略> . . . . .
#define M_tap 127
#define N_samp 32
. . . . . <中略> . . . . .
FIRStruct fir_prof;

fractional src_buf[N_samp];
fractional dst_buf[N_samp];

fractional _YBSS(256)  d[M_tap];
fractional _XDATA(256) h[M_tap] = {
  -13,   15,    24,     2,
  -16,    4,    23,    -4,
 . . . . <中略> . . . . .
};
. . . . . <中略> . . . . .
int main( void )
{
. . . . . <中略> . . . . .
  FIRStructInit(&fir_prof, 
                M_tap, 
                &h[0], 
                COEFFS_IN_DATA, 
                &d[0]);
  FIRDelayInit(&fir_prof);
. . . . . <中略> . . . . .
  while (1) { // infinite loop
. . . . . <中略> . . . . .
    FIR(N_samp, 
        &dst_buf[0], 
        &src_buf[0], 
        &fir_prof);
. . . . . <中略> . . . . .
  } // while(1) 
} // int main()

 プログラム領域にタップ係数を格納する場合には次の 2 箇所を書き換えます。

const fractional __attribute__((aligned(256))) h[M_tap] = {
  -13,   15,    24,     2,
  -16,    4,    23,    -4,
 . . . . <中略> . . . . .
};

  FIRStructInit(&fir_prof, 
                M_tap, 
                &h[0], 
                PSVPAG, 
                &d[0]);