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

📄 aaci_audio.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		//yz_change for DMA
            //(*pfnFillFIFO)(pwh);
		
		//Disable Tx Interrupt	
		 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 );
            }
			
        }
        else // (apidir == WAPI_IN)
        {
            TESTMSG("AACI_WaveContinue: WAPI_IN");
            (*pfnGetFIFO)(pwh);

            // Clear any receive overruns now we have emptied the FIFO
            if( AACI_RegRead32( AACIReg_Channel1Status ) & AACIBit_RXOverrun )
            {
                TESTMSG("AACI_WaveContinue: Receive Overrun - too slow!");
                AACI_RegWrite32( AACIReg_IntClear, AACIBit_RxOEC1 );
            }
        }
    }
#endif			
}

//-------------------------------------------------------
// VOID AACI_WaveEndOfData(WAPI_INOUT apidir)
//
//  Signals we have no more data to play 
//   (only called for WAPI_OUT).
//-------------------------------------------------------
VOID AACI_WaveEndOfData(WAPI_INOUT apidir)
{
#if 0
    FUNC_WPDD("+AACI_WaveEndOfData");

	RETAILMSG( yz_debug, (TEXT("AACI_WaveEndOfData()\r\n")));	
    if( apidir == WAPI_OUT )
    {
        g_fTxEndOfData = TRUE;

        // Once we get this, we won't be given any more data to play
        gv_fMoreData[WAPI_OUT] = FALSE;

        // Cause one final interrupt to make the driver return a STOPPED status
		DmaCmd = DMA_CMD_STOP;
        SetEvent( hAudioInterrupt );
    }
    
    FUNC_WPDD("-AACI_WaveEndOfData");
#endif
}

//-------------------------------------------------------
// VOID AACI_WaveStop(WAPI_INOUT apidir)
//
//  Stops the wave stream.
//-------------------------------------------------------
VOID AACI_WaveStop(WAPI_INOUT apidir)
{
	//FILE *f_in;
    FUNC_WPDD("+AACI_WaveStop");

	//RETAILMSG(yz_debug, (TEXT("AACI_WaveStop()\r\n")));
    // No more data to play
    gv_fMoreData[apidir] = FALSE;

    if( g_dwRunMode[apidir] != RUNMODE_STOPPED )
    {
        g_dwRunMode[apidir] = RUNMODE_STOPPED;

        if( apidir == WAPI_OUT )
        {
			OnPlayStop();
        	//yz_change for DMA
        /*	
            // Disable the AACI Transmit interrupts
            AACI_RegWrite32( AACIReg_Channel1IntEnable, 
                            AACI_RegRead32( AACIReg_Channel1IntEnable ) & 
                            ~(AACIBit_TxCIE | AACIBit_TxIE | AACIBit_TxUIE) );
*/
/*
				//yz_add for test
				f_in = fopen("\\windows\\hello_world.wav", "rb");				
				if(f_in == NULL)
					RETAILMSG(1, (TEXT("PDD_DMAThread() - file open FAILED!\r\n")));
				
				if((fread(total_buf, sizeof( char ), 200000, f_in)) != 200000)
					RETAILMSG(1, (TEXT("PDD_DMAThread() - file read Error! %d\r\n")));
				
				MMC_StartDMA(2, 0x10004090, total_buf, 200000);

				fclose(f_in);
				
				RETAILMSG(1, (TEXT("AACI_WaveStop(): File read done!\r\n")));
*/				
            if( !ClearTransmitFIFO() )
            {
                ERRMSG("AACI_WaveStop: Failed to clear Transmit FIFO");
            }

			RETAILMSG( 1 , (TEXT("aaci : stop\r\n")));
        }
        else // (apidir == WAPI_IN)
        {
            BOOL fCleared;
            
            // Disable the AACI Receive interrupts
            AACI_RegWrite32( AACIReg_Channel1IntEnable, 
                            AACI_RegRead32( AACIReg_Channel1IntEnable ) & 
                            ~(AACIBit_RxIE | AACIBit_RxOIE | 
                              AACIBit_RxTIE | AACIBit_RxTOIE) );

            // Clear the receive FIFO
            fCleared = ClearReceiveFIFO(NULL);

            if( !fCleared )
            {
                ERRMSG("AACI_WaveStop: Failed to clear Receive FIFO");
            }
			OnRecordStop();
        }
    }

    FUNC_WPDD("-AACI_WaveStop");
}

// -----------------------------------------------------------------------------
//  VOID AACI_Standby (WAPI_INOUT apidir)
//
//   Called between playing sounds to save power
// -----------------------------------------------------------------------------
VOID AACI_Standby(WAPI_INOUT apidir)
{
    FUNC_WPDD("+AACI_Standby");

	// Make sure we have stopped
    AACI_WaveStop(apidir);


    if( (g_dwRunMode[WAPI_OUT] == RUNMODE_STOPPED) && 
        (g_dwRunMode[WAPI_IN] == RUNMODE_STOPPED) )
    {
        // Power down device
        PowerDown();
    }
	RETAILMSG( 1 , (TEXT("aaci : standby\r\n")));
    FUNC_WPDD("-AACI_Standby");
}

//---------------------------------------------------------
//  VOID AACI_Deinitialize(VOID)
//
//  This routine is called when the driver
//  is being unloaded. Free up memory, etc.
//---------------------------------------------------------
VOID AACI_Deinitialize(VOID)
{
    FUNC_WPDD("+AACI_Deinitialize");

    if( g_AudioRegBase )
    {
        // Disable AACI functionality
        AACI_RegWrite32( AACIReg_MainControl, 0 );

        // Unmap hardware register space
        MmUnmapIoSpace( g_AudioRegBase, AACI_HWREGS_SIZE );
    }
	OnDeinit();
    FUNC_WPDD("-AACI_Deinitialize");
}

//---------------------------------------------------------
//   ULONG AACI_GetVolume(VOID)
//
//   Returns the digital volume to the caller
//---------------------------------------------------------
ULONG AACI_GetVolume(VOID)
{
    MISC1("AACI_GetVolume: 0x%08x", g_nVolume);

    return g_nVolume;
}

//---------------------------------------------------------
//   VOID AACI_SetVolume(ULONG)
//
//   Sets the digital volume based on the value sent by the caller
//---------------------------------------------------------
VOID AACI_SetVolume(ULONG Vol)
{
    USHORT rVol, lVol, codecVol;
    UCHAR rIdx, lIdx;

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

    // Convert to CODEC volume range
    // NOTE: Swap L & R as output is reversed on Versatile
    lVol = VolumeLUT[rIdx];
    rVol = VolumeLUT[lIdx];

    // 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 )
        codecVol = LM4549A_BIT_VOLUME_MUTE;

    MISC2("AACI_SetVolume: MSFT:0x%08x, CODEC:0x%04x", Vol, codecVol);
    
    AACI_CodecWrite16( LM4549A_MASTER_VOLUME, codecVol );
}

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

⌨️ 快捷键说明

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