⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hwctxt.cpp

📁 s3c2443的Wavedev代码,觉对好用.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
				hardware bug in the revision of the Samsung SC2443
				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\r\n")));
	//============================ Configure DMA Channel 1 ===========================
	//------ On platforms with the revision of the Samsung SC2443 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_pDMAregs->DISRC1	= (unsigned int)IISFIFRX_PHYS;	// DonGo modified.
	g_pDMAregs->DISRC1	= (unsigned int)0x55000014;	// DonGo modified.
	g_pDMAregs->DISRCC1 = (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_pDMAregs->DIDST1	= (int)(g_PhysDMABufferAddr.LowPart); 
	g_pDMAregs->DIDSTC1 &= ~(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_pDMAregs->DCON1	= (  HANDSHAKE_MODE | GENERATE_INTERRUPT 
#if DMA_FLAG	
//						   | TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );
						   | TRANSFER_WORD | (AUDIO_DMA_PAGE_SIZE / 4) );
#else						   
						   | NO_DMA_AUTO_RELOAD | TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );
//						   | NO_DMA_AUTO_RELOAD | TRANSFER_WORD | (AUDIO_DMA_PAGE_SIZE / 4) );
#endif						   

	g_pDMAregs->DMAREQSEL1 = (DMAREQSEL_I2SSDI) |(1) ;

	
	RETAILMSG(DBG_AUDIO,(TEXT("---InitInputDMA\r\n")));
	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 SC2443
				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 SC2443 CPU with the IIS SLAVE bug fix, this -----
	//		 code can be used to configure DMA channel 1 for input.

	//RETAILMSG(1,(TEXT("+++StartInputDMA\n")));
	
	if(!m_InputDMARunning)
		{
		//RETAILMSG(1,(TEXT("+++InputDMArunning first\r\n")));
		//----- 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(1, (TEXT("HardwareContext::StartInputDMA() - Unable to initialize input DMA channel!\r\n")));
			goto START_ERROR;
		}
		/*
		g_pIISregs->IISCON  &= ~(RECEIVE_DMA_PAUSE|RECEIVE_IDLE_CMD);	 
		g_pIISregs->IISCON  |= RECEIVE_DMA_REQUEST_ENABLE;	 
		*/
		//g_pIISregs->IISMOD  |= (IIS_RECEIVE_MODE|MASTER_CLOCK_FREQ_384fs);
	
		//----- 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_pDMAregs->DMASKTRIG1 = ENABLE_DMA_CHANNEL;	
		AUDIO_IN_DMA_ENABLE();
		
		/*
	#if DMA_FLAG
		// wait for DMA to start.
	RETAILMSG(DBG_AUDIO, (TEXT("Going into the DMA start loop")));
		//while((g_pDMAregs->DSTAT1&0xfffff)!=0);
	RETAILMSG(DBG_AUDIO, (TEXT("Out of the DMA start loop")));
		// change the buffer pointer
			SELECT_AUDIO_DMA_INPUT_BUFFER_B();
	#endif
	*/
	}

	// wait for DMA to start.
	delay_count = 0;
	while((g_pDMAregs->DSTAT1&0xfffff)==0)
	{
	      	if( delay_count++ > DELAY_COUNT )	break;
	}
	if(delay_count>DELAY_COUNT) RETAILMSG(1, (TEXT("TimeOut!!!\n")));


	SELECT_AUDIO_DMA_INPUT_BUFFER_B();

		
	//RETAILMSG(1,(TEXT("---StartInputDMA\n")));
	
	return(TRUE);

START_ERROR:
	return(FALSE);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		StopInputDMA()

Description:	Stops any DMA activity on the input channel.

Notes:			***** IMPLEMENTED *****

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::StopInputDMA()
{

	//------ On platforms with the revsion of the Samsung SC2443 CPU with the IIS SLAVE bug fix, this -----
	//		 code can be used to configure DMA channel 1 for input.

	//RETAILMSG(1,(TEXT("+++StopInputDMA\n")));
	//----- 1. If the input DMA is running, stop it -----
	if (m_InputDMARunning)
	{
		m_InputDMAStatus = DMA_CLEAR;				

		//StopI2SClock();

		/*
		g_pIISregs->IISCON &= ~RECEIVE_DMA_REQUEST_ENABLE;
		g_pIISregs->IISCON |= RECEIVE_IDLE_CMD;		// RXCHPAUSE
		
		g_pDMAregs->DMASKTRIG1 |= STOP_DMA_TRANSFER;
		g_pDMAregs->DMASKTRIG1 &= ~ENABLE_DMA_CHANNEL;
		*/
		AUDIO_IN_DMA_DISABLE();
		//g_pIISregs->IISMOD  |= IIS_TRANSMIT_MODE;		// reserved		
		AUDIO_IN_CLEAR_INTERRUPTS();

		AudioMute(DMA_CH_MIC, TRUE);		
	}

	m_InputDMARunning = FALSE;
	Codec_channel();
	//RETAILMSG(1,(TEXT("---StopInputDMA\n")));
}


DWORD HardwareContext::GetInterruptThreadPriority()
{
	HKEY hDevKey;
	DWORD dwValType;
	DWORD dwValLen;
	DWORD dwPrio = 249; // Default priority

	hDevKey = OpenDeviceKey((LPWSTR)m_DriverIndex);
	if (hDevKey)
	{
		dwValLen = sizeof(DWORD);
		RegQueryValueEx(
			hDevKey,
			TEXT("Priority256"),
			NULL,
			&dwValType,
			(PUCHAR)&dwPrio,
			&dwValLen);
		RegCloseKey(hDevKey);
	}

	return dwPrio;
}



/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		InitInterruptThread()

Description:	Initializes the IST for handling DMA interrupts.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitInterruptThread()
{

	m_hAudioInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);

	if (!m_hAudioInterrupt)
	{
		return(FALSE);
	}

	if (! InterruptInitialize(m_dwSysintrOutput, m_hAudioInterrupt, NULL, 0)) {
		RETAILMSG(1, (TEXT("Unable to initialize output interrupt\n")));
		return FALSE;
	}
	if (! InterruptInitialize(m_dwSysintrInput, m_hAudioInterrupt, NULL, 0)) {
		RETAILMSG(1, (TEXT("Unable to initialize input interrupt\n")));
		return FALSE;
	}
	
	m_hAudioInterruptThread  = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
											0,
											(LPTHREAD_START_ROUTINE)CallInterruptThread,
											this,
											0,
											NULL);
	if (!m_hAudioInterruptThread)
	{
		RETAILMSG(1, (TEXT("\ninterrupt thread open error.\n\n")));		
		return(FALSE);
	}

	// Bump up the priority since the interrupt must be serviced immediately.
	CeSetThreadPriority(m_hAudioInterruptThread, GetInterruptThreadPriority());

	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()
{
	I2S_Init();
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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()
{
	RETAILMSG(DBG_ON, (TEXT("HardwareContext::PowerDown\r\n")));
	StopOutputDMA();
	AudioMute((DMA_CH_OUT | DMA_CH_MIC), TRUE);
}


//############################################ Helper Functions #############################################

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		TransferOutputBuffer()

Description:	Retrieves the next "mixed" audio buffer of data to
				DMA into the output channel.

Returns:		Number of bytes needing to be transferred.
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferOutputBuffer(ULONG NumBuf)
{
	ULONG BytesTransferred = 0;
	PBYTE pBufferStart = m_Output_pbDMA_PAGES[NumBuf];
	PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
	PBYTE pBufferLast;

	__try
	{
		pBufferLast = m_OutputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
		BytesTransferred = m_OutBytes[NumBuf] = pBufferLast-pBufferStart;


		// Enable if you need to clear the rest of the DMA buffer
		StreamContext::ClearBuffer(pBufferLast,pBufferEnd);
		if(NumBuf == OUT_BUFFER_A)			// Output Buffer A
		{
			m_OutputDMAStatus &= ~DMA_DONEA;
			m_OutputDMAStatus |= DMA_STRTA;
		}
		else									// Output Buffer B
		{
			m_OutputDMAStatus &= ~DMA_DONEB;
			m_OutputDMAStatus |= DMA_STRTB;
		}
	}
	__except(EXCEPTION_EXECUTE_HANDLER) 
	{
		RETAILMSG(DBG_AUDIO, (TEXT("WAVDEV2.DLL:TransferOutputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
	}
	
	RETAILMSG(DBG_AUDIO, (TEXT("pBufferTransferred/NumBuf=%d(%d).\n"), BytesTransferred,NumBuf));

	return BytesTransferred;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		TransferOutputBuffers()

Description:	Determines which output buffer (A or B) needs to 
				be filled with sound data.  The correct buffer is
				then populated with data and ready to DMA to the 
				output channel.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferOutputBuffers(DWORD dwDCSR)
{
	ULONG BytesTransferred = 0;

	ULONG BytesTotal;
	DWORD Bits = dwDCSR & (DMA_DONEA|DMA_DONEB|DMA_BIU);

	switch (Bits)
	{
	case 0:
	case DMA_BIU:
		// No done bits set- must not be my interrupt
		return 0;
	case DMA_DONEA|DMA_DONEB|DMA_BIU:
		// Load B, then A
		BytesTransferred = TransferOutputBuffer(OUT_BUFFER_B);
		// fall through
	case DMA_DONEA: // This should never happen!
	case DMA_DONEA|DMA_BIU:
		BytesTransferred += TransferOutputBuffer(OUT_BUFFER_A);		// charlie, A => B
		break;
	case DMA_DONEA|DMA_DONEB:
		// Load A, then B
		BytesTransferred = TransferOutputBuffer(OUT_BUFFER_A);
#if DMA_FLAG		
		// charlie
		BytesTransferred += TransferOutputBuffer(OUT_BUFFER_B);
		break;		// charlie
#endif		
		// fall through
	case DMA_DONEB|DMA_BIU: // This should never happen!
	case DMA_DONEB:
		// Load B
		BytesTransferred += TransferOutputBuffer(OUT_BUFFER_B);		// charlie, B => A
		break;
	}
	// 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
	BytesTotal = m_OutBytes[OUT_BUFFER_A]+m_OutBytes[OUT_BUFFER_B];

	if (BytesTotal==0)
	{
		//RETAILMSG(1,(TEXT("+++ NO BYTES transferred by DMA\r\n")));
		StopOutputDMA();
	}

	RETAILMSG(DBG_AUDIO,(TEXT("--TransferOutputBuffers(%d+%d)\n"), m_OutBytes[OUT_BUFFER_A],m_OutBytes[OUT_BUFFER_B]));

	return BytesTransferred;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		TransferInputBuffer()

Description:	Retrieves the chunk of recorded sound data and inputs
				it into an audio buffer for potential "mixing".

Returns:		Number of bytes needing to be transferred.
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferInputBuffer(ULONG NumBuf)
{
	ULONG BytesTransferred = 0;

	PBYTE pBufferStart = m_Input_pbDMA_PAGES[NumBuf];
	PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
	PBYTE pBufferLast;

	__try
	{
		pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
		BytesTransferred = m_InBytes[NumBuf] = pBufferLast-pBufferStart;

		if(NumBuf == IN_BUFFER_A)			// Input Buffer A
		{
			m_InputDMAStatus &= ~DMA_DONEA;
			m_InputDMAStatus |= DMA_STRTA;
		}
		else								// Input Buffer B
		{
			m_InputDMAStatus &= ~DMA_DONEB;
			m_InputDMAStatus |= DMA_STRTB;
		}

	}
	__except(EXCEPTION_EXECUTE_HANDLER) 
	{
		RETAILMSG(DBG_AUDIO, (TEXT("WAVDEV2.DLL:TransferInputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
	}

	return BytesTransferred;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		TransferInputBuffers()

Description:	Determines which input buffer (A or B) needs to 
				be filled with recorded sound data.  The correct 
				buffer is then populated with recorded sound data
				from the input channel.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferInputBuffers(DWORD dwDCSR)
{
	ULONG BytesTransferred=0;
	DWORD Bits = dwDCSR & (DMA_DONEA|DMA_DONEB|DMA_BIU);

	switch (Bits)
	{
	case 0:
	case DMA_BIU:
		// No done bits set- must not be my interrupt
		return 0;
	case DMA_DONEA|DMA_DONEB|DMA_BIU:
		// Load B, then A
		BytesTransferred = TransferInputBuffer(IN_BUFFER_B);
		// fall through
	case DMA_DONEA: // This should never happen!
	case DMA_DONEA|DMA_BIU:
		// Load A
		BytesTransferred += TransferInputBuffer(IN_BUFFER_A);
		break;
	case DMA_DONEA|DMA_DONEB:
		// Load A, then B
		BytesTransferred = TransferInputBuffer(IN_BUFFER_A);
#if DMA_FLAG		
		BytesTransferred += TransferInputBuffer(IN_BUFFER_B);
		break;
#endif		
		// fall through
	case DMA_DONEB|DMA_BIU: // This should never happen!
	case DMA_DONEB:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -