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

 DSP ライブラリに含まれる関数をカテゴリ別に分類すると下のようになります。

  • ベクトル演算
  • 窓関数の初期化
  • 行列演算
  • フィルタ
  • FFT/DCT
  • PID 制御
  • 浮動小数点と固定小数点との相互変換
  • スタック・ガードの設定 (dsPIC33E のみ)

 これらのカテゴリ分けは、ライブラリのソース・ファイルの構成を反映しているだけで、ライブラリのオブジェクトおよびヘッダ・ファイル中ではすべての関数がフラットに定義されています。
 この中で、フィルタのカテゴリの中を見ると、

  • FIR() — FIR フィルタ
  • FIRDecimate() — FIR + ダウン・サンプル
  • FIRInterpolate() — アップ・サンプル + FIR
  • FIRLattice() — 格子型 FIR フィルタ
  • FIRLMS() — 適応 FIR フィルタ (最小二乗アルゴリズム)
  • IIRCanonic() — IIR フィルタ (標準型)
  • IIRTransposed() — IIR フィルタ (転置型)
  • IIRLattice() — 格子型 IIR フィルタ

などの関数が定義されています。
 残念ながら、現状では、C 言語で適当に書き散らかしたプログラムを C コンパイラがいい感じに DSP 命令を使ったオブジェクトに変換してくれるようにはなっていないので、DSP 命令を活かしたプログラムとするにはアセンブリ言語を使う必要があります。
 上記のライブラリ関数を利用することで間に合うのなら、アセンブリ言語によるプログラミングをする必要もなく、簡単に済みます。 ソースも付属しているので、必要なら一部を改造して、機能として足りない部分を補うこともできます。
 ここでは、上記の中から FIR() と IIRCanonic() を取り上げます。
 まず、「DSP エンジン部」で扱うデータ形式を下に示します。

 16 ビット幅の固定小数点数で、b15 の右 (b15 と b14 との間) に小数点があるものとします。
 2 進数としての「重み」は b15 が -20 (符号) であり、b14 が 2-1、以下同様に続いて、 b0 が 2-15 となります。
 このフォーマットを「1.15」あるいは「Q15」フォーマット呼びます。 1.15 の「1」は整数部 (および符号部) が 1 ビットであることを示しています。 符号部と共用しているため、「整数部」が現れるのは 0x8000 = -1.0 の場合に限られ、それ以外では -0.999969 ~ +0.999969 の範囲の小数部のみの数となります。
 1.15 の「15」は小数部が 15 ビットであることを示しており、これは「Q15」の「15」も同様です。
 ヘッダ・ファイル「dsp.h」の先頭で、

typedef int  fractional;

という宣言がされています。
 dsPIC は 16 ビット・プロセッサなので、int 型は 16 ビット符号付き整数を表します。 上の宣言は、単に int 型に fractional という別名を与えているだけに過ぎませんが、DSP ライブラリでは「fractional」型をデータやフィルタ係数の基本の型としています。
 DSP エンジンでは、積和演算のオペランドを「整数」として扱うモードおよび「固定小数点数」として扱うモードのいずれかを選択できます。
 固定小数点モードでの MAC 命令では、 1.15 フォーマットのふたつのオペランドを乗算し、その結果を 1.31 フォーマットの数として桁合わせを行い、9.31 フォーマットで数値が保持されている 40 ビット・アキュムレータに加算します。

 40 ビット・アキュムレータは、8/16/16 ビットごとに区切られて、SFR (Special Function Register) 空間で 3 つのレジスタ ACCxU、ACCxH、ACCxL としてアクセスできます。
 ここで、「x」はふたつあるアキュムレータ A / B の指定であり、たとえば ACCAU、ACCBU などとなります。
 ACCxH を読み出せば、位取りは 1.15 フォーマットとなり、もとの入力データとレベルが合います。 この SFR 経由でのアクセスでは、シフトや飽和演算は行われません。
 アキュムレータの内容を 16 ビット・データとしてストアする「SAC」命令では、アキュムレータ自身は変化させず、読み出した値にシフトおよび飽和演算を施した上で (SAC.R 命令では丸めも) b31 ~ b16 を抜き出して書き出します。
 飽和演算については、

  • なし
  • 通常飽和モード (1.31)
  • スーバー・サチュレーション・モード (9.31)

の 3 種のモードがあります。
 通常飽和モードでは、結果が 1.31 の範囲におさまるように飽和演算が行われます。
 スーパー・サチュレーション・モードでは、40 ビット・アキュムレータで保持できる範囲におさまるように飽和演算が行われます。 具体的には、

-256.0 ~ (256.0 - 2-31)

の範囲となります。