1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 #include <stdio.h>
22 #include "mxc_device.h"
23 #include "mxc_errors.h"
24 #include "mxc_assert.h"
25 #include "mxc_sys.h"
26 #include "mxc_lock.h"
27 #include "adc.h"
28 #include "dma.h"
29 #include "adc_reva.h"
30 
31 #define MXC_CONVERSION_INTERRUPT 0x1
32 #define MXC_CONVERSION_REQ_INTERRUPT 0X2
33 #define MXC_MONITOR_INTERRUPT 0X4
34 #define MXC_CONVERSION_SPEED_6MHZ 5847
35 // Mask for all Interrupt Enable Fields
36 #define ADC_IE_MASK                                                      \
37     (MXC_F_ADC_REVA_INTR_DONE_IE | MXC_F_ADC_REVA_INTR_REF_READY_IE |    \
38      MXC_F_ADC_REVA_INTR_HI_LIMIT_IE | MXC_F_ADC_REVA_INTR_LO_LIMIT_IE | \
39      MXC_F_ADC_REVA_INTR_OVERFLOW_IE)
40 
41 #define ADC_IF_MASK                                                      \
42     (MXC_F_ADC_REVA_INTR_DONE_IF | MXC_F_ADC_REVA_INTR_REF_READY_IF |    \
43      MXC_F_ADC_REVA_INTR_HI_LIMIT_IF | MXC_F_ADC_REVA_INTR_LO_LIMIT_IF | \
44      MXC_F_ADC_REVA_INTR_OVERFLOW_IF)
45 
46 #define MXC_MONITOR_NUM 4
47 
48 static mxc_adc_monitor_req_t *states[MXC_MONITOR_NUM];
49 static mxc_adc_complete_cb_t async_callback;
50 static mxc_adc_conversion_req_t *async_req;
51 volatile uint8_t flag; //indicates  to irqhandler where to store data
52 
MXC_ADC_RevA_Init(mxc_adc_reva_regs_t * adc)53 int MXC_ADC_RevA_Init(mxc_adc_reva_regs_t *adc)
54 {
55     //set adc frequency to work at approximately 6 MHZ
56     //NOTE: cannot use RevA version because MCR registers must be set
57     MXC_ADC_SetConversionSpeed(MXC_CONVERSION_SPEED_6MHZ);
58     //clear adc reference ready interrupt flag
59     MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_REF_READY_IF);
60 
61     //turn on adc
62     adc->ctrl |= MXC_F_ADC_REVA_CTRL_PWR;
63     //turn on reference buffer power
64     adc->ctrl |= MXC_F_ADC_REVA_CTRL_REFBUF_PWR;
65 
66     //wait until hardware set adc_intr.ref_ready_if to 1
67     while (!(adc->intr & MXC_F_ADC_REVA_INTR_REF_READY_IF)) {}
68 
69     //clear adc reference ready interrupt flag
70     MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_REF_READY_IF);
71 
72     //set lock variables initially to NULL
73     async_callback = NULL;
74 
75     for (uint8_t i = 0; i < MXC_MONITOR_NUM; i++) {
76         states[i] = NULL;
77     }
78 
79     async_req = NULL;
80 
81     return E_NO_ERROR;
82 }
83 
MXC_ADC_RevA_Shutdown(mxc_adc_reva_regs_t * adc)84 int MXC_ADC_RevA_Shutdown(mxc_adc_reva_regs_t *adc)
85 {
86     // Disable ADC Power
87     adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_PWR;
88     // Disable Reference Buffer Power
89     adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_REFBUF_PWR;
90     // Disable ADC Clock
91     adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_CLK_EN;
92 
93     if (async_callback != NULL) {
94         MXC_FreeLock((uint32_t *)&async_callback);
95     }
96 
97     for (uint8_t i = 0; i < MXC_MONITOR_NUM; i++) {
98         if (states[i] != NULL) {
99             MXC_FreeLock((uint32_t *)&states[i]);
100         }
101     }
102 
103     if (async_req != NULL) {
104         MXC_FreeLock((uint32_t *)&async_req);
105     }
106 
107     return E_NO_ERROR;
108 }
109 
MXC_ADC_RevA_Busy(mxc_adc_reva_regs_t * adc)110 int MXC_ADC_RevA_Busy(mxc_adc_reva_regs_t *adc)
111 {
112     return (adc->status & MXC_F_ADC_REVA_STATUS_AFE_PWR_UP_ACTIVE) >>
113            MXC_F_ADC_REVA_STATUS_AFE_PWR_UP_ACTIVE_POS;
114 }
115 
MXC_ADC_RevA_EnableInt(mxc_adc_reva_regs_t * adc,uint32_t flags)116 void MXC_ADC_RevA_EnableInt(mxc_adc_reva_regs_t *adc, uint32_t flags)
117 {
118     adc->intr = ((adc->intr | flags) & ADC_IE_MASK);
119 }
120 
MXC_ADC_RevA_DisableInt(mxc_adc_reva_regs_t * adc,uint32_t flags)121 void MXC_ADC_RevA_DisableInt(mxc_adc_reva_regs_t *adc, uint32_t flags)
122 {
123     adc->intr &= ~((flags & ADC_IE_MASK) | ADC_IF_MASK);
124 }
125 
MXC_ADC_RevA_GetFlags(mxc_adc_reva_regs_t * adc)126 int MXC_ADC_RevA_GetFlags(mxc_adc_reva_regs_t *adc)
127 {
128     return (adc->intr & ADC_IF_MASK);
129 }
130 
MXC_ADC_RevA_ClearFlags(mxc_adc_reva_regs_t * adc,uint32_t flags)131 void MXC_ADC_RevA_ClearFlags(mxc_adc_reva_regs_t *adc, uint32_t flags)
132 {
133     // Write 1 to clear flags
134     adc->intr = (adc->intr & ADC_IE_MASK) | (flags & ADC_IF_MASK);
135 }
136 
MXC_ADC_RevA_SetConversionSpeed(mxc_adc_reva_regs_t * adc,uint32_t hz)137 int MXC_ADC_RevA_SetConversionSpeed(mxc_adc_reva_regs_t *adc, uint32_t hz)
138 {
139     //enable clock
140     adc->ctrl |= MXC_F_ADC_REVA_CTRL_CLK_EN;
141     return E_NO_ERROR;
142 }
143 
MXC_ADC_RevA_GetConversionSpeed(uint8_t divider)144 int MXC_ADC_RevA_GetConversionSpeed(uint8_t divider)
145 {
146     uint32_t adc_clock_freq = PeripheralClock / divider;
147     return adc_clock_freq / 1024;
148 }
149 
MXC_ADC_RevA_SetDataAlignment(mxc_adc_reva_regs_t * adc,int msbJustify)150 void MXC_ADC_RevA_SetDataAlignment(mxc_adc_reva_regs_t *adc, int msbJustify)
151 {
152     if (msbJustify) {
153         adc->ctrl |= MXC_F_ADC_REVA_CTRL_DATA_ALIGN;
154     } else {
155         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_DATA_ALIGN;
156     }
157 }
158 
MXC_ADC_RevA_SetExtScale(mxc_adc_reva_regs_t * adc,mxc_adc_scale_t scale)159 void MXC_ADC_RevA_SetExtScale(mxc_adc_reva_regs_t *adc, mxc_adc_scale_t scale)
160 {
161     //clear adc division bits
162     adc->ctrl &= ~(MXC_S_ADC_REVA_CTRL_ADC_DIVSEL_DIV4);
163 
164     switch (scale) {
165     case MXC_ADC_SCALE_2X: //.05 ,ref scale 1, adc_divsel 0, input scale 0
166         adc->ctrl |= MXC_F_ADC_REVA_CTRL_REF_SCALE;
167         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_SCALE;
168         break;
169 
170     case MXC_ADC_SCALE_1:
171         //input scale = 0, adc_divsel = 0, ref scale = 0
172         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_REF_SCALE;
173         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_SCALE;
174         break;
175 
176     case MXC_ADC_SCALE_2:
177         //input scale = 1, adc_divsel = 0, ref scale = 0
178         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_REF_SCALE;
179         adc->ctrl |= MXC_F_ADC_REVA_CTRL_SCALE;
180         break;
181 #if TARGET_NUM != 32650
182     case MXC_ADC_SCALE_3:
183         //input scale = 0, adc_divsel = 2, ref scale = 0
184         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_REF_SCALE;
185         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_SCALE;
186         adc->ctrl |= MXC_S_ADC_REVA_CTRL_ADC_DIVSEL_DIV3;
187         break;
188 
189     case MXC_ADC_SCALE_4:
190         //input scale = 1, adc_divsel = 0x1, ref scale = 0,
191         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_REF_SCALE;
192         adc->ctrl |= MXC_F_ADC_REVA_CTRL_SCALE;
193         adc->ctrl |= MXC_S_ADC_REVA_CTRL_ADC_DIVSEL_DIV2;
194         break;
195 
196     case MXC_ADC_SCALE_6:
197         //input scale = 1, adc_divsel = 0x2, ref scale = 0
198         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_REF_SCALE;
199         adc->ctrl |= MXC_F_ADC_REVA_CTRL_SCALE;
200         adc->ctrl |= MXC_S_ADC_REVA_CTRL_ADC_DIVSEL_DIV3;
201         break;
202 
203     case MXC_ADC_SCALE_8:
204         //input scale = 1, adc_divsel = 0x3, ref scale = 0
205         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_REF_SCALE;
206         adc->ctrl |= MXC_F_ADC_REVA_CTRL_SCALE;
207         adc->ctrl |= MXC_S_ADC_REVA_CTRL_ADC_DIVSEL_DIV4;
208         break;
209 #endif
210     default:
211         //input scale = 0, adc_divsel = 0, ref scale = 0
212         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_REF_SCALE;
213         adc->ctrl &= ~MXC_F_ADC_REVA_CTRL_SCALE;
214         break;
215     }
216 }
217 
MXC_ADC_RevA_EnableMonitor(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_t monitor)218 void MXC_ADC_RevA_EnableMonitor(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_t monitor)
219 {
220     MXC_ASSERT(monitor < MXC_MONITOR_NUM);
221 
222     // MAX32650 LO and HI limit enables are shifted by 1 bit
223 #if TARGET_NUM == 32650
224     ((mxc_adc_regs_t *)adc)->limit[monitor] |=
225         (MXC_F_ADC_LIMIT_CH_HI_LIMIT_EN | MXC_F_ADC_LIMIT_CH_LO_LIMIT_EN);
226 #else
227     adc->limit[monitor] |=
228         (MXC_F_ADC_REVA_LIMIT_CH_HI_LIMIT_EN | MXC_F_ADC_REVA_LIMIT_CH_LO_LIMIT_EN);
229 #endif
230 }
231 
MXC_ADC_RevA_DisableMonitor(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_t monitor)232 void MXC_ADC_RevA_DisableMonitor(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_t monitor)
233 {
234     MXC_ASSERT(monitor < MXC_MONITOR_NUM);
235 
236     // MAX32650 LO and HI limit enables are shifted by 1 bit
237 #if TARGET_NUM == 32650
238     ((mxc_adc_regs_t *)adc)->limit[monitor] &=
239         ~(MXC_F_ADC_LIMIT_CH_HI_LIMIT_EN | MXC_F_ADC_LIMIT_CH_LO_LIMIT_EN);
240 #else
241     adc->limit[monitor] &=
242         ~(MXC_F_ADC_REVA_LIMIT_CH_HI_LIMIT_EN | MXC_F_ADC_REVA_LIMIT_CH_LO_LIMIT_EN);
243 #endif
244 }
245 
MXC_ADC_RevA_SetMonitorHighThreshold(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_t monitor,uint32_t threshold)246 void MXC_ADC_RevA_SetMonitorHighThreshold(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_t monitor,
247                                           uint32_t threshold)
248 {
249     MXC_ASSERT(monitor < MXC_MONITOR_NUM);
250     //clear current high threshold
251     adc->limit[monitor] &= ~MXC_F_ADC_REVA_LIMIT_CH_HI_LIMIT;
252     //set new high threshold
253     adc->limit[monitor] |= (threshold << MXC_F_ADC_REVA_LIMIT_CH_HI_LIMIT_POS) &
254                            MXC_F_ADC_REVA_LIMIT_CH_HI_LIMIT;
255 }
256 
MXC_ADC_RevA_GetMonitorHighThreshold(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_t monitor)257 int MXC_ADC_RevA_GetMonitorHighThreshold(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_t monitor)
258 {
259     MXC_ASSERT(monitor < MXC_MONITOR_NUM);
260     return (adc->limit[monitor] & MXC_F_ADC_REVA_LIMIT_CH_HI_LIMIT) >>
261            MXC_F_ADC_REVA_LIMIT_CH_HI_LIMIT_POS;
262 }
263 
MXC_ADC_RevA_SetMonitorLowThreshold(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_t monitor,uint32_t threshold)264 void MXC_ADC_RevA_SetMonitorLowThreshold(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_t monitor,
265                                          uint32_t threshold)
266 {
267     MXC_ASSERT(monitor < MXC_MONITOR_NUM);
268     adc->limit[monitor] &= ~MXC_F_ADC_REVA_LIMIT_CH_LO_LIMIT;
269     adc->limit[monitor] |= (threshold << MXC_F_ADC_REVA_LIMIT_CH_LO_LIMIT_POS) &
270                            MXC_F_ADC_REVA_LIMIT_CH_LO_LIMIT;
271 }
272 
MXC_ADC_RevA_GetMonitorLowThreshold(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_t monitor)273 int MXC_ADC_RevA_GetMonitorLowThreshold(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_t monitor)
274 {
275     MXC_ASSERT(monitor < MXC_MONITOR_NUM);
276     return (adc->limit[monitor] & MXC_F_ADC_REVA_LIMIT_CH_LO_LIMIT) >>
277            MXC_F_ADC_REVA_LIMIT_CH_LO_LIMIT_POS;
278 }
279 
MXC_ADC_RevA_SetMonitorChannel(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_t monitor,mxc_adc_chsel_t channel)280 void MXC_ADC_RevA_SetMonitorChannel(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_t monitor,
281                                     mxc_adc_chsel_t channel)
282 {
283     MXC_ASSERT(monitor < MXC_MONITOR_NUM);
284 
285     // MAX32650 'ch_sel' field is 4-bits wide instead of 5-bits
286 #if TARGET_NUM == 32650
287     ((mxc_adc_regs_t *)adc)->limit[monitor] &= ~MXC_F_ADC_LIMIT_CH_SEL;
288     ((mxc_adc_regs_t *)adc)->limit[monitor] |= (channel << MXC_F_ADC_LIMIT_CH_SEL_POS) &
289                                                MXC_F_ADC_LIMIT_CH_SEL;
290 #else
291     adc->limit[monitor] &= ~MXC_F_ADC_REVA_LIMIT_CH_SEL;
292     adc->limit[monitor] |= (channel << MXC_F_ADC_REVA_LIMIT_CH_SEL_POS) &
293                            MXC_F_ADC_REVA_LIMIT_CH_SEL;
294 #endif
295 }
296 
MXC_ADC_RevA_GetMonitorChannel(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_t monitor)297 int MXC_ADC_RevA_GetMonitorChannel(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_t monitor)
298 {
299     MXC_ASSERT(monitor < MXC_MONITOR_NUM);
300     return (adc->limit[monitor] & MXC_F_ADC_REVA_LIMIT_CH_SEL) >> MXC_F_ADC_REVA_LIMIT_CH_SEL_POS;
301 }
302 
MXC_ADC_RevA_EnableMonitorAsync(mxc_adc_monitor_t monitor,mxc_adc_monitor_cb_t callback)303 void MXC_ADC_RevA_EnableMonitorAsync(mxc_adc_monitor_t monitor, mxc_adc_monitor_cb_t callback)
304 {
305     MXC_ASSERT(monitor < MXC_MONITOR_NUM && callback != NULL);
306     states[monitor]->callback = callback;
307 }
308 
MXC_ADC_RevA_DisableMonitorAsync(mxc_adc_monitor_t monitor)309 void MXC_ADC_RevA_DisableMonitorAsync(mxc_adc_monitor_t monitor)
310 {
311     MXC_ASSERT(monitor < MXC_MONITOR_NUM);
312     states[monitor]->callback = NULL;
313 }
314 
MXC_ADC_RevA_StartConversion(mxc_adc_reva_regs_t * adc,mxc_adc_chsel_t channel)315 int MXC_ADC_RevA_StartConversion(mxc_adc_reva_regs_t *adc, mxc_adc_chsel_t channel)
316 {
317     uint16_t data;
318 
319     int error;
320 #if TARGET_NUM != 32650
321     if (channel > AIN16) {
322         return E_BAD_PARAM;
323     }
324 #else
325     if (channel > AIN12) {
326         return E_BAD_PARAM;
327     }
328 #endif
329 
330     //clear selction bits
331     adc->ctrl &= ~(MXC_F_ADC_REVA_CTRL_CH_SEL);
332     //set selction its to next channel to convert
333     adc->ctrl |= (channel << MXC_F_ADC_REVA_CTRL_CH_SEL_POS) & MXC_F_ADC_REVA_CTRL_CH_SEL;
334 
335     //clear ADC done interrupt flag
336     MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_DONE_IF);
337 
338     //set start bit
339     adc->ctrl |= MXC_F_ADC_REVA_CTRL_START;
340 
341     while (adc->status & MXC_F_ADC_REVA_STATUS_ACTIVE) {}
342 
343     if ((error = MXC_ADC_GetData(&data)) != E_NO_ERROR) {
344         return error;
345     }
346 
347     return (int)data;
348 }
349 
MXC_ADC_RevA_StartConversionAsync(mxc_adc_reva_regs_t * adc,mxc_adc_chsel_t channel,mxc_adc_complete_cb_t callback)350 int MXC_ADC_RevA_StartConversionAsync(mxc_adc_reva_regs_t *adc, mxc_adc_chsel_t channel,
351                                       mxc_adc_complete_cb_t callback)
352 {
353     //check status call get lock
354 #if TARGET_NUM != 32650
355     if (channel > AIN16 || callback == NULL) {
356         return E_BAD_PARAM;
357     }
358 #else
359     if (channel > AIN12 || callback == NULL) {
360         return E_BAD_PARAM;
361     }
362 #endif
363 
364     //check lock
365     while (MXC_GetLock((uint32_t *)&async_callback, (uint32_t)callback) != E_NO_ERROR) {}
366 
367     flag |= MXC_CONVERSION_INTERRUPT;
368     //clear selction bits
369     adc->ctrl &= ~(MXC_F_ADC_REVA_CTRL_CH_SEL);
370     //set selction its to next channel to convert
371     adc->ctrl |= (channel << MXC_F_ADC_REVA_CTRL_CH_SEL_POS) & MXC_F_ADC_REVA_CTRL_CH_SEL;
372 
373     //clear ADC done interrupt flag
374     MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_DONE_IF);
375 
376     //set start bit
377     adc->ctrl |= MXC_F_ADC_REVA_CTRL_START;
378 
379     //enable adc done interrupt
380     MXC_ADC_RevA_EnableInt(adc, MXC_F_ADC_REVA_INTR_DONE_IE);
381 
382     return E_NO_ERROR;
383 }
384 
MXC_ADC_RevA_StartConversionDMA(mxc_adc_reva_regs_t * adc,mxc_adc_chsel_t channel,mxc_dma_regs_t * dma,uint16_t * data,void (* callback)(int,int))385 int MXC_ADC_RevA_StartConversionDMA(mxc_adc_reva_regs_t *adc, mxc_adc_chsel_t channel,
386                                     mxc_dma_regs_t *dma, uint16_t *data, void (*callback)(int, int))
387 {
388     uint8_t channelDMA;
389     mxc_dma_config_t config;
390     mxc_dma_srcdst_t srcdst;
391 
392 #if TARGET_NUM != 32650
393     if (channel > AIN16) {
394         return E_BAD_PARAM;
395     }
396 #else
397     if (channel > AIN12) {
398         return E_BAD_PARAM;
399     }
400 #endif
401 
402     if (data == NULL) {
403         return E_BAD_PARAM;
404     }
405 
406     //clear selction bits
407     adc->ctrl &= ~(MXC_F_ADC_REVA_CTRL_CH_SEL);
408     //set selction its to next channel to convert
409     adc->ctrl |= (channel << MXC_F_ADC_REVA_CTRL_CH_SEL_POS) & MXC_F_ADC_REVA_CTRL_CH_SEL;
410 
411     //clear ADC done interrupt flag
412     MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_DONE_IF);
413 
414 #if TARGET_NUM == 32665
415     MXC_DMA_Init(dma);
416     channelDMA = MXC_DMA_AcquireChannel(dma);
417 #else
418     MXC_DMA_Init();
419     channelDMA = MXC_DMA_AcquireChannel();
420 #endif
421 
422     config.reqsel = MXC_S_DMA_REVA_CTRL_REQUEST_MEMTOMEM;
423     config.ch = channelDMA;
424 
425     config.srcwd = MXC_DMA_WIDTH_HALFWORD;
426     config.dstwd = MXC_DMA_WIDTH_HALFWORD;
427 
428     config.srcinc_en = 0;
429     config.dstinc_en = 0;
430 
431     srcdst.ch = channelDMA;
432     srcdst.source = (uint16_t *)&(adc->data);
433     srcdst.dest = data;
434     srcdst.len = 2;
435 
436     MXC_DMA_ConfigChannel(config, srcdst);
437     MXC_DMA_SetCallback(channelDMA, callback);
438     MXC_DMA_EnableInt(channelDMA);
439 
440 #if TARGET_NUM == 32665
441     channelDMA %= MXC_DMA_CH_OFFSET;
442 #endif
443     ((mxc_dma_reva_regs_t *)dma)->ch[channelDMA].ctrl |= 2 << MXC_F_DMA_REVA_CTRL_BURST_SIZE_POS;
444 
445     //set start bit
446     adc->ctrl |= MXC_F_ADC_REVA_CTRL_START;
447     MXC_DMA_Start(channelDMA);
448     ((mxc_dma_reva_regs_t *)dma)->ch[channelDMA].ctrl |= MXC_F_DMA_REVA_CTRL_CTZ_IE;
449 
450     return E_NO_ERROR;
451 }
452 
MXC_ADC_RevA_Handler(mxc_adc_reva_regs_t * adc)453 int MXC_ADC_RevA_Handler(mxc_adc_reva_regs_t *adc)
454 {
455     uint16_t data;
456     int error, i;
457 
458     if ((error = MXC_ADC_GetData(&data)) != E_NO_ERROR) {
459         return error;
460     }
461 
462     if (flag & MXC_CONVERSION_INTERRUPT) {
463         mxc_adc_complete_cb_t cb = async_callback;
464         MXC_FreeLock((uint32_t *)&async_callback);
465         MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_DONE_IF);
466         flag &= ~MXC_CONVERSION_INTERRUPT;
467         MXC_ADC_RevA_DisableInt(adc, MXC_F_ADC_REVA_INTR_DONE_IE);
468         //read data
469         (cb)(NULL, data);
470     }
471 
472     if (flag & MXC_CONVERSION_REQ_INTERRUPT) {
473         mxc_adc_conversion_req_t *temp = async_req;
474         MXC_FreeLock((uint32_t *)&async_req);
475         MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_DONE_IF);
476         flag &= ~MXC_CONVERSION_REQ_INTERRUPT;
477         MXC_ADC_RevA_DisableInt(adc, MXC_F_ADC_REVA_INTR_DONE_IE);
478         //read data
479         temp->rawADCValue = data;
480         (temp->callback)(temp, E_NO_ERROR);
481     }
482 
483     if ((MXC_ADC_RevA_GetFlags(adc) &
484          (MXC_F_ADC_REVA_INTR_HI_LIMIT_IF | MXC_F_ADC_REVA_INTR_LO_LIMIT_IF)) &&
485         flag & MXC_MONITOR_INTERRUPT) {
486         MXC_ADC_RevA_ClearFlags(adc,
487                                 MXC_F_ADC_REVA_INTR_HI_LIMIT_IF | MXC_F_ADC_REVA_INTR_LO_LIMIT_IF);
488 
489         for (i = 0; i < MXC_MONITOR_NUM; i++) {
490             if (states[i]->callback != NULL) {
491                 mxc_adc_monitor_req_t *temp = states[i];
492                 MXC_FreeLock((uint32_t *)&states[i]);
493                 temp->callback(temp, E_NO_ERROR);
494             }
495         }
496 
497         flag &= ~MXC_MONITOR_INTERRUPT;
498     }
499 
500     return E_NO_ERROR;
501 }
502 
MXC_ADC_RevA_Convert(mxc_adc_reva_regs_t * adc,mxc_adc_conversion_req_t * req)503 int MXC_ADC_RevA_Convert(mxc_adc_reva_regs_t *adc, mxc_adc_conversion_req_t *req)
504 {
505     uint16_t data;
506     int error;
507 
508     //clear selction bits
509     adc->ctrl &= ~(MXC_F_ADC_REVA_CTRL_CH_SEL);
510     //set selction its to next channel to convert
511     adc->ctrl |= (req->channel << MXC_F_ADC_REVA_CTRL_CH_SEL_POS) & MXC_F_ADC_REVA_CTRL_CH_SEL;
512 
513     if (req->channel <= AIN7) {
514         MXC_ADC_RevA_SetExtScale(adc, req->scale);
515     }
516 
517     //clear ADC done interrupt flag
518     MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_DONE_IF);
519 
520     //set start bit
521     adc->ctrl |= MXC_F_ADC_REVA_CTRL_START;
522 
523     if ((error = MXC_ADC_GetData(&data)) != E_NO_ERROR) {
524         return error;
525     }
526     req->rawADCValue = data;
527 
528     return E_NO_ERROR;
529 }
530 
MXC_ADC_RevA_ConvertAsync(mxc_adc_reva_regs_t * adc,mxc_adc_conversion_req_t * req)531 int MXC_ADC_RevA_ConvertAsync(mxc_adc_reva_regs_t *adc, mxc_adc_conversion_req_t *req)
532 {
533     //check lock
534     if (MXC_GetLock((uint32_t *)&async_req, (uint32_t)req) != E_NO_ERROR) {
535         return E_BUSY;
536     }
537 
538     //save callback function to be called from isr
539     flag |= MXC_CONVERSION_REQ_INTERRUPT;
540     async_callback = req->callback;
541     //clear selction bits
542     adc->ctrl &= ~(MXC_F_ADC_REVA_CTRL_CH_SEL);
543     //set selction its to next channel to convert
544     adc->ctrl |= (req->channel << MXC_F_ADC_REVA_CTRL_CH_SEL_POS) & MXC_F_ADC_REVA_CTRL_CH_SEL;
545 
546     if (req->channel <= AIN7) {
547         MXC_ADC_RevA_SetExtScale(adc, req->scale);
548     }
549 
550     //clear ADC done interrupt flag
551     MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_DONE_IF);
552 
553     //enable adc done interrupt
554     MXC_ADC_RevA_EnableInt(adc, MXC_F_ADC_REVA_INTR_DONE_IE);
555 
556     //set start bit
557     adc->ctrl |= MXC_F_ADC_REVA_CTRL_START;
558 
559     return E_NO_ERROR;
560 }
561 
MXC_ADC_RevA_Monitor(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_req_t req)562 void MXC_ADC_RevA_Monitor(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_req_t req)
563 {
564     MXC_ASSERT(req.monitor < MXC_MONITOR_NUM);
565 
566     while (adc->status & MXC_F_ADC_REVA_STATUS_ACTIVE) {}
567 
568     //clear selction bits
569     adc->ctrl &= ~(MXC_F_ADC_REVA_CTRL_CH_SEL);
570     //set selction its to next channel to convert
571     adc->ctrl |= (req.channel << MXC_F_ADC_REVA_CTRL_CH_SEL_POS) & MXC_F_ADC_REVA_CTRL_CH_SEL;
572 
573     MXC_ADC_RevA_SetMonitorChannel(adc, req.monitor, req.channel);
574 
575     MXC_ADC_RevA_SetMonitorHighThreshold(adc, req.monitor, req.highThreshold);
576     MXC_ADC_RevA_SetMonitorLowThreshold(adc, req.monitor, req.lowThreshold);
577 
578     if (req.channel <= AIN7) {
579         MXC_ADC_RevA_SetExtScale(adc, req.scale);
580     }
581 
582     MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_HI_LIMIT_IF | MXC_F_ADC_REVA_INTR_LO_LIMIT_IF);
583     MXC_ADC_RevA_EnableMonitor(adc, req.monitor);
584 
585     while (!(adc->intr & (MXC_F_ADC_REVA_INTR_HI_LIMIT_IF | MXC_F_ADC_REVA_INTR_LO_LIMIT_IF))) {}
586 }
587 
MXC_ADC_RevA_MonitorAsync(mxc_adc_reva_regs_t * adc,mxc_adc_monitor_req_t req)588 void MXC_ADC_RevA_MonitorAsync(mxc_adc_reva_regs_t *adc, mxc_adc_monitor_req_t req)
589 {
590     MXC_ASSERT(req.monitor < MXC_MONITOR_NUM);
591 
592     //check lock
593     while (MXC_GetLock((uint32_t *)&states[req.monitor], (uint32_t)&req) != E_NO_ERROR) {}
594 
595     while (adc->status & MXC_F_ADC_REVA_STATUS_ACTIVE) {}
596 
597     //clear selction bits
598     adc->ctrl &= ~(MXC_F_ADC_REVA_CTRL_CH_SEL);
599     //set selction its to next channel to convert
600     adc->ctrl |= (req.channel << MXC_F_ADC_REVA_CTRL_CH_SEL_POS) & MXC_F_ADC_REVA_CTRL_CH_SEL;
601 
602     MXC_ADC_RevA_SetMonitorChannel(adc, req.monitor, req.channel);
603 
604     MXC_ADC_RevA_SetMonitorHighThreshold(adc, req.monitor, req.highThreshold);
605     MXC_ADC_RevA_SetMonitorLowThreshold(adc, req.monitor, req.lowThreshold);
606 
607     if (req.channel <= AIN7) {
608         MXC_ADC_RevA_SetExtScale(adc, req.scale);
609     }
610 
611     MXC_ADC_RevA_ClearFlags(adc, MXC_F_ADC_REVA_INTR_HI_LIMIT_IF | MXC_F_ADC_REVA_INTR_LO_LIMIT_IF);
612 
613     MXC_ASSERT(req.callback != NULL);
614     MXC_ADC_RevA_EnableMonitorAsync(req.monitor, req.callback);
615     flag |= MXC_MONITOR_INTERRUPT;
616     MXC_ADC_RevA_EnableInt(adc, MXC_F_ADC_REVA_INTR_HI_LIMIT_IE | MXC_F_ADC_REVA_INTR_LO_LIMIT_IE);
617     MXC_ADC_RevA_EnableMonitor(adc, req.monitor);
618 }
619 
620 // ************************************* Function to Read ADC Data *******************************************
MXC_ADC_RevA_GetData(mxc_adc_reva_regs_t * adc,uint16_t * outdata)621 int MXC_ADC_RevA_GetData(mxc_adc_reva_regs_t *adc, uint16_t *outdata)
622 {
623     // See if a conversion is in process
624     if (adc->status & MXC_F_ADC_REVA_STATUS_ACTIVE) {
625         // Wait for conversion to complete
626         while ((adc->intr & MXC_F_ADC_REVA_INTR_DONE_IF) == 0) {}
627     }
628 
629     // Read 32-bit value and truncate to 16-bit for output depending on data align bit
630     if ((adc->ctrl & MXC_F_ADC_REVA_CTRL_DATA_ALIGN) == 0) {
631         *outdata = (uint16_t)(adc->data); /* LSB justified */
632     } else {
633         *outdata = (uint16_t)(adc->data >> 6); /* MSB justified */
634     }
635 
636     // Check for overflow
637     if (adc->status & MXC_F_ADC_REVA_STATUS_OVERFLOW) {
638         return E_OVERFLOW;
639     }
640 
641     return E_NO_ERROR;
642 }
643