1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include <drv/adc.h>
6 #include <aos/adc_csi.h>
7 #include "objects.h"
8 #include "PinNames.h"
9 #include "pinmap.h"
10
11 static const PinMap CSI_PinMap_ADC[] = {
12 { PB_4, ADC_CH0, 0 },
13 { PB_5, ADC_CH1, 0 },
14 { PB_6, ADC_CH2, 0 },
15 { PB_7, ADC_CH3, 0 },
16 { PB_1, ADC_CH4, 0 },
17 { PB_2, ADC_CH5, 0 },
18 { PB_3, ADC_CH6, 0 },
19 { VBAT_MEAS, ADC_CH7, 0 },
20 { NC, NC, 0 }
21 };
22
23 static uint16_t rtl872xd_adc_offset;
24 static uint16_t rtl872xd_adc_gain;
25
csi_adc_init(csi_adc_t * adc,uint32_t idx)26 csi_error_t csi_adc_init(csi_adc_t *adc, uint32_t idx)
27 {
28 if (!adc)
29 return CSI_ERROR;
30
31 adc->priv = (ADC_InitTypeDef *)malloc(sizeof(ADC_InitTypeDef));
32 ADC_InitTypeDef *ADC_InitStruct = (ADC_InitTypeDef *)adc->priv;
33
34 adc->dev.idx = idx;
35
36 /* Initialize ADC */
37 ADC_StructInit(ADC_InitStruct);
38 ADC_Init(ADC_InitStruct);
39 return CSI_OK;
40 }
41
csi_adc_uninit(csi_adc_t * adc)42 void csi_adc_uninit(csi_adc_t *adc)
43 {
44 /* Clear ADC Status */
45 ADC_INTClear();
46 /* Disable ADC */
47 ADC_Cmd(DISABLE);
48
49 if (adc->priv) {
50 free(adc->priv);
51 adc->priv = NULL;
52 }
53 }
54
csi_adc_start(csi_adc_t * adc)55 csi_error_t csi_adc_start(csi_adc_t *adc)
56 {
57 ADC_Cmd(ENABLE);
58 return CSI_OK;
59 }
60
csi_adc_stop(csi_adc_t * adc)61 csi_error_t csi_adc_stop(csi_adc_t *adc)
62 {
63 ADC_Cmd(DISABLE);
64 return CSI_OK;
65 }
66
csi_adc_channel_enable(csi_adc_t * adc,uint8_t ch_id,bool is_enable)67 csi_error_t csi_adc_channel_enable(csi_adc_t *adc, uint8_t ch_id, bool is_enable)
68 {
69 ADC_InitTypeDef *ADC_InitStruct = (ADC_InitTypeDef *)adc->priv;
70 uint32_t adc_idx;
71
72 if (ch_id != adc->dev.idx)
73 adc->dev.idx = ch_id;
74
75 adc_idx = CSI_PinMap_ADC[ch_id].peripheral;
76
77 ADC_InitStruct->ADC_CvlistLen = 0;
78 ADC_InitStruct->ADC_Cvlist[0] = adc_idx;
79 ADC_InitStruct->ADC_ChIDEn = is_enable; /* MSB 4bit is channel index*/
80 ADC_Init(ADC_InitStruct);
81 return CSI_OK;
82 }
83
csi_adc_sampling_time(csi_adc_t * adc,uint16_t clock_num)84 csi_error_t csi_adc_sampling_time(csi_adc_t *adc, uint16_t clock_num)
85 {
86 /* no need to set sampling time */
87 return CSI_OK;
88 }
89
csi_adc_channel_sampling_time(csi_adc_t * adc,uint8_t ch_id,uint16_t clock_num)90 csi_error_t csi_adc_channel_sampling_time(csi_adc_t *adc, uint8_t ch_id, uint16_t clock_num)
91 {
92 /* no need to set sampling time */
93 return CSI_OK;
94 }
95
csi_adc_continue_mode(csi_adc_t * adc,bool is_enable)96 csi_error_t csi_adc_continue_mode(csi_adc_t *adc, bool is_enable)
97 {
98 ADC_InitTypeDef *ADC_InitStruct = (ADC_InitTypeDef *)adc->priv;
99
100 if (is_enable) {
101 ADC_InitStruct->ADC_OpMode = ADC_AUTO_MODE;
102 ADC_Init(ADC_InitStruct);
103 }
104
105 return CSI_OK;
106 }
107
csi_adc_freq_div(csi_adc_t * adc,uint32_t div)108 uint32_t csi_adc_freq_div(csi_adc_t *adc, uint32_t div)
109 {
110 ADC_InitTypeDef *ADC_InitStruct = (ADC_InitTypeDef *)adc->priv;
111 uint32_t freq = 0;
112
113 switch (div) {
114 case 12:
115 ADC_InitStruct->ADC_ClkDiv = ADC_CLK_DIV_12;
116 freq = (uint32_t)(2000000 / 12);
117 break;
118 case 16:
119 ADC_InitStruct->ADC_ClkDiv = ADC_CLK_DIV_16;
120 freq = (uint32_t)(2000000 / 16);
121 break;
122 case 32:
123 ADC_InitStruct->ADC_ClkDiv = ADC_CLK_DIV_32;
124 freq = (uint32_t)(2000000 / 32);
125 break;
126 case 64:
127 ADC_InitStruct->ADC_ClkDiv = ADC_CLK_DIV_64;
128 freq = (uint32_t)(2000000 / 64);
129 break;
130 default:
131 ADC_InitStruct->ADC_ClkDiv = ADC_CLK_DIV_12;
132 freq = (uint32_t)(2000000 / 12);
133 break;
134 }
135
136 ADC_Init(ADC_InitStruct);
137 return freq;
138 }
139
AD2MV(int32_t ad,uint16_t offset,uint16_t gain)140 static int32_t AD2MV(int32_t ad, uint16_t offset, uint16_t gain)
141 {
142 return (int32_t)(((10 * ad) - offset) * 1000 / gain);
143 }
144
adc_get_offset_gain(uint16_t * offset,uint16_t * gain,uint8_t vbat)145 static void adc_get_offset_gain(uint16_t *offset, uint16_t *gain, uint8_t vbat)
146 {
147 uint8_t EfuseBuf[2];
148 uint32_t index;
149 uint32_t addressOffset;
150 uint32_t addressGain;
151
152 if (vbat) {
153 addressOffset = 0x1D4;
154 addressGain = 0x1D6;
155 } else {
156 addressOffset = 0x1D0;
157 addressGain = 0x1D2;
158 }
159
160 for (index = 0; index < 2; index++) {
161 EFUSERead8(0, addressOffset + index, EfuseBuf + index, L25EOUTVOLTAGE);
162 }
163 *offset = EfuseBuf[1] << 8 | EfuseBuf[0];
164
165 for (index = 0; index < 2; index++) {
166 EFUSERead8(0, addressGain + index, EfuseBuf + index, L25EOUTVOLTAGE);
167 }
168 *gain = EfuseBuf[1] << 8 | EfuseBuf[0];
169
170 if (*offset == 0xFFFF) {
171 if (vbat)
172 *offset = 0x9C4;
173 else
174 *offset = 0x9B0;
175 }
176
177 if (*gain == 0xFFFF) {
178 if (vbat)
179 *gain = 7860;
180 else
181 *gain = 0x2F12;
182 }
183 }
184
csi_adc_get_range(csi_adc_t * adc,uint8_t ch_id,uint32_t * range)185 csi_error_t csi_adc_get_range(csi_adc_t *adc, uint8_t ch_id, uint32_t *range)
186 {
187 if (ch_id < 4) {
188 *range = 3300; /*CH0~CH3: 3.3V*/
189 return CSI_OK;
190 } else if (ch_id < 7) {
191 *range = 1800; /*CH4~CH6: 1.8V*/
192 return CSI_OK;
193 } else if (ch_id == 7) {
194 *range = 5000; /*CH7: 5V*/
195 return CSI_OK;
196 } else {
197 return CSI_ERROR;
198 }
199 }
200
csi_adc_read(csi_adc_t * adc)201 int32_t csi_adc_read(csi_adc_t *adc)
202 {
203 int32_t value;
204 uint32_t data;
205
206 /* Clear FIFO */
207 ADC_ClearFIFO();
208
209 /* SW trigger to sample */
210 ADC_SWTrigCmd(ENABLE);
211 while (ADC_Readable() == 0)
212 ;
213 ADC_SWTrigCmd(DISABLE);
214
215 data = ADC_Read();
216 value = (int32_t)(data & BIT_MASK_DAT_GLOBAL);
217 return value;
218 }
219
csi_adc_read_voltage(csi_adc_t * adc)220 int32_t csi_adc_read_voltage(csi_adc_t *adc)
221 {
222 int32_t adc_data;
223
224 adc_data = csi_adc_read(adc);
225 return AD2MV(adc_data, rtl872xd_adc_offset, rtl872xd_adc_gain);
226 }
227
adc_csi_init(void)228 static int adc_csi_init(void)
229 {
230 csi_error_t ret;
231 static aos_adc_csi_t adc_csi_dev;
232
233 adc_get_offset_gain(&rtl872xd_adc_offset, &rtl872xd_adc_gain, 0);
234 if (rtl872xd_adc_gain == 0) {
235 printf("%s:%d: rtl872xd_adc_gain is 0\r\n", __func__, __LINE__);
236 return -1;
237 }
238
239 ret = csi_adc_init(&(adc_csi_dev.csi_adc), 0);
240 if (ret != CSI_OK) {
241 printf("%s:%d: csi_adc_init fail, ret:%d\r\n", __func__, __LINE__, ret);
242 return -1;
243 }
244
245 adc_csi_dev.aos_adc.dev.id = 0;
246 adc_csi_dev.aos_adc.resolution = 12;
247 adc_csi_dev.aos_adc.freq = 2000000 / 12;
248 return aos_adc_csi_register(&adc_csi_dev);
249 }
250
251 LEVEL1_DRIVER_ENTRY(adc_csi_init)
252