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 /** @page ADC
20 *
21 * Introduction
22 * ===============
23 * TLSRB91 supports hardware ADC function.
24 *
25 * API Reference
26 * ===============
27 * Header File: adc.h
28 */
29 #pragma once
30
31 #include "compiler.h"
32 #include "dma.h"
33 #include "gpio.h"
34 #include "reg_include/register_b91.h"
35
36 typedef enum {
37 ADC_VREF_0P9V = 0x01,
38 ADC_VREF_1P2V = 0x02,
39 } adc_ref_vol_e;
40 typedef enum {
41 ADC_VBAT_DIV_OFF = 0,
42 ADC_VBAT_DIV_1F3 = 0x02,
43 } adc_vbat_div_e;
44
45 typedef enum {
46 NOINPUTN = 0,
47 ADC_GPIO_PB0N = 0x01,
48 ADC_GPIO_PB1N = 0x02,
49 ADC_GPIO_PB2N = 0x03,
50 ADC_GPIO_PB3N = 0x04,
51 ADC_GPIO_PB4N = 0x05,
52 ADC_GPIO_PB5N = 0x06,
53 ADC_GPIO_PB6N = 0x07,
54 ADC_GPIO_PB7N = 0x08,
55 ADC_GPIO_PD0N = 0x09,
56 ADC_GPIO_PD1N = 0x0a,
57 ADC_TEMSENSORN_EE = 0x0e,
58 GND = 0x0f,
59 } adc_input_nch_e;
60 typedef enum {
61 NOINPUTP = 0,
62 ADC_GPIO_PB0P = 0x01,
63 ADC_GPIO_PB1P = 0x02,
64 ADC_GPIO_PB2P = 0x03,
65 ADC_GPIO_PB3P = 0x04,
66 ADC_GPIO_PB4P = 0x05,
67 ADC_GPIO_PB5P = 0x06,
68 ADC_GPIO_PB6P = 0x07,
69 ADC_GPIO_PB7P = 0x08,
70 ADC_GPIO_PD0P = 0x09,
71 ADC_GPIO_PD1P = 0x0a,
72 ADC_TEMSENSORP_EE = 0x0e,
73 ADC_VBAT = 0x0f,
74 } adc_input_pch_e;
75 /**
76 * @brief adc input pin type
77 * | | |
78 * | :-------- | :----------- |
79 * | <15:12> | <11:0> |
80 * |adc channel| gpio pin |
81 */
82 typedef enum {
83 ADC_GPIO_PB0 = GPIO_PB0 | (0x1 << 12),
84 ADC_GPIO_PB1 = GPIO_PB1 | (0x2 << 12),
85 ADC_GPIO_PB2 = GPIO_PB2 | (0x3 << 12),
86 ADC_GPIO_PB3 = GPIO_PB3 | (0x4 << 12),
87 ADC_GPIO_PB4 = GPIO_PB4 | (0x5 << 12),
88 ADC_GPIO_PB5 = GPIO_PB5 | (0x6 << 12),
89 ADC_GPIO_PB6 = GPIO_PB6 | (0x7 << 12),
90 ADC_GPIO_PB7 = GPIO_PB7 | (0x8 << 12),
91 ADC_GPIO_PD0 = GPIO_PD0 | (0x9 << 12),
92 ADC_GPIO_PD1 = GPIO_PD1 | (0xa << 12),
93 } adc_input_pin_def_e;
94 typedef enum {
95 ADC_GPIO_MODE,
96 ADC_VBAT_MODE,
97 } adc_input_pin_mode_e;
98
99 typedef enum {
100 ADC_RES8 = 0,
101 ADC_RES10 = 0x01,
102 ADC_RES12 = 0x02,
103 ADC_RES14 = 0x03,
104 } adc_res_e;
105
106 typedef enum {
107 ADC_SAMPLE_CYC_3,
108 ADC_SAMPLE_CYC_6,
109 ADC_SAMPLE_CYC_9,
110 ADC_SAMPLE_CYC_12,
111 ADC_SAMPLE_CYC_15,
112 ADC_SAMPLE_CYC_18,
113 ADC_SAMPLE_CYC_21,
114 ADC_SAMPLE_CYC_24,
115 ADC_SAMPLE_CYC_27,
116 ADC_SAMPLE_CYC_30,
117 ADC_SAMPLE_CYC_33,
118 ADC_SAMPLE_CYC_36,
119 ADC_SAMPLE_CYC_39,
120 ADC_SAMPLE_CYC_42,
121 ADC_SAMPLE_CYC_45,
122 ADC_SAMPLE_CYC_48,
123 } adc_sample_cycle_e;
124
125 typedef enum {
126 ADC_SAMPLE_FREQ_23K,
127 ADC_SAMPLE_FREQ_48K,
128 ADC_SAMPLE_FREQ_96K,
129 } adc_sample_freq_e;
130
131 typedef enum {
132 ADC_MISC_CHN = BIT(2),
133 } adc_chn_e;
134
135 typedef enum {
136 ADC_PRESCALE_1 = 0x00,
137 ADC_PRESCALE_1F8 = 0x03,
138 } adc_pre_scale_e;
139 enum {
140 ADC_MAX_STATE_NUM = 0x02,
141 };
142
143 /**
144 * @brief This function open sar_adc power.
145 * @return none.
146 */
adc_power_on(void)147 static inline void adc_power_on(void)
148 {
149 analog_write_reg8(areg_adc_pga_ctrl, (analog_read_reg8(areg_adc_pga_ctrl) & (~FLD_SAR_ADC_POWER_DOWN)));
150 }
151 /**
152 * @brief This function close sar_adc power.
153 * @return none
154 */
adc_power_off(void)155 static inline void adc_power_off(void)
156 {
157 analog_write_reg8(areg_adc_pga_ctrl, (analog_read_reg8(areg_adc_pga_ctrl) | FLD_SAR_ADC_POWER_DOWN));
158 }
159 /**
160 * @brief This function reset adc module
161 * @return none
162 */
adc_reset(void)163 static inline void adc_reset(void)
164 {
165 reg_rst3 &= (~FLD_RST3_SARADC);
166 reg_rst3 |= FLD_RST3_SARADC;
167 }
168 /**
169 * @brief This function serves to enable adc sample fifo.
170 * @return none
171 */
adc_fifo_enable(void)172 static inline void adc_fifo_enable(void)
173 {
174 reg_i2s_cfg2 &= (~FLD_AUDIO_FIFO1_RST);
175 }
176 /**
177 * @brief This function serves to disable adc sample fifo.
178 * @return none
179 */
adc_fifo_disable(void)180 static inline void adc_fifo_disable(void)
181 {
182 reg_i2s_cfg2 |= FLD_AUDIO_FIFO1_RST;
183 }
184 /**
185 * @brief This function enable adc source clock: Pad_24M
186 * @return none
187 */
adc_clk_en(void)188 static inline void adc_clk_en(void)
189 {
190 analog_write_reg8(areg_adc_clk_setting, analog_read_reg8(areg_adc_clk_setting) | FLD_CLK_24M_TO_SAR_EN);
191 }
192 /**
193 * @brief This function disable adc source clock: Pad_24M
194 * @return none
195 */
adc_clk_dis(void)196 static inline void adc_clk_dis(void)
197 {
198 analog_write_reg8(areg_adc_clk_setting, analog_read_reg8(areg_adc_clk_setting) & (~FLD_CLK_24M_TO_SAR_EN));
199 }
200 /**
201 * @brief This function sets adc sample clk. adc sample clk = 24M/(1+div) div: 0~7.
202 * @param[in] div - the divider of adc sample clock.
203 * @return none
204 */
adc_set_clk(unsigned char div)205 static inline void adc_set_clk(unsigned char div)
206 {
207 analog_write_reg8(areg_adc_sample_clk_div, div);
208 }
209 /**
210 * @brief This function sets ADC input channel as misc channel.
211 * @return none
212 */
adc_set_m_chn_en(void)213 static inline void adc_set_m_chn_en(void)
214 {
215 analog_write_reg8(areg_adc_chn_en, FLD_ADC_CHN_EN_M | (ADC_MAX_STATE_NUM << 4));
216 }
217 /**
218 * @brief This function serves to set resolution.
219 * @param[in] res - enum variable of ADC resolution.
220 * @return none
221 */
adc_set_resolution(adc_res_e res)222 static inline void adc_set_resolution(adc_res_e res)
223 {
224 analog_write_reg8(areg_adc_res_m, (analog_read_reg8(areg_adc_res_m) & (~FLD_ADC_RES_M)) | res);
225 }
226
227 /**
228 * @brief This function serves to set ADC sample time (the number of adc clocks for sample cycles)
229 * for the misc channel.
230 * @param[in] sample_cycle - enum variable of adc sample cycles.
231 * @return none
232 */
adc_set_tsample_cycle(adc_sample_cycle_e sample_cycle)233 static inline void adc_set_tsample_cycle(adc_sample_cycle_e sample_cycle)
234 {
235 // ana_ee<7:4> is reserved, so no need care its value
236 analog_write_reg8(areg_adc_tsmaple_m, sample_cycle); // optimize, <7:4> not cared
237 }
238 /**
239 * @brief This function open temperature sensor power.
240 * @return none
241 */
adc_temp_sensor_power_on(void)242 static inline void adc_temp_sensor_power_on(void)
243 {
244 analog_write_reg8(areg_temp_sensor_ctrl,
245 (analog_read_reg8(areg_temp_sensor_ctrl) & (~FLD_TEMP_SENSOR_POWER_DOWN)));
246 }
247 /**
248 * @brief This function close temperature sensor power.
249 * @return none
250 */
adc_temp_sensor_power_off(void)251 static inline void adc_temp_sensor_power_off(void)
252 {
253 analog_write_reg8(areg_temp_sensor_ctrl, (analog_read_reg8(areg_temp_sensor_ctrl) | FLD_TEMP_SENSOR_POWER_DOWN));
254 }
255 /**
256 * @brief This function serves to set input channel in differential_mode.
257 * @param[in] p_ain - enum variable of ADC analog positive input channel.
258 * @param[in] n_ain - enum variable of ADC analog negative input channel.
259 * @return none
260 */
adc_set_diff_input(adc_input_pch_e p_ain,adc_input_nch_e n_ain)261 static inline void adc_set_diff_input(adc_input_pch_e p_ain, adc_input_nch_e n_ain)
262 {
263 analog_write_reg8(areg_adc_res_m, analog_read_reg8(areg_adc_res_m) | FLD_ADC_EN_DIFF_CHN_M);
264 analog_write_reg8(areg_adc_ain_chn_misc, n_ain | (p_ain << 4));
265 }
266 /**
267 * @brief This function serves to set state and capture_state length.
268 * @param[in] r_max_mc - Value of length of "capture" state for MISC channel.
269 * @param[in] r_max_s - Value of length of "set" state for MISC channel.
270 * @return none
271 */
adc_set_state_length(unsigned short r_max_mc,unsigned char r_max_s)272 static inline void adc_set_state_length(unsigned short r_max_mc, unsigned char r_max_s)
273 {
274 analog_write_reg8(areg_r_max_mc, r_max_mc);
275 analog_write_reg8(areg_r_max_s, ((r_max_mc >> 8) << 6) | (r_max_s & FLD_R_MAX_S));
276 }
277 /**
278 * @brief This function serves to config adc_dma_chn channel.
279 * @param[in] chn - the DMA channel
280 * @return none
281 */
282 void adc_set_dma_config(dma_chn_e chn);
283 /**
284 * @brief This function serves to start sample with adc DMA channel.
285 * @param[in] adc_data_buf - the address of data buffer
286 * @param[in] data_byte_len - the length of data size by byte
287 * @return none
288 */
289 void adc_start_sample_dma(unsigned short *adc_data_buf, unsigned int data_byte_len);
290 /**
291 * @brief This function is used to set IO port for ADC supply or ADC IO port voltage sampling.
292 * @param[in] mode - ADC gpio pin sample mode
293 * @param[in] pin - adc_input_pin_def_e ADC input gpio pin
294 * @return none
295 */
296 void adc_pin_config(adc_input_pin_mode_e mode, adc_input_pin_def_e pin);
297 /**
298 * @brief This function is used to set two IO port configuration
299 * and set it as input channel of ADC difference IO port voltage sampling.
300 * @param[in] p_pin - enum variable of ADC analog positive input IO.
301 * @param[in] n_pin - enum variable of ADC analog negative input IO.
302 * @return none
303 */
304 void adc_set_diff_pin(adc_input_pin_def_e p_pin, adc_input_pin_def_e n_pin);
305 /**
306 * @brief This function serves to set the channel reference voltage.
307 * @param[in] v_ref - enum variable of ADC reference voltage.
308 * @return none
309 */
310 void adc_set_ref_voltage(adc_ref_vol_e v_ref);
311 /**
312 * @brief This function serves to set the sample frequency.
313 * @param[in] sample_freq - enum variable of ADC sample frequency.
314 * @return none
315 */
316 void adc_set_sample_rate(adc_sample_freq_e sample_freq);
317 /**
318 * @brief This function serves to set pre_scaling factor.
319 * @param[in] pre_scale - enum variable of ADC pre_scaling factor.
320 * @return none
321 */
322 void adc_set_scale_factor(adc_pre_scale_e pre_scale);
323 /**
324 * @brief This function servers to initialized ADC temperature sensor.
325 * When the reference voltage is set to 1.2V, and at the same time, the division factor is set to 1 the most accurate.
326 * @return none.
327 * @attention Temperature sensor suggested initial setting are Vref = 1.2V, pre_scale = 1.
328 * The user don't need to change it.
329 */
330 void adc_temperature_sample_init(void);
331 /**
332 * @brief This function serves to ADC gpio sample init.
333 * @param[in] pin - adc_input_pin_def_e ADC input gpio pin
334 * @param[in] v_ref - enum variable of ADC reference voltage.
335 * @param[in] pre_scale - enum variable of ADC pre_scaling factor.
336 * @param[in] sample_freq - enum variable of ADC sample frequency.
337 * @return none
338 * @attention gpio voltage sample suggested initial setting are Vref = 1.2V, pre_scale = 1/8.
339 * 0.9V Vref pre_scale must be 1.
340 * The sampling range are as follows:
341 * Vref pre_scale sampling range
342 * 1.2V 1 0 ~ 1.1V (suggest)
343 * 1.2V 1/8 0 ~ 3.5V (suggest)
344 * 0.9V 1 0 ~ 0.8V
345 */
346 void adc_gpio_sample_init(adc_input_pin_def_e pin, adc_ref_vol_e v_ref, adc_pre_scale_e pre_scale,
347 adc_sample_freq_e sample_freq);
348
349 /**
350 * @brief This function servers to set ADC configuration for ADC supply voltage sampling.
351 * @return none
352 * @attention battery voltage sample suggested initial setting are Vref = 1.2V, pre_scale = 1, vbat_div = 1/3.
353 * Which has higher accuracy, user don't need to change it.
354 * The battery voltage sample range is 1.8~3.5V,
355 * and must set sys_init with the mode for battery voltage less than 3.6V.
356 * For battery voltage > 3.6V, should take some external voltage divider.
357 */
358 void adc_battery_voltage_sample_init(void);
359 /**
360 * @brief This function serves to select Vbat voltage division factor
361 * @param[in] vbat_div - enum variable of Vbat division factor.
362 * @return none
363 */
364 void adc_set_vbat_divider(adc_vbat_div_e vbat_div);
365 /**
366 * @brief This function serves to ADC init.
367 * @param[in] v_ref - enum variable of ADC reference voltage.
368 * @param[in] pre_scale - enum variable of ADC pre_scaling factor.
369 * @param[in] sample_freq - enum variable of ADC sample frequency.
370 * @return none
371 * @attention Many features are configured in adc_init function. But some features
372 * such as adc_clk, resolution, tsample_cycle, we think better to set as default value,
373 * and user don't need to change them in most use cases.
374 */
375 void adc_init(adc_ref_vol_e v_ref, adc_pre_scale_e pre_scale, adc_sample_freq_e sample_freq);
376 /**
377 * @brief This function serves to start adc sample and get raw adc sample code.
378 * @param[in] sample_buffer - pointer to the buffer adc sample code need to store.
379 * @param[in] sample_num - the number of adc sample code.
380 * @return none
381 */
382 void adc_get_code_dma(unsigned short *sample_buffer, unsigned short sample_num);
383 /**
384 * @brief This function serves to directly get an adc sample code from analog registers.
385 * @return adc_code - the adc sample code.
386 */
387 unsigned short adc_get_code(void);
388 /**
389 * @brief This function serves to calculate voltage from adc sample code.
390 * @param[in] adc_code - the adc sample code.
391 * @return adc_vol_mv - the average value of adc voltage value.
392 */
393 unsigned short adc_calculate_voltage(unsigned short adc_code);
394 /**
395 * @brief This function serves to calculate temperature from temperature sensor adc sample code.
396 * @param[in] adc_code - the temperature sensor adc sample code.
397 * @return adc_temp_value - the of temperature value.
398 * attention Temperature and adc_code are linearly related.
399 * We test four chips between -40~130 (Celsius) and got an average ratio:
400 * Temp = 564 - ((adc_code * 819)>>13),when Vref = 1.2V, pre_scale = 1.
401 */
402 unsigned short adc_calculate_temperature(unsigned short adc_code);
403