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