- メインページ
- ネームスペース
- クラス
- ファイル

- ネームスペース一覧
- ネームスペースメンバ

# ネームスペース afw

## 説明

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

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

- afw::init
- afw::start

## 関数
void | initGPIO (void)
| GPIOの初期化
void | resetCODEC (void)
| オーディオ・コーデックのリセット
void | initSPORT (void)
| SPORT0の初期化
void | initDMA (void)
| SPORT DMAの初期化
void | initInterrupt (void)
| 割り込みのイネーブル
void | init (void)
| afwの初期化
void | start (void)
| SPORTとDMAのイネーブル
bool | ISR (void)
| SPORT0受信DMA割り込みサービス・ルーチン
void | initProcessData (int count)
| コールバック関数の初期化
void | processData (const shortfract leftIn[], const shortfract rightIn[], shortfract leftOut[], shortfract rightOut[], int count)
| オーディオ・コールバック関数
## 変数
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_32 = 31
| SPORT0のワード長
volatile int | txBuffer [INTR_PER_BUFFER][SAMPLE_PER_INTR][CH_PER_SAMPLE]
| SPORT0 DMA 送信バッファ
volatile int | rxBuffer [INTR_PER_BUFFER][SAMPLE_PER_INTR][CH_PER_SAMPLE]
| SPORT0 DMA 受信バッファ
short | lchIn [SAMPLE_PER_INTR]
| 左チャンネル入力バッファ
short | lchOut [SAMPLE_PER_INTR]
| 左チャンネル出力バッファ
short | rchIn [SAMPLE_PER_INTR]
| 右チャンネル入力バッファ
short | rchOut [SAMPLE_PER_INTR]
| 右チャンネル出力バッファ
const int | Hz = (int)(65536.0*65536.0/48000.0)
| 周波数指定用定数
shortfract * | temp
| 一時データ用バッファ
osc::COscillator * | tone
| トーン・ジェネレーター変数

## 関数

void afw::init | ( | void |  | ) |

afwの初期化

オーディオ・フレームワークの初期化。初期化関数はこれひとつよべば、残りの関数を まとめて呼んでくれる。ただし、 afw::start は呼ばないので、プログラマが明示的に 呼ばなければならない。また、afwISR()を割込みハンドラとして登録するのも プログラマの責任で行う

afw.cpp の 220 行で定義されています。

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

参照元 main().

    00221     {
    00222         initGPIO();
    00223         resetCODEC();
    00224         initSPORT();
    00225         initDMA();
    00226         initInterrupt();
    00227
    00228         initProcessData(SAMPLE_PER_INTR);
    00229     }

void afw::initDMA | ( | void |  | ) |

SPORT DMAの初期化

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

afw.cpp の 185 行で定義されています。

参照先 CH_PER_SAMPLE, INTR_PER_BUFFER, rxBuffer, SAMPLE_PER_INTR, と txBuffer.

参照元 init().

    00186     {
    00187
    00188                 // DMA3の設定
    00189         *pDMA3_CONFIG = WNR | WDSIZE_32 | DI_EN | DI_SEL | FLOW_AUTO | DMA2D ; // 32bit, 2DDMA, 各ライン割り込み、オートバッファ
    00190         *pDMA3_START_ADDR = (void *) rxBuffer;                  // 受信DMAバッファへのポインタ
    00191         *pDMA3_X_COUNT = CH_PER_SAMPLE * SAMPLE_PER_INTR;       // 2次元DMAの桁数
    00192         *pDMA3_X_MODIFY = sizeof(int);                          // 転送ごとのインクリメント量
    00193         *pDMA3_Y_COUNT = INTR_PER_BUFFER;                       // 2次元DMAの行数
    00194         *pDMA3_Y_MODIFY = sizeof(int);                          // 1行転送後のインクリメント量
    00195
    00196                 // DMA4の設定
    00197         *pDMA4_CONFIG = WDSIZE_32 | FLOW_AUTO | DMA2D;          // 32bit, 2DDMA, オートバッファ
    00198         *pDMA4_START_ADDR = (void *)txBuffer;                   // 受信DMAバッファへのポインタ
    00199         *pDMA4_X_COUNT = CH_PER_SAMPLE * SAMPLE_PER_INTR;       // 2次元DMAの桁数
    00200         *pDMA4_X_MODIFY = sizeof(int);                          // 転送ごとのインクリメント量
    00201         *pDMA4_Y_COUNT = INTR_PER_BUFFER;                       // 2次元DMAの行数
    00202         *pDMA4_Y_MODIFY = sizeof(int);                          // 1行転送後のインクリメント量
    00203
    00204     }

