📄 hwctxt.cpp
字号:
//----- 5. Make sure the audio isn't muted -----
AudioMute(AUDIO_CH_OUT, FALSE);
//----- 6. Start the DMA controller -----
DDKDmacClearChannelIntr(m_DmaTxChannel);
DDKDmacStartChan(m_DmaTxChannel);
InterruptDone(m_dwSysintrOutput);
UINT32 status;
status = BSPAudioClearInterruptStatus(SSI_TRANSFER_TX, SSI_CHANNEL0);
if(CSP_BITFEXT(status, SSI_SISR_TFS) == SSI_SISR_TFS_FS_OCCUR)
{
BSPSetSwap(TRUE);
}
else
{
BSPSetSwap(FALSE);
}
// call back BSP function to enable the output
BSPAudioStartOutput(TRUE);
// Set time slot mask registers (Slot 0 - Tag, Slot3 - PCM Left and Slot 4 - PCM Right)
// Set Slot 0 (TAG) value to indicate Frame Valid, PCM Left and PCM Right
BSPSetSlotTag(0x9800) ; // Binary:1001 1000 0000 0000
// Wait for DMA to start
while(DDKDmacGetTransSize(m_DmaTxChannel) == 0);
// Set DMA for next buffer
DDKDmacSetSrcAddress(m_DmaTxChannel, m_DmaTxBuffer[1]);
DEBUGMSG(ZONE_MISC, (TEXT("Output DMA transferred: %d\r\n"),
DDKDmacGetTransSize(m_DmaTxChannel)));
}
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
//
// DESCRIPTION: Stops playback DMA
//
// PARAMETERS:
// None
//
// RETURNS:
// None
//
//------------------------------------------------------------------------------
void HardwareContext::StopOutputDMA()
{
//----- 1. If the output DMA is running, stop it -----
if(m_OutputDMARunning)
{
// BSPAudioStartOutput(FALSE);
DDKDmacDisableChannelIntr(m_DmaTxChannel);
DDKDmacStopChan(m_DmaTxChannel);
DDKDmacClearChannelIntr(m_DmaTxChannel);
AudioMute(AUDIO_CH_OUT, TRUE);
m_OutputDMARunning = FALSE;
DEBUGMSG(ZONE_MISC, (TEXT("Stopped output DMA\r\n")));
}
}
//------------------------------------------------------------------------------
//
// FUNCTION: StartInputDMA
//
// DESCRIPTION: Start recording DMA
//
// PARAMETERS:
// None
//
// RETURNS:
// None
//
//------------------------------------------------------------------------------
BOOL HardwareContext::StartInputDMA()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+StartInputDMA\r\n")));
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 -----
DDKDmacSetRepeatType(m_DmaRxChannel, DMAC_REPEAT_FOREVER);
DDKDmacSetDestAddress(m_DmaRxChannel, m_DmaRxBuffer[0]);
//----- 3. Make sure the audio isn't muted -----
AudioMute(AUDIO_CH_IN, FALSE);
//----- 4. Start the input DMA -----
DDKDmacClearChannelIntr(m_DmaRxChannel);
DDKDmacStartChan(m_DmaRxChannel);
DDKDmacEnableChannelIntr(m_DmaRxChannel);
InterruptDone(m_dwSysintrInput);
BSPAudioClearInterruptStatus(SSI_TRANSFER_RX, SSI_CHANNEL0);
BSPAudioStartInput(TRUE);
// Wait for DMA to start
while(DDKDmacGetTransSize(m_DmaRxChannel) == 0);
// Set DMA for next buffer
DDKDmacSetDestAddress(m_DmaRxChannel, m_DmaRxBuffer[1]);
DEBUGMSG(ZONE_MISC, (TEXT("Started input DMA\r\n")));
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-StartInputDMA\r\n")));
return TRUE;
}
//------------------------------------------------------------------------------
//
// FUNCTION: StopInputDMA
//
// DESCRIPTION: Stops recording DMA
//
// PARAMETERS:
// None
//
// RETURNS:
// None
//
//------------------------------------------------------------------------------
void HardwareContext::StopInputDMA()
{
if(m_InputDMARunning)
{
BSPAudioStartInput(FALSE);
DDKDmacDisableChannelIntr(m_DmaRxChannel);
DDKDmacStopChan(m_DmaRxChannel);
DDKDmacClearChannelIntr(m_DmaRxChannel);
AudioMute(AUDIO_CH_IN, TRUE);
m_InputDMARunning = FALSE;
DEBUGMSG(ZONE_MISC, (TEXT("Stopped input DMA\r\n")));
}
}
//------------------------------------------------------------------------------
//
// FUNCTION: GetInterruptThreadPriority
//
// DESCRIPTION: Reads the registry entries to determine the priority
// of the audio interrupt service thread
//
// PARAMETERS:
// None
//
// RETURNS:
// priority
//
//------------------------------------------------------------------------------
DWORD HardwareContext::GetInterruptThreadPriority()
{
HKEY hDevKey;
DWORD dwValType;
DWORD dwValLen;
DWORD dwPrio = 249; // Default priority
DEBUGMSG(ZONE_FUNCTION, (TEXT("+GetInterruptThreadPriority\r\n")));
hDevKey = OpenDeviceKey((LPWSTR)m_DriverIndex);
if (hDevKey)
{
dwValLen = sizeof(DWORD);
RegQueryValueEx(
hDevKey,
TEXT("Priority256"),
NULL,
&dwValType,
(PUCHAR)&dwPrio,
&dwValLen);
RegCloseKey(hDevKey);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-GetInterruptThreadPriority: dwPrio=%d\r\n"), dwPrio));
return dwPrio;
}
//------------------------------------------------------------------------------
//
// Function: InitInterruptThread()
//
// Description: Initializes the IST for handling DMA interrupts.
//
// Returns: Boolean indicating success
//
//------------------------------------------------------------------------------
BOOL HardwareContext::InitInterruptThread()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+InitInterruptThread\r\n")));
m_hAudioInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
if(!m_hAudioInterrupt)
{
ERRORMSG(ZONE_ERROR, (TEXT("Unable to create interrupt event\r\n")));
return(FALSE);
}
if(!InterruptInitialize(m_dwSysintrOutput, m_hAudioInterrupt, NULL, 0))
{
ERRORMSG(ZONE_ERROR, (TEXT("Unable to initialize output interrupt\r\n")));
return FALSE;
}
if(!InterruptInitialize(m_dwSysintrInput, m_hAudioInterrupt, NULL, 0))
{
ERRORMSG(ZONE_ERROR, (TEXT("Unable to initialize input interrupt\r\n")));
return FALSE;
}
DEBUGMSG(ZONE_INTERRUPT, (TEXT("m_dwSysintrInput = %d m_dwSysintrOutput = %d\r\n"),
m_dwSysintrInput, m_dwSysintrOutput));
m_hAudioInterruptThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallInterruptThread,
this,
0,
NULL);
if(!m_hAudioInterruptThread)
{
ERRORMSG(ZONE_ERROR, (TEXT("Unable to create interrupt thread\r\n")));
return FALSE;
}
// Bump up the priority since the interrupt must be serviced immediately.
CeSetThreadPriority(m_hAudioInterruptThread, GetInterruptThreadPriority());
DEBUGMSG(ZONE_FUNCTION, (TEXT("-InitInterruptThread\r\n")));
return(TRUE);
}
//------------------------------------------------------------------------------
//
// Function: PowerUp()
//
// Description: Powers up the audio codec chip.
//
// Notes: Currently, this function is unimplemented because
// the audio codec chip is ONLY powered up when the
// user wishes to play or record. The AudioMute() function
// handles the powerup sequence.
//
// Returns: Boolean indicating success
//
//------------------------------------------------------------------------------
void HardwareContext::PowerUp()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+PowerUp\r\n")));
// Reload current gain settings
SetOutputGain(m_dwOutputGain);
SetInputGain(m_dwInputGain);
SetOutputMute(m_fOutputMute);
SetInputMute(m_fInputMute);
AudioMute((AUDIO_CH_OUT | AUDIO_CH_IN), FALSE);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-PowerUp\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: PowerDown()
//
// Description: Powers down the audio codec chip.
//
// Notes: Even if the input/output channels are muted, this
// function powers down the audio codec chip in order
// to conserve battery power.
//
// Returns: Boolean indicating success
//
//------------------------------------------------------------------------------
void HardwareContext::PowerDown()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+PowerDown\r\n")));
// StopOutputDMA();
AudioMute((AUDIO_CH_OUT | AUDIO_CH_IN), TRUE);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-PowerDown\r\n")));
}
//############################################ Helper Functions #############################################
//------------------------------------------------------------------------------
//
// FUNCTION: TransferOutputBuffer
//
// DESCRIPTION: Actual function to transfer playback data from
// the indicated buffer to DMA.
// Called by TransferOutputBuffers
//
// PARAMETERS:
// bufIndex - index of playback buffer to empty
//
// RETURNS:
// Number of bytes transferred from buffer
//
//------------------------------------------------------------------------------
UINT32 HardwareContext::TransferOutputBuffer(UINT8 bufIndex)
{
ULONG BytesTransferred = 0;
UINT8 *pBufferStart = (UINT8 *)m_Output_pbDMA_PAGES[bufIndex];
UINT8 *pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
UINT8 *pBufferLast;
__try
{
pBufferLast = m_OutputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd, NULL);
BytesTransferred = m_OutBytes[bufIndex] = pBufferLast-pBufferStart;
// Enable if you need to clear the rest of the DMA buffer
StreamContext::ClearBuffer(pBufferLast,pBufferEnd);
//if(BytesTransferred == 0)
// DmacSetRepeatType(m_DmaTxChannel, DMAC_REPEAT_DISABLED);
//else
DDKDmacSetSrcAddress(m_DmaTxChannel, m_DmaTxBuffer[bufIndex]);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferOutputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
}
return BytesTransferred;
}
//------------------------------------------------------------------------------
//
// FUNCTION: TransferOutputBuffers
//
// DESCRIPTION: Calls TransferOutputBuffer to transfer data from
// playback buffer to DMA. Also toggles the current
// buffer index to acheive double buffering. Stops
// output dma if nothing is transferred for 2
// buffers consecutively.
//
// PARAMETERS:
// None
//
// RETURNS:
// Number of bytes transferred from buffer
//
//------------------------------------------------------------------------------
UINT32 HardwareContext::TransferOutputBuffers(void)
{
UINT32 BytesTransferred = 0;
UINT32 DmaTransferred = 0;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+TransferOutputBuffers\r\n")));
//DmaTransferred = DmacGetTransSize(m_DmaRxChannel);
//RETAILMSG(1, (TEXT("DmaTransferred(%d).\r\n"), DmaTransferred));
BytesTransferred += TransferOutputBuffer(m_TxBufIndex);
m_TxBufIndex = (m_TxBufIndex == 0)? 1 : 0;
//for( DmaTransferred = 0; DmaTransferred < 1000000000; DmaTransferred++ );
//RETAILMSG(1, (TEXT("HardwareContext::TransferOutputBuffers(%d).\r\n"), BytesTransferred));
// If it was our interrupt, but we weren't able to transfer any bytes
// (e.g. no full buffers ready to be emptied)
// and all the output DMA buffers are now empty, then stop the output DMA
if(m_OutBytes[0] + m_OutBytes[1] == 0)
{
StopOutputDMA();
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-TransferOutputBuffers: BytesTransferred=%d\r\n"), BytesTransferred));
return BytesTransferred;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -