ネームスペース afw


説明

オーディオ・フレームワーク

ADSP-BF537 EZ-KIT Lite上で動作するオーディオフレームワーク関連の関数および変数を含む名前空間。 プログラマは以下の関数を呼んでオーディオ処理を開始する。


関数

void initGPIO (void)
 GPIOの初期化
void resetCODEC (void)
 オーディオ・コーデックのリセット
void initSPORT (void)
 SPORT0の初期化
void initDMA (void)
 SPORT DMAの初期化
void initInterrupt (void)
 割り込みのイネーブル
void init ()
 afwの初期化
void startAudio (void)
 SPORTとDMAのイネーブル
void rxISR (int signal)
 SPORT0受信DMA割り込みハンドラ
void initProcessData (void)
 コールバック関数の初期化
void processData (const shortfract leftIn[], const shortfract rightIn[], shortfract leftOut[], shortfract rightOut[], int count)
 オーディオ・コールバック関数

変数

int volatile txBuffer [INTR_PER_BUFFER][SAMPLE_PER_INTR][CH_PER_SAMPLE]
 SPORT0 DMA 送信バッファ
int volatile rxBuffer [INTR_PER_BUFFER][SAMPLE_PER_INTR][CH_PER_SAMPLE]
 SPORT0 DMA 受信バッファ
const int LEFT_CH = 0
 左チャンネル指定定数
const int RIGHT_CH = 1
 右チャンネル指定定数
const int INTR_PER_BUFFER = 3
 バッファ数宣言定数
const int CH_PER_SAMPLE = 2
 サンプルあたりチャンネル数の宣言
const int SAMPLE_PER_INTR = 8
 割り込みあたりのサンプル数
const int CODEC_RESET_PULS_WIDTH = 0x10000
 オーディオ・コーデックのリセット時間
const int SPORT0_SLEN_24 = 0x0017
 SPORT0のワード長
const int stages = 1
 ステージ数 バイクワッドフィルタの段数を与える。バイクワッド1段辺り2次なので、 6次のチェビシェフフィルタならステージ数は3
const shortfract coeff [stages *5] = { 0.098r, -0.185r, 0.195r, -0.392r, 0.195 }
 IIRフィルタ系数列 IIRフィルタに与える係数の列。先頭から順位にA2/k, A1/k, B2/k, B1/k, B0/k。A0は指定 しないが、1で無ければならない。複数ステージのバイクワッドを直列実装する場合は、 同じ順序で繰り返し係数を指定する。すなわち、 A02/k0, A01/k0, B02/k0, B01/k0, B00/k0, A12/k1, A11/k1, B12/k1, B11/k1, B10/k1, .
const short scalefactor [stages] = {1}
 係数のスケールを決める バイクワッドのステージ毎にスケールファクターkを決める。kは次の式で求める。 k = 2^p すなわち、k=1ならばp=0、k=4ならばp=2である。pの値は最初のステージから順に 宣言する。p0, p1, p2.
flt::CFilterfilter
  フィルタ・オブジェクト FIRフィルタを実装するためのオブジェクト。CFilter型は、他のフィルタ型の先祖に当たる。 実際に生成されるフィルタ・オブジェクトは、CFilterの子孫のクラスに属する。


関数

void afw::init ( void   ) 

afwの初期化

オーディオ・フレームワークの初期化。初期化関数はこれひとつよべば、残りの関数を まとめて呼んでくれる。ただし、 afw::startAudio は呼ばないので、プログラマが明示的に 呼ばなければならない。

afw.cpp172 行で定義されています。

参照先 initDMA()initGPIO()initInterrupt()initProcessData()initSPORT()resetCODEC().

参照元 main().

00173     {
00174         initGPIO();
00175         resetCODEC();
00176         initSPORT();
00177         initDMA();
00178         initInterrupt();
00179         
00180         initProcessData();
00181     }

void afw::initDMA ( void   ) 

SPORT DMAの初期化

SPORT0に接続されているDMAを設定する。DMA3が受信、DMA4が送信である。 オーディオ信号は16ビット以上の長さがあるのでワードサイズは32bit, 連続送受信のためにオートバッファ、モードを使う。また、トリプル・バッファを 実装するために、DMA転送は2次元で行い、3ライン分のバッファを確保して各ラインの 転送を終えるたびに割り込みを発生させる。 afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。

