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     //--------------------------------------------------------------------------//
00015     // Function:    Init1836()                                                  //
00016     //                                                                          //
00017     // Description: This function sets up the SPI port to configure the AD1836. //
00018     //              The content of the array sCodec1836TxRegs is sent to the    //
00019     //              codec.                                                      //
00020     //--------------------------------------------------------------------------//
00021     void Init1836(void)
00022     {
00023         int i;
00024         int j;
00025         static unsigned char ucActive_LED = 0x01;
00026 
00027         // write to Port A to reset AD1836
00028         *pFlashA_PortA_Data &= ~ucActive_LED;
00029         ssync();
00030     
00031         // keep reset low
00032         for (i=0; i<1000000; i++) 
00033             asm volatile("nop;");
00034         
00035         // write to Port A to enable AD1836
00036         *pFlashA_PortA_Data |= ucActive_LED;
00037         ssync();
00038     
00039         // wait to recover from reset
00040         for (i=0; i<1000000; i++) 
00041             asm volatile("nop;");
00042 
00043         // Enable PF4
00044         *pSPI_FLG = FLS4;
00045         // Set baud rate SCK = HCLK/(2*SPIBAUD) SCK = 2MHz  
00046         *pSPI_BAUD = 16;
00047         // configure spi port
00048         // SPI DMA write, 16-bit data, MSB first, SPI Master
00049         *pSPI_CTL = TIMOD_DMA_TX | SIZE | MSTR;
00050     
00051         // Set up DMA5 to transmit
00052         // Map DMA5 to SPI
00053         *pDMA5_PERIPHERAL_MAP   = 0x5000;
00054     
00055         // Configure DMA5
00056         // 16-bit transfers
00057         *pDMA5_CONFIG = WDSIZE_16;
00058         // Start address of data buffer
00059         *pDMA5_START_ADDR = (void *)sCodec1836TxRegs;
00060         // DMA inner loop count
00061         *pDMA5_X_COUNT = CODEC_1836_REGS_LENGTH;
00062         // Inner loop address increment
00063         *pDMA5_X_MODIFY = 2;
00064     
00065         // enable DMAs
00066         *pDMA5_CONFIG |= DMAEN;
00067         // enable spi
00068         *pSPI_CTL |= SPE;
00069     
00070         // wait until dma transfers for spi are finished 
00071     //  for (j=0; j<1000000; j++) 
00072     //      asm volatile ("nop;");
00073     
00074         // disable spi
00075     //  *pSPI_CTL = 0x0000;
00076     }
00077 
00078 
00079     /** SPORT0の初期化
00080        * 
00081        * オーディオコーデックに接続されているSPORT0を初期化する。シリアル回線の
00082        * フォーマットはマルチチャンネルで、クロックおよびフレーム信号は外部生成。この関数を読んだ段階
00083        * では、ポートはディセーブルのままにしておく。
00084        *
00085        * 
00086        * 詳細はADSP-BF533 Hardware Referenceの "Stereo Serial Operation" を参照のこと。
00087        * afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
00088        *
00089        * 注意:EZ-KIT Lite BF537 Rev 1.0のユーザーはSPORTのクロックおよびフレーム同期
00090        * 信号を自分で生成する設定に変更しなければならない。
00091        */
00092     void Init_Sport0(void)
00093     {
00094         // Sport0 receive configuration
00095         // External CLK, External Frame sync, MSB first
00096         // 32-bit data
00097         *pSPORT0_RCR1 = RFSR;
00098         *pSPORT0_RCR2 = SLEN_32;
00099     
00100         // Sport0 transmit configuration
00101         // External CLK, External Frame sync, MSB first
00102         // 24-bit data
00103         *pSPORT0_TCR1 = TFSR;
00104         *pSPORT0_TCR2 = SLEN_32;
00105     
00106         // Enable MCM 8 transmit & receive channels
00107         *pSPORT0_MTCS0 = 0x000000FF;
00108         *pSPORT0_MRCS0 = 0x000000FF;
00109     
00110         // Set MCM configuration register and enable MCM mode
00111         *pSPORT0_MCMC1 = 0x0000;
00112         *pSPORT0_MCMC2 = 0x101c;
00113     }
00114 
00115 
00116     /** SPORT DMAの初期化
00117        * 
00118        * SPORT0に接続されているDMAを設定する。DMA1が受信、DMA2が送信である。
00119        * オーディオ信号は16ビット以上の長さがあるのでワードサイズは32bit, 
00120        * 連続送受信のためにオートバッファ、モードを使う。また、トリプル・バッファを
00121        * 実装するために、DMA転送は2次元で行い、3ライン分のバッファを確保して各ラインの
00122        * 転送を終えるたびに割り込みを発生させる。
00123        * afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
00124        */
00125     void Init_DMA(void)
00126     {
00127         int i, field;
00128     
00129         // Set up DMA1 to receive
00130         // Map DMA1 to Sport0 RX
00131         *pDMA1_PERIPHERAL_MAP = 0x1000;
00132     
00133         // Configure DMA1
00134         // 32-bit transfers, Interrupt on completion, Autobuffer mode
00135         *pDMA1_CONFIG = WNR | WDSIZE_32 | DI_EN | DI_SEL | FLOW_1 | DMA2D ;
00136         // Start address of data buffer
00137         *pDMA1_START_ADDR = (void *)iRxBuffer1;
00138         // DMA inner loop count
00139         *pDMA1_X_COUNT = 8* SAMPLES_PER_INTR;
00140         // Inner loop address increment
00141         *pDMA1_X_MODIFY = 4;
00142         // DMA outer loop count, triple buffer
00143         *pDMA1_Y_COUNT = 3;
00144         // Outer loop address increment
00145         *pDMA1_Y_MODIFY = 4;    
00146     
00147         // Set up DMA2 to transmit
00148         // Map DMA2 to Sport0 TX
00149         *pDMA2_PERIPHERAL_MAP = 0x2000;
00150     
00151         // Configure DMA2
00152         // 32-bit transfers, Autobuffer mode
00153         *pDMA2_CONFIG = WDSIZE_32 | FLOW_1 | DMA2D;
00154         // Start address of data buffer
00155         *pDMA2_START_ADDR = (void *)iTxBuffer1;
00156         // DMA inner loop count
00157         *pDMA2_X_COUNT = 8* SAMPLES_PER_INTR;
00158         // Inner loop address increment
00159         *pDMA2_X_MODIFY = 4;
00160         // DMA outer loop count, triple buffere
00161         *pDMA2_Y_COUNT = 3;
00162         // Outer loop address increment
00163         *pDMA2_Y_MODIFY = 4;    
00164     
00165         for ( i=0; i<SAMPLES_PER_INTR; i++ ){
00166             for ( field=0; field<3; field ++ ){
00167                 // Clean up buffer for transfer
00168                 iRxBuffer1[field][i][INTERNAL_ADC_L0] = 0;
00169                 iRxBuffer1[field][i][INTERNAL_ADC_R0] = 0;
00170                 iRxBuffer1[field][i][INTERNAL_ADC_L1] = 0;
00171                 iRxBuffer1[field][i][INTERNAL_ADC_R1] = 0;
00172                 iTxBuffer1[field][i][INTERNAL_DAC_L0] = 0;
00173                 iTxBuffer1[field][i][INTERNAL_DAC_R0] = 0;
00174                 iTxBuffer1[field][i][INTERNAL_DAC_L1] = 0;
00175                 iTxBuffer1[field][i][INTERNAL_DAC_R1] = 0;
00176                 iTxBuffer1[field][i][INTERNAL_DAC_L2] = 0;
00177                 iTxBuffer1[field][i][INTERNAL_DAC_R2] = 0;
00178             }
00179         }
00180     }
00181 
00182     /** 割り込みのイネーブル
00183        * 
00184        * SPORT0 受信割込みを有効化する。SPORT0 受信割り込みはIVG9で処理したいので、その割り当ても設定する。
00185        * afw::init()が自動的に呼び出すので、プログラマがこの関数を明示的に呼ぶ必要はない。
00186        */
00187     void Init_Sport_Interrupts(void)
00188     {
00189         // Set Sport0 RX (DMA1) interrupt priority to 2 = IVG9 
00190         *pSIC_IAR0 = 0xffffffff;
00191         *pSIC_IAR1 = 0xffffff2f;
00192         *pSIC_IAR2 = 0xffffffff;
00193 
00194         // assign ISRs to interrupt vectors
00195         // Sport0 RX ISR -> IVG 9
00196         interrupt(SIGIVG9, rxISR);      
00197 
00198         // enable Sport0 RX interrupt
00199         *pSIC_IMASK = 0x00000200;
00200         ssync();
00201     }
00202 
00203 
00204     /** SPORTとDMAのイネーブル
00205        * 
00206        * 設定が終わったSPORTとDMAの両方をイネーブルする
00207        */
00208     void startAudio(void)
00209     {
00210         // enable DMAs
00211         *pDMA2_CONFIG |= DMAEN;
00212         *pDMA1_CONFIG |= DMAEN;
00213     
00214         // enable Sport0 TX and RX
00215         *pSPORT0_TCR1 |= TSPEN;
00216         *pSPORT0_RCR1 |= RSPEN;
00217     }
00218 
00219     /** afwの初期化
00220        * 
00221        * オーディオ・フレームワークの初期化。初期化関数はこれひとつよべば、残りの関数を
00222        * まとめて呼んでくれる。ただし、afw::startAudio は呼ばないので、プログラマが明示的に
00223        * 呼ばなければならない。
00224        */
00225     void init(void)
00226     {
00227         Init1836();
00228         Init_Sport0();
00229         Init_DMA();
00230         Init_Sport_Interrupts();
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         // confirm interrupt handling
00264         *pDMA1_IRQ_STATUS = 0x0001;
00265     
00266         
00267         if (  2 == *pDMA2_CURR_Y_COUNT )
00268             field = 0;
00269         else
00270             field ++;
00271     
00272         for ( int i=0; i<SAMPLES_PER_INTR; i++ ){   // Loop for each sample : Horie
00273             // copy input data from dma input buffer into variables
00274             leftIn[i] = iRxBuffer1[field][i][INTERNAL_ADC_L0] >> 16;
00275             rightIn[i] = iRxBuffer1[field][i][INTERNAL_ADC_R0] >> 16;
00276         }
00277             // call function that contains user code
00278         processData( leftIn, rightIn, leftOut, rightOut, SAMPLES_PER_INTR );                
00279     
00280         for ( int i=0; i<SAMPLES_PER_INTR; i++ ){   // Loop for each sample : Horie
00281             // copy processed data from variables into dma output buffer
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     // Variables                                                                //
00290     //                                                                          //
00291     // Description: The variables iChannelxLeftIn and iChannelxRightIn contain  //
00292     //              the data coming from the codec AD1836.  The (processed)     //
00293     //              playback data are written into the variables                //
00294     //              iChannelxLeftOut and iChannelxRightOut respectively, which  //
00295     //              are then sent back to the codec in the SPORT0 ISR.          //
00296     //              The values in the array iCodec1836TxRegs can be modified to //
00297     //              set up the codec in different configurations according to   //
00298     //              the AD1885 data sheet.                                      //
00299     //--------------------------------------------------------------------------//
00300 
00301     // array for registers to configure the ad1836
00302     // names are defined in "Talkthrough.h"
00303     volatile short sCodec1836TxRegs[CODEC_1836_REGS_LENGTH] =
00304     {                                   
00305                         DAC_CONTROL_1   | 0x000,
00306                         DAC_CONTROL_2   | 0x000,
00307                         DAC_VOLUME_0    | 0x3ff,
00308                         DAC_VOLUME_1    | 0x3ff,
00309                         DAC_VOLUME_2    | 0x3ff,
00310                         DAC_VOLUME_3    | 0x3ff,
00311                         DAC_VOLUME_4    | 0x3ff,
00312                         DAC_VOLUME_5    | 0x3ff,
00313                         ADC_CONTROL_1   | 0x000,
00314                         ADC_CONTROL_2   | 0x180,
00315                         ADC_CONTROL_3   | 0x000
00316                     
00317     };
00318     // SPORT0 DMA transmit buffer
00319     volatile int iTxBuffer1[3][SAMPLES_PER_INTR][8];    // Need place for each sample
00320     // SPORT0 DMA receive buffer
00321     volatile int iRxBuffer1[3][SAMPLES_PER_INTR][8];    // 
00322 
00323 
00324 
00325 }   // namespace afw

AudioFrameWorkに対してFri Sep 8 15:17:47 2006に生成されました。  doxygen 1.4.7