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         // 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     }
00200 
00201 
00202     /** SPORTとDMAのイネーブル
00203        * 
00204        * 設定が終わったSPORTとDMAの両方をイネーブルする
00205        */
00206     void startAudio(void)
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     }
00216 
00217     /** afwの初期化
00218        * 
00219        * オーディオ・フレームワークの初期化。初期化関数はこれひとつよべば、残りの関数を
00220        * まとめて呼んでくれる。ただし、 afw::startAudio は呼ばないので、プログラマが明示的に
00221        * 呼ばなければならない。
00222        */
00223     void init(void)
00224     {
00225         Init1836();
00226         Init_Sport0();
00227         Init_DMA();
00228         Init_Sport_Interrupts();
00229         
00230         initProcessData();
00231     }
00232     
00233     /** SPORT0受信DMA割り込みハンドラ
00234      * @param signal ハンドラが呼ばれた割り込み順位が与えられる。値は SIGIVG7 〜 SIGIVG15。
00235      *
00236      * rxISRはSPORT0の受信DMAから割り込みがかかるたびに呼び出され、割り込みのクリアと
00237      * トリプル・バッファの管理を行う。トリプルバッファの管理は、DMA1_CURR_Y_COUNTの値を
00238      * もとに行う。
00239      *
00240      * DMA1_CURR_Y_COUNTは、転送の最初に当たってDMA1_Y_COUNTの値に設定され、
00241      * ラインの転送が終わるごとにデクリメントされる。しかし、最後のラインの
00242      * 転送後は、デクリメントされずに1のままに留まる。その結果、各ラインの転送終了
00243      * では、割込み発生ごとに以下のようにDMA1_CURR_Y_COUNTの値が変化する
00244      * - 最初のラインの転送終了時。DMA1_CURR_Y_COUNT == 2。プロセッサが扱ってよいバッファの添え字は 0
00245      * - 2番目のラインの転送終了時。DMA1_CURR_Y_COUNT == 1。プロセッサが扱ってよいバッファの添え字は 1
00246      * - 3番目のラインの転送終了時。DMA1_CURR_Y_COUNT == 1。プロセッサが扱ってよいバッファの添え字は 2
00247      *
00248      * このことから、ソフトウェアとの同期に使ってよいのはDMAx_CURR_Y_COUNTが2の場合
00249      * のみであり、あとは決めうちでバッファの添え字をインクリメントしなければならない事がわかる。
00250      * プログラム中では、この添え字としてbufferIdxをあてている。
00251      * 
00252      * トリプルバッファの管理が終わったら、受信DMAバッファからデータを取り出し、並べ
00253      * なおしてから afw::processData を呼ぶ。
00254      */
00255         
00256 
00257     void rxISR( int signal )
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     }
00286 
00287 
00288     /** コーデック初期化ストリング
00289     *
00290     * SPI経由でAD1836Aに送る初期化データ群
00291     * 
00292     */
00293 
00294     volatile short sCodec1836TxRegs[CODEC_1836_REGS_LENGTH] =
00295     {                                   
00296                         DAC_CONTROL_1   | 0x000,
00297                         DAC_CONTROL_2   | 0x000,
00298                         DAC_VOLUME_0    | 0x3ff,
00299                         DAC_VOLUME_1    | 0x3ff,
00300                         DAC_VOLUME_2    | 0x3ff,
00301                         DAC_VOLUME_3    | 0x3ff,
00302                         DAC_VOLUME_4    | 0x3ff,
00303                         DAC_VOLUME_5    | 0x3ff,
00304                         ADC_CONTROL_1   | 0x000,
00305                         ADC_CONTROL_2   | 0x180,
00306                         ADC_CONTROL_3   | 0x000
00307                     
00308     };
00309 /** オーディオ送信用バッファ
00310    * 
00311    * 送信DMAがアクセスし、SPORT TXチャンネルにデータを送り込むためのバッファ
00312    *
00313    * 最下位の次元はAD1836Aの8チャンネル用に8つの要素を格納する。下から2番目の次元は、
00314    * 割込み1回ごとに送信されるサンプル数を指定する。1回の割り込みの間にDMA転送
00315    * されるデータの量は、 afw::SAMPLES_PER_INTR * 8 で決まる。
00316    *
00317    * 最上位の次元は、この配列がトリプルバッファ用であることを示す。
00318    */
00319     volatile int iTxBuffer1[INTR_PER_BUFFER][SAMPLES_PER_INTR][SLOT_PER_SAMPLE];    // Need place for each sample
00320     
00321 /** オーディオ受信用バッファ
00322    * 
00323    * 受信DMAがアクセスし、SPORT RXチャンネルからのデータを書き込むためのバッファ
00324    *
00325    * 最下位の次元はAD1836Aの8チャンネル用に8つの要素を格納する。下から2番目の次元は、
00326    * 割込み1回ごとに受信されるサンプル数を指定する。1回の割り込みの間にDMA転送
00327    * されるデータの量は、 afw::SAMPLES_PER_INTR * 8 で決まる。
00328    *
00329    * 最上位の次元は、この配列がトリプルバッファ用であることを示す。
00330    */
00331     volatile int iRxBuffer1[INTR_PER_BUFFER][SAMPLES_PER_INTR][SLOT_PER_SAMPLE];    // 
00332 
00333 
00334 
00335 }   // namespace afw

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