⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aaci_audio.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif
        AACIBit_DataSize16bits |
        AACIBit_EnableFIFOMode );

    INITMSG("AACI: Setup Main Control Register");
//yz_add	
    AACI_RegWrite32( AACIReg_MainControl, AACIBit_Enable | 
            AACIBit_Slot1TXEnable | AACIBit_Slot1RXEnable | 
            AACIBit_Slot2TXEnable | AACIBit_Slot2RXEnable | AACIBit_DMAEnable);

    // Wait for CODEC to be ready
    INITMSG("AACI: Wait till CODEC ready");
    while( (AACI_CodecRead16(LM4549A_POWERDOWN_CTRL_STAT) != 0xF) && loop < 10 )
    {
        Sleep(10);
        loop++;
    }
    if( loop == 10 )
    {
        ERRMSG("AACI: Failed to wait for CODEC to power up" );
        return FALSE;
    }

    // Turn off PC Beep (by default it is on full)
    INITMSG("AACI: Turn off PC Beep");
    AACI_CodecWrite16( LM4549A_PC_BEEP_VOLUME, LM4549A_BIT_VOLUME_MUTE );
	AACI_CodecWrite16( LM4549A_MASTER_VOLUME , 0x0000 );
	AACI_CodecWrite16( LM4549A_PCM_OUT_VOL , 0x0909 );
	//AACI_CodecWrite16( LM4549A_MIC_VOLUME , 0x8040 );
	AACI_CodecWrite16( LM4549A_GENERAL_PURPOSE , 0x00 );
	//AACI_CodecWrite16( LM4549A_RECORD_GAIN , 0x00 );
	AACI_CodecWrite16( LM4549A_RECORD_SELECT , 0x0404 );
	
	// Turn on Variable Rate Audio (VRA) to allow sample rate to be set
    INITMSG("AACI: Turn on VRA");
    AACI_CodecWrite16( LM4549A_EXT_AUDIO_CTRL_STAT, 0x1 );
    
	AACI_CodecWrite16( LM4549A_PCM_FRONT_DAC_RATE, 44100 );
	RETAILMSG( 0 , (TEXT("aaci : read sample per sec %x\r\n") , AACI_CodecRead16(LM4549A_PCM_FRONT_DAC_RATE) ));
	
	AACI_RegWrite32( AACIReg_Channel1IntEnable, 
		AACI_RegRead32( AACIReg_Channel1IntEnable ) & 
		~(AACIBit_TxCIE | AACIBit_TxIE | AACIBit_TxUIE) );
	
	
	// Clear any transmit underruns now we have filled the FIFO
	if( AACI_RegRead32( AACIReg_Channel1Status ) & AACIBit_TXUnderrun )
	{
		TESTMSG("AACI_WaveContinue: Transmit Underrun - too slow!");
		AACI_RegWrite32( AACIReg_IntClear, AACIBit_TxUEC1 );
	}


    return TRUE;
}

//-----------------------------------------------------------------------------
// Power functions - Place holder functions for your own power code
//-----------------------------------------------------------------------------
static void PowerDown()
{
    if( g_fPowerOn )
    {
        // Turn off the CODEC - go into low power mode
        g_fPowerOn = FALSE;
    }
}

static void PowerUp()
{
    if( !g_fPowerOn )
    {
        // Turn on the CODEC - from low power mode
        g_fPowerOn = TRUE;
    }
}


//--------------------------------------------------------------------------
//  MMRESULT AACI_WaveOpen (WAPI_INOUT apidir,
//                     LPWAVEFORMATEX lpFormat,
//                     BOOL fQueryFormatOnly)
//
//  Opens or query the wave stream.
//
//  It also can be used to query the format to see if it's a valid one.
//  To do so, the caller has to set fQueryFormatOnly to TRUE.
//
//  WAPI_INOUT apidir
//      Direction of the stream:  Playback=1, Record=0
//
//  LPWAVEFORMATEX lpFormat
//      Pointer to a structure that defines the format of the wave.
//      Based on Microsoft definition.
//
//  unsigned char fQueryFormatOnly
//      If the caller only want to check on the format,
//      this value should be set to TRUE
//---------------------------------------------------------------------------

