1 /**
2 *****************************************************************************
3 * @file cmem7_adc.c
4 *
5 * @brief CMEM7 ADC source file
6 *
7 *
8 * @version V1.0
9 * @date 3. September 2013
10 *
11 * @note
12 *
13 *****************************************************************************
14 * @attention
15 *
16 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
17 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
18 * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
19 * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
20 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
21 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
22 *
23 * <h2><center>© COPYRIGHT 2013 Capital-micro </center></h2>
24 *****************************************************************************
25 */
26
27 #include "cmem7_adc.h"
28 #include "cmem7.h"
29
30 #define ADC_SYSTEM_MODE_IDLE 0
31
adc_IsMultiChannel(uint32_t channel)32 static BOOL adc_IsMultiChannel(uint32_t channel) {
33 uint32_t i = 0;
34
35 for (i = 0; channel != 0; i++) {
36 channel &= (channel - 1);
37 }
38
39 return ((i > 1) ? TRUE : FALSE);
40 }
41
adc_GetChannel(uint32_t channel)42 static uint8_t adc_GetChannel(uint32_t channel) {
43 uint32_t i = 0;
44
45 for (i = 0; channel > 1; i++) {
46 channel >>= 1;
47 }
48
49 return i;
50 }
51
adc_Reset(uint8_t adc,BOOL enable)52 static void adc_Reset(uint8_t adc, BOOL enable) {
53 if (adc == ADC_PERIPH_1) {
54 ADC->POWERDOWN_RESET_b.POWERDOWN_ADC1 = TRUE;
55 ADC->POWERDOWN_RESET_b.RESET_ADC1 = TRUE;
56 udelay(8000);
57 if (enable) {
58 ADC->POWERDOWN_RESET_b.POWERDOWN_ADC1 = FALSE;
59 ADC->POWERDOWN_RESET_b.RESET_ADC1 = FALSE;
60 udelay(8000);
61 }
62 } else {
63 ADC->POWERDOWN_RESET_b.POWERDOWN_ADC2 = TRUE;
64 ADC->POWERDOWN_RESET_b.RESET_ADC2 = TRUE;
65 udelay(8000);
66 if (enable) {
67 ADC->POWERDOWN_RESET_b.POWERDOWN_ADC2 = FALSE;
68 ADC->POWERDOWN_RESET_b.RESET_ADC2 = FALSE;
69 udelay(8000);
70 }
71 }
72 }
73
ADC_Init(ADC_InitTypeDef * init)74 void ADC_Init(ADC_InitTypeDef* init) {
75 assert_param(init);
76 assert_param(IS_ADC_PHASE_CTRL(init->ADC_PhaseCtrl));
77 assert_param(IS_ADC_VSEN(init->ADC_VsenSelection));
78
79 SOFT_RESET->SOFTRST_b.ADC_n = 0;
80 SOFT_RESET->SOFTRST_b.ADC_n = 1;
81
82 ADC->CFG0_b.PHASE_CTRL = init->ADC_PhaseCtrl;
83 ADC->CFG0_b.VSEN = init->ADC_VsenSelection;
84 }
85
ADC_Enable(uint8_t adc,BOOL enable)86 void ADC_Enable(uint8_t adc, BOOL enable) {
87 assert_param(IS_ADC_ALL_PERIPH(adc));
88
89 adc_Reset(adc, enable);
90 }
91
ADC_EnableInt(uint32_t Int,BOOL enable)92 void ADC_EnableInt(uint32_t Int, BOOL enable) {
93 assert_param(IS_ADC_INT(Int));
94
95 if (enable) {
96 ADC->INT_MASK &= ~Int;
97 } else {
98 ADC->INT_MASK |= Int;
99 }
100 }
101
ADC_GetIntStatus(uint32_t Int)102 BOOL ADC_GetIntStatus(uint32_t Int) {
103 assert_param(IS_ADC_INT(Int));
104
105 if (0 != (ADC->INT_STATUS & Int)) {
106 return TRUE;
107 }
108
109 return FALSE;
110 }
111
ADC_ClearInt(uint32_t Int)112 void ADC_ClearInt(uint32_t Int) {
113 assert_param(IS_ADC_INT(Int));
114
115 ADC->INT_STATUS = Int;
116 }
117
ADC_StartConversion(uint8_t adc,uint8_t convMode,uint32_t channel)118 BOOL ADC_StartConversion(uint8_t adc, uint8_t convMode, uint32_t channel) {
119 assert_param(IS_ADC_ALL_PERIPH(adc));
120 assert_param(IS_ADC_CONVERSION(convMode));
121
122 if (adc == ADC_PERIPH_1) {
123 assert_param(IS_ADC1_CHANNEL(channel));
124 if (ADC->BUSY_b.ADC1_BUSY) {
125 return FALSE;
126 }
127
128 if (adc_IsMultiChannel(channel)) {
129 ADC->CFG_ADC1_b.SYSTEM_MODE = ADC_SYSTEM_MODE_SINGLE_CONV;
130 ADC->CFG_ADC1_b.MULTI_CHANNEL_BIT = channel;
131 ADC->CFG_ADC1_b.MULTI_CHANNEL_CONTINUE_SCAN =
132 (convMode == ADC_SYSTEM_MODE_CONTINUOUS_CONV) ? 1 : 0;
133 } else {
134 ADC->CFG_ADC1_b.SYSTEM_MODE = convMode;
135
136 if (convMode == ADC_SYSTEM_MODE_CONTINUOUS_CONV) {
137 ADC->CFG_ADC1_b.CHANNEL_SEL = adc_GetChannel(channel);
138 } else {
139 ADC->CFG_ADC1_b.MULTI_CHANNEL_BIT = channel;
140 ADC->CFG_ADC1_b.MULTI_CHANNEL_CONTINUE_SCAN = 0;
141 }
142 }
143
144 ADC->ADC1_START_b.EN = TRUE;
145 } else {
146 assert_param(IS_ADC2_CHANNEL(channel));
147 if (ADC->BUSY_b.ADC2_BUSY) {
148 return FALSE;
149 }
150
151 if (adc_IsMultiChannel(channel)) {
152 ADC->CFG_ADC2_b.SYSTEM_MODE = ADC_SYSTEM_MODE_SINGLE_CONV;
153 ADC->CFG_ADC2_b.MULTI_CHANNEL_BIT = channel;
154 ADC->CFG_ADC2_b.MULTI_CHANNEL_CONTINUE_SCAN =
155 (convMode == ADC_SYSTEM_MODE_CONTINUOUS_CONV) ? 1 : 0;
156 } else {
157 ADC->CFG_ADC2_b.SYSTEM_MODE = convMode;
158
159 if (convMode == ADC_SYSTEM_MODE_CONTINUOUS_CONV) {
160 ADC->CFG_ADC2_b.CHANNEL_SEL = adc_GetChannel(channel);
161 } else {
162 ADC->CFG_ADC2_b.MULTI_CHANNEL_BIT = channel;
163 ADC->CFG_ADC2_b.MULTI_CHANNEL_CONTINUE_SCAN = 0;
164 }
165 }
166
167 ADC->ADC2_START_b.EN = TRUE;
168 }
169
170 return TRUE;
171 }
172
ADC_StartCalibration(uint8_t adc,uint8_t calibration)173 BOOL ADC_StartCalibration(uint8_t adc, uint8_t calibration) {
174 assert_param(IS_ADC_ALL_PERIPH(adc));
175 assert_param(IS_ADC_CALIBRATION(calibration));
176
177 if (adc == ADC_PERIPH_1) {
178 if (ADC->BUSY_b.ADC1_BUSY) {
179 return FALSE;
180 }
181
182 ADC->CFG_ADC1_b.SYSTEM_MODE = calibration;
183 ADC->ADC1_START_b.EN = TRUE;
184 } else {
185 if (ADC->BUSY_b.ADC2_BUSY) {
186 return FALSE;
187 }
188
189 ADC->CFG_ADC2_b.SYSTEM_MODE = calibration;
190 ADC->ADC2_START_b.EN = TRUE;
191 }
192
193 return TRUE;
194 }
195
ADC_Stop(uint8_t adc)196 void ADC_Stop(uint8_t adc) {
197 assert_param(IS_ADC_ALL_PERIPH(adc));
198
199 if (adc == ADC_PERIPH_1) {
200 if (IS_ADC_CONVERSION(ADC->CFG_ADC1_b.SYSTEM_MODE)) {
201 ADC->ADC1_STOP_b.EN = TRUE;
202 }
203 while (ADC->BUSY_b.ADC1_BUSY) ;
204
205 ADC->ADC1_FIFO_CLEAR_b.CLEAR = TRUE;
206 //udelay(1000);
207 ADC->ADC1_FIFO_CLEAR_b.CLEAR = FALSE;
208 } else {
209 if (IS_ADC_CONVERSION(ADC->CFG_ADC2_b.SYSTEM_MODE)) {
210 ADC->ADC2_STOP_b.EN = TRUE;
211 }
212 while (ADC->BUSY_b.ADC2_BUSY) ;
213
214 ADC->ADC2_FIFO_CLEAR_b.CLEAR = TRUE;
215 //udelay(1000);
216 ADC->ADC2_FIFO_CLEAR_b.CLEAR = FALSE;
217 }
218 }
219
ADC_IsBusy(uint8_t adc)220 BOOL ADC_IsBusy(uint8_t adc) {
221 assert_param(IS_ADC_ALL_PERIPH(adc));
222
223 if (adc == ADC_PERIPH_1) {
224 if (ADC->BUSY_b.ADC1_BUSY) {
225 return TRUE;
226 }
227 } else {
228 if (ADC->BUSY_b.ADC2_BUSY) {
229 return TRUE;
230 }
231 }
232
233 return FALSE;
234 }
235
236 /* return value is actual read data size */
ADC_Read(uint8_t adc,uint8_t size,ADC_Data * data)237 uint8_t ADC_Read(uint8_t adc, uint8_t size, ADC_Data* data) {
238 uint8_t count = 0;
239 uint8_t sysMode;
240 uint32_t tmp = 0;
241 assert_param(IS_ADC_ALL_PERIPH(adc));
242 assert_param(data);
243
244 if (adc == ADC_PERIPH_1) {
245 sysMode = ADC->CFG_ADC1_b.SYSTEM_MODE;
246 } else {
247 sysMode = ADC->CFG_ADC2_b.SYSTEM_MODE;
248 }
249
250 if ((sysMode == ADC_SYSTEM_MODE_SINGLE_CONV) ||
251 (sysMode == ADC_SYSTEM_MODE_CONTINUOUS_CONV)) {
252 while (count < size) {
253 if (adc == ADC_PERIPH_1) {
254 if (ADC->STATUS_b.ADC1_READ_EMPTY) {
255 break;
256 }
257
258 tmp = ADC->ADC1_FIFO_READ;
259 (data + count)->channel = 1 << ((tmp&0xf000) >> 12);
260 (data + count++)->data = (tmp & 0xfff);
261 } else {
262 if (ADC->STATUS_b.ADC2_READ_EMPTY) {
263 break;
264 }
265 tmp = ADC->ADC2_FIFO_READ;
266 (data + count)->channel = 1 << ((tmp&0xf000) >> 12);
267 (data + count++)->data = (tmp & 0xfff);
268 }
269 }
270 } else if (sysMode == ADC_CALIBRATION_OFFSET) {
271 if (adc == ADC_PERIPH_1) {
272 if (!ADC->BUSY_b.ADC1_BUSY) {
273 (data + count)->channel = ADC_CHANNEL_CALIBRATION;
274 (data + count++)->data = ADC->ADC1_OUT_OFFSET_CALIBRATION;
275 }
276 } else {
277 if (!ADC->BUSY_b.ADC2_BUSY) {
278 (data + count)->channel = ADC_CHANNEL_CALIBRATION;
279 (data + count++)->data = ADC->ADC2_OUT_OFFSET_CALIBRATION;
280 }
281 }
282 } else if (sysMode == ADC_CALIBRATION_NEGTIVE_GAIN) {
283 if (adc == ADC_PERIPH_1) {
284 if (!ADC->BUSY_b.ADC1_BUSY) {
285 (data + count)->channel = ADC_CHANNEL_CALIBRATION;
286 (data + count++)->data = ADC->ADC1_OUT_NEGTIVE_GAIN_CALIBRATION;
287 }
288 } else {
289 if (!ADC->BUSY_b.ADC2_BUSY) {
290 (data + count)->channel = ADC_CHANNEL_CALIBRATION;
291 (data + count++)->data = ADC->ADC2_OUT_NEGTIVE_GAIN_CALIBRATION;
292 }
293 }
294 } else {
295 if (adc == ADC_PERIPH_1) {
296 if (!ADC->BUSY_b.ADC1_BUSY) {
297 (data + count)->channel = ADC_CHANNEL_CALIBRATION;
298 (data + count++)->data = ADC->ADC1_OUT_POSITIVE_GAIN_CALIBRATION;
299 }
300 } else {
301 if (!ADC->BUSY_b.ADC2_BUSY) {
302 (data + count)->channel = ADC_CHANNEL_CALIBRATION;
303 (data + count++)->data = ADC->ADC2_OUT_POSITIVE_GAIN_CALIBRATION;
304 }
305 }
306 }
307
308 return count;
309 }
310