hwctxt.cpp

来自「i.mx27 soc for wince 6.0」· C++ 代码 · 共 1,746 行 · 第 1/4 页

CPP
1,746
字号
//      None.
//
//  Returns:
//      None
//
//-----------------------------------------------------------------------------
void HardwareContext::PowerUp()
{
    BSPAudioPowerUp(TRUE);

    // Restart the audio I/O operations that were suspended when PowerDown()
    // was called.
    if (g_saveOutputDMARunning)
    {
        StartOutputDMA();
    }
#ifdef AUDIO_RECORDING_ENABLED
    if (g_saveInputDMARunning)
    {
        StartInputDMA();
    }
#endif

    BSPAudioPowerUp(FALSE);

    m_audioPowerdown = FALSE;
}


//-----------------------------------------------------------------------------
//
//  Function:  PowerDown
//
//  This function powers down the audio codec chip.  If the input/output 
//  channels are muted, then this function powers down the appropriate
//  components of the audio codec chip in order to conserve battery power.
//
//  The PowerDown() method will power down the entire audio chip while the
//  PowerDown(const DWORD channel) allows for the independent powerdown of
//  the input and/or output components to allow a finer degree of control.
//
//  Parameters:
//      None.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
void HardwareContext::PowerDown()
{
    // Note that for this special case, we do not need to grab the critical
    // section via Lock() and Unlock() before calling StopOutputDMA() and
    // StopInputDMA(). The powerdown thread runs at a high enough priority
    // that all other threads will be blocked while it runs. Having the
    // Lock() and Unlock() calls here may actually cause potential race
    // condition problems during the shutdown process.
    //
    // Furthermore, we will not resume operation until the hardware is powered
    // up again. At that point the hardware and audio driver state will be
    // reinitialized again. So at this point, we can just go ahead and shut
    // everything down.

    // Manually set the timed delay disable events. This will explicitly
    // trigger any in-progress delays to immediately terminate.
    if (m_hAudioDelayDisableEvent[0] != NULL)
    {
        PulseEvent(m_hAudioDelayDisableEvent[0]);
    }
#ifdef AUDIO_RECORDING_ENABLED
    if (m_hAudioDelayDisableEvent[1] != NULL)
    {
        PulseEvent(m_hAudioDelayDisableEvent[1]);
    }
#endif

    // This tells the low-level PMIC driver to immediately terminate any
    // pending timer delays.
    BSPAudioPowerDown(FALSE);

    // Set this flag to allow special handling for the powerdown procedure.
    // The most important thing we want to avoid when powering down is using
    // any sort of timer or other type of delay mechanism. We need to bypass
    // anything like that and simply shutdown the hardware components when
    // performing a powerdown operation.
    m_audioPowerdown = TRUE;

    // Save state for correct powerup handling.
    g_saveOutputDMARunning = m_OutputDMARunning;
#ifdef AUDIO_RECORDING_ENABLED
    g_saveInputDMARunning  = m_InputDMARunning;
#endif

    // Request all active audio-related DMA channels to stop.
    StopOutputDMA();
#ifdef AUDIO_RECORDING_ENABLED
    StopInputDMA();
#endif

    // Request audio devices to power down.
    BSPAudioPowerDown(TRUE);
}


//-----------------------------------------------------------------------------
//----------------------------- Helper Functions ------------------------------
//-----------------------------------------------------------------------------

//############################################ Helper Functions #############################################
//------------------------------------------------------------------------------
//
//  FUNCTION:       TransferOutputBuffer
//
//  DESCRIPTION:    Actual function to transfer playback data from 
//                  the indicated buffer to DMA. 
//                  Called by TransferOutputBuffers
//
//  PARAMETERS:     
//                  bufIndex - index of playback buffer to empty
//
//  RETURNS:        
//                  Number of bytes transferred from buffer
//
//------------------------------------------------------------------------------
UINT32 HardwareContext::TransferOutputBuffer(UINT8 bufIndex)
{
    ULONG BytesTransferred = 0;

    UINT8 *pBufferStart = (UINT8 *)m_Output_pbDMA_PAGES[bufIndex];
    UINT8 *pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
    UINT8 *pBufferLast;

    __try
    {
        
        pBufferLast = m_OutputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd, NULL);        
        BytesTransferred = m_OutBytes[bufIndex] = pBufferLast-pBufferStart;

        // Enable if you need to clear the rest of the DMA buffer
        StreamContext::ClearBuffer(pBufferLast,pBufferEnd);
                   
        //if(BytesTransferred == 0)
        //    DmacSetRepeatType(m_DmaTxChannel, DMAC_REPEAT_DISABLED);
        //else
        if (BytesTransferred > 0)
            DDKDmacSetSrcAddress(m_OutputDMAChan, m_DmaTxBuffer[bufIndex]);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferOutputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
    }

    return BytesTransferred;
}
//------------------------------------------------------------------------------
//
//  FUNCTION:       TransferOutputBuffers
//
//  DESCRIPTION:    Calls TransferOutputBuffer to transfer data from 
//                  playback buffer to DMA. Also toggles the current
//                  buffer index to acheive double buffering. Stops
//                  output dma if nothing is transferred for 2 
//                  buffers consecutively.
//
//  PARAMETERS:     
//                  None
//
//  RETURNS:        
//                  Number of bytes transferred from buffer
//
//------------------------------------------------------------------------------
UINT32 HardwareContext::TransferOutputBuffers(void)
{
    UINT32 BytesTransferred = 0;
//  UINT32 DmaTransferred = 0;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+TransferOutputBuffers\r\n")));
    
    //DmaTransferred = DmacGetTransSize(m_DmaRxChannel);
    //RETAILMSG(1, (TEXT("DmaTransferred(%d).\r\n"), DmaTransferred));
    BytesTransferred += TransferOutputBuffer(m_TxBufIndex);    
    m_TxBufIndex = (m_TxBufIndex == 0)? 1 : 0;
    
    //for( DmaTransferred = 0; DmaTransferred < 1000000000; DmaTransferred++ );
    
       
    //RETAILMSG(1, (TEXT("HardwareContext::TransferOutputBuffers(%d).\r\n"), BytesTransferred));
    
    // If it was our interrupt, but we weren't able to transfer any bytes
    // (e.g. no full buffers ready to be emptied)
    // and all the output DMA buffers are now empty, then stop the output DMA
    if((m_OutBytes[0] + m_OutBytes[1] == 0) && (BytesTransferred == 0x00))
    {
       UINT32 status = DDKDmacGetTransStatus(m_OutputDMAChan);
       if ((status == DMAC_TRANSFER_STATUS_COMPLETE) || (status == DMAC_TRANSFER_STATUS_NONE))
       //if (status == DMAC_TRANSFER_STATUS_COMPLETE)
       {
		 if(m_OutputDMARunning)
         {                        
	        BSPAudioStopOutput(AUDIO_BUS_STEREO_OUT, AUDIO_PATH_HEADSET);            
		    DDKDmacStopChan(m_OutputDMAChan);            
            m_OutputDMARunning = FALSE;
         }
       }
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("-TransferOutputBuffers: BytesTransferred=%d\r\n"), BytesTransferred));

    return BytesTransferred;
}

#ifdef AUDIO_RECORDING_ENABLED
//------------------------------------------------------------------------------
//
//  FUNCTION:       TransferInputBuffer
//
//  DESCRIPTION:    Actual function to transfer received data from 
//                  DMA to the indicated receive buffer. 
//                  Called by TransferInputBuffers
//
//  PARAMETERS:     
//                  bufIndex - index of receive buffer to fill
//
//  RETURNS:        
//                  Number of bytes transferred to buffer
//
//------------------------------------------------------------------------------
UINT32 HardwareContext::TransferInputBuffer(UINT8 bufIndex)
{
    ULONG BytesTransferred = 0;

    UINT8 *pBufferStart = (UINT8 *)m_Input_pbDMA_PAGES[bufIndex];
    UINT8 *pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
    UINT8 *pBufferLast;

    __try
    {
        pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd, NULL);
        BytesTransferred = m_InBytes[bufIndex] = pBufferLast-pBufferStart;
        //DmacSetRepeatType(m_DmaRxChannel, DMAC_REPEAT_ONCE);
        DDKDmacSetDestAddress(m_InputDMAChan, m_DmaRxBuffer[bufIndex]);
        //DmacStartChan(m_DmaRxChannel);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferInputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
    }

    return BytesTransferred;
}
//------------------------------------------------------------------------------
//
//  FUNCTION:       TransferInputBuffers
//
//  DESCRIPTION:    Calls TransferInputBuffer to transfer data from 
//                  DMA to receive buffer. Also toggles the current
//                  buffer index to acheive double buffering. Stops
//                  input dma if nothing is transferred.
//
//  PARAMETERS:     
//                  None
//
//  RETURNS:        
//                  Number of bytes transferred to buffer
//
//------------------------------------------------------------------------------
UINT32 HardwareContext::TransferInputBuffers(void)
{
    UINT32 BytesTransferred = 0;
   // UINT32 DmaTransferred = 0;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+TransferInputBuffers\r\n")));
    
   // DmaTransferred = DmacGetTransSize(m_DmaRxChannel);
   // RETAILMSG(1, (TEXT("DmaTransferred(%d).\r\n"), DmaTransferred));

    BytesTransferred = TransferInputBuffer(m_RxBufIndex);
    m_RxBufIndex = (m_RxBufIndex == 0)? 1 : 0;
    
   // RETAILMSG(1, (TEXT("HardwareContext::TransferInputBuffers(%d).\r\n"), BytesTransferred));
    
    // If it was our interrupt, but we weren't able to transfer any bytes
    // (e.g. no empty buffers ready to be filled)
    // Then stop the input DMA
    if(BytesTransferred == 0)
    {
	   if (DDKDmacGetTransStatus(m_OutputDMAChan) & DMAC_TRANSFER_STATUS_COMPLETE)
		   if(m_InputDMARunning)
		   {
				BSPAudioStopInput(AUDIO_BUS_VOICE_IN, AUDIO_PATH_MIC);
		        DDKDmacStopChan(m_InputDMAChan);
		        m_InputDMARunning = FALSE;
		    }


    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("-TransferInputBuffers: BytesTransferred=%d\r\n"), BytesTransferred));
    return BytesTransferred;
}

#endif 


//------------------------------------------------------------------------------
//
//  FUNCTION:       InterruptThread
//
//  DESCRIPTION:    Interrupt service routine for playback and recording
//                  DMA interrupts
//
//  PARAMETERS:     
//                  None
//
//  RETURNS:        
//                  None
//
//------------------------------------------------------------------------------

void HardwareContext::InterruptThread()
{
#ifdef AUDIO_RECORDING_ENABLED
    UINT32 InputTransferred;
#endif

    UINT32 OutputTransferred;
    UINT32 intrMask;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+InterruptThread\r\n")));

    // Fast way to access embedded pointers in wave headers in other processes.
    SetProcPermissions((ULONG)-1);

    while(m_Initialized)
    {
        DEBUGMSG(ZONE_INTERRUPT, (TEXT("+WaitForSingleObject\r\n")));
        WaitForSingleObject(m_hAudioInterrupt, INFINITE);
        DEBUGMSG(ZONE_INTERRUPT, (TEXT("-WaitForSingleObject\r\n")));

        //----- 1. Grab the lock -----
        
        Lock();

        __try
        {
            //----- 2. Determine the interrupt source (input DMA operation or output DMA operation?) -----
            //----- NOTE:   Often, platforms use two separate DMA channels for input/output operations but
            //              have the OAL return SYSINTR_AUDIO as the interrupt source.  If this is the case,
            //              then the interrupt source (input or output DMA channel) must be determined in
            //              this step.

            intrMask = DDKDmacGetTransStatus(m_OutputDMAChan);
            
            if(intrMask != DMAC_TRANSFER_STATUS_NONE)
            {
                //----- 3. Acknowledge the DMA interrupt -----
                DDKDmacClearChannelIntr(m_OutputDMAChan);
                InterruptDone(m_dwSysintrOutput);
		        if ( (intrMask == DMAC_TRANSFER_STATUS_COMPLETE) && 
		  	        (m_OutputDMARunning == TRUE) )
                {
              	      OutputTransferred = TransferOutputBuffers();
                }
            }

#ifdef AUDIO_RECORDING_ENABLED

            intrMask = DDKDmacGetTransStatus(m_InputDMAChan);
          
            if(intrMask != DMAC_TRANSFER_STATUS_NONE)
            {
                //----- 3. Acknowledge the DMA interrupt -----
                DDKDmacClearChannelIntr(m_InputDMAChan);
                InterruptDone(m_dwSysintrInput);
                if((intrMask == DMAC_TRANSFER_STATUS_COMPLETE) && (m_InputDMARunning == TRUE))
                {                    
                    InputTransferred = TransferInputBuffers();                    
                 
                }
            }
#endif
	     
        }
        __except(EXCEPTION_EXECUTE_HANDLER) 
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:InterruptThread() - EXCEPTION: %d"), GetExceptionCode()));
        }

        //----- 10. Give up the lock ----- 
        Unlock();

    }  // while(TRUE)

    DEBUGMSG(ZONE_FUNCTION, (TEXT("-InterruptThread\r\n")));
}


//-----------------------------------------------------------------------------
//
//  Function:  CallInterruptThread
//
//  This function serves as a wrapper for the IST called within the hardware
//  context.
//
//  Parameters:
//      None.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
DWORD CALLBACK CallInterruptThread(HardwareContext *pHWContext)
{
    if (pHWContext != NULL)
    {
        pHWContext->InterruptThread();
    }
    else
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("CallInterruptThread() called with ")
                              TEXT("pHWContext == NULL\n")));
    }
	return 1;
}











⌨️ 快捷键说明

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