void afw::initGPIO | ( | void |  | ) |

GPIOの初期化

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

- pin 2..5 (0x003C) プッシュボタン
- pin 6..11 (0x0FC0) LED
- pin 12 (0x1000) コーデックのRESETピン

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

afw.cpp の 114 行で定義されています。

参照元 init().

    00115     {
    00116         *pPORTF_FER   &= ~PF12;         // ポート Fのプログラマブル・フラグを利用できるようにする。
    00117         *pPORTFIO_DIR |=  PF12;         // ポートFの方向設定。LEDとコーデックのRESET制御を出力に
    00118     }

void afw::initInterrupt | ( | void |  | ) |

割り込みのイネーブル

SPORT0 受信割込みを有効化する。SPORT0 受信割り込みはデフォルトでは DMA3に割り当てられているので、DMA3割込みを有効にする。

afw.cpp の 211 行で定義されています。

参照元 init().

    00212     {
    00213
    00214                 // SPORT0 RX 割込みを有効に。デフォルトはDMA3
    00215         *pSIC_IMASK |= IRQ_DMA3;
    00216     }

void afw::initProcessData | ( | int | count | ) |

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

引数:

  | count | afw::processDataが呼ばれる際、各バッファに格納されているオーディオデータの数

バッファ変数と発振器オブジェクトを生成して実行に備える。

processdata.cpp の 34 行で定義されています。

参照先 Hz, temp, と tone.

参照元 init().

    00035     {
    00036         temp = new shortfract[count];
    00037         tone = new osc::CTableLookup( 440*Hz );
    00038     }

void afw::initSPORT | ( | void |  | ) |

SPORT0の初期化

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

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

- 外部クロック
- 外部LR信号
- I2S設定
  - xCKFE = 1
  - xFSR = 1
  - LAxFS = 0
  - LxFS = 0
  - xRFST = 0
  - xDTYPE = 0
- 24bit データ
- セカンダリ・チャンネル無効

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

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

afw.cpp の 163 行で定義されています。

参照先 SPORT0_SLEN_32.

参照元 init().

    00164     {
    00165                 // Sport0 受信設定
    00166         *pSPORT0_RCR1 = RFSR | RCKFE;
    00167         *pSPORT0_RCR2 = SPORT0_SLEN_32 | RSFSE;
    00168
    00169                 // Sport0 送信設定
    00170         *pSPORT0_TCR1 = TFSR | TCKFE;
    00171         *pSPORT0_TCR2 = SPORT0_SLEN_32 | TSFSE;
    00172
    00173
    00174     }

bool afw::ISR | ( | void |  | ) |

SPORT0受信DMA割り込みサービス・ルーチン

戻り値:
  デバイスの割り込み処理を行ったときには真を返す。行わなければ偽。

afw::ISRはSPORT0の受信DMAから割り込みがかかるたびに呼び出され、割り込みのクリアと トリプル・バッファの管理を行う。トリプルバッファの管理は、DMA3_CURR_Y_COUNTレジスタの値を もとに行う。 なお、割り込みがSPORT0 受信DMA割込みではない場合、afwISRは何もせずに戻る。

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

- 最初のラインの転送終了時。DMA3_CURR_Y_COUNT == 2。プロセッサが扱ってよいバッファの添え字は 0
- 2番目のラインの転送終了時。DMA3_CURR_Y_COUNT == 1。プロセッサが扱ってよいバッファの添え字は 1
- 3番目のラインの転送終了時。DMA3_CURR_Y_COUNT == 1。プロセッサが扱ってよいバッファの添え字は 2

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

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

afw.cpp の 271 行で定義されています。

参照先 lchIn, lchOut, LEFT_CH, processData(), rchIn, rchOut, RIGHT_CH, rxBuffer, SAMPLE_PER_INTR, と txBuffer.

