1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019, 2021 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #include "fsl_adc12.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.adc12"
17 #endif
18 
19 /*! @brief Transform raw signed calibration result to unified type int32_t. */
20 #define ADC12_TRANSFORM_CALIBRATION_RESULT(resultValue, bitWidth)    \
21     (((resultValue) >= (int32_t)(uint32_t)(1UL << ((bitWidth)-1))) ? \
22          ((resultValue) - (int32_t)(uint32_t)(1UL << (bitWidth))) :  \
23          (resultValue));
24 
25 /*******************************************************************************
26  * Prototypes
27  ******************************************************************************/
28 /*!
29  * @brief Get instance number for ADC12 module.
30  *
31  * @param base ADC12 peripheral base address
32  */
33 static uint32_t ADC12_GetInstance(ADC_Type *base);
34 
35 /*!
36  * @brief Check calibration failed status.
37  *
38  * Check if the calibration is failed by comparing the calibration result value with its limit range.
39  * 1. Each calibration result value's limit range is:
40  *     Symbol       Min            Typ                      Max
41  *     ______________________________________________________________________________________
42  *     OFS          -48            -8                        22
43  *     CLP9         -12             4                        20
44  *     CLPX         -16             0                        16
45  *     CLPS          30             72                       120
46  *     CLP0          CLPS-14        CLPS                     CLPS+14
47  *     CLP1          Typ1-16        Typ1=CLP0+CLP0           Typ1+16
48  *     CLP2          Typ2-20        Typ2=CLP1+CLP1-26        Typ2+20
49  *     CLP3          Typ3-36        Typ3=CLP2+CLP2           Typ3+36
50  * 2. To get the accurate calibration value, following conditions should be met.
51  *     1). Enable hardware average and set average number to 32.
52  *     2). No parallel calibration of ADCs because they will disturb each other.
53  *     2). For VREFH pin on PCB, use 3 bypass capacitance in the range: 1uF, 100nF and 1nF and place them as close as
54  *         possible to the VREFH pin.
55  * @param base ADC12 peripheral base address.
56  * @retval kStatus_Success Calibration is done successfully.
57  * @retval kStatus_Fail Calibration is failed.
58  */
59 static status_t ADC12_GetCalibrationStatus(ADC_Type *base);
60 
61 /*******************************************************************************
62  * Variables
63  ******************************************************************************/
64 /*! @brief Pointers to ADC12 bases for each instance. */
65 static ADC_Type *const s_adc12Bases[] = ADC_BASE_PTRS;
66 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
67 /*! @brief Pointers to ADC12 clocks for each instance. */
68 static const clock_ip_name_t s_adc12Clocks[] = ADC12_CLOCKS;
69 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
70 
71 /*******************************************************************************
72  * Code
73  ******************************************************************************/
ADC12_GetInstance(ADC_Type * base)74 static uint32_t ADC12_GetInstance(ADC_Type *base)
75 {
76     uint32_t instance;
77 
78     /* Find the instance index from base address mappings. */
79     for (instance = 0; instance < ARRAY_SIZE(s_adc12Bases); instance++)
80     {
81         if (s_adc12Bases[instance] == base)
82         {
83             break;
84         }
85     }
86 
87     assert(instance < ARRAY_SIZE(s_adc12Bases));
88 
89     return instance;
90 }
91 
ADC12_GetCalibrationStatus(ADC_Type * base)92 static status_t ADC12_GetCalibrationStatus(ADC_Type *base)
93 {
94     /* Get raw calibration result. OFS, CLP9, CLPX are signed number. The highest position bit is the signal bit.
95     Other calibration value registers are unsigned number. */
96     int32_t OFS   = (int32_t)(uint32_t)((base->OFS & ADC_OFS_OFS_MASK) >> ADC_OFS_OFS_SHIFT);
97     int32_t CLP9  = (int32_t)(uint32_t)((base->CLP9 & ADC_CLP9_CLP9_MASK) >> ADC_CLP9_CLP9_SHIFT);
98     int32_t CLPX  = (int32_t)(uint32_t)((base->CLPX & ADC_CLPX_CLPX_MASK) >> ADC_CLPX_CLPX_SHIFT);
99     uint32_t CLPS = ((base->CLPS & ADC_CLPS_CLPS_MASK) >> ADC_CLPS_CLPS_SHIFT);
100     uint32_t CLP0 = ((base->CLP0 & ADC_CLP0_CLP0_MASK) >> ADC_CLP0_CLP0_SHIFT);
101     uint32_t CLP1 = ((base->CLP1 & ADC_CLP1_CLP1_MASK) >> ADC_CLP1_CLP1_SHIFT);
102     uint32_t CLP2 = ((base->CLP2 & ADC_CLP2_CLP2_MASK) >> ADC_CLP2_CLP2_SHIFT);
103     uint32_t CLP3 = ((base->CLP3 & ADC_CLP3_CLP3_MASK) >> ADC_CLP3_CLP3_SHIFT);
104     uint32_t Typ1 = (CLP0 + CLP0);
105     uint32_t Typ2 = (CLP1 + CLP1 - 26U);
106     uint32_t Typ3 = (CLP2 + CLP2);
107     status_t ret  = kStatus_Success;
108 
109     /* Transform raw calibration result to unified type int32_t when the conversion result value is signed number. */
110     OFS  = ADC12_TRANSFORM_CALIBRATION_RESULT(OFS, 16);
111     CLP9 = ADC12_TRANSFORM_CALIBRATION_RESULT(CLP9, 7);
112     CLPX = ADC12_TRANSFORM_CALIBRATION_RESULT(CLPX, 7);
113 
114     /* Check the calibration result value with its limit range. */
115 
116     if ((OFS < -48) || (OFS > 22) || (CLP9 < -12) || (CLP9 > 20) || (CLPX < -16) || (CLPX > 16) || (CLPS < 30U) ||
117         (CLPS > 120U) || (CLP0 < (CLPS - 14U)) || (CLP0 > (CLPS + 14U)) || (CLP1 < (Typ1 - 16U)) ||
118         (CLP1 > (Typ1 + 16U)) || (CLP2 < (Typ2 - 20U)) || (CLP2 > (Typ2 + 20U)) || (CLP3 < (Typ3 - 36U)) ||
119         (CLP3 > (Typ3 + 36U)))
120     {
121         ret = kStatus_Fail;
122     }
123 
124     return ret;
125 }
126 
127 /*!
128  * brief Initialize the ADC12 module.
129  *
130  * param base ADC12 peripheral base address.
131  * param config Pointer to "adc12_config_t" structure.
132  */
ADC12_Init(ADC_Type * base,const adc12_config_t * config)133 void ADC12_Init(ADC_Type *base, const adc12_config_t *config)
134 {
135     assert(config);
136 
137     uint32_t tmp32;
138 
139 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
140     /* Enable the clock. */
141     CLOCK_EnableClock(s_adc12Clocks[ADC12_GetInstance(base)]);
142 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
143 
144     /* ADCx_CFG1. */
145     tmp32 = (base->CFG1 & ~(ADC_CFG1_ADICLK_MASK | ADC_CFG1_ADIV_MASK | ADC_CFG1_MODE_MASK));
146     tmp32 |= (ADC_CFG1_ADICLK(config->clockSource) | ADC_CFG1_ADIV(config->clockDivider) |
147               ADC_CFG1_MODE(config->resolution));
148     base->CFG1 = tmp32;
149 
150     /* ADCx_CFG2. */
151     tmp32 = (base->CFG2 & ~ADC_CFG2_SMPLTS_MASK);
152     tmp32 |= ADC_CFG2_SMPLTS(config->sampleClockCount - 1U);
153     base->CFG2 = tmp32;
154 
155     /* ADCx_SC2. */
156     tmp32 = (base->SC2 & ~ADC_SC2_REFSEL_MASK);
157     tmp32 |= ADC_SC2_REFSEL(config->referenceVoltageSource);
158     base->SC2 = tmp32;
159 
160     /* ADCx_SC3. */
161     tmp32 = (base->SC3 & ~ADC_SC3_ADCO_MASK);
162     if (true == config->enableContinuousConversion)
163     {
164         tmp32 |= ADC_SC3_ADCO_MASK;
165     }
166     base->SC3 = tmp32;
167 }
168 
169 /*!
170  * brief De-initialize the ADC12 module.
171  *
172  * param base ADC12 peripheral base address.
173  */
ADC12_Deinit(ADC_Type * base)174 void ADC12_Deinit(ADC_Type *base)
175 {
176 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
177     /* Disable the clock. */
178     CLOCK_DisableClock(s_adc12Clocks[ADC12_GetInstance(base)]);
179 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
180 }
181 
182 /*!
183  * brief Gets an available pre-defined settings for converter's configuration.
184  *
185  * This function initializes the converter configuration structure with an available settings. The default values are:
186  *
187  * Example:
188    code
189    config->referenceVoltageSource = kADC12_ReferenceVoltageSourceVref;
190    config->clockSource = kADC12_ClockSourceAlt0;
191    config->clockDivider = kADC12_ClockDivider1;
192    config->resolution = kADC12_Resolution8Bit;
193    config->sampleClockCount = 12U;
194    config->enableContinuousConversion = false;
195    endcode
196  * param config Pointer to "adc12_config_t" structure.
197  */
ADC12_GetDefaultConfig(adc12_config_t * config)198 void ADC12_GetDefaultConfig(adc12_config_t *config)
199 {
200     assert(config);
201 
202     /* Initializes the configure structure to zero. */
203     (void)memset(config, 0, sizeof(*config));
204 
205     config->referenceVoltageSource     = kADC12_ReferenceVoltageSourceVref;
206     config->clockSource                = kADC12_ClockSourceAlt0;
207     config->clockDivider               = kADC12_ClockDivider1;
208     config->resolution                 = kADC12_Resolution8Bit;
209     config->sampleClockCount           = 13U;
210     config->enableContinuousConversion = false;
211 }
212 
213 /*!
214  * brief Configure the conversion channel.
215  *
216  * This operation triggers the conversion in software trigger mode. In hardware trigger mode, this API configures the
217  * channel while the external trigger source helps to trigger the conversion.
218  *
219  * Note that the "Channel Group" has a detailed description.
220  * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC can have more than one
221  * group of status and control register, one for each conversion. The channel group parameter indicates which group of
222  * registers are used, channel group 0 is for Group A registers and channel group 1 is for Group B registers. The
223  * channel groups are used in a "ping-pong" approach to control the ADC operation.  At any time, only one of the
224  * channel groups is actively controlling ADC conversions. Channel group 0 is used for both software and hardware
225  * trigger modes of operation. Channel groups 1 and greater indicate potentially multiple channel group registers for
226  * use only in hardware trigger mode. See the chip configuration information in the MCU reference manual about the
227  * number of SC1n registers (channel groups) specific to this device.  None of the channel groups 1 or greater are used
228  * for software trigger operation and therefore writes to these channel groups do not initiate a new conversion.
229  * Updating channel group 0 while a different channel group is actively controlling a conversion is allowed and
230  * vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a
231  * conversion aborts the current conversion.
232  *
233  * param base ADC12 peripheral base address.
234  * param channelGroup Channel group index.
235  * param config Pointer to "adc12_channel_config_t" structure.
236  */
ADC12_SetChannelConfig(ADC_Type * base,uint32_t channelGroup,const adc12_channel_config_t * config)237 void ADC12_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc12_channel_config_t *config)
238 {
239     assert(channelGroup < ADC_SC1_COUNT);
240     assert(config);
241 
242     uint32_t tmp32;
243 
244     /* ADCx_SC1n. */
245     tmp32 = (base->SC1[channelGroup] & ~(ADC_SC1_ADCH_MASK | ADC_SC1_AIEN_MASK));
246     tmp32 |= ADC_SC1_ADCH(config->channelNumber);
247     if (true == config->enableInterruptOnConversionCompleted)
248     {
249         tmp32 |= ADC_SC1_AIEN_MASK;
250     }
251     base->SC1[channelGroup] = tmp32;
252 }
253 
254 /*!
255  * brief Get the status flags of channel.
256  *
257  * param base ADC12 peripheral base address.
258  * param channelGroup Channel group index.
259  *
260  * return Flags' mask if indicated flags are asserted. See to "_adc12_channel_status_flags".
261  */
ADC12_GetChannelStatusFlags(ADC_Type * base,uint32_t channelGroup)262 uint32_t ADC12_GetChannelStatusFlags(ADC_Type *base, uint32_t channelGroup)
263 {
264     assert(channelGroup < ADC_SC1_COUNT);
265 
266     uint32_t tmp32  = base->SC1[channelGroup];
267     uint32_t result = 0U;
268 
269     /* ADCx_SC1n. */
270     if (ADC_SC1_COCO_MASK == (tmp32 & ADC_SC1_COCO_MASK))
271     {
272         result |= (uint32_t)kADC12_ChannelConversionCompletedFlag;
273     }
274 
275     return result;
276 }
277 
278 /*!
279  * brief Automate the hardware calibration.
280  *
281  * This auto calibration helps to adjust the gain automatically according to the converter's working environment.
282  * Execute the calibration before conversion. Note that the software trigger should be used during calibration.
283  *
284  * param base ADC12 peripheral base address.
285  * retval kStatus_Success Calibration is done successfully.
286  * retval kStatus_Fail Calibration is failed.
287  */
ADC12_DoAutoCalibration(ADC_Type * base)288 status_t ADC12_DoAutoCalibration(ADC_Type *base)
289 {
290     bool enabledHardwareTrigger = false;
291     bool enabledHardwareAverage = false;
292     uint32_t averageMode;
293     uint32_t tmp32;
294     uint32_t saveCFG1;
295     status_t ret = kStatus_Success;
296 
297     /* Save current clock divider. */
298     saveCFG1 = base->CFG1;
299     /* Set ADCK (ADC clock) to half the maximum specified frequency for calibration. */
300     base->CFG1 |= ADC_CFG1_ADIV(1);
301 
302     /* Save current trigger mode. Then set to software trigger mode. */
303     tmp32 = base->SC2;
304     if (ADC_SC2_ADTRG_MASK == (tmp32 & ADC_SC2_ADTRG_MASK))
305     {
306         enabledHardwareTrigger = true;
307         tmp32 &= ~ADC_SC2_ADTRG_MASK;
308         base->SC2 = tmp32;
309     }
310     /* Save current average mode. Then enable hardware average and set average number to be maximum value. */
311     tmp32       = base->SC3;
312     averageMode = ((tmp32 & ADC_SC3_AVGS_MASK) >> ADC_SC3_AVGS_SHIFT);
313     if (ADC_SC3_AVGE_MASK == (tmp32 & ADC_SC3_AVGE_MASK))
314     {
315         enabledHardwareAverage = true;
316     }
317     tmp32 &= ~ADC_SC3_AVGS_MASK;
318     tmp32 |= (ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(((uint32_t)ADC_SC3_AVGS_MASK >> (uint32_t)ADC_SC3_AVGS_SHIFT)));
319 
320     /* Trigger calibration and wait until it complete. */
321     tmp32 |= ADC_SC3_CAL_MASK;
322     base->SC3 = tmp32;
323     while ((uint32_t)kADC12_ChannelConversionCompletedFlag !=
324            (ADC12_GetChannelStatusFlags(base, 0U) & (uint32_t)kADC12_ChannelConversionCompletedFlag))
325     {
326     }
327 
328     if ((uint32_t)kADC12_CalibrationFailedFlag == (ADC12_GetStatusFlags(base) & (uint32_t)kADC12_CalibrationFailedFlag))
329     {
330         ret = kStatus_Fail;
331     }
332     /* Clear conversion done flag. */
333     (void)ADC12_GetChannelConversionValue(base, 0U);
334 
335     /* Restore original trigger mode. */
336     if (true == enabledHardwareTrigger)
337     {
338         base->SC2 |= ADC_SC2_ADTRG_MASK;
339     }
340     /* Restore original average mode. */
341     tmp32 = base->SC3;
342     if (false == enabledHardwareAverage)
343     {
344         tmp32 &= ~ADC_SC3_AVGE_MASK;
345     }
346     tmp32 |= ADC_SC3_AVGS(averageMode);
347     base->SC3 = tmp32;
348 
349     /* Restore adc clock divider. */
350     base->CFG1 = saveCFG1;
351 
352     return ret;
353 }
354 
355 /*!
356  * brief Configure the hardware compare mode.
357  *
358  * The hardware compare mode provides a way to process the conversion result automatically by hardware. Only the result
359  * in compare range is available. To compare the range, see "adc12_hardware_compare_mode_t", or the reference manual
360  * document for more detailed information.
361  *
362  * param base ADC12 peripheral base address.
363  * param config Pointer to "adc12_hardware_compare_config_t" structure. Pass "NULL" to disable the feature.
364  */
ADC12_SetHardwareCompareConfig(ADC_Type * base,const adc12_hardware_compare_config_t * config)365 void ADC12_SetHardwareCompareConfig(ADC_Type *base, const adc12_hardware_compare_config_t *config)
366 {
367     uint32_t tmp32;
368 
369     /* Disable hardware compare. */
370     if (NULL == config)
371     {
372         base->SC2 &= ~(ADC_SC2_ACFE_MASK | ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK);
373     }
374     else
375     {
376         /* Set the compare mode. */
377         tmp32 = (base->SC2 & ~(ADC_SC2_ACFE_MASK | ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK));
378         switch (config->hardwareCompareMode)
379         {
380             case kADC12_HardwareCompareMode0:
381                 break;
382             case kADC12_HardwareCompareMode1:
383                 tmp32 |= ADC_SC2_ACFGT_MASK;
384                 break;
385             case kADC12_HardwareCompareMode2:
386                 tmp32 |= ADC_SC2_ACREN_MASK;
387                 break;
388             case kADC12_HardwareCompareMode3:
389                 tmp32 |= (ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK);
390                 break;
391             default:
392                 assert(false);
393                 break;
394         }
395         tmp32 |= ADC_SC2_ACFE_MASK;
396         base->SC2 = tmp32;
397 
398         /* Set the compare value. */
399         base->CV1 = (uint32_t)config->value1;
400         base->CV2 = (uint32_t)config->value2;
401     }
402 }
403 
404 /*!
405  * brief Set the hardware average mode.
406  *
407  * Hardware average mode provides a way to process the conversion result automatically by hardware. The multiple
408  * conversion results are accumulated and averaged internally. This aids to get more accurate conversion result.
409  *
410  * param base ADC12 peripheral base address.
411  * param mode Setting hardware average mode. See to "adc12_hardware_average_mode_t".
412  */
ADC12_SetHardwareAverage(ADC_Type * base,adc12_hardware_average_mode_t mode)413 void ADC12_SetHardwareAverage(ADC_Type *base, adc12_hardware_average_mode_t mode)
414 {
415     uint32_t tmp32 = base->SC3;
416 
417     /* ADCx_SC3. */
418     tmp32 &= ~(ADC_SC3_AVGS_MASK | ADC_SC3_AVGE_MASK);
419     switch (mode)
420     {
421         case kADC12_HardwareAverageCount4:
422         case kADC12_HardwareAverageCount8:
423         case kADC12_HardwareAverageCount16:
424         case kADC12_HardwareAverageCount32:
425             tmp32 |= (ADC_SC3_AVGS(mode) | ADC_SC3_AVGE_MASK);
426             break;
427         case kADC12_HardwareAverageDisabled:
428             break;
429         default:
430             assert(false);
431             break;
432     }
433     base->SC3 = tmp32;
434 }
435 
436 /*!
437  * brief Get the status flags of the converter.
438  *
439  * param base ADC12 peripheral base address.
440  *
441  * return Flags' mask if indicated flags are asserted. See to "_adc12_status_flags".
442  */
ADC12_GetStatusFlags(ADC_Type * base)443 uint32_t ADC12_GetStatusFlags(ADC_Type *base)
444 {
445     uint32_t result = 0;
446 
447     /* ADCx_SC2. */
448     if (ADC_SC2_ADACT_MASK == (base->SC2 & ADC_SC2_ADACT_MASK))
449     {
450         result |= (uint32_t)kADC12_ActiveFlag;
451     }
452 
453     if (kStatus_Fail == ADC12_GetCalibrationStatus(base))
454     {
455         result |= (uint32_t)kADC12_CalibrationFailedFlag;
456     }
457 
458     return result;
459 }
460