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