⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interface.c

📁 usoc在北京博创兴业有限公司的实验平台s3c2410上运行。 2. 各实验的全部源代码分别存放在各实验目录下面。
💻 C
字号:
/***************************************************************************\
	Copyright (c) 2004-2007 www.up-tech.com, All rights reserved.
	by allan_hua	2005.12.28
\***************************************************************************/
/***************************************************************************\
    #说明: 系统硬件与播放器软件的接口文件,包含系统硬件接口的初始化、缓冲区
           的设置和使用,用户向不同平台移植只需修改这个文件和并完成函数
           int mp3_input_read(unsigned char *buf, int len)功能即可。

\***************************************************************************/
#include "reg2410.h"
#include "macro.h"
#include "../inc/sys/io.h"
#include "isr.h"

enum audio_command {
  AUDIO_COMMAND_INIT,
  AUDIO_COMMAND_CONFIG,
  AUDIO_COMMAND_PLAY,
  AUDIO_COMMAND_STOP,
  AUDIO_COMMAND_FINISH
};

struct audio_config {
    enum audio_command command;
    unsigned int channels;
    unsigned int speed;
  } ;
  
enum audio_mode {
  AUDIO_MODE_ROUND,
  AUDIO_MODE_DITHER
};  
  
struct audio_play 
  {
    enum audio_command command;
    unsigned int nsamples;
    signed int const *samples[2];
    enum audio_mode mode;
    struct audio_stats *stats;
  };  
  
struct audio_init {
    enum audio_command command;
    char const *path;
  };

# define MAX_NSAMPLES	(1152 * 3)	/* allow for resampled frame */

static int opened;

# define NSLOTS		25 	/* 大约3秒钟数据 (44.1 kHz) */
# define NBUFFERS	 3	/* 3个缓冲区 */

static struct buffer {
  int speed;
  volatile int playing;
  unsigned int pcm_length;
  unsigned char pcm_data[NSLOTS * MAX_NSAMPLES * 2 * 2];
} output[NBUFFERS];

static int bindex;         //要填入数据的缓冲数据索引 0->1->2->0->1....
static int playing_index;  //正在播放的缓冲数据索引   0->1->2->0->1....
static c_speed=44100;

//========================================
typedef struct _SRT
{
  unsigned int pllcon;
  unsigned int div;
}SRT;

//================只适用于44.1k的 CBR ========================= 
SRT srt[9]={
            {(0xa1<<12)|(0x03<<4)|1,0x42},	//48.0K
            {(0xa1<<12)|(0x03<<4)|1,0x42},	//44.1K            
            {(0xa1<<12)|(0x03<<4)|1,0x42},	//32.0K
            {(0xa1<<12)|(0x03<<4)|1,0x42},	//24.0K
            {(0xa1<<12)|(0x03<<4)|1,0x42},	//22.050K
            {(0xa1<<12)|(0x03<<4)|1,0x42},	//16.0K
            
            {(0xa1<<12)|(0x03<<4)|1,0x42},	//12.0K
            {(0xa1<<12)|(0x03<<4)|1,0x42},	//11.025K
            {(0xa1<<12)|(0x03<<4)|1,0x42},	//8.0K
            };
//============================================================

void IIS_PortSetting(void);
int  Audio_Init(void);
static void uda1341_l3_address(U8 data);
static void uda1341_l3_data(U8 data);
unsigned Init_UDA1341(void);

int rate_index(unsigned int rate)
{
  switch (rate) {
  case 48000: return 0; 
  case 44100: return 1;
  case 32000: return 2;
  case 24000: return 3;
  case 22050: return 4;
  case 16000: return 5;
  case 12000: return 6;
  case 11025: return 7;
  case  8000: return 8;
  }

  return -1;
}

//***************************************************************************
//重新置采样率
void set_sample_rate(int speed)
{
 int sri;  
 static int curr_speed=0;
 
 if(speed != curr_speed)
       {
        curr_speed=speed;
        if((sri=rate_index(curr_speed))<0) sri=1;
   
        rMPLLCON=srt[sri].pllcon;
        rIISPSR=srt[sri].div;	
       }
}

#define	ClearPending(x)	do{rSRCPND &= ~(1 << (x));	rINTPND = 0;}while(0)
extern void INTS_OFF(void); 
extern void INTS_ON(void); 
//BDMA中断
void IIS_DMA_Done(int vector, void* data)
{
    Disable_Irq(IRQ_DMA2);
    ClearPending(IRQ_DMA2);
    rIISCON &= ~(1<<0);                             //IIS Dis
    rDMASKTRIG2 = (0<<1);

    output[playing_index].pcm_length=0;	            //本缓冲区长度设为0
    output[playing_index].playing=0;		        //清除本缓冲区播放标志,以便装放新的数据
    playing_index=(playing_index+1) % NBUFFERS;	    //指到下一个缓冲区

    if(output[playing_index].playing==0)
    { rDMASKTRIG2 = (0<<1); opened=0;return;}       //如果没有数据,

    //DMA2 for AudioOut
    rDISRC2 = (U32)(output[playing_index].pcm_data);//For Src
    rDCON2|=((output[playing_index].pcm_length)/2); //important to DMA count
    rDMASKTRIG2 |= (1<<1); 	      //DMA2En 
    rIISCON |= (1<<0);            //IIS Enable; 
    set_sample_rate(output[playing_index].speed);	//根据采样率设置主频
    
    Enable_Irq(IRQ_DMA2);
}

