📄 iis_dual.c
字号:
/*************************************************
NAME: iis_dual.c
DESC: S3C2410 IIS (UDA1341) simultaneous record & play test
HISTORY:
OCT.17.2002:purnnamu: first release
NOV.05.2002:purnnamu: Rec start/stop randomly.
APR.01.2003:ky.shim: minor modification.
MAY.08.2003:ky.shim: migration to S3C24A0X
*************************************************/
#include <math.h>
#include <stdlib.h>
#include "24a0addr.h"
#include "24a0lib.h"
#include "def.h"
#include "iis.h"
//#include "iis_dual.h"
//declarations of some functions in iis.c
void IIS_PortSetting(void);
void _WrL3Addr(U8 data);
void _WrL3Data(U8 data,int halt);
void Init1341RecPlay(void);
void AudioInit(void);
void AudioBufCopy(void);
void AudioInStart(void);
void AudioInStop(void);
void AudioOutStart(void);
void AudioOutStop(void);
void AudioOutRandom(void);
void __irq IsrAudioInOut(void);
void __irq IsrAudioMute(void);
void InterruptLatencyStart(void);
void InterruptLatencyStop(void);
void __irq IsrTimer0_InterruptLatency(void);
#define MAX_INDEX_AUDIO_BUF (200)
#define AUDIO_BUF_SIZE (1000) //500 stereo samples
U16 (*playBuf)[AUDIO_BUF_SIZE];
U16 (*recBuf)[AUDIO_BUF_SIZE];
volatile int indexPlayBuf,indexRecBuf;
volatile int stopPlay,stopRec;
volatile int audioOutActive,audioInActive;
//**************************************************
// IIS test
//**************************************************
void Test_IisRecPlay(void)
{
int i;
int ranPlay=FALSE;
char key;
srand(0);
Uart_Printf("[ IIS (Master Mode,Rec&Play) Test(UDA1341) ]\n");
Uart_TxEmpty(0);
ChangeMPllValue(82,4,1); //FCLK=90.316800MHz, PCLK=45.158400MHz <-- 5.644800MHz*8
ChangeClockDivider(0,1); // 1:1:2
ChangeSdramParameter(HCLK);
Uart_Init(45158400,115200);
IIS_PortSetting();
Init1341RecPlay();
playBuf=(U16 (*)[AUDIO_BUF_SIZE])0x11000000;
recBuf = (U16 (*)[AUDIO_BUF_SIZE])(0x11000000+sizeof(U16)*AUDIO_BUF_SIZE*MAX_INDEX_AUDIO_BUF);
indexPlayBuf=indexRecBuf=0;
audioOutActive=audioInActive=FALSE;
stopPlay=stopRec=FALSE;
//for(i=0x31000000;i<0x31100000;i+=4)*((U32 *)i)=0;
AudioInit();
pISR_DMA = (U32)IsrAudioInOut;
pISR_EINT0_2 = (U32)IsrAudioMute;
Uart_Printf("If you want to mute or no mute push the 'EIN9' key repeatedly\n");
Uart_Printf("Sampling Frequency = %d Hz\n",22050);
// Clear Int Pending and Unmask
ClearPending(BIT_EINT0_2);
rINTMSK = ~(BIT_EINT0_2);
ClearPending(BIT_DMA);
rINTMSK=~(BIT_DMA);
rSUBSRCPND=(BIT_SUB_DMA0|BIT_SUB_DMA2);
rINTSUBMSK=~(BIT_SUB_DMA0|BIT_SUB_DMA2);
while(1)
{
Uart_Printf("\n[Select Menu] (Rec Play Begin End Toggle Random)\n"
"1:R_B 2:R_E 3:PR_T 4:P_B 5:P_E 6:Copy:R->P 7:IL_B 8:IL_E 9:Exit\n");
// Uart_Printf("\n[Select Menu] (Rec Play Begin End)\n"
// "1:R_B 2:R_E 3:P_B 4:P_E 5:Copy_R->P 6:Exit\n");
while((key=Uart_GetKey())==0)
{
if(ranPlay==TRUE)
AudioOutRandom();
}
switch(key)
{
case '1':
AudioInStart();
break;
case '2':
AudioInStop();
break;
case '3':
if(ranPlay==FALSE)
{
ranPlay=TRUE;
Uart_Printf("Random Play Stop/Start begins.\n");
}
else
{
ranPlay=FALSE;
Uart_Printf("Random Play Stop/Start ends.\n");
}
break;
case '4':
AudioOutStart();
break;
case '5':
AudioOutStop();
break;
case '6':
AudioBufCopy();
break;
case '7':
InterruptLatencyStart();
break;
case '8':
InterruptLatencyStop();
break;
case '9':
rINTSUBMSK|=(BIT_SUB_DMA0|BIT_SUB_DMA2);
rINTMSK|=(BIT_DMA|BIT_EINT7_10);
//(0,0)=1:1:1, (0,1)=1:1:2, (1,0)=1:2:2 (1,1)=1:2:4, (2,0)=1:4:5, (2,1)=1:4:8
ChangeClockDivider(1,1);
//(76,4,1)=84Mhz, (93,4,1)=101Mhz, (54,1,1)=124Mhz, (68,4,0)=152Mhz
//(93,4,0)=202Mhz, (47,1,0)=220Mhz, (72,2,0)=240Mhz, (79,2,0)=261Mhz
//(60.2.0)=204MHz
ChangeMPllValue(60,2,0);// FCLK=204Mhz
ChangeSdramParameter(HCLK);
Uart_Init(0,115200);
return;
default:
break;
}
}
}
void AudioBufCopy(void)
{
int i,j;
Uart_Printf("[Audio Buffer Copy recBuf -> playBuf]\n");
if(audioInActive==TRUE)
{
Uart_Printf("Rec is ongoing. Please Stop Recording.\n");
return;
}
for(i=0;i<MAX_INDEX_AUDIO_BUF;i++)
for(j=0;j<AUDIO_BUF_SIZE;j++)
playBuf[i][j]=recBuf[i][j];
}
void InterruptLatencyStart(void)
{
Uart_Printf("[Random Interrupt Latency Start]\n");
pISR_TIMER0 = (U32)IsrTimer0_InterruptLatency; //to make a worst condition
rTCFG0=(3<<0); //Timer0&1Prescaler=(3+1)
rTCFG1=(3<<0); //Timer0=PCLK/4/16
rTCNTB0=1;
rTCON=(1<<1); //T0ManualUpdate
rTCON=(1<<0); //T0Start
rINTMSK&=~(BIT_TIMER0);
}
void InterruptLatencyStop(void)
{
rINTMSK|=BIT_TIMER0;
Uart_Printf("[Random Interrupt Latency Stop]\n");
}
void AudioInit(void)
{
//DMA0 for AudioIn
rDMASKTRIG0 = (1<<2); //Dma0Stop
//DMA2 for AudioOut
rDMASKTRIG2 = (1<<2); //Dma2Stop
//IIS
rIISCON=(1<<5)|(1<<4)|(1<<1);
//TxDMAReqEn,RxDMAReqEn,IISPrescalerEn
rIISMOD=(0<<8)|(3<<6)|(0<<4)|(1<<3)|(0<<2)|(1<<0);
//Master,Tx&Rx,IisFormat,16bit,256fs,32fs
rIISPSR = (7<<5) + 7;
//Prescaler A,B=7 <- (PCLK = 45MHz)/8 = 5.625MHz
rIISFCON=(1<<15)|(1<<14)|(1<<13)|(0<<12);
//TxFifo=DMA,RxFifo=DMA,TxFifoEn,RxFifoDis
rIISCON|=(1<<0);
//IIS Enable;
//IIS will not start because DMA is not ready.
}
//**************************************************
// AudioOut
//**************************************************
void AudioOutStart(void)
{
if(audioOutActive!=FALSE)
{
Uart_Printf("[N/A]");
return;
}
Uart_Printf("[AudioOut Start]\n");
stopPlay=FALSE;
audioOutActive=TRUE;
indexPlayBuf=0;
//Init DMA Ch 2
rDISRC2 = (U32)(playBuf[indexPlayBuf++]);
rDISRCC2 = (0<<1)|(0<<0); //Src=AHB,Increment
rDIDST2 = (U32)IISFIFO; // Tx FIFO address
rDIDSTC2 = (1<<1)|(1<<0); //Dst=APB,Fixed;
rDCON2 = (1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(1<<24)|(1<<23)|(1<<22)|(1<<20)|(AUDIO_BUF_SIZE);
//handshake,Sync=APB,IntEn,unit,single,dst=I2SSDO,HwReqMode,NoAutoReload,Halfword,
rDMASKTRIG2 = (1<<1); //DMA2En
//IIS will start to work.
}
#define DMA_OFF_TIMEOUT (1000)
void AudioOutStop(void)
{
Uart_Printf("\n[AudioOut Stop]\n");
stopPlay=TRUE;
}
void AudioOutRandom(void)
{
static state=0;
if( (rand()/(RAND_MAX/2000000)) < 1 )
{
switch(state++)
{
case 0:
AudioOutStart();
state=1;
break;
case 1:
state=2;
break;
case 2:
AudioOutStop();
state=0;
break;
default:
break;
}
}
}
void __sub_IsrAudioOut(void) //DMA2 done interrupt subroutine
{
int timeOut=0;
//NMI doesn't using auto-reload.
// ClearPending(BIT_DMA2);
if(stopPlay==TRUE)
{
#if 1
rDMASKTRIG2|= (1<<2); //NMI
#else
rDMASKTRIG2= (1<<2); //StopDMA2 //recommended
#endif
while (rDMASKTRIG2&(1<<1) && (timeOut++ < DMA_OFF_TIMEOUT));
if(timeOut >= DMA_OFF_TIMEOUT)
Uart_Printf("ERROR: DMA2 Stop timed out\n");
rDMASKTRIG2 &= ~(1<<2); //not needed.... remove!!!
audioOutActive=FALSE;
//Uart_Printf("<PE>");
}
else
{
rDISRC2 = (U32)(playBuf[indexPlayBuf++]);
if(indexPlayBuf==MAX_INDEX_AUDIO_BUF)
{
indexPlayBuf=0;
}
rDMASKTRIG2 |= (1<<1); //enable DMA2
if((indexPlayBuf%10)==0)
{
if(indexPlayBuf==0)WrUTXH0(';');
else WrUTXH0(',');
}
}
}
//**************************************************
// AudioIn
//**************************************************
void AudioInStart(void)
{
if(audioInActive!=FALSE)
{
Uart_Printf("[N/A]");
return;
}
Uart_Printf("[AudioIn Start]\n");
stopRec=FALSE;
audioInActive=TRUE;
indexRecBuf=0;
//Init DMA Ch 0
rDISRC0 = (U32)IISFIFO; // Rx FIFO address
rDISRCC0 = (1<<1)|(1<<0); //Src=APB,Fixed;
rDIDST0 = (U32)(recBuf[indexRecBuf++]);
rDIDSTC0 = (0<<1)|(0<<0); //DSt=AHB,Increment
rDCON0 = (1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(2<<24)|(1<<23)|(0<<22)|(1<<20)|(AUDIO_BUF_SIZE);
//handshake,Sync=APB,IntEn,unit,single,dst=I2SSDI,HwReqMode,AutoReload,Halfword,
rDMASKTRIG0 = (1<<1); //DMA1En
rIISFCON|=(1<<12); //RxFifoEn
rIISCON|=(1<<4); //RxDmaServiceRequestEn
while((rDSTAT0&0xFFFFF) == 0);
rDIDST0 = (U32)(recBuf[indexRecBuf++]);
//IIS will start to work.
}
void AudioInStop(void)
{
Uart_Printf("\n[AudioIn Stop]\n");
stopRec=TRUE;
}
void __sub_IsrAudioIn(void) //DMA0 done interrupt
{
int timeOut=0;
// ClearPending(BIT_DMA0); //Clear pending bit
while((rDSTAT0 & 0xFFFFF) == 0); //wait until the current autoreload is completed
if(stopRec==TRUE)
{
rIISCON&=~(1<<4); //RxDmaServiceRequestDis
rIISFCON&=~(1<<12); //RxFifoDis
#if 1
rDMASKTRIG0|= (1<<2); //NMI
#else
rDMASKTRIG0= (1<<2); //recommended
#endif
while (rDMASKTRIG0&(1<<1) && (timeOut++ < DMA_OFF_TIMEOUT));
if(timeOut >= DMA_OFF_TIMEOUT)
Uart_Printf("ERROR: DMA0 Stop timed out\n");
rDMASKTRIG0 &= ~(1<<2); //not needed.... remove!!!
audioInActive=FALSE;
//Uart_Printf("[RE]");
}
else
{
rDIDST0 = (U32)(recBuf[indexRecBuf++]);
if(indexRecBuf==MAX_INDEX_AUDIO_BUF)
{
indexRecBuf=0;
}
if((indexRecBuf%10)==0)
{
if(indexRecBuf==0)WrUTXH0(':');
else WrUTXH0('.');
}
}
}
//*************************************************
// Audio In/Out IRQ
//*************************************************
void __irq IsrAudioInOut(void)
{
rINTSUBMSK|=(BIT_SUB_DMA0|BIT_SUB_DMA2);
if(rSUBSRCPND&BIT_SUB_DMA0) __sub_IsrAudioIn();
else __sub_IsrAudioOut();
ClearPending(BIT_DMA);
rSUBSRCPND=(BIT_SUB_DMA0|BIT_SUB_DMA2); // Clear Sub int pending
rINTSUBMSK&=~(BIT_SUB_DMA0|BIT_SUB_DMA2);
}
void __irq IsrAudioMute(void)
{
static int mute=0;
ClearPending(BIT_EINT7_10);
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("\n[Mute]\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("\n[No Mute]\n");
}
}
//The following ISR makes an interrupt latency random time for audioIn and audioOut
void __irq IsrTimer0_InterruptLatency(void)
{
static U16 count=0;
ClearPending(BIT_TIMER0);
count++;
if(count==0x0)count=1;
Delay(count&0x7f);
Led_Display(count);
rTCNTB0=count;
rTCON=(1<<1); //T0ManualUpdate
rTCON=(1<<0); //T0Start
}
//**************************************************
// UDA1341
//**************************************************
#define L3D (1<<16) //GPDAT[16] = L3DATA
#define L3C (1<<17) //GPDAT[17] = L3CLOCK
#define L3M (1<<18) //GPDAT[18] = L3MODE
void Init1341RecPlay(void)
{
/*
//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)
*/
//Port Initialize for 24A0X
//----------------------------------------------------------
// GPCON_M GROUP
//Ports : GP18 GP17 GP16
//Signal : L3MODE L3CLOCK L3DATA
//Setting: OUTPUT OUTPUT OUTPUT
// [15:14] [13:12] [11:10]
//Binary : 01 , 01 01
//----------------------------------------------------------
rGPDAT = rGPDAT & ~(L3M|L3C|L3D) |(L3M|L3C); //Start condition : L3M=H, L3C=H
rGPPU = rGPPU & ~(0x7<<15) |(0x7<<15); //The pull up function is disabled GPUP[17:15] 0011 1000 0000 0000 0000
rGPCON_M = rGPCON_M & ~(0x3f<<8) |(0x15<<8); //GPCON_M[13:8]=Output(L3MODE):Output(L3CLOCK):Output(L3DATA)
//L3 Interface
_WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
_WrL3Data(0x60,0); //0,1,10,000,0 : Reset,256fs,no DCfilter,iis
_WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
_WrL3Data(0x20,0); //0,0,10,000,0 : No reset,256fs,no DCfilter,iis
/*
//play
_WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
_WrL3Data(0x81,0); //1,0,0,0,0,0,01 : OGS=0,IGS=0,ADC_NI,DAC_NI,sngl speed,AoffDon
//record
if(mode)
{
_WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
_WrL3Data(0xa2,0); //1,0,1,0,0,0,10 : OGS=0,IGS=1,ADC_NI,DAC_NI,sngl speed,AonDoff
_WrL3Addr(0x14 + 0); //DATA0 (000101xx+00)
_WrL3Data(0xc2,0); //11000,010 : DATA0, Extended addr(010)
_WrL3Data(0x4d,0); //010,011,01 : DATA0, MS=9dB, Ch1=on Ch2=off,
}
*/
_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(0x4d,0); //010,011,01 : DATA0, MS=9dB, Ch1=on Ch2=off,
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -