272 lines
6.0 KiB
C
272 lines
6.0 KiB
C
#include "typesdef.h"
|
|
#include "list.h"
|
|
#include "dev.h"
|
|
#include "devid.h"
|
|
#include "hal/i2s.h"
|
|
#include "hal/i2c.h"
|
|
#include "osal/sleep.h"
|
|
#include "hal_i2s_audio.h"
|
|
#include "osal/string.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define __iis_sram_acton __at_section(".iiscode")
|
|
|
|
__iis_sram_acton static void demo_sram(uint32 sys_con,uint32 con)
|
|
{
|
|
/* 下面三句要放在SRAM上跑 */
|
|
//enable iis0
|
|
(*((volatile uint32 *)0x40004900)) |= BIT(0);
|
|
|
|
|
|
SYSCTRL_REG_OPT(
|
|
SYSCTRL->SYS_CON2 = sys_con;
|
|
);
|
|
|
|
//iis 1 set rx
|
|
(*((volatile uint32 *)0x40004A00)) = con;
|
|
}
|
|
|
|
|
|
static void audio_8311_irq_handle(uint32 irq, uint32 irq_data)
|
|
{
|
|
audio_i2s_config *priv = (audio_i2s_config*)irq_data;
|
|
void *buf;
|
|
int buf_size;
|
|
//speaker_user_action* speaker_act = (speaker_user_action*)priv->speaker_management->app_action;
|
|
if (I2S_IRQ_FLAG_HALF == irq)
|
|
{
|
|
buf = priv->set_buf(priv->priv_el,&priv->reg_node,&buf_size);
|
|
|
|
if(buf)
|
|
{
|
|
priv->irq_func(priv->i2s_dev , buf, buf_size);
|
|
}
|
|
else
|
|
{
|
|
if(priv->play_empty_buf)
|
|
{
|
|
priv->irq_func(priv->i2s_dev , priv->play_empty_buf, priv->buf_size);
|
|
}
|
|
}
|
|
|
|
// _os_printf("A");
|
|
}
|
|
else if (I2S_IRQ_FLAG_FULL == irq)
|
|
{
|
|
|
|
//半中断有配置新的buf,则将完成的录音帧通知应用层,如果为NULL,则代表没有配置新的buf,只能使用旧的buf
|
|
if(priv->reg_node)
|
|
{
|
|
//buf_size大部分是无效值,如果是喇叭,get_buf则基本是空函数,如果是mic,get_buf则是返回已经录音完成的buf
|
|
priv->get_buf(priv->priv_el,priv->current_node,&buf_size);
|
|
priv->current_node = priv->reg_node;
|
|
priv->reg_node = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//play_config是喇叭配置,mic_config麦克风配置,只要是非NULL,默认传入的参数是对的
|
|
int audio_i2s_install(audio_i2s_config *play_config,audio_i2s_config *mic_config)
|
|
{
|
|
int res = RET_ERR;
|
|
int duplex_en = 0;
|
|
struct i2s_device *i2s_dev;
|
|
audio_i2s_config *config;
|
|
int i2s_devid;
|
|
int sample_freq = ~0;
|
|
int sample_bit = ~0;
|
|
int data_format = ~0;
|
|
void *buf;
|
|
int buf_size;
|
|
if(!play_config && !mic_config)
|
|
{
|
|
goto audio_i2s_install_end;
|
|
}
|
|
//需要同步
|
|
if(play_config && mic_config)
|
|
{
|
|
duplex_en = 1;
|
|
*(unsigned int *)0x40020000=0x3fac87e4;
|
|
SYSCTRL_REG_OPT(
|
|
SYSCTRL->SYS_CON3 = (SYSCTRL->SYS_CON3 & ~(0x01 << 27)) | (1 << 27);
|
|
);
|
|
extern unsigned int _iis_start;
|
|
extern unsigned int _iis_end;
|
|
unsigned int iis_start = (unsigned int)&_iis_start;
|
|
unsigned int iis_end = (unsigned int)&_iis_end;
|
|
unsigned int iis_sram_start = (unsigned int)demo_sram;
|
|
os_memcpy((void*)iis_sram_start,(void*)iis_start,iis_end-iis_start);
|
|
|
|
}
|
|
else
|
|
{
|
|
*(unsigned int *)0x40020000=0x3fac87e4;
|
|
SYSCTRL_REG_OPT(
|
|
SYSCTRL->SYS_CON3 = (SYSCTRL->SYS_CON3 & ~(0x01 << 27));
|
|
);
|
|
|
|
}
|
|
|
|
//打开对应i2s,前提是i2s的id要设置对,否则就会出现异常,后续只是获取id设备,不验证是否为i2s设备,强行转换
|
|
if(play_config && play_config->i2s_devid != ~0)
|
|
{
|
|
config = play_config;
|
|
config->irq_func = (i2s_irq_func)i2s_write;
|
|
i2s_devid = config->i2s_devid;
|
|
i2s_dev = (struct i2s_device *)dev_get(i2s_devid);
|
|
if(!i2s_dev)
|
|
{
|
|
res = I2S_DEV_NULL;
|
|
goto audio_i2s_install_end;
|
|
}
|
|
|
|
if(!config->play_empty_buf)
|
|
{
|
|
res = I2S_PLAY_EMPTY_BUF_NULL;
|
|
goto audio_i2s_install_end;
|
|
}
|
|
|
|
if(!config->set_buf && !config->get_buf)
|
|
{
|
|
res = I2S_REGISTER_FUNC_NULL;
|
|
goto audio_i2s_install_end;
|
|
}
|
|
|
|
|
|
config->i2s_dev = i2s_dev;
|
|
sample_freq = config->sample_freq;
|
|
sample_bit = config->sample_bit;
|
|
data_format = config->data_fmt;
|
|
i2s_open(i2s_dev , I2S_MODE_MASTER, sample_freq, sample_bit);
|
|
//设置duplex_en
|
|
i2s_ioctl(i2s_dev,I2S_IOCTL_CMD_SET_DUPLEX,duplex_en);
|
|
i2s_ioctl(i2s_dev, I2S_IOCTL_CMD_SET_DATA_FMT, data_format);
|
|
i2s_request_irq(i2s_dev , I2S_IRQ_FLAG_HALF | I2S_IRQ_FLAG_FULL, (i2s_irq_hdl)audio_8311_irq_handle, (uint32)config);
|
|
config->irq_func(i2s_dev , config->play_empty_buf, config->buf_size);
|
|
|
|
|
|
}
|
|
|
|
if(mic_config && mic_config->i2s_devid != ~0)
|
|
{
|
|
|
|
|
|
config = mic_config;
|
|
config->irq_func = i2s_read;
|
|
i2s_devid = config->i2s_devid;
|
|
i2s_dev = (struct i2s_device *)dev_get(i2s_devid);
|
|
|
|
if(!config->set_buf && !config->get_buf)
|
|
{
|
|
res = I2S_REGISTER_FUNC_NULL;
|
|
goto audio_i2s_install_end;
|
|
}
|
|
|
|
if(!i2s_dev)
|
|
{
|
|
res = I2S_DEV_NULL;
|
|
goto audio_i2s_install_end;
|
|
}
|
|
config->i2s_dev = i2s_dev;
|
|
data_format = config->data_fmt;
|
|
if(duplex_en == 1)
|
|
{
|
|
i2s_open(i2s_dev , I2S_MODE_MASTER, sample_freq, sample_bit);
|
|
}
|
|
else
|
|
{
|
|
i2s_open(i2s_dev , I2S_MODE_MASTER, config->sample_freq, config->sample_bit);
|
|
}
|
|
|
|
//设置duplex_en
|
|
i2s_ioctl(i2s_dev,I2S_IOCTL_CMD_SET_DUPLEX,duplex_en);
|
|
i2s_ioctl(i2s_dev, I2S_IOCTL_CMD_SET_DATA_FMT, data_format);
|
|
i2s_request_irq(i2s_dev , I2S_IRQ_FLAG_HALF | I2S_IRQ_FLAG_FULL, (i2s_irq_hdl)audio_8311_irq_handle, (uint32)config);
|
|
buf = config->set_buf(config->priv_el,&config->current_node,&buf_size);
|
|
if(!buf)
|
|
{
|
|
res = I2S_MIC_FIRST_BUF_NULL;
|
|
goto audio_i2s_install_end;
|
|
}
|
|
config->irq_func(i2s_dev, buf, buf_size);
|
|
}
|
|
|
|
//如果是同步,则运行同步操作
|
|
if(duplex_en)
|
|
{
|
|
uint32 con = 0;
|
|
uint32 sys_con = 0;
|
|
|
|
__disable_irq();
|
|
con = (*((volatile uint32 *)0x40004900));
|
|
con &= ~ BIT(8);
|
|
con |= BIT(0);
|
|
|
|
sys_con = SYSCTRL->SYS_CON2;
|
|
sys_con &= ~ BIT(0);
|
|
demo_sram(sys_con,con);
|
|
__enable_irq();
|
|
|
|
}
|
|
|
|
res = RET_OK;
|
|
audio_i2s_install_end:
|
|
return res;
|
|
}
|
|
|
|
int audio_i2s_uninstall(audio_i2s_config *play_config,audio_i2s_config *mic_config)
|
|
{
|
|
int res = RET_ERR;
|
|
int i2s_devid;
|
|
struct i2s_device *i2s_dev;
|
|
audio_i2s_config *config;
|
|
if(play_config && play_config->i2s_devid != ~0)
|
|
{
|
|
config = play_config;
|
|
i2s_devid = config->i2s_devid;
|
|
i2s_dev = (struct i2s_device *)dev_get(i2s_devid);
|
|
if(!i2s_dev)
|
|
{
|
|
goto audio_i2s_uninstall_end;
|
|
}
|
|
i2s_close(i2s_dev);
|
|
}
|
|
|
|
if(mic_config && mic_config->i2s_devid != ~0)
|
|
{
|
|
config = mic_config;
|
|
i2s_devid = config->i2s_devid;
|
|
i2s_dev = (struct i2s_device *)dev_get(i2s_devid);
|
|
if(!i2s_dev)
|
|
{
|
|
goto audio_i2s_uninstall_end;
|
|
}
|
|
i2s_close(i2s_dev);
|
|
|
|
}
|
|
res = I2S_OK;
|
|
audio_i2s_uninstall_end:
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|