?? iis.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 + -