📄 pcm.c
字号:
/*******************************************************************************
File Name: pcm.c
Description: S3C2460 PCM Audio Interface Function Test Code
Version: 0.0
History:
0.0: 2004. 07. 07, First draft, programmed and tested by Yoh-Han Lee
- This S3C2460 PCM test code works with AK2430 PCM Codec on the SMDK2460.
- Test of AK2430 IIC Interface with S3C2460 is supported.
- PCM In/Out in DMA mode is supported.
- PCM In/Out in interrupt mode is supported. Thanks to Rader.
********************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "option.h"
#include "type.h"
#include "2460addr.h"
#include "2460lib.h"
#include "2460slib.h"
#include "pcm.h"
#include "PLL.h"
//#define PCM_REC_LEN 0xfffff*2 //Max value of DMA Transfer Counter (20bit) = 0xfffff, Date Size=Half word (2bytes)
#define PCM_REC_LEN 0x3ffff*2
//org
//#define DOWN_BUF 0x11000000 //_NONCACHE_STARTADDRESS
//khs(050909)
#define DOWN_BUF _NONCACHE_STARTADDRESS //_NONCACHE_STARTADDRESS
#define PCM_OUT_Threshold 16
#define PCM_IN_Threshold 16
unsigned int save_PCM_rGPICON, save_PCM_rGPIDAT, save_PCM_rGPIUP;
unsigned int PCM_size, PCM_fs;
unsigned short *Rec_PCM_BUF, *End_PCM_BUF, *Play_PCM_BUF;
volatile short PCM_Out_INT_Exit = 0;
volatile short PCM_In_INT_Exit =0;
unsigned char *PCM_BUF,*PCM_temp;
unsigned char Exit_Key;
volatile char PCM_Rec_Done = 0;
void AK2430_IIC_Write(unsigned int slvAddr,unsigned int addr,unsigned char data);
unsigned char AK2430_IIC_Read(unsigned int slvAddr,unsigned char addr);
void PCM_Port_Init(void);
void PCM_Port_Return(void);
void AK2430_CodecInit_PCMOut(void);
void AK2430_CodecExit_PCMOut(void);
void AK2430_CodecInit_PCMIn(void);
void AK2430_CodecExit_PCMIn(void);
void PCM_PCMout_DMA1(unsigned int PCM_Size);
void PCM_PCMin_DMA2(unsigned int PCM_Size);
void PCM_PCMout_INT(unsigned int PCM_Size);
void PCM_PCMin_INT(unsigned int PCM_Size);
static void __irq DMA1_Play_Done(void);
static void __irq DMA2_Rec_Done(void);
void __irq Irq_PCM_PCMout(void);
void __irq Irq_PCM_PCMin(void);
void * func_pcm_test[][2]=
{
//PCM Function Test Item
(void *)PCM_Codec_IIC_Test, "PCM Codec IIC Test ",
(void *)PCM_In_Out_Test, "Record Sound and Play it through PCM Codec. ",
0,0
};
void PCM_Test(void)
{
int i;
while(1)
{
i=0;
printf("\n\n========================= PCM Function Test ==========================\n\n");
while(1)
{ //display menu
printf("%2d:%s",i,func_pcm_test[i][1]);
i++;
if((int)(func_pcm_test[i][0])==0)
{
printf("\n");
break;
}
if((i%2)==0)
printf("\n");
}
printf("\n======================================================================");
printf("\nSelect #Item or Press enter key to exit:");
i = GetIntNum();
if(i==-1) break; // return.
if(i>=0 && (i<(sizeof(func_pcm_test)/8)) ) // select and execute...
( (void (*)(void)) (func_pcm_test[i][0]) )();
}
}
//Top Level PCM Test Functions
void PCM_Codec_IIC_Test(void)
{
unsigned int i;
printf("\nIIC Test of AK2430 PCM Codec.\n");
printf("\nReg. Addr. Reg. Data\n");
for(i=0x2; i<0x1f; i++)
{
printf("0x%02x 0x%02x \n", i, AK2430_IIC_Read(0x9e, i));
}
for(i=0;i<32;i++)
{
AK2430_IIC_Write(0x9e, 0x15, i);
printf("MASTERVOL: %2d \n", AK2430_IIC_Read(0x9e, 0x15));
}
}
//*khs. added for mode selection
uint8 pcm_mode=1;
void PLL_Change(uint8 mode)
{
PreChangeSDRAMParameter();
if(pcm_mode==0)
{
SetCLKDIV(1,1,0);
//*khs. ARM=256MHz, Hclk=128MHz, Pclk=64MHz
SetMPLL( 120, 1, 1);
}
else
{
SetMPLL( Startup_MDIV, Startup_PDIV, Startup_SDIV);
SetCLKDIV( Startup_ARMCLKdiv, Startup_HCLKdiv, Startup_PCLKdiv);
}
GlobalCLK();
Init_LogicalConsole();
ChangeSDRAMParameter(HCLK);
Delay(100);
return;
}
void PCM_In_Out_Test(void)
{
int i;
PCM_Port_Init();
printf("\nSelect PCM In/Out Operation Mode\n");
printf("0: Interrupt, 1: DMA\n");
i = GetIntNum();
//->
//khs.050516
// added for selecting master or slave mode
printf("\nSelect Record Mode\n");
printf("0: Master Mode, 1: Slave Mode\n");
pcm_mode=GetIntNum();
PLL_Change(pcm_mode);
//<-
switch(i)
{
case 0://Interrupt Mode
//PCM In
AK2430_CodecInit_PCMIn();
PCM_PCMin_INT(PCM_REC_LEN/8);
AK2430_CodecExit_PCMIn();
//->
//khs.050516
// added for selecting master or slave mode
printf("\nSelect Play Mode\n");
printf("0: Master Mode, 1: Slave Mode\n");
pcm_mode=GetIntNum();
PLL_Change(pcm_mode);
//<-
//PCM Out
AK2430_CodecInit_PCMOut();
PCM_PCMout_INT(PCM_REC_LEN/8);
break;
case 1://DMA Mode
//PCM In
AK2430_CodecInit_PCMIn();
PCM_PCMin_DMA2(PCM_REC_LEN/8);
AK2430_CodecExit_PCMIn();
//->
//khs.050516
// added for selecting master or slave mode
printf("\nSelect Play Mode\n");
printf("0: Master Mode, 1: Slave Mode\n");
pcm_mode=GetIntNum();
PLL_Change(pcm_mode);
//<-
//PCM Out
AK2430_CodecInit_PCMOut();
PCM_PCMout_DMA1(PCM_REC_LEN/8);
break;
default:
break;
}
AK2430_CodecExit_PCMOut();
PCM_Out_INT_Exit = 0;
PCM_In_INT_Exit =0;
PCM_Port_Return();
}
// Functional Sub-Routines
void PCM_Port_Init(void)
{
//Push PCM GPIO port configuration
save_PCM_rGPIDAT=rGPIDAT;
save_PCM_rGPICON=rGPICON;
save_PCM_rGPIUP=rGPIPU;
//---------------------------------------------------------------------
//PORT E GROUP
//Ports : GPA4 GPA3 GPA2 GPA1 GPA0
//Signal : PCM SYNC PCM SDO PCM SDI PCM RESETn PCM BITCLK
//Binary : 11, 11, 11, 11, 11
//---------------------------------------------------------------------
rGPICON = rGPICON & ~(0xffc0000) | 0xaa80000;
rGPIPU = rGPIPU & ~(0x3e00) | 0x3e00;
}
void PCM_Port_Return(void)
{
//Pop PCM GPIO port configuration
rGPICON=save_PCM_rGPICON;
rGPIDAT=save_PCM_rGPIDAT;
rGPIPU=save_PCM_rGPIUP;
}
////PCM Codec Register Setting for Out-Operation
void AK2430_CodecInit_PCMOut(void)
{
AK2430_IIC_Write(0x9e, 0x18, 0x07); //MSTCLK_I = 19.2MHz
//->
//khs.050516
// modified for mode selection
#if 1 //new>>
if(pcm_mode==0)
AK2430_IIC_Write(0x9e, 0x1B, 0xC); //external PCM Codec Slave Mode
else
AK2430_IIC_Write(0x9e, 0x1B, 0x0); //external PCM Codec Master Mode
#else //org>>
AK2430_IIC_Write(0x9e, 0x1B, 0x0); //external PCM Codec Master Mode
#endif
//<-
AK2430_IIC_Write(0x9e, 0x1E, 0x01); //DLCK = 256kHz, 14bit linear code (2's complement format)
AK2430_IIC_Write(0x9e, 0x0C, 0x0); //0 dB
AK2430_IIC_Write(0x9e, 0x10, 0x1F); //three dB
AK2430_IIC_Write(0x9e, 0x11, 0x1F); //three dB
AK2430_IIC_Write(0x9e, 0x06, 0x40); //POP Mute Off
AK2430_IIC_Write(0x9e, 0x03, 0x01); //CKI Buff On other blocks Off
Delay(1);
AK2430_IIC_Write(0x9e, 0x03, 0x09); //PLL2, CKI Buff On and other blocks Off
Delay(300);
AK2430_IIC_Write(0x9e, 0x04, 0x01); //RXSUM On and other blocks Off
AK2430_IIC_Write(0x9e, 0x05, 0x20); //PCM Codec On and other blocks Off
Delay(50);
AK2430_IIC_Write(0x9e, 0x07, 0x20); //sw_COL Close and other sw Open
AK2430_IIC_Write(0x9e, 0x08, 0x20); //sw_COR Close and othr sw Open
AK2430_IIC_Write(0x9e, 0x09, 0x14); //sw_EPL, sw_EPR Amp output
AK2430_IIC_Write(0x9e, 0x04, 0x31); //EPL/R Amp(RXSUM) On and other blocks Off
Delay(1600);
}
void AK2430_CodecExit_PCMOut(void)
{
AK2430_IIC_Write(0x9e, 0x04, 0x01); //EPL/R Amp Off
Delay(1300);
AK2430_IIC_Write(0x9e, 0x07, 0x00); //sw_COL Close and other sw Open
AK2430_IIC_Write(0x9e, 0x08, 0x00); //sw_COR Close and othr sw Open
AK2430_IIC_Write(0x9e, 0x09, 0x00); //sw_EPL, sw_EPR Amp output
AK2430_IIC_Write(0x9e, 0x04, 0x00); //RXSUM Off
AK2430_IIC_Write(0x9e, 0x05, 0x00); //PCM Codec Off
}
//PCM Codec Register Setting for In-Operation
void AK2430_CodecInit_PCMIn(void)
{
AK2430_IIC_Write(0x9e, 0x18, 0x07); //MSTCLK_I = 19.2MHz
//Transfer data enable
//->
//khs.050516
// modified for mode selection
#if 1 //new>>
if(pcm_mode==0)
AK2430_IIC_Write(0x9e, 0x1B, 0xC); //external PCM Codec Slave Mode
else
AK2430_IIC_Write(0x9e, 0x1B, 0x0); //external PCM Codec Master Mode
#else //org>>
AK2430_IIC_Write(0x9e, 0x1B, 0x0); //external PCM Codec Master Mode
#endif
//<-
AK2430_IIC_Write(0x9e, 0x1E, 0x01); //DLCK = 256kHz, 14bit linear code (2's complement format)
AK2430_IIC_Write(0x9e, 0x0D, 0x5); //0 dB
AK2430_IIC_Write(0x9e, 0x06, 0x40); //POP Mute Off
AK2430_IIC_Write(0x9e, 0x03, 0x01); //CKI Buff On other blocks Off
Delay(1);
AK2430_IIC_Write(0x9e, 0x03, 0x09); //PLL2, CKI Buff On and other blocks Off
Delay(300);
AK2430_IIC_Write(0x9e, 0x05, 0x10); //TXSUM On and other blocks Off
AK2430_IIC_Write(0x9e, 0x05, 0x30); //PCM Codec, TX Sum On and other blocks Off
Delay(50);
AK2430_IIC_Write(0x9e, 0x0B, 0x11); //sw_COI, sw_TX1 Close and other sw Open
AK2430_IIC_Write(0x9e, 0x05, 0x35); //MIC AMP1, MIC BIAS1, PCM CODEC, TX SUM On and other bolcks OFF
Delay(1600);
}
void AK2430_CodecExit_PCMIn(void)
{
AK2430_IIC_Write(0x9e, 0x05, 0x30); //MIC Amp1, MIC Bias1 Off
Delay(1300);
AK2430_IIC_Write(0x9e, 0x0B, 0x00); //sw_COI, sw_TX1 Open
AK2430_IIC_Write(0x9e, 0x05, 0x00); //TX SUM, PCM Codec Off
}
//////////////////////////////////////////////////////////////////////////
void PCM_PCMout_DMA1(unsigned int PCM_Size)
{
unsigned int i;
//pISR_EINT0= (unsigned)Muting;
pISR_DMA_SBUS= (unsigned)DMA1_Play_Done;
ClearPending(BIT_DMA_SBUS);
rSUBSRCPND=(BIT_SUB_DMA1);
rINTMSK = ~(BIT_DMA_SBUS);
rINTSUBMSK=~(BIT_SUB_DMA1);
Play_PCM_BUF=(unsigned short *)DOWN_BUF;
//*Play_PCM_BUF= 0x50f0;
//PCM Initialize
printf("\nConnect head-phone plug into speaker-out socket on SMDK2460 and Press any key.\n");
getchar();
printf("\nNow Play...\n");
printf("\nIf you want to exit, Press the 'x' key.\n");
//DMA Ch1 for PCMInitialize
rDISRC1 = (unsigned)Play_PCM_BUF;
rDISRCC1 = (0<<1) + (0<<0); //The source is in the system bus(AHB), Increment
rDIDST1 = 0x46200008; //PCM Out Data Fifo
rDIDSTC1 = (1<<1) + (1<<0); //The destination is in the peripheral bus(APB), Fixed
rDCON1 = (0<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(0<<22)+(1<<20)+(PCM_Size/2);
rDMASKTRIG1 = (0<<2) + (1<<1) + (0<<0); //No-stop[2], DMA1 channel On[1], No-sw trigger[0]
rDMAREQSEL1 = (4<<1) + (1<<0);
//Transfer data enable
//->
//khs.050516
// modified for mode selection
#if 1 //new>>
if(pcm_mode==0)
rPCM_CLKCTL = (1<<19) | (1<<18) | (124<<9) |(31<<0);
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -