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

📄 hwctxt.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    BOOL rc = FALSE;
    
    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::StartOutputDMA\r\n")));

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

    // Terminate the existing playback CODEC disable timer since we're about
    // to start another playback operation.
    if (m_AudioDelayDisableTimerID[0] != NULL)
    {
        timeKillEvent(m_AudioDelayDisableTimerID[0]);
        m_AudioDelayDisableTimerID[0] = NULL;
    }
    
    // Reinitialize audio output if it is not already active.
    if (!m_OutputDMARunning)
    {
        // Initialize output DMA state variables
        m_OutputDMARunning = TRUE;
        m_OutputDMAStatus  = DMA_DONEA | DMA_DONEB;    

        // Save up to the first 8 words (32 bytes) of the output audio stream
        // so that we can prefill the SSI transmit FIFO later before we enable
        // the transmitter.
        nSsiFifoPrefill = TransferOutputBuffer((PBYTE)ssiFifoPrefill,
                                               (PBYTE)ssiFifoPrefill +
                                                   sizeof(ssiFifoPrefill));

        // Convert from bytes to number of words (i.e., the number of elements
        // in the ssiFifoPrefill[] buffer that are currently in use).
        nSsiFifoPrefill /= sizeof(HWSAMPLE);

        // Also prime the output DMA buffers.
        ULONG nOutputTransferred = TransferOutputBuffers(m_OutputDMAStatus);
        
        // Check if any audio output data was actually transferred available
        // and transferred to the SSI FIFO prefill and/or DMA output buffers.
        //
        // Note that we don't really care that nSsiFifoPrefill is in "words"
        // while nOutputTransferred is in "bytes" since all that we care about
        // here is whether the sum of the two is non-zero.
        if(nSsiFifoPrefill + nOutputTransferred > 0)
        {
            // Reset the state of the output DMA transfer list.
            //
            // Note that the second "watermark" argument to DDKSdmaInitChain()
            // is actually in bytes whereas "m_OutputDMALevel" is given in
            // SSI FIFO slots or words. Therefore, we have to multiply by the
            // audio data word size to ensure that we are properly refilling
            // the SSI TX FIFO.
            // 
            if(!DDKSdmaInitChain(m_OutputDMAChan,
                                 m_OutputDMALevel * sizeof(HWSAMPLE)))
            {
                    DEBUGMSG(ZONE_ERROR,
                             (_T("HardwareContext::StartOutputDMA(): Unable ")
                              _T("to initialize output DMA channel!\r\n")));
                    goto START_ERROR;
            }

            DEBUGMSG(ZONE_VERBOSE, (_T("  Starting first DMA operation\r\n")));

            // Start the output DMA channel. This must be done before we call
            // BSPAudioStartOutput() because we have to make sure that audio
            // data is already available before we activate the audio output
            // hardware.
            DDKSdmaStartChan(m_OutputDMAChan);

            // Enable the audio output hardware. We also fill the SSI transmit
            // FIFO at this point with the initial words from the audio stream
            // so that there is data immediately ready to be transmitted when
            // we enable the SSI transmitter.
            // This call must be done after we have already activated the
            // output DMA channel (by calling DDKSdmaStartChan()). Otherwise,
            // there is a race condition between how fast the initial transmit
            // FIFO will be emptied and whether the DMA controller will be
            // ready yet to handle the first interrupt from the FIFO.
            BSPAudioStartOutput(AUDIO_BUS_STEREO_OUT,
                                AUDIO_PATH_HEADSET,
                                ssiFifoPrefill,
                                nSsiFifoPrefill);
        }
        else
        {
            // We did not transfer any data, so DMA wasn't enabled.
            m_OutputDMARunning=FALSE;
        }
    }
    
    rc = TRUE;

START_ERROR:
    Unlock();
    
    DEBUGMSG(ZONE_FUNCTION,(_T("-HardwareContext::StartOutputDMA\r\n")));

    return rc;
}


//-----------------------------------------------------------------------------
//
//  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 the output DMA is running, stop it
    if (m_OutputDMARunning)
    {
        // Reset output DMA state variables
        m_OutputDMAStatus  = DMA_CLEAR;
        m_OutputDMARunning = FALSE;

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

        // Kill the output DMA channel
        DDKSdmaStopChan(m_OutputDMAChan, FALSE);
    }

    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;
    DDK_DMA_ACCESS audioDataRXWordSize = DDK_DMA_ACCESS_8BIT;

    if (sizeof(HWSAMPLE) == sizeof(INT16))
    {
        audioDataRXWordSize = DDK_DMA_ACCESS_16BIT;
    }
    else if (sizeof(HWSAMPLE) == sizeof(INT32))
    {
        audioDataRXWordSize = DDK_DMA_ACCESS_32BIT;
    }

    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 input DMA channel
    if (!BSPAudioInitInput(AUDIO_BUS_VOICE_IN))
    {
        ERRORMSG(ZONE_ERROR, (_T("BSPAudioInitInput failed.\r\n")));
        goto cleanUp;
    }

    // Allocate a DMA chain for the virtual channel to handle the DMA transfer
    // requests.
    if (!DDKSdmaAllocChain(m_InputDMAChan, NUM_DMA_BUFFERS))
    {
        ERRORMSG(ZONE_ERROR, (_T("DDKSdmaAllocChain failed.\r\n")));
        goto cleanUp;
    }            

    // Configure buffer descriptors
    if (!DDKSdmaSetBufDesc(m_InputDMAChan,
                           0, 
                           DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_CONT, 
                           g_PhysDMABufferAddr.LowPart +
                               (2 * AUDIO_DMA_PAGE_SIZE), 
                           0,
                           audioDataRXWordSize,
                           AUDIO_DMA_PAGE_SIZE))
    {
        ERRORMSG(ZONE_ERROR, (_T("DDKSdmaSetBufDesc failed.\r\n")));
        goto cleanUp;
    }
        
    if (!DDKSdmaSetBufDesc(m_InputDMAChan,
                           1, 
                           DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_CONT |
                               DDK_DMA_FLAGS_WRAP, 
                           g_PhysDMABufferAddr.LowPart +
                               (3 * AUDIO_DMA_PAGE_SIZE), 
                           0,
                           audioDataRXWordSize,
                           AUDIO_DMA_PAGE_SIZE))
    {
        ERRORMSG(ZONE_ERROR, (_T("DDKSdmaSetBufDesc 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);
    
    if (m_InputDMAChan != 0)
    {
        // Kill the input DMA channel
        DDKSdmaStopChan(m_InputDMAChan, TRUE);
        m_InputDMAChan = 0;
    }

    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)
    {
        // Initialize the input DMA state variables.
        m_InputDMARunning = TRUE;
        m_InputDMAStatus  = ~(DMA_DONEA | DMA_DONEB);

        // Reset the state of the input DMA chain.
        //
        // Note that the second "watermark" argument to DDKSdmaInitChain()
        // is actually in bytes whereas "m_InputDMALevel" is given in
        // SSI FIFO slots or words. Therefore, we have to multiply by the
        // audio data word size to ensure that we are properly emptying
        // the SSI RX FIFO.
        //
        if(!DDKSdmaInitChain(m_InputDMAChan,
                             m_InputDMALevel * sizeof(HWSAMPLE)))
        {
            DEBUGMSG(ZONE_ERROR, (_T("HardwareContext::StartInputDMA() - ")
                      _T("Unable to initialize input DMA channel!\r\n")));
            goto START_ERROR;
        }

        // Start the input DMA.
        DDKSdmaStartChan(m_InputDMAChan);

        // Enable audio input devices. This must be done after we activate the
        // input DMA channel because the audio hardware will immediately start
        // recording when this call is made.
        BSPAudioStartInput(AUDIO_BUS_VOICE_IN, AUDIO_PATH_MIC);
    }

    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)
    {
        // Reset input DMA state variables
        m_InputDMAStatus  = DMA_CLEAR;                
        m_InputDMARunning = FALSE;

        // Disable audio input devices
        BSPAudioStopInput(AUDIO_BUS_VOICE_IN, AUDIO_PATH_MIC);
        
        // Kill the output DMA channel
        DDKSdmaStopChan(m_InputDMAChan, FALSE);
    }

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

#endif // #ifdef AUDIO_RECORDING_ENABLED

⌨️ 快捷键说明

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