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

📄 i2s.cpp

📁 s3c2443的Wavedev代码,觉对好用.
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

   
Module Name:	I2S.CPP

Abstract:		I2S Interface Routines for Samsung SC2443 CPU
  
Notes:			This code assumes that the CPU acts as the master that is 
				connected to a CODEC chip configured in slave mode.

				Some platforms require the audio CODEC chip to act as the master
				while the CPU's IIS controller is put into slave mode.  For these
				environments, the IIS_MASTER_MODE flag (located in I2S_Init())
				should be replaced with the IIS_SLAVE_MODE flag.

Environment:	Samsung SC2443 CPU and Windows 3.0 (or later)

-2005.11.12 - DonGo.

-*/

#include <windows.h>
#include <s3c2443.h>
#include "i2s.h"
#include <bsp_cfg.h>

//------------------------------ GLOBALS -------------------------------------------
extern volatile	S3C2443_IISBUS_REG *g_pIISregs;								// I2S control registers
extern volatile S3C2443_IOPORT_REG *g_pIOPregs;								// GPIO registers (needed to enable SPI)
extern volatile S3C2443_CLKPWR_REG *g_pCLKPWRreg;							// CLCKPWR (needed to enable SPI clocks)
//----------------------------------------------------------------------------------

// Display debug message.
#define DBG_ON 0 

#ifdef DEBUG
#define ZONE_ERROR  1
#endif


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		I2S_Init()

Description:	Initializes the IIS bus and controller.

Notes:			This routine assumes that the control registers (see 
				the globals section above) have already been initialized.

Returns:		Boolean indicating success.
-------------------------------------------------------------------*/
#define I2S_BIT_CLK_TIMES	32		//which times of I2SLRCK?
#define I2S_CODEC_CLK_TIMES	384		//which times of I2SLRCK?

BOOL I2S_Init()
{
	volatile UINT i = 0;
	volatile UINT count = 0;
	volatile UINT prescaler = 0;

//	float I2S_Codec_CLK;
	
	RETAILMSG(DBG_ON, (TEXT("+I2S_Init\n")));

   	//-------------------------------------------------------------------------------
	//PORT E GROUP
	//Ports  :	 GPE4			 GPE3			 GPE2		   GPE1			GPE0 
	//Signal :	I2S DO		   I2S DI		 CDCLK		I2S CLK		I2S LRCLK
	//Binary :   10,				10,			 10,			  10,			  10,			10	
	//-------------------------------------------------------------------------------
	g_pIOPregs->GPECON = g_pIOPregs->GPECON & ~(0x3ff) | 0x2aa;


	//IIS Pre-scaler Setting...The following value is not valid...
	g_pIISregs->IISPSR &= 0;
	g_pIISregs->IISPSR |= IIS_PRESCALER_ENABLE |(2<<8);  	// PCLK(50Mhz)/(2+1)=16.9Mhz

	// Disable all the activities
	g_pIISregs->IISCON  = (1<<6)+(1<<5)+(1<<4)+(1<<3)+(0<<2)+(0<<1)+(0<<0);
	for(i=0; i<10; i++);

	g_pIISregs->IISCON  = (TRANSMIT_DMA_REQUEST_ENABLE | RECEIVE_DMA_REQUEST_ENABLE);

	g_pIISregs->IISMOD  = (  IIS_MASTER_MODE | IIS_TRANSMIT_RECEIVE_MODE | ACTIVE_CHANNEL_LEFT
						   	| SERIAL_INTERFACE_IIS_COMPAT | MASTER_CLOCK_FREQ_384fs 
						   	| SERIAL_BIT_CLOCK_FREQ_32fs| DATA_16_BITS_PER_CHANNEL);

	prescaler = SetI2SClockRate(IS2LRCLK_44100);
	
	//----- 4. For power management purposes, shut the clocks off! -----
	//Configure IIS regs
	g_pIISregs->IISFIC &= ~((1<<15)|(1<<7));	// TXFIFO/RXFIFO flush.
	for(i=0; i<10; i++);
	g_pIISregs->IISFIC |= (1<<15)|(1<<7);	// TXFIFO/RXFIFO flush.
	for(i=0; i<10; i++);
	g_pIISregs->IISFIC &= ~((1<<15)|(1<<7));	// TXFIFO/RXFIFO flush.
	for(i=0; i<10; i++);

	//I2S_Codec_CLK = (float)((float)S3C2443_PCLK/(float)(prescaler+1));
	#if 0
	DWORD modeval = g_pIISregs->IISMOD;
	switch( (modeval>>10)&0x03 )
	{
		case 0:
			RETAILMSG(DBG_ON, (TEXT("I2S Master CLK(PCLK) = %ldHz\n"), S3C2443_PCLK));
			break;
		case 1:
			//if(g_pCLKPWRreg->CLKSRC&(1<<9))
				RETAILMSG(DBG_ON, (TEXT("I2S Master CLK: FOUT_mpll\n")));
			else
				RETAILMSG(DBG_ON, (TEXT("I2S Master CLK: EREFCLK\n")));
			break;
		case 2:
			RETAILMSG(DBG_ON, (TEXT("I2S Master CLK(PCLK) = %ldHz\n"), S3C2443_PCLK));			
			break;
		default:
			RETAILMSG(DBG_ON, (TEXT("I2S Master CLK Default!!!\n")));
			break;
	}
	RETAILMSG(DBG_ON,(TEXT("I2S Codec Clock=%ldHz\n"), (DWORD)(I2S_Codec_CLK)));
	RETAILMSG(DBG_ON,(TEXT("I2S Bit Clock=%ldHz\n"), (DWORD)((I2S_Codec_CLK/I2S_CODEC_CLK_TIMES)*I2S_BIT_CLK_TIMES)));
	RETAILMSG(DBG_ON,(TEXT("I2S Sampling Rate=%ldHz\n"), (DWORD)(I2S_Codec_CLK/I2S_CODEC_CLK_TIMES)));
	#else
	DWORD modeval = g_pIISregs->IISMOD;
	switch( (modeval>>10)&0x03 )
	{
		case 0:
			//RETAILMSG(1, (TEXT("I2S Master CLK(PCLK) = %ldHz\n"), S3C2443_PCLK));
			break;
		case 1:
			/*
			//if(g_pCLKPWRreg->CLKSRC&(1<<9))
				RETAILMSG(1, (TEXT("I2S Master CLK: FOUT_mpll\n")));
			else
				RETAILMSG(1, (TEXT("I2S Master CLK: EREFCLK\n")));
			break;*/
		case 2:
			RETAILMSG(1, (TEXT("I2S Master CLK(PCLK) = %ldHz\n"), S3C2443_PCLK));			
			break;
		default:
			RETAILMSG(1, (TEXT("I2S Master CLK Default!!!\n")));
			break;
	}
	//RETAILMSG(1,(TEXT("I2S Codec Clock=%ldHz\n"), (DWORD)(I2S_Codec_CLK)));
	//RETAILMSG(1,(TEXT("I2S Bit Clock=%ldHz\n"), (DWORD)((I2S_Codec_CLK/I2S_CODEC_CLK_TIMES)*I2S_BIT_CLK_TIMES)));
	//RETAILMSG(1,(TEXT("I2S Sampling Rate=%ldHz\n"), (DWORD)(I2S_Codec_CLK/I2S_CODEC_CLK_TIMES)));
	#endif
	RETAILMSG(DBG_ON, (TEXT("-I2S_Init\n")));

	//g_pIISregs->IISCON |= IIS_INTERFACE_ENABLE;				// Enable I2S clock

	return(TRUE);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		I2S_Deinit()

Description:	Deinitializes the I2S bus and controller.

Notes:			This routine DOES NOT unmap the control registers;
				the caller is responsible for freeing this memory.

Returns:		Boolean indicating success.
-------------------------------------------------------------------*/
BOOL I2S_Deinit()
{
	//----- 1. Stop the I2S clocks -----

	RETAILMSG(DBG_ON, (TEXT("I2S_Deinit()\n")));
	StopI2SClock();

	return TRUE;
}



/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		I2S_WriteData()

Description:	Outputs the specified data onto the I2S bus.

Notes:			This routine expects that the I2S clock is already
				running when it is called.

Returns:		Boolean indicating success.
-------------------------------------------------------------------*/
BOOL I2S_WriteData(LPWORD lpBuff, DWORD dwLen)
{
	
	return FALSE;
}


//------------------------------------ Helper Routines ------------------------------------

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		StartI2SClock()

Description:	Enables the I2S clock that drives the audio codec chip.

Returns:		N/A
-------------------------------------------------------------------*/
VOID StartI2SClock(VOID)
{
	g_pIISregs->IISCON |= IIS_INTERFACE_ENABLE;			// Disable the I2S clock
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		StopI2SClock()

Description:	Disables the I2S clock that drives the audio codec chip.

Returns:		N/A
-------------------------------------------------------------------*/
VOID StopI2SClock(VOID)
{
	g_pIISregs->IISCON &= ~IIS_INTERFACE_ENABLE;			// Disable the I2S clock
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		SetI2SClockRate()

Description:	Sets the I2S clock that drives the audio codec chip:

Params:			ClockRate	IS2LRCLK_800		800   Khz
							IS2LRCLK_11025		11025 Khz
							IS2LRCLK_16000		16000 Khz
							IS2LRCLK_22050		22050 Khz
							IS2LRCLK_32000		32000 Khz
							IS2LRCLK_44100		44100 Khz
							IS2LRCLK_48000		48000 Khz
							IS2LRCLK_64000		64000 Khz
							IS2LRCLK_88200		88200 Khz
							IS2LRCLK_96000		96000 Khz

Returns:		N/A
-------------------------------------------------------------------*/
int SetI2SClockRate(DWORD ClockRate)
{
	BYTE  prescaler;
	DWORD codeclock, i2scdclk;

	//----- 1. Set the clock rate  -----
	//		FORMAT:			bits[9:5] - Prescaler Control A
	//						bits[4:0] - Prescaler Control B
	//
	//						Range: 0-31 and the division factor is N+1 (a.k.a. 1-32)
	//
	//		The I2SLRCLK frequency is determined as follows:
	//
	//				I2SLRCLK = CODECLK / I2SCDCLK		and		(prescaler+1) = PCLK / CODECLK
	//
	//		Thus, rearranging the equations a bit we can see that:
	//
	//				prescaler = (PCLK / CODECLK) - 1 
	//		or
	//				prescaler = ((PCLK / (IS2LRCLK * IS2CDCLK)) - 1
	//	
	//		NOTE: The following formula is actually used in order to avoid floating point arithmetic:
	//
	//				prescaler = ((PCLK + ((IS2LRCLK * IS2CDCLK) - 1)) / (IS2LRCLK * IS2CDCLK)) - 1
	//
	if(g_pIISregs->IISMOD & MASTER_CLOCK_FREQ_384fs)
	{
		i2scdclk = 384;				// Sampling frequency
	}
	else
	{
		i2scdclk = 256;				// Sampling frequency
	}

	codeclock = ClockRate * i2scdclk;

	prescaler = (BYTE)((S3C2443_PCLK + (codeclock/2)) / codeclock + 0.5) - 1;

	RETAILMSG(DBG_ON,(TEXT("I2CCDCLK=%d --> Prescaler:%d\r\n"), i2scdclk, prescaler));
 
	//----- IMPORTANT: Make sure we set both channel prescalers to the same value (see datasheet for details) -----
	g_pIISregs->IISPSR = (g_pIISregs->IISPSR & ~(0x3ff<<0)) | (prescaler<<0) | IIS_PRESCALER_ENABLE;

		return prescaler;
}




⌨️ 快捷键说明

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