ネームスペース afw


説明

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

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 startAudio (void)
 SPORTとDMAのイネーブル
void init (void)
 afwの初期化
void rxISR (int signal)
 SPORT0受信DMA割り込みハンドラ
void initProcessData (void)
 コールバック関数の処理化
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::Init1836 ( void   ) 

AD1836Aの初期化

コーデックを初期化するために、リセットパルスを与え、SPI経由で初期化ストリングを送る。

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

参照先 CODEC_1836_REGS_LENGTHpFlashA_PortA_DatasCodec1836TxRegsTIMOD_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_Sport0 ( void   ) 

SPORT0の初期化

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

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

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

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

参照先 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_DMA ( void   ) 

SPORT DMAの初期化

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

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

参照先 FLOW_AutobufferINTERNAL_ADC_L0INTERNAL_ADC_L1INTERNAL_ADC_R0INTERNAL_ADC_R1INTERNAL_DAC_L0INTERNAL_DAC_L1INTERNAL_DAC_L2INTERNAL_DAC_R0INTERNAL_DAC_R1INTERNAL_DAC_R2INTR_PER_BUFFERiRxBuffer1iTxBuffer1SAMPLES_PER_INTRSLOT_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_Sport_Interrupts ( void   ) 

割り込みのイネーブル

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

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

参照先 rxISR().

参照元 init().

00186     {
00187         // Set Sport0 RX (DMA1) interrupt priority to 2 = IVG9 
00188         *pSIC_IAR0 = 0xffffffff;
00189         *pSIC_IAR1 = 0xffffff2f;
00190         *pSIC_IAR2 = 0xffffffff;
00191 
00192         // assign ISRs to interrupt vectors
00193         // Sport0 RX ISR -> IVG 9
00194         interrupt(SIGIVG9, rxISR);      
00195 
00196         // enable Sport0 RX interrupt
00197         *pSIC_IMASK = 0x00000200;
00198         ssync();
00199     }

void afw::startAudio ( void   ) 

SPORTとDMAのイネーブル

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

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

参照元 main().

00207     {
00208         // enable DMAs
00209         *pDMA2_CONFIG |= DMAEN;
00210         *pDMA1_CONFIG |= DMAEN;
00211     
00212         // enable Sport0 TX and RX
00213         *pSPORT0_TCR1 |= TSPEN;
00214         *pSPORT0_RCR1 |= RSPEN;
00215     }

void afw::init ( void   ) 

afwの初期化

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

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

参照先 Init1836()Init_DMA()Init_Sport0()Init_Sport_Interrupts()initProcessData().

参照元 main().

00224     {
00225         Init1836();
00226         Init_Sport0();
00227         Init_DMA();
00228         Init_Sport_Interrupts();
00229         
00230         initProcessData();
00231     }

void afw::rxISR ( int  signal  ) 

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

引数:
signal ハンドラが呼ばれた割り込み順位が与えられる。値は SIGIVG7 〜 SIGIVG15。
rxISRはSPORT0の受信DMAから割り込みがかかるたびに呼び出され、割り込みのクリアと トリプル・バッファの管理を行う。トリプルバッファの管理は、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 を呼ぶ。

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

参照先 INTERNAL_ADC_L0INTERNAL_ADC_R0INTERNAL_DAC_L0INTERNAL_DAC_R0iRxBuffer1iTxBuffer1processData()SAMPLES_PER_INTR.

参照元 Init_Sport_Interrupts().

00258     {
00259         static int field = 2;
00260         short leftIn[SAMPLES_PER_INTR], rightIn[SAMPLES_PER_INTR];
00261         short leftOut[SAMPLES_PER_INTR], rightOut[SAMPLES_PER_INTR];
00262                 
00263         // 割り込みのクリア
00264         *pDMA1_IRQ_STATUS = 0x0001;
00265     
00266         
00267         if (  2 == *pDMA2_CURR_Y_COUNT )
00268             field = 0;  // トリプルバッファの最初でfield変数を同期する
00269         else
00270             field ++;   // それ以外では決めうちで更新
00271     
00272         for ( int i=0; i<SAMPLES_PER_INTR; i++ ){   // すべてのサンプルについて
00273             // DMAバッファのデータを並べなおす
00274             leftIn[i] = iRxBuffer1[field][i][INTERNAL_ADC_L0] >> 16;
00275             rightIn[i] = iRxBuffer1[field][i][INTERNAL_ADC_R0] >> 16;
00276         }
00277             // ユーザー信号処理ルーチンの呼び出し
00278         processData( leftIn, rightIn, leftOut, rightOut, SAMPLES_PER_INTR );                
00279     
00280         for ( int i=0; i<SAMPLES_PER_INTR; i++ ){   // すべてのサンプルについて
00281             // DMAバッファにデータを並べなおす
00282             iTxBuffer1[field][i][INTERNAL_DAC_L0] = leftOut[i] << 16;
00283             iTxBuffer1[field][i][INTERNAL_DAC_R0] = rightOut[i] << 16;
00284         }
00285     }

void afw::initProcessData ( void   ) 

コールバック関数の処理化

コールバック関数を呼ぶ前に初期化の必要がある場合は、この関数内部で行う。

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

参照元 init().

00030     {
00031         // 必要に応じてここで processData用の初期化を行う
00032     }

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

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

引数:
leftIn 左チャンネルの入力データバッファ
rightIn 右チャンネルの入力データバッファ
leftOut 左チャンネルの出力データバッファ
rightOut 右チャンネルの出力データバッファ
count 各バッファに格納されているオーディオデータの数
この関数はDMAが受信バッファをいっぱいにするたびに割り込み経由で呼ばれる。 引数として渡されるのは受信データを含む入力バッファのほか、送信データを 格納するために使う出力バッファとデータ個数である。 ユーザーは関数内部で入力バッファのデータを加工して、出力バッファに送信すべき データをおく。

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

for文は常に必要なので、改造する場合はfor文の内側だけを書き換える。引数 である配列の各要素は、オーディオのサンプルデータが順番に格納されたもの である。したがって、これらを順番に処理することで、オーディオ処理を実装 できる。

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

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

参照元 rxISR().

00066     {
00067     
00068         for ( int i=0; i<count; i++ ) {
00069             // ここで信号処理を行う
00070         }
00071     }


変数

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に送る初期化データ群

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

参照元 Init1836().

volatile int afw::iTxBuffer1

オーディオ送信用バッファ

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

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

最上位の次元は、この配列がトリプルバッファ用であることを示す。

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

参照元 Init_DMA()rxISR().

volatile int afw::iRxBuffer1

オーディオ受信用バッファ

受信DMAがアクセスし、SPORT RXチャンネルからのデータを書き込むためのバッファ

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

最上位の次元は、この配列がトリプルバッファ用であることを示す。

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

参照元 Init_DMA()rxISR().

const int afw::SLOT_PER_SAMPLE = 8

サンプルあたりのスロット数。

AD1836Aのマルチチャンネル・モードでは8。ユーザーが変えてはならない。

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

参照元 Init_DMA().

const int afw::SAMPLES_PER_INTR = 8

割り込み1回あたりに転送する、サンプル数。

ユーザーが変えてよい。

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

参照元 Init_DMA()rxISR().

const int afw::INTR_PER_BUFFER = 3

過去何回分の割り込みのデータを用意するか。

トリプルバッファなので3

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

参照元 Init_DMA().


AudioFrameWorkに対してTue Oct 24 11:29:51 2006に生成されました。  doxygen 1.4.7