1 /*
2  * Copyright 2017-2019 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_adc.h"
9 
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.adc"
13 #endif
14 
15 /*******************************************************************************
16  * Prototypes
17  ******************************************************************************/
18 /*!
19  * @brief Get instance number for ADC module.
20  *
21  * @param base ADC peripheral base address
22  */
23 static uint32_t ADC_GetInstance(ADC_Type *base);
24 
25 /*******************************************************************************
26  * Variables
27  ******************************************************************************/
28 /*! @brief Pointers to ADC bases for each instance. */
29 static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS;
30 
31 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
32 /*! @brief Pointers to ADC clocks for each instance. */
33 static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS;
34 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
35 
36 /*******************************************************************************
37  * Code
38  ******************************************************************************/
ADC_GetInstance(ADC_Type * base)39 static uint32_t ADC_GetInstance(ADC_Type *base)
40 {
41     uint32_t instance;
42 
43     /* Find the instance index from base address mappings. */
44     for (instance = 0; instance < ARRAY_SIZE(s_adcBases); instance++)
45     {
46         if (s_adcBases[instance] == base)
47         {
48             break;
49         }
50     }
51 
52     assert(instance < ARRAY_SIZE(s_adcBases));
53 
54     return instance;
55 }
56 
57 /*!
58  * brief Initializes the ADC module.
59  *
60  * param base   ADC peripheral base address.
61  * param config Pointer to configuration structure. See "adc_config_t".
62  */
ADC_Init(ADC_Type * base,const adc_config_t * config)63 void ADC_Init(ADC_Type *base, const adc_config_t *config)
64 {
65     assert(NULL != config);
66 
67     uint32_t tmp32;
68 
69 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
70     /* Enable the clock. */
71     CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]);
72 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
73 
74     /* Configure SC2 register. */
75     tmp32 = (base->SC2) & (~ADC_SC2_REFSEL_MASK);
76     tmp32 |= ADC_SC2_REFSEL(config->referenceVoltageSource);
77     base->SC2 = tmp32;
78 
79     /* Configure SC3 register. */
80     tmp32 =
81         ADC_SC3_ADICLK(config->clockSource) | ADC_SC3_MODE(config->ResolutionMode) | ADC_SC3_ADIV(config->clockDivider);
82     if (config->enableLowPower)
83     {
84         tmp32 |= ADC_SC3_ADLPC_MASK;
85     }
86     if (config->enableLongSampleTime)
87     {
88         tmp32 |= ADC_SC3_ADLSMP_MASK;
89     }
90     base->SC3 = tmp32;
91 }
92 
93 /*!
94  * brief De-initialize the ADC module.
95  *
96  * param base ADC peripheral base address.
97  */
ADC_Deinit(ADC_Type * base)98 void ADC_Deinit(ADC_Type *base)
99 {
100     /* Disable ADC module. */
101     base->SC1 |= ADC_SC1_ADCH_MASK;
102 
103 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
104     /* Disable the clock. */
105     CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]);
106 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
107 }
108 
109 /*!
110  * brief Gets an available pre-defined settings for the converter's configuration.
111  *
112  * This function initializes the converter configuration structure with available settings. The default values are as
113  * follows.
114  * code
115  *   config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
116  *   config->enableLowPower = false;
117  *   config->enableLongSampleTime = false;
118  *   config->clockDivider = kADC_ClockDivider1;
119  *   config->ResolutionMode = kADC_Resolution8BitMode;
120  *   config->clockSource = kADC_ClockSourceAlt0;
121  * endcode
122  * param config Pointer to the configuration structure.
123  */
ADC_GetDefaultConfig(adc_config_t * config)124 void ADC_GetDefaultConfig(adc_config_t *config)
125 {
126     /* Initializes the configure structure to zero. */
127     (void)memset(config, 0, sizeof(*config));
128 
129     config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
130     config->enableLowPower         = false;
131     config->enableLongSampleTime   = false;
132     config->clockDivider           = kADC_ClockDivider1;
133     config->ResolutionMode         = kADC_Resolution8BitMode;
134     config->clockSource            = kADC_ClockSourceAlt0;
135 }
136 
137 /*!
138  * brief Configure the hardware compare mode.
139  *
140  * The compare function can be configured to check for an upper or lower limit. After the
141  * input is sampled and converted, the result is added to the complement of the compare
142  * value (ADC_CV).
143  *
144  * param base ADC peripheral base address.
145  * param config Pointer to "adc_hardware_compare_config_t" structure.
146  */
ADC_SetHardwareCompare(ADC_Type * base,const adc_hardware_compare_config_t * config)147 void ADC_SetHardwareCompare(ADC_Type *base, const adc_hardware_compare_config_t *config)
148 {
149     assert(NULL != config);
150 
151     uint32_t tmp32;
152 
153     /* Configure SC2 register. */
154     tmp32 = (base->SC2) & ~(ADC_SC2_ACFGT_MASK | ADC_SC2_ACFE_MASK);
155     tmp32 |= ((uint32_t)(config->compareMode) << ADC_SC2_ACFGT_SHIFT);
156     base->SC2 = tmp32;
157 
158     /* Configure CV register. */
159     base->CV = ADC_CV_CV(config->compareValue);
160 }
161 
162 /*!
163  * brief Configure the Fifo mode.
164  *
165  * The ADC module supports FIFO operation to minimize the interrupts to CPU in order to
166  * reduce CPU loading in ADC interrupt service routines. This module contains two FIFOs
167  * to buffer analog input channels and analog results respectively.
168  *
169  * param base ADC peripheral base address.
170  * param config Pointer to "adc_fifo_config_t" structure.
171  */
ADC_SetFifoConfig(ADC_Type * base,const adc_fifo_config_t * config)172 void ADC_SetFifoConfig(ADC_Type *base, const adc_fifo_config_t *config)
173 {
174     assert(NULL != config);
175 
176     uint32_t tmp32;
177 
178     /* Configure SC4 register. */
179     tmp32 = ADC_SC4_AFDEP(config->FifoDepth);
180     if (config->enableFifoScanMode)
181     {
182         tmp32 |= ADC_SC4_ASCANE_MASK;
183     }
184     if (config->enableCompareAndMode)
185     {
186         tmp32 |= ADC_SC4_ACFSEL_MASK;
187     }
188 #if defined(FSL_FEATURE_ADC_HAS_SC4_HTRGME) && FSL_FEATURE_ADC_HAS_SC4_HTRGME
189     if (config->enableHWTriggerMultConv)
190     {
191         tmp32 |= ADC_SC4_HTRGME_MASK;
192     }
193 #endif /* FSL_FEATURE_ADC_HAS_SC4_HTRGME */
194     base->SC4 = tmp32;
195 }
196 
197 /*!
198  * brief Gets an available pre-defined settings for the FIFO's configuration.
199  *
200  * param config Pointer to the FIFO configuration structure, please refer to adc_fifo_config_t for details.
201  */
ADC_GetDefaultFIFOConfig(adc_fifo_config_t * config)202 void ADC_GetDefaultFIFOConfig(adc_fifo_config_t *config)
203 {
204     assert(config != NULL);
205 
206     (void)memset(config, 0, sizeof(*config));
207 
208     config->enableFifoScanMode   = false;
209     config->enableCompareAndMode = false;
210     config->FifoDepth            = 0UL;
211 #if defined(FSL_FEATURE_ADC_HAS_SC4_HTRGME) && FSL_FEATURE_ADC_HAS_SC4_HTRGME
212     config->enableHWTriggerMultConv = false;
213 #endif
214 }
215 
216 /*!
217  * brief Configures the conversion channel.
218  *
219  * This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API
220  * configures the channel while the external trigger source helps to trigger the conversion.
221  *
222  * param base ADC peripheral base address.
223  * param config Pointer to "adc_channel_config_t" structure.
224  */
ADC_SetChannelConfig(ADC_Type * base,const adc_channel_config_t * config)225 void ADC_SetChannelConfig(ADC_Type *base, const adc_channel_config_t *config)
226 {
227     assert(NULL != config);
228 
229     uint32_t tmp32;
230 
231     /* Configure SC1 register. */
232     tmp32 = ADC_SC1_ADCH(config->channelNumber);
233     if (config->enableContinuousConversion)
234     {
235         tmp32 |= ADC_SC1_ADCO_MASK;
236     }
237     if (config->enableInterruptOnConversionCompleted)
238     {
239         tmp32 |= ADC_SC1_AIEN_MASK;
240     }
241     base->SC1 = tmp32;
242 }
243 
244 /*!
245  * brief Get the status flags of channel.
246  *
247  * param  base ADC peripheral base address.
248  * return "True" means conversion has completed and "false" means conversion has not completed.
249  */
ADC_GetChannelStatusFlags(ADC_Type * base)250 bool ADC_GetChannelStatusFlags(ADC_Type *base)
251 {
252     bool ret = false;
253 
254     if (ADC_SC1_COCO_MASK == (ADC_SC1_COCO_MASK & (base->SC1)))
255     {
256         ret = true;
257     }
258 
259     return ret;
260 }
261 
262 /*!
263  * brief Get the ADC status flags.
264  *
265  * param base ADC peripheral base address.
266  * return Flags' mask if indicated flags are asserted. See "_adc_status_flags".
267  */
ADC_GetStatusFlags(ADC_Type * base)268 uint32_t ADC_GetStatusFlags(ADC_Type *base)
269 {
270     uint32_t tmp32;
271 
272     tmp32 = (base->SC2) & (ADC_SC2_ADACT_MASK | ADC_SC2_FEMPTY_MASK | ADC_SC2_FFULL_MASK);
273 
274     return tmp32;
275 }
276