123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- #include "include.h"
- #include "bsp_vad.h"
- #include "asr.h"
- #if VAD_EN
- #define TRACE_EN 0
- #if TRACE_EN
- #define TRACE(...) printf(__VA_ARGS__)
- #else
- #define TRACE(...)
- #endif
- void asr_kick_start(void);
- u32 getcfg_mic_bias_method(u8 mic_ch);
- static void vad_reset(void);
- #if VAD_MODE_SEL == VAD_MODE_1
- AT(.vad.mic_buf.adc)
- u16 vad_sdadc_buf[VAD_DMA_SIZE];
- #else
- struct asr_buf_t {
- volatile s16 wptr;
- volatile s16 rptr;
- short pcm_buf[ASR_PCM_BUFF_NUM][ASR_PCM_NUM];
- } asr_buf AT(.vad.mic_buf.data);
- #endif
- typedef enum {
- VAD_NORMAL = 0,
- VAD_SLEEP,
- VAD_W4_WAKE,
- } VAD_SLEEP_STA;
- typedef enum {
- VAD_IDLE = 0,
- VAD_START,
- VAD_CONTINUE,
- } VAD_STA;
- typedef struct {
- volatile u8 sta; //vad唤醒状态
- volatile u8 sleep_flag;
- volatile u16 offset; //VADDMACON0的高16位, +1:u8
- u8 start; //vad功能是否启动
- u16 vad_reboot_cnt; //vad reboot 计数
- u16 *speech_start; //语音在adcdma上对应的起始地址
- u32 start_tick; //唤醒时的tick
- u32 dma_len; //DMA总长度
- u8 *dma_ptr; //DMA 中断触发模式,half or all done
- u8 *dma_ptr_t;
- u32 dma_addr_end;
- u32 samples; //vad的样点数
- u16 neg_flag_cnt;
- u8 voice_flag;
- bool init_flag;
- } vad_cb_t;
- static vad_cb_t vad_cb;
- #if VAD_MODE_SEL == VAD_MODE_1
- //计算预取前面frames_num帧的offset
- AT(.vad_text.vad)
- static void vad_prefetch_cal(u16 frames_num)
- {
- u32 vad_len = frames_num * vad_cb.samples;
- //VAD要取512个u16的整数倍,offset要往前推成整数
- if(vad_cb.offset < KWS_SAMPLES) {
- vad_cb.offset = 0;
- } else {
- vad_cb.offset -= ((vad_cb.offset)%KWS_SAMPLES);
- }
- //计算往前推frames_num帧之后,VAD在DMA上的起始地址
- if(vad_cb.offset >= vad_len) {
- vad_cb.speech_start = (u16 *)(asr_get_adc_buff_addr() + ((vad_cb.offset - vad_len)<<1));
- } else {
- vad_cb.speech_start = (u16 *)(asr_get_adc_buff_addr() + ((vad_cb.dma_len - (vad_len - vad_cb.offset))<<1));
- }
- }
- //取出前面(512点/帧)的数据
- AT(.vad_text.vad)
- static u32 vad_prefetch_read(void)
- {
- u32 p = (u32)vad_cb.speech_start;
- vad_cb.speech_start += KWS_SAMPLES;
- if ((u32)vad_cb.speech_start >= vad_cb.dma_addr_end) {
- vad_cb.speech_start = (u16 *)asr_get_adc_buff_addr();
- }
- return p;
- }
- AT(.vad_text.vad)
- static u32 vad_dma_audio_read(u16 offset)
- {
- u32 rptr;
- if (vad_cb.offset > 0) {
- rptr = asr_get_adc_buff_addr() + vad_cb.offset * 2;
- } else {
- rptr = (u32)vad_cb.dma_ptr_t;
- }
- u32 p = (u32)(rptr + (offset << 1));
- if (p >= vad_cb.dma_addr_end) {
- //TRACE("vad_dma_audio_read p:%x vad_cb.dma_addr_end:%x\n", p, vad_cb.dma_addr_end);
- p = asr_get_adc_buff_addr();
- }
- return p;
- }
- AT(.vad_text.vad)
- static void vad_continue_process(void)
- {
- s16 num, num2;
- u8 i;
- int16_t *rptr;
- u16 offset, dma_half_size;
- num2 = 0;
- offset = vad_cb.offset;
- vad_cb.dma_ptr_t = vad_cb.dma_ptr;
- dma_half_size = vad_cb.dma_len / 2;
- num = dma_half_size >> 9; //除以512, 计算DMA中有num个512帧
- if (offset > 0) { //刚取完前面帧,不需要取DMA所有数据
- if ((u32)vad_cb.dma_ptr_t == asr_get_adc_buff_addr()) {
- if (offset <= dma_half_size) { //VAD起来的offset位于half done前 //offset==dma_half_size, num-num2=0
- num2 = offset>>9; // 除以512
- } else { //dma half done, 但是VAD起来的offset位于all done前
- offset = (dma_half_size<<1) - offset;
- num2 = -(offset>>9);
- }
- } else {
- if (offset > dma_half_size) { //VAD起来的offset位于all done前 //offset==dma_half_size, num-num2=0
- offset = offset - dma_half_size;
- num2 = offset>>9;
- } else { //dma all done, 但是VAD起来的offset位于half done前
- offset = dma_half_size - offset;
- num2 = -(offset>>9);
- }
- }
- }
- if (num2 > num) {
- TRACE("------------vad offset error!--------\n");
- vad_reset(); //VAD强制清零
- return;
- }
- num -= num2;
- #if DEBUG_EN
- GPIOASET = BIT(14);
- #endif
- TRACE("num %d %d\n", num, num2);
- for (i = 0; i < num; i++) {
- rptr = (int16_t *)vad_dma_audio_read(KWS_SAMPLES * i);
- asr_callback_process(rptr);
- // if (i != 0 && i % 5 == 0) delay_5ms(1); //主动释放线程5ms
- }
- #if DEBUG_EN
- GPIOACLR = BIT(14);
- #endif
- vad_cb.offset = 0;
- }
- #else
- AT(.com_text.alg)
- static s16 alg_ptr_to_next(s16 ptr)
- {
- s16 res = ptr + 1;
- if (res >= ASR_PCM_BUFF_NUM) {
- res = 0;
- }
- return res;
- }
- void vad_force_asr_start(void)
- {
- vad_cb.start_tick = tick_get();
- struct asr_buf_t *p = &asr_buf;
- p->rptr = ASR_PCM_BUFF_NUM - 2;
- vad_cb.sta = VAD_START;
- if (vad_cb.sleep_flag == VAD_SLEEP) {
- vad_cb.sleep_flag = VAD_W4_WAKE;
- } else if (vad_cb.sleep_flag == VAD_NORMAL) {
- asr_kick_start();
- }
- }
- #endif
- AT(.com_text.vad)
- static void vad_reboot(void)
- {
- if (vad_cb.init_flag) {
- VADCON0 &= ~BIT(0); //VAD disable
- vad_cb.vad_reboot_cnt = 0;
- VADCON0 |= BIT(0); //VAD enable
- }
- }
- AT(.vad_text.vad)
- static void vad_reset(void)
- {
- if (vad_cb.init_flag) {
- TRACE("%s\n",__func__);
- VADCON0 &= ~BIT(0); //VAD disable
- vad_cb.sta = VAD_IDLE;
- vad_cb.offset = 0;
- vad_cb.speech_start = 0;
- vad_cb.start_tick = 0;
- VADCON0 |= BIT(0); //VAD enable
- SDADC0DMACON |= BIT(9); //VAD interrupt enable
- sys_clk_free(INDEX_KARAOK);
- }
- }
- AT(.com_text.vad.sta)
- bool vad_is_start(void)
- {
- return vad_cb.start;
- }
- ///返回VAD是否已经唤醒
- AT(.vad_text.vad)
- bool vad_is_wake(void)
- {
- return (bool)(vad_cb.sta >= VAD_START);
- }
- ///VAD启动检测
- void vad_start(void)
- {
- if (vad_cb.init_flag) {
- vad_reset();
- SDADC0DMACON &= ~BIT(9); //VAD interrupt disable
- SDADCDMACLR |= BIT(24); //clear VAD interrupt flag
- SDADC0DMACON |= BIT(9); //VAD interrupt enable
- VADCON0 |= BIT(6); // tick
- VADCON0 |= BIT(0); // VAD enable
- vad_cb.start = 1;
- TRACE("VADCON0 %08x\n",VADCON0);
- TRACE("VADCON1 %08x\n",VADCON1);
- TRACE("VADCON2 %08x\n",VADCON2);
- TRACE("SDADCDMACON:%08x\n", SDADCDMACON);
- }
- }
- void vad_stop(void)
- {
- if (vad_cb.init_flag) {
- SDADC0DMACON &= ~BIT(9); //VAD interrupt disable
- SDADCDMACLR |= BIT(24);
- VADCON0 &= ~BIT(0); //VAD disable
- VADCON0 &= ~BIT(6); // tick
- vad_cb.start = 0;
- vad_cb.sta = VAD_IDLE;
- vad_cb.init_flag = false;
- }
- }
- ///进出休眠模式的配置
- AT(.vad_text.vad)
- void vad_sleep_config(bool enter)
- {
- if (enter) {
- vad_cb.sleep_flag = VAD_SLEEP;
- vad_reset();
- } else {
- vad_cb.sleep_flag = VAD_NORMAL;
- if (vad_cb.sta == VAD_START && vad_cb.sleep_flag == VAD_NORMAL) {
- asr_kick_start();
- }
- }
- }
- AT(.vad_text.vad.proc)
- void vad_kws_process(void)
- {
- if ((KWS_RUNTIME_LIMIT != 0) && (vad_cb.start_tick > 0)) {
- if (tick_check_expire(vad_cb.start_tick, KWS_RUNTIME_LIMIT)) { //超过KWS限制的时间
- vad_reset();
- return;
- }
- }
- #if VAD_MODE_SEL == VAD_MODE_1
- if (vad_cb.sta == VAD_START) {
- sys_clk_req(INDEX_KARAOK,SYS_160M); //借用INDEX_KARAOK
- u8 vad_pre_num = VAD_PREFETCH_NUM + VAD_PRE_GET;
- vad_prefetch_cal(vad_pre_num * 512 / vad_cb.samples);
- int16_t *rptr;
- for (u8 i = 0; i < vad_pre_num; i++) {
- //先把当前DMA的数据取出来扔到asr alg
- rptr = (int16_t *)vad_prefetch_read();
- asr_callback_process(rptr);
- // if (i != 0 && i % 5 == 0) delay_5ms(1); //主动释放线程5ms
- }
- TRACE("VAD_START\n");
- TRACE("vad_pre_num: %d\n", vad_pre_num);
- TRACE("vad offset: %x\n", vad_cb.offset);
- vad_cb.sta = VAD_CONTINUE;
- } else if (vad_cb.sta == VAD_CONTINUE){
- vad_continue_process();
- }
- #else
- struct asr_buf_t *p = &asr_buf;
- if (vad_cb.sta == VAD_START) {
- sys_clk_req(INDEX_KARAOK,SYS_160M);
- asr_callback_process(p->pcm_buf[p->rptr]);
- p->rptr = alg_ptr_to_next(p->rptr);
- vad_cb.sta = VAD_CONTINUE;
- } else if (vad_cb.sta == VAD_CONTINUE){
- asr_callback_process(p->pcm_buf[p->rptr]);
- p->rptr = alg_ptr_to_next(p->rptr);
- }
- #endif
- }
- AT(.com_text.vad)
- void vad_isr(void)
- {
- if ((SDADCDMAFLAG & BIT(24))) {
- SDADCDMACLR |= BIT(24);
- SDADC0DMACON &= ~BIT(9); //VAD interrupt disable
- vad_cb.offset = VADDMACON>> 16; //获取VAD中断时,VAD DMA BUFF的偏移地址
- vad_cb.start_tick = tick_get();
- vad_cb.vad_reboot_cnt = 0;
- vad_cb.voice_flag = 1;
- #if VAD_MODE_SEL == VAD_MODE_2
- struct asr_buf_t *p = &asr_buf;
- p->rptr = p->wptr - (ASR_PRE_READ + 1);
- if (p->rptr < 0) {
- p->rptr += ASR_PCM_BUFF_NUM;
- }
- #endif
- vad_cb.sta = VAD_START;
- if (vad_cb.sleep_flag == VAD_SLEEP) {
- vad_cb.sleep_flag = VAD_W4_WAKE;
- } else if (vad_cb.sleep_flag == VAD_NORMAL) {
- asr_kick_start();
- }
- }
- }
- ///SDADC DMA中断
- AT(.com_text.vad)
- void vad_sdadc_isr(void)
- {
- if (SDADCDMAFLAG & BIT(24)) { //VAD voice
- SDADCDMACLR |= BIT(24);
- if (vad_cb.sta == VAD_CONTINUE) {
- if (vad_cb.neg_flag_cnt) {
- vad_cb.neg_flag_cnt--;
- if (vad_cb.neg_flag_cnt == (VAD_NEG_FLAG_THRESHOLD - 1)) {
- vad_cb.neg_flag_cnt = VAD_NEG_FLAG_THRESHOLD / 2;
- vad_cb.voice_flag = 1;
- }
- }
- }
- } else { //VAD not voice
- if (vad_cb.sta == VAD_CONTINUE) {
- if (vad_cb.neg_flag_cnt >= VAD_NEG_FLAG_THRESHOLD) {
- vad_cb.neg_flag_cnt = VAD_NEG_FLAG_THRESHOLD;
- vad_cb.voice_flag = 0;
- } else {
- vad_cb.neg_flag_cnt++;
- }
- }
- }
- }
- AT(.com_text.vad.proc)
- void vad_sdadc_process(u8 *ptr, u32 samples, int ch_mode)
- {
- vad_cb.vad_reboot_cnt++;
- if (vad_cb.vad_reboot_cnt >= VAD_REBOOT_THRESOLD ) {
- vad_reboot();
- }
- #if VAD_MODE_SEL == VAD_MODE_1
- vad_cb.dma_ptr = ptr;
- #else
- struct asr_buf_t *p = &asr_buf;
- memcpy(p->pcm_buf[p->wptr], ptr, ASR_PCM_NUM * 2);
- p->wptr = alg_ptr_to_next(p->wptr);
- #endif
- if (((vad_cb.sta == VAD_CONTINUE) || (vad_cb.sta == VAD_START)) && vad_cb.sleep_flag == VAD_NORMAL) {
- asr_kick_start();
- }
- }
- u8 vad_init(void)
- {
- #if VAD_MODE_SEL == VAD_MODE_2
- memset(&asr_buf, 0, sizeof(struct asr_buf_t));
- #endif
- memset(&vad_cb,0,sizeof(vad_cb_t));
- vad_cb.dma_len = asr_get_adc_buff_len();
- vad_cb.dma_addr_end = asr_get_adc_buff_addr() + vad_cb.dma_len * 2;
- vad_cb.sta = VAD_IDLE;
- vad_cb.start = 0;
- vad_cb.samples = (1 << VAD_SAMPLES) * 128;
- CLKGAT3 |= BIT(12); //vad_clken
- delay_ms(1);
- VADCON0 = 0;
- u8 mic_index = xcfg_cb.bt_mmic_cfg;
- VADCON0 |= (mic_index << 1);
- VADCON0 |= (VAD_SAMPLES << 4); //sample
- VADCON1 = (VAD_NEG_CNT | (VAD_POS_CNT << 16));
- VADCON2 = 0x00FF000F;
- vad_cb.init_flag = true;
- return 1;
- }
- u8 vad_mic_pwr_sel_io(void)
- {
- u8 mic_index = xcfg_cb.bt_mmic_cfg;
- u8 io = (getcfg_mic_bias_method(mic_index+1)& 0xf0) >> 4;
- return io;
- }
- void bsp_vad_start(void)
- {
- #if ASR_DUMP_EN
- asr_huart_init();
- #endif
- vad_init();
- vad_start();
- #if VAD_MODE_SEL == VAD_MODE_2
- vad_force_asr_start();
- #endif
- }
- void bsp_vad_stop(void)
- {
- vad_stop();
- }
- #endif
|