1 /*
2 * Copyright (C) 2021 Alibaba Group Holding Limited
3 */
4
5 #include <stdint.h>
6 #include <errno.h>
7 #include <stdbool.h>
8 #include <aos/kernel.h>
9 #include <aos/list.h>
10 #include <aos/adc.h>
11 #include <aos/adc_core.h>
12
13 #define AOS_ADC_CHECK_NULL(x) \
14 do { \
15 if ((x) == NULL) { \
16 return -EINVAL; \
17 } \
18 } while (0)
19
aos_adc_get(aos_adc_ref_t * ref,uint32_t id)20 aos_status_t aos_adc_get(aos_adc_ref_t *ref, uint32_t id)
21 {
22 AOS_ADC_CHECK_NULL(ref);
23
24 return aos_dev_get(ref, AOS_DEV_TYPE_ADC, id);
25 }
26
aos_adc_put(aos_adc_ref_t * ref)27 void aos_adc_put(aos_adc_ref_t *ref)
28 {
29 if (ref == NULL)
30 return;
31
32 aos_dev_put(ref);
33 }
34
aos_adc_set_sample_time(aos_adc_ref_t * ref,int32_t channel,uint32_t time)35 aos_status_t aos_adc_set_sample_time(aos_adc_ref_t *ref, int32_t channel, uint32_t time)
36 {
37 aos_status_t ret;
38 aos_adc_t *adc;
39
40 AOS_ADC_CHECK_NULL(ref);
41 adc = aos_container_of(ref->dev, aos_adc_t, dev);
42 if (adc->ops->set_sample_time == NULL)
43 return -ENOTSUP;
44
45 aos_dev_lock(ref->dev);
46 /* Convert time(unit:us) into the number of adc clock cycle. */
47 ret = adc->ops->set_sample_time(adc, channel, (time * adc->freq) / 1000000U);
48 aos_dev_unlock(ref->dev);
49 return ret;
50 }
51
aos_adc_set_mode(aos_adc_ref_t * ref,aos_adc_mode_t mode)52 aos_status_t aos_adc_set_mode(aos_adc_ref_t *ref, aos_adc_mode_t mode)
53 {
54 aos_status_t ret;
55 aos_adc_t *adc;
56
57 AOS_ADC_CHECK_NULL(ref);
58 adc = aos_container_of(ref->dev, aos_adc_t, dev);
59 if (adc->ops->set_mode == NULL)
60 return -ENOTSUP;
61
62 aos_dev_lock(ref->dev);
63 ret = adc->ops->set_mode(adc, mode);
64 aos_dev_unlock(ref->dev);
65 return ret;
66 }
67
aos_adc_get_resolution(aos_adc_ref_t * ref,uint32_t * resolution)68 aos_status_t aos_adc_get_resolution(aos_adc_ref_t *ref, uint32_t *resolution)
69 {
70 aos_adc_t *adc;
71
72 AOS_ADC_CHECK_NULL(ref);
73 AOS_ADC_CHECK_NULL(resolution);
74
75 adc = aos_container_of(ref->dev, aos_adc_t, dev);
76 AOS_ADC_CHECK_NULL(adc);
77 *resolution = adc->resolution;
78
79 return 0;
80 }
81
aos_adc_get_range(aos_adc_ref_t * ref,int32_t channel,uint32_t * range)82 aos_status_t aos_adc_get_range(aos_adc_ref_t *ref, int32_t channel, uint32_t *range)
83 {
84 aos_status_t ret;
85 aos_adc_t *adc;
86
87 AOS_ADC_CHECK_NULL(ref);
88 AOS_ADC_CHECK_NULL(range);
89
90 adc = aos_container_of(ref->dev, aos_adc_t, dev);
91 AOS_ADC_CHECK_NULL(adc);
92 if (adc->ops->get_range == NULL)
93 return -ENOTSUP;
94
95 aos_dev_lock(ref->dev);
96 ret = adc->ops->get_range(adc, channel, range);
97 aos_dev_unlock(ref->dev);
98 return ret;
99 }
100
aos_adc_read(aos_adc_ref_t * ref,int32_t channel,int32_t * data)101 aos_status_t aos_adc_read(aos_adc_ref_t *ref, int32_t channel, int32_t *data)
102 {
103 aos_status_t ret;
104 aos_adc_t *adc;
105
106 AOS_ADC_CHECK_NULL(ref);
107 AOS_ADC_CHECK_NULL(data);
108
109 adc = aos_container_of(ref->dev, aos_adc_t, dev);
110 AOS_ADC_CHECK_NULL(adc);
111
112 aos_dev_lock(ref->dev);
113 ret = adc->ops->read(adc, channel, data);
114 aos_dev_unlock(ref->dev);
115 return ret;
116 }
117
aos_adc_read_voltage(aos_adc_ref_t * ref,int32_t channel,int32_t * data)118 aos_status_t aos_adc_read_voltage(aos_adc_ref_t *ref, int32_t channel, int32_t *data)
119 {
120 aos_status_t ret;
121 aos_adc_t *adc;
122
123 AOS_ADC_CHECK_NULL(ref);
124 AOS_ADC_CHECK_NULL(data);
125
126 adc = aos_container_of(ref->dev, aos_adc_t, dev);
127 AOS_ADC_CHECK_NULL(adc);
128
129 aos_dev_lock(ref->dev);
130 ret = adc->ops->read_voltage(adc, channel, data);
131 aos_dev_unlock(ref->dev);
132 return ret;
133 }
134
dev_adc_unregister(aos_dev_t * dev)135 static void dev_adc_unregister(aos_dev_t *dev)
136 {
137 aos_adc_t *adc = aos_container_of(dev, aos_adc_t, dev);
138
139 if (adc->ops->unregister)
140 adc->ops->unregister(adc);
141 }
142
dev_adc_get(aos_dev_ref_t * ref)143 static aos_status_t dev_adc_get(aos_dev_ref_t *ref)
144 {
145 aos_adc_t *adc = aos_container_of(ref->dev, aos_adc_t, dev);
146
147 if (!aos_dev_ref_is_first(ref))
148 return 0;
149
150 return adc->ops->startup(adc);
151 }
152
dev_adc_put(aos_dev_ref_t * ref)153 static void dev_adc_put(aos_dev_ref_t *ref)
154 {
155 aos_adc_t *adc = aos_container_of(ref->dev, aos_adc_t, dev);
156
157 if (!aos_dev_ref_is_last(ref))
158 return;
159
160 adc->ops->shutdown(adc);
161 }
162
163 static const aos_dev_ops_t dev_adc_ops = {
164 .unregister = dev_adc_unregister,
165 .get = dev_adc_get,
166 .put = dev_adc_put,
167 };
168
aos_adc_register(aos_adc_t * adc)169 aos_status_t aos_adc_register(aos_adc_t *adc)
170 {
171 aos_status_t ret;
172
173 AOS_ADC_CHECK_NULL(adc);
174
175 /* startup/shutdown/read must be set. */
176 if ((adc->ops == NULL) || (adc->ops->startup == NULL) ||
177 (adc->ops->shutdown == NULL) || (adc->ops->read == NULL) ||
178 (adc->ops->read_voltage == NULL))
179 return -EINVAL;
180
181 if ((adc->resolution == 0) || (adc->freq == 0))
182 return -EINVAL;
183
184 adc->dev.type = AOS_DEV_TYPE_ADC;
185 adc->dev.ops = &dev_adc_ops;
186 #ifdef AOS_COMP_VFS
187 /* TODO: support vfs ops. */
188 adc->dev.vfs_helper.name[0] = '\0';
189 adc->dev.vfs_helper.ops = NULL;
190 #endif
191
192 return aos_dev_register(&(adc->dev));
193 }
194
aos_adc_unregister(uint32_t id)195 aos_status_t aos_adc_unregister(uint32_t id)
196 {
197 return aos_dev_unregister(AOS_DEV_TYPE_ADC, id);
198 }
199