参照元 cec::ivg9().

    00272     {
    00273         if ( *pSIC_ISR & IRQ_DMA3 ){        // SPORT0_RX割込みか?
    00274             static unsigned int bufferIdx = 0;       // トリプル・バッファ操作用インデックス
    00275
    00276             *pDMA3_IRQ_STATUS = 0x0001;         // 割込みクリア
    00277
    00278                     // トリプルバッファのどのバッファを使うか決める
    00279             if ( *pDMA3_CURR_Y_COUNT == 2 )     // 2次元DMAの最初の行の転送が終了した場合
    00280                 bufferIdx = 0;
    00281             else if ( bufferIdx < 2 )           // それ以外の場合
    00282                 bufferIdx ++;
    00283             else
    00284                 bufferIdx = 0;                  // 値が異常な場合の処理
    00285
    00286                     // DMAが格納した受信データを入力バッファにコピーする
    00287                     // 受信データバッファは24bit データを左詰めで32bit 変数に格納しているので
    00288                     // 16bit右シフトして入力バッファにコピーする
    00289             for( int i =0; i< SAMPLE_PER_INTR; i++ ){
    00290                 lchIn[i] = rxBuffer[bufferIdx][i][LEFT_CH]  >>16;
    00291                 rchIn[i] = rxBuffer[bufferIdx][i][RIGHT_CH] >>16;
    00292             }
    00293
    00294                     // ユーザー・コールバック関数の呼び出し
    00295             processData(
    00296                             (shortfract *)lchIn,       // short型とshortfract型は
    00297                             (shortfract *)rchIn,      // 同じ大きさなので、
    00298                             (shortfract *)lchOut,      // キャストによって強制変換していい
    00299                             (shortfract *)rchOut,
    00300                             SAMPLE_PER_INTR
    00301                         );
    00302
    00303                     // 出力バッファのデータを送信データバッファにコピーする
    00304                     // 送信データバッファは24bit データを左詰めで32bit 変数に格納しているので
    00305                     // 出力バッファから16bit左シフトして送信バッファにコピーする
    00306             for( int i =0; i< SAMPLE_PER_INTR; i++ ){
    00307                 txBuffer[bufferIdx][i][LEFT_CH] = lchOut[i] <<16;
    00308                 txBuffer[bufferIdx][i][RIGHT_CH]= rchOut[i] <<16;
    00309             }
    00310             return (true);         // 割込み処理を行った
    00311         }
    00312         else
    00313             return(false);          // 割込み処理を行わなかった
    00314
    00315     }

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

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

引数:

  | leftIn | 左チャンネルの入力データバッファ
  | rightIn | 右チャンネルの入力データバッファ
  | leftOut | 左チャンネルの出力データバッファ
  | rightOut | 右チャンネルの出力データバッファ
  | count | 各バッファに格納されているオーディオデータの数

この関数はDMAが受信バッファをいっぱいにするたびに割り込み経由で呼ばれる。 引数として渡されるのは受信データを含む入力バッファのほか、送信データを 格納するために使う出力バッファとデータ個数である。 ユーザーは関数内部で入力バッファのデータを加工して、出力バッファに送信すべき データをおく。呼び出しに先立って初期化が必要な場合は、 afw::initProcessData() 関数で行う。

配列はshortfract型である。この16bit固定小数点型はshortと同じ大きさを 持つが、四則は固定小数点領域で定義されている。

呼び出されると、gein変数とfreq変数に、外部ボリュームの値を設定する。この 値は 0..+1の範囲を取る。この値を元に、生成する信号の周波数を指定し、振幅を 調整して出力する。

割り込みソースのクリアなどは、この関数の呼び出し側で行うので、関数内で 処理する必要はない。

processdata.cpp の 66 行で定義されています。

参照先 ad7998::getValue(), Hz, osc::COscillator::run(), osc::COscillator::setFreq(), temp, tone, ad7998::Vin1, と ad7998::Vin2.

参照元 ISR().

    00073     {
    00074         shortfract gain, freq;
    00075
    00076         gain = ad7998::getValue(ad7998::Vin1);  // ボリュームの値を読み取る
    00077         freq = ad7998::getValue(ad7998::Vin2);  // ボリュームの値を読み取る
    00078
    00079         tone->setFreq( (freq.v >> 5) * Hz );    // 周波数をボリュームの値にあわせて更新。最大1023Hz
    00080         tone->run( temp, count );               // 信号を生成
    00081         for ( int i=0; i<count; i++ ){        // 引数配列のすべてのデータを処理する。
    00082             leftOut[i] = temp[i] * gain;      // 振幅を設定
    00083             rightOut[i]= temp[i] * gain;
    00084         }
    00085
    00086     }   // processData

void afw::resetCODEC | ( | void |  | ) |

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

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

afw.cpp の 126 行で定義されています。

参照先 CODEC_RESET_PULS_WIDTH.

参照元 init().

    00127     {
    00128         *pPORTFIO_CLEAR = PF12;             // リセット・ピンをアサートする。
    00129
    00130         for( int i = 0; i< CODEC_RESET_PULS_WIDTH;i++)          // アサート状態を一定時間保持
    00131             asm volatile( "nop;" );
    00132
    00133         *pPORTFIO_SET = PF12;               // リセット・ピンをデアサートする。
    00134
    00135
    00136     }

void afw::start | ( | void |  | ) |

SPORTとDMAのイネーブル

