📄 hwctxt.cpp
字号:
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 + -