hwctxt.cpp

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

CPP
1,746
字号
        
    UINT32 OutputTransferred;
    
    if(!m_OutputDMARunning)
    {
        //----- 1. Initialize our buffer counters -----
        // For now, pretend output dma is running in case we accidentally get reentered
        m_OutputDMARunning=TRUE;
        m_OutBytes[0] = 0;
        m_OutBytes[1] = 0;
        m_TxBufIndex = 0;

	    Lock();        
        //----- 2. Prime the output buffer with sound data -----        
	//RETAILMSG(1, (TEXT("SDMA+\r\n")));
        OutputTransferred = TransferOutputBuffers();    
        OutputTransferred += TransferOutputBuffers();        
	//RETAILMSG(1, (TEXT("SDMA-\r\n")));
        
        Unlock();
              
        //----- 3. If we did transfer any data to the DMA buffers, go ahead and enable DMA -----
        if(OutputTransferred)
        {
            //----- 4. Configure the channel for playback -----
            DDKDmacSetSrcAddress(m_OutputDMAChan, m_DmaTxBuffer[0]);
            DDKDmacSetRepeatType(m_OutputDMAChan, DMAC_REPEAT_FOREVER);
            DDKDmacEnableChannelIntr(m_OutputDMAChan);

            //----- 5. Make sure the audio isn't muted -----
            //AudioMute(AUDIO_CH_OUT, FALSE);                 

            //----- 6. Start the DMA controller -----
            DDKDmacClearChannelIntr(m_OutputDMAChan);
            DDKDmacStartChan(m_OutputDMAChan);
            //InterruptDone(m_dwSysintrOutput);
            
            //UINT32 status;
            //status = ClearInterruptStatus(SSI_TRANSFER_TX, SSI_CHANNEL0);

           // call back BSP function to enable the output
            BSPAudioStartOutput(AUDIO_BUS_STEREO_OUT, AUDIO_PATH_HEADSET);
           
            // Wait for DMA to start
            while(DDKDmacGetTransSize(m_OutputDMAChan) == 0);
            // Set DMA for next buffer
			
            DDKDmacSetSrcAddress(m_OutputDMAChan, m_DmaTxBuffer[1]);

            //DEBUGMSG(1, (TEXT("Output DMA transferred: %d\r\n"),
                           //     DDKDmacGetTransSize(m_OutputDMAChan)));
        }
        else    // We didn't transfer any data, so DMA wasn't enabled
        {
            m_OutputDMARunning = FALSE;
        }
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("-StartOutputDMA\r\n")));
    return TRUE;
}


//-----------------------------------------------------------------------------
//
//  Function:  StopOutputDMA
//
//  This function stops any DMA activity on the output channel.
//
//  This function can only be called after Lock() has already been called. A
//  matching Unlock() call must also be made after this function has finished.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
void HardwareContext::StopOutputDMA()
{
    DEBUGMSG(ZONE_FUNCTION ,(_T("+HardwareContext::StopOutputDMA\n")));
    
	if(m_OutputDMARunning)
    {
       // BSPAudioStartOutput(FALSE);

         // Disable the speaker, Stereo DAC, and the audio MUX.
        BSPAudioStopOutput(AUDIO_BUS_STEREO_OUT, AUDIO_PATH_HEADSET);

        DDKDmacDisableChannelIntr(m_OutputDMAChan);
        DDKDmacStopChan(m_OutputDMAChan);
        DDKDmacClearChannelIntr(m_OutputDMAChan);

        m_OutputDMARunning = FALSE;

        DEBUGMSG(ZONE_MISC, (TEXT("Stopped output DMA\r\n")));
    }


    DEBUGMSG(ZONE_FUNCTION,(_T("-HardwareContext::StopOutputDMA\n")));
}


#ifdef AUDIO_RECORDING_ENABLED

//-----------------------------------------------------------------------------
//
//  Function:  InitInputDMA
//
//  This function initializes the DMA channel for input.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL HardwareContext::InitInputDMA()
{	
    BOOL rc = FALSE;

    //TODO: Replace the DMAC_TRANSFER_SIZE with appropriate macro name
    //when changed in mx27_ddk.h

    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::InitInputDMA\r\n")));

    // Check if DMA buffer has been allocated
    if (!g_PhysDMABufferAddr.LowPart)
    {
        ERRORMSG(ZONE_ERROR, (_T("Invalid DMA buffer physical address.\r\n")));
        goto cleanUp;
    }
	
	// Configure the platform-specific output DMA channel
    if (!BSPAudioInitInput(AUDIO_BUS_VOICE_IN, m_DmaRxBuffer[0], AUDIO_DMA_PAGE_SIZE))
    {
        ERRORMSG(ZONE_ERROR, (_T("BSPAudioInitOutput failed.\r\n")));
        goto cleanUp;
    }

    rc = TRUE;

cleanUp:
    if (!rc)
    {
        DeinitInputDMA();
    }

    DEBUGMSG(ZONE_FUNCTION,(_T("-HardwareContext::InitInputDMA\r\n")));

    return rc;
}


//-----------------------------------------------------------------------------
//
//  Function:  DeinitInputDMA
//
//  This function deinitializes the DMA channel for input.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL HardwareContext::DeinitInputDMA()
{    
    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::DeinitInputDMA\n")));

    // Stop the audio input devices
    BSPAudioStopInput(AUDIO_BUS_VOICE_IN, AUDIO_PATH_MIC);
    
    DDKDmacStopChan(m_InputDMAChan);
    DDKDmacReleaseChan(m_InputDMAChan);
    DDKDmacClearChannelIntr(m_InputDMAChan);

    DEBUGMSG(ZONE_FUNCTION,(_T("-HardwareContext::DeinitInputDMA\n")));

    return TRUE;
}


//-----------------------------------------------------------------------------
//
//  Function:  StartInputDMA
//
//  This function starts inputting the sound data from the audio codec
//  chip via the DMA.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL HardwareContext::StartInputDMA()
{

    BOOL rc = FALSE;

    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::StartInputDMA\r\n")));

    // Must acquire critical section Lock() here so that we don't have a race
    // condition with StopInputDMA() and the interrupt handler.
    Lock();

    // Terminate the existing record CODEC disable timer since we're about
    // to start another recording operation.
    if (m_AudioDelayDisableTimerID[1] != NULL)
    {
        timeKillEvent(m_AudioDelayDisableTimerID[1]);
        m_AudioDelayDisableTimerID[1] = NULL;
    }

    // Reinitialize audio input if it is not already active.
    if(!m_InputDMARunning)
    {
        //----- 1. Initialize our buffer counters -----
        // For now, pretend input dma is running in case we accidentally get reentered
        m_InputDMARunning = TRUE;
        m_InBytes[0] = 0;
        m_InBytes[1] = 0;
		m_RxBufIndex = 0;

        //----- 2. Configure the channel for record -----
         //TODO: Define the channel number appropriately for m_DmaRxChannel
        DDKDmacSetRepeatType(m_InputDMAChan, DMAC_REPEAT_FOREVER);
        DDKDmacSetDestAddress(m_InputDMAChan, m_DmaRxBuffer[0]);

        //----- 3. Make sure the audio isn't muted -----
        //AudioMute(AUDIO_CH_IN, FALSE);                  

        //----- 4. Start the input DMA -----
        DDKDmacClearChannelIntr(m_InputDMAChan);
        DDKDmacStartChan(m_InputDMAChan);
        DDKDmacEnableChannelIntr(m_InputDMAChan);

        //InterruptDone(m_dwSysintrInput);

        BSPAudioStartInput(AUDIO_BUS_VOICE_IN, AUDIO_PATH_MIC);

        // Wait for DMA to start
        while(DDKDmacGetTransSize(m_InputDMAChan) == 0);
        // Set DMA for next buffer
        DDKDmacSetDestAddress(m_InputDMAChan, m_DmaRxBuffer[1]);
        
        DEBUGMSG(ZONE_MISC, (TEXT("Started input DMA\r\n")));

    }

    rc = TRUE;

//START_ERROR:
    Unlock();

    DEBUGMSG(ZONE_FUNCTION,(TEXT("-HardwareContext::StartInputDMA\r\n")));
    
    return rc;
}


//-----------------------------------------------------------------------------
//
//  Function:  StopInputDMA
//
//  This function stops any DMA activity on the input channel.
//
//  This function can only be called after Lock() has already been called. A
//  matching Unlock() call must also be made after this function has finished.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
void HardwareContext::StopInputDMA()
{
    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::StopInputDMA\n")));

    // If the input DMA is running, stop it
   if(m_InputDMARunning)
    {
        BSPAudioStopInput(AUDIO_BUS_VOICE_IN, AUDIO_PATH_MIC);

        DDKDmacDisableChannelIntr(m_InputDMAChan);
        DDKDmacStopChan(m_InputDMAChan);
        DDKDmacClearChannelIntr(m_InputDMAChan);

        //AudioMute(AUDIO_CH_IN, TRUE);       
        
        m_InputDMARunning = FALSE;

        DEBUGMSG(ZONE_MISC, (TEXT("Stopped input DMA\r\n")));
        
    }

    DEBUGMSG(ZONE_FUNCTION,(_T("-HardwareContext::StopInputDMA\n")));
}

#endif // #ifdef AUDIO_RECORDING_ENABLED


//-----------------------------------------------------------------------------
//
//  Function:  GetInterruptThreadPriority
//
//  This function attempts to retrieve the thread priority for the audio
//  IST from the registry and supplies a default priority if one is not
//  found.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns thread priority for the audio IST.
//
//-----------------------------------------------------------------------------
DWORD HardwareContext::GetInterruptThreadPriority()
{
    HKEY hDevKey;
    DWORD dwValType;
    DWORD dwValLen;
    DWORD dwPrio = INTR_PRIORITY; // Default IST priority

    hDevKey = OpenDeviceKey((LPWSTR)m_dwDriverIndex);
    if (hDevKey)
    {
        dwValLen = sizeof(DWORD);
        RegQueryValueEx(
            hDevKey,
            INTR_PRIORITY_REGKEY,
            NULL,
            &dwValType,
            (PUCHAR)&dwPrio,
            &dwValLen);
        RegCloseKey(hDevKey);
    }

    return dwPrio;
}


//-----------------------------------------------------------------------------
//
//  Function:  InitInterruptThread
//
//  This function initializes the IST for handling DMA interrupts.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL HardwareContext::InitInterruptThread()
{
    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::InitInterruptThread\n")));

    // Create an automatic reset, unsignaled, and unnamed event for IST
    // signaling.
    m_hAudioInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);

    // Check if event creation suceeded
    if (!m_hAudioInterrupt)
    {
        ERRMSG("Unable to create audio interrupt event");
        return(FALSE);
    }

    // Register the audio driver interrupts.
    if (m_pSSI2)
    {
        if (! InterruptInitialize(m_dwSysintrOutput, m_hAudioInterrupt, NULL, 0))
        {
            ERRMSG("Unable to initialize audio input interrupt for SSI1");
            return FALSE;
        }

        // Mask SSI1 interrupts. DMA transfer interrupts are used to signal
        // the Interrupt Service Thread (IST).
        
        //InterruptMask(m_dwSysintrOutput, TRUE);
    }

    if (m_pSSI1)
    {
        if (! InterruptInitialize(m_dwSysintrInput, m_hAudioInterrupt, NULL, 0))
        {
            ERRMSG("Unable to initialize audio output interrupt for SSI2");
            return FALSE;
        }

        // Mask SSI2 interrupts. DMA transfer interrupts are used to signal
        // the Interrupt Service Thread (IST).
        //InterruptMask(m_dwSysintrInput, TRUE);
    }
 
 
    // Create the Interrupt Service Thread (IST).
    m_hAudioInterruptThread =
        CreateThread((LPSECURITY_ATTRIBUTES)NULL,
                     0,
                     (LPTHREAD_START_ROUTINE)CallInterruptThread,
                     this,
                     0,
                     NULL);
    if (!m_hAudioInterruptThread)
    {
        ERRMSG("Unable to create audio interrupt event handling thread");
        return FALSE;
    }

    // Bump up the priority since the interrupt must be serviced immediately.
    CeSetThreadPriority(m_hAudioInterruptThread, GetInterruptThreadPriority());

    DEBUGMSG(ZONE_FUNCTION,(_T("-HardwareContext::InitInterruptThread\n")));

    return(TRUE);
}


//-----------------------------------------------------------------------------
//
//  Function:  PowerUp
//
//  This function powers up the audio codec chip.  Note that the audio CODEC
//  chip is ONLY powered up when the user wishes to play or record.  
//
//  Parameters:

⌨️ 快捷键说明

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