//int MsgRecord[100][2];

MMRESULT AACI_WaveOpen (WAPI_INOUT apidir,
    LPWAVEFORMATEX lpFormat,
    BOOL fQueryFormatOnly)
{

    MMRESULT mmRet = MMSYSERR_NOERROR;

    FUNC_WPDD("+AACI_WaveOpen");	
	RETAILMSG(0,(TEXT("aaci Samples PerSec : %d , %d , %d , %d \r\n") , 
		lpFormat->nSamplesPerSec , lpFormat->nAvgBytesPerSec  , lpFormat->nBlockAlign  , lpFormat->wBitsPerSample ));

    PRINTMSG( ZONE_VERBOSE, (TEXT("AACI_WaveOpen: dir=%d, chan=%d, samp=%d, bits=%d\n"), 
            apidir, lpFormat->nChannels, (USHORT)lpFormat->nSamplesPerSec, 
            lpFormat->wBitsPerSample) );

    if ((lpFormat->wFormatTag != WAVE_FORMAT_PCM) ||
        (lpFormat->nChannels !=1 && lpFormat->nChannels != 2) ||
        (lpFormat->nSamplesPerSec < 4000 || lpFormat->nSamplesPerSec > 48000) ||
        (lpFormat->wBitsPerSample != 16 && lpFormat->wBitsPerSample != 8))
    {
        VERBOSEMSG("AACI_WaveOpen: Bad Format");
        mmRet = WAVERR_BADFORMAT;
        goto EXIT;
    }


    // If the caller only wants to check on that format, return having 
    //  checked above
    if (fQueryFormatOnly)
    {
        VERBOSEMSG("AACI_WaveOpen: QueryFormatOnly");
        goto EXIT;
    }

	//RETAILMSG(yz_debug,(TEXT("AACI_WaveOpen()\r\n")));
    //  If the device is already being use, return with MMSYSERR_ALLOCATED
    if (g_fInUse[apidir])
    {
        mmRet = MMSYSERR_ALLOCATED;
        goto EXIT;
    }

    g_fInUse[apidir] = TRUE;
    g_pwfx[apidir] = lpFormat;

    // Make sure the CODEC is on
    PowerUp();

    // Sort out pointer to correct function for speedy operation
    if( apidir == WAPI_OUT )
    {
        VERBOSEMSG("AACI_WaveOpen: WAPI_OUT");

        if (lpFormat->wBitsPerSample == 8)
        {
            if (lpFormat->nChannels == 1)
                    pfnFillFIFO = FillFIFO_M8;
            else
                    pfnFillFIFO = FillFIFO_S8;
        }
        else
        {
            if (lpFormat->nChannels == 1)
            	{
		            pfnFillFIFO = FillFIFO_M16;
            	}	
            else
            	{
            	    pfnFillFIFO = FillFIFO_S16;
            	}
        }

        // Unmute and turn PCM and Line Level volumes to max
        // Set output sample rate
		
        AACI_CodecWrite16( LM4549A_PCM_FRONT_DAC_RATE, 
                (USHORT)lpFormat->nSamplesPerSec );
		RETAILMSG( 0 , (TEXT("aaci : read sample per sec %x\r\n") , AACI_CodecRead16(LM4549A_PCM_FRONT_DAC_RATE) ));

		AACI_RegWrite32( AACIReg_Channel1IntEnable, 
			AACI_RegRead32( AACIReg_Channel1IntEnable ) & 
			~(AACIBit_TxCIE | AACIBit_TxIE | AACIBit_TxUIE) );
		
		
		// Clear any transmit underruns now we have filled the FIFO
		if( AACI_RegRead32( AACIReg_Channel1Status ) & AACIBit_TXUnderrun )
		{
			TESTMSG("AACI_WaveContinue: Transmit Underrun - too slow!");
			AACI_RegWrite32( AACIReg_IntClear, AACIBit_TxUEC1 );
		}
		OnPlayOpen();
    }
    else
    {
        VERBOSEMSG("AACI_WaveOpen: WAPI_IN");

        if (lpFormat->wBitsPerSample == 8)
        {
            if (lpFormat->nChannels == 1)
                    pfnGetFIFO = GetFIFO_M8;
            else
                    pfnGetFIFO = GetFIFO_S8;
        }
        else
        {
            if (lpFormat->nChannels == 1)
                    pfnGetFIFO = GetFIFO_M16;
            else
                    pfnGetFIFO = GetFIFO_S16;
        }
		
        // NOTE: By default only the MIC will be active for recording, you 
        //  need to use the RECORD_SELECT codec register to change this

        // Set up input gain to something reasonable (not too high so as to 
        //  reduce signal chopping)
        AACI_CodecWrite16( LM4549A_RECORD_GAIN, 0x0a0a );
        
        // Set input sample rate
        AACI_CodecWrite16( LM4549A_PCM_ADC_RATE,
                (USHORT)lpFormat->nSamplesPerSec );

		AACI_RegWrite32( AACIReg_Channel1RxControl, 
			AACI_RegRead32(AACIReg_Channel1RxControl) & 
			(~AACIBit_EnableFIFO) );
		
        // Clear any interrupts
        AACI_RegWrite32( AACIReg_IntClear, AACIBit_RxTOFEC1 | AACIBit_RxOEC1 );
		
        // Enable Receive
        AACI_RegWrite32( AACIReg_Channel1RxControl, 
			AACI_RegRead32(AACIReg_Channel1RxControl) | 
			AACIBit_EnableFIFO );
		OnRecordOpen();
    }
EXIT:
    FUNC_WPDD("-AACI_WaveOpen");
//    OnOpen();
	//memset( MsgRecord , 0 , sizeof( MsgRecord ) );
	//KernelIoControl( IOCTL_HAL_FREE_DMA_SYSINTR +1 , 0 , 0 , 0 , 0 , 0 );
    return(mmRet);
}

// -----------------------------------------------------------------------------
//   VOID AACI_WaveClose(WAPI_INOUT apidir)
//
//   Closes the Wave Stream.
//   Sets the "In use" flag to FALSE;
// -----------------------------------------------------------------------------
VOID AACI_WaveClose(WAPI_INOUT apidir)
{
    FUNC_WPDD("AACI_WaveClose()");
	
	//RETAILMSG(yz_debug,(TEXT("AACI_WaveClose()\r\n")));
	
    if( apidir == WAPI_OUT )
    {
		OnPlayClose();
	}
	else
		OnRecordClose();
	/*
        VERBOSEMSG("AACI_WaveClose: WAPI_OUT");

	//yz_change
	p_n = 0;
        // Mute PCM and Line Level
        AACI_CodecWrite16( LM4549A_PCM_OUT_VOL, LM4549A_BIT_VOLUME_MUTE );
        AACI_CodecWrite16( LM4549A_LINE_LEV_OUT_VOL, LM4549A_BIT_VOLUME_MUTE );
    }
    else
    {
        VERBOSEMSG("AACI_WaveClose: WAPI_IN");

        // Mute input gain
        AACI_CodecWrite16( LM4549A_RECORD_GAIN, LM4549A_BIT_VOLUME_MUTE );
    }
*/
    g_pwfx[apidir]   = NULL;
    g_fInUse[apidir] = FALSE;
/*    
   if( MsgCount )
   	{
   		int i;
		for( i=0; i<MsgCount; i++ )
			RETAILMSG( 1 , (TEXT("physiaddr : %x , %x: \r\n") , MsgRecord[i][0] , MsgRecord[i][1]));
    }
*/    	
    //yz_add
    //fclose(DebugFile);
    
   //KernelIoControl( IOCTL_HAL_FREE_DMA_SYSINTR +2 , 0 , 0 , 0 , 0 , 0 );
//    OnClose();
    FUNC_WPDD("-AACI_WaveClose");
}

// -----------------------------------------------------------------------------
//  VOID AACI_WaveStart(WAPI_INOUT apidir, PWAVEHDR pwh)
//
//  Starts playback or record. Also called when overflow or underflow occurs to
//   re-synchoronise.
// -----------------------------------------------------------------------------
VOID AACI_WaveStart(WAPI_INOUT apidir, PWAVEHDR pwh)
{
    FUNC_WPDD("+AACI_WaveStart");

    // We are now running
    g_dwRunMode[apidir] = RUNMODE_RUNNING;

    // Start by assuming we have more data to send/get
    gv_fMoreData[apidir] = TRUE;	

	
    // Make sure the CODEC is on
    PowerUp();

#ifdef AACI_STATS
    g_dwBytesRecorded[apidir] = 0;
#endif    

    if( apidir == WAPI_OUT )
    {
        // We havn't got to the end yet!
        g_fTxEndOfData = FALSE;
        
        // Disable Transmit
        AACI_RegWrite32( AACIReg_Channel1TxControl, 
                        AACI_RegRead32(AACIReg_Channel1TxControl) & 
                        (~AACIBit_EnableFIFO) );

        // Fill up the FIFO
        (*pfnFillFIFO)(pwh);

        // Clear any interrupts
        AACI_RegWrite32( AACIReg_IntClear, AACIBit_TxUEC1 );	
   // Enable Transmit
        AACI_RegWrite32( AACIReg_Channel1TxControl, 
                        AACI_RegRead32(AACIReg_Channel1TxControl) | 
                        AACIBit_EnableFIFO );
        OnPlayStart();
    }
    else // (apidir == WAPI_IN)
    {
		// Disable Receive
        AACI_RegWrite32( AACIReg_Channel1RxControl, 
                        AACI_RegRead32(AACIReg_Channel1RxControl) & 
                        (~AACIBit_EnableFIFO) );

        // Clear any interrupts
        AACI_RegWrite32( AACIReg_IntClear, AACIBit_RxTOFEC1 | AACIBit_RxOEC1 );

        // Enable Receive
        AACI_RegWrite32( AACIReg_Channel1RxControl, 
                        AACI_RegRead32(AACIReg_Channel1RxControl) | 
                        AACIBit_EnableFIFO );
		OnRecordStart();
    }
    FUNC_WPDD("-AACI_WaveStart");
}

// -----------------------------------------------------------------------------
//  VOID AACI_WaveContinue (WAPI_INOUT apidir, PWAVEHDR pwh)
//
//  Continues playback or record, will be called straight after GetInterrupt
//   returns PLAYING or RECORDING status.
// -----------------------------------------------------------------------------
VOID AACI_WaveContinue (WAPI_INOUT apidir, PWAVEHDR pwh)
{
#if 0
    while( pwh != NULL && pwh->dwBytesRecorded >= pwh->dwBufferLength )
    {
        pwh = pwh->lpNext;
    }

	RETAILMSG(yz_debug,(TEXT("AACI_WaveContinue()\r\n")));

    if( pwh == NULL )
    {
        gv_fMoreData[apidir] = FALSE;
	RETAILMSG(yz_debug,(TEXT("AACI_WaveContinue() - NULL\r\n")));	
    }
    else
    {
        if (apidir == WAPI_OUT)
        {
            // Output these messages under test as they slow things down if 
            //  on most of the time
            TESTMSG("AACI_WaveContinue: WAPI_OUT");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -