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 "adc.h"
27 #include "adc_regs.h"
28 #include "adc_revb.h"
29 #include "gcr_regs.h"
30 #include "mcr_regs.h"
31 #include "mxc_lock.h"
32 #include "mxc_pins.h"
33 #include "pwrseq_regs.h"
34
35 /*TODO-
36 * This is work in progress file and has not finalized yet. Expected to change some parameters as well as some function prototypes.
37 */
38
39 #define MXC_F_MCR_ADCCFG2_CH 0x3
40 #define TEMP_FACTOR 530.582f / 4096.0f
41 #define TEMP_FACTOR1V25 1.25f * TEMP_FACTOR
42 #define TEMP_FACTOR2V048 2.048f * TEMP_FACTOR
43
initGPIOForChannel(mxc_adc_chsel_t channel)44 static void initGPIOForChannel(mxc_adc_chsel_t channel)
45 {
46 switch (channel) {
47 case MXC_ADC_CH_0:
48 MXC_GPIO_Config(&gpio_cfg_adc_ain0);
49 break;
50
51 case MXC_ADC_CH_1:
52 MXC_GPIO_Config(&gpio_cfg_adc_ain1);
53 break;
54
55 case MXC_ADC_CH_2:
56 MXC_GPIO_Config(&gpio_cfg_adc_ain2);
57 break;
58
59 case MXC_ADC_CH_3:
60 MXC_GPIO_Config(&gpio_cfg_adc_ain3);
61 break;
62
63 case MXC_ADC_CH_4:
64 MXC_GPIO_Config(&gpio_cfg_adc_ain4);
65 break;
66
67 case MXC_ADC_CH_5:
68 MXC_GPIO_Config(&gpio_cfg_adc_ain5);
69 break;
70
71 case MXC_ADC_CH_6:
72 MXC_GPIO_Config(&gpio_cfg_adc_ain6);
73 break;
74
75 case MXC_ADC_CH_7:
76 MXC_GPIO_Config(&gpio_cfg_adc_ain7);
77 break;
78
79 default:
80 break;
81 }
82 }
83
initGPIOforHWTrig(mxc_adc_trig_sel_t hwTrig)84 static void initGPIOforHWTrig(mxc_adc_trig_sel_t hwTrig)
85 {
86 mxc_gpio_cfg_t gpioCfg;
87 switch (hwTrig) {
88 case MXC_ADC_TRIG_SEL_TMR0:
89 case MXC_ADC_TRIG_SEL_TMR1:
90 case MXC_ADC_TRIG_SEL_TMR2:
91 case MXC_ADC_TRIG_SEL_TMR3:
92 case MXC_ADC_TRIG_SEL_TEMP_SENS:
93 break;
94 case MXC_ADC_TRIG_SEL_P1_12:
95 gpioCfg.port = MXC_GPIO1;
96 gpioCfg.mask = MXC_GPIO_PIN_12;
97 gpioCfg.func = MXC_GPIO_FUNC_ALT2;
98 gpioCfg.pad = MXC_GPIO_PAD_NONE;
99 gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIOH;
100 gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
101 MXC_GPIO_Config(&gpioCfg);
102 break;
103 case MXC_ADC_TRIG_SEL_P1_13:
104 gpioCfg.port = MXC_GPIO1;
105 gpioCfg.mask = MXC_GPIO_PIN_13;
106 gpioCfg.func = MXC_GPIO_FUNC_ALT2;
107 gpioCfg.pad = MXC_GPIO_PAD_NONE;
108 gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIOH;
109 gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
110 MXC_GPIO_Config(&gpioCfg);
111 break;
112 case MXC_ADC_TRIG_SEL_P1_14:
113 gpioCfg.port = MXC_GPIO1;
114 gpioCfg.mask = MXC_GPIO_PIN_14;
115 gpioCfg.func = MXC_GPIO_FUNC_ALT2;
116 gpioCfg.pad = MXC_GPIO_PAD_NONE;
117 gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIOH;
118 gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
119 MXC_GPIO_Config(&gpioCfg);
120 break;
121 }
122 }
123
MXC_ADC_Init(mxc_adc_req_t * req)124 int MXC_ADC_Init(mxc_adc_req_t *req)
125 {
126 switch (req->clock) {
127 case MXC_ADC_CLK_HCLK:
128 break;
129 case MXC_ADC_CLK_EXT:
130 MXC_GPIO_Config(&gpio_cfg_extclk);
131 MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_EXTCLK);
132 break;
133 case MXC_ADC_CLK_IBRO:
134 MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IBRO);
135 break;
136 default:
137 return E_BAD_PARAM;
138 }
139
140 MXC_SYS_Reset_Periph(MXC_SYS_RESET0_ADC);
141 MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_ADC);
142
143 /* This is required for temperature sensor only */
144 MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IBRO);
145
146 MXC_ADC_ReferenceSelect(req->ref);
147
148 return MXC_ADC_RevB_Init((mxc_adc_revb_regs_t *)MXC_ADC, req);
149 }
150
MXC_ADC_Shutdown(void)151 int MXC_ADC_Shutdown(void)
152 {
153 MXC_ADC_RevB_Shutdown((mxc_adc_revb_regs_t *)MXC_ADC);
154
155 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_ADC);
156
157 return E_NO_ERROR;
158 }
159
MXC_ADC_EnableInt(uint32_t flags)160 void MXC_ADC_EnableInt(uint32_t flags)
161 {
162 MXC_ADC_RevB_EnableInt((mxc_adc_revb_regs_t *)MXC_ADC, flags);
163 }
164
MXC_ADC_DisableInt(uint32_t flags)165 void MXC_ADC_DisableInt(uint32_t flags)
166 {
167 MXC_ADC_RevB_DisableInt((mxc_adc_revb_regs_t *)MXC_ADC, flags);
168 }
169
MXC_ADC_GetFlags(void)170 int MXC_ADC_GetFlags(void)
171 {
172 return MXC_ADC_RevB_GetFlags((mxc_adc_revb_regs_t *)MXC_ADC);
173 }
174
MXC_ADC_ClearFlags(uint32_t flags)175 void MXC_ADC_ClearFlags(uint32_t flags)
176 {
177 MXC_ADC_RevB_ClearFlags((mxc_adc_revb_regs_t *)MXC_ADC, flags);
178 }
179
MXC_ADC_ClockSelect(mxc_adc_clock_t clock)180 void MXC_ADC_ClockSelect(mxc_adc_clock_t clock)
181 {
182 MXC_ADC_RevB_ClockSelect((mxc_adc_revb_regs_t *)MXC_ADC, clock);
183 }
184
MXC_ADC_StartConversion(void)185 int MXC_ADC_StartConversion(void)
186 {
187 return MXC_ADC_RevB_StartConversion((mxc_adc_revb_regs_t *)MXC_ADC);
188 }
189
MXC_ADC_StartConversionAsync(mxc_adc_complete_cb_t callback)190 int MXC_ADC_StartConversionAsync(mxc_adc_complete_cb_t callback)
191 {
192 return MXC_ADC_RevB_StartConversionAsync((mxc_adc_revb_regs_t *)MXC_ADC, callback);
193 }
194
MXC_ADC_StartConversionDMA(mxc_adc_conversion_req_t * req,int * data,void (* callback)(int,int))195 int MXC_ADC_StartConversionDMA(mxc_adc_conversion_req_t *req, int *data, void (*callback)(int, int))
196 {
197 return MXC_ADC_RevB_StartConversionDMA((mxc_adc_revb_regs_t *)MXC_ADC, req, data, callback);
198 }
199
MXC_ADC_Handler(void)200 int MXC_ADC_Handler(void)
201 {
202 return MXC_ADC_RevB_Handler((mxc_adc_revb_regs_t *)MXC_ADC);
203 }
204
MXC_ADC_GetData(int * outdata)205 int MXC_ADC_GetData(int *outdata)
206 {
207 return MXC_ADC_RevB_GetData((mxc_adc_revb_regs_t *)MXC_ADC, outdata);
208 }
209
MXC_ADC_InputDividerSelect(mxc_adc_chsel_t ch,mxc_adc_divsel_t div,mxc_adc_dynamic_pullup_t lpEn)210 int MXC_ADC_InputDividerSelect(mxc_adc_chsel_t ch, mxc_adc_divsel_t div,
211 mxc_adc_dynamic_pullup_t lpEn)
212 {
213 uint32_t bitOffset;
214
215 if (ch > MXC_ADC_CH_7 || div > MXC_ADC_DIV2_50K) {
216 return E_BAD_PARAM;
217 }
218
219 bitOffset = ch << 1;
220 MXC_MCR->adccfg2 &= ~(MXC_F_MCR_ADCCFG2_CH << bitOffset);
221 MXC_MCR->adccfg2 |= (div << bitOffset);
222
223 if (lpEn == MXC_ADC_PY_DN_DISABLE) {
224 MXC_ADC_DynamicModeDis(ch);
225 } else {
226 MXC_ADC_DynamicModeEn(ch);
227 }
228
229 return E_NO_ERROR;
230 }
231
MXC_ADC_ReferenceSelect(mxc_adc_refsel_t ref)232 int MXC_ADC_ReferenceSelect(mxc_adc_refsel_t ref)
233 {
234 switch (ref) {
235 case MXC_ADC_REF_EXT:
236 MXC_MCR->adccfg0 |= MXC_F_MCR_ADCCFG0_EXT_REF;
237 break;
238 case MXC_ADC_REF_INT_1V25:
239 MXC_MCR->adccfg0 &= ~(MXC_F_MCR_ADCCFG0_EXT_REF | MXC_F_MCR_ADCCFG0_REF_SEL);
240 break;
241 case MXC_ADC_REF_INT_2V048:
242 MXC_MCR->adccfg0 &= ~MXC_F_MCR_ADCCFG0_EXT_REF;
243 MXC_MCR->adccfg0 |= MXC_F_MCR_ADCCFG0_REF_SEL;
244 break;
245 default:
246 return E_BAD_PARAM;
247 }
248
249 return E_NO_ERROR;
250 }
251
MXC_ADC_LowPowerModeDividerSelect(mxc_adc_div_lpmode_t div_lpmode)252 int MXC_ADC_LowPowerModeDividerSelect(mxc_adc_div_lpmode_t div_lpmode)
253 {
254 MXC_MCR->adccfg0 &= ~(MXC_F_MCR_ADCCFG0_LP_5K_DIS | MXC_F_MCR_ADCCFG0_LP_50K_DIS);
255 MXC_MCR->adccfg0 |= div_lpmode;
256
257 return E_NO_ERROR;
258 }
259
MXC_ADC_EnableConversion(void)260 void MXC_ADC_EnableConversion(void)
261 {
262 MXC_ADC_RevB_EnableConversion((mxc_adc_revb_regs_t *)MXC_ADC);
263 }
264
MXC_ADC_DisableConversion(void)265 void MXC_ADC_DisableConversion(void)
266 {
267 MXC_ADC_RevB_DisableConversion((mxc_adc_revb_regs_t *)MXC_ADC);
268 }
269
MXC_ADC_TS_SelectEnable(void)270 void MXC_ADC_TS_SelectEnable(void)
271 {
272 MXC_ADC_RevB_TS_SelectEnable((mxc_adc_revb_regs_t *)MXC_ADC);
273 }
274
MXC_ADC_TS_SelectDisable(void)275 void MXC_ADC_TS_SelectDisable(void)
276 {
277 MXC_ADC_RevB_TS_SelectDisable((mxc_adc_revb_regs_t *)MXC_ADC);
278 }
279
MXC_ADC_FIFO_Level(void)280 uint16_t MXC_ADC_FIFO_Level(void)
281 {
282 return MXC_ADC_RevB_FIFO_Level((mxc_adc_revb_regs_t *)MXC_ADC);
283 }
284
MXC_ADC_FIFO_Threshold_Config(uint32_t fifo_threshold)285 int MXC_ADC_FIFO_Threshold_Config(uint32_t fifo_threshold)
286 {
287 return MXC_ADC_RevB_FIFO_Threshold_Config((mxc_adc_revb_regs_t *)MXC_ADC, fifo_threshold);
288 }
289
MXC_ADC_AverageConfig(mxc_adc_avg_t avg_number)290 int MXC_ADC_AverageConfig(mxc_adc_avg_t avg_number)
291 {
292 return MXC_ADC_RevB_AverageConfig((mxc_adc_revb_regs_t *)MXC_ADC, avg_number);
293 }
294
MXC_ADC_Clear_ChannelSelect(void)295 void MXC_ADC_Clear_ChannelSelect(void)
296 {
297 MXC_ADC_RevB_Clear_ChannelSelect((mxc_adc_revb_regs_t *)MXC_ADC);
298 }
299
MXC_ADC_TriggerConfig(mxc_adc_conversion_req_t * req)300 void MXC_ADC_TriggerConfig(mxc_adc_conversion_req_t *req)
301 {
302 initGPIOforHWTrig(req->hwTrig);
303 MXC_ADC_RevB_TriggerConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
304 }
305
MXC_ADC_ConversionModeConfig(mxc_adc_conversion_req_t * req)306 void MXC_ADC_ConversionModeConfig(mxc_adc_conversion_req_t *req)
307 {
308 MXC_ADC_RevB_ConversionModeConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
309 }
310
MXC_ADC_SetConversionDelay(int delay)311 void MXC_ADC_SetConversionDelay(int delay)
312 {
313 MXC_ADC_RevB_SetConversionDelay((mxc_adc_revb_regs_t *)MXC_ADC, delay);
314 }
315
MXC_ADC_SlotsConfig(mxc_adc_conversion_req_t * req)316 int MXC_ADC_SlotsConfig(mxc_adc_conversion_req_t *req)
317 {
318 return MXC_ADC_RevB_SlotsConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
319 }
320
MXC_ADC_ChSelectConfig(mxc_adc_chsel_t ch,uint32_t slot_num)321 int MXC_ADC_ChSelectConfig(mxc_adc_chsel_t ch, uint32_t slot_num)
322 {
323 return MXC_ADC_RevB_ChSelectConfig((mxc_adc_revb_regs_t *)MXC_ADC, ch, slot_num);
324 }
325
MXC_ADC_Configuration(mxc_adc_conversion_req_t * req)326 int MXC_ADC_Configuration(mxc_adc_conversion_req_t *req)
327 {
328 MXC_ADC_ConversionModeConfig(req);
329
330 MXC_ADC_TriggerConfig(req);
331
332 MXC_ADC_FIFO_Threshold_Config(req->fifo_threshold);
333
334 MXC_ADC_SlotsConfig(req);
335
336 MXC_ADC_Clear_ChannelSelect();
337
338 //number of samples to average
339 MXC_ADC_AverageConfig(req->avg_number);
340
341 MXC_ADC_LowPowerModeDividerSelect(req->lpmode_divder);
342
343 return E_NO_ERROR;
344 }
345
MXC_ADC_SlotConfiguration(mxc_adc_slot_req_t * req,uint32_t slot_length)346 int MXC_ADC_SlotConfiguration(mxc_adc_slot_req_t *req, uint32_t slot_length)
347 {
348 uint32_t loop_counter = 0;
349
350 for (loop_counter = 0; loop_counter <= slot_length; loop_counter++) {
351 initGPIOForChannel(req->channel);
352
353 if (req->channel <= MAX_ADC_RES_DIV_CH) {
354 MXC_ADC_InputDividerSelect(req->channel, req->div, req->pullup_dyn);
355 }
356
357 MXC_ADC_ChSelectConfig(req->channel, loop_counter);
358 req++;
359 }
360 return E_NO_ERROR;
361 }
362
MXC_ConvertTemperature_ToK(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp_k)363 int MXC_ConvertTemperature_ToK(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
364 float *temp_k)
365 {
366 switch (ref) {
367 case MXC_ADC_REF_EXT:
368 *temp_k = tempSensor_Readout * TEMP_FACTOR * ext_ref;
369 break;
370
371 case MXC_ADC_REF_INT_1V25:
372 *temp_k = tempSensor_Readout * TEMP_FACTOR1V25;
373 break;
374
375 case MXC_ADC_REF_INT_2V048:
376 *temp_k = tempSensor_Readout * TEMP_FACTOR2V048;
377 break;
378
379 default:
380 return E_BAD_PARAM;
381 }
382 return E_NO_ERROR;
383 }
384
MXC_ConvertTemperature_ToC(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp)385 int MXC_ConvertTemperature_ToC(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
386 float *temp)
387 {
388 if (MXC_ConvertTemperature_ToK(tempSensor_Readout, ref, ext_ref, temp) == E_NO_ERROR) {
389 *temp = *temp - 273.15f;
390 return E_NO_ERROR;
391 } else {
392 return E_BAD_PARAM;
393 }
394 }
395
MXC_ConvertTemperature_ToF(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp)396 int MXC_ConvertTemperature_ToF(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
397 float *temp)
398 {
399 if (MXC_ConvertTemperature_ToK(tempSensor_Readout, ref, ext_ref, temp) == E_NO_ERROR) {
400 *temp = (*temp * 1.8f) - 459.67f;
401 return E_NO_ERROR;
402 } else {
403 return E_BAD_PARAM;
404 }
405 }
406
MXC_ADC_DynamicModeEn(mxc_adc_chsel_t ch)407 int MXC_ADC_DynamicModeEn(mxc_adc_chsel_t ch)
408 {
409 if (ch > MXC_ADC_CH_7) {
410 return E_BAD_PARAM;
411 }
412
413 MXC_MCR->adccfg1 |= (1 << ch);
414
415 return E_NO_ERROR;
416 }
417
MXC_ADC_DynamicModeDis(mxc_adc_chsel_t ch)418 int MXC_ADC_DynamicModeDis(mxc_adc_chsel_t ch)
419 {
420 if (ch > MXC_ADC_CH_7) {
421 return E_BAD_PARAM;
422 }
423
424 MXC_MCR->adccfg1 &= ~(1 << ch);
425
426 return E_NO_ERROR;
427 }
428