📄 hwctxt.cpp
字号:
g_pIOPregs = (volatile S3C2440A_IOPORT_REG*)VirtualAlloc(0, sizeof(S3C2440A_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
if (!g_pIOPregs)
{
DEBUGMSG(1, (TEXT("IOPreg: VirtualAlloc failed!\r\n")));
return(FALSE);
}
if (!VirtualCopy((PVOID)g_pIOPregs, (PVOID)(S3C2440A_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
DEBUGMSG(1, (TEXT("IOPreg: VirtualCopy failed!\r\n")));
return(FALSE);
}
g_pDMAregs = (volatile S3C2440A_DMA_REG*)VirtualAlloc(0, sizeof(S3C2440A_DMA_REG), MEM_RESERVE, PAGE_NOACCESS);
if (!g_pDMAregs)
{
DEBUGMSG(1, (TEXT("DMAreg: VirtualAlloc failed!\r\n")));
return(FALSE);
}
if (!VirtualCopy((PVOID)g_pDMAregs, (PVOID)(S3C2440A_BASE_REG_PA_DMA >> 8), sizeof(S3C2440A_DMA_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
DEBUGMSG(1, (TEXT("DMAreg: VirtualCopy failed!\r\n")));
return(FALSE);
}
s2440INT = (volatile S3C2440A_INTR_REG*)VirtualAlloc(0, sizeof(S3C2440A_INTR_REG), MEM_RESERVE, PAGE_NOACCESS);
if (!g_pDMAregs)
{
DEBUGMSG(1, (TEXT("INTreg: VirtualAlloc failed!\r\n")));
return(FALSE);
}
if (!VirtualCopy((PVOID)s2440INT, (PVOID)(S3C2440A_BASE_REG_PA_INTR >> 8), sizeof(S3C2440A_INTR_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
DEBUGMSG(1, (TEXT("INTreg: VirtualCopy failed!\r\n")));
return(FALSE);
}
g_pCLKPWRreg = (volatile S3C2440A_CLKPWR_REG*)VirtualAlloc(0, sizeof(S3C2440A_CLKPWR_REG), MEM_RESERVE, PAGE_NOACCESS);
if (!g_pCLKPWRreg)
{
DEBUGMSG(1, (TEXT("DMAreg: VirtualAlloc failed!\r\n")));
return(FALSE);
}
if (!VirtualCopy((PVOID)g_pCLKPWRreg, (PVOID)(S3C2440A_BASE_REG_PA_CLOCK_POWER >> 8), sizeof(S3C2440A_CLKPWR_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
DEBUGMSG(1, (TEXT("DMAreg: VirtualCopy failed!\r\n")));
return(FALSE);
}
PowerUp();
return(TRUE);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: Deinit()
Description: Deinitializest the hardware: disables DMA channel(s),
clears any pending interrupts, powers down the audio
codec chip, etc.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::Deinit()
{
//----- 1. Disable the input/output channels -----
// AUDIO_IN_DMA_DISABLE();
AUDIO_OUT_DMA_DISABLE();
//----- 2. Disable/clear DMA input/output interrupts -----
AUDIO_IN_CLEAR_INTERRUPTS();
AUDIO_OUT_CLEAR_INTERRUPTS();
//----- 3. Turn the audio hardware off -----
AudioMute(DMA_CH_OUT | DMA_CH_MIC, TRUE);
//----- 4. Unmap the control registers and DMA buffers -----
UnmapRegisters();
UnmapDMABuffers();
return TRUE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: UnmapRegisters()
Description: Unmaps the config registers used by both the SPI and
I2S controllers.
Notes: The SPI and I2S controllers both use the GPIO config
registers, so these MUST be deinitialized LAST.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::UnmapRegisters()
{
return TRUE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: MapDMABuffers()
Description: Maps the DMA buffers used for audio input/output
on the I2S bus.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::MapDMABuffers()
{
PBYTE pVirtDMABufferAddr = NULL;
DMA_ADAPTER_OBJECT Adapter;
memset(&Adapter, 0, sizeof(DMA_ADAPTER_OBJECT));
Adapter.InterfaceType = Internal;
Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
// Allocate a block of virtual memory (physically contiguous) for the DMA buffers.
//
pVirtDMABufferAddr = (PBYTE)HalAllocateCommonBuffer(&Adapter, (AUDIO_DMA_PAGE_SIZE * 4), &g_PhysDMABufferAddr, FALSE);
if (pVirtDMABufferAddr == NULL)
{
RETAILMSG(TRUE, (TEXT("WAVEDEV.DLL:HardwareContext::MapDMABuffers() - Failed to allocate DMA buffer.\r\n")));
return(FALSE);
}
// Setup the DMA page pointers.
// NOTE: Currently, input and output each have two DMA pages: these pages are used in a round-robin
// fashion so that the OS can read/write one buffer while the audio codec chip read/writes the other buffer.
//
m_Output_pbDMA_PAGES[0] = pVirtDMABufferAddr;
m_Output_pbDMA_PAGES[1] = pVirtDMABufferAddr + AUDIO_DMA_PAGE_SIZE;
m_Input_pbDMA_PAGES[0] = pVirtDMABufferAddr + (2 * AUDIO_DMA_PAGE_SIZE);
m_Input_pbDMA_PAGES[1] = pVirtDMABufferAddr + (3 * AUDIO_DMA_PAGE_SIZE);
return(TRUE);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: UnmapDMABuffers()
Description: Unmaps the DMA buffers used for audio input/output
on the I2S bus.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::UnmapDMABuffers()
{
if(m_Output_pbDMA_PAGES[0])
{
VirtualFree((PVOID)m_Output_pbDMA_PAGES[0], 0, MEM_RELEASE);
}
return TRUE;
}
BOOL HardwareContext::Codec_channel()
{
UCHAR status = UDA1341_STATUS_B | UDA1341_STATUS_IGS; //enable 6dB mic boost
// which parts to turn on?
if (m_InputDMARunning) {
status |= UDA1341_STATUS_PWR_ADC; // turn on ADC
}
if (m_OutputDMARunning) {
status |= UDA1341_STATUS_PWR_DAC; // turn on DAC
}
//****** Port B Initialize *****
g_pIOPregs->GPBDAT |= L3M|L3C; //start condition : L3M=H, L3C=H
g_pIOPregs->GPBUP |= 0x1c; //pull-up disable
g_pIOPregs->GPBCON = ((g_pIOPregs->GPBCON & 0x3ffc0f) | 0x000150);
WriteL3Addr(UDA1341_ADDR_STATUS);
WriteL3Data(status, 0);
return(TRUE);
}
MMRESULT HardwareContext::SetOutputGain (DWORD dwGain)
{
m_dwOutputGain = dwGain & 0xffff; // save off so we can return this from GetGain - but only MONO
// convert 16-bit gain to 5-bit attenuation
UCHAR ucGain;
if (m_dwOutputGain == 0) {
ucGain = 0x3F; // mute: set maximum attenuation
}
else {
ucGain = (UCHAR) ((0xffff - m_dwOutputGain) >> 11); // codec supports 64dB attenuation, we'll only use 32
}
ASSERT((ucGain & 0xC0) == 0); // bits 6,7 clear indicate DATA0 in Volume mode.
WriteL3Addr(UDA1341_ADDR_DATA0);
WriteL3Data(ucGain, 0);
return MMSYSERR_NOERROR;
}
MMRESULT HardwareContext::SetOutputMute (BOOL fMute)
{
m_fOutputMute = fMute;
WriteL3Addr(UDA1341_ADDR_DATA0);
WriteL3Data(fMute ? 0x84 : 0x80, 0); // DATA0: 0x80 + fMute << 2
return MMSYSERR_NOERROR;
}
BOOL HardwareContext::GetOutputMute (void)
{
return m_fOutputMute;
}
DWORD HardwareContext::GetOutputGain (void)
{
return m_dwOutputGain;
}
BOOL HardwareContext::GetInputMute (void)
{
return m_fInputMute;
}
MMRESULT HardwareContext::SetInputMute (BOOL fMute)
{
m_fInputMute = fMute;
return m_InputDeviceContext.SetGain(fMute ? 0: m_dwInputGain);
}
DWORD HardwareContext::GetInputGain (void)
{
return m_dwInputGain;
}
MMRESULT HardwareContext::SetInputGain (DWORD dwGain)
{
m_dwInputGain = dwGain;
if (! m_fInputMute) {
m_InputDeviceContext.SetGain(dwGain);
}
return MMSYSERR_NOERROR;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: InitCodec()
Description: Initializes the audio codec chip.
Notes: The audio codec chip is intialized for output mode
but powered down. To conserve battery life, the chip
is only powered up when the user starts playing a
file.
Specifically, the powerup/powerdown logic is done
in the AudioMute() function. If either of the
audio channels are unmuted, then the chip is powered
up; otherwise the chip is powered own.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitCodec()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+++InitCodec\n")));
//****** Port B Initialize *****
g_pIOPregs->GPBDAT |= L3M|L3C; //start condition : L3M=H, L3C=H
g_pIOPregs->GPBUP |= 0x1c; //pull-up disable
g_pIOPregs->GPBCON = ((g_pIOPregs->GPBCON & 0x3ffc0f) | 0x000150);
// Reset codec internal registers by toggling the status register reset bit
WriteL3Addr(UDA1341_ADDR_STATUS);
WriteL3Data(UDA1341_STATUS_RESET | UDA1341_STATUS_CLK384,0);
WriteL3Addr(UDA1341_ADDR_STATUS);
WriteL3Data(UDA1341_STATUS_CLK384,0);
// set default gain, power state
WriteL3Addr(UDA1341_ADDR_STATUS);
WriteL3Data(UDA1341_STATUS_B | UDA1341_STATUS_IGS | UDA1341_STATUS_PWR_DAC,0);
// extended address:
WriteL3Addr(UDA1341_ADDR_DATA0);
WriteL3Data(0xC2,0); //11000,010 : DATA0, Extended addr(010)
WriteL3Data(0xef,0); //111,011,11 : DATA0, MS=+9dB, MixerMode=both(1)
// disable AGC
WriteL3Addr(UDA1341_ADDR_DATA0);
WriteL3Data(0xC4,0); //11000,100 : DATA0, Extended addr(100)
WriteL3Data(0xe0,0); //111,000,00 : DATA0, AGC=Off, IG[0,1]=0
WriteL3Addr(UDA1341_ADDR_DATA0);
WriteL3Data(0xC4,0); //11000,101 : DATA0, Extended addr(101)
WriteL3Data(0xe8,0); //111,01000 : DATA0, IG[6:2]=01000
return(TRUE);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: InitOutputDMA()
Description: Initializes the DMA channel for output.
Notes: DMA Channel 2 is used for transmitting output sound
data from system memory to the I2S controller.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitOutputDMA()
{
//----- 1. Initialize the DMA channel for output mode and use the first output DMA buffer -----
if (!g_PhysDMABufferAddr.LowPart)
{
DEBUGMSG(TRUE, (TEXT("ERROR:HardwareContext::InitOutputDMA: Invalid DMA buffer physical address.\r\n")));
return(FALSE);
}
g_pDMAregs->DISRC2 = (int)(g_PhysDMABufferAddr.LowPart);
g_pDMAregs->DISRCC2 &= ~(SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS); // Source is system bus, increment addr
//----- 2. Initialize the DMA channel to send data over the I2S bus -----
g_pDMAregs->DIDST2 = (int)(S3C2440A_BASE_REG_PA_IISBUS+0x10);
g_pDMAregs->DIDSTC2 |= (DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS); // Dest is periperal bus, fixed addr
//----- 3. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----
// single tx, single service, I2SSDO, I2S request, no auto-reload, half-word, tx count
g_pDMAregs->DCON2 = ( HANDSHAKE_MODE | GENERATE_INTERRUPT | I2SSDO_DMA2 | DMA_TRIGGERED_BY_HARDWARE
| TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );
//----- 4. Reset the playback pointers -----
AUDIO_RESET_PLAYBACK_POINTER();
DEBUGMSG(ZONE_FUNCTION,(TEXT("---InitOutputDMA\n")));
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -