hwctxt.cpp
来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C++ 代码 · 共 1,380 行 · 第 1/3 页
CPP
1,380 行
return(TRUE);
MAP_ERROR:
if(pTemp)
{
VirtualFree(pTemp, 0, MEM_RELEASE);
}
return(FALSE);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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()
{
//****** L3 I/F (GPIO) Initialize *****
g_pIOPregs->GPDAT |= L3M|L3C; //start condition : L3M=H, L3C=H
g_pIOPregs->GPPU |= (0x7<<15); //pull-up disable GPIO15,16,17 (0b111 -> 0x7)
g_pIOPregs->GPCON_M = ((g_pIOPregs->GPCON_M & ~(0x3f<<8)) | (0x15<<8)); // all output (gp18,17,16)
_WrL3Addr(0x14+2); //STATUS (000101xx+10)
if( m_InputDMARunning & m_OutputDMARunning )
_WrL3Data(0xa3,0); //1,0,1,0,0,0,11 : OGS=0,IGS=1,ADC_NI,DAC_NI,sngl speed,AoffDon
else if( m_InputDMARunning )
_WrL3Data(0xa2,0); //1,0,1,0,0,0,10 : OGS=0,IGS=1,ADC_NI,DAC_NI,sngl speed,AoffDon
else if( m_OutputDMARunning )
_WrL3Data(0xa1,0); //1,0,1,0,0,0,01 : OGS=0,IGS=1,ADC_NI,DAC_NI,sngl speed,AoffDon
else
_WrL3Data(0xa0,0); //1,0,1,0,0,0,00 : OGS=0,IGS=1,ADC_NI,DAC_NI,sngl speed,AoffDon
return(TRUE);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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()
{
RETAILMSG(1, (TEXT("+++InitCodec\r\n")));
g_pIOPregs->GPDAT |= L3M|L3C; //start condition : L3M=H, L3C=H
g_pIOPregs->GPCON_M = ((g_pIOPregs->GPCON_M & ~(0x3f<<8)) | (0x15<<8)); // all output (gp18,17,16)
g_pIOPregs->GPPU |= (0x7<<15); //pull-up disable GPIO16,17,18 (0b111 -> 0x7)
/****** L3 Interface ******/
#if (AUDIO_CODEC_CLOCK == 256) // test value
RETAILMSG(1,(TEXT("256 clock\r\n")));
_WrL3Addr(0x14+2); //STATUS (000101xx+10)
_WrL3Data(0x60,0); //0,1,10,000,0 : reset,256fs,no DCfilter,iis
_WrL3Addr(0x14+2); //STATUS (000101xx+10)
_WrL3Data(0x20,0); //0,0,10,000,0 : no reset,256fs,no DCfilter,iis
_WrL3Addr(0x14+2); //STATUS (000101xx+10)
_WrL3Data(0xa1,0); //1,0,0,0,0,0,01 : OGS=0,IGS=0,ADC_NI,DAC_NI,sngl speed,AoffDon
#else
RETAILMSG(1,(TEXT("384 clock\r\n")));
_WrL3Addr(0x14+2); //STATUS (000101xx+10)
_WrL3Data(0x50,0); //0,1,01,000,0 : reset,384fs,no DCfilter,iis
_WrL3Addr(0x14+2); //STATUS (000101xx+10)
_WrL3Data(0x10,0); //0,0,01,000,0 : no reset,384fs,no DCfilter,iis
_WrL3Addr(0x14+2); //STATUS (000101xx+10)
_WrL3Data(0xa1,0); ///1,0,1,0,0,0,01 : OGS=0,IGS=1,ADC_NI,DAC_NI,sngl speed,AoffDon
#endif
_WrL3Addr(0x14 + 0); //DATA0 (000101xx+00)
_WrL3Data(0xc2,0); //11000,010 : DATA0, Extended addr(010)
_WrL3Data(0x4d,0); //010,011,01 : DATA0, MS=9dB, Ch1=on Ch2=off,
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 -----
g_pDMA2regs->DISRC = (int)(IMAGE_AUDIO_DMA_BUFFER_PHYS);
g_pDMA2regs->DISRCC &= ~(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_pDMA2regs->DIDST = (int)(IISFIF_PHYS);
g_pDMA2regs->DIDSTC |= (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_pDMA2regs->DCON = ( HANDSHAKE_MODE | GENERATE_INTERRUPT | I2SSDO_DMA2 | DMA_TRIGGERED_BY_HARDWARE
#if DMA_FLAG
| TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2 ) );
#else
| NO_DMA_AUTO_RELOAD | TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );
#endif
//----- 4. Reset the playback pointers -----
AUDIO_RESET_PLAYBACK_POINTER();
RETAILMSG(DBG_AUDIO,(TEXT("---InitOutputDMA\n")));
return TRUE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: StartOutputDMA()
Description: Starts outputting the sound data to the audio codec
chip via DMA.
Notes: Currently, both playback and record share the same
DMA channel. Consequently, we can only start this
operation if the input channel isn't using DMA.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::StartOutputDMA()
{
RETAILMSG(DBG_AUDIO,(TEXT("+++StartOutputDMA\n")));
if(!m_OutputDMARunning)
{
//----- 1. Initialize our buffer counters -----
m_OutputDMARunning=TRUE;
m_OutBytes[OUT_BUFFER_A]=m_OutBytes[OUT_BUFFER_B]=0;
//----- 2. Prime the output buffer with sound data -----
m_OutputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;
ULONG OutputTransferred = TransferOutputBuffers(m_OutputDMAStatus);
//----- 3. If we did transfer any data to the DMA buffers, go ahead and enable DMA -----
if(OutputTransferred)
{
//----- 4. Configure the DMA channel for playback -----
if(!InitOutputDMA())
{
RETAILMSG(DBG_AUDIO, (TEXT("HardwareContext::StartOutputDMA() - Unable to initialize output DMA channel!\r\n")));
goto START_ERROR;
}
#if 1
////////////////////////////////////////////////////////////////////////////////
// To correct left/right channel on ouput stream,
// You should reset IISCON[0] bit.
Lock();
g_pIISregs->IISCON &= ~IIS_INTERFACE_ENABLE;
RETAILMSG(DBG_AUDIO,(_T("v_pIISregs->IISCON = 0x%X\r\n"), g_pIISregs->IISCON));
g_pIISregs->IISCON |= TRANSMIT_DMA_REQUEST_ENABLE;
g_pIISregs->IISCON &= ~TRANSMIT_IDLE_CMD;
g_pIISregs->IISFCON |= ( TRANSMIT_FIFO_ACCESS_DMA | TRANSMIT_FIFO_ENABLE );
g_pIISregs->IISMOD |= IIS_TRANSMIT_MODE;
//----- 5. Make sure the audio isn't muted -----
AudioMute(DMA_CH_OUT, FALSE);
//----- 6. Start the DMA controller -----
AUDIO_RESET_PLAYBACK_POINTER();
SELECT_AUDIO_DMA_OUTPUT_BUFFER_A();
Codec_channel(); // Turn ON output channel
// charlie, start A buffer
AUDIO_OUT_DMA_ENABLE();
// wait for DMA to start.
RETAILMSG(DBG_AUDIO, (TEXT("Going into DSTAT Loop\r\n")));
while((g_pDMA2regs->DSTAT&0xfffff)==0);
RETAILMSG(DBG_AUDIO, (TEXT("Out of DSTAT Loop\r\n")));
// check if tx fifo data is ready
RETAILMSG(DBG_AUDIO, (TEXT("Checking for IIS FIFO data ready\r\n")));
while ( !(g_pIISregs->IISCON & (1<<7)) ) ;
RETAILMSG(DBG_AUDIO, (TEXT("Out of IIS FIFO data ready\r\n")));
g_pIISregs->IISCON |= IIS_INTERFACE_ENABLE;
Unlock();
////////////////////////////////////////////////////////////////////////////////
// change the buffer pointer
SELECT_AUDIO_DMA_OUTPUT_BUFFER_B();
// Set DMA for B Buffer
#else
g_pIISregs->IISCON |= TRANSMIT_DMA_REQUEST_ENABLE;
g_pIISregs->IISCON &= ~TRANSMIT_IDLE_CMD;
g_pIISregs->IISFCON |= ( TRANSMIT_FIFO_ACCESS_DMA | TRANSMIT_FIFO_ENABLE );
g_pIISregs->IISMOD |= IIS_TRANSMIT_MODE;
//----- 5. Make sure the audio isn't muted -----
AudioMute(DMA_CH_OUT, FALSE);
//----- 6. Start the DMA controller -----
AUDIO_RESET_PLAYBACK_POINTER();
SELECT_AUDIO_DMA_OUTPUT_BUFFER_A();
Codec_channel(); // Turn ON output channel
// charlie, start A buffer
AUDIO_OUT_DMA_ENABLE();
#if DMA_FLAG
// wait for DMA to start.
while((g_pDMA2regs->DSTAT&0xfffff)==0);
// change the buffer pointer
SELECT_AUDIO_DMA_OUTPUT_BUFFER_B();
// Set DMA for B Buffer
#endif
#endif
}
else // We didn't transfer any data, so DMA wasn't enabled
{
m_OutputDMARunning=FALSE;
}
}
RETAILMSG(DBG_AUDIO,(TEXT("---StartOutputDMA\n")));
return TRUE;
START_ERROR:
return FALSE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: StopOutputDMA()
Description: Stops any DMA activity on the output channel.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::StopOutputDMA()
{
//----- 1. If the output DMA is running, stop it -----
if (m_OutputDMARunning)
{
m_OutputDMAStatus = DMA_CLEAR;
AUDIO_OUT_DMA_DISABLE();
AUDIO_OUT_CLEAR_INTERRUPTS();
g_pIISregs->IISCON &= ~TRANSMIT_DMA_REQUEST_ENABLE;
g_pIISregs->IISCON |= TRANSMIT_IDLE_CMD;
g_pIISregs->IISFCON &= ~( TRANSMIT_FIFO_ACCESS_DMA | TRANSMIT_FIFO_ENABLE );
g_pIISregs->IISMOD &= ~IIS_TRANSMIT_MODE;
AudioMute(DMA_CH_OUT, TRUE);
}
m_OutputDMARunning = FALSE;
Codec_channel();
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: InitInputDMA()
Description: Initializes the DMA channel for input.
Notes: ***** NOT IMPLEMENTED *****
The following routine is not implemented due to a
hardware bug in the revision of the Samsung SC24A0
CPU this driver was developed on. See the header
at the top of this file for details.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitInputDMA()
{
RETAILMSG(DBG_AUDIO,(TEXT("+++InitInputDMA\n")));
//============================ Configure DMA Channel 1 ===========================
//------ On platforms with the revsion of the Samsung SC24A0 CPU with the IIS SLAVE bug fix, this -----
// code can be used to configure DMA channel 1 for input.
//----- 1. Initialize the DMA channel for input mode and use the first input DMA buffer -----
g_pDMA0regs->DISRC = (int)(IISFIF_PHYS);
g_pDMA0regs->DISRCC = (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS); // Source is periperal bus, fixed addr
//----- 2. Initialize the DMA channel to receive data over the I2S bus -----
g_pDMA0regs->DIDST = (int)(IMAGE_AUDIO_DMA_BUFFER_PHYS);
g_pDMA0regs->DIDSTC &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS); // Destination is system bus, increment addr
//----- 3. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----
// single tx, single service, I2SSDI, I2S request, no auto-reload, half-word, tx count
g_pDMA0regs->DCON = ( HANDSHAKE_MODE | GENERATE_INTERRUPT | I2SSDI_DMA0 | DMA_TRIGGERED_BY_HARDWARE
#if DMA_FLAG
| TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );
#else
| NO_DMA_AUTO_RELOAD | TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );
#endif
return(TRUE);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: StartInputDMA()
Description: Starts inputting the recorded sound data from the
audio codec chip via DMA.
Notes: ***** NOT IMPLEMENTED *****
The following routine is not implemented due to a
hardware bug in the revision of the Samsung SC24A0
CPU this driver was developed on. See the header
at the top of this file for details.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::StartInputDMA()
{
//------ On platforms with the revsion of the Samsung SC24A0 CPU with the IIS SLAVE bug fix, this -----
// code can be used to configure DMA channel 1 for input.
RETAILMSG(DBG_AUDIO,(TEXT("+++StartInputDMA\n")));
if(!m_InputDMARunning)
{
//----- 1. Initialize our buffer counters -----
m_InputDMARunning=TRUE;
Codec_channel(); // Turn On Input channel
m_InBytes[IN_BUFFER_A]=m_InBytes[IN_BUFFER_B]=0;
//----- 2. Prime the output buffer with sound data -----
m_InputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;
//----- 3. Configure the DMA channel for record -----
if(!InitInputDMA())
{
RETAILMSG(DBG_AUDIO, (TEXT("HardwareContext::StartInputDMA() - Unable to initialize input DMA channel!\r\n")));
goto START_ERROR;
}
g_pIISregs->IISFCON |= (RECEIVE_FIFO_ACCESS_DMA | RECEIVE_FIFO_ENABLE);
g_pIISregs->IISCON |= RECEIVE_DMA_REQUEST_ENABLE;
g_pIISregs->IISMOD |= IIS_RECEIVE_MODE;
//----- 4. Make sure the audio isn't muted -----
AudioMute(DMA_CH_MIC, FALSE);
//----- 5. Start the input DMA -----
AUDIO_RESET_RECORD_POINTER();
SELECT_AUDIO_DMA_INPUT_BUFFER_A();
Codec_channel(); // Turn On Input channel
g_pDMA0regs->DMASKTRIG = ENABLE_DMA_CHANNEL;
#if DMA_FLAG
// wait for DMA to start.
RETAILMSG(DBG_AUDIO, (TEXT("Going into DSTAT Loop\r\n")));
while((g_pDMA0regs->DSTAT&0xfffff)==0);
RETAILMSG(DBG_AUDIO, (TEXT("Out of DSTAT Loop\r\n")));
// change the buffer pointer
SELECT_AUDIO_DMA_INPUT_BUFFER_B();
#endif
}
RETAILMSG(DBG_AUDIO,(TEXT("---StartInputDMA\n")));
return(TRUE);
START_ERROR:
return(FALSE);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: StopInputDMA()
Description: Stops any DMA activity on the input channel.
Notes: ***** NOT IMPLEMENTED *****
The following routine is not implemented due to a
hardware bug in the revision of the Samsung SC24A0
CPU this driver was developed on. See the header
at the top of this file for details.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::StopInputDMA()
{
//------ On platforms with the revsion of the Samsung SC24A0 CPU with the IIS SLAVE bug fix, this -----
// code can be used to configure DMA channel 1 for input.
//----- 1. If the output DMA is running, stop it -----
if (m_InputDMARunning)
{
m_InputDMAStatus = DMA_CLEAR;
g_pIISregs->IISCON &= ~RECEIVE_DMA_REQUEST_ENABLE;
g_pIISregs->IISFCON &= ~(RECEIVE_FIFO_ACCESS_DMA | RECEIVE_FIFO_ENABLE);
g_pDMA0regs->DMASKTRIG |= STOP_DMA_TRANSFER;
g_pDMA0regs->DMASKTRIG &= ~ENABLE_DMA_CHANNEL;
g_pIISregs->IISMOD &= ~IIS_RECEIVE_MODE;
AUDIO_IN_CLEAR_INTERRUPTS();
AudioMute(DMA_CH_MIC, TRUE);
}
m_InputDMARunning = FALSE;
Codec_channel();
}
DWORD HardwareContext::GetInterruptThreadPriority()
{
HKEY hDevKey;
DWORD dwValType;
DWORD dwValLen;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?