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]);