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

📄 record.c

📁 基于华邦W90P710 arm开发板的AC97模块测试程序
💻 C
字号:
#include"710defs.h"
#include"AC97.h"
#include"HB_it.h"
/*播放缓冲区的首地址*/
#define base_addres  0x100000
/*播放数据*/
UINT8 PlayData[300000] = {0};
UINT32 PCM_QUEUE_LEN = (512*1024);
UINT _uPlayVol = 0x1f1f;
UINT16 sPlayVolume = 0;
UINT16 sRecVolume = 0;
BOOL PlayLastBlock,RecDmaToggle;
volatile UINT32 _uPcmQHead, _uPcmQTail;


/*延时函数*/
static void Delay(int nCnt)
{
    volatile int  loop;
    for (loop=0; loop<nCnt; loop++);
}


/*播放函数*/
INT Play_Callback(UINT8 *pucBuff, UINT32 uDataLen)
{
    UINT nLen;
    nLen = PCM_QUEUE_LEN - _uPcmQHead;
    
    /*将数据从PCM队列中取出放到DMA缓存区*/
    if (nLen >= uDataLen)
    {
        memcpy(pucBuff, &PlayData[_uPcmQHead], uDataLen);
        _uPcmQHead = (_uPcmQHead + uDataLen) % PCM_QUEUE_LEN;
    }
    else
    {
        memcpy(pucBuff, &PlayData[_uPcmQHead], nLen);
        memcpy(&pucBuff[nLen], PlayData, uDataLen - nLen);
        _uPcmQHead = uDataLen - nLen;

    }
    return 0;
}

/*录音函数*/
INT  record_callback(UINT8 *pucBuff, UINT32 uDataLen)
{
	INT	nLen;

	//copy the input PCM into PCM queue from the DMA buffer
	nLen = PCM_QUEUE_LEN - _uPcmQTail;
	if (nLen >= uDataLen)
	{
		memcpy(&PlayData[_uPcmQTail], pucBuff, uDataLen);
		_uPcmQTail = (_uPcmQTail + uDataLen) % PCM_QUEUE_LEN;
	}
	else
	{
		memcpy(&PlayData[_uPcmQTail], pucBuff, nLen);
		memcpy(PlayData, &pucBuff[nLen], uDataLen - nLen);
		_uPcmQTail = uDataLen - nLen;
	}
	return 0;
}


/* 读AC97寄存器*/
static UINT16 ac97_read_register(INT nIdx)
{
    UINT volatile nWait;
    
    /* 置起R_WB位并写入寄存器地址 */
    REG_ACTL_ACOS1 = (0x80 | nIdx);
    
    /* 设置帧是否有效和有效的时隙 */
    REG_ACTL_ACOS0 = 0x11;
    Delay(100);
    
    /* 检查AC_ACTL_ACCON的AC_R_FINISH位是否被置高,若被置高,说明读数据缓存区已经准备好给CPU读取 */
    for (nWait = 0; nWait < 0x10000; nWait++)
    {
        if (REG_ACTL_ACCON & AC_R_FINISH)
            break;
    }


    REG_ACTL_ACOS0 = 0;
    Delay(100);        
    return (REG_ACTL_ACIS2 & 0xFFFF);
}



/* 写AC97寄存器*/
static INT ac97_write_register(INT nIdx, UINT16 sValue)
{
    volatile UINT    nWait;
    /* 清R_WB位并写入寄存器地址*/
    REG_ACTL_ACOS1 = nIdx;
    
    /* 写入AC97寄存器的值*/
    REG_ACTL_ACOS2 = sValue;
    
    /* 设置帧的有效位和有效的时隙*/
    REG_ACTL_ACOS0 = 0x13;
    
    Delay(100);
    
    /* 检查AC_ACTL_ACCON的AC_W_FINISH位,若被清零,说明AC-LINK控制数据输出缓存已经被CPU移到编解码器*/
    for (nWait = 0; nWait < 0x10000; nWait++)
    {
        if (!(REG_ACTL_ACCON & AC_W_FINISH))
            break;
    }
   
    /*若读回的值和写入的值相同,则说明写入成功*/ 
   if (ac97_read_register(nIdx) != sValue)
   {while(1)
     ;
   }
    
    REG_ACTL_ACOS0 = 0;

    return 0;
}


/*初始化AC97*/
UINT8 Initac97()
{
 
    /*使能音频控制器和AC-LINK接口*/
    REG_ACTL_CON = REG_ACTL_CON | IIS_AC_PIN_SEL | AUDIO_EN | ACLINK_EN | PFIFO_EN | RFIFO_EN | T_DMA_IRQ | R_DMA_IRQ | DMA_EN;
    Delay(1000);
    /*stereo模式*/
    REG_ACTL_RESET = REG_ACTL_RESET | 0xf000;

       

    /* 重启音频控制器 */
    REG_ACTL_RESET = REG_ACTL_RESET | ACTL_RESET_BIT;
    Delay(1000);
    REG_ACTL_RESET = REG_ACTL_RESET & ~ACTL_RESET_BIT;
    Delay(1000);


    
    /* 重启AC97接口 */
    REG_ACTL_RESET = REG_ACTL_RESET | AC_RESET;
    Delay(1000);

    REG_ACTL_RESET = REG_ACTL_RESET & ~AC_RESET;
    Delay(1000);


    /* 冷启动AC97 */
    REG_ACTL_ACCON = REG_ACTL_ACCON | AC_C_RES;
    Delay(1000);
    REG_ACTL_ACCON = REG_ACTL_ACCON & ~AC_C_RES;
    Delay(1000);
    
    /* 检查AC97的ACTL_ACIS0的CODEC_READY位,若置起则说明AC97准备好了 */
    if (!(REG_ACTL_ACIS0 & 0x10))
    {
        while(1);

    }

    Delay(100);

    /*选择麦克 1;3D控制 关;looback 关*/
    ac97_write_register(AC97_GENERAL_PURPOSE, 0);
    
    return 0;    
}


/*开始播放函数*/
UINT8 StartPlay(INT nSamplingRate)
{
       
    /* 使能VRA(variable rate audio)并设置播放采样率*/
    ac97_write_register(AC97_EXT_AUDIO_CTRL, ac97_read_register(AC97_EXT_AUDIO_CTRL)|0x1);
    ac97_write_register(AC97_FRONT_DAC_RATE, nSamplingRate);
    
     /*设置DMA基地址和目的地址长度*/
    REG_ACTL_PDSTB = base_addres; 
    REG_ACTL_PDST_LENGTH = 0x1000; 
    
    PlayLastBlock = 0;
    
    /* 开始播放 */
    REG_ACTL_ACOS0 = 0x1c; //设置数据传输时隙有效
    REG_ACTL_PSR = 0x3;
    REG_ACTL_RESET = REG_ACTL_RESET | AC_PLAY;
    return 0;
}


  /* 设置音量 */
INT SetPlayVolume(UINT8 ucLeftVol, UINT8 ucRightVol) 
{
    INT    nLData, nRData;

    if (ucLeftVol == 0)
        nLData = 0x80;
    else
        nLData = 31 - (ucLeftVol & 0x1f);
        
    if (ucRightVol == 0)
        nRData = 0x80;
    else
        nRData = 31 - (ucRightVol & 0x1f);

    sPlayVolume = (nLData << 8) | nRData;
        
    if (ucLeftVol == 0)
        nLData = 0x80;
    else
        nLData = 62 - ucLeftVol*2;
        
    if (ucRightVol == 0)
        nRData = 0x80;
    else
        nRData = 62 - ucRightVol*2;
    
    _uPlayVol = (nLData << 8) | nRData;
    
    /* 设置音量 */
    ac97_write_register(AC97_PCM_OUT_VOLUME, sPlayVolume ); //PCM数据输出音量
    ac97_write_register(AC97_AUX_OUT_VOLUME, _uPlayVol); //耳机音量设置
    ac97_write_register(AC97_MASTER_VOLUME, _uPlayVol); //全局音量设置

    return 0;


}



void StopPlay()
{
    
    /* 停止播放 */
    REG_ACTL_RESET = REG_ACTL_RESET & ~AC_PLAY;
    REG_ACTL_ACOS0 = 0;
    
    /*关闭音频播放中断 */
    REG_AIC_MDCR = REG_AIC_MDCR | 0x40;

    
    return ;
}


/* 开始录音 */
INT  StartRecord(INT nSamplingRate)
{

	REG_ACTL_RESET = REG_ACTL_RESET &~RECORD_LEFT_CHNNEL &~RECORD_RIGHT_CHNNEL;
	REG_ACTL_RESET = REG_ACTL_RESET | RECORD_RIGHT_CHNNEL | RECORD_LEFT_CHNNEL;
		
	
	ac97_write_register(AC97_RECORD_SELECT, 0);	/* record select MIC in */
	
	/* set record vol */
	ac97_write_register(AC97_RECORD_GAIN, 0x0f0f);
	//ac97_write_register(AC97_MIC_VOLUME, sRecVolume | 1<<6);
	ac97_write_register(AC97_RECORD_GAIN_MIC, 0x0f0f);

	
	/* set record sampling rate */
	if (nSamplingRate != 48000)
	{
		/* enable VRA and set sampling frequency */
		ac97_write_register(AC97_EXT_AUDIO_CTRL, ac97_read_register(AC97_EXT_AUDIO_CTRL)|0x1);
		ac97_write_register(AC97_LR_ADC_RATE, nSamplingRate);
	}
	
	/* set DMA record destination base address */
	REG_ACTL_RDSTB = base_addres;
	
	/* set DMA record buffer length */
	REG_ACTL_RDST_LENGTH = 4096;

	/* start recording */
	REG_ACTL_RSR = 0x3;
	REG_ACTL_RESET = REG_ACTL_RESET | AC_RECORD;

	return 0;
}

/* 停止录音 */
void  StopRecord()
{
	/* stop recording */
	REG_ACTL_RESET = REG_ACTL_RESET & ~AC_RECORD;

	/* disable audio record interrupt */

	REG_AIC_MDCR = REG_AIC_MDCR | 0x40;
	
	return ;
}

/* 设置录音音量 */
INT  SetRecordVolume(UINT8 ucLeftVol, UINT8 ucRightVol)
{
	if (ucLeftVol == 0)
		ucLeftVol = 0x80;
	else
		ucLeftVol = 32 - (ucLeftVol & 0x1f);
		
	if (ucRightVol == 0)
		ucRightVol = 0x80;
	else
		ucRightVol = 32 - (ucRightVol & 0x1f);

	sRecVolume = (ucLeftVol << 8) | ucRightVol;
	
	ac97_write_register(AC97_MIC_VOLUME, sRecVolume );
	
	REG_ACTL_ACOS0 = 0;

   	return 0;
}







int main(void)
{

 PCM_QUEUE_LEN = sizeof (PlayData);

 _uPcmQHead = 0;
 _uPcmQTail = 0;
 
  /* 设置I/O连接到音频 */
 REG_GPIO_CFG0 = 0x155; 
  /*// GPIO4,1:输入      GPIO0,2,3:输出 */                         
 REG_GPIO_DIR0 = 0xd;
                         
  /*使能音频时钟 */
 REG_CLKSEL = REG_CLKSEL|0x10000;                

 Initac97();
 
  /* 使能AC97播放中断 */
 REG_AIC_SCR6 = 0x41;                       
 REG_AIC_MECR = 0x40;
 
 
 
 StartRecord(12000);
 
 SetRecordVolume(30,30);
 
  /* 检查是否录音完成 */
 while(1)
 {
  if (_uPcmQTail >= (PCM_QUEUE_LEN-4096))
  break;
  }
 StopRecord();
  
   /* 使能AC97播放中断 */
 REG_AIC_SCR6 = 0x41;                       
 REG_AIC_MECR = 0x40;
               

 SetPlayVolume(30,30);
 
 StartPlay(12000);
 
  /* 检查是否播放完成 */
 while(1)
 {
  if (_uPcmQHead >= (PCM_QUEUE_LEN-4096))
  break;
  }
 StopPlay();
}

⌨️ 快捷键说明

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