afw.cpp126 行で定義されています。

参照先 CH_PER_SAMPLEINTR_PER_BUFFERrxBufferSAMPLE_PER_INTRtxBuffer.

参照元 init().

00127     {
00128     
00129                 // DMA3の設定
00130         *pDMA3_CONFIG = WNR | WDSIZE_32 | DI_EN | DI_SEL | FLOW_AUTO | DMA2D ; // 32bit, 2DDMA, 各ライン割り込み、オートバッファ
00131         *pDMA3_START_ADDR = (void *) rxBuffer;                  // 受信DMAバッファへのポインタ
00132         *pDMA3_X_COUNT = CH_PER_SAMPLE * SAMPLE_PER_INTR;       // 2次元DMAの桁数
00133         *pDMA3_X_MODIFY = sizeof(int);                          // 転送ごとのインクリメント量
00134         *pDMA3_Y_COUNT = INTR_PER_BUFFER;                       // 2次元DMAの行数
00135         *pDMA3_Y_MODIFY = sizeof(int);                          // 1行転送後のインクリメント量
00136     
00137                 // DMA4の設定
00138         *pDMA4_CONFIG = WDSIZE_32 | FLOW_AUTO | DMA2D;          // 32bit, 2DDMA, オートバッファ
00139         *pDMA4_START_ADDR = (void *)txBuffer;                   // 受信DMAバッファへのポインタ
00140         *pDMA4_X_COUNT = CH_PER_SAMPLE * SAMPLE_PER_INTR;       // 2次元DMAの桁数
00141         *pDMA4_X_MODIFY = sizeof(int);                          // 転送ごとのインクリメント量
00142         *pDMA4_Y_COUNT = INTR_PER_BUFFER;                       // 2次元DMAの行数
00143         *pDMA4_Y_MODIFY = sizeof(int);                          // 1行転送後のインクリメント量
00144 
00145     }

void afw::initGPIO ( void   ) 

GPIOの初期化

PORT Fに割り当てられているGPIO(フラグピン)の初期化を行う。 PORT Fのピン割り当ては以下のとおり(カッコ内はマスク)

afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。

afw.cpp53 行で定義されています。

参照元 init().

00054     {
00055         *pPORTF_FER = 0x0000;           // ポート Fのプログラマブル・フラグを利用できるようにする。
00056         *pPORTFIO_DIR = 0x1FC0;         // ポートFの方向設定。LEDとコーデックのRESET制御を出力に
00057         *pPORTFIO_INEN = 0x003C;        // プッシュボタン用のピンを入力可能にする
00058         *pPORTFIO_CLEAR = 0x0FC0;       // LEDを消灯
00059     }

void afw::initInterrupt ( void   ) 

割り込みのイネーブル

SPORT0 受信割込みを有効化する。SPORT0 受信割り込みはIVG9で処理したいので、その割り当ても設定する。 afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。

afw.cpp152 行で定義されています。

参照先 rxISR().

参照元 init().

00153     {
00154                 // SPORT0受信DMA終了割り込み(DMA3)の優先度を設定する 
00155         *pSIC_IAR0 &= 0xff0fffff;           // DMA3の割り込み割りあてを解除
00156         *pSIC_IAR0 |= 0x00200000;           // DMA3を優先度2 (IVG9)に割り当てる
00157 
00158                 // 割込みハンドラを登録する
00159         interrupt( SIGIVG9, rxISR );
00160 
00161                 // SPORT0 RX 割込みを有効に
00162         *pSIC_IMASK |= 0x00000020;
00163     }

void afw::initProcessData ( void   ) 

コールバック関数の初期化

フィルタ・オブジェクトを生成して実行の準備を行う。生成するオブジェクトのクラスは flt::CIIRFilterExである。 オブジェクト生成時に係数配列やタップ数を指定するため、実行時にこれらのパラメータを指定する必要はない。

processdata.cpp45 行で定義されています。

参照先 coefffilterscalefactorstages.

参照元 init().

