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

📄 aaci_audio.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
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 + -