/*L3MODE:J7(GPB2);L3DATA:K3(GPB3);L3CLOCK:K4(GPB4)*/
#define L3DATA (1<<3)
#define L3CLOCK (1<<4)
void uda_io_init()
{
/*IISLRCLK=GPE0,IISSCLK=GPE1,CDCLK=GPE2,IISSDI=GPE3,IISSDO=GP4*/
GPECON|=(1<<1)|(1<<3)|(1<<5)|(1<<7)|(1<<9);
GPEUP|=(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0);;
GPBCON|=(1<<4)|(1<<6)|(1<<8);
GPBUP|=(1<<4)|(1<<3)|(1<<2);
}
void WriteL3(unsigned char data, unsigned char mode)
{
//mode = 0,地址模式;mode = 1,數據傳輸模式
int i, k;
uda_io_init();
if(mode == 0) //地址模式時序
{
GPBDAT = GPBDAT & ~(L3MODE|L3DATA|L3CLOCK )|L3CLOCK;
}
else //數據模式時序
{
GPBDAT = GPBDAT & ~(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE);
}
for(k = 0; k < 5; k++); //延時
for(i = 0; i < 8; i++)
{
if(data & 0x1)
{
GPBDAT &= ~L3CLOCK;
GPBDAT |= L3DATA; //發送高電平
for(k = 0; k < 5; k++);
GPBDAT |= L3CLOCK;
GPBDAT |= L3DATA;
for(k = 0; k < 5; k++);
}
else
{
GPBDAT &= ~L3CLOCK;
GPBDAT &= ~L3DATA; //發送低電平
for(k = 0; k < 5; k++);
GPBDAT |= L3CLOCK;
GPBDAT &= ~L3DATA;
for(k = 0; k < 5; k++);
}
data >>= 1;
}
GPBDAT = GPBDAT & ~(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE);
}
void record()
{
unsigned short int temp;
unsigned int i,stop=0,count=0;
GPBDAT = GPBDAT & ~(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE);
WriteL3(0x14+2,0);
WriteL3(0x60,1); //復位
WriteL3(0x14+2,0);
WriteL3(0x10,1); //00010000 系統時鐘頻率384fs
WriteL3(0x14+2,0);
WriteL3(0xa2,1); //10100010 輸入增益6db,ADC開,DAC關
WriteL3(0x14+0,0);
WriteL3(0x0,1); //音量衰減0db
WriteL3(0x7b,1); //01,1110,11 (BB 18dB~24dB) Treble 6dB
WriteL3(0x14+0,0);
WriteL3(0x90,1); //采樣頻率為44.1khz
WriteL3(0xc0,1);
WriteL3(0xe0,1); //000,00000 MA 0dB
WriteL3(0xc4,1);
WriteL3(0xf0,1); //100,1,00,00 AGC使能
WriteL3(0xc2,1);
WriteL3(0xf9,1); //010,110,11 MIC 27dB input 1選擇 通道2關閉
WriteL3(0xc6,1);
WriteL3(0xe0,1); //output lever -9db ATTACK TIME=11ms,DECAY TIME=100ms
/*IIS配置*/
IISCON = (0<<5)|(0<<4)|(1<<3)|(0<<2)|(1<<1); //DMA禁止,在接受空閑狀態,不產生IISLRCK信號,IIS預分頻使能
IISMOD = (0<<9)|(0<<8)|(1<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0); //主設備時鐘PCLK,主設備模式,接收模式,串行數據16位,主時鐘是384fs,串行位時鐘32fs
IISPSR = (2<<5)|2; //預分頻都是N=2
IISFCON = (0<<14)|(1<<12); //發送FIFO正常,發送FIFO使能
IISCON|=(1<<0); //iis開啟
while(stop==0)
if((IISCON & (1<<6))==0) //檢查輸入FIFO是否為滿
record_buffer[count+2*i+1]=(temp>>8);
}
count+=64;
}
}
IISCON = 0x0; //關閉IIS
GPBDAT|=1; //蜂鳴器輸出高點平
}
void playsound(unsigned char *buffer, int length)
char flag;
GPBDAT = GPBDAT & ~(L3MODE|L3CLOCK|L3DATA) |(L3MODE|L3CLOCK); //L3開始傳輸:L3M=H, L3C=H
//配置UDA1341
WriteL3(0x14 + 2,0); //狀態模式(000101xx+10)
WriteL3(0x60,1); //0,1,10, 000,0 : 狀態0,復位
WriteL3(0x14 + 2,0); //狀態模式 (000101xx+10)
WriteL3(0x10,1); //0,0,01, 000,0 : 狀態0, 384fs,IIS,no DC-filtering
WriteL3(0x14 + 2,0); //狀態模式 (000101xx+10)
WriteL3(0xc1,1); //1,0,0,0, 0,0,01:狀態1,
//Gain of DAC 6 dB,Gain of ADC 0dB,ADC non-inverting,
//DAC non-inverting,Single speed playback,ADC-Off DAC-On
//配置s3c2440的IIS寄存器
//預分頻器為2,所以CDCLK=PCLK/(3+1)=16.928kHz
IISPSR = 2<<5|2;
//無效DMA,輸入空閑,預分頻器有效
IISCON = (0<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1);
//PCLK為時鐘源,輸出模式,IIS模式,每個聲道16位,CODECLK=384fs,SCLK=32fs
IISMOD = (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0);
IISFCON = (0<<15)|(1<<13); //輸出FIFO正常模式,輸出FIFO使能
flag=1;
count=0;
//開啟IIS
IISCON |= 0x1;
while(flag)
{
if((IISCON & (1<<7))==0) //檢查輸出FIFO是否為空
{
//FIFO中的數據為16位,深度為32
//當輸出FIFO為空時,一次性向FIFO寫入32個16位數據
for(i=0;i<32;i++)
{
IISFIFO=(buffer[2*i+count])+(buffer[2*i+1+count]<<8);
}
count+=64;
if(count>length)
flag=0; //音頻數據傳輸完,則退出
}
}
IISCON = 0x0; //關閉IIS
}