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

📄 iis.c

📁 MBA2440(s3c2440)的 源代码文件 ARM920T内核。
💻 C
字号:
/***********************************************************
 *
 * File Name: Iis.c
 * Description: S3C2440A IIS controller Function Test
 * Version: 0.2 

 * History:
 * 		0.0: 2002. 03. 06, Programming Start by SOP.
 * 		0.1: 2004. 02. 04, Modified by Y. H. Lee.
 * 		- IIS Master Tx: Play Sample Wave File.
 * 		- IIS Master Rx: Record Sound using MIC and Play it.
 * 		- IIS maser clock selection (PCLK or MPLLin) is supported.
 * 		0.2: 2004. 04. 26, Modified by Y. H. Lee.
 * 		- Recording Sound via Line-In is available in the MBA24402440 base board (Rev 0.19).
************************************************************/

#include "2440addr.h"
#include "2440lib.h"
#include "def.h"
#include "iis.h"

#define REC_LEN_IIS 	0xfffff*2
#define PLAY_IIS		0
#define RECORD_MICIn	1
#define RECORD_LineIn	2 
 
#define L3C (1<<4)		  //GPB4 = L3CLOCK
#define L3D (1<<3)		  //GPB3 = L3DATA
#define L3M (1<<2)		  //GPB2 = L3MODE

#define DOWNLOAD_ADDR				0x31000000

#define WAV_FMT_wChannels			*(unsigned short *)(DOWNLOAD_ADDR + 4 + 0x16)
#define WAV_FMT_dwSamplePerSec		*(unsigned int   *)(DOWNLOAD_ADDR + 4 + 0x18)
#define WAV_FMT_wBitsPerSample		*(unsigned int   *)(DOWNLOAD_ADDR + 4 + 0x22)
#define WAV_FMT_chunk_Size			*(unsigned int   *)(DOWNLOAD_ADDR + 4 + 0x28)



char mute = 1;
//char which_Buf = 1;
char Rec_Done = 0;

unsigned char *Buf,*_temp;
unsigned char *rec_buf = (unsigned char *)DOWNLOAD_ADDR;


unsigned short wchannel, wbps;
unsigned int size, fs; 
unsigned int save_B, save_E, save_PB, save_PE;

extern U32 Hclk, Pclk;
float IIS_Codec_CLK;


void IIS_Port_Init(void);
void IIS_Port_Return(void);
void Download_Wave_File(void);
void IIS_RecSound_DMA1( int mode, U32 rec_size);
void IIS_PlayWave_DMA2(unsigned char *start_addr, U32 play_size);

void _WrL3Addr(U8 data);
void _WrL3Data(U8 data,int halt);

void __irq RxInt(void);
void __irq Muting(void);
void __irq DMA2_Done(void);
void __irq DMA1_Rec_Done(void);


void * func_iis_test[][2]=
{	
	//IIS Function Test Item
	(void *)Play_Wave_IIS,				"Play Wave File. ",
   	(void *)RecordSound_ViaMICIn_IIS,	"Record Sound via MIC-In and Play it. ",
   	(void *)RecordSound_ViaLineIn_IIS, 	"Record Sound via Line-In and Play it. ",
   	0,0
};

void IIS_Test(void)
{
	int i, sel;
		
	while(1)
	{
		i=0;
		Uart_Printf("+------------------[ IIS test ]-------------------+\n");
		while(1)
		{   //display menu
			Uart_Printf("| %2d:%s\n",i+1,func_iis_test[i][1]);
			i++;
			if((int)(func_iis_test[i][0])==0)	break;
		}
		Uart_Printf("| %2d:Previous menu\n", i+1);
		Uart_Printf("+-------------------------------------------------+\n");
		Uart_Printf(" Select the number to test : ");
		sel = Uart_GetIntNum();
		sel--;
		Uart_Printf("+-------------------------------------------------+\n\n\n");
		if(sel == i){
			return;
		}if(sel>=0 && (sel<((sizeof(func_iis_test)-1)/8)) ){
			( (void (*)(void)) (func_iis_test[sel][0]) )();
		}else{
			Uart_Printf("Wrong number seleted.. Try again!!\n\n\n");
		}
	}
	
}

//Play Wave File
void Play_Wave_IIS(void)
{
	Uart_Printf("\nPlay Wave File.\n");

	IIS_Port_Init();
	Download_Wave_File();

	Init1341(PLAY_IIS);
	IIS_PlayWave_DMA2(Buf+0x30, size);

	IIS_Port_Return();
    
	mute = 1;
}

//Record Sound via MIC-In
void RecordSound_ViaMICIn_IIS(void)
{
	Uart_Printf("\nRecord Sound via MIC-In.\n");

	IIS_Port_Init(); 
	
	Init1341(RECORD_MICIn);
	IIS_RecSound_DMA1(RECORD_MICIn, REC_LEN_IIS);
	Init1341(PLAY_IIS);
	IIS_PlayWave_DMA2(rec_buf, REC_LEN_IIS);

	IIS_Port_Return();
	
	mute = 1;
	Uart_Printf("\n\n");
}

//Record Sound via Line-In 
void RecordSound_ViaLineIn_IIS(void)
{
	Uart_Printf("\nRecord Sound via Line-In.\n");

	IIS_Port_Init(); 
	
	Init1341(RECORD_LineIn);
	IIS_RecSound_DMA1(RECORD_LineIn, REC_LEN_IIS);
	Init1341(PLAY_IIS);
	IIS_PlayWave_DMA2(rec_buf, REC_LEN_IIS);

	IIS_Port_Return();
	
	mute = 1;
}


/* Sub-Routines */ 

//Setting Port related to IIS  
void IIS_Port_Init(void)
{
	Uart_Select(0);
	Uart_TxEmpty(0);
	Delay(0);	//calibrate Delay()

	save_B  = rGPBCON;	 
	save_E  = rGPECON;	 
	save_PB = rGPBUP;
	save_PE = rGPEUP;
    	
	//----------------------------------------------------------
	//   PORT B GROUP
	//Ports  :   GPB4    GPB3   GPB2  
	//Signal :  L3CLOCK L3DATA L3MODE
	//Setting:   OUTPUT OUTPUT OUTPUT 
	//	        [9:8]   [7:6}  [5:4]
	//Binary :     01  ,   01    01 
	//----------------------------------------------------------    
	rGPBUP  = rGPBUP  & ~(0x7<<2) | (0x7<<2);   //The pull up function is disabled GPB[4:2] 1 1100    
	rGPBCON = rGPBCON & ~(0x3f<<4) | (0x15<<4); //GPB[4:2]=Output(L3CLOCK):Output(L3DATA):Output(L3MODE)

	//----------------------------------------------------------
	//   PORT E GROUP
	//Ports  :  GPE4    GPE3   GPE2  GPE1    GPE0 
	//Signal : I2SSDO  I2SSDI CDCLK I2SSCLK I2SLRCK 
	//Binary :   10  ,   10     10 ,  10	10    
	//----------------------------------------------------------
	rGPEUP  = rGPEUP  & ~(0x1f)  | 0x1f;    //The pull up function is disabled GPE[4:0] 1 1111
	rGPECON = rGPECON & ~(0x3ff) | 0x2aa;   //GPE[4:0]=I2SSDO:I2SSDI:CDCLK:I2SSCLK:I2SLRCK

	rGPFUP   = ((rGPFUP   & ~(1<<0)) | (1<<0));     //GPF0
	rGPFCON  = ((rGPFCON  & ~(3<<0)) | (1<<1));     //GPF0=EINT0    
	rEXTINT0 = ((rEXTINT0 & ~(7<<0)) | (2<<0));     //EINT0=falling edge triggered  
}

void IIS_Port_Return(void)
{
	rGPBCON = save_B;
	rGPECON = save_E;
	rGPBUP  = save_PB;
	rGPEUP  = save_PE;
}

