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
19 /********************************************************************************************************
20 * @file adc.c
21 *
22 * @brief This is the source file for B91
23 *
24 * @author Driver Group
25 *
26 *******************************************************************************************************/
27 #include "adc.h"
28 #include "audio.h"
29 #include "compiler.h"
30
31 _attribute_data_retention_sec_ unsigned short g_adc_vref = 1175; //default ADC ref voltage (unit:mV)
32 volatile unsigned char g_adc_pre_scale;
33 volatile unsigned char g_adc_vbat_divider;
34
35 dma_chn_e adc_dma_chn;
36 dma_config_t adc_rx_dma_config=
37 {
38 .dst_req_sel= 0,
39 .src_req_sel=DMA_REQ_AUDIO1_RX,//adc use the audio1 interface
40 .dst_addr_ctrl=DMA_ADDR_INCREMENT,
41 .src_addr_ctrl=DMA_ADDR_FIX,
42 .dstmode=DMA_NORMAL_MODE,
43 .srcmode=DMA_HANDSHAKE_MODE,
44 .dstwidth=DMA_CTR_WORD_WIDTH,//must word
45 .srcwidth=DMA_CTR_WORD_WIDTH,//must word
46 .src_burst_size=0,//must 0
47 .read_num_en=0,
48 .priority=0,
49 .write_num_en=0,
50 .auto_en=0,//must 0
51 };
52 /**
53 * @brief This function serves to config adc_dma_chn channel.
54 * @param[in] chn - the DMA channel
55 * @return none
56 */
adc_set_dma_config(dma_chn_e chn)57 void adc_set_dma_config(dma_chn_e chn)
58 {
59 adc_dma_chn = chn;
60 dma_config(chn, &adc_rx_dma_config);
61 dma_clr_irq_mask(adc_dma_chn,TC_MASK|ERR_MASK|ABT_MASK);
62 dma_set_irq_mask(adc_dma_chn, TC_MASK);
63
64 audio_data_fifo1_path_sel(SAR_ADC_DATA_IN_FIFO,OUT_NO_USE);//connect DMA and ADC by audio input fifo1.
65 }
66 /**
67 * @brief This function serves to start sample with adc DMA channel.
68 * @param[in] adc_data_buf - the address of data buffer
69 * @param[in] data_byte_len - the length of data size by byte
70 * @return none
71 */
adc_start_sample_dma(unsigned short * adc_data_buf,unsigned int data_byte_len)72 void adc_start_sample_dma(unsigned short *adc_data_buf,unsigned int data_byte_len)
73 {
74 dma_set_address(adc_dma_chn,reg_fifo_buf_adr(1),(unsigned int)convert_ram_addr_cpu2bus(adc_data_buf));
75 dma_set_size(adc_dma_chn,data_byte_len,DMA_WORD_WIDTH);
76 dma_chn_en(adc_dma_chn);
77 adc_fifo_enable();
78 }
79 /**
80 * @brief This function serves to get adc DMA sample status.
81 * @return 0: the sample is in progress.
82 * !0: the sample is finished.
83 */
adc_get_sample_status_dma(void)84 unsigned char adc_get_sample_status_dma(void)
85 {
86 return (dma_get_tc_irq_status(1<<adc_dma_chn));
87 }
88 /**
89 * @brief This function serves to clear adc DMA sample status.
90 * @return none
91 */
adc_clr_sample_status_dma(void)92 void adc_clr_sample_status_dma(void)
93 {
94 dma_chn_dis(adc_dma_chn);
95 dma_clr_tc_irq_status(1<<adc_dma_chn);
96 }
97 /**
98 * @brief This function serves to stop adc DMA sample.
99 * @return none
100 * @attention function disable adc sample fifo, next sample should enable it.
101 */
adc_stop_sample_dma(void)102 void adc_stop_sample_dma(void)
103 {
104 adc_fifo_disable();
105 }
106 /**
107 * @brief This function is used to set IO port for ADC supply or ADC IO port voltage sampling.
108 * @param[in] mode - ADC gpio pin sample mode
109 * @param[in] pin - adc_input_pin_def_e ADC input gpio pin
110 * @return none
111 */
adc_pin_config(adc_input_pin_mode_e mode,adc_input_pin_def_e pin)112 void adc_pin_config(adc_input_pin_mode_e mode ,adc_input_pin_def_e pin)
113 {
114 unsigned short adc_input_pin = pin & 0xfff;
115 switch(mode)
116 {
117 case ADC_GPIO_MODE :
118 gpio_function_en(adc_input_pin);
119 gpio_input_dis(adc_input_pin);
120 gpio_output_dis(adc_input_pin);
121 gpio_set_low_level(adc_input_pin);
122 break;
123 case ADC_VBAT_MODE :
124 gpio_function_en(adc_input_pin);
125 gpio_input_dis(adc_input_pin);
126 gpio_output_en(adc_input_pin);
127 gpio_set_high_level(adc_input_pin);
128 break;
129 }
130 }
131 /**
132 * @brief This function is used to set two IO port configuration and set it as input channel of ADC difference IO port voltage sampling.
133 * @param[in] p_pin - enum variable of ADC analog positive input IO.
134 * @param[in] n_pin - enum variable of ADC analog negative input IO.
135 * @return none
136 */
adc_set_diff_pin(adc_input_pin_def_e p_pin,adc_input_pin_def_e n_pin)137 void adc_set_diff_pin(adc_input_pin_def_e p_pin, adc_input_pin_def_e n_pin)
138 {
139 adc_pin_config(ADC_GPIO_MODE, p_pin);
140 adc_pin_config(ADC_GPIO_MODE, n_pin);
141 adc_set_diff_input(p_pin >> 12, n_pin >> 12);
142 }
143 /**
144 * @brief This function serves to set the channel reference voltage.
145 * @param[in] v_ref - enum variable of ADC reference voltage.
146 * @return none
147 */
adc_set_ref_voltage(adc_ref_vol_e v_ref)148 void adc_set_ref_voltage(adc_ref_vol_e v_ref)
149 {
150 analog_write_reg8(areg_adc_vref, v_ref);
151 if(v_ref == ADC_VREF_1P2V)
152 {
153 //Vref buffer bias current trimming: 150%
154 //Comparator preamp bias current trimming: 100%
155 analog_write_reg8(areg_ain_scale , (analog_read_reg8( areg_ain_scale )&(0xC0)) | 0x3d );
156 g_adc_vref = 1175;
157 }
158 else if(v_ref == ADC_VREF_0P9V)
159 {
160 //Vref buffer bias current trimming: 100%
161 //Comparator preamp bias current trimming: 100%
162 analog_write_reg8( areg_ain_scale , (analog_read_reg8( areg_ain_scale )&(0xC0)) | 0x15 );
163 g_adc_vref=900;// v_ref = ADC_VREF_0P9V,
164 }
165 }
166 /**
167 * @brief This function serves to set the sample frequency.
168 * @param[in] sample_freq - enum variable of ADC sample frequency.
169 * @return none
170 */
adc_set_sample_rate(adc_sample_freq_e sample_freq)171 void adc_set_sample_rate(adc_sample_freq_e sample_freq)
172 {
173 switch(sample_freq)
174 {
175 case ADC_SAMPLE_FREQ_23K :
176 adc_set_state_length(1023, 15);
177 /**
178 * The length of Tsample should match the sampling frequency.
179 * changed by chaofan,confirmed by haitao.20201230.
180 **/
181 adc_set_tsample_cycle(ADC_SAMPLE_CYC_24);//24 adc clocks for sample cycle
182 break;
183 case ADC_SAMPLE_FREQ_48K :
184 adc_set_state_length(490, 10);
185 adc_set_tsample_cycle(ADC_SAMPLE_CYC_12);//12 adc clocks for sample cycle
186 break;
187 case ADC_SAMPLE_FREQ_96K :
188 adc_set_state_length(240, 10);
189 adc_set_tsample_cycle(ADC_SAMPLE_CYC_6);//6 adc clocks for sample cycle
190 break;
191 }
192 }
193 /**
194 * @brief This function serves to set pre_scaling factor.
195 * @param[in] pre_scale - enum variable of ADC pre_scaling factor.
196 * @return none
197 */
adc_set_scale_factor(adc_pre_scale_e pre_scale)198 void adc_set_scale_factor(adc_pre_scale_e pre_scale)
199 {
200 analog_write_reg8( areg_ain_scale , (analog_read_reg8( areg_ain_scale )&(~FLD_SEL_AIN_SCALE)) | (pre_scale<<6) );
201 g_adc_pre_scale = 1<<(unsigned char)pre_scale;
202 }
203 /**
204 * @brief This function serves to select Vbat voltage division factor
205 * @param[in] vbat_div - enum variable of Vbat division factor.
206 * @return none
207 */
adc_set_vbat_divider(adc_vbat_div_e vbat_div)208 void adc_set_vbat_divider(adc_vbat_div_e vbat_div)
209 {
210 analog_write_reg8(areg_adc_vref_vbat_div, (analog_read_reg8(areg_adc_vref_vbat_div)&(~FLD_ADC_VREF_VBAT_DIV)) | (vbat_div<<2) );
211 if(vbat_div)
212 {
213 g_adc_vbat_divider=5-vbat_div;
214 }
215 else
216 {
217 g_adc_vbat_divider=1;
218 }
219 }
220 /**
221 * @brief This function serves to ADC init.
222 * @param[in] v_ref - enum variable of ADC reference voltage.
223 * @param[in] pre_scale - enum variable of ADC pre_scaling factor.
224 * @param[in] sample_freq - enum variable of ADC sample frequency.
225 * @return none
226 * @attention Many features are configured in adc_init function. But some features
227 * such as adc_clk, resolution, tsample_cycle, we think better to set as default value,
228 * and user don't need to change them in most use cases.
229 */
adc_init(adc_ref_vol_e v_ref,adc_pre_scale_e pre_scale,adc_sample_freq_e sample_freq)230 void adc_init(adc_ref_vol_e v_ref,adc_pre_scale_e pre_scale,adc_sample_freq_e sample_freq)
231 {
232 adc_power_off();//power off sar adc
233 adc_reset();//reset whole digital adc module
234 adc_clk_en();//enable signal of 24M clock to sar adc
235 adc_set_clk(5);//default adc_clk 4M = 24M/(1+div),
236 adc_set_ref_voltage(v_ref);//set channel Vref
237 adc_set_scale_factor(pre_scale);//set Analog input pre-scaling
238 adc_set_sample_rate(sample_freq);//set sample frequency.
239 adc_set_resolution(ADC_RES14);//default adc_resolution set as 14bit ,BIT(13) is sign bit
240 /**
241 * Move the Tsample set to function adc_set_sample_rate(),because of the length of Tsample should match the sampling frequency.
242 * changed by chaofan,confirmed by haitao.20201230.
243 **/
244 adc_set_m_chn_en();//enable adc channel.
245 }
246 /**
247 * @brief This function serves to ADC gpio sample init.
248 * @param[in] pin - adc_input_pin_def_e ADC input gpio pin
249 * @param[in] v_ref - enum variable of ADC reference voltage.
250 * @param[in] pre_scale - enum variable of ADC pre_scaling factor.
251 * @param[in] sample_freq - enum variable of ADC sample frequency.
252 * @return none
253 * @attention gpio voltage sample suggested initial setting are Vref = 1.2V, pre_scale = 1/4.
254 * changed by chaofan.20201230.
255 */
adc_gpio_sample_init(adc_input_pin_def_e pin,adc_ref_vol_e v_ref,adc_pre_scale_e pre_scale,adc_sample_freq_e sample_freq)256 void adc_gpio_sample_init(adc_input_pin_def_e pin,adc_ref_vol_e v_ref,adc_pre_scale_e pre_scale,adc_sample_freq_e sample_freq)
257 {
258 adc_init(v_ref,pre_scale,sample_freq);
259 adc_set_vbat_divider(ADC_VBAT_DIV_OFF);
260 adc_pin_config(ADC_GPIO_MODE, pin);
261 adc_set_diff_input(pin >> 12, GND);
262 }
263 /**
264 * @brief This function servers to initialized ADC temperature sensor.When the reference voltage is set to 1.2V, and
265 * at the same time, the division factor is set to 1 the most accurate.
266 * @return none.
267 * @attention Temperature sensor suggested initial setting are Vref = 1.2V, pre_scale = 1.
268 * The user don't need to change it.
269 */
adc_temperature_sample_init(void)270 void adc_temperature_sample_init(void)
271 {
272 adc_init(ADC_VREF_1P2V, ADC_PRESCALE_1, ADC_SAMPLE_FREQ_96K);
273 adc_set_diff_input(ADC_TEMSENSORP_EE, ADC_TEMSENSORN_EE);
274 adc_set_vbat_divider(ADC_VBAT_DIV_OFF);
275 adc_temp_sensor_power_on();
276 }
277
278 /**
279 * @brief This function servers to set ADC configuration with internal Vbat channel for ADC supply voltage sampling.
280 * @return none
281 * @attention Vbat channel battery voltage sample suggested initial setting are Vref = 1.2V, pre_scale = 1/4, vbat_div = off.
282 * The Vbat channel battery voltage sample range is 1.8~3.5V and is low accuracy,
283 * and must set sys_init with the mode for battery voltage less than 3.6V.
284 * For accurate battery voltage sampling or battery voltage > 3.6V, should use gpio sampling with some external voltage divider.
285 * Recommended configuration parameters:
286 * --3/4 external resistor voltage divider(total resistance 400k, without any capacitance),
287 * --1.2V Vref,
288 * --1/4 Scale
289 * --Sampling frequence below 48K.
290 * changed by chaofan.20201230.
291 */
adc_battery_voltage_sample_init(void)292 void adc_battery_voltage_sample_init(void)
293 {
294 adc_init(ADC_VREF_1P2V, ADC_PRESCALE_1F4, ADC_SAMPLE_FREQ_96K);
295 adc_set_vbat_divider(ADC_VBAT_DIV_OFF);
296 adc_set_diff_input(ADC_VBAT, GND);
297 }
298 /**
299 * @brief This function serves to start adc sample and get raw adc sample code.
300 * @param[in] sample_buffer - pointer to the buffer adc sample code need to store.
301 * @param[in] sample_num - the number of adc sample code.
302 * @return none
303 */
adc_get_code_dma(unsigned short * sample_buffer,unsigned short sample_num)304 void adc_get_code_dma(unsigned short *sample_buffer, unsigned short sample_num)
305 {
306 /******start adc sample********/
307 adc_start_sample_dma((unsigned short *)sample_buffer, sample_num<<1);
308 /******wait for adc sample finish********/
309 while(!adc_get_sample_status_dma());
310 /******stop dma smaple********/
311 adc_stop_sample_dma();
312 /******clear adc sample finished status********/
313 adc_clr_sample_status_dma();//must
314 /******get adc sample data and sort these data ********/
315 for(int i=0;i<sample_num;i++)
316 {
317 if(sample_buffer[i] & BIT(13))
318 { //14 bit resolution, BIT(13) is sign bit, 1 means negative voltage in differential_mode
319 sample_buffer[i] = 0;
320 }
321 else
322 {
323 sample_buffer[i] = (sample_buffer[i] & 0x1fff); //BIT(12..0) is valid adc code
324 }
325 }
326 }
327 /**
328 * @brief This function serves to directly get an adc sample code from analog registers.
329 * If you want to get the sampling results twice in succession,
330 * Must ensure that the sampling interval is more than 2 times the sampling period.
331 * @return adc_code - the adc sample code.
332 */
adc_get_code(void)333 unsigned short adc_get_code(void)
334 {
335 unsigned short adc_code;
336 /******Lock ADC code in analog register ********/
337 analog_write_reg8(areg_adc_data_sample_control,analog_read_reg8(areg_adc_data_sample_control) | FLD_NOT_SAMPLE_ADC_DATA);
338 adc_code = analog_read_reg16(areg_adc_misc_l);
339 analog_write_reg8(areg_adc_data_sample_control,analog_read_reg8(areg_adc_data_sample_control) & (~FLD_NOT_SAMPLE_ADC_DATA));
340
341 if(adc_code & BIT(13)){
342 adc_code=0;
343 }
344 else{
345 adc_code &= 0x1FFF;
346 }
347 return adc_code;
348 }
349 /**
350 * @brief This function serves to calculate voltage from adc sample code.
351 * @param[in] adc_code - the adc sample code.
352 * @return adc_vol_mv - the average value of adc voltage value.
353 */
adc_calculate_voltage(unsigned short adc_code)354 unsigned short adc_calculate_voltage(unsigned short adc_code)
355 {
356 //////////////// adc sample data convert to voltage(mv) ////////////////
357 // (Vref, adc_pre_scale) (BIT<12~0> valid data)
358 // = adc_code * Vref * adc_pre_scale / 0x2000
359 // = adc_code * Vref * adc_pre_scale >>13
360 return ((adc_code * g_adc_vbat_divider * g_adc_pre_scale * g_adc_vref)>>13);
361 }
362 /**
363 * @brief This function serves to calculate temperature from temperature sensor adc sample code.
364 * @param[in] adc_code - the temperature sensor adc sample code.
365 * @return adc_temp_value - the of temperature value.
366 * attention Temperature and adc_code are linearly related. We test four chips between -40~130 (Celsius) and got an average relationship:
367 * Temp = 564 - ((adc_code * 819)>>13),when Vref = 1.2V, pre_scale = 1.
368 */
adc_calculate_temperature(unsigned short adc_code)369 unsigned short adc_calculate_temperature(unsigned short adc_code)
370 {
371 //////////////// adc sample data convert to temperature(Celsius) ////////////////
372 //adc_temp_value = 564 - ((adc_code * 819)>>13)
373 return 564 - ((adc_code * 819)>>13);
374 }
375
376
377