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::CFilter * | filter |
フィルタ・オブジェクト FIRフィルタを実装するためのオブジェクト。CFilter型は、他のフィルタ型の先祖に当たる。 実際に生成されるフィルタ・オブジェクトは、CFilterの子孫のクラスに属する。 |
void afw::init | ( | void | ) |
afwの初期化
オーディオ・フレームワークの初期化。初期化関数はこれひとつよべば、残りの関数を まとめて呼んでくれる。ただし、 afw::startAudio は呼ばないので、プログラマが明示的に 呼ばなければならない。
参照先 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()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
参照先 CH_PER_SAMPLE・INTR_PER_BUFFER・rxBuffer・SAMPLE_PER_INTR・txBuffer.
参照元 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()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
参照元 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()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
参照先 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.cpp の 45 行で定義されています。
参照先 coeff・filter・scalefactor・stages.
参照元 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のクロックおよびフレーム同期 信号を自分で生成する設定に変更しなければならない。
参照先 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 | 各バッファに格納されているオーディオデータの数 |
実行に当たって必要なfilterオブジェクトの生成は、 afw::initProcessDataで行っている。
processdata.cpp の 65 行で定義されています。
参照先 filter・flt::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()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
参照元 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。 |
DMA3_CURR_Y_COUNTレジスタは、転送の最初に当たってDMA3_CURR_Y_COUNTレジスタの値に設定され、 ラインの転送が終わるごとにデクリメントされる。しかし、最後のラインの 転送後は、デクリメントされずに1のままに留まる。その結果、各ラインの転送終了 では、割込み発生ごとに以下のようにDMA3_CURR_Y_COUNTレジスタの値が変化する
このことから、ソフトウェアとの同期に使ってよいのはDMAx_CURR_Y_COUNTレジスタが2の場合 のみであり、あとは決めうちでバッファの添え字をインクリメントしなければならない事がわかる。 プログラム中では、この添え字としてbufferIdxをあてている。
トリプルバッファの管理が終わったら、受信DMAバッファからデータを取り出し、並べ なおしてから afw::processData を呼ぶ。
参照先 LEFT_CH・processData()・RIGHT_CH・rxBuffer・SAMPLE_PER_INTR・txBuffer.
参照元 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 | ) |
const int afw::CH_PER_SAMPLE = 2 |
const int afw::CODEC_RESET_PULS_WIDTH = 0x10000 |
オーディオ・コーデックのリセット時間
EZ-KIT Lite BF537では、オーディオ・コーデックのリセット信号がADSP-BF537のPF12に 接続されている。コーデックの使用に先立って、この信号をアサートしなければならない。
このマクロは、リセット信号をアサートする時間を与える。時間はループの繰り返し 回数なので、あまり精度は高くない。注意深い値が必要である。
参照元 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.cpp の 25 行で定義されています。
参照元 initProcessData().
const int afw::INTR_PER_BUFFER = 3 |
バッファ数宣言定数
DMA用のバッファ領域を afw::txBufferおよび afw::rxBufferとして 確保する際に、割り込みいくつ分のバッファを用意するかを宣言する。 具体的にいえば、トリプルバッファなので3を宣言する。過去3回の割り込み分のデータをバッファに 格納できるということである。
参照元 initDMA().
const int afw::LEFT_CH = 0 |
const int afw::RIGHT_CH = 1 |
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 だけ用意される次元は、このバッファが割込み何回分のデータを 格納するかを表す。
const int afw::SAMPLE_PER_INTR = 8 |
const short afw::scalefactor[stages] = {1} |
係数のスケールを決める バイクワッドのステージ毎にスケールファクターkを決める。kは次の式で求める。 k = 2^p すなわち、k=1ならばp=0、k=4ならばp=2である。pの値は最初のステージから順に 宣言する。p0, p1, p2.
..
processdata.cpp の 32 行で定義されています。
参照元 initProcessData().
const int afw::SPORT0_SLEN_24 = 0x0017 |
SPORT0のワード長
SPORT0設定時に使うワード長である。EZ-KIT BF537に搭載されているコーデックは I2S回線のデータを24bit使うので、ここでは24を用意している。
参照元 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 だけ用意される次元は、このバッファが割込み何回分のデータを 格納するかを表す。