bsp_anc.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. #include "include.h"
  2. #if ANC_EN
  3. #define TRACE_EN 1
  4. #if TRACE_EN
  5. #define TRACE(...) printf(__VA_ARGS__)
  6. #else
  7. #define TRACE(...)
  8. #endif
  9. typedef struct {
  10. u16 gain;
  11. u8 nos_band;
  12. u8 msc_band;
  13. u32 param_buf[8 * 5 + 2];
  14. u32 drc_buf[20];
  15. u8 drc_band;
  16. u8 drc_en;
  17. u8 rfu[1];
  18. u8 bypass :1;
  19. } anc_channel_t;
  20. struct anc_cfg_t {
  21. anc_channel_t *ch;
  22. u8 spr;
  23. u8 rfu[1];
  24. u16 mic_type :3; //mic输入类型
  25. };
  26. typedef struct {
  27. u32 *addr;
  28. u32 *len;
  29. } anc_param;
  30. anc_channel_t anc_ch AT(.anc_buf.ch);
  31. struct anc_cfg_t anc_cfg AT(.anc.cfg);
  32. #define ANC_FIX_BIT 23
  33. #define EQ_GAIN_MAX 0x07eca9cd //24dB
  34. #define EQ_GAIN_MIN 0x00081385 //-24dB
  35. #define EQ_GAIN_STEP 2 //0.2dB
  36. static const anc_param anc_ff_eq_tbl[8] = {
  37. //降噪模式参数
  38. {&RES_BUF_ANC_L0_NOS_EQ, &RES_LEN_ANC_L0_NOS_EQ},
  39. {&RES_BUF_ANC_L0_NOS_DRC, &RES_LEN_ANC_L0_NOS_DRC},
  40. {&RES_BUF_ANC_R0_NOS_EQ, &RES_LEN_ANC_R0_NOS_EQ},
  41. {&RES_BUF_ANC_R0_NOS_DRC, &RES_LEN_ANC_R0_NOS_DRC},
  42. //通透模式参数
  43. {&RES_BUF_ANC_TP_L0_NOS_EQ, &RES_LEN_ANC_TP_L0_NOS_EQ},
  44. {&RES_BUF_ANC_TP_L0_NOS_DRC, &RES_LEN_ANC_TP_L0_NOS_DRC},
  45. {&RES_BUF_ANC_TP_R0_NOS_EQ, &RES_LEN_ANC_TP_R0_NOS_EQ},
  46. {&RES_BUF_ANC_TP_R0_NOS_DRC, &RES_LEN_ANC_TP_R0_NOS_DRC},
  47. };
  48. u32 bsp_anc_gain_adjust_do(s8 value)
  49. {
  50. s32 gain, abs_gain, adjust_val = 0;
  51. gain = (s32)sys_cb.anc_mic_gain; //初始gain值
  52. if (value != 0) {
  53. adjust_val = (s32)anc_pow10_cal(value * EQ_GAIN_STEP);
  54. gain = ((s64)gain * adjust_val) >> ANC_FIX_BIT;
  55. abs_gain = gain > 0? gain : -gain;
  56. if (abs_gain > EQ_GAIN_MAX || abs_gain < EQ_GAIN_MIN) {
  57. return sys_cb.anc_mic_gain;
  58. }
  59. }
  60. return (u32)gain;
  61. }
  62. void bsp_anc_gain_adjust(s8 value)
  63. {
  64. if (anc_cfg.ch == NULL) {
  65. return;
  66. }
  67. sys_cb.anc_adjust_val = value;
  68. anc_cfg.ch->param_buf[0] = bsp_anc_gain_adjust_do(value);
  69. anc_set_param(); //更新参数
  70. }
  71. bool bsp_anc_res_check_crc(u32 addr, u32 len)
  72. {
  73. u8 *ptr = (u8 *)addr;
  74. u8 offset = 0;
  75. if (ptr[0] == 'E' && ptr[1] == 'q' && ptr[2] == 0x01) {
  76. offset = 4;
  77. }
  78. u8 band_cnt = ptr[3+offset];
  79. if (band_cnt > 8) {
  80. return false;
  81. }
  82. u32 res_crc = ptr[band_cnt*27+11+offset] << 8 | ptr[band_cnt*27+10+offset];
  83. u32 cal_crc = calc_crc(ptr, band_cnt*27+10+offset, 0xffff);
  84. if (res_crc == cal_crc) {
  85. return true;
  86. } else {
  87. return false;
  88. }
  89. }
  90. void bsp_anc_set_nos_param(u8 band_cnt, const u32 *param)
  91. {
  92. anc_cfg.ch->nos_band = band_cnt;
  93. if (band_cnt == 0 || param == NULL) {
  94. return;
  95. }
  96. memcpy(anc_cfg.ch->param_buf, param, (band_cnt * 5 + 1) * 4);
  97. }
  98. void bsp_anc_set_msc_param(u8 band_cnt, const u32 *param)
  99. {
  100. anc_cfg.ch->msc_band = band_cnt;
  101. if (band_cnt == 0 || param == NULL) {
  102. return;
  103. }
  104. anc_cfg.ch->param_buf[41] = param[0];
  105. memcpy(&anc_cfg.ch->param_buf[anc_cfg.ch->nos_band * 5 + 1], param + 1, band_cnt * 5 * 4);
  106. }
  107. void bsp_anc_set_drc_param(u8 band_cnt, const u32 *param)
  108. {
  109. if (band_cnt == 0 || param == NULL) {
  110. return;
  111. }
  112. anc_cfg.ch->drc_en = 1;
  113. anc_cfg.ch->drc_band = band_cnt;
  114. memcpy(&anc_cfg.ch->drc_buf[0], param, 4* 4);
  115. anc_cfg.ch->drc_buf[4] = 0; //in_level
  116. anc_cfg.ch->drc_buf[5] = 0; //out_gain
  117. anc_cfg.ch->drc_buf[6] = param[4]; //tav
  118. anc_cfg.ch->drc_buf[7] = 0x00800000; //in_rms = 0
  119. memcpy(&anc_cfg.ch->drc_buf[8], &param[5], 3*4*band_cnt);
  120. }
  121. //EQ V2
  122. int bsp_anc_set_nos_param_by_res(u32 addr, u32 len)
  123. {
  124. if (len == 0) {
  125. return -1;
  126. }
  127. if (!bsp_anc_res_check_crc(addr, len)) {
  128. return -2;
  129. }
  130. u8 *ptr = (u8 *)addr;
  131. u8 band_cnt = ptr[7];
  132. u32 *param = (u32 *)&ptr[8];
  133. bsp_anc_set_nos_param(band_cnt, param);
  134. sys_cb.anc_mic_gain = anc_cfg.ch->param_buf[0]; //保存资源文件中的gain值
  135. if (xcfg_cb.anc_gain_en) {
  136. if (!anc_cb.tp_flag && sys_cb.anc_adjust_val != 0) { //写入量产测试的Gain
  137. anc_cfg.ch->param_buf[0] = bsp_anc_gain_adjust_do(sys_cb.anc_adjust_val);
  138. } else if (anc_cb.tp_flag && sys_cb.tp_adjust_val != 0) { //写入量产测试的Gain
  139. anc_cfg.ch->param_buf[0] = bsp_anc_gain_adjust_do(sys_cb.tp_adjust_val);
  140. }
  141. }
  142. return 0;
  143. }
  144. //EQ V2
  145. int bsp_anc_set_msc_param_by_res(u32 addr, u32 len)
  146. {
  147. if (len == 0) {
  148. return -1;
  149. }
  150. if (!bsp_anc_res_check_crc(addr, len)) {
  151. return -2;
  152. }
  153. u8 *ptr = (u8 *)addr;
  154. u8 band_cnt = ptr[7];
  155. u32 *param = (u32 *)&ptr[8];
  156. bsp_anc_set_msc_param(band_cnt, param);
  157. return 0;
  158. }
  159. //DRC V3
  160. int bsp_anc_set_drc_param_by_res(u32 addr, u32 len)
  161. {
  162. u8 drc_cnt;
  163. u32 res_crc, cal_crc;
  164. if (len == 0) {
  165. return -1;
  166. }
  167. u8 *ptr = (u8 *)addr;
  168. if (ptr[2] != 0x02 || ptr[7] > 4 || !ptr[7]) { //DRC V3
  169. return -2;
  170. }
  171. drc_cnt = ptr[7];
  172. res_crc = ptr[drc_cnt * 17 + 41] << 8 | ptr[drc_cnt * 17 + 40];
  173. cal_crc = calc_crc(ptr, drc_cnt * 17 + 40, 0xffff);
  174. if (res_crc != cal_crc) {
  175. return -3;
  176. }
  177. bsp_anc_set_drc_param(drc_cnt, (const u32 *)&ptr[8]);
  178. return 0;
  179. }
  180. void bsp_anc_set_mic_gain(u8 anl, u8 gain)
  181. {
  182. TRACE("anc set mic gain:%d %d\n", anl, gain);
  183. anc_set_mic_gain(anl, gain);
  184. }
  185. void bsp_anc_mic_mute(u8 mute)
  186. {
  187. TRACE("anc mic mute:%x\n", mute);
  188. set_mic_mute(mute);
  189. }
  190. void bsp_anc_start(void)
  191. {
  192. dac_fade_in();
  193. if (sys_cb.anc_start == 0) {
  194. sys_cb.anc_start = 1;
  195. sys_cb.sleep_aupll_en = 1;
  196. anc_start();
  197. }
  198. }
  199. void bsp_anc_stop(void)
  200. {
  201. if (sys_cb.anc_start) {
  202. anc_stop();
  203. sys_cb.anc_start = 0;
  204. sys_cb.sleep_aupll_en = 0;
  205. }
  206. }
  207. //无线/uart调anc参数接口
  208. void bsp_anc_dbg_eq_param(u8 packet, u8 band_cnt, u32 *eq_buf)
  209. {
  210. if (packet > 2) {
  211. anc_set_tansparency_mode(1);
  212. packet -= 2;
  213. } else {
  214. anc_set_tansparency_mode(0);
  215. }
  216. if (packet == 1) {
  217. bsp_anc_set_nos_param(band_cnt, eq_buf);
  218. }
  219. anc_set_param(); //更新参数
  220. }
  221. void bsp_anc_set_param(u8 tp)
  222. {
  223. const anc_param *anc_tbl;
  224. anc_tbl = &anc_ff_eq_tbl[4 * tp];
  225. #if BT_TWS_EN
  226. if (xcfg_cb.bt_tws_en) {
  227. if (!(sys_cb.tws_force_channel - 1)) { //TWS下FF/FB模式右声道取R的曲线给MICL
  228. anc_tbl = &anc_ff_eq_tbl[4 * tp + 2];
  229. }
  230. }
  231. #endif
  232. anc_set_tansparency_mode(tp);
  233. bsp_anc_set_nos_param_by_res(*anc_tbl[0].addr, *anc_tbl[0].len);
  234. bsp_anc_set_drc_param_by_res(*anc_tbl[1].addr, *anc_tbl[1].len);
  235. anc_set_param(); //更新参数
  236. }
  237. void bsp_anc_parse_cmd_process(u8 *rx_buf)
  238. {
  239. // printf("anc rx:");
  240. // print_r(rx_buf, 16);
  241. u8 *ptr = rx_buf;
  242. u8 channel = ptr[5];
  243. u8 bit_ctl = ptr[6];
  244. s8 adjust0 = (s8)ptr[8];
  245. bool eq_tool = (bool)(bit_ctl & BIT(4));//判断是EQ工具还是量产工具
  246. bool tp_flag = (bool)(bit_ctl & BIT(5));//判断是anc模式测试,还是通透模式测试
  247. if(!tp_flag){
  248. if (!sys_cb.anc_start|| sys_cb.anc_user_mode != 1) {
  249. bsp_anc_set_mode(1);
  250. }
  251. }else{
  252. if (!sys_cb.anc_start|| sys_cb.anc_user_mode != 2) {
  253. bsp_anc_set_mode(2);
  254. }
  255. }
  256. eq_dbg_cb.eq_spp_cb.rx_size = 16;
  257. do {
  258. u8 ch = channel - 1;
  259. #if BT_TWS_EN
  260. if (xcfg_cb.bt_tws_en) {
  261. if (ch == 2 || (ch == func_bt_tws_get_channel())) { //声道不相等,转发
  262. if(bt_tws_is_connected()) {
  263. if (ch == 2) { //把这个声道去掉,重新算下CRC
  264. ptr[5] = (func_bt_tws_get_channel() == 1) ? 2 : 1;
  265. u16 crc = calc_crc(ptr, 14, 0xffff);
  266. ptr[14] = crc;
  267. ptr[15] = crc >> 8;
  268. }
  269. bt_tws_sync(TWS_SYNC_INFO_EQ);
  270. }
  271. if (ch != 2) { //如果收到单声道的命令,转发后跳出
  272. break;
  273. }
  274. }
  275. }
  276. #endif
  277. bool ch_mute = !((bit_ctl & BIT(0)) && (bit_ctl & BIT(2)) == 0);
  278. s8 old_ajust_val = sys_cb.anc_adjust_val;
  279. bsp_anc_mic_mute(ch_mute);
  280. if (!eq_tool) {
  281. bsp_anc_gain_adjust(adjust0);
  282. }
  283. if (bit_ctl & BIT(1)) {
  284. if (!tp_flag) {
  285. param_write((u8*)&sys_cb.anc_adjust_val, PARAM_ANC_MIC_VAL, 1);
  286. } else {
  287. sys_cb.tp_adjust_val = sys_cb.anc_adjust_val;
  288. sys_cb.anc_adjust_val = old_ajust_val;
  289. param_write((u8*)&sys_cb.tp_adjust_val, PARAM_ANC_TP_MIC_VAL, 1);
  290. }
  291. }
  292. //调整again,研发调试用
  293. if (bit_ctl & BIT(4)) {
  294. bsp_anc_set_mic_gain(1, ptr[10]);
  295. }
  296. if (bit_ctl & BIT(1)) {
  297. param_sync();
  298. }
  299. TRACE("## anc dbg mute:%d eq_tool:%d anl_vol:%d save:%d\n", ch_mute, eq_tool, ptr[10], (bool)(bit_ctl & BIT(1)));
  300. } while (0);
  301. }
  302. //mode: 0[off], 1[anc], 2[tansparency]
  303. void bsp_anc_set_mode(u8 mode)
  304. {
  305. if (!xcfg_cb.anc_en) {
  306. return;
  307. }
  308. sys_cb.anc_user_mode = mode;
  309. if (mode == 0) {
  310. bsp_anc_stop();
  311. } else {
  312. bsp_anc_set_param(mode - 1);
  313. bsp_anc_start();
  314. }
  315. TRACE("anc user mode:%d\n", mode);
  316. }
  317. void bsp_anc_init(void)
  318. {
  319. if (!xcfg_cb.anc_en) {
  320. TRACE("'xcfg_cb.anc_en' define 0\n");
  321. return;
  322. }
  323. memset(&anc_cfg, 0, sizeof(anc_cfg));
  324. memset(&anc_ch, 0, sizeof(anc_ch));
  325. anc_cfg.ch = &anc_ch;
  326. anc_cfg.spr = SPR_384000;
  327. anc_cfg.ch->drc_en = 0;
  328. anc_cfg.ch->gain = ((u16)BT_ANL_GAIN << 6) | 0;
  329. anc_cfg.ch->bypass = 0;
  330. param_read((u8*)&sys_cb.anc_adjust_val, PARAM_ANC_MIC_VAL, 1);
  331. param_read((u8*)&sys_cb.tp_adjust_val, PARAM_ANC_TP_MIC_VAL, 1);
  332. anc_init(&anc_cfg);
  333. bsp_anc_set_param(0);
  334. TRACE("anc init\n");
  335. TRACE("anc mic type:%d\n", anc_cfg.mic_type);
  336. TRACE("anc mic gain:%x\n", anc_cfg.ch->gain);
  337. TRACE("anc adjust mic gain: %d, %d\n", sys_cb.anc_adjust_val, sys_cb.tp_adjust_val);
  338. }
  339. void bsp_anc_exit(void)
  340. {
  341. anc_exit();
  342. sys_cb.anc_start = 0;
  343. }
  344. #endif //ANC_EN