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