📄 aaci_audio.c
字号:
static DWORD TestTransmit_Complete( BOOL fNotCompact )
{
DWORD dwRet;
// Fill the FIFO for transmitting (to allow us some time to receive the
// interrupt)
while( !(AACI_RegRead32( AACIReg_Channel1Status ) & AACIBit_TXFIFOFull) )
{
AACI_RegWrite32( AACIReg_Channel1FIFO, 0 );
}
// Enable Interrupt
g_dwTestIntStatus = 0;
AACI_RegWrite32( AACIReg_Channel1IntEnable, AACIBit_TxCIE );
// Enable Transmit and wait for completion
AACI_RegWrite32( AACIReg_Channel1TxControl,
AACI_RegRead32(AACIReg_Channel1TxControl) |
AACIBit_EnableFIFO );
dwRet = WaitForSingleObject( g_hTestInterrupt, TESTWAIT_TRANSMIT );
// Disable interrupts
AACI_RegWrite32( AACIReg_Channel1IntEnable, 0 );
if( g_dwTestIntStatus & AACIBit_TxCIE )
{
RETAILMSG( TRUE, (TEXT("PASS\n")) );
return MMSYSERR_NOERROR;
}
RETAILMSG( TRUE, (TEXT("FAIL (ints=0x%04x)\n"), g_dwTestIntStatus) );
return MMSYSERR_ERROR;
}
static DWORD TestTransmit_HalfEmpty( BOOL fNotCompact )
{
DWORD dwCount, dwDataCount;
DWORD dwRet;
dwDataCount = (fNotCompact ? 2 : 1);
do
{
// Put some data words into the FIFO for transmitting
for( dwCount = 0; dwCount < dwDataCount; dwCount++ )
{
AACI_RegWrite32( AACIReg_Channel1FIFO, 0 );
}
// Enable the half-way (or less) interrupt to see what the status of
// the FIFO is
g_dwTestIntStatus = 0;
AACI_RegWrite32( AACIReg_Channel1IntEnable, AACIBit_TxIE );
dwRet = WaitForSingleObject( g_hTestInterrupt, TESTWAIT_TRANSMIT );
// Make sure interrupts disabled
AACI_RegWrite32( AACIReg_Channel1IntEnable, 0 );
// Check for when we don't have the half-way or less interrupt set
if( !(g_dwTestIntStatus & AACIBit_TxIE) )
{
// It shouldn't be active at just over halfway in the FIFO
// (starting from 1)
if( (fNotCompact && dwDataCount == (TX_FIFOSIZE_NOTCOMPACT/2)+2) ||
(!fNotCompact && dwDataCount == (TX_FIFOSIZE_COMPACT/2)+1) )
{
RETAILMSG( TRUE, (TEXT("PASS\n")) );
return MMSYSERR_NOERROR;
}
else
{
// Wrong half way level
break;
}
}
if( !ClearTransmitFIFO() )
{
RETAILMSG(TRUE, (TEXT("TestTransmit_HalfEmpty: WARNING - problems clearing FIFO after test\n")) );
}
dwDataCount += (fNotCompact ? 2 : 1);
}
while( dwDataCount <= TX_FIFOSIZE_NOTCOMPACT );
RETAILMSG( TRUE, (TEXT("FAIL (halfway=%d)\n"),dwDataCount) );
return MMSYSERR_ERROR;
}
DWORD TestReceive( DWORD uMsg )
{
DWORD dwTest;
DWORD dwRXCtrl, dwRXSize;
DWORD dwRet = MMSYSERR_NOERROR, dwResult;
RETAILMSG( TRUE, (TEXT("TestReceive v0.2\n")) );
if( !g_fInUse[WAPI_IN] )
{
RETAILMSG( TRUE, (TEXT("TestTransmit_xxx: ERROR - WaveIn channel should have been opened\n")) );
return MMSYSERR_ERROR;
}
if( g_fInUse[WAPI_OUT] )
{
// We need to take over the whole AACI so we need both channels
RETAILMSG( TRUE, (TEXT("TestReceive_xxx: ERROR - WaveOut channel in use\n")) );
return MMSYSERR_ERROR;
}
g_fTesting = TRUE;
g_fInUse[WAPI_OUT] = TRUE; // Stop anyone else using the playback channel
// whilst we are testing record
g_fTestIntDisable = TRUE; // Assume we don't want interrupts to continue
// after the first one
// Reset device to get into known state
ResetDevice();
dwRXCtrl = AACIBit_Slot3DataInFIFO | AACIBit_Slot4DataInFIFO |
AACIBit_EnableFIFOMode;
// Set input rate to 4KHz
AACI_CodecWrite16( LM4549A_PCM_ADC_RATE, 4000 );
PAUSE;
// Disable AACI and then Transmit & Receive FIFOs
AACI_RegWrite32( AACIReg_MainControl, 0 );
AACI_RegWrite32( AACIReg_Channel1TxControl, 0 );
AACI_RegWrite32( AACIReg_Channel1RxControl, 0 );
PAUSE;
// Turn on AACI without slot comms
AACI_RegWrite32( AACIReg_MainControl, AACIBit_Enable );
// Create an interrupt event
g_hTestInterrupt = CreateEvent( NULL, FALSE, FALSE, NULL );
for( dwTest = 0; dwTest < 6; dwTest++ )
{
switch( dwTest )
{
case 0:
RETAILMSG( TRUE, (TEXT("Data size 16 bits: ")) );
dwRXSize = AACIBit_DataSize16bits;
break;
case 1:
RETAILMSG( TRUE, (TEXT("Data size 12 bits: ")) );
dwRXSize = AACIBit_DataSize12bits;
break;
case 2:
RETAILMSG( TRUE, (TEXT("Data size 18 bits: ")) );
dwRXSize = AACIBit_DataSize18bits;
break;
case 3:
RETAILMSG( TRUE, (TEXT("Data size 20 bits: ")) );
dwRXSize = AACIBit_DataSize20bits;
break;
case 4:
RETAILMSG( TRUE, (TEXT("Data size 16 bits compact: ")) );
dwRXSize = AACIBit_DataSize16bits | AACIBit_EnableCompactMode;
break;
case 5:
RETAILMSG( TRUE, (TEXT("Data size 12 bits compact: ")) );
dwRXSize = AACIBit_DataSize12bits | AACIBit_EnableCompactMode;
break;
}
// Set up Receive FIFO (Disable AACI whilst changing receive size and
// compact mode)
AACI_RegWrite32( AACIReg_MainControl, 0 );
AACI_RegWrite32( AACIReg_Channel1RxControl, dwRXCtrl | dwRXSize );
AACI_RegWrite32( AACIReg_Channel1IntEnable, 0 );
PAUSE;
AACI_RegWrite32( AACIReg_MainControl, AACIBit_Enable );
// Clear the event of any previous interrupts
ResetEvent( g_hTestInterrupt );
g_fTestIntDisable = TRUE;
switch (uMsg)
{
case TESTRX_OVERRUN:
dwResult = TestReceive_Overrun( (dwTest < 4) );
break;
case TESTRX_HALFFULL:
dwResult = TestReceive_HalfFull( (dwTest < 4) );
break;
case TESTRX_RUNAWAY:
dwResult = TestReceive_Runaway( (dwTest < 4) );
break;
default:
RETAILMSG(TRUE, (TEXT("TestReceive: Unsupported test %d\n"),
uMsg) );
dwResult = MMSYSERR_ERROR;
}
if( dwResult != MMSYSERR_NOERROR ) dwRet = dwResult;
// Check for error?
if( !ClearReceiveFIFO(NULL) )
{
RETAILMSG(TRUE, (TEXT("TestReceive: WARNING - problems clearing FIFO after test\n")) );
}
}
CloseHandle( g_hTestInterrupt );
// Clean up
ResetDevice();
AACI_SetVolume(g_nVolume);
g_fInUse[WAPI_OUT] = FALSE;
g_fTesting = FALSE;
return dwRet;
}
static DWORD TestReceive_Overrun( BOOL fNotCompact )
{
DWORD dwRet;
// Enable Interrupt
g_dwTestIntStatus = 0;
AACI_RegWrite32( AACIReg_Channel1IntEnable, AACIBit_RxOIE );
// Enable Receive and wait for overrun
AACI_RegWrite32( AACIReg_Channel1RxControl,
AACI_RegRead32(AACIReg_Channel1RxControl) |
AACIBit_EnableFIFO );
dwRet = WaitForSingleObject( g_hTestInterrupt, TESTWAIT_RECEIVE );
// Disable interrupts
AACI_RegWrite32( AACIReg_Channel1IntEnable, 0 );
if( g_dwTestIntStatus & AACIBit_RxOIE )
{
if( !ClearReceiveFIFO( &dwRet ) )
{
RETAILMSG(TRUE, (TEXT("TestReceive_Overrun: WARNING - problems clearing FIFO after test\n")) );
}
if( (fNotCompact && dwRet == RX_FIFOSIZE_NOTCOMPACT) ||
(!fNotCompact && dwRet == RX_FIFOSIZE_COMPACT) )
{
RETAILMSG( TRUE, (TEXT("PASS\n")) );
return MMSYSERR_NOERROR;
}
}
else
{
dwRet = -1;
}
RETAILMSG( TRUE, (TEXT("FAIL (ints=0x%04x, size=%d)\n"),
g_dwTestIntStatus, dwRet) );
return MMSYSERR_ERROR;
}
static DWORD TestReceive_HalfFull( BOOL fNotCompact )
{
DWORD dwRet, dwDataCount, dwData;
// First enable the receive FIFO till it over fills
g_dwTestIntStatus = 0;
AACI_RegWrite32( AACIReg_Channel1IntEnable, AACIBit_RxOIE );
AACI_RegWrite32( AACIReg_Channel1RxControl,
AACI_RegRead32(AACIReg_Channel1RxControl) |
AACIBit_EnableFIFO );
dwRet = WaitForSingleObject( g_hTestInterrupt, TESTWAIT_RECEIVE );
// Make sure interrupts disabled
AACI_RegWrite32( AACIReg_Channel1IntEnable, 0 );
if( g_dwTestIntStatus & AACIBit_RxOIE )
{
// Disable receive & clear the interrupts
AACI_RegWrite32( AACIReg_Channel1RxControl,
AACI_RegRead32(AACIReg_Channel1RxControl) &
~(AACIBit_EnableFIFO) );
AACI_RegWrite32( AACIReg_IntClear, AACIBit_ClearAllInts );
// Now we start reading the receive FIFO until we don't get the
// half-full interrupt
dwDataCount = (fNotCompact ? RX_FIFOSIZE_NOTCOMPACT :
RX_FIFOSIZE_COMPACT);
do
{
dwData = AACI_RegRead32( AACIReg_Channel1FIFO );
dwDataCount--;
if( fNotCompact )
{
dwData = AACI_RegRead32( AACIReg_Channel1FIFO );
dwDataCount--;
}
// Enable the half-full Interrupt
g_dwTestIntStatus = 0;
AACI_RegWrite32( AACIReg_Channel1IntEnable, AACIBit_RxIE );
dwRet = WaitForSingleObject( g_hTestInterrupt, 2000 );
// Make sure interrupts disabled
AACI_RegWrite32( AACIReg_Channel1IntEnable, 0 );
if( !(g_dwTestIntStatus & AACIBit_RxIE) )
{
// It shouldn't be active at just under halfway in the FIFO
// (from 1)
if( (fNotCompact && dwDataCount == (RX_FIFOSIZE_NOTCOMPACT/2)-2) ||
(!fNotCompact && dwDataCount == (RX_FIFOSIZE_COMPACT/2)-1) )
{
RETAILMSG( TRUE, (TEXT("PASS\n")) );
return MMSYSERR_NOERROR;
}
else
{
// Wrong half way level
break;
}
}
} while ( dwDataCount > 0 );
}
else
{
dwDataCount = -1;
}
if( fNotCompact )
{
RETAILMSG( TRUE, (TEXT("FAIL (ints=0x%04x, halffull %d (!= %d expected), dataread=%d)\n"),
g_dwTestIntStatus, dwDataCount, (RX_FIFOSIZE_NOTCOMPACT/2)-2,
RX_FIFOSIZE_NOTCOMPACT - dwDataCount ) );
}
else
{
RETAILMSG( TRUE, (TEXT("FAIL (ints=0x%04x, halffull %d (!= %d expected), dataread=%d)\n"),
g_dwTestIntStatus, dwDataCount, (RX_FIFOSIZE_COMPACT/2)-1,
RX_FIFOSIZE_COMPACT - dwDataCount ) );
}
return MMSYSERR_ERROR;
}
#define TEST_RECSECS 5
#define TEST_RECFREQ 22050
#define TEST_RECSAMPLES (TEST_RECFREQ * TEST_RECSECS)
#define TEST_RECTHRESH (TEST_RECSAMPLES / 10)
static DWORD TestReceive_Runaway( BOOL fNotCompact )
{
DWORD dwLoops, dwStartTime, dwEndTime, dwCount;
DWORD dwSamplesRec, dwData, dwStatus;
DWORD dwWait, dwRet = MMSYSERR_NOERROR;
// The reason it does not pass reliably is probably due to the way
// interrupts are used.
RETAILMSG( TRUE, (TEXT("*** NOTE: This test does not pass reliably - please ignore failures ***\n")) );
g_dwTestIntStatus = 0;
AACI_RegWrite32( AACIReg_MainControl,
AACIBit_Enable | AACIBit_Slot1TXEnable |
AACIBit_Slot1RXEnable | AACIBit_Slot2TXEnable |
AACIBit_Slot2RXEnable );
PAUSE;
RETAILMSG( TRUE, (TEXT("Setting sample rate to %d\n"), TEST_RECFREQ) );
AACI_CodecWrite16( LM4549A_PCM_ADC_RATE, TEST_RECFREQ );
PAUSE;
AACI_RegWrite32( AACIReg_MainControl, AACIBit_Enable );
for( dwLoops = 0; dwLoops < 10; dwLoops++ )
{
RETAILMSG( TRUE, (TEXT("Loop %d\n"), dwLoops) );
dwSamplesRec = 0;
// Enable half-full interrupt
AACI_RegWrite32( AACIReg_Channel1IntEnable, AACIBit_RxIE );
// Ticks are 1ms, wait for 5 secs
// Note: this will not wait for 5 seconds if the ticks wrap around,
// but as this is a simple test let us ignore this for now
dwStartTime = GetTickCount();
dwEndTime = dwStartTime + (TEST_RECSECS * 1000);
RETAILMSG( TRUE, (TEXT(" Start ticks %lu, End ticks %lu, Status 0x%08x\n"),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -