afw.cpp

説明を見る。
00001 #include "afw.h"
00002 #include <signal.h>
00003 /** \file afw.cpp
00004  *  \brief オーディオ・フレームワーク・ファイル
00005  *  \author アナログ・デバイセズ株式会社
00006  *  \version 1.0
00007  *  \date    2006.Sep.8
00008  *
00009  * このファイルはVisualDSP++ 4.5のサンプル・アプリケーション、TalkTrhoughから
00010  * 複製して変更したものである。EZ-KIT BF533のオーディオ・コーディックを利用する
00011  * ための関数群からなる。。
00012  */
00013 namespace afw{
00014     /** AD1836Aの初期化
00015     *
00016     * コーデックを初期化するために、リセットパルスを与え、SPI経由で初期化ストリングを送る。
00017     * 
00018     */
00019     void Init1836(void)
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     }
00075 
00076 
00077     /** SPORT0の初期化
00078        * 
00079        * オーディオコーデックに接続されているSPORT0を初期化する。シリアル回線の
00080        * フォーマットはマルチチャンネルで、クロックおよびフレーム信号は外部生成。この関数を読んだ段階
00081        * では、ポートはディセーブルのままにしておく。
00082        *
00083        * 
00084        * 詳細はADSP-BF533 Hardware Referenceの "Stereo Serial Operation" を参照のこと。
00085        * afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
00086        *
00087        * 注意:EZ-KIT Lite BF537 Rev 1.0のユーザーはSPORTのクロックおよびフレーム同期
00088        * 信号を自分で生成する設定に変更しなければならない。
00089        */
00090     void Init_Sport0(void)
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     }
00112 
00113 
00114     /** SPORT DMAの初期化
00115        * 
00116        * SPORT0に接続されているDMAを設定する。DMA1が受信、DMA2が送信である。
00117        * オーディオ信号は16ビット以上の長さがあるのでワードサイズは32bit, 
00118        * 連続送受信のためにオートバッファ、モードを使う。また、トリプル・バッファを
00119        * 実装するために、DMA転送は2次元で行い、3ライン分のバッファを確保して各ラインの
00120        * 転送を終えるたびに割り込みを発生させる。
00121        * afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
00122        */
00123     void Init_DMA(void)
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     }
00179 
00180     /** 割り込みのイネーブル
00181        * 
00182        * SPORT0 受信割込みを有効化する。SPORT0 受信割り込みはIVG9で処理したいので、その割り当ても設定する。
00183        * afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
00184        */
00185     void Init_Sport_Interrupts(void)
00186     {
00187         // enable Sport0 RX interrupt
00188         *pSIC_IMASK = 0x00000200;
00189         ssync();
00190     }
00191 
00192 
00193     void start(void)
00194     {
00195         // enable DMAs
00196         *pDMA2_CONFIG |= DMAEN;
00197         *pDMA1_CONFIG |= DMAEN;
00198     
00199         // enable Sport0 TX and RX
00200         *pSPORT0_TCR1 |= TSPEN;
00201         *pSPORT0_RCR1 |= RSPEN;
00202     }
00203 
00204     void init(void)
00205     {
00206         Init1836();
00207         Init_Sport0();
00208         Init_DMA();
00209         Init_Sport_Interrupts();
00210         
00211         initProcessData( SAMPLES_PER_INTR );
00212     }
00213     
00214     /** SPORT0受信DMA割り込みハンドラ
00215      *
00216      * ISRはSPORT0の受信DMAから割り込みがかかるたびに、 \ref cecの割り込みハンドラから呼び出され、割り込みのクリアと
00217      * トリプル・バッファの管理を行う。トリプルバッファの管理は、DMA1_CURR_Y_COUNTの値を
00218      * もとに行う。
00219      *
00220      * DMA1_CURR_Y_COUNTは、転送の最初に当たってDMA1_Y_COUNTの値に設定され、
00221      * ラインの転送が終わるごとにデクリメントされる。しかし、最後のラインの
00222      * 転送後は、デクリメントされずに1のままに留まる。その結果、各ラインの転送終了
00223      * では、割込み発生ごとに以下のようにDMA1_CURR_Y_COUNTの値が変化する
00224      * - 最初のラインの転送終了時。DMA1_CURR_Y_COUNT == 2。プロセッサが扱ってよいバッファの添え字は 0
00225      * - 2番目のラインの転送終了時。DMA1_CURR_Y_COUNT == 1。プロセッサが扱ってよいバッファの添え字は 1
00226      * - 3番目のラインの転送終了時。DMA1_CURR_Y_COUNT == 1。プロセッサが扱ってよいバッファの添え字は 2
00227      *
00228      * このことから、ソフトウェアとの同期に使ってよいのはDMAx_CURR_Y_COUNTが2の場合
00229      * のみであり、あとは決めうちでバッファの添え字をインクリメントしなければならない事がわかる。
00230      * プログラム中では、この添え字としてbufferIdxをあてている。
00231      * 
00232      * トリプルバッファの管理が終わったら、受信DMAバッファからデータを取り出し、並べ
00233      * なおしてから afw::processData を呼ぶ。
00234      * 
00235      * なお、SPORT0 RX割り込みの処理を行った場合には true 、行わなかったときには falseを返す
00236      */
00237         
00238 
00239     bool ISR( void )
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     }
00273 
00274 
00275     /** コーデック初期化ストリング
00276     *
00277     * SPI経由でAD1836Aに送る初期化データ群
00278     * 
00279     */
00280 
00281     volatile short sCodec1836TxRegs[CODEC_1836_REGS_LENGTH] =
00282     {                                   
00283                         DAC_CONTROL_1   | 0x000,
00284                         DAC_CONTROL_2   | 0x000,
00285                         DAC_VOLUME_0    | 0x3ff,
00286                         DAC_VOLUME_1    | 0x3ff,
00287                         DAC_VOLUME_2    | 0x3ff,
00288                         DAC_VOLUME_3    | 0x3ff,
00289                         DAC_VOLUME_4    | 0x3ff,
00290                         DAC_VOLUME_5    | 0x3ff,
00291                         ADC_CONTROL_1   | 0x000,
00292                         ADC_CONTROL_2   | 0x180,
00293                         ADC_CONTROL_3   | 0x000
00294                     
00295     };
00296 /** オーディオ送信用バッファ
00297    * 
00298    * 送信DMAがアクセスし、SPORT TXチャンネルにデータを送り込むためのバッファ
00299    *
00300    * 最下位の次元はAD1836Aの8チャンネル用に8つの要素を格納する。下から2番目の次元は、
00301    * 割込み1回ごとに送信されるサンプル数を指定する。1回の割り込みの間にDMA転送
00302    * されるデータの量は、 afw::SAMPLES_PER_INTR * 8 で決まる。
00303    *
00304    * 最上位の次元は、この配列がトリプルバッファ用であることを示す。
00305    */
00306     volatile int iTxBuffer1[INTR_PER_BUFFER][SAMPLES_PER_INTR][SLOT_PER_SAMPLE];    // Need place for each sample
00307     
00308 /** オーディオ受信用バッファ
00309    * 
00310    * 受信DMAがアクセスし、SPORT RXチャンネルからのデータを書き込むためのバッファ
00311    *
00312    * 最下位の次元はAD1836Aの8チャンネル用に8つの要素を格納する。下から2番目の次元は、
00313    * 割込み1回ごとに受信されるサンプル数を指定する。1回の割り込みの間にDMA転送
00314    * されるデータの量は、 afw::SAMPLES_PER_INTR * 8 で決まる。
00315    *
00316    * 最上位の次元は、この配列がトリプルバッファ用であることを示す。
00317    */
00318     volatile int iRxBuffer1[INTR_PER_BUFFER][SAMPLES_PER_INTR][SLOT_PER_SAMPLE];    // 
00319 
00320 
00321 
00322 }   // namespace afw

AudioFrameWorkに対してMon Apr 9 17:15:14 2007に生成されました。  doxygen 1.5.1-p1