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

📄 hwctxt.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:


//-----------------------------------------------------------------------------
//
//  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_DriverIndex);
    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_pSSI1)
    {
        if (! InterruptInitialize(m_dwSysintrSSI1, m_hAudioInterrupt, NULL, 0))
        {
            ERRMSG("Unable to initialize audio input interrupt for SSI1");
            return FALSE;
        }

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

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

        // Mask SSI2 interrupts. SDMA transfer interrupts are used to signal
        // the Interrupt Service Thread (IST).
        InterruptMask(m_dwSysintrSSI2, 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:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
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 ------------------------------
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
//
//  Function:  TransferOutputBuffer
//
//  This function retrieves the next "mixed" audio buffer of data to DMA into 
//  the output channel.
//
//  Parameters:
//      NumBuf
//          [in] Output DMA page to be filled.
//
//  Returns:
//      Returns number of bytes placed into output buffer.
//
//-----------------------------------------------------------------------------
ULONG HardwareContext::TransferOutputBuffer(const PBYTE pBufferStart,
                                            const PBYTE pBufferEnd)
{
    ULONG BytesTransferred = 0;

    PBYTE pBufferLast;

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

        // Only mark the DMA buffer as being in use if some data was actually
        // transferred.
        if (BytesTransferred > 0)
        {
            // Enable if you need to clear the rest of the DMA buffer
            // TODO:
            // Probably want to do something better than clearing out remaining
            // buffer samples.  DC output by replicating last sample or
            // some type of fade out would be better.
            StreamContext::ClearBuffer(pBufferLast, pBufferEnd);
        }
    }
    __except(EXCEPTION_EXECUTE_HANDLER) 
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferOutputBuffer() - ")
                              TEXT("EXCEPTION: %d"), GetExceptionCode()));
    }

    return BytesTransferred;
}


//-----------------------------------------------------------------------------
//
//  Function:  TransferOutputBuffers
//
//  This function determines which output buffer (A or B) needs to be filled 
//  with sound data.  The correct buffer is then populated with data and ready 
//  to DMA to the output channel.
//
//  Parameters:
//      dwDCSR
//          [in] Current status of the output DMA.
//
//  Returns:
//      Returns number of bytes placed into the output buffers.
//
//-----------------------------------------------------------------------------
ULONG HardwareContext::TransferOutputBuffers(DWORD dwDCSR)
{
    ULONG BytesTransferred_A = 0;
    ULONG BytesTransferred_B = 0;

    if (dwDCSR & DMA_DONEA)
    {
        // DMA buffer A is free, try to refill it.
        BytesTransferred_A =
            TransferOutputBuffer(m_Output_pbDMA_PAGES[OUT_BUFFER_A],
                                 m_Output_pbDMA_PAGES[OUT_BUFFER_A] +
                                     AUDIO_DMA_PAGE_SIZE);
        if (BytesTransferred_A > 0)
        {
            m_OutputDMAStatus &= ~DMA_DONEA;
        }
    }

    if (dwDCSR & DMA_DONEB)
    {
        // DMA buffer B is free, try to refill it.
        //
        // Note that we can refill both DMA buffers at once if both DMA
        // buffers are free and there is sufficient data.
        //
        BytesTransferred_B =
            TransferOutputBuffer(m_Output_pbDMA_PAGES[OUT_BUFFER_B],
                                 m_Output_pbDMA_PAGES[OUT_BUFFER_B] +
                                     AUDIO_DMA_PAGE_SIZE);
        if (BytesTransferred_B > 0)
        {
            m_OutputDMAStatus &= ~DMA_DONEB;
        }
    }

    return BytesTransferred_A + BytesTransferred_B;
}


#ifdef AUDIO_RECORDING_ENABLED

//-----------------------------------------------------------------------------
//
//  Function:  TransferInputBuffer
//
//  This function retrieves the chunk of recorded sound data and inputs
//  it into an audio buffer for potential "mixing".
//
//  Parameters:
//      NumBuf
//          [in] Input DMA page to be filled.
//
//  Returns:
//      Returns number of bytes placed into input buffer.
//
//-----------------------------------------------------------------------------
ULONG HardwareContext::TransferInputBuffer(ULONG NumBuf)
{
    ULONG BytesTransferred = 0;

    PBYTE pBufferStart = m_Input_pbDMA_PAGES[NumBuf];
    PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
    PBYTE pBufferLast;

    __try
    {
        pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart,
                                                          pBufferEnd,NULL);
        BytesTransferred = pBufferLast - pBufferStart;

        // We will mark the input DMA buffer as being in use again regardless
        // of whether or not the data was completely copied out to an
        // application-supplied data buffer. The input DMA buffer must be
        // immediately reused because the audio recording operation is still
        // running.
        if(NumBuf == IN_BUFFER_A)
        {
            m_InputDMAStatus &= ~DMA_DONEA;
        }

⌨️ 快捷键说明

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