• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************/
18 #include "audio.h"
19 #include "clock.h"
20 #include "pwm.h"
21 #include "stimer.h"
22 
23 unsigned char audio_rx_dma_chn;
24 unsigned char audio_tx_dma_chn;
25 
26 dma_chain_config_t g_audio_tx_dma_list_cfg;
27 dma_chain_config_t g_audio_rx_dma_list_cfg;
28 
29 aduio_i2s_codec_config_t audio_i2s_codec_config = {
30     .audio_in_mode = BIT_16_MONO,
31     .audio_out_mode = BIT_16_MONO_FIFO0,
32     .i2s_data_select = I2S_BIT_16_DATA,
33     .codec_data_select = CODEC_BIT_16_DATA,
34     .i2s_codec_m_s_mode = I2S_M_CODEC_S,
35     .i2s_data_invert_select = I2S_DATA_INVERT_DIS,  // L channel default
36     .in_digital_gain = CODEC_IN_D_GAIN_0_DB,
37     .in_analog_gain = CODEC_IN_A_GAIN_8_DB,
38     .out_digital_gain = CODEC_OUT_D_GAIN_0_DB,
39     .out_analog_gain = CODEC_OUT_A_GAIN_6_DB,
40     .mic_input_mode_select = 1,  // 0 single-ended input, 1 differential input
41 };
42 
43 dma_config_t audio_dma_rx_config = {
44     .dst_req_sel = 0,
45     .src_req_sel = DMA_REQ_AUDIO0_RX,  // rx req
46     .dst_addr_ctrl = DMA_ADDR_INCREMENT,
47     .src_addr_ctrl = DMA_ADDR_FIX,
48     .dstmode = DMA_NORMAL_MODE,
49     .srcmode = DMA_HANDSHAKE_MODE,
50     .dstwidth = DMA_CTR_WORD_WIDTH,  // must word
51     .srcwidth = DMA_CTR_WORD_WIDTH,  // must word
52     .src_burst_size = 0,             // must 0
53     .read_num_en = 0,
54     .priority = 0,
55     .write_num_en = 0,
56     .auto_en = 0,  // must 0
57 };
58 
59 dma_config_t audio_dma_tx_config = {
60     .dst_req_sel = DMA_REQ_AUDIO0_TX,  // tx req
61     .src_req_sel = 0,
62     .dst_addr_ctrl = DMA_ADDR_FIX,
63     .src_addr_ctrl = DMA_ADDR_INCREMENT,  // increment
64     .dstmode = DMA_HANDSHAKE_MODE,        // handshake
65     .srcmode = DMA_NORMAL_MODE,
66     .dstwidth = DMA_CTR_WORD_WIDTH,  // must word
67     .srcwidth = DMA_CTR_WORD_WIDTH,  // must word
68     .src_burst_size = 0,             // must 0
69     .read_num_en = 0,
70     .priority = 0,
71     .write_num_en = 0,
72     .auto_en = 0,  // must 0
73 };
74 
75 /**
76  * @brief      This function serves to invert data between R channel and L channel.
77  * @param[in]  en - I2S_DATA_INVERT_DIS: L channel (default); I2S_DATA_INVERT_EN: R channel.
78  * @return     none
79  */
audio_set_mono_chn(audio_data_invert_e en)80 void audio_set_mono_chn(audio_data_invert_e en)
81 {
82     audio_i2s_codec_config.i2s_data_invert_select = en;
83 }
84 
85 /**
86  * @brief      This function serves to set mic input mode.
87  * @param[in]  input_mode - 0 single-ended input, 1 differential input.
88  * @return     none
89  */
audio_set_codec_mic_input_mode(unsigned char input_mode)90 void audio_set_codec_mic_input_mode(unsigned char input_mode)
91 {
92     audio_i2s_codec_config.mic_input_mode_select = input_mode;
93 }
94 
95 /**
96  * 	@brief      This function serves to set in path digital and analog gain  .
97  * 	@param[in]  d_gain - digital gain value
98  * 	@param[in]  a_gain - analog  gain value
99  * 	@return     none
100  */
audio_set_codec_in_path_a_d_gain(codec_in_path_digital_gain_e d_gain,codec_in_path_analog_gain_e a_gain)101 void audio_set_codec_in_path_a_d_gain(codec_in_path_digital_gain_e d_gain, codec_in_path_analog_gain_e a_gain)
102 {
103     audio_i2s_codec_config.in_digital_gain = d_gain;
104     audio_i2s_codec_config.in_analog_gain = a_gain;
105 }
106 
107 /**
108  * 	@brief      This function serves to set out path digital and analog gain  .
109  * 	@param[in]  d_gain - digital gain value
110  * 	@param[in]  a_gain - analog  gain value
111  * 	@return     none
112  */
audio_set_codec_out_path_a_d_gain(codec_out_path_digital_gain_e d_gain,codec_out_path_analog_gain_e a_gain)113 void audio_set_codec_out_path_a_d_gain(codec_out_path_digital_gain_e d_gain, codec_out_path_analog_gain_e a_gain)
114 {
115     audio_i2s_codec_config.out_digital_gain = d_gain;
116     audio_i2s_codec_config.out_analog_gain = a_gain;
117 }
118 
119 /**
120   * @brief      This function serves to choose which is master to provide clock.
121   * @param[in]  m_s - I2S_S_CODEC_M: i2s as slave ,codec as master; I2S_M_CODEC_S: i2s as  master, codec  as slave.
122   * @return     none
123   */
audio_set_i2s_codec_m_s(i2s_codec_m_s_mode_e m_s)124 void audio_set_i2s_codec_m_s(i2s_codec_m_s_mode_e m_s)
125 {
126     audio_i2s_codec_config.i2s_codec_m_s_mode = m_s;
127 }
128 
129 /**
130  * 	@brief      This function serves to choose which is master to provide clock.
131  * 	@param[in]  chn_wl: select word  length and audio channel number
132  * 	@return     none
133  */
aduio_set_chn_wl(audio_channel_wl_mode_e chn_wl)134 void aduio_set_chn_wl(audio_channel_wl_mode_e chn_wl)
135 {
136     switch (chn_wl) {
137         case MONO_BIT_16:
138             audio_i2s_codec_config.audio_in_mode = BIT_16_MONO;
139             audio_i2s_codec_config.audio_out_mode = BIT_16_MONO_FIFO0;
140             audio_i2s_codec_config.i2s_data_select = I2S_BIT_16_DATA;
141             audio_i2s_codec_config.codec_data_select = CODEC_BIT_16_DATA;
142             break;
143 
144         case MONO_BIT_20:
145             audio_i2s_codec_config.audio_in_mode = BIT_20_OR_24_MONO;
146             audio_i2s_codec_config.audio_out_mode = BIT_20_OR_24_MONO_FIFO0;
147             audio_i2s_codec_config.i2s_data_select = I2S_BIT_20_DATA;
148             audio_i2s_codec_config.codec_data_select = CODEC_BIT_20_DATA;
149             break;
150 
151         case MONO_BIT_24:
152             audio_i2s_codec_config.audio_in_mode = BIT_20_OR_24_MONO;
153             audio_i2s_codec_config.audio_out_mode = BIT_20_OR_24_MONO_FIFO0;
154             audio_i2s_codec_config.i2s_data_select = I2S_BIT_24_DATA;
155             audio_i2s_codec_config.codec_data_select = CODEC_BIT_24_DATA;
156             break;
157 
158         case STEREO_BIT_16:
159             audio_i2s_codec_config.audio_in_mode = BIT_16_STEREO;
160             audio_i2s_codec_config.audio_out_mode = BIT_16_STEREO_FIFO0;
161             audio_i2s_codec_config.i2s_data_select = I2S_BIT_16_DATA;
162             audio_i2s_codec_config.codec_data_select = CODEC_BIT_16_DATA;
163             break;
164 
165         case STEREO_BIT_20:
166             audio_i2s_codec_config.audio_in_mode = BIT_20_OR_24_STEREO;
167             audio_i2s_codec_config.audio_out_mode = BIT_20_OR_24_STEREO_FIFO0;
168             audio_i2s_codec_config.i2s_data_select = I2S_BIT_20_DATA;
169             audio_i2s_codec_config.codec_data_select = CODEC_BIT_20_DATA;
170             break;
171 
172         case STEREO_BIT_24:
173             audio_i2s_codec_config.audio_in_mode = BIT_20_OR_24_STEREO;
174             audio_i2s_codec_config.audio_out_mode = BIT_20_OR_24_STEREO_FIFO0;
175             audio_i2s_codec_config.i2s_data_select = I2S_BIT_24_DATA;
176             audio_i2s_codec_config.codec_data_select = CODEC_BIT_24_DATA;
177             break;
178     }
179 }
180 
181 /**
182  * @brief     This function selects  pin  for i2s.
183  * @param[in]  pin - the selected pin.
184  * @return    none
185  */
audio_i2s_set_pin_mux(i2s_pin_e pin)186 void audio_i2s_set_pin_mux(i2s_pin_e pin)
187 {
188     unsigned char val = 0;
189     unsigned char start_bit = (BIT_LOW_BIT(pin & 0xff) % 4) << 1;
190     unsigned char mask = (unsigned char)~BIT_RNG(start_bit, start_bit + 1);
191     if (pin == I2S_BCK_PC3) {
192         val = 0;  // function 0
193     } else if ((pin == I2S_ADC_LR_PC4) || (pin == I2S_ADC_DAT_PC5) || (pin == I2S_DAC_LR_PC6) ||
194                (pin == I2S_DAC_DAT_PC7)) {
195         val = 1 << (start_bit);  // function 1
196     }
197     reg_gpio_func_mux(pin) = (reg_gpio_func_mux(pin) & mask) | val;
198     gpio_function_dis(pin);
199 }
200 
201 /**
202  * @brief     This function configures i2s pin.
203  * @param[in] none
204  * @return    none
205  */
audio_i2s_set_pin(void)206 void audio_i2s_set_pin(void)
207 {
208     audio_i2s_set_pin_mux(I2S_BCK_PC3);
209     audio_i2s_set_pin_mux(I2S_ADC_LR_PC4);
210     audio_i2s_set_pin_mux(I2S_ADC_DAT_PC5);
211     audio_i2s_set_pin_mux(I2S_DAC_LR_PC6);
212     audio_i2s_set_pin_mux(I2S_DAC_DAT_PC7);
213 }
214 
215 /**
216  * 	@brief      This function serves to set codec supply voltage
217  * 	@param[in]  volt - the voltage of codec supply.A1 2.8V default,A0 1.8V default.
218  * 	@return     none
219  *
220  */
audio_set_codec_supply(codec_volt_supply_e volt)221 void audio_set_codec_supply(codec_volt_supply_e volt)
222 {
223     if (g_chip_version == 0xff) {  // A0 1.8v default ( BIT(7) - 1: 2.8v 0: 1.8v )
224         if (volt == CODEC_2P8V) {
225             analog_write_reg8(0x02, analog_read_reg8(0x02) | BIT(7));
226         } else if (volt == CODEC_1P8V) {
227             analog_write_reg8(0x02, analog_read_reg8(0x02) & (~BIT(7)));
228         }
229     } else {  // A1 2.8v default ( BIT(7) - 1: 1.8v 0: 2.8v )
230         if (volt == CODEC_1P8V) {
231             analog_write_reg8(0x02, analog_read_reg8(0x02) | BIT(7));
232         } else if (volt == CODEC_2P8V) {
233             analog_write_reg8(0x02, analog_read_reg8(0x02) & (~BIT(7)));
234         }
235     }
236 }
237 
238 /**
239  * @brief     This function configures dmic pin.
240  * @param[in] pin_gp - the group of dmic pin
241  * @return    none
242  */
audio_set_dmic_pin(dmic_pin_group_e pin_gp)243 void audio_set_dmic_pin(dmic_pin_group_e pin_gp)
244 {
245     if (pin_gp == DMIC_GROUPB_B2_DAT_B3_B4_CLK) {
246         reg_gpio_pad_mul_sel = BIT(2);
247         reg_gpio_pb_fuc_h = reg_gpio_pb_fuc_h & (~BIT_RNG(0, 1));
248         reg_gpio_pb_fuc_l = (reg_gpio_pb_fuc_h & (~BIT_RNG(4, 7))) | 0x0f;
249         gpio_function_dis(GPIO_PB2 | GPIO_PB3 | GPIO_PB4);
250     } else if (pin_gp == DMIC_GROUPC_C1_DAT_C2_C3_CLK) {
251         reg_gpio_pad_mul_sel = BIT(0);
252         reg_gpio_pc_fuc_l = (reg_gpio_pc_fuc_l & (~BIT_RNG(2, 7))) | ((2 << 2) | (2 << 4) | (2 << 6));
253         gpio_function_dis(GPIO_PC1 | GPIO_PC2 | GPIO_PC3);
254     } else if (pin_gp == DMIC_GROUPD_D4_DAT_D5_D6_CLK) {  // can not use in A0
255         reg_gpio_pd_fuc_h = (reg_gpio_pd_fuc_h & (~BIT_RNG(0, 5))) | ((1 << 0) | (1 << 2) | (1 << 4));
256         gpio_function_dis(GPIO_PD4 | GPIO_PD5 | GPIO_PD6);
257     } else if (pin_gp == DMIC_B2_DAT_B3_CLK) {
258         reg_gpio_pad_mul_sel = BIT(2);
259         reg_gpio_pb_fuc_l = (reg_gpio_pb_fuc_h & (~BIT_RNG(4, 7))) | 0x0f;
260         gpio_function_dis(GPIO_PB2 | GPIO_PB3);
261     } else if (pin_gp == DMIC_C1_DAT_C2_CLK) {
262         reg_gpio_pad_mul_sel = BIT(0);
263         reg_gpio_pc_fuc_l = (reg_gpio_pc_fuc_l & (~BIT_RNG(2, 5))) | ((2 << 2) | (2 << 4));
264         gpio_function_dis(GPIO_PC1 | GPIO_PC2);
265     } else if (pin_gp == DMIC_D4_DAT_D5_CLK) {  // can not use in A0
266         reg_gpio_pd_fuc_h = (reg_gpio_pd_fuc_h & (~BIT_RNG(0, 3))) | ((1 << 0) | (1 << 2));
267         gpio_function_dis(GPIO_PD4 | GPIO_PD5);
268     }
269 }
270 
271 /**
272  * @brief     This function serves to enable rx_dma channel.
273  * @return    none
274  */
audio_rx_dma_en(void)275 void audio_rx_dma_en(void)
276 {
277     dma_chn_en(audio_rx_dma_chn);
278 }
279 
280 /**
281   * @brief     This function serves to disable rx_dma channel.
282   * @return    none
283   */
audio_rx_dma_dis(void)284 void audio_rx_dma_dis(void)
285 {
286     dma_chn_dis(audio_rx_dma_chn);
287 }
288 
289 /**
290   * @brief     This function serves to enable tx_dma channel.
291   * @return    none
292   */
audio_tx_dma_en(void)293 void audio_tx_dma_en(void)
294 {
295     dma_chn_en(audio_tx_dma_chn);
296 }
297 
298 /**
299   * @brief     This function serves to disable dis_dma channel.
300   * @return    none
301   */
audio_tx_dma_dis(void)302 void audio_tx_dma_dis(void)
303 {
304     dma_chn_dis(audio_tx_dma_chn);
305 }
306 
307 /**
308   * @brief     This function serves to config  rx_dma channel.
309   * @param[in] chn          - dma channel
310   * @param[in] dst_addr     - the dma address of destination
311   * @param[in] data_len     - the length of dma rx size by byte
312   * @param[in] head_of_list - the head address of dma llp.
313   * @return    none
314   */
audio_rx_dma_config(dma_chn_e chn,unsigned short * dst_addr,unsigned int data_len,dma_chain_config_t * head_of_list)315 void audio_rx_dma_config(dma_chn_e chn, unsigned short *dst_addr, unsigned int data_len,
316                          dma_chain_config_t *head_of_list)
317 {
318     audio_rx_dma_chn = chn;
319     audio_set_rx_buff_len(data_len);
320     dma_config(audio_rx_dma_chn, &audio_dma_rx_config);
321     dma_set_address(chn, REG_AUDIO_AHB_BASE, (unsigned int)convert_ram_addr_cpu2bus(dst_addr));
322     dma_set_size(chn, data_len, DMA_WORD_WIDTH);
323     reg_dma_llp(chn) = (unsigned int)convert_ram_addr_cpu2bus(head_of_list);
324 }
325 
326 /**
327  * @brief     This function serves to set rx dma chain transfer
328  * @param[in] rx_config - the head of list of llp_pointer.
329  * @param[in] llpointer - the next element of llp_pointer.
330  * @param[in] dst_addr  -the dma address of destination.
331  * @param[in] data_len  -the length of dma size by byte.
332  * @return    none
333  */
audio_rx_dma_add_list_element(dma_chain_config_t * config_addr,dma_chain_config_t * llpointer,unsigned short * dst_addr,unsigned int data_len)334 void audio_rx_dma_add_list_element(dma_chain_config_t *config_addr, dma_chain_config_t *llpointer,
335                                    unsigned short *dst_addr, unsigned int data_len)
336 {
337     config_addr->dma_chain_ctl = reg_dma_ctrl(audio_rx_dma_chn) | BIT(0);
338     config_addr->dma_chain_src_addr = REG_AUDIO_AHB_BASE;
339     config_addr->dma_chain_dst_addr = (unsigned int)convert_ram_addr_cpu2bus(dst_addr);
340     config_addr->dma_chain_data_len = dma_cal_size(data_len, 4);
341     config_addr->dma_chain_llp_ptr = (unsigned int)convert_ram_addr_cpu2bus(llpointer);
342 }
343 
344 /**
345  * @brief     This function serves to config  tx_dma channel.
346  * @param[in] chn          - dma channel
347  * @param[in] src_addr     - the address of source
348  * @param[in] data_len     - the length of dma rx size by byte
349  * @param[in] head_of_list - the head address of dma llp.
350  * @return    none
351  */
audio_tx_dma_config(dma_chn_e chn,unsigned short * src_addr,unsigned int data_len,dma_chain_config_t * head_of_list)352 void audio_tx_dma_config(dma_chn_e chn, unsigned short *src_addr, unsigned int data_len,
353                          dma_chain_config_t *head_of_list)
354 {
355     audio_tx_dma_chn = chn;
356     audio_set_tx_buff_len(data_len);
357     dma_config(audio_tx_dma_chn, &audio_dma_tx_config);
358     dma_set_address(chn, (unsigned int)convert_ram_addr_cpu2bus(src_addr), REG_AUDIO_AHB_BASE);
359     dma_set_size(chn, data_len, DMA_WORD_WIDTH);
360     reg_dma_llp(chn) = (unsigned int)convert_ram_addr_cpu2bus(head_of_list);
361 }
362 
363 /**
364  * @brief     This function serves to set tx dma chain transfer
365  * @param[in] config_addr - the head of list of llp_pointer.
366  * @param[in] llpointer   - the next element of llp_pointer.
367  * @param[in] src_addr    - the address of source
368  * @param[in] data_len    - the length of dma size by byte.
369  * @return    none
370  */
audio_tx_dma_add_list_element(dma_chain_config_t * config_addr,dma_chain_config_t * llpointer,unsigned short * src_addr,unsigned int data_len)371 void audio_tx_dma_add_list_element(dma_chain_config_t *config_addr, dma_chain_config_t *llpointer,
372                                    unsigned short *src_addr, unsigned int data_len)
373 {
374     config_addr->dma_chain_ctl = reg_dma_ctrl(audio_tx_dma_chn) | BIT(0);
375     config_addr->dma_chain_src_addr = (unsigned int)convert_ram_addr_cpu2bus(src_addr);
376     config_addr->dma_chain_dst_addr = REG_AUDIO_AHB_BASE;
377     config_addr->dma_chain_data_len = dma_cal_size(data_len, 4);
378     config_addr->dma_chain_llp_ptr = (unsigned int)convert_ram_addr_cpu2bus(llpointer);
379 }
380 
381 /**
382  * @brief     This function serves to  initialize audio by mc
383  * @param[in] flow_mode  - select input out flow mode
384  * @param[in] rate       - audio sampling rate.
385  * @param[in] channel_wl - word length and channel number.
386  * @return    none
387  */
audio_init(audio_flow_mode_e flow_mode,audio_sample_rate_e rate,audio_channel_wl_mode_e channel_wl)388 void audio_init(audio_flow_mode_e flow_mode, audio_sample_rate_e rate, audio_channel_wl_mode_e channel_wl)
389 {
390     aduio_set_chn_wl(channel_wl);
391     audio_set_codec_clk(1, 16);  // from ppl 192/16=12M
392     audio_mux_config(CODEC_I2S, audio_i2s_codec_config.audio_in_mode, audio_i2s_codec_config.audio_in_mode,
393                      audio_i2s_codec_config.audio_out_mode);
394     audio_i2s_config(I2S_I2S_MODE, audio_i2s_codec_config.i2s_data_select, audio_i2s_codec_config.i2s_codec_m_s_mode,
395                      audio_i2s_codec_config.i2s_data_invert_select);
396     audio_set_i2s_clock(rate, AUDIO_RATE_EQUAL, 0);
397     audio_clk_en(1, 1);
398     reg_audio_codec_vic_ctr = FLD_AUDIO_CODEC_SLEEP_ANALOG;  // active analog sleep mode
399     while (!(reg_audio_codec_stat_ctr & FLD_AUDIO_CODEC_PON_ACK)) {
400     }
401     // wait codec can be configed
402     if (flow_mode < BUF_TO_LINE_OUT) {
403         audio_codec_adc_config(audio_i2s_codec_config.i2s_codec_m_s_mode, (flow_mode % 3), rate,
404                                audio_i2s_codec_config.codec_data_select, MCU_WREG);
405     }
406 
407     if (flow_mode > LINE_IN_TO_BUF) {
408         audio_codec_dac_config(audio_i2s_codec_config.i2s_codec_m_s_mode, rate,
409                                audio_i2s_codec_config.codec_data_select, MCU_WREG);
410     }
411     while (!(reg_audio_codec_stat_ctr ==
412              (FLD_AUDIO_CODEC_ADC12_LOCKED | FLD_AUDIO_CODEC_DAC_LOCKED | FLD_AUDIO_CODEC_PON_ACK))) {
413     }  // wait codec adc/dac locked
414 
415     audio_data_fifo0_path_sel(I2S_DATA_IN_FIFO, I2S_OUT);
416 }
417 
418 /**
419  * @brief     This function serves to read data from codec register.
420  * @param[in] addr: the address of codec register
421  * @return    none
422  */
audio_i2c_codec_read(unsigned char addr)423 unsigned char audio_i2c_codec_read(unsigned char addr)
424 {
425     reg_i2c_data_buf(0) = addr << 1;
426     reg_i2c_len = 0x01;  // rx_len
427     reg_i2c_sct1 = FLD_I2C_LS_ID | FLD_I2C_LS_ADDR | FLD_I2C_LS_START;
428 
429     while (i2c_master_busy()) {
430     }
431     // wait busy=0
432     while (reg_i2c_mst & FLD_I2C_ACK_IN) {
433     }
434     // wait ack=0
435 
436     reg_i2c_sct1 = FLD_I2C_LS_ID | FLD_I2C_LS_DATAR | FLD_I2C_LS_START | FLD_I2C_LS_ID_R | FLD_I2C_LS_ACK;
437     while (i2c_master_busy()) {
438     }
439     // wait busy=0
440     unsigned char rdat8 = reg_i2c_data_buf(0);
441     reg_i2c_sct1 = FLD_I2C_LS_STOP | FLD_I2C_LS_ID_R;
442     while (i2c_master_busy()) {
443     }
444     // wait busy=0
445     return rdat8;
446 }
447 
448 /**
449  * @brief     This function serves to write data to  codec register.
450  * @param[in] addr: the address of codec register
451  * @return    none
452  */
audio_i2c_codec_write(unsigned char addr,unsigned char wdat)453 void audio_i2c_codec_write(unsigned char addr, unsigned char wdat)
454 {
455     reg_i2c_data_buf(0) = addr << 1;
456     reg_i2c_data_buf(1) = wdat;
457     reg_i2c_len = 2;  // tx_len
458     reg_i2c_sct1 = FLD_I2C_LS_ID | FLD_I2C_LS_DATAW | FLD_I2C_LS_START | FLD_I2C_LS_STOP;
459     while (i2c_master_busy()) {
460     }
461     // wait busy=0
462     while (reg_i2c_mst & FLD_I2C_ACK_IN) {
463     }
464     // wait ack=0
465 }
466 
467 /**
468  * @brief      This function serves to enable i2c master for codec i2c slave .
469  * @param[in]  none.
470  * @return     none.
471  */
audio_i2c_init(codec_type_e codec_type,i2c_sda_pin_e sda_pin,i2c_scl_pin_e scl_pin)472 void audio_i2c_init(codec_type_e codec_type, i2c_sda_pin_e sda_pin, i2c_scl_pin_e scl_pin)
473 {
474     i2c_master_init();
475     i2c_set_master_clk((unsigned char)(sys_clk.pclk * 1000 * 1000 / (4 * 20000)));  // set i2c frequency 400K.
476     if (codec_type == INNER_CODEC) {
477         reg_audio_i2c_mode = 0x05;  // codec config by i2c
478         reg_i2c_id = (0x34 << 1);   // set i2c id
479         reg_audio_i2c_addr = 0x34;
480     } else if (codec_type == EXT_CODEC) {
481         reg_i2c_id = 0x34;
482         i2c_set_pin(sda_pin, scl_pin);
483     }
484 }
485 
486 /**
487  * @brief     This function serves to  initialize audio by i2c
488  * @param[in] flow_mode  - select input out flow mode
489  * @param[in] rate       - audio sampling rate.
490  * @param[in] channel_wl - word length and channel number.
491  * @return    none
492  */
audio_init_i2c(audio_flow_mode_e flow_mode,audio_sample_rate_e rate,audio_channel_wl_mode_e channel_wl)493 void audio_init_i2c(audio_flow_mode_e flow_mode, audio_sample_rate_e rate, audio_channel_wl_mode_e channel_wl)
494 {
495     aduio_set_chn_wl(channel_wl);
496     audio_set_codec_clk(1, 16);  // from ppl 192/16=12M
497     audio_mux_config(CODEC_I2S, audio_i2s_codec_config.audio_in_mode, audio_i2s_codec_config.audio_in_mode,
498                      audio_i2s_codec_config.audio_out_mode);
499     audio_i2s_config(I2S_I2S_MODE, audio_i2s_codec_config.i2s_data_select, audio_i2s_codec_config.i2s_codec_m_s_mode,
500                      audio_i2s_codec_config.i2s_data_invert_select);
501     audio_set_i2s_clock(rate, AUDIO_RATE_EQUAL, 0);
502     audio_clk_en(1, 1);
503     audio_i2c_init(INNER_CODEC, 0, 0);
504     audio_i2c_codec_write(addr_audio_codec_vic_ctr, FLD_AUDIO_CODEC_SLEEP_ANALOG);  // active analog sleep mode
505     while (!(audio_i2c_codec_read(addr_audio_codec_stat_ctr) & FLD_AUDIO_CODEC_PON_ACK)) {
506     }
507     // wait codec can be configed
508     if (flow_mode < BUF_TO_LINE_OUT) {
509         audio_codec_adc_config(audio_i2s_codec_config.i2s_codec_m_s_mode, (flow_mode % 3), rate,
510                                audio_i2s_codec_config.codec_data_select, I2C_WREG);
511     }
512     if (flow_mode > LINE_IN_TO_BUF) {
513         audio_codec_dac_config(audio_i2s_codec_config.i2s_codec_m_s_mode, rate,
514                                audio_i2s_codec_config.codec_data_select, I2C_WREG);
515     }
516     while (!(audio_i2c_codec_read(addr_audio_codec_stat_ctr) ==
517              (FLD_AUDIO_CODEC_ADC12_LOCKED | FLD_AUDIO_CODEC_DAC_LOCKED | FLD_AUDIO_CODEC_PON_ACK))) {
518     }  // wait codec adc/dac locked
519     audio_data_fifo0_path_sel(I2S_DATA_IN_FIFO, I2S_OUT);
520 }
521 
522 /**
523  * @brief     This function serves to config codec for dac.
524  * @param[in] mode        - select i2s as master or slave
525  * @param[in] rate		  - audio sampling rate
526  * @param[in] data_select - codec dac word length
527  * @param[in] wreg_mode   - mcu or i2c config codec
528  * @return    none
529  */
audio_codec_dac_config(i2s_codec_m_s_mode_e mode,audio_sample_rate_e rate,codec_data_select_e data_select,codec_wreg_mode_e wreg_mode)530 void audio_codec_dac_config(i2s_codec_m_s_mode_e mode, audio_sample_rate_e rate, codec_data_select_e data_select,
531                             codec_wreg_mode_e wreg_mode)
532 {
533     if (wreg_mode == MCU_WREG) {
534         BM_SET(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_SOFT_MUTE);  // dac mute
535         if ((audio_i2s_codec_config.audio_out_mode == BIT_16_MONO_FIFO0) ||
536             ((audio_i2s_codec_config.audio_out_mode == BIT_20_OR_24_MONO_FIFO0))) {
537             BM_CLR(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_SB);         // active DAC power
538             BM_SET(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_LEFT_ONLY);  // active left channel only
539         } else {
540             BM_CLR(reg_audio_codec_dac_ctr,
541                    FLD_AUDIO_CODEC_DAC_SB |
542                        FLD_AUDIO_CODEC_DAC_LEFT_ONLY);  // active DAC power,active left and right channel
543         }
544 
545         BM_CLR(reg_audio_codec_vic_ctr,
546                FLD_AUDIO_CODEC_SB | FLD_AUDIO_CODEC_SB_ANALOG |
547                    FLD_AUDIO_CODEC_SLEEP_ANALOG);  // disable sleep mode ,disable sb_analog,disable global standby
548 
549         /* data word length ,interface master/slave selection,
550         * audio interface protocol selection ,active dac audio interface
551         */
552         reg_audio_codec_dac_itf_ctr =
553             MASK_VAL(FLD_AUDIO_CODEC_FORMAT, CODEC_I2S_MODE, FLD_AUDIO_CODEC_DAC_ITF_SB, CODEC_ITF_AC,
554                      FLD_AUDIO_CODEC_SLAVE, mode, FLD_AUDIO_CODEC_WL, data_select);
555 
556         /* disable DAC digital gain coupling, Left channel DAC digital gain */
557         reg_audio_codec_dacl_gain =
558             MASK_VAL(FLD_AUDIO_CODEC_DAC_LRGOD, 0, FLD_AUDIO_CODEC_DAC_GODL, audio_i2s_codec_config.out_digital_gain);
559 
560         reg_audio_codec_dacr_gain = MASK_VAL(
561             FLD_AUDIO_CODEC_DAC_GODR, audio_i2s_codec_config.out_digital_gain); /* Right channel DAC digital gain */
562 
563         /* disable Headphone gain coupling, set Left channel HP amplifier gain */
564         reg_audio_codec_hpl_gain =
565             MASK_VAL(FLD_AUDIO_CODEC_HPL_LRGO, 0, FLD_AUDIO_CODEC_HPL_GOL, audio_i2s_codec_config.out_analog_gain);
566 
567         reg_audio_codec_hpr_gain =
568             MASK_VAL(FLD_AUDIO_CODEC_HPR_GOR,
569                      audio_i2s_codec_config.out_analog_gain); /* Right channel HP amplifier gain programming */
570 
571         reg_audio_codec_dac_freq_ctr = (FLD_AUDIO_CODEC_DAC_FREQ & (rate == AUDIO_ADC_16K_DAC_48K ? AUDIO_48K : rate));
572 
573         BM_CLR(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_SOFT_MUTE); /* dac mute */
574     } else if (wreg_mode == I2C_WREG) {
575         /* active DAC power,active left and right channel,dac mute */
576         audio_i2c_codec_write(
577             addr_audio_codec_dac_ctr,
578             MASK_VAL(FLD_AUDIO_CODEC_DAC_SB, 0, FLD_AUDIO_CODEC_DAC_LEFT_ONLY, 0, FLD_AUDIO_CODEC_DAC_SOFT_MUTE, 1));
579 
580         /* disable sleep mode ,disable sb_analog,disable global standby */
581         audio_i2c_codec_write(addr_audio_codec_vic_ctr, MASK_VAL(FLD_AUDIO_CODEC_SB, 0, FLD_AUDIO_CODEC_SB_ANALOG, 0,
582                                                                  FLD_AUDIO_CODEC_SLEEP_ANALOG, 0));
583 
584         /* data word length ,interface master/slave selection, audio interface protocol selection,
585         * active dac audio interface */
586         audio_i2c_codec_write(addr_audio_codec_dac_itf_ctr,
587                               MASK_VAL(FLD_AUDIO_CODEC_FORMAT, CODEC_I2S_MODE, FLD_AUDIO_CODEC_DAC_ITF_SB,
588                                        CODEC_ITF_AC, FLD_AUDIO_CODEC_SLAVE, mode, FLD_AUDIO_CODEC_WL, data_select));
589 
590         /* disable DAC digital gain coupling, Left channel DAC digital gain */
591         audio_i2c_codec_write(
592             addr_audio_codec_dacl_gain,
593             MASK_VAL(FLD_AUDIO_CODEC_DAC_LRGOD, 0, FLD_AUDIO_CODEC_DAC_GODL, audio_i2s_codec_config.out_digital_gain));
594 
595         audio_i2c_codec_write(addr_audio_codec_dacr_gain,
596                               MASK_VAL(FLD_AUDIO_CODEC_DAC_GODR,
597                                        audio_i2s_codec_config.out_digital_gain)); /* Right channel DAC digital gain */
598 
599         /* disable Headphone gain coupling, set Left channel HP amplifier gain */
600         audio_i2c_codec_write(addr_audio_codec_hpl_gain, MASK_VAL(FLD_AUDIO_CODEC_HPL_LRGO, 0, FLD_AUDIO_CODEC_HPL_GOL,
601                                                                   audio_i2s_codec_config.out_analog_gain));
602 
603         audio_i2c_codec_write(
604             addr_audio_codec_hpr_gain,
605             MASK_VAL(FLD_AUDIO_CODEC_HPR_GOR,
606                      audio_i2s_codec_config.out_analog_gain)); /*  Right channel HP amplifier gain programming */
607 
608         audio_i2c_codec_write(addr_audio_codec_dac_freq_ctr, (FLD_AUDIO_CODEC_DAC_FREQ & rate));
609 
610         /* dac mute */
611         audio_i2c_codec_write(
612             addr_audio_codec_dac_ctr,
613             MASK_VAL(FLD_AUDIO_CODEC_DAC_SB, 0, FLD_AUDIO_CODEC_DAC_LEFT_ONLY, 0, FLD_AUDIO_CODEC_DAC_SOFT_MUTE, 0));
614     }
615 }
616 
617 /**
618  * @brief     This function serves to config codec for adc.
619  * @param[in] mode        - select i2s as master or slave
620  * @param[in] in_mode     - line_in/amic/dmic input mode select
621  * @param[in] rate        - audio sampling rate
622  * @param[in] data_select - codec adc word length
623  * @param[in] wreg_mode   - mcu or i2c config codec
624  * @return    none
625  */
audio_codec_adc_config(i2s_codec_m_s_mode_e mode,audio_input_mode_e in_mode,audio_sample_rate_e rate,codec_data_select_e data_select,codec_wreg_mode_e wreg_mode)626 void audio_codec_adc_config(i2s_codec_m_s_mode_e mode, audio_input_mode_e in_mode, audio_sample_rate_e rate,
627                             codec_data_select_e data_select, codec_wreg_mode_e wreg_mode)
628 {
629     if (wreg_mode == MCU_WREG) {
630         BM_SET(reg_audio_codec_adc12_ctr, FLD_AUDIO_CODEC_ADC12_SOFT_MUTE); /* adc mute */
631         if ((audio_i2s_codec_config.audio_in_mode == BIT_16_MONO) ||
632             ((audio_i2s_codec_config.audio_in_mode == BIT_20_OR_24_MONO))) {
633             BM_CLR(reg_audio_codec_adc12_ctr, FLD_AUDIO_CODEC_ADC1_SB); /* active anc0 channel,mono */
634         } else {
635             BM_CLR(reg_audio_codec_adc12_ctr,
636                    FLD_AUDIO_CODEC_ADC1_SB | FLD_AUDIO_CODEC_ADC2_SB); /* active adc0 and adc1 channel */
637         }
638         BM_CLR(reg_audio_codec_vic_ctr,
639                FLD_AUDIO_CODEC_SB | FLD_AUDIO_CODEC_SB_ANALOG |
640                    FLD_AUDIO_CODEC_SLEEP_ANALOG); /* disable sleep mode ,disable sb_analog, disable global standby */
641 
642         if (in_mode == AMIC_INPUT) {
643             /* Microphone 1 input selection ,Microphone biasing active,Single-ended input, MICBIAS1 output=2.08V, */
644             reg_audio_codec_mic1_ctr =
645                 MASK_VAL(FLD_AUDIO_CODEC_MIC1_SEL, 0, FLD_AUDIO_CODEC_MICBIAS1_SB, 0, FLD_AUDIO_CODEC_MIC_DIFF1,
646                          audio_i2s_codec_config.mic_input_mode_select, FLD_AUDIO_CODEC_MICBIAS1_V, 0);
647             /* Microphone 2 input selection,Single-ended input */
648             reg_audio_codec_mic2_ctr = MASK_VAL(FLD_AUDIO_CODEC_MIC2_SEL, 0, FLD_AUDIO_CODEC_MIC_DIFF2,
649                                                 audio_i2s_codec_config.mic_input_mode_select);
650 
651             /* enable wind noise filter mode3 */
652             reg_audio_codec_adc_wnf_ctr = CODEC_ADC_WNF_MODE3;
653 
654             /* analog 0/4/8/12/16/20 dB boost gain */
655             reg_audio_codec_mic_l_R_gain =
656                 MASK_VAL(FLD_AUDIO_CODEC_AMIC_L_GAIN, audio_i2s_codec_config.in_analog_gain,
657                          FLD_AUDIO_CODEC_AMIC_R_GAIN, audio_i2s_codec_config.in_analog_gain);
658         } else if (in_mode == DMIC_INPUT) {
659             reg_audio_dmic_12 =
660                 MASK_VAL(FLD_AUDIO_CODEC_ADC_DMIC_SEL2, 1, FLD_AUDIO_CODEC_ADC_DMIC_SEL1, 1, FLD_AUDIO_CODEC_DMIC2_SB,
661                          CODEC_ITF_AC, FLD_AUDIO_CODEC_DMIC1_SB, CODEC_ITF_AC);
662         } else if (in_mode == LINE_INPUT) {
663             /* analog 0/4/8/12/16/20 dB boost gain */
664             reg_audio_codec_mic_l_R_gain =
665                 MASK_VAL(FLD_AUDIO_CODEC_AMIC_L_GAIN, audio_i2s_codec_config.in_analog_gain,
666                          FLD_AUDIO_CODEC_AMIC_R_GAIN, audio_i2s_codec_config.in_analog_gain);
667         }
668 
669         /* 0db~43db  1db step ,digital programmable gain */
670         reg_audio_adc1_gain =
671             MASK_VAL(FLD_AUDIO_CODEC_ADC_LRGID, 1, FLD_AUDIO_CODEC_ADC_GID1, audio_i2s_codec_config.in_digital_gain);
672         /* data word length ,interface master/slave selection, audio interface protocol selection  */
673         reg_audio_codec_adc_itf_ctr = MASK_VAL(FLD_AUDIO_CODEC_FORMAT, CODEC_I2S_MODE, FLD_AUDIO_CODEC_SLAVE, mode,
674                                                FLD_AUDIO_CODEC_WL, data_select);
675         /* audio adc interface active */
676         BM_CLR(reg_audio_codec_adc2_ctr, FLD_AUDIO_CODEC_ADC12_SB);
677 
678         /* adc high pass filter active, set adc sample rate */
679         reg_audio_codec_adc_freq_ctr = MASK_VAL(FLD_AUDIO_CODEC_ADC12_HPF_EN, 1, FLD_AUDIO_CODEC_ADC_FREQ,
680                                                 rate == AUDIO_ADC_16K_DAC_48K ? AUDIO_16K : rate);
681 
682         BM_CLR(reg_audio_codec_adc12_ctr, FLD_AUDIO_CODEC_ADC12_SOFT_MUTE); /* adc unmute */
683     } else if (wreg_mode == I2C_WREG) {
684         /* active adc0 and adc1  channel, if mono only active adc1,adc mute */
685         audio_i2c_codec_write(addr_audio_codec_adc12_ctr, MASK_VAL(FLD_AUDIO_CODEC_ADC1_SB, 0, FLD_AUDIO_CODEC_ADC2_SB,
686                                                                    0, FLD_AUDIO_CODEC_ADC12_SOFT_MUTE, 1));
687 
688         /* disable sleep mode ,disable sb_analog,disable global standby */
689         audio_i2c_codec_write(addr_audio_codec_vic_ctr, MASK_VAL(FLD_AUDIO_CODEC_SB, 0, FLD_AUDIO_CODEC_SB_ANALOG, 0,
690                                                                  FLD_AUDIO_CODEC_SLEEP_ANALOG, 0));
691 
692         if (in_mode == AMIC_INPUT) {
693             /* Microphone 1 input selection ,Microphone biasing active,Single-ended input,MICBIAS1 output=2.08V */
694             audio_i2c_codec_write(addr_audio_codec_mic1_ctr,
695                                   MASK_VAL(FLD_AUDIO_CODEC_MIC1_SEL, 0, FLD_AUDIO_CODEC_MICBIAS1_SB, 0,
696                                            FLD_AUDIO_CODEC_MIC_DIFF1, 0, FLD_AUDIO_CODEC_MICBIAS1_V, 0));
697 
698             /* Microphone 2 input selection,Single-ended input */
699             audio_i2c_codec_write(addr_audio_codec_mic2_ctr,
700                                   MASK_VAL(FLD_AUDIO_CODEC_MIC2_SEL, 0, FLD_AUDIO_CODEC_MIC_DIFF2, 0));
701 
702             /* analog 0/4/8/12/16/20 dB boost gain */
703             audio_i2c_codec_write(addr_audio_codec_mic_l_R_gain,
704                                   MASK_VAL(FLD_AUDIO_CODEC_AMIC_L_GAIN, audio_i2s_codec_config.in_analog_gain,
705                                            FLD_AUDIO_CODEC_AMIC_R_GAIN, audio_i2s_codec_config.in_analog_gain));
706         } else if (in_mode == DMIC_INPUT) {
707             audio_i2c_codec_write(addr_audio_dmic_12,
708                                   MASK_VAL(FLD_AUDIO_CODEC_ADC_DMIC_SEL2, 1, FLD_AUDIO_CODEC_ADC_DMIC_SEL1, 1,
709                                            FLD_AUDIO_CODEC_DMIC2_SB, CODEC_ITF_AC, FLD_AUDIO_CODEC_DMIC1_SB,
710                                            CODEC_ITF_AC));
711         } else if (in_mode == LINE_INPUT) {
712             /* analog 0/4/8/12/16/20 dB boost gain */
713             audio_i2c_codec_write(addr_audio_codec_mic_l_R_gain,
714                                   MASK_VAL(FLD_AUDIO_CODEC_AMIC_L_GAIN, audio_i2s_codec_config.in_analog_gain,
715                                            FLD_AUDIO_CODEC_AMIC_R_GAIN, audio_i2s_codec_config.in_analog_gain));
716         }
717 
718         /* 0db~43db  1db step ,digital programmable gain */
719         audio_i2c_codec_write(addr_audio_adc1_gain, MASK_VAL(FLD_AUDIO_CODEC_ADC_LRGID, 1, FLD_AUDIO_CODEC_ADC_GID1,
720                                                              audio_i2s_codec_config.in_digital_gain));
721 
722         audio_i2c_codec_write(addr_audio_codec_adc_itf_ctr,
723                               MASK_VAL(FLD_AUDIO_CODEC_FORMAT, CODEC_I2S_MODE, FLD_AUDIO_CODEC_SLAVE, mode,
724                                        FLD_AUDIO_CODEC_WL, data_select));
725 
726         audio_i2c_codec_write(addr_audio_codec_adc2_ctr, ~FLD_AUDIO_CODEC_ADC12_SB); /* audio adc interface active */
727 
728         /* adc high pass filter active, set adc sample rate */
729         audio_i2c_codec_write(addr_audio_codec_adc_freq_ctr,
730                               MASK_VAL(FLD_AUDIO_CODEC_ADC12_HPF_EN, 1, FLD_AUDIO_CODEC_ADC_FREQ, rate));
731 
732         /* dac mute */
733         audio_i2c_codec_write(addr_audio_codec_adc12_ctr, MASK_VAL(FLD_AUDIO_CODEC_ADC1_SB, 0, FLD_AUDIO_CODEC_ADC2_SB,
734                                                                    0, FLD_AUDIO_CODEC_ADC12_SOFT_MUTE, 0));
735     }
736 }
737 
738 /**
739  * @brief     This function serves to set data path.
740  * @param[in] audio_flow    - audio flow  select
741  * @param[in] ain0_mode     - fifo0 input mode select
742  * @param[in] ain1_mode     - fifo1 input mode select
743  * @param[in] i2s_aout_mode - fifo output source select
744  * @return    none
745  */
audio_mux_config(audio_flow_e audio_flow,audio_in_mode_e ain0_mode,audio_in_mode_e ain1_mode,audio_out_mode_e i2s_aout_mode)746 void audio_mux_config(audio_flow_e audio_flow, audio_in_mode_e ain0_mode, audio_in_mode_e ain1_mode,
747                       audio_out_mode_e i2s_aout_mode)
748 {
749     reg_audio_ctrl |= audio_flow;
750     reg_audio_tune = MASK_VAL(FLD_AUDIO_I2S_I2S_AIN0_COME, ain0_mode, FLD_AUDIO_I2S_I2S_AIN1_COME, ain1_mode,
751                               FLD_AUDIO_I2S_I2S_AOUT_COME, i2s_aout_mode);
752 }
753 
754 /**
755  * @brief     This function serves to config interface, word length, and m/s .
756  * @param[in] i2s_format - interface protocol
757  * @param[in] wl   		 - audio data word length
758  * @param[in] m_s        - select i2s as master or slave
759  * @param[in] en         - 1 enable audio data invert , 0 disable audio data invert.
760  *                         For example in mono mode switch R and L channel data to fifo0
761  * @return    none
762  */
audio_i2s_config(i2s_mode_select_e i2s_format,i2s_data_select_e wl,i2s_codec_m_s_mode_e m_s,audio_data_invert_e en)763 void audio_i2s_config(i2s_mode_select_e i2s_format, i2s_data_select_e wl, i2s_codec_m_s_mode_e m_s,
764                       audio_data_invert_e en)
765 {
766     reg_i2s_cfg = MASK_VAL(FLD_AUDIO_I2S_FORMAT, i2s_format, FLD_AUDIO_I2S_WL, wl, FLD_AUDIO_I2S_LRP, 0,
767                            FLD_AUDIO_I2S_LRSWAP, en, FLD_AUDIO_I2S_ADC_DCI_MS, m_s, FLD_AUDIO_I2S_DAC_DCI_MS, m_s);
768 }
769 
770 /**
771  * @brief     This function serves to set i2s clock and audio sampling rate when i2s as master.
772  * @param[in] audio_rate - audio sampling rate
773  * @param[in] match		 - the match of audio rate.
774  * @param[in] match_en   - initial must 0, then change rate must 1
775  * @return    none
776  * @attention i2s clock  divider from pll,sampling rate calculation is based on pll=192M,so pll must be 192M
777  */
audio_set_i2s_clock(audio_sample_rate_e audio_rate,audio_rate_match_e match,unsigned char match_en)778 _attribute_ram_code_sec_noinline_ void audio_set_i2s_clock(audio_sample_rate_e audio_rate, audio_rate_match_e match,
779                                                            unsigned char match_en)
780 {
781     reg_tx_wptr = 0xffff;  // enable tx_rptr
782     unsigned short tx_rptr_old;
783     switch (audio_rate) {
784         case AUDIO_8K:
785             audio_set_i2s_clk(1, 8);    // set i2s clk 24M
786             audio_set_i2s_bclk(12);     // 24/(2*12) = 1M bclk
787             audio_set_lrclk(125, 125);  // bclk/125=8k
788             break;
789 
790         case AUDIO_16K:
791             audio_set_i2s_clk(1, 8);    // set i2s clk 24M
792             audio_set_i2s_bclk(6);      // 24/(2*6) = 2M bclk
793             audio_set_lrclk(125, 125);  // bclk/125=16k
794             break;
795 
796         case AUDIO_32K:
797             audio_set_i2s_clk(1, 8);    // set i2s clk 24M
798             audio_set_i2s_bclk(3);      // 24/(2*3) = 4M bclk
799             audio_set_lrclk(125, 125);  // bclk/125=32k
800             break;
801 
802         case AUDIO_ADC_16K_DAC_48K:
803             audio_set_i2s_clk(2, 125);  // i2s clk 3.072 M
804             audio_set_i2s_bclk(0);      // 3.072/1 = 3.072M bclk
805             audio_set_lrclk(192, 64);   // adc_lrclk=3.072/192=16K,dac_lrclk=3.072/64=48K
806             break;
807 
808         case AUDIO_48K:
809             if (match_en) {
810                 tx_rptr_old = reg_tx_rptr;
811                 while (tx_rptr_old == reg_tx_rptr) {
812                 }
813             }
814 
815             if (match == AUDIO_RATE_EQUAL) {         // 48000
816                 audio_set_i2s_clk(2, 125);           // i2s clk 3.072 M
817                 audio_set_i2s_bclk(0);               // 3.072/1 = 3.072M bclk
818                 audio_set_lrclk(64, 64);             // bclk/64=48k
819             } else if (match == AUDIO_RATE_GT_L0) {  // 48004
820                 audio_set_i2s_clk(3, 169);
821                 audio_set_i2s_bclk(0);
822                 audio_set_lrclk(71, 71);
823             } else if (match == AUDIO_RATE_GT_L1) {  // 48012.0
824                 audio_set_i2s_clk(4, 129);
825                 audio_set_i2s_bclk(0);
826                 audio_set_lrclk(124, 124);
827             } else if (match == AUDIO_RATE_LT_L0) {  // 47994.0
828                 audio_set_i2s_clk(2, 63);
829                 audio_set_i2s_bclk(0);
830                 audio_set_lrclk(127, 127);
831             } else if (match == AUDIO_RATE_LT_L1) {  // 47985.0
832                 audio_set_i2s_clk(4, 165);
833                 audio_set_i2s_bclk(0);
834                 audio_set_lrclk(97, 97);
835             }
836             break;
837 
838         case AUDIO_44EP1K:
839             if (match_en) {
840                 tx_rptr_old = reg_tx_rptr;
841                 while (tx_rptr_old == reg_tx_rptr) {
842                 }
843             }
844 
845             if (match == AUDIO_RATE_EQUAL) {  // 44099.9
846                 audio_set_i2s_clk(8, 215);
847                 audio_set_i2s_bclk(0);
848                 audio_set_lrclk(162, 162);
849             } else if (match == AUDIO_RATE_GT_L0) {  // 44110.2
850                 audio_set_i2s_clk(11, 228);
851                 audio_set_i2s_bclk(0);
852                 audio_set_lrclk(210, 210);
853             } else if (match == AUDIO_RATE_GT_L1) {  // 44117.6
854                 audio_set_i2s_clk(5, 170);
855                 audio_set_i2s_bclk(0);
856                 audio_set_lrclk(128, 128);
857             } else if (match == AUDIO_RATE_LT_L0) {  // 44094.4
858                 audio_set_i2s_clk(7, 254);
859                 audio_set_i2s_bclk(0);
860                 audio_set_lrclk(120, 120);
861             } else if (match == AUDIO_RATE_LT_L1) {  // 44081.6
862                 audio_set_i2s_clk(9, 245);
863                 audio_set_i2s_bclk(0);
864                 audio_set_lrclk(160, 160);
865             }
866             break;
867     }
868 }
869 
870 /**
871  * @brief  This function serves to set audio rx dma chain transfer.
872  * @param[in] chn       -  dma channel
873  * @param[in] in_buff   - the pointer of rx_buff.
874  * @param[in] buff_size - the size of rx_buff.
875  * @return    none
876  */
audio_rx_dma_chain_init(dma_chn_e chn,unsigned short * in_buff,unsigned int buff_size)877 void audio_rx_dma_chain_init(dma_chn_e chn, unsigned short *in_buff, unsigned int buff_size)
878 {
879     audio_rx_dma_config(chn, (unsigned short *)in_buff, buff_size, &g_audio_rx_dma_list_cfg);
880     audio_rx_dma_add_list_element(&g_audio_rx_dma_list_cfg, &g_audio_rx_dma_list_cfg, (unsigned short *)in_buff,
881                                   buff_size);
882     audio_rx_dma_en();
883 }
884 
885 /**
886   * @brief  This function serves to initialize audio tx dma chain transfer.
887   * @param[in] chn       - dma channel
888   * @param[in] out_buff  - the pointer of tx_buff.
889   * @param[in] buff_size - the size of tx_buff.
890   * @return    none
891   */
audio_tx_dma_chain_init(dma_chn_e chn,unsigned short * out_buff,unsigned int buff_size)892 void audio_tx_dma_chain_init(dma_chn_e chn, unsigned short *out_buff, unsigned int buff_size)
893 {
894     audio_tx_dma_config(chn, (unsigned short *)out_buff, buff_size, &g_audio_tx_dma_list_cfg);
895     audio_tx_dma_add_list_element(&g_audio_tx_dma_list_cfg, &g_audio_tx_dma_list_cfg, (unsigned short *)out_buff,
896                                   buff_size);
897     audio_tx_dma_en();
898 }
899 
900 #define WM8731_ANA_AUDIO_PATH_CTRL        0x08  // Analogue Audio Path Control
901 #define WM8731_DIG_AUDIO_PATH_CTRL        0x0a  // Digital Audio Path Control
902 #define WM8731_POWER_DOWN_CTRL            0x0c  // Power Down Control
903 #define WM8731_ST_LINE_VOL                0x00  // Set linmute volume
904 #define WM8731_ST_RINE_VOL                0x02  // Set rinmute volume
905 #define WM8731_DIG_AUDIO_INTERFACE_FORMAT 0x0e  // Digital Audio Interface Format
906 #define WM8731_SAMPLING_CTRL              0x10  // Sampling Control
907 #define WM8731_ACTIVE_CTRL                0x12  // Active Control
908 #define WM8731_RESET_CTRL                 0x1e  // Reset Register
909 
910 unsigned char LineIn_To_I2S_CMD_TAB[9][2] = {
911     {WM8731_RESET_CTRL, 0x00},
912     {WM8731_ST_LINE_VOL, 0x10},
913     {WM8731_ST_RINE_VOL, 0x10},
914     {WM8731_ANA_AUDIO_PATH_CTRL, 0x13},
915     {WM8731_DIG_AUDIO_PATH_CTRL, 0x00},
916     {WM8731_POWER_DOWN_CTRL, 0x22},
917     {WM8731_DIG_AUDIO_INTERFACE_FORMAT, 0x02},
918     {WM8731_SAMPLING_CTRL, 0x19},
919     {WM8731_ACTIVE_CTRL, 0x01},
920 
921 };
922 
923 /**
924  * @brief     This function serves to  set external  codec by i2c
925  * @return    none
926  */
audio_set_ext_codec(void)927 void audio_set_ext_codec(void)
928 {
929     for (unsigned char i = 0; i < 9; i++) {
930         audio_i2c_codec_write(LineIn_To_I2S_CMD_TAB[i][0] >> 1, LineIn_To_I2S_CMD_TAB[i][1]);
931     }
932 }
933 
934 /**
935  * @brief     This function serves to  set pwm0 as external codec mclk
936  * @param[in] pin - the pin of pwm0
937  * @return    none
938  */
pwm_set(pwm_pin_e pin)939 void pwm_set(pwm_pin_e pin)
940 {
941     reg_pwm_enable = 0;
942     reg_pwm0_enable = 0;  // off pwm0
943     pwm_set_pin(pin);
944     pwm_set_clk((unsigned char)(sys_clk.pclk * 1000 * 1000 / 24000000 - 1));
945     // reg_pwm_clkdiv = 0;// set pwm clk equal pclk 24M
946     pwm_set_pwm0_mode(PWM_NORMAL_MODE);
947     pwm_set_tcmp(PWM0_ID, 1);
948     pwm_set_tmax(PWM0_ID, 2);  // 24M/2=12M pwm  mclk to  ext codec clk
949     pwm_start(PWM0_ID);
950 }
951 
952 /**
953  * @brief This function serves to initialize audio(external codec WM8731) by i2c.
954  * @param[in]  pwm0_pin - the pin of pwm0
955  * @param[in]  sda_pin  - the pin port selected as I2C sda pin port.
956  * @param[in]  scl_pin  - the pin port selected as I2C scl pin port.
957  * @return    none
958  */
audio_i2s_init(pwm_pin_e pwm0_pin,i2c_sda_pin_e sda_pin,i2c_scl_pin_e scl_pin)959 void audio_i2s_init(pwm_pin_e pwm0_pin, i2c_sda_pin_e sda_pin, i2c_scl_pin_e scl_pin)
960 {
961     pwm_set(pwm0_pin);
962     audio_i2s_set_pin();
963     audio_i2c_init(EXT_CODEC, sda_pin, scl_pin);
964     aduio_set_chn_wl(MONO_BIT_16);
965     audio_mux_config(IO_I2S, BIT_16_MONO, BIT_16_MONO, BIT_16_MONO_FIFO0);
966     audio_i2s_config(I2S_I2S_MODE, I2S_BIT_16_DATA, I2S_M_CODEC_S, I2S_DATA_INVERT_DIS);
967     audio_set_i2s_clock(AUDIO_32K, AUDIO_RATE_EQUAL, 0);
968     audio_clk_en(1, 1);
969     audio_set_ext_codec();
970     audio_data_fifo0_path_sel(I2S_DATA_IN_FIFO, I2S_OUT);
971 }
972 
973 /**
974  * @brief    This function serves to active soft mute dac and disable dma .
975  * @return    none
976  */
audio_pause_out_path(void)977 void audio_pause_out_path(void)
978 {
979     BM_SET(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_SOFT_MUTE);  // dac mute
980     audio_tx_dma_dis();
981 }
982 
983 /**
984   * @brief    This function serves to inactive soft mute dac and enable dma after change_sample_rate.
985   * @return    none
986   */
audio_resume_out_path(void)987 void audio_resume_out_path(void)
988 {
989     BM_CLR(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_SOFT_MUTE);  // dac unmute
990     audio_tx_dma_en();
991 }
992 /**
993  * @brief     This function serves to change sample rate for dac.
994  * @param[in] rate     -  the sample rate of dac
995  * @return    none
996  */
audio_change_sample_rate(audio_sample_rate_e rate)997 _attribute_ram_code_sec_ void audio_change_sample_rate(audio_sample_rate_e rate)
998 {
999     audio_set_i2s_clock(rate, AUDIO_RATE_EQUAL, 1);
1000     reg_audio_codec_dac_freq_ctr = (FLD_AUDIO_CODEC_DAC_FREQ & rate);
1001 }
1002 
1003 /**
1004  * @brief     This function serves to power down codec_dac.
1005  * @return    none
1006  */
audio_codec_dac_power_down(void)1007 void audio_codec_dac_power_down(void)
1008 {
1009     BM_SET(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_SOFT_MUTE);
1010     delay_ms(10);
1011     BM_SET(reg_audio_codec_dac_itf_ctr, FLD_AUDIO_CODEC_DAC_ITF_SB);
1012     BM_SET(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_SB);
1013     delay_ms(1);
1014     BM_SET(reg_audio_codec_vic_ctr, FLD_AUDIO_CODEC_SLEEP_ANALOG);
1015     reg_audio_codec_vic_ctr = MASK_VAL(FLD_AUDIO_CODEC_SB, CODEC_ITF_PD, FLD_AUDIO_CODEC_SB_ANALOG, CODEC_ITF_PD,
1016                                        FLD_AUDIO_CODEC_SLEEP_ANALOG, CODEC_ITF_PD);
1017     audio_tx_dma_dis();
1018     audio_clk_en(0, 0);
1019 }
1020 
1021 /**
1022  * @brief     This function serves to power on codec_dac.
1023  * @return    none
1024  */
audio_codec_dac_power_on(void)1025 void audio_codec_dac_power_on(void)
1026 {
1027     audio_clk_en(1, 1);
1028     BM_SET(reg_audio_codec_vic_ctr, FLD_AUDIO_CODEC_SLEEP_ANALOG);
1029     delay_ms(1);
1030     BM_CLR(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_SB);
1031     BM_CLR(reg_audio_codec_dac_itf_ctr, FLD_AUDIO_CODEC_DAC_ITF_SB);
1032     reg_audio_codec_vic_ctr = MASK_VAL(FLD_AUDIO_CODEC_SB, CODEC_ITF_AC, FLD_AUDIO_CODEC_SB_ANALOG, CODEC_ITF_AC,
1033                                        FLD_AUDIO_CODEC_SLEEP_ANALOG, CODEC_ITF_AC);
1034     BM_CLR(reg_audio_codec_dac_ctr, FLD_AUDIO_CODEC_DAC_SOFT_MUTE);  // unmute
1035     audio_tx_dma_en();
1036 }
1037 
1038 /**
1039  * @brief     This function serves to power down codec_adc.
1040  * @return    none
1041  */
audio_codec_adc_power_down(void)1042 void audio_codec_adc_power_down(void)
1043 {
1044     BM_SET(reg_audio_codec_adc12_ctr, FLD_AUDIO_CODEC_ADC12_SOFT_MUTE);
1045     delay_ms(10);
1046     BM_SET(reg_audio_codec_adc2_ctr, FLD_AUDIO_CODEC_ADC12_SB);
1047     BM_SET(reg_audio_codec_adc12_ctr, FLD_AUDIO_CODEC_ADC1_SB | FLD_AUDIO_CODEC_ADC2_SB);
1048 
1049     BM_SET(reg_audio_codec_vic_ctr, FLD_AUDIO_CODEC_SLEEP_ANALOG);
1050     reg_audio_codec_vic_ctr = MASK_VAL(FLD_AUDIO_CODEC_SB, CODEC_ITF_PD, FLD_AUDIO_CODEC_SB_ANALOG, CODEC_ITF_PD,
1051                                        FLD_AUDIO_CODEC_SLEEP_ANALOG, CODEC_ITF_PD);
1052     audio_rx_dma_dis();
1053     audio_clk_en(0, 0);
1054 }
1055 
1056 /**
1057  * @brief     This function serves to power on codec_adc.
1058  * @return    none
1059  */
audio_codec_adc_power_on(void)1060 void audio_codec_adc_power_on(void)
1061 {
1062     audio_clk_en(1, 1);
1063     BM_SET(reg_audio_codec_vic_ctr, FLD_AUDIO_CODEC_SLEEP_ANALOG);
1064     delay_ms(1);
1065     BM_CLR(reg_audio_codec_adc12_ctr, FLD_AUDIO_CODEC_ADC1_SB | FLD_AUDIO_CODEC_ADC2_SB);
1066     BM_CLR(reg_audio_codec_adc2_ctr, FLD_AUDIO_CODEC_ADC12_SB);
1067     reg_audio_codec_vic_ctr = MASK_VAL(FLD_AUDIO_CODEC_SB, CODEC_ITF_AC, FLD_AUDIO_CODEC_SB_ANALOG, CODEC_ITF_AC,
1068                                        FLD_AUDIO_CODEC_SLEEP_ANALOG, CODEC_ITF_AC);
1069     BM_CLR(reg_audio_codec_adc12_ctr, FLD_AUDIO_CODEC_ADC12_SOFT_MUTE);
1070 
1071     audio_rx_dma_en();
1072 }
1073