00046     {
00047         // iirフィルタを作る
00048         filter = new flt::CIIRFilterEx( coeff, scalefactor,stages );
00049 //        filter = new flt::CIIRFilter( coeff, stages );   // スケーリングしない場合
00050     }

void afw::initSPORT ( void   ) 

SPORT0の初期化

オーディオコーデックに接続されているSPORT0を初期化する。シリアル回線の フォーマットはI2Sで、クロックおよびLR信号は外部生成。この関数を読んだ段階 では、ポートはディセーブルのままにしておく。

設定は送受信とも以下のとおり

詳細はADSP-BF537 Hardware Referenceの "Stereo Serial Operation" を参照のこと。 afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。

注意:EZ-KIT Lite BF537 Rev 1.0のユーザーはSPORTのクロックおよびフレーム同期 信号を自分で生成する設定に変更しなければならない。

afw.cpp104 行で定義されています。

参照先 SPORT0_SLEN_24.

参照元 init().

00105     {
00106                 // Sport0 受信設定
00107         *pSPORT0_RCR1 = RFSR | RCKFE;
00108         *pSPORT0_RCR2 = SPORT0_SLEN_24 | RSFSE;
00109     
00110                 // Sport0 送信設定
00111         *pSPORT0_TCR1 = TFSR | TCKFE;
00112         *pSPORT0_TCR2 = SPORT0_SLEN_24 | TSFSE;
00113 
00114     
00115     }

void afw::processData ( const shortfract  leftIn[],
const shortfract  rightIn[],
shortfract  leftOut[],
shortfract  rightOut[],
int  count 
)

オーディオ・コールバック関数

引数:
leftIn 左チャンネルの入力データバッファ
rightIn 右チャンネルの入力データバッファ
leftOut 左チャンネルの出力データバッファ
rightOut 右チャンネルの出力データバッファ
count 各バッファに格納されているオーディオデータの数
左チャンネルにFIRフィルタを施して出力する。同じ入力データを 比較のため処理せずに右チャンネルにも出力する。

実行に当たって必要なfilterオブジェクトの生成は、 afw::initProcessDataで行っている。

processdata.cpp65 行で定義されています。

参照先 filterflt::CFilter::run().

参照元 rxISR().

00072     {    
00073             // 注意:左チャンネルしか処理していない
00074         filter->run( leftIn, leftOut, count ); 
00075 
00076             // 参照用に未処理の信号を右チャンネルに出力している
00077         for( int i=0; i<count; i++ )
00078             rightOut[i] = leftIn[i];
00079     }   // processData

void afw::resetCODEC ( void   ) 

オーディオ・コーデックのリセット

PORT Fに割り当てられているコーデック・リセット信号(PF12)をトグルする。 afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。

afw.cpp67 行で定義されています。

参照先 CODEC_RESET_PULS_WIDTH.

参照元 init().

00068     {
00069         *pPORTFIO_CLEAR = PF12;             // リセット・ピンをアサートする。
00070     
00071         for( int i = 0; i< CODEC_RESET_PULS_WIDTH;i++)          // アサート状態を一定時間保持
00072             asm volatile( "nop;" );
00073     
00074         *pPORTFIO_SET = PF12;               // リセット・ピンをデアサートする。
00075 
00076 
00077     }

void afw::rxISR ( int  signal  ) 

SPORT0受信DMA割り込みハンドラ

引数:
signal ハンドラが呼ばれた割り込み順位が与えられる。値は SIGIVG7 〜 SIGIVG15。
rxISRはSPORT0の受信DMAから割り込みがかかるたびに呼び出され、割り込みのクリアと トリプル・バッファの管理を行う。トリプルバッファの管理は、DMA3_CURR_Y_COUNTレジスタの値を もとに行う。

DMA3_CURR_Y_COUNTレジスタは、転送の最初に当たってDMA3_CURR_Y_COUNTレジスタの値に設定され、 ラインの転送が終わるごとにデクリメントされる。しかし、最後のラインの 転送後は、デクリメントされずに1のままに留まる。その結果、各ラインの転送終了 では、割込み発生ごとに以下のようにDMA3_CURR_Y_COUNTレジスタの値が変化する

このことから、ソフトウェアとの同期に使ってよいのはDMAx_CURR_Y_COUNTレジスタが2の場合 のみであり、あとは決めうちでバッファの添え字をインクリメントしなければならない事がわかる。 プログラム中では、この添え字としてbufferIdxをあてている。

トリプルバッファの管理が終わったら、受信DMAバッファからデータを取り出し、並べ なおしてから afw::processData を呼ぶ。

afw.cpp251 行で定義されています。

参照先 LEFT_CHprocessData()RIGHT_CHrxBufferSAMPLE_PER_INTRtxBuffer.

参照元 initInterrupt().

00252     {
00253         static int bufferIdx = 0;       // トリプル・バッファ操作用インデックス
00254     
00255         *pDMA3_IRQ_STATUS = 0x0001;         // 割込みクリア
00256     
00257                 // トリプルバッファのどのバッファを使うか決める
00258         if ( *pDMA3_CURR_Y_COUNT == 2 )     // 2次元DMAの最初の行の転送が終了した場合
00259             bufferIdx = 0;
00260         else                                // それ以外の場合
00261             bufferIdx ++;
00262 
00263                 // DMAが格納した受信データを入力バッファにコピーする
00264                 // 受信データバッファは24bit データを右詰で32bit 変数に格納しているので
00265                 // 8bit右シフトして入力バッファにコピーする
00266         for( int i =0; i< SAMPLE_PER_INTR; i++ ){
00267             lchIn[i] =  rxBuffer[bufferIdx][i][LEFT_CH]  >>8;
00268             rchIn[i] = rxBuffer[bufferIdx][i][RIGHT_CH] >>8;
00269         }
00270         
00271                 // ユーザー・コールバック関数の呼び出し
00272         processData( 
00273                         (shortfract *)lchIn,       // short型とshortfract型は
00274                         (shortfract *)rchIn,      // 同じ大きさなので、
00275                         (shortfract *)lchOut,      // キャストによって強制変換していい
00276                         (shortfract *)rchOut, 
00277                         SAMPLE_PER_INTR 
00278                     );              
00279 
00280                 // 出力バッファのデータを送信データバッファにコピーする
00281                 // 送信データバッファは24bit データを右詰で32bit 変数に格納しているので
00282                 // 出力バッファから8bit左シフトして送信バッファにコピーする 
00283         for( int i =0; i< SAMPLE_PER_INTR; i++ ){
00284             txBuffer[bufferIdx][i][LEFT_CH] = lchOut[i] <<8;
00285             txBuffer[bufferIdx][i][RIGHT_CH]= rchOut[i] <<8;
00286         }
00287 
00288     }

void afw::startAudio ( void   ) 

SPORTとDMAのイネーブル

設定が終わったSPORTとDMAの両方をイネーブルする

afw.cpp187 行で定義されています。

参照元 main().

00188     {
00189                 // DMA開始
00190         *pDMA4_CONFIG   |= DMAEN;   // 送信
00191         *pDMA3_CONFIG   |= DMAEN;   // 受信
00192     
00193                 // SPORT開始
00194         *pSPORT0_TCR1   |= TSPEN;
00195         *pSPORT0_RCR1   |= RSPEN;
00196     }


変数

const int afw::CH_PER_SAMPLE = 2

サンプルあたりチャンネル数の宣言

サンプルあたり何チャンネルのデータを伝送するか宣言する。I2Sはステレオなので、この値は2である。 この値はユーザーが変更してはならない。

afw.h63 行で定義されています。

参照元 initDMA().

const int afw::CODEC_RESET_PULS_WIDTH = 0x10000

オーディオ・コーデックのリセット時間

EZ-KIT Lite BF537では、オーディオ・コーデックのリセット信号がADSP-BF537のPF12に 接続されている。コーデックの使用に先立って、この信号をアサートしなければならない。

このマクロは、リセット信号をアサートする時間を与える。時間はループの繰り返し 回数なので、あまり精度は高くない。注意深い値が必要である。

afw.h81 行で定義されています。

参照元 resetCODEC().

const shortfract afw::coeff[stages *5] = { 0.098r, -0.185r, 0.195r, -0.392r, 0.195 }

IIRフィルタ系数列 IIRフィルタに与える係数の列。先頭から順位にA2/k, A1/k, B2/k, B1/k, B0/k。A0は指定 しないが、1で無ければならない。複数ステージのバイクワッドを直列実装する場合は、 同じ順序で繰り返し係数を指定する。すなわち、 A02/k0, A01/k0, B02/k0, B01/k0, B00/k0, A12/k1, A11/k1, B12/k1, B11/k1, B10/k1, .

.. kの値はステージ毎に指定できるkの指定は afw::scalefactorで指定する。

サンプルで使っている係数は、「実践ディジタル・フィルタ設計入門」(ISBN4-7898-3400-X)158ページから引用した。

processdata.cpp25 行で定義されています。

参照元 initProcessData().

const int afw::INTR_PER_BUFFER = 3

バッファ数宣言定数

DMA用のバッファ領域を afw::txBufferおよび afw::rxBufferとして 確保する際に、割り込みいくつ分のバッファを用意するかを宣言する。 具体的にいえば、トリプルバッファなので3を宣言する。過去3回の割り込み分のデータをバッファに 格納できるということである。

afw.h55 行で定義されています。

参照元 initDMA().

const int afw::LEFT_CH = 0

左チャンネル指定定数

afw::rxBufferおよび、 afw::txBufferにアクセスする際、最下位の添え字を指定 するときに使う。

afw.h38 行で定義されています。

参照元 rxISR().

const int afw::RIGHT_CH = 1

右チャンネル指定定数

afw::rxBufferおよび、 afw::txBufferにアクセスする際、最下位の添え字を指定 するときに使う。

afw.h45 行で定義されています。

参照元 rxISR().

volatile int afw::rxBuffer

SPORT0 DMA 受信バッファ

受信DMAがアクセスし、SPORT RXチャンネルからデータを受け取るのバッファ

最下位の次元はL, Rチャンネル用に2つの要素を格納する。下から2番目の次元は、 割込み1回ごとに送信されるサンプル数を指定する。1回の割り込みの間にDMA転送 されるデータの量は、 afw::SAMPLE_PER_INTR * afw::CH_PER_SAMPLE で決まる。

afw::INTR_PER_BUFFER だけ用意される次元は、このバッファが割込み何回分のデータを 格納するかを表す。

afw.cpp41 行で定義されています。

参照元 initDMA()rxISR().

const int afw::SAMPLE_PER_INTR = 8

割り込みあたりのサンプル数

何サンプルのデータを受信したら割り込みをかけるかを指定する。この値を大きくするほど 効率がよくなるが、遅延も増大し、また、必要なメモリ量も増える。したがって、これらの バランスを考えながらユーザーが値を決めることになる。

afw.h71 行で定義されています。

参照元 initDMA()rxISR().

const short afw::scalefactor[stages] = {1}

係数のスケールを決める バイクワッドのステージ毎にスケールファクターkを決める。kは次の式で求める。 k = 2^p すなわち、k=1ならばp=0、k=4ならばp=2である。pの値は最初のステージから順に 宣言する。p0, p1, p2.

..

processdata.cpp32 行で定義されています。

参照元 initProcessData().

const int afw::SPORT0_SLEN_24 = 0x0017

SPORT0のワード長

SPORT0設定時に使うワード長である。EZ-KIT BF537に搭載されているコーデックは I2S回線のデータを24bit使うので、ここでは24を用意している。

afw.h88 行で定義されています。

参照元 initSPORT().

volatile int afw::txBuffer

SPORT0 DMA 送信バッファ

送信DMAがアクセスし、SPORT TXチャンネルにデータを送り込むためのバッファ

最下位の次元はL, Rチャンネル用に2つの要素を格納する。下から2番目の次元は、 割込み1回ごとに送信されるサンプル数を指定する。1回の割り込みの間にDMA転送 されるデータの量は、 afw::SAMPLE_PER_INTR * afw::CH_PER_SAMPLE で決まる。

afw::INTR_PER_BUFFER だけ用意される次元は、このバッファが割込み何回分のデータを 格納するかを表す。

afw.cpp27 行で定義されています。

参照元 initDMA()rxISR().


IIR filter sample by wrapper classに対してMon Dec 18 17:29:47 2006に生成されました。  doxygen 1.5.1-p1