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

📄 aaci_audio_ok.c

📁 此压缩包为杰得开发得z228的BSP的源代码,可以实现很多功能,尤其是视频解码有很好的效果.
💻 C
📖 第 1 页 / 共 5 页
字号:
    return g_nVolume;
}
FILE* fp = NULL; // for test
//---------------------------------------------------------
//   VOID AACI_SetVolume(ULONG)
//
//   Sets the digital volume based on the value sent by the caller
//---------------------------------------------------------
#define DEFAULT_MINI_VOLUME 4
VOID AACI_SetVolume(ULONG Vol)
{
	USHORT rVol, lVol, codecVol;
	UCHAR rIdx, lIdx;

	g_nVolume = Vol;
	RETAILMSG( 0, (TEXT("Vol (size=%d)\n"),Vol) ); 

	// Extract top 5 MSBs from Left and Right channel volumes
	rIdx = (UCHAR)((Vol & 0xF8000000) >> (32 - 5));//高5位
	lIdx = (UCHAR)((Vol & 0x0000F800) >> (16 - 5));//中间五位 

	RETAILMSG( DBG_AACI, (TEXT("AACI_SetVolume()\r\n")));	
    
	// Convert to CODEC volume range
	// NOTE: Swap L & R as output is reversed on Versatile
	lVol = VolumeLUT[rIdx];//总共有32档2的5次方 --总共32档
	rVol = VolumeLUT[lIdx];//总共有32档2的5次方 --总共32档

	RETAILMSG( 0, (TEXT("lIdx (size=%d)\n"),lIdx) ); 
	RETAILMSG( 0, (TEXT("rIdx (size=%d)\n"),rIdx) ); 
	RETAILMSG( 0, (TEXT("lVol (size=%d)\n"),lVol) );
	RETAILMSG( 0, (TEXT("rVol (size=%d)\n"),rVol) );

	// Create CODEC data packet
    codecVol = (rVol) | (lVol << 8);//写声卡寄存器

	// Check for mute volume setting on both channels, and convert to 
	//  complete mute
	if ( codecVol == LM4549A_MUTEVOL_RL )//这个成立则对应 LOUT2/ROUT2  VOL =100000--这种情况衰减倍数太多基本就没有输出,所以可以直接关掉
		codecVol = LM4549A_BIT_VOLUME_MUTE;

	MISC2("AACI_SetVolume: MSFT:0x%08x, CODEC:0x%04x", Vol, codecVol);
	Volume = codecVol;
	//for test
	if(fp)
	{
		fprintf(fp, "AACI_SetVolume : Volume = 0x%x Vol = 0x%x, rIdx = %u\n", Volume, Vol, rIdx);
		fflush(fp);
	}	

	//add junxz 调整到最小音量不为最大的bug
	//当音量小于一定的值时就关掉功放
	if(lIdx  < DEFAULT_MINI_VOLUME || rIdx < DEFAULT_MINI_VOLUME)
	{
		if(fp)
		{
			fprintf(fp, "to here\n");	
			fflush(fp);
		}
		AACI_CodecWrite16( 0x18, 0xe000 );
		//AACI_RegWrite32( AACIReg_Slot12Tx, 0x00000 );
		//AACI_RegWrite32( AACIReg_Slot12Tx, (AACI_CodecRead16(0x54)&(~0x07)) <<4);
		SET_SLOT12_FALSE;
	}
	else
	{
		if(lout&&playflags)
		{
			if(TRUE==leftout)
			{
				AACI_CodecWrite16( 0x18, 0xa000 );
			}
			else
			{
				AACI_CodecWrite16( 0x18, AACI_CodecRead16(0x18)|0x001d);
			}
			//AACI_RegWrite32( AACIReg_Slot12Tx, (AACI_CodecRead16(0x54)|0x07) <<4 );
			SET_SLOT12_TRUE;
		}
		else if(headphone&&playflags)
		{
			AACI_CodecWrite16( 0x18, 0x4000);
		}
	}

	if(lout&&playflags)//如果当前是用喇叭并且当前是在播放
		AACI_CodecWrite16( 0x02, Volume&0x7fff );//控制喇叭寄存器(通过0x02控制音量)
	else
		AACI_CodecWrite16( 0x02, Volume|0x8000 );//控制喇叭寄存器(通过0x02控制音量)

	if(headphone&&playflags)//如果当前是用耳机并且当前是在播放
		AACI_CodecWrite16( 0x04, Volume&0x7fff );//控制喇叭寄存器(通过0x02控制音量)
	else
		AACI_CodecWrite16( 0x04, Volume|0x8000 );//控制喇叭寄存器(通过0x02控制音量)
	
}

//---------------------------------------------------------
//   VOID AACI_LeftSound(WAPI_INOUT)
//
//   Sets WAPI_OUT or WAPI_IN to set left speaker on or off 
//---------------------------------------------------------
void AACI_LeftSound(WAPI_INOUT apidir)
{
	if((WAPI_OUT == apidir)&&(headphone!=TRUE))
	{
		leftout = FALSE;
		AACI_CodecWrite16(0x02, AACI_CodecRead16(0x02)|0x001f);
		RETAILMSG( 0, (TEXT("AACI_LeftSound() -> OFF AACI_CodecRead16(0x18)=0x%x\r\n"), AACI_CodecRead16(0x18)) ); 
	}
	else if((WAPI_IN == apidir)&&(headphone!=TRUE))
	{
		leftout = TRUE;
		//AACI_CodecWrite16(0x02, AACI_CodecRead16(0x02)&(~0x001f)); // modify by he
		AACI_CodecWrite16(0x02, Volume);
		RETAILMSG( 0, (TEXT("AACI_LeftSound() -> ON  AACI_CodecRead16(0x18)=0x%x\r\n"), AACI_CodecRead16(0x18)) );		
	}
}

// -----------------------------------------------------------------------------
//
//   AUDIO_STATE AACI_GetInterruptType(VOID)
//
//   Called by the driver's ISR.
//   Returns the state of the stream being Played/Recorded.
// -----------------------------------------------------------------------------
AUDIO_STATE AACI_GetInterruptType(VOID)
{
    AUDIO_STATE asResult = AUDIO_STATE_IGNORE;
    ULONG ulStatus;
	
#ifdef TEST_API
    if( !g_fTesting )
    {
#endif
        ulStatus = AACI_RegRead32( AACIReg_Channel1IntStatus );

        // check WAPI_IN first
        if( g_dwRunMode[WAPI_IN] == RUNMODE_RUNNING )
        {
            if( gv_fMoreData[WAPI_IN] )
            {
                if( ulStatus & AACIBit_RxIE )
                {
                    asResult |= AUDIO_STATE_IN_RECORDING;
                }
                else if( AACI_RegRead32( AACIReg_Channel1Status ) & 
                         AACIBit_RXFIFOHalfFull )
                {
                    // No obvious interrupt, but channel status shows half 
                    //  full, so report recording
                    asResult |= AUDIO_STATE_IN_RECORDING;
                    
                    WRNMSG1("AACI_GetInterruptType: Receive status halffull but no interrupt!");
                }
            }
            else
            {
                // Signal end of recording
                asResult |= AUDIO_STATE_IN_STOPPED;
                g_dwRunMode[WAPI_IN] = RUNMODE_STOPPING;
#ifdef AACI_STATS
                MISC1( "AACI_GetInterruptType: Stopping receive - no more data (read %d bytes)", 
                        g_dwBytesRecorded[WAPI_IN] );
#endif
            }
        }
        else
        {
            if( ulStatus & (AACIBit_RxIE | AACIBit_RxOIE | 
                            AACIBit_RxTIE | AACIBit_RxTOIE) )
            {
                // Getting receive interrupts when not running - disable them
                VERBOSEMSG("AACI_GetInterruptType: Disabling Receive interrupts as not running");
                AACI_RegWrite32( AACIReg_Channel1IntEnable, 
                                AACI_RegRead32( AACIReg_Channel1IntEnable ) & 
                                ~(AACIBit_RxIE | AACIBit_RxOIE | 
                                  AACIBit_RxTIE | AACIBit_RxTOIE) );
            }
        }

        // check WAPI_OUT
        if( g_dwRunMode[WAPI_OUT] == RUNMODE_RUNNING )
        {
			//RETAILMSG( 1 , (TEXT("aaci : query interrupt \r\n")));
			//if( DmaCmd == DMA_CMD_START )
			asResult |= AUDIO_STATE_OUT_PLAYING;			
        }
        else
        {
            if( ulStatus & (AACIBit_TxCIE | AACIBit_TxIE | AACIBit_TxUIE) )
            {
                // Getting transmit interrupts when not running - disable them
                VERBOSEMSG("AACI_GetInterruptType: Disabling Transmit interrupts as not running");
                AACI_RegWrite32( AACIReg_Channel1IntEnable, 
                                 AACI_RegRead32( AACIReg_Channel1IntEnable ) & 
                                 ~(AACIBit_TxCIE | AACIBit_TxIE | AACIBit_TxUIE) );
            }
        }

#ifdef TEST_API
    }
    else
    {
        // Just TESTING... Save the interrupt status for the tests
        g_dwTestIntStatus = AACI_RegRead32( AACIReg_Channel1IntStatus );

        TESTMSG2("AACI_GetInterruptType: ints=0x%08x, status=0x%04x", 
                g_dwTestIntStatus, AACI_RegRead32(AACIReg_Channel1Status));

        // Disable any other interrupts (clears the interrupt status)
        if( g_fTestIntDisable ) AACI_RegWrite32( AACIReg_Channel1IntEnable, 0 );

        // Wake up any tests waiting for an interrupt
        SetEvent( g_hTestInterrupt );
    }
#endif

    return asResult;
}


