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 + -
显示快捷键?