設定が終わったSPORTとDMAの両方をイネーブルし、オーディオ処理を開始する。 必ず afw::init()の後に呼ぶ。

afw.cpp の 232 行で定義されています。

参照元 main().

    00233     {
    00234                 // DMA開始
    00235         *pDMA4_CONFIG   |= DMAEN;   // 送信
    00236         *pDMA3_CONFIG   |= DMAEN;   // 受信
    00237
    00238                 // SPORT開始
    00239         *pSPORT0_TCR1   |= TSPEN;
    00240         *pSPORT0_RCR1   |= RSPEN;
    00241     }

## 変数

const int afw::CH_PER_SAMPLE = 2

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

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

afw.cpp の 46 行で定義されています。

参照元 initDMA().

const int afw::CODEC_RESET_PULS_WIDTH = 0x10000

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

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

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

afw.cpp の 64 行で定義されています。

参照元 resetCODEC().

const int afw::Hz = (int)(65536.0*65536.0/48000.0)

周波数指定用定数

osc::COscillatorに対して周波数を指定する際、周波数単位として用いる。 たとえば440Hzの信号を生成したい場合は、440*Hzとする。

processdata.cpp の 17 行で定義されています。

参照元 initProcessData(), と processData().

const int afw::INTR_PER_BUFFER = 3

バッファ数宣言定数

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

afw.cpp の 38 行で定義されています。

参照元 initDMA().

short afw::lchIn[SAMPLE_PER_INTR]

左チャンネル入力バッファ

afw::processDataに引数として渡すための一時バッファ。 afw::rxBufferのデータは L,R,L,Rになっているので、左チャンネルだけ取り出してこのバッファに格納する。

afw.cpp の 249 行で定義されています。

参照元 ISR().

short afw::lchOut[SAMPLE_PER_INTR]

左チャンネル出力バッファ

afw::processDataに引数として渡すための一時バッファ。 afw::txBufferのデータは L,R,L,Rになっているので、 afw::processDataが返してきた値の左チャンネルデータを このバッファから読み出して afw::txBufferに格納する。

afw.cpp の 256 行で定義されています。

参照元 ISR().

const int afw::LEFT_CH = 0

左チャンネル指定定数

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

afw.cpp の 21 行で定義されています。

参照元 ISR().

short afw::rchIn[SAMPLE_PER_INTR]

右チャンネル入力バッファ

afw::processDataに引数として渡すための一時バッファ。 afw::rxBufferのデータは L,R,L,Rになっているので、右チャンネルだけ取り出してこのバッファに格納する。

afw.cpp の 262 行で定義されています。

参照元 ISR().

short afw::rchOut[SAMPLE_PER_INTR]

右チャンネル出力バッファ

afw::processDataに引数として渡すための一時バッファ。 afw::txBufferのデータは L,R,L,Rになっているので、 afw::processDataが返してきた値の右チャンネルデータを このバッファから読み出して afw::txBufferに格納する。

afw.cpp の 269 行で定義されています。

参照元 ISR().

const int afw::RIGHT_CH = 1

右チャンネル指定定数

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

afw.cpp の 28 行で定義されています。

参照元 ISR().

volatile int afw::rxBuffer[INTR_PER_BUFFER][SAMPLE_PER_INTR][CH_PER_SAMPLE]

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.cpp の 102 行で定義されています。

参照元 initDMA(), と ISR().

const int afw::SAMPLE_PER_INTR = 8

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

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

afw.cpp の 54 行で定義されています。

参照元 init(), initDMA(), と ISR().

const int afw::SPORT0_SLEN_32 = 31

SPORT0のワード長

SPORT0設定時に使うワード長である。EZ-KIT BF537に搭載されているコーデックは 32bit長のI2S回線を使うので、ワード長が32になるよう指定する。 32bit長にする場合は、31と設定することに注意。

afw.cpp の 72 行で定義されています。

参照元 initSPORT().

shortfract* afw::temp

一時データ用バッファ

データを一時的に格納するために使う。

processdata.cpp の 23 行で定義されています。

参照元 ad7998::getValue(), initProcessData(), と processData().

osc::COscillator* afw::tone

トーン・ジェネレーター変数

発振器型のオブジェクトを確保して、トーンジェネレータとする。

processdata.cpp の 28 行で定義されています。

参照元 initProcessData(), と processData().

volatile int afw::txBuffer[INTR_PER_BUFFER][SAMPLE_PER_INTR][CH_PER_SAMPLE]

SPORT0 DMA 送信バッファ

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

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

最上位の次元は、このバッファが割込み何回分のデータを 格納するかを表す。

afw.cpp の 90 行で定義されています。

参照元 initDMA(), と ISR().