📄 iis.c
字号:
/*======================================================================
Project Name : S3C2443
Copyright 2006 by Samsung Electronics, Inc.
All rights reserved.
Project Description :
This software is only for verifying functions of the S3C2443.
Anybody can use this code without our permission.
File Name : iis.c
Description : S3C2443 IIS module code
Author : Junon Jeon
Dept : AP
Created Date : 2006.06.02
Version : 0.0
History
R0.0 (2006.06.02): Junon draft
- S3C2443 IIS test code is derived from S3C2413A IIS test code.
=======================================================================*/
#include "System.h"
#include "iis.h"
#define IIS_BUFFER 0x31000000
#define REC_LEN_IIS 0xfffff*4 //Max value of DMA Transfer Counter (20bit) = 0xfffff, Date Size=Word (4bytes)
#define PLAY_IIS 0
#define RECORD_MIC_IN 1
#define RECORD_LINE_IN 2
#define RECORD_PLAY_SIM 3
#define L3C (1<<2) // GPG2 = L3CLOCK
#define L3D (1<<1) // GPG1 = L3DATA
#define L3M (1<<0) // GPG0 = L3MODE
// Global variables
char which_Buf = 1;
volatile char Rec_Done = 0;
unsigned char *Buf,*_temp;
unsigned char *rec_buf = (unsigned char *)(IIS_BUFFER+0x28);
unsigned char *rec_buf1 = (unsigned char *)(IIS_BUFFER + REC_LEN_IIS);
unsigned int size, fs;
unsigned int save_GPE_CON, save_GPG_CON;
unsigned int save_GPE_DAT, save_GPG_DAT;
float IIS_Codec_CLK;
// Functions
// GPIO port setting
void IIS_Port_Init(void);
void IIS_Port_Return(void);
// L3 inteface function for initializing UDM1341
void _WrL3Addr(unsigned char data);
void _WrL3Data(unsigned char data,int halt);
void Init1341(int);
// IIS library
unsigned int IIS_Select_SamplingRate(void);
void Select_IIS_Master_CLK(void);
void Select_PCLK(void);
void Select_EXTCLK(void);
void Select_EPLL(void);
void Select_EPLL_Ref_CLK(void);
void down_wav(void);
void __irq Rx_IIS_Int(void);
void __irq DMA1_Rec_Done(void);
void __irq DMA2_Done(void);
void __irq Play_Rec_Simul(void);
void Play_Iis(void);
void IIS_RecSound_DMA1( int mode, unsigned int rec_size);
void IIS_RecSound_DMA1_Repeat(unsigned char *start_addr, unsigned int rec_size);
void IIS_PlayWave_DMA2(unsigned char *start_addr, unsigned int play_size);
void IIS_Paly_Rec_Simul(unsigned char *start_addr, unsigned int play_size);
void IIS_RecSound_DMA1_SLV(int mode, unsigned int rec_size);
void RecordSound_ViaLineIn_SLV(void);
void Play_Iis_MASTER(void);
void Data_init(void);
void IIS_PlayWave_DMA2_MASTER(unsigned char *start_addr, unsigned int play_size);
void RecordSound_ViaLineIn_MASTER(void);
void IIS_RecSound_DMA1_MASTER(int mode, unsigned int rec_size);
void Play_Iis_SLAVE(void);
void IIS_PlayWave_DMA2_SLAVE(unsigned char *start_addr, unsigned int play_size);
void Play_Iis_EXTCLK(void);
void IIS_PlayWave_DMA2_EXTCLK(unsigned char *start_addr, unsigned int play_size);
void * func_iis_test[][2]=
{
//IIS Function Test Item
// "123456789012345678901"
(void *)Play_Iis, "Play Wave ",
(void *)RecordSound_ViaMICIn_Playit, "Record(MicIn) & Play ",
(void *)RecordSound_ViaLineIn_Playit, "Record(LineIn) & Play",
(void *)RECORD_PLAY_SIMtaneously, "Record and Play Simultaneously. ",
(void *)RecordSound_ViaLineIn_MASTER, "RECORD MASTER MODE",
(void *)Play_Iis_MASTER, "PLAY MASTER MODE ",
(void *)RecordSound_ViaLineIn_SLV, "RECORD SLAVE MODE",
(void *)Play_Iis_SLAVE, "PLAY SLAVE MODE ",
(void *)Play_Iis_EXTCLK, "PLAY EXT CDCLK ",
0,0
};
void Test_IIS(void)
{
int i;
while(1)
{
i=0;
printf("\n\n================== IIS Function Test =====================\n\n");
while(1)
{ //display menu
printf("%2d:%s",i,func_iis_test[i][1]);
i++;
if((int)(func_iis_test[i][0])==0)
{
printf("\n");
break;
}
if((i%1)==0)
printf("\n");
}
printf("\n==========================================================\n");
printf("Select #Item or Press Enter key to exit : ");
i = GetIntNum();
if(i==-1) break; // return.
if(i>=0 && (i<((sizeof(func_iis_test)-1)/8)) ) // select and execute...
( (void (*)(void)) (func_iis_test[i][0]) )();
}
}
//============================== [ IIS Drivers ] ===============================
// Setting Port related to IIS
void IIS_Port_Init(void)
{
save_GPG_CON = rGPGCON; // L3
save_GPE_CON = rGPECON; // IIS
//----------------------------------------------------------
//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
//----------------------------------------------------------
rGPGCON = rGPGCON & ~(0x3f) | (1<<4)|(1<<2)|(1); // output setting
//-------------------------------------------------------------------------------
//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
//-------------------------------------------------------------------------------
rGPECON = rGPECON & ~(0x3ff) | 0x2aa; // IIS function setting
rGPEUDP = 0xffffffff; // pull_up_down disable
}
void IIS_Port_Return(void)
{
rGPGCON = save_GPG_CON;
rGPECON = save_GPE_CON;
}
// L3 interface library
void _WrL3Addr(unsigned char data)
{
int i,j;
rGPGDAT = rGPGDAT & ~(L3D | L3M | L3C) | L3C; //L3D=L, L3M=L(in address mode), L3C=H
for(j=0;j<4;j++); //tsu(L3) > 190ns
for(i=0;i<8;i++) //LSB first
{
if(data & 0x1) //If data's LSB is 'H'
{
rGPGDAT &= ~L3C; //L3C=L
rGPGDAT |= L3D; //L3D=H
for(j=0;j<4;j++); //tcy(L3) > 500ns
rGPGDAT |= L3C; //L3C=H
rGPGDAT |= L3D; //L3D=H
for(j=0;j<4;j++); //tcy(L3) > 500ns
}
else //If data's LSB is 'L'
{
rGPGDAT &= ~L3C; //L3C=L
rGPGDAT &= ~L3D; //L3D=L
for(j=0;j<4;j++); //tcy(L3) > 500ns
rGPGDAT |= L3C; //L3C=H
rGPGDAT &= ~L3D; //L3D=L
for(j=0;j<4;j++); //tcy(L3) > 500ns
}
data >>= 1;
}
rGPGDAT = rGPGDAT & ~(L3D | L3M | L3C) | (L3C | L3M); //L3M=H,L3C=H
}
void _WrL3Data(unsigned char data,int halt)
{
int i,j;
if(halt)
{
rGPGDAT = rGPGDAT & ~(L3D | L3M | L3C) | L3C; //L3C=H(while tstp, L3 interface halt condition)
for(j=0;j<4;j++); //tstp(L3) > 190ns
}
rGPGDAT = rGPGDAT & ~(L3D | L3M | L3C) | (L3C | L3M); //L3M=H(in data transfer mode)
for(j=0;j<4;j++); //tsu(L3)D > 190ns
for(i=0;i<8;i++)
{
if(data & 0x1) //if data's LSB is 'H'
{
rGPGDAT &= ~L3C; //L3C=L
rGPGDAT |= L3D; //L3D=H
for(j=0;j<4;j++); //tcy(L3) > 500ns
rGPGDAT |= (L3C | L3D); //L3C=H,L3D=H
for(j=0;j<4;j++); //tcy(L3) > 500ns
}
else //If data's LSB is 'L'
{
rGPGDAT &= ~L3C; //L3C=L
rGPGDAT &= ~L3D; //L3D=L
for(j=0;j<4;j++); //tcy(L3) > 500ns
rGPGDAT |= L3C; //L3C=H
rGPGDAT &= ~L3D; //L3D=L
for(j=0;j<4;j++); //tcy(L3) > 500ns
}
data >>= 1; //For check next bit
}
rGPGDAT = rGPGDAT & ~(L3D | L3M | L3C) | (L3C | L3M); //L3M=H,L3C=H
}
//Initialization of UDA1341 Audio Codec using L3 Interface
void Init1341(int mode)
{
rGPGDAT = rGPGDAT & ~(L3M|L3C|L3D) |(L3M|L3C); //Start condition : L3M=H, L3C=H
if(mode == PLAY_IIS)
{ //L3 Interface
_WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
_WrL3Data(0x50,0); //0,1,01, 000,0 : Status 0,Reset, 384fs,IIS-bus,no DC-filtering
// _WrL3Data(0x60,0); //0,1,10, 000,0 : Status 0,Reset, 256fs,IIS-bus,no DC-filtering
// _WrL3Data(0x40,0); //0,1,00, 000,0 : Status 0,Reset, 512fs,IIS-bus,no DC-filtering
_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_MIC_IN)
{
_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_LINE_IN)
{
_WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
_WrL3Data(0xa2,0); //bit[7:0] => 1,0,1,0, 0,0,10 Gain of ADC 6dB, ADC(on) DAC(off)
_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 15dB, input channel 1 select (input channel 2 off)
}
// Record & play simultaneously
if(mode == RECORD_PLAY_SIM)
{
_WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
_WrL3Data(0xa3,0); // 1,0,1,0,0,0,11 : OGS=0,IGS=1,ADC_NI,DAC_NI,sngl speed,AonDon
_WrL3Addr(0x14 + 0); //DATA0 (000101xx+00)
_WrL3Data(0xc2,0); //11000,010 : DATA0, Extended addr(010)
_WrL3Data(0xff,0); //010,011,01 : DATA0, MS=9dB, Ch1=on Ch2=on
}
}
unsigned int IIS_Select_SamplingRate(void)
{
int i;
printf("\nSelect ADC/DAC Rate\n");
printf("0:11.025kHz, 1:22.05kHz, 2:44.1kHz, 3:88.2kHz\n");
printf("4:8kHz, 5:16kHz, 6:32kHz, 7:48kHz, 8:64kHz, 9:96kHz\n");
i = GetIntNum();
switch(i)
{
case 0:
return 11025;
case 1:
return 22050;
case 2:
return 44100;
case 3:
return 88200;
case 4:
return 8000;
case 5:
return 16000;
case 6:
return 32000;
case 7:
return 48000;
case 8:
return 64000;
case 9:
return 96000;
default:
return 44100;
}
}
// IIS source clock selection
void Select_PCLK(void)
{
unsigned int pdf = 5; // prescaler division factor
// SYSCON register setting
rPCLKCON |= (1<<9); // PCLK bus block of i2s enable
rSCLKCON |= (1<<9); // I2S source clock enable
rCLKDIV1 &= ~(0xf<<12); // I2S clock divider for EPLL.
// IIS clock register setting
rIISMOD = (rIISMOD & ~(7<<10)) | (0<<12)|(0<<10); // internal codec clock source, PCLK Master mode
rIISPSR = (1<<15)|(pdf); // prescaler enable, prescaler division factor[9:0]
//In case PCLK = 50 MHz, IIS Codec CLK = 50/(5+1) = 8.34MHz-->22KHz
printf("\nIIS Master CLK(PCLK) = %4.2f MHz", (float)PCLK/1000000);
IIS_Codec_CLK = (float)PCLK/(pdf+1);
printf("\nIIS Codec CLK = %4.2f MHz", IIS_Codec_CLK/1000000);
}
void Select_EXTCLK(void)
{
unsigned int pdf = 0; // prescaler division factor
printf("\n Board To Board Test Source Board is OK? \n");
// SYSCON register setting
rPCLKCON |= (1<<9); // PCLK bus block of i2s enable
rSCLKCON |= (1<<9); // I2S source clock enable
rCLKSRC = (rCLKSRC & ~(3<<14)) | (1<<14); // I2S first source clock selection
rCLKDIV1 &= ~(0xf<<12); // I2S clock divider for EPLL.
// IIS clock register setting
rIISMOD = (rIISMOD & ~(7<<10)) | (1<<12)|(1<<10); // Get Codec clock froem extenal codec chip, using codeclki master mode
rIISPSR = (1<<15)|(pdf); // prescaler enable, prescaler division factor[9:0]
}
void Select_EPLL(void)
{
unsigned int pdf = 10; // prescaler division factor
// SYSCON register setting
rPCLKCON |= (1<<9); // PCLK bus block of i2s enable
rSCLKCON |= (1<<9); // I2S source clock enable
rEPLLCON= (40<<16) | (1<<8) | 1; // EPLL OUT IS 96Mhz : (Mdiv<<16) | (Pdiv<<8) | Sdiv;
rCLKSRC = (rCLKSRC & ~(3<<14)) | (0<<14); // I2S source clock selection EPLL divided clock
rCLKSRC = (rCLKSRC & ~(1<<6)) | (1<<6); // ESYSCLK Soure is divided EPlL clock
rCLKDIV1 &= ~(0xf<<12); // I2S clock divider for EPLL.
Delay(100);
rGPHCON = (rGPHCON & ~(3<<28)) | (2<<28);
rMISCCR = (rMISCCR & ~(7<<8)) | (1<<8);
printf("Check EPLL OUT!! and Press Ant Key if You Want Go!!\n");
getchar();
// IIS clock register setting
rIISMOD = (rIISMOD & ~(7<<10)) | (0<<12)|(1<<10); // internal codec clock source, EPLL Div Master mode
rIISPSR = (1<<15)|(pdf); // prescaler enable, prescaler division factor[9:0]
}
void Select_EPLL_Ref_CLK(void)
{
unsigned int pdf = 1; // prescaler division factor
rPCLKCON |= (1<<9); // PCLK bus block of i2s enable
rSCLKCON |= (1<<9); // I2S source clock enable
rEPLLCON= (1<<24) | (40<<16) | (1<<8) | 1; // EPLL Off , EPLL OUT IS 96Mhz : (Mdiv<<16) | (Pdiv<<8) | Sdiv;
rCLKSRC = (rCLKSRC & ~(3<<14)) | (3<<14); // I2S source clock selection EPLL reference clock
rCLKSRC = (rCLKSRC & ~(1<<6)) | (0<<6); // ESYSCLK Soure is divided EPlL clock
rCLKDIV1 &= ~(0xf<<12); // I2S clock divider for EPLL.
Delay(100);
rGPHCON = (rGPHCON & ~(3<<28)) | (2<<28);
rMISCCR = (rMISCCR & ~(7<<8)) | (1<<8);
printf("Check EPLL OUT!! and Press Ant Key if You Want Go!!\n");
getchar();
// IIS clock register setting
rIISMOD = (rIISMOD & ~(7<<10)) | (0<<12)|(1<<10); // internal codec clock source, EPLL Div Master mode
rIISPSR = (1<<15)|(pdf); // prescaler enable, prescaler division factor[9:0]
}
void Select_IIS_Master_CLK(void)
{
int sel;
//unsigned short Sampling_Rate;
printf("\nSelect IIS Master Clock Source\n");
printf("0:PCLK[D], 1:IIS EXTCLK, 2:EPLL, 3:EPLL Ref. CLK\n");
sel = GetIntNum();
switch(sel)
{
case 0://In case of IIS Master Clock Source = PCLK
Select_PCLK();
break;
case 1://In case of IIS Master Clock Source = EXTCLK Form GPIO (CDCLK input)
Select_EXTCLK();
break;
case 2://In case of IIS Master Clock Source = divided EPLL or EPLL ref.
Select_EPLL();
break;
case 3://In case of IIS Master Clock Source = EPLL Ref. CLK
Select_EPLL_Ref_CLK();
break;
default :
Select_PCLK();
break;
}
}
// download wave files
void down_wav(void)
{
//Non-cacheable area = 0x31000000 ~ 0x33cf0000
Buf = (unsigned char *)IIS_BUFFER;
_temp = Buf;
printf("Download the PCM(no ADPCM) file by DNW serial port(With header)!!\n");
printf("Download address is %xh\n", Buf);
while(((unsigned int)_temp - (unsigned int)Buf) < 4)
{
Led_Display(0);
Delay(1500);
Led_Display(15);
Delay(1500);
}
printf("\ndata=%x",size);
size = *(Buf) | *(Buf + 1)<<8 | *(Buf + 2)<<16 | *(Buf + 3)<<24;
printf("\ndata=%x",size);
printf("\nNow, Downloading... [ File Size : %8d( 0)]",size);
while(((unsigned int)_temp - (unsigned int)Buf) < (size)){
printf("\b\b\b\b\b\b\b\b\b%8d)",(unsigned int)_temp - (unsigned int)Buf);
Delay(5000);
}
printf("\b\b\b\b\b\b\b\b\b%8d)]\n",(unsigned int)_temp - (unsigned int)Buf);
rINTSUBMSK |= BIT_SUB_RXD1;
rINTMSK |= BIT_UART1;
size = *(Buf + 0x2c) | *(Buf + 0x2d)<<8 | *(Buf + 0x2e)<<16 | *(Buf + 0x2f)<<24;
size = (size>>1)<<1;
fs = *(Buf + 0x1c) | *(Buf + 0x1d)<<8 | *(Buf + 0x1e)<<16 | *(Buf + 0x1f)<<24;
printf("Sample Size = %d\n",size/2);
printf("Sampling Frequency = %d Hz\n",fs);
printf("\n[ Now play the wave file .....]\n");
printf("If you want to mute or no mute push the 'EIN0' key repeatedly\n");
}
//=================================== [ IIS Test codes ] ==================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -