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 #include <stdio.h>
21 #include "adc.h"
22 #include "adc_regs.h"
23 #include "adc_revb.h"
24 #include "gcr_regs.h"
25 #include "mxc_device.h"
26 #include "mxc_errors.h"
27 #include "mxc_assert.h"
28 #include "mxc_sys.h"
29 #include "mcr_regs.h"
30 #include "mxc_lock.h"
31 #include "mxc_pins.h"
32 #include "pwrseq_regs.h"
33
34 #define MXC_F_MCR_ADC_CFG2_CH 0x3
35
36 #define TEMP_FACTOR (double)530.582f / (double)4096.0f
37 #define TEMP_FACTOR1V25 (double)1.25f * TEMP_FACTOR
38 #define TEMP_FACTOR2V048 (double)2.048f * TEMP_FACTOR
39
initGPIOForChannel(mxc_adc_chsel_t channel)40 static void initGPIOForChannel(mxc_adc_chsel_t channel)
41 {
42 switch (channel) {
43 case MXC_ADC_CH_0:
44 MXC_GPIO_Config(&gpio_cfg_adc_ain0);
45 break;
46
47 case MXC_ADC_CH_1:
48 MXC_GPIO_Config(&gpio_cfg_adc_ain1);
49 break;
50
51 case MXC_ADC_CH_2:
52 MXC_GPIO_Config(&gpio_cfg_adc_ain2);
53 break;
54
55 case MXC_ADC_CH_3:
56 MXC_GPIO_Config(&gpio_cfg_adc_ain3);
57 break;
58
59 case MXC_ADC_CH_4:
60 MXC_GPIO_Config(&gpio_cfg_adc_ain4);
61 break;
62
63 case MXC_ADC_CH_5:
64 MXC_GPIO_Config(&gpio_cfg_adc_ain5);
65 break;
66
67 case MXC_ADC_CH_6:
68 MXC_GPIO_Config(&gpio_cfg_adc_ain6);
69 break;
70
71 case MXC_ADC_CH_7:
72 MXC_GPIO_Config(&gpio_cfg_adc_ain7);
73 break;
74
75 case MXC_ADC_CH_8:
76 MXC_GPIO_Config(&gpio_cfg_adc_ain8);
77 break;
78
79 case MXC_ADC_CH_9:
80 MXC_GPIO_Config(&gpio_cfg_adc_ain9);
81 break;
82
83 case MXC_ADC_CH_10:
84 MXC_GPIO_Config(&gpio_cfg_adc_ain10);
85 break;
86
87 case MXC_ADC_CH_11:
88 MXC_GPIO_Config(&gpio_cfg_adc_ain11);
89 break;
90
91 default:
92 break;
93 }
94 }
95
initGPIOforHWTrig(mxc_adc_trig_sel_t hwTrig)96 static void initGPIOforHWTrig(mxc_adc_trig_sel_t hwTrig)
97 {
98 mxc_gpio_cfg_t gpioCfg;
99 switch (hwTrig) {
100 case MXC_ADC_TRIG_SEL_TMR0:
101 case MXC_ADC_TRIG_SEL_TMR1:
102 case MXC_ADC_TRIG_SEL_TMR2:
103 case MXC_ADC_TRIG_SEL_TMR3:
104 case MXC_ADC_TRIG_SEL_TEMP_SENS:
105 break;
106 case MXC_ADC_TRIG_SEL_P0_29:
107 gpioCfg.port = MXC_GPIO0;
108 gpioCfg.mask = MXC_GPIO_PIN_29;
109 gpioCfg.func = MXC_GPIO_FUNC_ALT4;
110 gpioCfg.pad = MXC_GPIO_PAD_NONE;
111 gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIO;
112 gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
113 MXC_GPIO_Config(&gpioCfg);
114 break;
115 case MXC_ADC_TRIG_SEL_P0_22:
116 gpioCfg.port = MXC_GPIO0;
117 gpioCfg.mask = MXC_GPIO_PIN_22;
118 gpioCfg.func = MXC_GPIO_FUNC_ALT2;
119 gpioCfg.pad = MXC_GPIO_PAD_NONE;
120 gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIO;
121 gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
122 MXC_GPIO_Config(&gpioCfg);
123 break;
124 case MXC_ADC_TRIG_SEL_P1_4:
125 gpioCfg.port = MXC_GPIO1;
126 gpioCfg.mask = MXC_GPIO_PIN_4;
127 gpioCfg.func = MXC_GPIO_FUNC_ALT4;
128 gpioCfg.pad = MXC_GPIO_PAD_NONE;
129 gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIO;
130 gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
131 MXC_GPIO_Config(&gpioCfg);
132 break;
133 }
134 }
135
MXC_ADC_Init(mxc_adc_req_t * req)136 int MXC_ADC_Init(mxc_adc_req_t *req)
137 {
138 #ifndef MSDK_NO_GPIO_CLK_INIT
139 /* ADC in reset state */
140 switch (req->clock) {
141 case MXC_ADC_CLK_HCLK:
142 break;
143 case MXC_ADC_CLK_EXT:
144 MXC_GPIO_Config(&gpio_cfg_hfextclk);
145 MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_EXTCLK);
146 break;
147 case MXC_ADC_CLK_IBRO:
148 MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IBRO);
149 break;
150 case MXC_ADC_CLK_ERFO:
151 MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_ERFO);
152 break;
153 default:
154 return E_BAD_PARAM;
155 }
156
157 MXC_SYS_Reset_Periph(MXC_SYS_RESET0_ADC);
158 MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_ADC);
159
160 /* This is required for temperature sensor only */
161 MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IBRO);
162 #endif
163
164 MXC_ADC_ReferenceSelect(req->ref);
165
166 return MXC_ADC_RevB_Init((mxc_adc_revb_regs_t *)MXC_ADC, req);
167 }
168
MXC_ADC_Shutdown(void)169 int MXC_ADC_Shutdown(void)
170 {
171 MXC_ADC_RevB_Shutdown((mxc_adc_revb_regs_t *)MXC_ADC);
172
173 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_ADC);
174
175 return E_NO_ERROR;
176 }
177
MXC_ADC_EnableInt(uint32_t flags)178 void MXC_ADC_EnableInt(uint32_t flags)
179 {
180 MXC_ADC_RevB_EnableInt((mxc_adc_revb_regs_t *)MXC_ADC, flags);
181 }
182
MXC_ADC_DisableInt(uint32_t flags)183 void MXC_ADC_DisableInt(uint32_t flags)
184 {
185 MXC_ADC_RevB_DisableInt((mxc_adc_revb_regs_t *)MXC_ADC, flags);
186 }
187
MXC_ADC_GetFlags(void)188 int MXC_ADC_GetFlags(void)
189 {
190 return MXC_ADC_RevB_GetFlags((mxc_adc_revb_regs_t *)MXC_ADC);
191 }
192
MXC_ADC_ClearFlags(uint32_t flags)193 void MXC_ADC_ClearFlags(uint32_t flags)
194 {
195 MXC_ADC_RevB_ClearFlags((mxc_adc_revb_regs_t *)MXC_ADC, flags);
196 }
197
MXC_ADC_ClockSelect(mxc_adc_clock_t clock)198 void MXC_ADC_ClockSelect(mxc_adc_clock_t clock)
199 {
200 MXC_ADC_RevB_ClockSelect((mxc_adc_revb_regs_t *)MXC_ADC, clock);
201 }
202
MXC_ADC_StartConversion(void)203 int MXC_ADC_StartConversion(void)
204 {
205 return MXC_ADC_RevB_StartConversion((mxc_adc_revb_regs_t *)MXC_ADC);
206 }
207
MXC_ADC_StartConversionAsync(mxc_adc_complete_cb_t callback)208 int MXC_ADC_StartConversionAsync(mxc_adc_complete_cb_t callback)
209 {
210 return MXC_ADC_RevB_StartConversionAsync((mxc_adc_revb_regs_t *)MXC_ADC, callback);
211 }
212
MXC_ADC_StartConversionDMA(mxc_adc_conversion_req_t * req,int * data,void (* callback)(int,int))213 int MXC_ADC_StartConversionDMA(mxc_adc_conversion_req_t *req, int *data, void (*callback)(int, int))
214 {
215 return MXC_ADC_RevB_StartConversionDMA((mxc_adc_revb_regs_t *)MXC_ADC, req, data, callback);
216 }
217
MXC_ADC_Handler(void)218 int MXC_ADC_Handler(void)
219 {
220 return MXC_ADC_RevB_Handler((mxc_adc_revb_regs_t *)MXC_ADC);
221 }
222
MXC_ADC_GetData(int * outdata)223 int MXC_ADC_GetData(int *outdata)
224 {
225 return MXC_ADC_RevB_GetData((mxc_adc_revb_regs_t *)MXC_ADC, outdata);
226 }
227
MXC_ADC_ReferenceSelect(mxc_adc_refsel_t ref)228 int MXC_ADC_ReferenceSelect(mxc_adc_refsel_t ref)
229 {
230 switch (ref) {
231 case MXC_ADC_REF_EXT:
232 MXC_MCR->adc_cfg0 |= MXC_F_MCR_ADC_CFG0_EXT_REF;
233 break;
234 case MXC_ADC_REF_INT_1V25:
235 MXC_MCR->adc_cfg0 &= ~(MXC_F_MCR_ADC_CFG0_EXT_REF | MXC_F_MCR_ADC_CFG0_REF_SEL);
236 break;
237 case MXC_ADC_REF_INT_2V048:
238 MXC_MCR->adc_cfg0 &= ~MXC_F_MCR_ADC_CFG0_EXT_REF;
239 MXC_MCR->adc_cfg0 |= MXC_F_MCR_ADC_CFG0_REF_SEL;
240 break;
241 default:
242 return E_BAD_PARAM;
243 }
244
245 return E_NO_ERROR;
246 }
247
MXC_ADC_DynamicModeEn(mxc_adc_chsel_t ch)248 int MXC_ADC_DynamicModeEn(mxc_adc_chsel_t ch)
249 {
250 if (ch > MAX_ADC_RES_DIV_CH) {
251 return E_BAD_PARAM;
252 }
253
254 MXC_MCR->adc_cfg1 |= (1 << ch);
255
256 return E_NO_ERROR;
257 }
258
MXC_ADC_DynamicModeDis(mxc_adc_chsel_t ch)259 int MXC_ADC_DynamicModeDis(mxc_adc_chsel_t ch)
260 {
261 if (ch > MAX_ADC_RES_DIV_CH) {
262 return E_BAD_PARAM;
263 }
264
265 MXC_MCR->adc_cfg1 &= ~(1 << ch);
266
267 return E_NO_ERROR;
268 }
269
MXC_ADC_InputDividerSelect(mxc_adc_chsel_t ch,mxc_adc_divsel_t div,mxc_adc_dynamic_pullup_t lpEn)270 int MXC_ADC_InputDividerSelect(mxc_adc_chsel_t ch, mxc_adc_divsel_t div,
271 mxc_adc_dynamic_pullup_t lpEn)
272 {
273 uint32_t bitOffset;
274
275 if (ch > MXC_ADC_CH_12 || div > MXC_ADC_DIV2_50K) {
276 return E_BAD_PARAM;
277 }
278
279 bitOffset = ch << 1;
280 MXC_MCR->adc_cfg2 &= ~(MXC_F_MCR_ADC_CFG2_CH << bitOffset);
281 MXC_MCR->adc_cfg2 |= (div << bitOffset);
282
283 if (lpEn == MXC_ADC_PY_DN_DISABLE) {
284 MXC_ADC_DynamicModeDis(ch);
285 } else {
286 MXC_ADC_DynamicModeEn(ch);
287 }
288
289 return E_NO_ERROR;
290 }
291
MXC_ADC_LowPowerModeDividerSelect(mxc_adc_div_lpmode_t div_lpmode)292 int MXC_ADC_LowPowerModeDividerSelect(mxc_adc_div_lpmode_t div_lpmode)
293 {
294 MXC_MCR->adc_cfg0 &= ~(MXC_F_MCR_ADC_CFG0_LP_5K_DIS | MXC_F_MCR_ADC_CFG0_LP_50K_DIS);
295 MXC_MCR->adc_cfg0 |= div_lpmode;
296
297 return E_NO_ERROR;
298 }
299
MXC_ADC_EnableConversion(void)300 void MXC_ADC_EnableConversion(void)
301 {
302 MXC_ADC_RevB_EnableConversion((mxc_adc_revb_regs_t *)MXC_ADC);
303 }
304
MXC_ADC_DisableConversion(void)305 void MXC_ADC_DisableConversion(void)
306 {
307 MXC_ADC_RevB_DisableConversion((mxc_adc_revb_regs_t *)MXC_ADC);
308 }
309
MXC_ADC_TS_SelectEnable(void)310 void MXC_ADC_TS_SelectEnable(void)
311 {
312 MXC_ADC_RevB_TS_SelectEnable((mxc_adc_revb_regs_t *)MXC_ADC);
313 }
314
MXC_ADC_TS_SelectDisable(void)315 void MXC_ADC_TS_SelectDisable(void)
316 {
317 MXC_ADC_RevB_TS_SelectDisable((mxc_adc_revb_regs_t *)MXC_ADC);
318 }
319
MXC_ADC_FIFO_Level(void)320 uint16_t MXC_ADC_FIFO_Level(void)
321 {
322 return MXC_ADC_RevB_FIFO_Level((mxc_adc_revb_regs_t *)MXC_ADC);
323 }
324
MXC_ADC_FIFO_Threshold_Config(uint32_t fifo_threshold)325 int MXC_ADC_FIFO_Threshold_Config(uint32_t fifo_threshold)
326 {
327 return MXC_ADC_RevB_FIFO_Threshold_Config((mxc_adc_revb_regs_t *)MXC_ADC, fifo_threshold);
328 }
329
MXC_ADC_AverageConfig(mxc_adc_avg_t avg_number)330 int MXC_ADC_AverageConfig(mxc_adc_avg_t avg_number)
331 {
332 return MXC_ADC_RevB_AverageConfig((mxc_adc_revb_regs_t *)MXC_ADC, avg_number);
333 }
334
MXC_ADC_Clear_ChannelSelect(void)335 void MXC_ADC_Clear_ChannelSelect(void)
336 {
337 MXC_ADC_RevB_Clear_ChannelSelect((mxc_adc_revb_regs_t *)MXC_ADC);
338 }
339
MXC_ADC_TriggerConfig(mxc_adc_conversion_req_t * req)340 void MXC_ADC_TriggerConfig(mxc_adc_conversion_req_t *req)
341 {
342 initGPIOforHWTrig(req->hwTrig);
343 MXC_ADC_RevB_TriggerConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
344 }
345
MXC_ADC_ConversionModeConfig(mxc_adc_conversion_req_t * req)346 void MXC_ADC_ConversionModeConfig(mxc_adc_conversion_req_t *req)
347 {
348 MXC_ADC_RevB_ConversionModeConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
349 }
350
MXC_ADC_SetConversionDelay(int delay)351 void MXC_ADC_SetConversionDelay(int delay)
352 {
353 MXC_ADC_RevB_SetConversionDelay((mxc_adc_revb_regs_t *)MXC_ADC, delay);
354 }
355
MXC_ADC_SlotsConfig(mxc_adc_conversion_req_t * req)356 int MXC_ADC_SlotsConfig(mxc_adc_conversion_req_t *req)
357 {
358 return MXC_ADC_RevB_SlotsConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
359 }
360
MXC_ADC_ChSelectConfig(mxc_adc_chsel_t ch,uint32_t slot_num)361 int MXC_ADC_ChSelectConfig(mxc_adc_chsel_t ch, uint32_t slot_num)
362 {
363 return MXC_ADC_RevB_ChSelectConfig((mxc_adc_revb_regs_t *)MXC_ADC, ch, slot_num);
364 }
365
MXC_ADC_Configuration(mxc_adc_conversion_req_t * req)366 int MXC_ADC_Configuration(mxc_adc_conversion_req_t *req)
367 {
368 MXC_ADC_ConversionModeConfig(req);
369
370 MXC_ADC_TriggerConfig(req);
371
372 MXC_ADC_FIFO_Threshold_Config(req->fifo_threshold);
373
374 MXC_ADC_SlotsConfig(req);
375
376 MXC_ADC_Clear_ChannelSelect();
377
378 //number of samples to average
379 MXC_ADC_AverageConfig(req->avg_number);
380
381 MXC_ADC_LowPowerModeDividerSelect(req->lpmode_divder);
382
383 return E_NO_ERROR;
384 }
385
MXC_ADC_SlotConfiguration(mxc_adc_slot_req_t * req,uint32_t slot_length)386 int MXC_ADC_SlotConfiguration(mxc_adc_slot_req_t *req, uint32_t slot_length)
387 {
388 uint32_t loop_counter = 0;
389
390 for (loop_counter = 0; loop_counter <= slot_length; loop_counter++) {
391 initGPIOForChannel(req->channel);
392
393 if (req->channel <= MAX_ADC_RES_DIV_CH) {
394 MXC_ADC_InputDividerSelect(req->channel, req->div, req->pullup_dyn);
395 }
396
397 MXC_ADC_ChSelectConfig(req->channel, loop_counter);
398 req++;
399 }
400 return E_NO_ERROR;
401 }
402
MXC_ConvertTemperature_ToK(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp_k)403 int MXC_ConvertTemperature_ToK(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
404 float *temp_k)
405 {
406 switch (ref) {
407 case MXC_ADC_REF_EXT:
408 *temp_k = (double)tempSensor_Readout * (double)TEMP_FACTOR * (double)ext_ref;
409 break;
410
411 case MXC_ADC_REF_INT_1V25:
412 *temp_k = tempSensor_Readout * TEMP_FACTOR1V25;
413 break;
414
415 case MXC_ADC_REF_INT_2V048:
416 *temp_k = tempSensor_Readout * TEMP_FACTOR2V048;
417 break;
418
419 default:
420 return E_BAD_PARAM;
421 }
422 return E_NO_ERROR;
423 }
424
MXC_ConvertTemperature_ToC(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp)425 int MXC_ConvertTemperature_ToC(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
426 float *temp)
427 {
428 if (MXC_ConvertTemperature_ToK(tempSensor_Readout, ref, ext_ref, temp) == E_NO_ERROR) {
429 *temp = *temp - 273.15f;
430 return E_NO_ERROR;
431 } else {
432 return E_BAD_PARAM;
433 }
434 }
435
MXC_ConvertTemperature_ToF(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp)436 int MXC_ConvertTemperature_ToF(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
437 float *temp)
438 {
439 if (MXC_ConvertTemperature_ToK(tempSensor_Readout, ref, ext_ref, temp) == E_NO_ERROR) {
440 *temp = (*temp * 1.8f) - 459.67f;
441 return E_NO_ERROR;
442 } else {
443 return E_BAD_PARAM;
444 }
445 }
446
MXC_ADC_EnableComparator(mxc_adc_comp_t comp,mxc_adc_chsel_t negCh,mxc_adc_chsel_t posCh)447 int MXC_ADC_EnableComparator(mxc_adc_comp_t comp, mxc_adc_chsel_t negCh, mxc_adc_chsel_t posCh)
448 {
449 if (negCh > MXC_ADC_CH_3) {
450 return E_BAD_PARAM;
451 }
452
453 if (posCh < MXC_ADC_CH_4 || posCh > MXC_ADC_CH_7) {
454 return E_BAD_PARAM;
455 }
456
457 initGPIOForChannel(negCh);
458 initGPIOForChannel(posCh);
459
460 switch (comp) {
461 case MXC_ADC_COMP_0:
462 MXC_SETFIELD(MXC_MCR->aincomp, MXC_F_MCR_AINCOMP_NSEL_COMP0,
463 (1 << negCh) << MXC_F_MCR_AINCOMP_NSEL_COMP0_POS);
464 MXC_SETFIELD(MXC_MCR->aincomp, MXC_F_MCR_AINCOMP_PSEL_COMP0,
465 (1 << posCh % 4) << MXC_F_MCR_AINCOMP_PSEL_COMP0_POS);
466 break;
467 case MXC_ADC_COMP_1:
468 MXC_SETFIELD(MXC_MCR->aincomp, MXC_F_MCR_AINCOMP_NSEL_COMP1,
469 (1 << negCh) << MXC_F_MCR_AINCOMP_NSEL_COMP1_POS);
470 MXC_SETFIELD(MXC_MCR->aincomp, MXC_F_MCR_AINCOMP_PSEL_COMP1,
471 (1 << posCh % 4) << MXC_F_MCR_AINCOMP_PSEL_COMP1_POS);
472 break;
473 default:
474 return E_BAD_PARAM;
475 }
476
477 MXC_MCR->aincomp &= ~(comp << MXC_F_MCR_AINCOMP_PD_POS);
478
479 return E_NO_ERROR;
480 }
481
MXC_ADC_DisableComparator(mxc_adc_comp_t comp)482 int MXC_ADC_DisableComparator(mxc_adc_comp_t comp)
483 {
484 switch (comp) {
485 case MXC_ADC_COMP_0:
486 MXC_MCR->aincomp &= ~(MXC_F_MCR_AINCOMP_NSEL_COMP0 | MXC_F_MCR_AINCOMP_PSEL_COMP0);
487 break;
488 case MXC_ADC_COMP_1:
489 MXC_MCR->aincomp &= ~(MXC_F_MCR_AINCOMP_NSEL_COMP1 | MXC_F_MCR_AINCOMP_PSEL_COMP1);
490 break;
491 default:
492 return E_BAD_PARAM;
493 }
494
495 MXC_MCR->aincomp |= (comp << MXC_F_MCR_AINCOMP_PD_POS);
496
497 return E_NO_ERROR;
498 }
499
500 //End
501