bsp_vad.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. #include "include.h"
  2. #include "bsp_vad.h"
  3. #include "asr.h"
  4. #if VAD_EN
  5. #define TRACE_EN 0
  6. #if TRACE_EN
  7. #define TRACE(...) printf(__VA_ARGS__)
  8. #else
  9. #define TRACE(...)
  10. #endif
  11. void asr_kick_start(void);
  12. u32 getcfg_mic_bias_method(u8 mic_ch);
  13. static void vad_reset(void);
  14. #if VAD_MODE_SEL == VAD_MODE_1
  15. AT(.vad.mic_buf.adc)
  16. u16 vad_sdadc_buf[VAD_DMA_SIZE];
  17. #else
  18. struct asr_buf_t {
  19. volatile s16 wptr;
  20. volatile s16 rptr;
  21. short pcm_buf[ASR_PCM_BUFF_NUM][ASR_PCM_NUM];
  22. } asr_buf AT(.vad.mic_buf.data);
  23. #endif
  24. typedef enum {
  25. VAD_NORMAL = 0,
  26. VAD_SLEEP,
  27. VAD_W4_WAKE,
  28. } VAD_SLEEP_STA;
  29. typedef enum {
  30. VAD_IDLE = 0,
  31. VAD_START,
  32. VAD_CONTINUE,
  33. } VAD_STA;
  34. typedef struct {
  35. volatile u8 sta; //vad唤醒状态
  36. volatile u8 sleep_flag;
  37. volatile u16 offset; //VADDMACON0的高16位, +1:u8
  38. u8 start; //vad功能是否启动
  39. u16 vad_reboot_cnt; //vad reboot 计数
  40. u16 *speech_start; //语音在adcdma上对应的起始地址
  41. u32 start_tick; //唤醒时的tick
  42. u32 dma_len; //DMA总长度
  43. u8 *dma_ptr; //DMA 中断触发模式,half or all done
  44. u8 *dma_ptr_t;
  45. u32 dma_addr_end;
  46. u32 samples; //vad的样点数
  47. u16 neg_flag_cnt;
  48. u8 voice_flag;
  49. bool init_flag;
  50. } vad_cb_t;
  51. static vad_cb_t vad_cb;
  52. #if VAD_MODE_SEL == VAD_MODE_1
  53. //计算预取前面frames_num帧的offset
  54. AT(.vad_text.vad)
  55. static void vad_prefetch_cal(u16 frames_num)
  56. {
  57. u32 vad_len = frames_num * vad_cb.samples;
  58. //VAD要取512个u16的整数倍,offset要往前推成整数
  59. if(vad_cb.offset < KWS_SAMPLES) {
  60. vad_cb.offset = 0;
  61. } else {
  62. vad_cb.offset -= ((vad_cb.offset)%KWS_SAMPLES);
  63. }
  64. //计算往前推frames_num帧之后,VAD在DMA上的起始地址
  65. if(vad_cb.offset >= vad_len) {
  66. vad_cb.speech_start = (u16 *)(asr_get_adc_buff_addr() + ((vad_cb.offset - vad_len)<<1));
  67. } else {
  68. vad_cb.speech_start = (u16 *)(asr_get_adc_buff_addr() + ((vad_cb.dma_len - (vad_len - vad_cb.offset))<<1));
  69. }
  70. }
  71. //取出前面(512点/帧)的数据
  72. AT(.vad_text.vad)
  73. static u32 vad_prefetch_read(void)
  74. {
  75. u32 p = (u32)vad_cb.speech_start;
  76. vad_cb.speech_start += KWS_SAMPLES;
  77. if ((u32)vad_cb.speech_start >= vad_cb.dma_addr_end) {
  78. vad_cb.speech_start = (u16 *)asr_get_adc_buff_addr();
  79. }
  80. return p;
  81. }
  82. AT(.vad_text.vad)
  83. static u32 vad_dma_audio_read(u16 offset)
  84. {
  85. u32 rptr;
  86. if (vad_cb.offset > 0) {
  87. rptr = asr_get_adc_buff_addr() + vad_cb.offset * 2;
  88. } else {
  89. rptr = (u32)vad_cb.dma_ptr_t;
  90. }
  91. u32 p = (u32)(rptr + (offset << 1));
  92. if (p >= vad_cb.dma_addr_end) {
  93. //TRACE("vad_dma_audio_read p:%x vad_cb.dma_addr_end:%x\n", p, vad_cb.dma_addr_end);
  94. p = asr_get_adc_buff_addr();
  95. }
  96. return p;
  97. }
  98. AT(.vad_text.vad)
  99. static void vad_continue_process(void)
  100. {
  101. s16 num, num2;
  102. u8 i;
  103. int16_t *rptr;
  104. u16 offset, dma_half_size;
  105. num2 = 0;
  106. offset = vad_cb.offset;
  107. vad_cb.dma_ptr_t = vad_cb.dma_ptr;
  108. dma_half_size = vad_cb.dma_len / 2;
  109. num = dma_half_size >> 9; //除以512, 计算DMA中有num个512帧
  110. if (offset > 0) { //刚取完前面帧,不需要取DMA所有数据
  111. if ((u32)vad_cb.dma_ptr_t == asr_get_adc_buff_addr()) {
  112. if (offset <= dma_half_size) { //VAD起来的offset位于half done前 //offset==dma_half_size, num-num2=0
  113. num2 = offset>>9; // 除以512
  114. } else { //dma half done, 但是VAD起来的offset位于all done前
  115. offset = (dma_half_size<<1) - offset;
  116. num2 = -(offset>>9);
  117. }
  118. } else {
  119. if (offset > dma_half_size) { //VAD起来的offset位于all done前 //offset==dma_half_size, num-num2=0
  120. offset = offset - dma_half_size;
  121. num2 = offset>>9;
  122. } else { //dma all done, 但是VAD起来的offset位于half done前
  123. offset = dma_half_size - offset;
  124. num2 = -(offset>>9);
  125. }
  126. }
  127. }
  128. if (num2 > num) {
  129. TRACE("------------vad offset error!--------\n");
  130. vad_reset(); //VAD强制清零
  131. return;
  132. }
  133. num -= num2;
  134. #if DEBUG_EN
  135. GPIOASET = BIT(14);
  136. #endif
  137. TRACE("num %d %d\n", num, num2);
  138. for (i = 0; i < num; i++) {
  139. rptr = (int16_t *)vad_dma_audio_read(KWS_SAMPLES * i);
  140. asr_callback_process(rptr);
  141. // if (i != 0 && i % 5 == 0) delay_5ms(1); //主动释放线程5ms
  142. }
  143. #if DEBUG_EN
  144. GPIOACLR = BIT(14);
  145. #endif
  146. vad_cb.offset = 0;
  147. }
  148. #else
  149. AT(.com_text.alg)
  150. static s16 alg_ptr_to_next(s16 ptr)
  151. {
  152. s16 res = ptr + 1;
  153. if (res >= ASR_PCM_BUFF_NUM) {
  154. res = 0;
  155. }
  156. return res;
  157. }
  158. void vad_force_asr_start(void)
  159. {
  160. vad_cb.start_tick = tick_get();
  161. struct asr_buf_t *p = &asr_buf;
  162. p->rptr = ASR_PCM_BUFF_NUM - 2;
  163. vad_cb.sta = VAD_START;
  164. if (vad_cb.sleep_flag == VAD_SLEEP) {
  165. vad_cb.sleep_flag = VAD_W4_WAKE;
  166. } else if (vad_cb.sleep_flag == VAD_NORMAL) {
  167. asr_kick_start();
  168. }
  169. }
  170. #endif
  171. AT(.com_text.vad)
  172. static void vad_reboot(void)
  173. {
  174. if (vad_cb.init_flag) {
  175. VADCON0 &= ~BIT(0); //VAD disable
  176. vad_cb.vad_reboot_cnt = 0;
  177. VADCON0 |= BIT(0); //VAD enable
  178. }
  179. }
  180. AT(.vad_text.vad)
  181. static void vad_reset(void)
  182. {
  183. if (vad_cb.init_flag) {
  184. TRACE("%s\n",__func__);
  185. VADCON0 &= ~BIT(0); //VAD disable
  186. vad_cb.sta = VAD_IDLE;
  187. vad_cb.offset = 0;
  188. vad_cb.speech_start = 0;
  189. vad_cb.start_tick = 0;
  190. VADCON0 |= BIT(0); //VAD enable
  191. SDADC0DMACON |= BIT(9); //VAD interrupt enable
  192. sys_clk_free(INDEX_KARAOK);
  193. }
  194. }
  195. AT(.com_text.vad.sta)
  196. bool vad_is_start(void)
  197. {
  198. return vad_cb.start;
  199. }
  200. ///返回VAD是否已经唤醒
  201. AT(.vad_text.vad)
  202. bool vad_is_wake(void)
  203. {
  204. return (bool)(vad_cb.sta >= VAD_START);
  205. }
  206. ///VAD启动检测
  207. void vad_start(void)
  208. {
  209. if (vad_cb.init_flag) {
  210. vad_reset();
  211. SDADC0DMACON &= ~BIT(9); //VAD interrupt disable
  212. SDADCDMACLR |= BIT(24); //clear VAD interrupt flag
  213. SDADC0DMACON |= BIT(9); //VAD interrupt enable
  214. VADCON0 |= BIT(6); // tick
  215. VADCON0 |= BIT(0); // VAD enable
  216. vad_cb.start = 1;
  217. TRACE("VADCON0 %08x\n",VADCON0);
  218. TRACE("VADCON1 %08x\n",VADCON1);
  219. TRACE("VADCON2 %08x\n",VADCON2);
  220. TRACE("SDADCDMACON:%08x\n", SDADCDMACON);
  221. }
  222. }
  223. void vad_stop(void)
  224. {
  225. if (vad_cb.init_flag) {
  226. SDADC0DMACON &= ~BIT(9); //VAD interrupt disable
  227. SDADCDMACLR |= BIT(24);
  228. VADCON0 &= ~BIT(0); //VAD disable
  229. VADCON0 &= ~BIT(6); // tick
  230. vad_cb.start = 0;
  231. vad_cb.sta = VAD_IDLE;
  232. vad_cb.init_flag = false;
  233. }
  234. }
  235. ///进出休眠模式的配置
  236. AT(.vad_text.vad)
  237. void vad_sleep_config(bool enter)
  238. {
  239. if (enter) {
  240. vad_cb.sleep_flag = VAD_SLEEP;
  241. vad_reset();
  242. } else {
  243. vad_cb.sleep_flag = VAD_NORMAL;
  244. if (vad_cb.sta == VAD_START && vad_cb.sleep_flag == VAD_NORMAL) {
  245. asr_kick_start();
  246. }
  247. }
  248. }
  249. AT(.vad_text.vad.proc)
  250. void vad_kws_process(void)
  251. {
  252. if ((KWS_RUNTIME_LIMIT != 0) && (vad_cb.start_tick > 0)) {
  253. if (tick_check_expire(vad_cb.start_tick, KWS_RUNTIME_LIMIT)) { //超过KWS限制的时间
  254. vad_reset();
  255. return;
  256. }
  257. }
  258. #if VAD_MODE_SEL == VAD_MODE_1
  259. if (vad_cb.sta == VAD_START) {
  260. sys_clk_req(INDEX_KARAOK,SYS_160M); //借用INDEX_KARAOK
  261. u8 vad_pre_num = VAD_PREFETCH_NUM + VAD_PRE_GET;
  262. vad_prefetch_cal(vad_pre_num * 512 / vad_cb.samples);
  263. int16_t *rptr;
  264. for (u8 i = 0; i < vad_pre_num; i++) {
  265. //先把当前DMA的数据取出来扔到asr alg
  266. rptr = (int16_t *)vad_prefetch_read();
  267. asr_callback_process(rptr);
  268. // if (i != 0 && i % 5 == 0) delay_5ms(1); //主动释放线程5ms
  269. }
  270. TRACE("VAD_START\n");
  271. TRACE("vad_pre_num: %d\n", vad_pre_num);
  272. TRACE("vad offset: %x\n", vad_cb.offset);
  273. vad_cb.sta = VAD_CONTINUE;
  274. } else if (vad_cb.sta == VAD_CONTINUE){
  275. vad_continue_process();
  276. }
  277. #else
  278. struct asr_buf_t *p = &asr_buf;
  279. if (vad_cb.sta == VAD_START) {
  280. sys_clk_req(INDEX_KARAOK,SYS_160M);
  281. asr_callback_process(p->pcm_buf[p->rptr]);
  282. p->rptr = alg_ptr_to_next(p->rptr);
  283. vad_cb.sta = VAD_CONTINUE;
  284. } else if (vad_cb.sta == VAD_CONTINUE){
  285. asr_callback_process(p->pcm_buf[p->rptr]);
  286. p->rptr = alg_ptr_to_next(p->rptr);
  287. }
  288. #endif
  289. }
  290. AT(.com_text.vad)
  291. void vad_isr(void)
  292. {
  293. if ((SDADCDMAFLAG & BIT(24))) {
  294. SDADCDMACLR |= BIT(24);
  295. SDADC0DMACON &= ~BIT(9); //VAD interrupt disable
  296. vad_cb.offset = VADDMACON>> 16; //获取VAD中断时,VAD DMA BUFF的偏移地址
  297. vad_cb.start_tick = tick_get();
  298. vad_cb.vad_reboot_cnt = 0;
  299. vad_cb.voice_flag = 1;
  300. #if VAD_MODE_SEL == VAD_MODE_2
  301. struct asr_buf_t *p = &asr_buf;
  302. p->rptr = p->wptr - (ASR_PRE_READ + 1);
  303. if (p->rptr < 0) {
  304. p->rptr += ASR_PCM_BUFF_NUM;
  305. }
  306. #endif
  307. vad_cb.sta = VAD_START;
  308. if (vad_cb.sleep_flag == VAD_SLEEP) {
  309. vad_cb.sleep_flag = VAD_W4_WAKE;
  310. } else if (vad_cb.sleep_flag == VAD_NORMAL) {
  311. asr_kick_start();
  312. }
  313. }
  314. }
  315. ///SDADC DMA中断
  316. AT(.com_text.vad)
  317. void vad_sdadc_isr(void)
  318. {
  319. if (SDADCDMAFLAG & BIT(24)) { //VAD voice
  320. SDADCDMACLR |= BIT(24);
  321. if (vad_cb.sta == VAD_CONTINUE) {
  322. if (vad_cb.neg_flag_cnt) {
  323. vad_cb.neg_flag_cnt--;
  324. if (vad_cb.neg_flag_cnt == (VAD_NEG_FLAG_THRESHOLD - 1)) {
  325. vad_cb.neg_flag_cnt = VAD_NEG_FLAG_THRESHOLD / 2;
  326. vad_cb.voice_flag = 1;
  327. }
  328. }
  329. }
  330. } else { //VAD not voice
  331. if (vad_cb.sta == VAD_CONTINUE) {
  332. if (vad_cb.neg_flag_cnt >= VAD_NEG_FLAG_THRESHOLD) {
  333. vad_cb.neg_flag_cnt = VAD_NEG_FLAG_THRESHOLD;
  334. vad_cb.voice_flag = 0;
  335. } else {
  336. vad_cb.neg_flag_cnt++;
  337. }
  338. }
  339. }
  340. }
  341. AT(.com_text.vad.proc)
  342. void vad_sdadc_process(u8 *ptr, u32 samples, int ch_mode)
  343. {
  344. vad_cb.vad_reboot_cnt++;
  345. if (vad_cb.vad_reboot_cnt >= VAD_REBOOT_THRESOLD ) {
  346. vad_reboot();
  347. }
  348. #if VAD_MODE_SEL == VAD_MODE_1
  349. vad_cb.dma_ptr = ptr;
  350. #else
  351. struct asr_buf_t *p = &asr_buf;
  352. memcpy(p->pcm_buf[p->wptr], ptr, ASR_PCM_NUM * 2);
  353. p->wptr = alg_ptr_to_next(p->wptr);
  354. #endif
  355. if (((vad_cb.sta == VAD_CONTINUE) || (vad_cb.sta == VAD_START)) && vad_cb.sleep_flag == VAD_NORMAL) {
  356. asr_kick_start();
  357. }
  358. }
  359. u8 vad_init(void)
  360. {
  361. #if VAD_MODE_SEL == VAD_MODE_2
  362. memset(&asr_buf, 0, sizeof(struct asr_buf_t));
  363. #endif
  364. memset(&vad_cb,0,sizeof(vad_cb_t));
  365. vad_cb.dma_len = asr_get_adc_buff_len();
  366. vad_cb.dma_addr_end = asr_get_adc_buff_addr() + vad_cb.dma_len * 2;
  367. vad_cb.sta = VAD_IDLE;
  368. vad_cb.start = 0;
  369. vad_cb.samples = (1 << VAD_SAMPLES) * 128;
  370. CLKGAT3 |= BIT(12); //vad_clken
  371. delay_ms(1);
  372. VADCON0 = 0;
  373. u8 mic_index = xcfg_cb.bt_mmic_cfg;
  374. VADCON0 |= (mic_index << 1);
  375. VADCON0 |= (VAD_SAMPLES << 4); //sample
  376. VADCON1 = (VAD_NEG_CNT | (VAD_POS_CNT << 16));
  377. VADCON2 = 0x00FF000F;
  378. vad_cb.init_flag = true;
  379. return 1;
  380. }
  381. u8 vad_mic_pwr_sel_io(void)
  382. {
  383. u8 mic_index = xcfg_cb.bt_mmic_cfg;
  384. u8 io = (getcfg_mic_bias_method(mic_index+1)& 0xf0) >> 4;
  385. return io;
  386. }
  387. void bsp_vad_start(void)
  388. {
  389. #if ASR_DUMP_EN
  390. asr_huart_init();
  391. #endif
  392. vad_init();
  393. vad_start();
  394. #if VAD_MODE_SEL == VAD_MODE_2
  395. vad_force_asr_start();
  396. #endif
  397. }
  398. void bsp_vad_stop(void)
  399. {
  400. vad_stop();
  401. }
  402. #endif