//======================================================
int mp3_finish()
{  
    rIISCON=0x0;    //IIS stop
    rDCON2=0x0;   //BDMA stop    
    Disable_Irq(IRQ_DMA2);

    return 4;
}
//======================================================
int mp3_stop()
{	
  int i;
 
  rDCON2 &=0xffefffff;	       //DMA2 stop  
  
  opened = 0;  

  for (i = 0; i < NBUFFERS; ++i) 
  {

    output[i].playing    = 0;
    output[i].pcm_length = 0;
  }

  bindex = 0;
  playing_index=0;

  return 3;
}

//******************** 用户初始化硬件函数 **********************************

void Interrupt_Init(void)
{
    INTS_OFF();
	SetISR_Interrupt(IRQ_DMA2, IIS_DMA_Done, NULL);
    INTS_ON();
}

void IIS_Init(void)	 /****** IIS Initialize ******/
{
    //For S3C2410 IIS
    rIISCON&=0;
    rIISMOD&=0;
    rIISFCON&=0;
   
    rIISCON|=(1<<5)|(1<<2)|(1<<1);
    //TxDMAReqEn,RxIdle,IISPrescalerEn    
    rIISMOD|=(0<<8)|(2<<6)|(0<<4)|(1<<3)|(1<<2)|(1<<0);
    //Master,Tx,IisFormat,IIS,16bit,384fs,32fs  
    rIISFCON|=(1<<15)|(1<<13);
    //TxFifo=DMA,TxFifoEn
}

void IISDMA2_init(void)       //DMA初始化
{
    //DMA2 for AudioOut
    rDISRC2 = (U32)(output[playing_index].pcm_data);       //For Src
    rDISRCC2 = (0<<1)|(0<<0);   //Src=AHB,Increment
    rDIDST2 = (U32)0x55000010;  //Tx FIFO address
    rDIDSTC2 = (1<<1)|(1<<0);   //Dst=APB,Fixed;
    rDCON2 = (0<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|\
             (0<<24)|(1<<23)|(1<<22)|(1<<20)|((output[playing_index].pcm_length)/2);  // important to DMA count
    //handshake,Sync=APB,IntEn,unit,single,dst=I2SSDO,HwReqMode,NoAutoReload,Halfword,
    rDMASKTRIG2 = (1<<1); 	    //DMA2En 
    rIISCON|=(1<<0);            //IIS Enable; 
}
//*********************************************************************/
int init(struct audio_init *init)
{
  int i;
  
  opened = 0;

  for (i = 0; i < NBUFFERS; ++i) 
  {

    output[i].playing    = 0;
    output[i].pcm_length = 0;
  }

  bindex = 0;
  playing_index=0;

  Interrupt_Init();
  IIS_PortSetting();
  IIS_Init();
  Init_UDA1341();
  return 0;
}

//======================================================
int config(struct audio_config *config)
{

  c_speed=config->speed;   
  
  return 1;
}

//======================================================
void write_dev()
{
  output[bindex].playing=1;
  
  if(opened==0)            //如果第一次播放,初始化BDMA
   {
    opened=1;
    playing_index=bindex;
    set_sample_rate(output[playing_index].speed);
    IISDMA2_init();    
   }
}
//======================================================
//解码部分调用该函数进行数据播放
int play(struct audio_play *Audio_play)
{
  struct buffer *buffer;
  unsigned int len;

  buffer = &output[bindex];
  
  while(buffer->playing==1);

  /* prepare block */
  
  buffer->speed=c_speed;  

  //回调库函数
  len = audio_pcm_s16le(&buffer->pcm_data[buffer->pcm_length], Audio_play->nsamples,
			Audio_play->samples[0], Audio_play->samples[1], Audio_play->mode,Audio_play->stats);

  buffer->pcm_length += len;

  if ((buffer->pcm_length + MAX_NSAMPLES * 2 * 2) >= sizeof(buffer->pcm_data))
  {
    write_dev();
    bindex = (bindex + 1) % NBUFFERS;
    Uart_Printf(0,">");   // 输出播放进度
  }
  return 2;
}

/*****************************************************************************************

音频DAC的初始化函数,系统中使用的芯片为UDA1341,初始化函数参考芯片手册编写。
  
  Changed by allan_hua  2005.12.28

\*****************************************************************************************/

static void uda1341_l3_address(U8 data)   ///zhaoning
{
	int i;

	write_gpio_bit(GPIO_L3CLOCK, 1);
	write_gpio_bit(GPIO_L3DATA, 0);
	hudelay(10);
	write_gpio_bit(GPIO_L3MODE, 0);
	hudelay(5);
	
	for (i = 0; i < 8; i++) {
		if (data & 0x1) {
			write_gpio_bit(GPIO_L3CLOCK, 0);
			hudelay(1);
			write_gpio_bit(GPIO_L3DATA, 1);
			hudelay(1);
			write_gpio_bit(GPIO_L3CLOCK, 1);
			hudelay(1);
		} else {
			write_gpio_bit(GPIO_L3CLOCK, 0);
			hudelay(1);
			write_gpio_bit(GPIO_L3DATA, 0);
			hudelay(1);
			write_gpio_bit(GPIO_L3CLOCK, 1);
			hudelay(1);
		}
		data >>= 1;
	}
    hudelay(5);
	write_gpio_bit(GPIO_L3MODE, 1);
	hudelay(1);
}

static void uda1341_l3_data(U8 data)  ///zhaoning
{
	int i;
	write_gpio_bit(GPIO_L3MODE, 1);
	hudelay(5);
	
	for (i = 0; i < 8; i++) {
		if (data & 0x1) {
			write_gpio_bit(GPIO_L3CLOCK, 0);
			hudelay(1);
			write_gpio_bit(GPIO_L3DATA, 1);
			hudelay(1);
			write_gpio_bit(GPIO_L3CLOCK, 1);
			hudelay(1);
		} else {
			write_gpio_bit(GPIO_L3CLOCK, 0);
			hudelay(1);
			write_gpio_bit(GPIO_L3DATA, 0);
			hudelay(1);
			write_gpio_bit(GPIO_L3CLOCK, 1);
			hudelay(1);
		}

		data >>= 1;
	}
	//write_gpio_bit(GPIO_L3MODE, 1);
	hudelay(1);
	write_gpio_bit(GPIO_L3MODE, 0);
	hudelay(2);
	write_gpio_bit(GPIO_L3MODE, 1);
}

static int uda1341_volume;
static U8 uda_sampling;
static int uda1341_boost;
unsigned Init_UDA1341(void)
{

  	uda1341_volume = 62 - ((DEF_VOLUME * 61) / 100);
	uda1341_boost = 0;
  	uda_sampling = DATA2_DEEMP_NONE | DATA2_PEAKAFTER;
	uda_sampling &= ~(DATA2_MUTE);

	write_gpio_bit(GPIO_L3CLOCK, 1);
	write_gpio_bit(GPIO_L3MODE, 1);

	uda1341_l3_address(UDA1341_REG_STATUS);
    uda1341_l3_data(STAT0_RST); 
    
	uda1341_l3_address(UDA1341_REG_STATUS);
    uda1341_l3_data(STAT0_SC_384FS | STAT0_IF_I2S | STAT0_DC_FILTER); // 256 system clock,IIS
    uda1341_l3_data(STAT1 | STAT1_DAC_GAIN | STAT1_ADC_GAIN | STAT1_ADC_ON | STAT1_DAC_ON);

    uda1341_l3_address(UDA1341_REG_DATA0);
	uda1341_l3_data(DATA0 |DATA0_VOLUME(uda1341_volume));  // maximum volume
	uda1341_l3_data(DATA1 |DATA1_BASS(uda1341_boost)| DATA1_TREBLE(0));
    uda1341_l3_data(DATA2 |uda_sampling);
	uda1341_l3_data(EXTADDR(EXT2));
	uda1341_l3_data(EXTDATA(EXT2_MIC_GAIN(0x6)| EXT2_MIXMODE_CH2));
	uda1341_l3_data(EXTADDR(EXT5));
	uda1341_l3_data(EXTDATA(0x7));

	write_gpio_bit(GPIO_L3CLOCK, 1);
	write_gpio_bit(GPIO_L3MODE, 0);
    return 1;
}

void IIS_PortSetting(void)
{
    //----------------------------------------------------------
    //   PORT G GROUP
    //Ports  :   GPG9   GPG10  GPG8  
    //Signal :  L3CLOCK L3DATA L3MODE
    //Setting:   OUTPUT OUTPUT OUTPUT 
    //          [18:19] [20:21] [16:17]
    //Binary :     01  ,  01      01 
    //----------------------------------------------------------
    rGPGDAT = rGPGDAT & ~(UDA1341_MODE|L3CLK|L3DATA) |(UDA1341_MODE|L3CLK); 
    //Start condition : L3M=H, L3C=H
    rGPGUP  = rGPGUP  & ~(0x7<<8)|(0x7<<8);   
    //The pull up function is disabled GPG[8:10]     
    rGPGCON = rGPGCON & ~(0x3f<<16)|(0x15<<16); 
    //GPB[8:10]=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    
    //----------------------------------------------------------
    rGPEDAT = 0x0;
    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
}

int Audio_Init(void)
{
    IIS_PortSetting();
    Init_UDA1341();
    return OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -