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

📄 aaci_audio.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 5 页
字号:

//-----------------------------------------------------------------------
//   VOID AACI_RegWrite32 (USHORT reg, ULONG val)
//
//   Writes 32 bits to the 5530/5540 I/O port
//-----------------------------------------------------------------------
VOID AACI_RegWrite32(USHORT reg, ULONG val)
{
    PULONG reg_loc;

    reg_loc  = (PULONG)(g_AudioRegBase + reg);
    *reg_loc = val;
}

//-----------------------------------------------------------------------
//   ULONG AACI_RegRead32(USHORT reg)
//
//   Reads 32 bits from the 5530/5540 I/O port
//-----------------------------------------------------------------------
ULONG AACI_RegRead32(USHORT reg)
{
    PULONG reg_loc;
    ULONG val;

    reg_loc  = (PULONG)(g_AudioRegBase + reg);
    val      = *reg_loc;
    return( val );
}


// -----------------------------------------------------------------------------
// Clear FIFO Functions
// -----------------------------------------------------------------------------

// Clear the FIFO by enabling transmit, waiting for it to empty then 
//  disabling transmit
static BOOL ClearTransmitFIFO()
{
    DWORD dwStatus, dwCount = 0;

    // Make sure FIFO is enabled
    AACI_RegWrite32( AACIReg_Channel1TxControl, 
                     AACI_RegRead32(AACIReg_Channel1TxControl) | 
                     AACIBit_EnableFIFO );
    Sleep(10);
    
    // Wait till not busy
    dwStatus = AACI_RegRead32(AACIReg_Channel1Status);
    while( (dwCount < 10) && (dwStatus & AACIBit_TXFIFOBusy) )
    {
        // Check for any flagged interrupts (and clear them if need be)
        if( (dwStatus & AACIBit_TXUnderrun) && !(dwStatus & AACIBit_TXFIFOEmpty) )
        {
            ERRMSG("Underrun occurred (FIFO not empty)");
            AACI_RegWrite32( AACIReg_IntClear, AACIBit_TxUEC1 );
        }
        Sleep(50);
        dwStatus = AACI_RegRead32(AACIReg_Channel1Status);
        dwCount++;
    } 

    // Disable FIFO and clear interrupts
    AACI_RegWrite32( AACIReg_Channel1TxControl, 
                     AACI_RegRead32(AACIReg_Channel1TxControl) & 
                     ~(AACIBit_EnableFIFO) );
    AACI_RegWrite32( AACIReg_IntClear, AACIBit_TxUEC1 );

    // Had to quit out of busy loop?
    if( dwCount == 10 )
    {
        WRNMSG2("ClearTransmitFIFO: WARNING! count=%d, status=0x%04x", 
                dwCount, AACI_RegRead32(AACIReg_Channel1Status));
        return FALSE;
    }    

    return TRUE;
}

// Clear the FIFO by reading the received data
static BOOL ClearReceiveFIFO( DWORD *pdwDataRead )
{
    DWORD dwData, dwCount = 0; // dwStatus, dwNewStatus;

    // Make sure FIFO disabled and clear interrupts
    AACI_RegWrite32( AACIReg_Channel1RxControl, 
                     AACI_RegRead32(AACIReg_Channel1RxControl) & 
                     ~(AACIBit_EnableFIFO) );
    AACI_RegWrite32( AACIReg_IntClear, AACIBit_RxTOFEC1 | AACIBit_RxOEC1 );
    
    // Read all the data in the FIFO
    // (NOTE: Do not use RX_FIFOSIZE as we may be called from the Test API in 
    //  different modes)
    while( !(AACI_RegRead32(AACIReg_Channel1Status) & AACIBit_RXFIFOEmpty) && 
           dwCount < (RX_FIFOSIZE_NOTCOMPACT*2) )
    {
        dwData = AACI_RegRead32( AACIReg_Channel1FIFO );
        dwCount++;        
    }

    // Return bytes read if we are given something to put them in
    if( pdwDataRead ) *pdwDataRead = dwCount;

    // Did something go wrong? (usually means that there is incoming data 
    //  held in slots, we can ignore this)
    if( dwCount == (RX_FIFOSIZE_NOTCOMPACT*2) || 
        (AACI_RegRead32(AACIReg_Channel1Status) & AACIBit_RXFIFOBusy) )
    {
        WRNMSG2("ClearReceiveFIFO: WARNING! read=%d, status=0x%04x", dwCount, 
                AACI_RegRead32(AACIReg_Channel1Status));
        return FALSE;
    }

    return TRUE;
}


#ifdef DEBUG
//-----------------------------------------------------------------------
// Debug information
//-----------------------------------------------------------------------

#define PRINT_STEREO_VOLUME(m,v) \
    PRINTMSG( ZONE_INIT, \
        (TEXT("%21s = 0x%04x (Mute = %d, Left = 0x%03x, Right = 0x%03x)\n"), \
            TEXT(m), v, (v & LM4549A_BIT_VOLUME_MUTE) != 0, (v >> 8) & 0x3F, \
            v & 0x3F) )

#define PRINT_MONO_VOLUME(m,v) \
    PRINTMSG( ZONE_INIT, \
        (TEXT("%21s = 0x%04x (Mute = %d, Mono = 0x%03x)\n"), \
            TEXT(m), v, (v & LM4549A_BIT_VOLUME_MUTE) != 0, v & 0x3F) )

#define PRINT_SETTING(m,s) \
    PRINTMSG( ZONE_INIT, \
        (TEXT("%21s = 0x%04x\n"), TEXT(m), s) )

static void DumpCurrentSettings()
{
    USHORT codec_data;

    codec_data = AACI_CodecRead16( LM4549A_RESET );
    PRINT_SETTING( "Reset", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_MASTER_VOLUME );
    PRINT_STEREO_VOLUME( "Master volume", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_LINE_LEV_OUT_VOL );
    PRINT_STEREO_VOLUME( "Line Level out volume", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_MASTER_VOLUME_MONO );
    PRINT_MONO_VOLUME( "Master Mono volume", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_PC_BEEP_VOLUME );
    PRINTMSG( ZONE_INIT, (TEXT("%21s = 0x%04x (Mute = %d, Mono = 0x%02x)\n"), 
        TEXT("PC Beep volume"), codec_data, 
        (codec_data & LM4549A_BIT_VOLUME_MUTE) != 0, (codec_data>>1) & 0xF) );

    codec_data = AACI_CodecRead16( LM4549A_PHONE_VOLUME );
    PRINT_MONO_VOLUME( "Phone volume", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_MIC_VOLUME );
    PRINTMSG( ZONE_INIT, (TEXT("%21s = 0x%04x (Mute = %d, Gain = %d, Mono = 0x%03x)\n"), 
        TEXT("Mic volume"), codec_data, 
        (codec_data & LM4549A_BIT_VOLUME_MUTE) != 0, 
        (codec_data & LM4549A_BIT_VOLUME_GAIN) != 0, codec_data & 0x1F) );

    codec_data = AACI_CodecRead16( LM4549A_LINE_IN_VOLUME );
    PRINT_STEREO_VOLUME( "Line in volume", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_CD_VOLUME );
    PRINT_STEREO_VOLUME( "CD volume", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_VIDEO_VOLUME );
    PRINT_STEREO_VOLUME( "Video volume", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_AUX_VOLUME );
    PRINT_STEREO_VOLUME( "AUX volume", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_PCM_OUT_VOL );
    PRINT_STEREO_VOLUME( "PCM out volume", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_RECORD_SELECT );
    PRINTMSG( ZONE_INIT, (TEXT("%21s = 0x%04x (Left = 0x%02x, Right = 0x%02x)\n"), 
        TEXT("Record Select"), codec_data, (codec_data >> 8) & 0x7, 
        codec_data & 0x7) );

    codec_data = AACI_CodecRead16( LM4549A_RECORD_GAIN );
    PRINTMSG( ZONE_INIT, (TEXT("%21s = 0x%04x (Mute = %d, Left = 0x%02x, Right = 0x%02x)\n"), 
        TEXT("Record Gain"), codec_data, 
        (codec_data & LM4549A_BIT_VOLUME_MUTE) != 0, (codec_data >> 8) & 0xF, 
        codec_data & 0xF) );

    codec_data = AACI_CodecRead16( LM4549A_GENERAL_PURPOSE );
    PRINT_SETTING( "General Purpose", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_3D_CONTROL );
    PRINT_SETTING( "3D Control", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_POWERDOWN_CTRL_STAT );
    PRINT_SETTING( "Powerdown Status", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_EXT_AUDIO_ID );
    PRINT_SETTING( "Extended Audio ID", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_EXT_AUDIO_CTRL_STAT );
    PRINT_SETTING( "Extended Audio Status", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_PCM_FRONT_DAC_RATE );
    PRINT_SETTING( "PCM Front DAC Rate", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_PCM_ADC_RATE );
    PRINT_SETTING( "PCM ADC Rate", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_VENDOR_ID1 );
    PRINT_SETTING( "Vendor ID1", codec_data );

    codec_data = AACI_CodecRead16( LM4549A_VENDOR_ID2 );
    PRINT_SETTING( "Vendor ID2", codec_data );
}
#endif // DEBUG

#ifdef TEST_API
// -----------------------------------------------------------------------------
// Test Functions
// -----------------------------------------------------------------------------

#define TESTWAIT_TRANSMIT   5000
#define TESTWAIT_RECEIVE    5000

#define PAUSE   Sleep(100)


DWORD TestTransmit( DWORD uMsg )
{
    DWORD dwTest;
    DWORD dwTXCtrl, dwTXSize;
    DWORD dwRet = MMSYSERR_NOERROR, dwResult;

    RETAILMSG( TRUE, (TEXT("TestTransmit v0.5\n")) );

    if( !g_fInUse[WAPI_OUT] )
    {
        RETAILMSG( TRUE, (TEXT("TestTransmit_xxx: ERROR - WaveOut channel should have been opened\n")) );
        return MMSYSERR_ERROR;
    }

    if( g_fInUse[WAPI_IN] )
    {
        // We need to take over the whole AACI so we need both channels
        RETAILMSG( TRUE, (TEXT("TestTransmit_xxx: ERROR - WaveIn channel in use\n")) );
        return MMSYSERR_ERROR;
    }

    g_fTesting = TRUE;
    g_fInUse[WAPI_IN] = TRUE;   // Stop anyone else using the record channel 
                                //  whilst we are testing playback
    g_fTestIntDisable = TRUE;   // Assume we don't want interrupts to continue 
                                //  after the first one

    // Reset device to get into known state
    ResetDevice();

    dwTXCtrl = AACIBit_Slot3DataInFIFO | AACIBit_Slot4DataInFIFO | 
                AACIBit_EnableFIFOMode;

    // Set output rate to 8KHz
    AACI_CodecWrite16( LM4549A_PCM_FRONT_DAC_RATE, 8000 );

    // Disable AACI and then Transmit & Receive FIFOs
    PAUSE;
    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: ")) );
            dwTXSize = AACIBit_DataSize16bits;
            break;
        case 1:
            RETAILMSG( TRUE, (TEXT("Data size 12 bits: ")) );
            dwTXSize = AACIBit_DataSize12bits;
            break;
        case 2:
            RETAILMSG( TRUE, (TEXT("Data size 18 bits: ")) );
            dwTXSize = AACIBit_DataSize18bits;
            break;
        case 3:
            RETAILMSG( TRUE, (TEXT("Data size 20 bits: ")) );
            dwTXSize = AACIBit_DataSize20bits;
            break;
        case 4:
            RETAILMSG( TRUE, (TEXT("Data size 16 bits compact: ")) );
            dwTXSize = AACIBit_DataSize16bits | AACIBit_EnableCompactMode;
            break;
        case 5:
            RETAILMSG( TRUE, (TEXT("Data size 12 bits compact: ")) );
            dwTXSize = AACIBit_DataSize12bits | AACIBit_EnableCompactMode;
            break;
        }
        // Set up Transmit FIFO (Disable AACI whilst changing transmit size 
        //  and compact mode)
        AACI_RegWrite32( AACIReg_MainControl, 0 );
        AACI_RegWrite32( AACIReg_Channel1TxControl, dwTXCtrl | dwTXSize );
        AACI_RegWrite32( AACIReg_Channel1IntEnable, 0 );
        PAUSE;
        AACI_RegWrite32( AACIReg_MainControl, AACIBit_Enable );

        // Clear the event of any previous interrupts
        ResetEvent( g_hTestInterrupt );

        switch (uMsg)
        {
            case TESTTX_FIFOSIZE:
                dwResult = TestTransmit_FIFOSize( (dwTest < 4) );
                break;
            case TESTTX_COMPLETE:
                dwResult = TestTransmit_Complete( (dwTest < 4) );
                break;
            case TESTTX_HALFEMPTY:
                dwResult = TestTransmit_HalfEmpty( (dwTest < 4) );
                break;
            default:
                RETAILMSG(TRUE, (TEXT("TestTransmit: Unsupported test %d\n"), 
                        uMsg) );
                dwResult = MMSYSERR_ERROR;
        }
        if( dwResult != MMSYSERR_NOERROR ) dwRet = dwResult;

        // Check for error?
        if( !ClearTransmitFIFO() )
        {
            RETAILMSG(TRUE, (TEXT("TestTransmit: WARNING - problems clearing FIFO after test\n")) );
        }
    }

    CloseHandle( g_hTestInterrupt );

    // Clean up
    ResetDevice();
    AACI_SetVolume(g_nVolume);

    g_fInUse[WAPI_IN] = FALSE;
    g_fTesting = FALSE;

    return dwRet;
}

static DWORD TestTransmit_FIFOSize( BOOL fNotCompact )
{
    DWORD dwCount = 0;

    // Fill up FIFO!
    while( !(AACI_RegRead32( AACIReg_Channel1Status ) & AACIBit_TXFIFOFull) && 
           dwCount <= TX_FIFOSIZE_NOTCOMPACT )
    {
        // Left Channel (or both when compact enabled)
        AACI_RegWrite32( AACIReg_Channel1FIFO, 0 );
        dwCount++;

        // Right Channel (when not compact)
        if( fNotCompact )
        {
            AACI_RegWrite32( AACIReg_Channel1FIFO, 0 );
            dwCount++;
        }
    }

    if( ((fNotCompact && dwCount == TX_FIFOSIZE_NOTCOMPACT) || 
         (!fNotCompact && dwCount == TX_FIFOSIZE_COMPACT)) &&
         (AACI_RegRead32( AACIReg_Channel1Status ) & AACIBit_TXFIFOFull) )
    {
        RETAILMSG( TRUE, (TEXT("PASS\n")) );
        return MMSYSERR_NOERROR;
    }

    RETAILMSG( TRUE, (TEXT("FAIL (size=%d)\n"),dwCount) );
    return MMSYSERR_ERROR;
}


⌨️ 快捷键说明

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