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>&copy; 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