void Download_Wave_File(void)
{
	unsigned int temp, i;

	pISR_UART0 = (unsigned)RxInt;
	rINTMSK    = ~(BIT_UART0);
	rINTSUBMSK = ~(BIT_SUB_RXD0);

	Buf   = (unsigned char *)DOWNLOAD_ADDR;
	_temp = Buf;

	Uart_Printf("\nDownload the PCM(no ADPCM) file by DNW serial port(With header)!!\n");
	Uart_Printf("Download Start Address: 0x%x\n", Buf);
	Uart_Printf("in DNW, select 'Serial Port->Transmit', and choose the file you wanna send\n");
	
	while(((unsigned int)_temp - (unsigned int)Buf) == 0)
	{
		Led_Display(1);
		i = 1;
		while(i != 3){
			Delay(1500);
			Led_Display(1<<i);
			i++;
		}
		while(i != 0){
			Delay(1500);
			Led_Display(1<<i);
			i--;
		}
		Delay(1500);
	}
    
    //size value defined by DNW Serial tranmit
	size = *(Buf) | *(Buf + 1)<<8 | *(Buf + 2)<<16 | *(Buf + 3)<<24;
	Uart_Printf("\nNow, Downloading... [ File Size : %7d  	    0bytes]", size);
      
	while(((unsigned int)_temp - (unsigned int)Buf) < size) 
		Uart_Printf("\b\b\b\b\b\b\b\b%7d ",(unsigned int)_temp - (unsigned int)Buf);
	
	Uart_Printf("\b\b\b\b\b\b\b\b%7d ]\n",(unsigned int)_temp - (unsigned int)Buf);

	rINTSUBMSK |= BIT_SUB_RXD0;

	wchannel = WAV_FMT_wChannels;
	if(wchannel == 1)		Uart_Printf("This wave file is MONO\n");
	else if(wchannel == 2)	Uart_Printf("This wave file is STEREO\n");
	
	fs   = WAV_FMT_dwSamplePerSec;
	Uart_Printf("Sample rate per sec = %d Hz\n", fs);

	wbps = WAV_FMT_wBitsPerSample;
	Uart_Printf("bit resolution of sample = %d bits\n", wbps);

	size = WAV_FMT_chunk_Size;
	Uart_Printf("Sample PCM Data Size = %d\n", size);
}

void IIS_RecSound_DMA1(int mode, U32 rec_size)
{
	pISR_DMA1  = (unsigned)DMA1_Rec_Done;

	rIISCON = (1<<4) + (1<<3) + (1<<1);	   
	rIISMOD = (0<<9)+(0<<8) + (1<<6) + (0<<5) + (0<<4) + (1<<3) + (0<<2) + (1<<0);
	rIISFCON = (1<<14) + (1<<12);	  
    	
	Uart_Printf("\nIISLRCK = %d Hz", (int) IIS_Codec_CLK/384);

 	rINTMSK = ~(BIT_DMA1);

	//--- DMA1 Initialize
	rDISRCC1 = (1<<1) + (1<<0);   
	rDISRC1  = ((U32)IISFIFO);    
	rDIDSTC1 = (0<<1) + (0<<0);     
	rDIDST1  = (int)rec_buf;                            
	rDCON1   = (1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)+(1<<22)+(1<<20)+(rec_size/2);
	rDMASKTRIG1 = (0<<2) + (1<<1) + 0;    //No-stop, DMA1 channel on, No-sw trigger

	if(mode ==1)
	Uart_Printf("\n\nAre you ready to record sound via MIC-In on MBA24402440?");
	if(mode ==2)
	Uart_Printf("\n\nAre you ready to record sound via Line-In on MBA24402440?");
	
	Uart_Printf("\nPress any key to start record!\n");
	Uart_Getch();
	Uart_Printf("Recording...\n");
   
   	//IIS Rx start
	rIISCON |= 0x1;
   
	while(!Rec_Done)
	{
		Uart_Printf(".");
		Delay(2000);
	}
   
	Rec_Done = 0;

	//IIS Rx stop
	Delay(10);				//For end of H/W Rx
	rIISCON     = 0x0;			//IIS stop
	rDMASKTRIG1 = (1<<2);	//DMA1 stop
	rIISFCON    = 0x0;			//For FIFO flush
	
	rINTMSK  |= (BIT_DMA1);
	Uart_Printf("\nEnd of Record!\n");	
}


void IIS_PlayWave_DMA2(unsigned char *start_addr, U32 play_size)
{
	pISR_DMA2  = (unsigned)DMA2_Done;
	pISR_EINT0 = (unsigned)Muting;

	Uart_Printf("\nIIS Master CLK(PCLK) = %4.2f MHz", Pclk/MEGA);

	if(fs==44100)
    {
        rIISPSR = (3<<5) + 3;
		IIS_Codec_CLK = (float)Pclk/4;
		Uart_Printf("\nIIS Codec CLK = %4.2f MHz", IIS_Codec_CLK/MEGA);
    }
    else if(fs==22050)
    {
        rIISPSR = (11<<5) + 11;
		IIS_Codec_CLK = (float)Pclk/12;
		Uart_Printf("\nIIS Codec CLK = %4.2f MHz", IIS_Codec_CLK/MEGA);
    }
    
   	//TX DMA service enable, Rx channel idle, IIS prescaler enable
	rIISCON = (1<<5)+(1<<2)+(1<<1);
	rIISMOD = (0<<9)+(0<<8)+(2<<6)+(0<<5)+(0<<4)+(0<<2)+(1<<0);
	if(wbps == 8)			rIISMOD |= (0<<3);
	else if(wbps == 16)		rIISMOD |= (1<<3);
	rIISFCON = (1<<15)+(1<<13);

	Uart_Printf("\nIISLRCK = %d Hz", (int) IIS_Codec_CLK/256);

	rINTMSK    = ~(BIT_EINT0 | BIT_DMA2);
	
	//DMA2 Register Setting 
	rDISRC2  = (int)(start_addr);
	rDISRCC2 = (0<<1) + (0<<0);
	rDIDST2  = ((U32)IISFIFO);
	rDIDSTC2 = (0<<2) + (1<<1) + (1<<0);
	rDCON2   = (1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(0<<24)+(1<<23)+(0<<22)+(1<<20)+(play_size/2);
	rDMASKTRIG2 = (0<<2) + (1<<1) + (0<<0);	    //No-stop, DMA2 channel On, and No-sw trigger 
    
	Uart_Printf("\nIf you want to mute or no mute, Push the 'EIN0' button repeatedly.\n");
	Uart_Printf("Press any key to exit!\n");
	Uart_Printf("\nPlay...\n");
  
	//IIS Tx Start
	rIISCON |= 0x1;		 //IIS Interface start
		
	while(!Uart_GetKey());
    	
	//IIS Tx Stop
	Delay(10);			 //For end of H/W Tx
	rIISCON	&= ~(1<<0);	    //IIS Interface stop

	rDMASKTRIG2  = (1<<2);	 //DMA2 stop
	rIISFCON = 0x0;	    //For FIFO flush
		
	rINTMSK |= (BIT_EINT0 | BIT_DMA2);
	 	
	Uart_Printf("\nEnd of Play!\n");
}

//Initialization of UDA1341 Audio Codec using L3 Interface 
void Init1341(int mode)
{
 	//Port Initialize
	//----------------------------------------------------------
	//   PORT B GROUP
	//Ports  :   GPB4    GPB3   GPB2  
	//Signal :  L3CLOCK L3DATA   L3MODE
	//Setting:  OUTPUT   OUTPUT  OUTPUT 
	//	          [9:8]       [7:6]      [5:4]
	//Binary :    01,          01,        01 
	//----------------------------------------------------------    
	rGPBDAT = rGPBDAT & ~(L3M|L3C|L3D) |(L3M|L3C); //Start condition : L3M=H, L3C=H
	rGPBUP  = rGPBUP  & ~(0x7<<2) |(0x7<<2);	 //The pull up function is disabled GPB[4:2] 1 1100    
	rGPBCON = rGPBCON & ~(0x3f<<4) |(0x15<<4);     //GPB[4:2]=Output(L3CLOCK):Output(L3DATA):Output(L3MODE)

	//L3 Interface
	_WrL3Addr(0x14 + 2);     //STATUS (000101xx+10)
 	_WrL3Data(0x60,0);	 //0,1,01, 000,0 : Status 0,Reset, 384fs,IIS-bus,no DC-filtering
	
	_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(0x81,0);	 //bit[7:0] => 1,0,0,0, 0,0,01 

	//Record Sound via MIC In
	if(mode == RECORD_MICIn)
	{
		_WrL3Addr(0x14 + 2);    //STATUS (000101xx+10)
		_WrL3Data(0xa2,0);	//bit[7:0] => 1,0,1,0,0,0,10
		
		_WrL3Addr(0x14 + 0);    //DATA0 (000101xx+00)
		_WrL3Data(0xc2, 0);	//1100 0,010  : Extended addr(3bits), 010 
		_WrL3Data(0xf2, 0);	//111,100,10 : DATA0, MIC Amplifier Gain 21dB, input channel 2 select (input channel 1 off)
	}
    	
	//Record Sound via Line In
	if(mode == RECORD_LineIn)
	{
		_WrL3Addr(0x14 + 2);    //STATUS (000101xx+10)
		_WrL3Data(0xa2,0);	//bit[7:0] => 1,0,1,0, 0,0,10 
		
		_WrL3Addr(0x14 + 0);    //DATA0 (000101xx+00)
		_WrL3Data(0xc2, 0);	//1100 0,010  : Extended addr(3bits), 010 
		_WrL3Data(0xf1, 0);	//111,100,01 : DATA0, MIC Amplifier Gain 21dB, input channel 1 select (input channel 2 off)
	}	    	
}


void _WrL3Addr(U8 data)
{	 
 	S32 i,j;

	rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | L3C;	//L3D=L, L3M=L(in address mode), L3C=H

	for(j=0;j<4;j++);	 //tsu(L3) > 190ns

	//GPB[4:2]=L3C:L3D:L3M
	for(i=0;i<8;i++)	//LSB first
	{
	  	if(data & 0x1)	//If data's LSB is 'H'
	  	{
			rGPBDAT &= ~L3C;	 //L3C=L
			rGPBDAT |= L3D;		 //L3D=H		 
			for(j=0;j<4;j++);	        //tcy(L3) > 500ns
			rGPBDAT |= L3C;		 //L3C=H
			rGPBDAT |= L3D;		 //L3D=H
			for(j=0;j<4;j++);	        //tcy(L3) > 500ns
	  	}
	  	else		//If data's LSB is 'L'
	  	{
			rGPBDAT &= ~L3C;	//L3C=L
			rGPBDAT &= ~L3D;	//L3D=L
			for(j=0;j<4;j++);	       //tcy(L3) > 500ns
			rGPBDAT |= L3C;	       //L3C=H
			rGPBDAT &= ~L3D;	//L3D=L
			for(j=0;j<4;j++);	       //tcy(L3) > 500ns		
	  	}
	  	data >>= 1;
	}

	rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | (L3C | L3M);	 //L3M=H,L3C=H   
}


void _WrL3Data(U8 data,int halt)
{
 	S32 i,j;

	if(halt)
	{
	  	rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | L3C;   //L3C=H(while tstp, L3 interface halt condition)	  
	  	for(j=0;j<4;j++);		//tstp(L3) > 190ns
    }

	rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | (L3C | L3M);   //L3M=H(in data transfer mode)	  
	for(j=0;j<4;j++);		//tsu(L3)D > 190ns

	//GPB[4:2]=L3C:L3D:L3M
	for(i=0;i<8;i++)
	{
	  	if(data & 0x1)	//if data's LSB is 'H'
	  	{
	     		rGPBDAT &= ~L3C;		//L3C=L
	     		rGPBDAT |= L3D;			//L3D=H

	     		for(j=0;j<4;j++);			//tcy(L3) > 500ns
	     		rGPBDAT |= (L3C | L3D);	//L3C=H,L3D=H
	     		for(j=0;j<4;j++);		 	//tcy(L3) > 500ns
	  	}
	  	else		//If data's LSB is 'L'
	  	{
	     		rGPBDAT &= ~L3C;	//L3C=L
	     		rGPBDAT &= ~L3D;	//L3D=L
	     		for(j=0;j<4;j++);		//tcy(L3) > 500ns
	     		rGPBDAT |= L3C;		//L3C=H
	     		rGPBDAT &= ~L3D;	//L3D=L
	     		for(j=0;j<4;j++);		//tcy(L3) > 500ns
	  	}
		data >>= 1;		//For check next bit
	}

	rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | (L3C | L3M);    //L3M=H,L3C=H
}


/* ISRs */
void __irq DMA1_Rec_Done(void)
{
    ClearPending(BIT_DMA1);     //Clear pending bit
    Rec_Done = 1;
} 

void __irq DMA2_Done(void)
{
	rIISCON	&= ~(1<<0);
	rIISCON |= 0x1;
	
    ClearPending(BIT_DMA2); //Clear pending bit
	Uart_Printf("\n~~~");
	//Uart_Printf("\nrIISMOD=0x%x\n",rIISMOD);
}

void __irq RxInt(void)
{
	rSUBSRCPND = BIT_SUB_RXD0;	    //Clear pending bit (Requested)
	rSUBSRCPND;
	ClearPending(BIT_UART0);

	*_temp++ = RdURXH0(); 
}

void __irq Muting(void)
{
    ClearPending(BIT_EINT0);		//Clear pending bit

    if(mute)    //Mute
    {
	  _WrL3Addr(0x14 + 0);		//DATA0 (000101xx+00)
	  _WrL3Data(0xa4,0);		  //10,1,00,1,00 : after, no de-emp, mute, flat 
	  mute = 0;
	  Uart_Printf("\nMute on...\n");
    }
    else	  //No mute
    {
	  _WrL3Addr(0x14 + 0);		//DATA0 (000101xx+00)
	  _WrL3Data(0xa0,0);		  //10,1,00,0,00 : after, no de-emp, no mute, flat 
	  mute = 1;
	  Uart_Printf("\nMute off...\n");
    }
}

⌨️ 快捷键说明

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