📄 aaci_audio.c
字号:
#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 + -