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

📄 hwctxt.cpp

📁 2443 wince5.0 bsp, source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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()
{
	//----- 1. Free the fast driver-->driver calling mechanism object -----
	if(g_hUTLObject) 
	{
		CloseHandle(g_hUTLObject);
	}
	
	if ( g_pIISregs )
		VirtualFree((PVOID)g_pIISregs, 0, MEM_RELEASE);
	if ( g_pDMAregs )	
		VirtualFree((PVOID)g_pDMAregs, 0, MEM_RELEASE);
	if ( g_pIOPregs )			
		VirtualFree((PVOID)g_pIOPregs, 0, MEM_RELEASE);
	if ( g_pCLKPWRreg )		
		VirtualFree((PVOID)g_pCLKPWRreg, 0, MEM_RELEASE);

	if ( s2443INT )		
		VirtualFree((PVOID)s2443INT, 0, MEM_RELEASE);

	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);
    m_pVirtDMABufferAddr = pVirtDMABufferAddr;

    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_pVirtDMABufferAddr)
	{
		VirtualFree((PVOID)m_pVirtDMABufferAddr, 0, MEM_RELEASE);
	}

	return TRUE;
}

BOOL HardwareContext::Codec_channel()
{

		//RETAILMSG(DBG_ON, (TEXT("+Codec_channel\r\n")));

		//******  L3 I/F (GPIO) Initialize *****
   	//----------------------------------------------------------
	//PORT G GROUP
	//Ports  :   GPG0       GPG1        GPG2  
	//Signal :  L3MODE     L3DATA      L3CLK
	//Setting:  OUTPUT     OUTPUT      OUTPUT 
	//	        [1:0]      [3:2]       [5:4]
	//Binary :  01          01           01 
	//----------------------------------------------------------   

		g_pIOPregs->GPGDAT = g_pIOPregs->GPGDAT & ~(L3M|L3C|L3D) |(L3M|L3C);  //Start condition : L3M=H, L3C=H

		g_pIOPregs->GPGCON = g_pIOPregs->GPGCON & ~(0x3f); 
		g_pIOPregs->GPGCON |= ((0x1<<4) |(0x1<<2) |(0x1<<0)); 
		
#ifdef EVT1		
	g_pIOPregs->EXTINT1 = READEXTINT1(g_pIOPregs->EXTINT1) | (1<<11)|(1<<7)|(1<<3);
#else
		g_pIOPregs->GPGUDP  = g_pIOPregs->GPGUDP & ~(0x3f<<0) | (2<<4)|(2<<2)|(2<<0);	// 1:Pull-Down disable
#endif		

		g_pIOPregs->GPGDAT = g_pIOPregs->GPGDAT & ~(L3M|L3C|L3D) |(L3M|L3C);  //Start condition : L3M=H, L3C=H
#if 1
	_WrL3Addr(0x14+2); 		//STATUS (000101xx+10)	
	if( m_InputDMARunning & m_OutputDMARunning )
		_WrL3Data(0xa3,0); 	// 1010 0011	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AonDon
	else if( m_InputDMARunning ) 
		_WrL3Data(0xa2,0); 	// 1010 0010	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AonDoff		
	else if( m_OutputDMARunning )
		_WrL3Data(0xa1,0); 	// 1010 0001	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AoffDon
	else
		_WrL3Data(0xa0,0); 	// 1010 0000	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AoffDoff
#else
	_WrL3Addr(0x14+2); 		//STATUS (000101xx+10)	
	_WrL3Data(0xa1,0); 	// 1010 0011	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AonDon
#endif	
	//RETAILMSG(DBG_ON, (TEXT("-Codec_channel\r\n")));
	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.
    _WrL3Addr(UDA1341_ADDR_DATA0);
    _WrL3Data(ucGain, 0); 

    return MMSYSERR_NOERROR;
}

MMRESULT HardwareContext::SetOutputMute (BOOL fMute)
{
    m_fOutputMute = fMute;


    _WrL3Addr(UDA1341_ADDR_DATA0);
    _WrL3Data(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()
{
	
	RETAILMSG(DBG_ON, (TEXT("+IIS InitCodec\r\n")));

	g_pIOPregs->GPGCON = g_pIOPregs->GPGCON & ~( (0x3<<4)|(0x3<<2)|(0x3<<0) ); 
	g_pIOPregs->GPGCON |= ((0x1<<4) |(0x1<<2) |(0x1<<0));
#ifdef EVT1	
	g_pIOPregs->EXTINT1 = READEXTINT1(g_pIOPregs->EXTINT1) | (1<<11)|(1<<7)|(1<<3);
#else 
	g_pIOPregs->GPGUDP  = g_pIOPregs->GPGUDP & ~(0x3f<<0) | (2<<4)|(2<<2)|(2<<0);	// 1:Pull-Down disable
#endif
	g_pIOPregs->GPGDAT = (g_pIOPregs->GPGDAT & ~(L3M|L3C|L3D)) |(L3M|L3C);  //Start condition : L3M=H, L3C=H	
	   
	/****** 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); 	// 0110 0000: reset, 256fs, no DCfilter, iis bus

	_WrL3Addr(0x14+2); 	//STATUS (000101xx+10)
	_WrL3Data(0x20,0); 	// 0010 0000: no reset, 256fs, no DCfilter, iis bus

	_WrL3Addr(0x14+2); 	//STATUS (000101xx+10)
	_WrL3Data(0xa1,0); 	// 1010 0001	: OGS 0db, IGS 6db, ADC_NI, DAC_NI, sngl speed, ADC on DAC on	
#else
	RETAILMSG(1,(TEXT("384 clock\r\n")));
	_WrL3Addr(0x14+2); 	//STATUS (000101xx+10)
	_WrL3Data(0x50,0); 	//0101 0000: Reset, 384fs, IIS bus, no DCfilter

	_WrL3Addr(0x14+2); 	//STATUS (000101xx+10)
		_WrL3Data(0x10,0); 	// 0001 0000: No reset, 384fs, IIS bus, no DCfilter

	_WrL3Addr(0x14+2); 	//STATUS (000101xx+10)	
	_WrL3Data(0xa1,0); 	// 1010 0011: OGS 0db, IGS 6db, PAD noninvert, PDA noninvert, single speed, ADC on DAC on
#endif
	_WrL3Addr(0x14 + 0); 	//DATA0 (000101xx+00)
	_WrL3Data(0xc2,0);	 // 1100 0010: DATA0, Extended addr(010) 
	_WrL3Data(0x4d,0);	 // 111 111 01: DATA0, MS=9dB, Ch1=on Ch2=on

	RETAILMSG(DBG_ON, (TEXT("-IIS InitCodec\r\n")));

	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()
{

	RETAILMSG(DBG_AUDIO,(TEXT("+++InitOutputDMA\n")));

	//----- 1. Initialize the DMA channel for output mode and use the first output DMA buffer -----
    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	= IISFIFTX_PHYS; 
	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
#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->DMAREQSEL2 = (DMAREQSEL_I2SSDO) |(1<<0);	// HW_SEL
	
	//----- 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()
{
	volatile int i=0;
	static int tmp=0;
	
	g_ForCount=1;
	RETAILMSG(DBG_ON, (TEXT("StartOutputDMA\n")));
	
	//RETAILMSG(1, (TEXT("#####Start OUTPUT DMA.\r\n")));
	if(!m_OutputDMARunning)
	{
		//RETAILMSG(1, (TEXT("### it's the first time\r\n")));
		//----- 1. Initialize our buffer counters -----
		m_OutputDMARunning=TRUE;
		Codec_channel();	
		//--------------------------- for short length audio file hsjang 060518 ------------------------------
		if (g_NeedtoSleep)
		{
			Sleep(15);
		}
		// -------------------------------------------------------------------------------------------
		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);
		RETAILMSG(DBG_ON,(TEXT("OutputTransferred=%d\n"), OutputTransferred));
		// Turn ON output channel
		//----- 3. If we did transfer any data to the DMA buffers, go ahead and enable DMA -----

		if(OutputTransferred)
	   {
		   //RETAILMSG(1, (TEXT("### it's the first time ########\r\n")));
			//----- 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;
			}

			////////////////////////////////////////////////////////////////////////////////
			// To correct left/right channel on ouput stream,
			// You should reset IISCON[0] bit.
			Lock();
			
			/*
			g_pIISregs->IISCON  &= ~IIS_INTERFACE_ENABLE;	// interface disable
			
			g_pIISregs->IISCON  |= TRANSMIT_DMA_REQUEST_ENABLE;
			g_pIISregs->IISCON  &= ~TRANSMIT_IDLE_CMD;	// Not Idle.(channel no stop)
			*/
			//g_pIISregs->IISMOD  &= ~(1<<9|1<<8); //IIS_TRANSMIT_MODE;	// Transmit only 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

			//RETAILMSG(1,(TEXT("+")));
			//RETAILMSG(1,(TEXT("-")));
			
			AUDIO_OUT_DMA_ENABLE();

			// wait for DMA to start.
			delay_count = 0;
	        	while((g_pDMAregs->DSTAT2&0xfffff)==0) // wait until DSTAT2 becomes zero
			{
	        	      if( delay_count++ > DELAY_COUNT )	break; // if delay count is over DELAY_COUNT defined for TIMEOUT
	        	}
			if(delay_count>DELAY_COUNT) RETAILMSG(1, (TEXT("TimeOut!!!\n")));
			
			//g_pIISregs->IISCON  |= IIS_INTERFACE_ENABLE;

			

			Unlock();
			////////////////////////////////////////////////////////////////////////////////

			// change the buffer pointer
			SELECT_AUDIO_DMA_OUTPUT_BUFFER_B();
			// Set DMA for B Buffer

		

		}
		else	// We didn't transfer any data, so DMA wasn't enabled
		{
		RETAILMSG(DBG_AUDIO,(TEXT("<<<<m_OutputDMARunning=FALSE; >>>>>\n")));
			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()
{
	//RETAILMSG(DBG_ON, (TEXT("+StopOutputDMA\r\n")));
	//----- 1. If the output DMA is running, stop it -----
	if (m_OutputDMARunning)
	{
		m_OutputDMAStatus = DMA_CLEAR;				
		//StopI2SClock();
		AUDIO_OUT_DMA_DISABLE();
		AUDIO_OUT_CLEAR_INTERRUPTS();
		/*
		g_pIISregs->IISCON &= ~TRANSMIT_DMA_REQUEST_ENABLE;	// Disable TX DMA
		g_pIISregs->IISCON |= TRANSMIT_IDLE_CMD;		// TXCHPAUSE
		*/
		//g_pIISregs->IISMOD  &= ~IIS_TRANSMIT_MODE;		// reserved
		AudioMute(DMA_CH_OUT, TRUE);		
	}

	m_OutputDMARunning = FALSE;
	Codec_channel();
	g_ForCount=1;
	//RETAILMSG(DBG_ON, (TEXT("-StopOutputDMA\r\n")));

}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 SC2443

⌨️ 快捷键说明

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