// -----------------------------------------------------------------------------
// FIFO operations
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// Hardware (CODEC and AACI) operations
// -----------------------------------------------------------------------------

// Internal function to send raw data to the codec
static VOID CodecSend( ULONG raw_codec_reg, ULONG raw_codec_data )
{
    // First check that the AACISLxTX registers are empty
    TESTWAIT(!( AACI_RegRead32(AACIReg_SlotFlag) & 
               (AACIBit_Slot1TXEmpty | AACIBit_Slot2TXEmpty)), 
             "Slot1TXEmpty | Slot2TXEmpty")

    AACI_RegWrite32( AACIReg_Slot2Tx, raw_codec_data );
    AACI_RegWrite32( AACIReg_Slot1Tx, raw_codec_reg );

    // Pause so that slots can be transmitted
    Sleep(1);

    // Wait till slots 1&2 transmit complete
    TESTWAIT(AACI_RegRead32(AACIReg_SlotFlag) & 
             (AACIBit_Slot1TXBusy | AACIBit_Slot2TXBusy), 
             "Slot1TXBusy | Slot2TXBusy")

    // Pause here for the operation to complete on the CODEC, i.e. wait for 
    //  data to be returned or CODEC registers to be updated depending on 
    //  read or write
    Sleep(1);
}

//-----------------------------------------------------------------------
//
//  USHORT AACI_CodecRead16( USHORT codec_reg )
//
//  Reads data from the CODEC
//
//-----------------------------------------------------------------------
USHORT AACI_CodecRead16( USHORT codec_reg )
{
    // Tell the codec we are trying to read a register
    CodecSend( (((ULONG)codec_reg) << 12) | AACIBit_Slot1Tx_Read, (ULONG)0 );

    // Check if LM4549 has returned requested value
    TESTWAIT(!( AACI_RegRead32( AACIReg_SlotFlag ) & AACIBit_Slot2RXValid ), 
             "Slot2RXValid")

    return( (USHORT)(AACI_RegRead32( AACIReg_Slot2Rx ) >> 4) );
}

//-----------------------------------------------------------------------
//
//  void AACI_CodecWrite16( USHORT codec_reg, USHORT codec_data  )
//
//  Writes data to the CODEC
//
//-----------------------------------------------------------------------
VOID AACI_CodecWrite16( USHORT codec_reg, USHORT codec_data )
{
    CodecSend( (((ULONG)codec_reg) << 12), (((ULONG)codec_data) << 4) );
}

//-----------------------------------------------------------------------
//   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;
    }

⌨️ 快捷键说明

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