1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2023 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_lpadc.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.lpadc"
17 #endif
18 
19 #ifndef ADC_VERID_DIFFEN_MASK
20 #define ADC_VERID_DIFFEN_MASK (0x2U)
21 #endif /* ADC_VERID_DIFFEN_MASK */
22 
23 #ifndef ADC_VERID_NUM_SEC_MASK
24 #define ADC_VERID_NUM_SEC_MASK (0x800U)
25 #endif /* ADC_VERID_NUM_SEC_MASK */
26 
27 #define ADC_CMDL_CHANNEL_MODE_MASK  (0x60U)
28 #define ADC_CMDL_CHANNEL_MODE_SHIFT (5U)
29 #define ADC_CMDL_CHANNEL_MODE(x) \
30     (((uint32_t)(((uint32_t)(x)) << ADC_CMDL_CHANNEL_MODE_SHIFT)) & ADC_CMDL_CHANNEL_MODE_MASK)
31 
32 #define GET_ADC_CFG_TPRICTRL_VALUE(val) (((uint32_t)val) & 0x3U)
33 
34 #if defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES
35 #define GET_ADC_CFG_TRES_VALUE(val) ((((uint32_t)val) & 0x4U) >> 2U)
36 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES */
37 
38 #if defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES
39 #define GET_ADC_CFG_TCMDRES_VALUE(val) ((((uint32_t)val) & 0x8U) >> 3U)
40 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES */
41 
42 #if defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI
43 #define GET_ADC_CFG_HPT_EXDI_VALUE(val) ((((uint32_t)val) & 0x10U) >> 4U)
44 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI */
45 
46 #if defined(LPADC_RSTS)
47 #define LPADC_RESETS_ARRAY LPADC_RSTS
48 #elif defined(ADC_RSTS)
49 #define LPADC_RESETS_ARRAY ADC_RSTS
50 #endif
51 
52 /*******************************************************************************
53  * Prototypes
54  ******************************************************************************/
55 /*!
56  * @brief Get instance number for LPADC module.
57  *
58  * @param base LPADC peripheral base address
59  */
60 static uint32_t LPADC_GetInstance(ADC_Type *base);
61 
62 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ
63 /*!
64  * @brief Get gain conversion result .
65  *
66  * @param gainAdjustment gain adjustment value.
67  */
68 static uint32_t LPADC_GetGainConvResult(float gainAdjustment);
69 #endif /* defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
70 
71 /*******************************************************************************
72  * Variables
73  ******************************************************************************/
74 /*! @brief Pointers to LPADC bases for each instance. */
75 static ADC_Type *const s_lpadcBases[] = ADC_BASE_PTRS;
76 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
77 /*! @brief Pointers to LPADC clocks for each instance. */
78 static const clock_ip_name_t s_lpadcClocks[] = LPADC_CLOCKS;
79 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
80 #if defined(LPADC_RESETS_ARRAY)
81 /* Reset array */
82 static const reset_ip_name_t s_lpadcResets[] = LPADC_RESETS_ARRAY;
83 #endif
84 
85 /*******************************************************************************
86  * Code
87  ******************************************************************************/
LPADC_GetInstance(ADC_Type * base)88 static uint32_t LPADC_GetInstance(ADC_Type *base)
89 {
90     uint32_t instance;
91 
92     /* Find the instance index from base address mappings. */
93     /*
94      * $Branch Coverage Justification$
95      * (instance >= ARRAY_SIZE(s_lpadcBases)) not covered. The peripheral base
96      * address is always valid and checked by assert.
97      */
98     for (instance = 0; instance < ARRAY_SIZE(s_lpadcBases); instance++)
99     {
100         /*
101          * $Branch Coverage Justification$
102          * (s_lpadcBases[instance] != base) not covered. The peripheral base
103          * address is always valid and checked by assert.
104          */
105         if (MSDK_REG_SECURE_ADDR(s_lpadcBases[instance]) == MSDK_REG_SECURE_ADDR(base))
106         {
107             break;
108         }
109     }
110 
111     assert(instance < ARRAY_SIZE(s_lpadcBases));
112 
113     return instance;
114 }
115 
116 #if (defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ)
117 /*!
118  * brief  Get gain conversion Result .
119  *
120  * param gainAdjustment gain adjustment value.
121  */
LPADC_GetGainConvResult(float gainAdjustment)122 static uint32_t LPADC_GetGainConvResult(float gainAdjustment)
123 {
124     uint16_t i        = 0U;
125     uint32_t tmp32    = 0U;
126     uint32_t GCRa[17] = {0};
127     uint32_t GCALR    = 0U;
128 
129     for (i = 0x11U; i > 0U; i--)
130     {
131         tmp32          = (uint32_t)((gainAdjustment) / ((float)(1.0 / (double)(1U << (0x10U - (i - 1U))))));
132         GCRa[i - 1U]   = tmp32;
133         gainAdjustment = gainAdjustment - ((float)tmp32) * ((float)(1.0 / (double)(1U << (0x10U - (i - 1U)))));
134     }
135     /* Get GCALR value calculated */
136     for (i = 0x11U; i > 0U; i--)
137     {
138         GCALR += GCRa[i - 1U] * ((uint32_t)(1UL << (uint32_t)(i - 1UL)));
139     }
140 
141     /* to return GCALR value calculated */
142     return GCALR;
143 }
144 #endif /* defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
145 
146 /*!
147  * brief Initializes the LPADC module.
148  *
149  * param base   LPADC peripheral base address.
150  * param config Pointer to configuration structure. See "lpadc_config_t".
151  */
LPADC_Init(ADC_Type * base,const lpadc_config_t * config)152 void LPADC_Init(ADC_Type *base, const lpadc_config_t *config)
153 {
154     /* Check if the pointer is available. */
155     assert(config != NULL);
156 
157     uint32_t tmp32 = 0U;
158 
159 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
160     /* Enable the clock for LPADC instance. */
161     (void)CLOCK_EnableClock(s_lpadcClocks[LPADC_GetInstance(base)]);
162 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
163 
164 #if defined(LPADC_RESETS_ARRAY)
165     RESET_ReleasePeripheralReset(s_lpadcResets[LPADC_GetInstance(base)]);
166 #endif
167 
168     /* Reset the module. */
169     LPADC_DoResetConfig(base);
170 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
171     LPADC_DoResetFIFO0(base);
172     LPADC_DoResetFIFO1(base);
173 #else
174     LPADC_DoResetFIFO(base);
175 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
176 
177     /* Disable the module before setting configuration. */
178     LPADC_Enable(base, false);
179 
180     /* Configure the module generally. */
181     if (config->enableInDozeMode)
182     {
183         base->CTRL &= ~ADC_CTRL_DOZEN_MASK;
184     }
185     else
186     {
187         base->CTRL |= ADC_CTRL_DOZEN_MASK;
188     }
189 
190 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS
191     /* Set calibration average mode. */
192     base->CTRL |= ADC_CTRL_CAL_AVGS(config->conversionAverageMode);
193 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS */
194 
195 /* ADCx_CFG. */
196 #if defined(FSL_FEATURE_LPADC_HAS_CFG_ADCKEN) && FSL_FEATURE_LPADC_HAS_CFG_ADCKEN
197     if (config->enableInternalClock)
198     {
199         tmp32 |= ADC_CFG_ADCKEN_MASK;
200     }
201 #endif /* FSL_FEATURE_LPADC_HAS_CFG_ADCKEN */
202 #if defined(FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG) && FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG
203     if (config->enableVref1LowVoltage)
204     {
205         tmp32 |= ADC_CFG_VREF1RNG_MASK;
206     }
207 #endif /* FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG */
208     if (config->enableAnalogPreliminary)
209     {
210         tmp32 |= ADC_CFG_PWREN_MASK;
211     }
212     tmp32 |= (ADC_CFG_PUDLY(config->powerUpDelay)              /* Power up delay. */
213               | ADC_CFG_REFSEL(config->referenceVoltageSource) /* Reference voltage. */
214 #if defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U)
215               | ADC_CFG_PWRSEL(config->powerLevelMode)         /* Power configuration. */
216 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U) */
217     );
218 
219     tmp32 |= ADC_CFG_TPRICTRL(GET_ADC_CFG_TPRICTRL_VALUE(config->triggerPriorityPolicy));
220 
221 #if (defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES)
222     tmp32 |= ADC_CFG_TRES(GET_ADC_CFG_TRES_VALUE(config->triggerPriorityPolicy));
223 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES */
224 
225 #if (defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES)
226     tmp32 |= ADC_CFG_TCMDRES(GET_ADC_CFG_TCMDRES_VALUE(config->triggerPriorityPolicy));
227 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES */
228 
229 #if (defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI)
230     tmp32 |= ADC_CFG_HPT_EXDI(GET_ADC_CFG_HPT_EXDI_VALUE(config->triggerPriorityPolicy));
231 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI */
232 
233     base->CFG = tmp32;
234 
235     /* ADCx_PAUSE. */
236     if (config->enableConvPause)
237     {
238         base->PAUSE = ADC_PAUSE_PAUSEEN_MASK | ADC_PAUSE_PAUSEDLY(config->convPauseDelay);
239     }
240     else
241     {
242         base->PAUSE = 0U;
243     }
244 
245 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
246     /* ADCx_FCTRL0. */
247     base->FCTRL[0] = ADC_FCTRL_FWMARK(config->FIFO0Watermark);
248     /* ADCx_FCTRL1. */
249     base->FCTRL[1] = ADC_FCTRL_FWMARK(config->FIFO1Watermark);
250 #else
251     /* ADCx_FCTRL. */
252     base->FCTRL           = ADC_FCTRL_FWMARK(config->FIFOWatermark);
253 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
254 
255     /* Enable the module after setting configuration. */
256     LPADC_Enable(base, true);
257 }
258 
259 /*!
260  * brief Gets an available pre-defined settings for initial configuration.
261  *
262  * This function initializes the converter configuration structure with an available settings. The default values are:
263  * code
264  *   config->enableInDozeMode        = true;
265  *   config->conversionAverageMode   = kLPADC_ConversionAverage1;
266  *   config->enableAnalogPreliminary = false;
267  *   config->powerUpDelay            = 0x80;
268  *   config->referenceVoltageSource  = kLPADC_ReferenceVoltageAlt1;
269  *   config->powerLevelMode          = kLPADC_PowerLevelAlt1;
270  *   config->triggerPriorityPolicy   = kLPADC_TriggerPriorityPreemptImmediately;
271  *   config->enableConvPause         = false;
272  *   config->convPauseDelay          = 0U;
273  *   config->FIFO0Watermark          = 0U;
274  *   config->FIFO1Watermark          = 0U;
275  *   config->FIFOWatermark           = 0U;
276  * endcode
277  * param config Pointer to configuration structure.
278  */
LPADC_GetDefaultConfig(lpadc_config_t * config)279 void LPADC_GetDefaultConfig(lpadc_config_t *config)
280 {
281     /* Initializes the configure structure to zero. */
282     (void)memset(config, 0, sizeof(*config));
283 
284 #if defined(FSL_FEATURE_LPADC_HAS_CFG_ADCKEN) && FSL_FEATURE_LPADC_HAS_CFG_ADCKEN
285     config->enableInternalClock = false;
286 #endif /* FSL_FEATURE_LPADC_HAS_CFG_ADCKEN */
287 #if defined(FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG) && FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG
288     config->enableVref1LowVoltage = false;
289 #endif /* FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG */
290     config->enableInDozeMode = true;
291 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS
292     /* Set calibration average mode. */
293     config->conversionAverageMode = kLPADC_ConversionAverage1;
294 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS */
295     config->enableAnalogPreliminary = false;
296     config->powerUpDelay            = 0x80;
297     config->referenceVoltageSource  = kLPADC_ReferenceVoltageAlt1;
298 #if defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U)
299     config->powerLevelMode = kLPADC_PowerLevelAlt1;
300 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U) */
301     config->triggerPriorityPolicy = kLPADC_TriggerPriorityPreemptImmediately;
302     config->enableConvPause       = false;
303     config->convPauseDelay        = 0U;
304 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
305     config->FIFO0Watermark = 0U;
306     config->FIFO1Watermark = 0U;
307 #else
308     config->FIFOWatermark = 0U;
309 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
310 }
311 
312 /*!
313  * brief De-initializes the LPADC module.
314  *
315  * param base LPADC peripheral base address.
316  */
LPADC_Deinit(ADC_Type * base)317 void LPADC_Deinit(ADC_Type *base)
318 {
319     /* Disable the module. */
320     LPADC_Enable(base, false);
321 
322 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
323     /* Gate the clock. */
324     (void)CLOCK_DisableClock(s_lpadcClocks[LPADC_GetInstance(base)]);
325 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
326 }
327 
328 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
329 /*!
330  * brief Get the result in conversion FIFOn.
331  *
332  * param base LPADC peripheral base address.
333  * param result Pointer to structure variable that keeps the conversion result in conversion FIFOn.
334  * param index Result FIFO index.
335  *
336  * return Status whether FIFOn entry is valid.
337  */
LPADC_GetConvResult(ADC_Type * base,lpadc_conv_result_t * result,uint8_t index)338 bool LPADC_GetConvResult(ADC_Type *base, lpadc_conv_result_t *result, uint8_t index)
339 {
340     assert(result != NULL); /* Check if the input pointer is available. */
341 
342     uint32_t tmp32 = 0U;
343 
344     tmp32 = base->RESFIFO[index];
345 
346     if (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
347     {
348         return false; /* FIFO is empty. Discard any read from RESFIFO. */
349     }
350 
351     result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
352     result->loopCountIndex  = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
353     result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
354     result->convValue       = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
355 
356     return true;
357 }
358 /*!
359  * brief Get the result in conversion FIFOn using blocking method.
360  *
361  * param base LPADC peripheral base address.
362  * param result Pointer to structure variable that keeps the conversion result in conversion FIFOn.
363  * param index Result FIFO index.
364  */
LPADC_GetConvResultBlocking(ADC_Type * base,lpadc_conv_result_t * result,uint8_t index)365 void LPADC_GetConvResultBlocking(ADC_Type *base, lpadc_conv_result_t *result, uint8_t index)
366 {
367     assert(result != NULL); /* Check if the input pointer is available. */
368 
369     uint32_t tmp32 = 0U;
370 
371     tmp32 = base->RESFIFO[index];
372 
373     while (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
374     {
375         tmp32 = base->RESFIFO[index];
376     }
377 
378     result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
379     result->loopCountIndex  = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
380     result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
381     result->convValue       = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
382 }
383 #else
384 /*!
385  * brief Get the result in conversion FIFO.
386  *
387  * param base LPADC peripheral base address.
388  * param result Pointer to structure variable that keeps the conversion result in conversion FIFO.
389  *
390  * return Status whether FIFO entry is valid.
391  */
LPADC_GetConvResult(ADC_Type * base,lpadc_conv_result_t * result)392 bool LPADC_GetConvResult(ADC_Type *base, lpadc_conv_result_t *result)
393 {
394     assert(result != NULL); /* Check if the input pointer is available. */
395 
396     uint32_t tmp32 = 0U;
397 
398     tmp32 = base->RESFIFO;
399 
400     if (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
401     {
402         return false; /* FIFO is empty. Discard any read from RESFIFO. */
403     }
404 
405     result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
406     result->loopCountIndex  = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
407     result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
408     result->convValue       = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
409 
410     return true;
411 }
412 /*!
413  * @brief Get the result in conversion FIFO using blocking method.
414  *
415  * @param base LPADC peripheral base address.
416  * @param result Pointer to structure variable that keeps the conversion result in conversion FIFO.
417  */
LPADC_GetConvResultBlocking(ADC_Type * base,lpadc_conv_result_t * result)418 void LPADC_GetConvResultBlocking(ADC_Type *base, lpadc_conv_result_t *result)
419 {
420     assert(result != NULL); /* Check if the input pointer is available. */
421 
422     uint32_t tmp32 = 0U;
423 
424     tmp32 = base->RESFIFO;
425 
426     while (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
427     {
428         tmp32 = base->RESFIFO;
429     }
430 
431     result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
432     result->loopCountIndex  = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
433     result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
434     result->convValue       = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
435 }
436 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
437 
438 /*!
439  * brief Configure the conversion trigger source.
440  *
441  * Each programmable trigger can launch the conversion command in command buffer.
442  *
443  * param base LPADC peripheral base address.
444  * param triggerId ID for each trigger. Typically, the available value range is from 0 to 3.
445  * param config Pointer to configuration structure. See to #lpadc_conv_trigger_config_t.
446  */
LPADC_SetConvTriggerConfig(ADC_Type * base,uint32_t triggerId,const lpadc_conv_trigger_config_t * config)447 void LPADC_SetConvTriggerConfig(ADC_Type *base, uint32_t triggerId, const lpadc_conv_trigger_config_t *config)
448 {
449     assert(triggerId < ADC_TCTRL_COUNT); /* Check if the triggerId is available in this device. */
450     assert(config != NULL);              /* Check if the input pointer is available. */
451 
452     uint32_t tmp32;
453 
454     tmp32 = ADC_TCTRL_TCMD(config->targetCommandId) /* Trigger command select. */
455             | ADC_TCTRL_TDLY(config->delayPower)    /* Trigger delay select. */
456             | ADC_TCTRL_TPRI(config->priority)      /* Trigger priority setting. */
457 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
458             | ADC_TCTRL_FIFO_SEL_A(config->channelAFIFOSelect)
459 #if !(defined(FSL_FEATURE_LPADC_HAS_NO_TCTRL_FIFO_SEL_B) && FSL_FEATURE_LPADC_HAS_NO_TCTRL_FIFO_SEL_B)
460             | ADC_TCTRL_FIFO_SEL_B(config->channelBFIFOSelect)
461 #endif /* FSL_FEATURE_LPADC_HAS_NO_TCTRL_FIFO_SEL_B  */
462 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
463         ;
464     if (config->enableHardwareTrigger)
465     {
466         tmp32 |= ADC_TCTRL_HTEN_MASK;
467     }
468 
469     base->TCTRL[triggerId] = tmp32;
470 }
471 
472 /*!
473  * brief Gets an available pre-defined settings for trigger's configuration.
474  *
475  * This function initializes the trigger's configuration structure with an available settings. The default values are:
476  * code
477  *   config->targetCommandId        = 0U;
478  *   config->delayPower             = 0U;
479  *   config->priority               = 0U;
480  *   config->channelAFIFOSelect     = 0U;
481  *   config->channelBFIFOSelect     = 0U;
482  *   config->enableHardwareTrigger  = false;
483  * endcode
484  * param config Pointer to configuration structure.
485  */
LPADC_GetDefaultConvTriggerConfig(lpadc_conv_trigger_config_t * config)486 void LPADC_GetDefaultConvTriggerConfig(lpadc_conv_trigger_config_t *config)
487 {
488     assert(config != NULL); /* Check if the input pointer is available. */
489 
490     /* Initializes the configure structure to zero. */
491     (void)memset(config, 0, sizeof(*config));
492 
493     config->targetCommandId = 0U;
494     config->delayPower      = 0U;
495     config->priority        = 0U;
496 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
497     config->channelAFIFOSelect = 0U;
498     config->channelBFIFOSelect = 0U;
499 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
500     config->enableHardwareTrigger = false;
501 }
502 
503 /*!
504  * brief Configure conversion command.
505  *
506  * note The number of compare value register on different chips is different, that is mean in some chips, some
507  * command buffers do not have the compare functionality.
508  *
509  * param base LPADC peripheral base address.
510  * param commandId ID for command in command buffer. Typically, the available value range is 1 - 15.
511  * param config Pointer to configuration structure. See to #lpadc_conv_command_config_t.
512  */
LPADC_SetConvCommandConfig(ADC_Type * base,uint32_t commandId,const lpadc_conv_command_config_t * config)513 void LPADC_SetConvCommandConfig(ADC_Type *base, uint32_t commandId, const lpadc_conv_command_config_t *config)
514 {
515     assert(commandId < (ADC_CMDL_COUNT + 1U)); /* Check if the commandId is available on this device. */
516     assert(config != NULL);                    /* Check if the input pointer is available. */
517 
518     uint32_t tmp32 = 0;
519 
520     commandId--; /* The available command number are 1-15, while the index of register group are 0-14. */
521 
522     /* ADCx_CMDL. */
523     tmp32 = ADC_CMDL_ADCH(config->channelNumber);        /* Channel number. */
524 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH
525     tmp32 |= ADC_CMDL_ALTB_ADCH(config->channelBNumber); /* Alternate channel B number. */
526 #endif
527 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
528     tmp32 |= ADC_CMDL_CSCALE(config->sampleScaleMode);        /* Full/Part scale input voltage. */
529 #endif                                                        /* FSL_FEATURE_LPADC_HAS_CMDL_CSCALE */
530 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE
531     tmp32 |= ADC_CMDL_ALTB_CSCALE(config->channelBScaleMode); /* Alternate channel B full/Part scale input voltage. */
532 #endif                                                        /* FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE */
533 
534 #if !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U))
535 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF
536     assert(((config->sampleChannelMode >= kLPADC_SampleChannelDiffBothSideAB) &&
537             (((base->VERID) & ADC_VERID_DIFFEN_MASK) != 0U)) ||
538            (config->sampleChannelMode < kLPADC_SampleChannelDiffBothSideAB));
539 #endif /* defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF */
540 
541 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_CTYPE) && FSL_FEATURE_LPADC_HAS_CMDL_CTYPE
542     assert(((config->sampleChannelMode == kLPADC_SampleChannelDiffBothSide) &&
543             (((base->VERID) & ADC_VERID_DIFFEN_MASK) != 0U)) ||
544            ((config->sampleChannelMode == kLPADC_SampleChannelDualSingleEndBothSide) &&
545             (((base->VERID) & ADC_VERID_NUM_SEC_MASK) != 0U)) ||
546            (config->sampleChannelMode < kLPADC_SampleChannelDualSingleEndBothSide));
547 #endif /* defined(FSL_FEATURE_LPADC_HAS_CMDL_CTYPE) && FSL_FEATURE_LPADC_HAS_CMDL_CTYPE */
548 #endif /* !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U)) */
549 
550     tmp32 |= ADC_CMDL_CHANNEL_MODE(config->sampleChannelMode);
551 
552 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_MODE) && FSL_FEATURE_LPADC_HAS_CMDL_MODE
553     tmp32 |= ADC_CMDL_MODE(config->conversionResolutionMode);
554 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_MODE */
555 
556 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN) && FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN
557     /* Enable alternate channel B.*/
558     if (config->enableChannelB)
559     {
560         tmp32 |= ADC_CMDL_ALTBEN_MASK;
561     }
562 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN */
563 
564     base->CMD[commandId].CMDL = tmp32;
565 
566     /* ADCx_CMDH. */
567     tmp32 = ADC_CMDH_NEXT(config->chainedNextCommandNumber) /* Next Command Select. */
568             | ADC_CMDH_LOOP(config->loopCount)              /* Loop Count Select. */
569             | ADC_CMDH_AVGS(config->hardwareAverageMode)    /* Hardware Average Select. */
570             | ADC_CMDH_STS(config->sampleTimeMode)          /* Sample Time Select. */
571             | ADC_CMDH_CMPEN(config->hardwareCompareMode);  /* Hardware compare enable. */
572 #if (defined(FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG) && FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG)
573     if (config->enableWaitTrigger)
574     {
575         tmp32 |= ADC_CMDH_WAIT_TRIG_MASK; /* Wait trigger enable. */
576     }
577 #endif                                    /* FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG */
578 
579     if (config->enableAutoChannelIncrement)
580     {
581         tmp32 |= ADC_CMDH_LWI_MASK;
582     }
583     base->CMD[commandId].CMDH = tmp32;
584 
585     /* Hardware compare settings.
586      * Not all Command Buffers have an associated Compare Value register. The compare function is only available on
587      * Command Buffers that have a corresponding Compare Value register. Therefore, assertion judgment needs to be
588      * made before setting the CV register.
589      */
590 
591     if ((kLPADC_HardwareCompareDisabled != config->hardwareCompareMode) && (commandId < ADC_CV_COUNT))
592     {
593         /* Set CV register. */
594         base->CV[commandId] = (ADC_CV_CVH(config->hardwareCompareValueHigh)    /* Compare value high. */
595                                | ADC_CV_CVL(config->hardwareCompareValueLow)); /* Compare value low. */
596     }
597 }
598 
599 /*!
600  * brief Gets an available pre-defined settings for conversion command's configuration.
601  *
602  * This function initializes the conversion command's configuration structure with an available settings. The default
603  * values are:
604  * code
605  *   config->sampleScaleMode            = kLPADC_SampleFullScale;
606  *   config->channelBScaleMode          = kLPADC_SampleFullScale;
607  *   config->sampleChannelMode          = kLPADC_SampleChannelSingleEndSideA;
608  *   config->channelNumber              = 0U;
609  *   config->channelBNumber             = 0U;
610  *   config->chainedNextCommandNumber   = 0U;
611  *   config->enableAutoChannelIncrement = false;
612  *   config->loopCount                  = 0U;
613  *   config->hardwareAverageMode        = kLPADC_HardwareAverageCount1;
614  *   config->sampleTimeMode             = kLPADC_SampleTimeADCK3;
615  *   config->hardwareCompareMode        = kLPADC_HardwareCompareDisabled;
616  *   config->hardwareCompareValueHigh   = 0U;
617  *   config->hardwareCompareValueLow    = 0U;
618  *   config->conversionResolutionMode   = kLPADC_ConversionResolutionStandard;
619  *   config->enableWaitTrigger          = false;
620  *   config->enableChannelB             = false;
621  * endcode
622  * param config Pointer to configuration structure.
623  */
LPADC_GetDefaultConvCommandConfig(lpadc_conv_command_config_t * config)624 void LPADC_GetDefaultConvCommandConfig(lpadc_conv_command_config_t *config)
625 {
626     assert(config != NULL); /* Check if the input pointer is available. */
627 
628     /* Initializes the configure structure to zero. */
629     (void)memset(config, 0, sizeof(*config));
630 
631 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
632     config->sampleScaleMode = kLPADC_SampleFullScale;
633 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_CSCALE */
634 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE
635     config->channelBScaleMode = kLPADC_SampleFullScale;
636 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE */
637     config->sampleChannelMode = kLPADC_SampleChannelSingleEndSideA;
638     config->channelNumber     = 0U;
639 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH
640     config->channelBNumber = 0U;
641 #endif                                       /* FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE */
642     config->chainedNextCommandNumber   = 0U; /* No next command defined. */
643     config->enableAutoChannelIncrement = false;
644     config->loopCount                  = 0U;
645     config->hardwareAverageMode        = kLPADC_HardwareAverageCount1;
646     config->sampleTimeMode             = kLPADC_SampleTimeADCK3;
647     config->hardwareCompareMode        = kLPADC_HardwareCompareDisabled;
648     config->hardwareCompareValueHigh   = 0U; /* No used. */
649     config->hardwareCompareValueLow    = 0U; /* No used. */
650 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_MODE) && FSL_FEATURE_LPADC_HAS_CMDL_MODE
651     config->conversionResolutionMode = kLPADC_ConversionResolutionStandard;
652 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_MODE */
653 #if defined(FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG) && FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG
654     config->enableWaitTrigger = false;
655 #endif                              /* FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG */
656 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN) && FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN
657     config->enableChannelB = false; /* Enable alternate channel B.*/
658 #endif                              /* FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN */
659 }
660 
661 #if defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) && FSL_FEATURE_LPADC_HAS_CFG_CALOFS
662 /*!
663  * brief Enable the calibration function.
664  *
665  * When CALOFS is set, the ADC is configured to perform a calibration function anytime the ADC executes
666  * a conversion. Any channel selected is ignored and the value returned in the RESFIFO is a signed value
667  * between -31 and 31. -32 is not a valid and is never a returned value. Software should copy the lower 6-
668  * bits of the conversion result stored in the RESFIFO after a completed calibration conversion to the
669  * OFSTRIM field. The OFSTRIM field is used in normal operation for offset correction.
670  *
671  * param base LPADC peripheral base address.
672  * param enable switcher to the calibration function.
673  */
LPADC_EnableCalibration(ADC_Type * base,bool enable)674 void LPADC_EnableCalibration(ADC_Type *base, bool enable)
675 {
676     LPADC_Enable(base, false);
677     if (enable)
678     {
679         base->CFG |= ADC_CFG_CALOFS_MASK;
680     }
681     else
682     {
683         base->CFG &= ~ADC_CFG_CALOFS_MASK;
684     }
685     LPADC_Enable(base, true);
686 }
687 
688 #if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM
689 /*!
690  * brief Do auto calibration.
691  *
692  * Calibration function should be executed before using converter in application. It used the software trigger and a
693  * dummy conversion, get the offset and write them into the OFSTRIM register. It called some of functional API
694  * including: -LPADC_EnableCalibration(...) -LPADC_LPADC_SetOffsetValue(...) -LPADC_SetConvCommandConfig(...)
695  *   -LPADC_SetConvTriggerConfig(...)
696  *
697  * param base  LPADC peripheral base address.
698  */
LPADC_DoAutoCalibration(ADC_Type * base)699 void LPADC_DoAutoCalibration(ADC_Type *base)
700 {
701     assert(0u == LPADC_GetConvResultCount(base));
702 
703     uint32_t mLpadcCMDL;
704     uint32_t mLpadcCMDH;
705     uint32_t mLpadcTrigger;
706     lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct;
707     lpadc_conv_command_config_t mLpadcCommandConfigStruct;
708     lpadc_conv_result_t mLpadcResultConfigStruct;
709 
710     /* Enable the calibration function. */
711     LPADC_EnableCalibration(base, true);
712 
713     /* Keep the CMD and TRG state here and restore it later if the calibration completes.*/
714     mLpadcCMDL    = base->CMD[0].CMDL; /* CMD1L. */
715     mLpadcCMDH    = base->CMD[0].CMDH; /* CMD1H. */
716     mLpadcTrigger = base->TCTRL[0];    /* Trigger0. */
717 
718     /* Set trigger0 configuration - for software trigger. */
719     LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct);
720     mLpadcTriggerConfigStruct.targetCommandId = 1U;                   /* CMD1 is executed. */
721     LPADC_SetConvTriggerConfig(base, 0U, &mLpadcTriggerConfigStruct); /* Configurate the trigger0. */
722 
723     /* Set conversion CMD configuration. */
724     LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct);
725     mLpadcCommandConfigStruct.hardwareAverageMode = kLPADC_HardwareAverageCount128;
726     LPADC_SetConvCommandConfig(base, 1U, &mLpadcCommandConfigStruct); /* Set CMD1 configuration. */
727 
728     /* Do calibration. */
729     LPADC_DoSoftwareTrigger(base, 1U); /* 1U is trigger0 mask. */
730     while (!LPADC_GetConvResult(base, &mLpadcResultConfigStruct))
731     {
732     }
733     /* The valid bits of data are bits 14:3 in the RESFIFO register. */
734     LPADC_SetOffsetValue(base, (uint32_t)(mLpadcResultConfigStruct.convValue) >> 3UL);
735     /* Disable the calibration function. */
736     LPADC_EnableCalibration(base, false);
737 
738     /* restore CMD and TRG registers. */
739     base->CMD[0].CMDL = mLpadcCMDL;    /* CMD1L. */
740     base->CMD[0].CMDH = mLpadcCMDH;    /* CMD1H. */
741     base->TCTRL[0]    = mLpadcTrigger; /* Trigger0. */
742 }
743 #endif                                 /* FSL_FEATURE_LPADC_HAS_OFSTRIM */
744 #endif                                 /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */
745 
746 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFS
747 /*!
748  * brief Do offset calibration.
749  *
750  * param base LPADC peripheral base address.
751  */
LPADC_DoOffsetCalibration(ADC_Type * base)752 void LPADC_DoOffsetCalibration(ADC_Type *base)
753 {
754     LPADC_EnableOffsetCalibration(base, true);
755     while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK))
756     {
757     }
758 }
759 
760 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ
761 /*!
762  * brief Do auto calibration.
763  *
764  * param base  LPADC peripheral base address.
765  */
LPADC_DoAutoCalibration(ADC_Type * base)766 void LPADC_DoAutoCalibration(ADC_Type *base)
767 {
768     LPADC_PrepareAutoCalibration(base);
769     LPADC_FinishAutoCalibration(base);
770 }
771 
772 /*!
773  * brief Prepare auto calibration, LPADC_FinishAutoCalibration has to be called before using the LPADC.
774  * LPADC_DoAutoCalibration has been split in two API to avoid to be stuck too long in the function.
775  *
776  * param base  LPADC peripheral base address.
777  */
LPADC_PrepareAutoCalibration(ADC_Type * base)778 void LPADC_PrepareAutoCalibration(ADC_Type *base)
779 {
780 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
781     assert((0U == LPADC_GetConvResultCount(base, 0)) && (0U == LPADC_GetConvResultCount(base, 1)));
782 #else  /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 1)) */
783     assert(LPADC_GetConvResultCount(base) == 0U);
784 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2)) */
785 
786     /* Request gain calibration. */
787     base->CTRL |= ADC_CTRL_CAL_REQ_MASK;
788 }
789 
790 /*!
791  * brief Finish auto calibration start with LPADC_PrepareAutoCalibration.
792  *
793  * param base  LPADC peripheral base address.
794  */
LPADC_FinishAutoCalibration(ADC_Type * base)795 void LPADC_FinishAutoCalibration(ADC_Type *base)
796 {
797 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE
798     int32_t GCCa;
799     int32_t GCCb;
800     float GCRa;
801     float GCRb;
802 #else
803     uint32_t GCCa;
804     float GCRa;
805 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
806     uint32_t GCCb;
807     float GCRb;
808 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
809 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE */
810 
811     while ((ADC_GCC_RDY_MASK != (base->GCC[0] & ADC_GCC_RDY_MASK))
812 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
813            || (ADC_GCC_RDY_MASK != (base->GCC[1] & ADC_GCC_RDY_MASK))
814 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
815     )
816     {
817     }
818 
819 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE
820     GCCa = (int32_t)(base->GCC[0] & ADC_GCC_GAIN_CAL_MASK);
821     GCCb = (int32_t)(base->GCC[1] & ADC_GCC_GAIN_CAL_MASK);
822     if (0U != ((base->GCC[0]) & 0x8000U))
823     {
824         GCCa         = GCCa - 0x10000;
825         GCRa         = (float)((131072.0) /
826                        (131072.0 - (double)GCCa)); /* Gain_CalA = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[0]))*/
827         base->GCR[0] = LPADC_GetGainConvResult(GCRa); /* write A side GCALR. */
828     }
829 
830     if (0U != ((base->GCC[1]) & 0x8000U))
831     {
832         GCCb         = GCCb - 0x10000;
833         GCRb         = (float)((131072.0) /
834                        (131072.0 - (double)GCCb)); /* Gain_CalB = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[1]))*/
835         base->GCR[1] = LPADC_GetGainConvResult(GCRb); /* write B side GCALR. */
836     }
837 #else
838     /* Calculate gain offset. */
839     GCCa         = (base->GCC[0] & ADC_GCC_GAIN_CAL_MASK);
840     GCRa         = (float)((131072.0) /
841                    (131072.0 - (double)GCCa)); /* Gain_CalA = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[0]))*/
842     base->GCR[0] = LPADC_GetGainConvResult(GCRa);      /* write A side GCALR. */
843 
844 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
845     GCCb         = (base->GCC[1] & ADC_GCC_GAIN_CAL_MASK);
846     GCRb         = (float)((131072.0) /
847                    (131072.0 - (double)GCCb)); /* Gain_CalB = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[1]))*/
848     base->GCR[1] = LPADC_GetGainConvResult(GCRb);      /* write B side GCALR. */
849 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
850 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE */
851     /* Indicate the values are valid. */
852     base->GCR[0] |= ADC_GCR_RDY_MASK;
853 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
854     base->GCR[1] |= ADC_GCR_RDY_MASK;
855 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
856 
857     while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK))
858     {
859     }
860 }
861 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
862 
863 /*!
864  * brief Get calibration value into the memory which is defined by invoker.
865  *
866  * note Please note the ADC will be disabled temporary.
867  * note This function should be used after finish calibration.
868  *
869  * param base LPADC peripheral base address.
870  * param ptrCalibrationValue Pointer to lpadc_calibration_value_t structure, this memory block should be always powered
871  * on even in low power modes.
872  */
LPADC_GetCalibrationValue(ADC_Type * base,lpadc_calibration_value_t * ptrCalibrationValue)873 void LPADC_GetCalibrationValue(ADC_Type *base, lpadc_calibration_value_t *ptrCalibrationValue)
874 {
875     assert(ptrCalibrationValue != NULL);
876 
877     bool adcEnabled = false;
878 
879     /* Check if ADC is enabled. */
880     if ((base->CTRL & ADC_CTRL_ADCEN_MASK) != 0UL)
881     {
882         LPADC_Enable(base, false);
883         adcEnabled = true;
884     }
885 
886 #if (defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ)
887     uint32_t i;
888     for (i = 0UL; i < 33UL; i++)
889     {
890 #if defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK)
891         ptrCalibrationValue->generalCalibrationValueA[i] =
892             (uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GAR0))) + i)) & 0xFFFFU);
893 #if !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U))
894         ptrCalibrationValue->generalCalibrationValueB[i] =
895             (uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GBR0))) + i)) & 0xFFFFU);
896 #endif /* (defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U)) */
897 #else
898         ptrCalibrationValue->generalCalibrationValueA[i] =
899             (uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GAR[0]))) + i)) & 0xFFFFU);
900 #if !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U))
901         ptrCalibrationValue->generalCalibrationValueB[i] =
902             (uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GBR[0]))) + i)) & 0xFFFFU);
903 #endif /* (defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U)) */
904 
905 #endif /* defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK) */
906     }
907 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
908 
909     ptrCalibrationValue->gainCalibrationResultA = (uint16_t)(base->GCR[0] & ADC_GCR_GCALR_MASK);
910 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
911     ptrCalibrationValue->gainCalibrationResultB = (uint16_t)(base->GCR[1] & ADC_GCR_GCALR_MASK);
912 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
913 
914     if (adcEnabled)
915     {
916         LPADC_Enable(base, true);
917     }
918 }
919 
920 /*!
921  * brief Set calibration value into ADC calibration registers.
922  *
923  * note Please note the ADC will be disabled temporary.
924  *
925  * param base LPADC peripheral base address.
926  * param ptrCalibrationValue Pointer to lpadc_calibration_value_t structure which contains ADC's calibration value.
927  */
LPADC_SetCalibrationValue(ADC_Type * base,const lpadc_calibration_value_t * ptrCalibrationValue)928 void LPADC_SetCalibrationValue(ADC_Type *base, const lpadc_calibration_value_t *ptrCalibrationValue)
929 {
930     assert(ptrCalibrationValue != NULL);
931 
932     bool adcEnabled = false;
933 
934     /* Check if ADC is enabled. */
935     if ((base->CTRL & ADC_CTRL_ADCEN_MASK) != 0UL)
936     {
937         LPADC_Enable(base, false);
938         adcEnabled = true;
939     }
940 
941 #if (defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ)
942     for (uint32_t i = 0UL; i < 33UL; i++)
943     {
944 #if defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK)
945         *(((volatile uint32_t *)(&(base->CAL_GAR0))) + i) = ptrCalibrationValue->generalCalibrationValueA[i];
946 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
947         *(((volatile uint32_t *)(&(base->CAL_GBR0))) + i) = ptrCalibrationValue->generalCalibrationValueB[i];
948 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
949 #else
950         *(((volatile uint32_t *)(&(base->CAL_GAR[0]))) + i) = ptrCalibrationValue->generalCalibrationValueA[i];
951 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
952         *(((volatile uint32_t *)(&(base->CAL_GBR[0]))) + i) = ptrCalibrationValue->generalCalibrationValueB[i];
953 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
954 #endif /* defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK) */
955     }
956 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
957 
958     base->GCR[0] = ADC_GCR_GCALR(ptrCalibrationValue->gainCalibrationResultA) | ADC_GCR_RDY_MASK;
959 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
960     base->GCR[1] = ADC_GCR_GCALR(ptrCalibrationValue->gainCalibrationResultB) | ADC_GCR_RDY_MASK;
961 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
962     /*
963      * $Branch Coverage Justification$
964      * while ((base->STAT & ADC_STAT_CAL_RDY_MASK) == ADC_STAT_CAL_RDY_MASK) not covered. Test unfeasible,
965      * the calibration ready state is too short not to catch.
966      */
967     while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK))
968     {
969     }
970 
971     if (adcEnabled)
972     {
973         LPADC_Enable(base, true);
974     }
975 }
976 
977 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFS */
978