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