ADSP-BF537 EZ-KIT Lite上で動作するオーディオフレームワーク関連の関数および変数を含む名前空間。 プログラマは以下の関数を呼んでオーディオ処理を開始する。
関数 | |
void | Init1836 (void) |
AD1836Aの初期化 | |
void | Init_Sport0 (void) |
SPORT0の初期化 | |
void | Init_DMA (void) |
SPORT DMAの初期化 | |
void | Init_Sport_Interrupts (void) |
割り込みのイネーブル | |
void | start (void) |
オーディオ処理の開始 | |
void | init (void) |
afwの初期化 | |
bool | ISR (void) |
SPORT0受信DMA割り込みハンドラ | |
void | initProcessData (int count) |
コールバック関数の処理化 | |
void | processData (const short leftIn[],const short rightIn[],short leftOut[],short rightOut[],int count) |
オーディオ・コールバック関数 | |
short | osc () |
変数 | |
volatile short | sCodec1836TxRegs [CODEC_1836_REGS_LENGTH] |
コーデック初期化ストリング | |
volatile int | iTxBuffer1 [INTR_PER_BUFFER][SAMPLES_PER_INTR][SLOT_PER_SAMPLE] |
オーディオ送信用バッファ | |
volatile int | iRxBuffer1 [INTR_PER_BUFFER][SAMPLES_PER_INTR][SLOT_PER_SAMPLE] |
オーディオ受信用バッファ | |
const int | SLOT_PER_SAMPLE = 8 |
サンプルあたりのスロット数。 | |
const int | SAMPLES_PER_INTR = 8 |
割り込み1回あたりに転送する、サンプル数。 | |
const int | INTR_PER_BUFFER = 3 |
過去何回分の割り込みのデータを用意するか。 | |
const int | DAC_CONTROL_1 = 0x0000 |
const int | DAC_CONTROL_2 = 0x1000 |
const int | DAC_VOLUME_0 = 0x2000 |
const int | DAC_VOLUME_1 = 0x3000 |
const int | DAC_VOLUME_2 = 0x4000 |
const int | DAC_VOLUME_3 = 0x5000 |
const int | DAC_VOLUME_4 = 0x6000 |
const int | DAC_VOLUME_5 = 0x7000 |
const int | ADC_0_PEAK_LEVEL = 0x8000 |
const int | ADC_1_PEAK_LEVEL = 0x9000 |
const int | ADC_2_PEAK_LEVEL = 0xA000 |
const int | ADC_3_PEAK_LEVEL = 0xB000 |
const int | ADC_CONTROL_1 = 0xC000 |
const int | ADC_CONTROL_2 = 0xD000 |
const int | ADC_CONTROL_3 = 0xE000 |
const int | INTERNAL_ADC_L0 = 0 |
const int | INTERNAL_ADC_L1 = 1 |
const int | INTERNAL_ADC_R0 = 4 |
const int | INTERNAL_ADC_R1 = 5 |
const int | INTERNAL_DAC_L0 = 0 |
const int | INTERNAL_DAC_L1 = 1 |
const int | INTERNAL_DAC_L2 = 2 |
const int | INTERNAL_DAC_R0 = 4 |
const int | INTERNAL_DAC_R1 = 5 |
const int | INTERNAL_DAC_R2 = 6 |
const int | CODEC_1836_REGS_LENGTH = 11 |
size of array iCodec1836TxRegs and iCodec1836RxRegs | |
const int | TIMOD_DMA_TX = 0x0003 |
SPI transfer mode | |
const int | SLEN_32 = 0x001f |
SPORT0 word length | |
const int | FLOW_Autobuffer = 0x1000 |
DMA flow mode |
void afw::init | ( | void | ) |
afwの初期化
オーディオ・フレームワークの初期化。初期化関数はこれひとつよべば、残りの関数を まとめて呼んでくれる。ただし、 afw::start は呼ばないので、プログラマが明示的に 呼ばなければならない。
参照先 Init1836()・Init_DMA()・Init_Sport0()・Init_Sport_Interrupts()・initProcessData()・SAMPLES_PER_INTR.
参照元 main().
00205 { 00206 Init1836(); 00207 Init_Sport0(); 00208 Init_DMA(); 00209 Init_Sport_Interrupts(); 00210 00211 initProcessData( SAMPLES_PER_INTR ); 00212 }
void afw::Init1836 | ( | void | ) |
AD1836Aの初期化
コーデックを初期化するために、リセットパルスを与え、SPI経由で初期化ストリングを送る。
参照先 CODEC_1836_REGS_LENGTH・pFlashA_PortA_Data・sCodec1836TxRegs・TIMOD_DMA_TX.
参照元 init().
00020 { 00021 int i; 00022 int j; 00023 static unsigned char ucActive_LED = 0x01; 00024 00025 // write to Port A to reset AD1836 00026 *pFlashA_PortA_Data &= ~ucActive_LED; 00027 ssync(); 00028 00029 // keep reset low 00030 for (i=0; i<1000000; i++) 00031 asm volatile("nop;"); 00032 00033 // write to Port A to enable AD1836 00034 *pFlashA_PortA_Data |= ucActive_LED; 00035 ssync(); 00036 00037 // wait to recover from reset 00038 for (i=0; i<1000000; i++) 00039 asm volatile("nop;"); 00040 00041 // Enable PF4 00042 *pSPI_FLG = FLS4; 00043 // Set baud rate SCK = HCLK/(2*SPIBAUD) SCK = 2MHz 00044 *pSPI_BAUD = 16; 00045 // configure spi port 00046 // SPI DMA write, 16-bit data, MSB first, SPI Master 00047 *pSPI_CTL = TIMOD_DMA_TX | SIZE | MSTR; 00048 00049 // Set up DMA5 to transmit 00050 // Map DMA5 to SPI 00051 *pDMA5_PERIPHERAL_MAP = 0x5000; 00052 00053 // Configure DMA5 00054 // 16-bit transfers 00055 *pDMA5_CONFIG = WDSIZE_16; 00056 // Start address of data buffer 00057 *pDMA5_START_ADDR = (void *)sCodec1836TxRegs; 00058 // DMA inner loop count 00059 *pDMA5_X_COUNT = CODEC_1836_REGS_LENGTH; 00060 // Inner loop address increment 00061 *pDMA5_X_MODIFY = 2; 00062 00063 // enable DMAs 00064 *pDMA5_CONFIG |= DMAEN; 00065 // enable spi 00066 *pSPI_CTL |= SPE; 00067 00068 // SPI DMAの終了待ち。ここのタイミングによっては音が出ないことがある。 00069 for (j=0; j<1000000; j++) 00070 asm volatile ("nop;"); 00071 00072 // disable spi 00073 *pSPI_CTL = 0x0000; 00074 }
void afw::Init_DMA | ( | void | ) |
SPORT DMAの初期化
SPORT0に接続されているDMAを設定する。DMA1が受信、DMA2が送信である。 オーディオ信号は16ビット以上の長さがあるのでワードサイズは32bit, 連続送受信のためにオートバッファ、モードを使う。また、トリプル・バッファを 実装するために、DMA転送は2次元で行い、3ライン分のバッファを確保して各ラインの 転送を終えるたびに割り込みを発生させる。 afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
参照先 FLOW_Autobuffer・INTERNAL_ADC_L0・INTERNAL_ADC_L1・INTERNAL_ADC_R0・INTERNAL_ADC_R1・INTERNAL_DAC_L0・INTERNAL_DAC_L1・INTERNAL_DAC_L2・INTERNAL_DAC_R0・INTERNAL_DAC_R1・INTERNAL_DAC_R2・INTR_PER_BUFFER・iRxBuffer1・iTxBuffer1・SAMPLES_PER_INTR・SLOT_PER_SAMPLE.
参照元 init().
00124 { 00125 int i, field; 00126 00127 // Set up DMA1 to receive 00128 // Map DMA1 to Sport0 RX 00129 *pDMA1_PERIPHERAL_MAP = 0x1000; 00130 00131 // Configure DMA1 00132 // 32-bit transfers, Interrupt on completion, Autobuffer mode 00133 *pDMA1_CONFIG = WNR | WDSIZE_32 | DI_EN | DI_SEL | FLOW_Autobuffer | DMA2D ; 00134 // Start address of data buffer 00135 *pDMA1_START_ADDR = (void *)iRxBuffer1; 00136 // DMA inner loop count 00137 *pDMA1_X_COUNT = SLOT_PER_SAMPLE * SAMPLES_PER_INTR; 00138 // Inner loop address increment 00139 *pDMA1_X_MODIFY = sizeof(int); 00140 // DMA outer loop count, triple buffer 00141 *pDMA1_Y_COUNT = INTR_PER_BUFFER; 00142 // Outer loop address increment 00143 *pDMA1_Y_MODIFY = sizeof(int); 00144 00145 // Set up DMA2 to transmit 00146 // Map DMA2 to Sport0 TX 00147 *pDMA2_PERIPHERAL_MAP = 0x2000; 00148 00149 // Configure DMA2 00150 // 32-bit transfers, Autobuffer mode 00151 *pDMA2_CONFIG = WDSIZE_32 | FLOW_Autobuffer | DMA2D; 00152 // Start address of data buffer 00153 *pDMA2_START_ADDR = (void *)iTxBuffer1; 00154 // DMA inner loop count 00155 *pDMA2_X_COUNT = SLOT_PER_SAMPLE * SAMPLES_PER_INTR; 00156 // Inner loop address increment 00157 *pDMA2_X_MODIFY = sizeof(int); 00158 // DMA outer loop count, triple buffere 00159 *pDMA2_Y_COUNT = INTR_PER_BUFFER; 00160 // Outer loop address increment 00161 *pDMA2_Y_MODIFY = sizeof(int); 00162 00163 for ( i=0; i<SAMPLES_PER_INTR; i++ ){ 00164 for ( field=0; field<INTR_PER_BUFFER; field ++ ){ 00165 // Clean up buffer for transfer 00166 iRxBuffer1[field][i][INTERNAL_ADC_L0] = 0; 00167 iRxBuffer1[field][i][INTERNAL_ADC_R0] = 0; 00168 iRxBuffer1[field][i][INTERNAL_ADC_L1] = 0; 00169 iRxBuffer1[field][i][INTERNAL_ADC_R1] = 0; 00170 iTxBuffer1[field][i][INTERNAL_DAC_L0] = 0; 00171 iTxBuffer1[field][i][INTERNAL_DAC_R0] = 0; 00172 iTxBuffer1[field][i][INTERNAL_DAC_L1] = 0; 00173 iTxBuffer1[field][i][INTERNAL_DAC_R1] = 0; 00174 iTxBuffer1[field][i][INTERNAL_DAC_L2] = 0; 00175 iTxBuffer1[field][i][INTERNAL_DAC_R2] = 0; 00176 } 00177 } 00178 }
void afw::Init_Sport0 | ( | void | ) |
SPORT0の初期化
オーディオコーデックに接続されているSPORT0を初期化する。シリアル回線の フォーマットはマルチチャンネルで、クロックおよびフレーム信号は外部生成。この関数を読んだ段階 では、ポートはディセーブルのままにしておく。
詳細はADSP-BF533 Hardware Referenceの "Stereo Serial Operation" を参照のこと。 afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
注意:EZ-KIT Lite BF537 Rev 1.0のユーザーはSPORTのクロックおよびフレーム同期 信号を自分で生成する設定に変更しなければならない。
参照先 SLEN_32.
参照元 init().
00091 { 00092 // Sport0 receive configuration 00093 // External CLK, External Frame sync, MSB first 00094 // 32-bit data 00095 *pSPORT0_RCR1 = RFSR; 00096 *pSPORT0_RCR2 = SLEN_32; 00097 00098 // Sport0 transmit configuration 00099 // External CLK, External Frame sync, MSB first 00100 // 24-bit data 00101 *pSPORT0_TCR1 = TFSR; 00102 *pSPORT0_TCR2 = SLEN_32; 00103 00104 // Enable MCM 8 transmit & receive channels 00105 *pSPORT0_MTCS0 = 0x000000FF; 00106 *pSPORT0_MRCS0 = 0x000000FF; 00107 00108 // Set MCM configuration register and enable MCM mode 00109 *pSPORT0_MCMC1 = 0x0000; 00110 *pSPORT0_MCMC2 = 0x101c; 00111 }
void afw::Init_Sport_Interrupts | ( | void | ) |
割り込みのイネーブル
SPORT0 受信割込みを有効化する。SPORT0 受信割り込みはIVG9で処理したいので、その割り当ても設定する。 afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
参照元 init().
void afw::initProcessData | ( | int | count | ) |
コールバック関数の処理化
コールバック関数を呼ぶ前に初期化の必要がある場合は、この関数内部で行う。
count | afw::processData() が呼び出されるとき、各バッファに格納されているオーディオデータの数 |
processdata.cpp の 30 行で定義されています。
参照元 init().
bool afw::ISR | ( | void | ) |
SPORT0受信DMA割り込みハンドラ
ISRはSPORT0の受信DMAから割り込みがかかるたびに、 cecの割り込みハンドラから呼び出され、割り込みのクリアと トリプル・バッファの管理を行う。トリプルバッファの管理は、DMA1_CURR_Y_COUNTの値を もとに行う。
DMA1_CURR_Y_COUNTは、転送の最初に当たってDMA1_Y_COUNTの値に設定され、 ラインの転送が終わるごとにデクリメントされる。しかし、最後のラインの 転送後は、デクリメントされずに1のままに留まる。その結果、各ラインの転送終了 では、割込み発生ごとに以下のようにDMA1_CURR_Y_COUNTの値が変化する
このことから、ソフトウェアとの同期に使ってよいのはDMAx_CURR_Y_COUNTが2の場合 のみであり、あとは決めうちでバッファの添え字をインクリメントしなければならない事がわかる。 プログラム中では、この添え字としてbufferIdxをあてている。
トリプルバッファの管理が終わったら、受信DMAバッファからデータを取り出し、並べ なおしてから afw::processData を呼ぶ。
なお、SPORT0 RX割り込みの処理を行った場合には true 、行わなかったときには falseを返す
参照先 INTERNAL_ADC_L0・INTERNAL_ADC_R0・INTERNAL_DAC_L0・INTERNAL_DAC_R0・iRxBuffer1・iTxBuffer1・processData()・SAMPLES_PER_INTR.
参照元 cec::ivg9().
00240 { 00241 static int field = 2; 00242 short leftIn[SAMPLES_PER_INTR], rightIn[SAMPLES_PER_INTR]; 00243 short leftOut[SAMPLES_PER_INTR], rightOut[SAMPLES_PER_INTR]; 00244 00245 if ( *pSIC_ISR & DMA1_IRQ ){ // SPORT0 RX (DMA1) の割り込みか 00246 // 割り込みのクリア 00247 *pDMA1_IRQ_STATUS = 0x0001; 00248 00249 00250 if ( 2 == *pDMA2_CURR_Y_COUNT ) 00251 field = 0; // トリプルバッファの最初でfield変数を同期する 00252 else 00253 field ++; // それ以外では決めうちで更新 00254 00255 for ( int i=0; i<SAMPLES_PER_INTR; i++ ){ // すべてのサンプルについて 00256 // DMAバッファのデータを並べなおす 00257 leftIn[i] = iRxBuffer1[field][i][INTERNAL_ADC_L0] >> 16; 00258 rightIn[i] = iRxBuffer1[field][i][INTERNAL_ADC_R0] >> 16; 00259 } 00260 // ユーザー信号処理ルーチンの呼び出し 00261 processData( leftIn, rightIn, leftOut, rightOut, SAMPLES_PER_INTR ); 00262 00263 for ( int i=0; i<SAMPLES_PER_INTR; i++ ){ // すべてのサンプルについて 00264 // DMAバッファにデータを並べなおす 00265 iTxBuffer1[field][i][INTERNAL_DAC_L0] = leftOut[i] << 16; 00266 iTxBuffer1[field][i][INTERNAL_DAC_R0] = rightOut[i] << 16; 00267 } 00268 return true; 00269 } 00270 else 00271 return false; 00272 }
void afw::processData | ( | const short | leftIn[], | |
const short | rightIn[], | |||
short | leftOut[], | |||
short | rightOut[], | |||
int | count | |||
) |
オーディオ・コールバック関数
leftIn | 左チャンネルの入力データバッファ | |
rightIn | 右チャンネルの入力データバッファ | |
leftOut | 左チャンネルの出力データバッファ | |
rightOut | 右チャンネルの出力データバッファ | |
count | 各バッファに格納されているオーディオデータの数 |
配列はshortfract型である。この16bit固定小数点型はshortと同じ大きさを 持つが、四則は固定小数点領域で定義されている。
for文は常に必要なので、改造する場合はfor文の内側だけを書き換える。引数 である配列の各要素は、オーディオのサンプルデータが順番に格納されたもの である。したがって、これらを順番に処理することで、オーディオ処理を実装 できる。
割り込みソースのクリアなどは、この関数の呼び出し側で行うので、関数内で 処理する必要はない。
processdata.cpp の 60 行で定義されています。
参照元 ISR().
void afw::start | ( | void | ) |
const int afw::INTR_PER_BUFFER = 3 |
volatile int afw::iRxBuffer1 |
オーディオ受信用バッファ
受信DMAがアクセスし、SPORT RXチャンネルからのデータを書き込むためのバッファ
最下位の次元はAD1836Aの8チャンネル用に8つの要素を格納する。下から2番目の次元は、 割込み1回ごとに受信されるサンプル数を指定する。1回の割り込みの間にDMA転送 されるデータの量は、 afw::SAMPLES_PER_INTR * 8 で決まる。
最上位の次元は、この配列がトリプルバッファ用であることを示す。
参照元 Init_DMA()・ISR().
volatile int afw::iTxBuffer1 |
オーディオ送信用バッファ
送信DMAがアクセスし、SPORT TXチャンネルにデータを送り込むためのバッファ
最下位の次元はAD1836Aの8チャンネル用に8つの要素を格納する。下から2番目の次元は、 割込み1回ごとに送信されるサンプル数を指定する。1回の割り込みの間にDMA転送 されるデータの量は、 afw::SAMPLES_PER_INTR * 8 で決まる。
最上位の次元は、この配列がトリプルバッファ用であることを示す。
参照元 Init_DMA()・ISR().
const int afw::SAMPLES_PER_INTR = 8 |
volatile short afw::sCodec1836TxRegs |
初期値:
{ DAC_CONTROL_1 | 0x000, DAC_CONTROL_2 | 0x000, DAC_VOLUME_0 | 0x3ff, DAC_VOLUME_1 | 0x3ff, DAC_VOLUME_2 | 0x3ff, DAC_VOLUME_3 | 0x3ff, DAC_VOLUME_4 | 0x3ff, DAC_VOLUME_5 | 0x3ff, ADC_CONTROL_1 | 0x000, ADC_CONTROL_2 | 0x180, ADC_CONTROL_3 | 0x000 }
SPI経由でAD1836Aに送る初期化データ群
参照元 Init1836().
const int afw::SLOT_PER_SAMPLE = 8 |