1 /*
2 * Copyright 2020-2023 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.cns_adc"
13 #endif
14
15 /*******************************************************************************
16 * Prototypes
17 ******************************************************************************/
18 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
19 static uint32_t ADC_GetInstance(ADC_Type *base);
20 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
21
22 /*******************************************************************************
23 * Variables
24 ******************************************************************************/
25 static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS;
26
27 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
28 /*! @brief Pointers to adc clocks for each instance. */
29 static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS;
30 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
31
32 /*******************************************************************************
33 * Code
34 ******************************************************************************/
35
36 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
37 /*!
38 * @brief Get the ADC peripheral instance
39 *
40 * @param base ADC peripheral base address.
41 * @return The instance of input ADC peripheral base address.
42 */
ADC_GetInstance(ADC_Type * base)43 static uint32_t ADC_GetInstance(ADC_Type *base)
44 {
45 uint32_t instance;
46 uint32_t adcArrayCount = (sizeof(s_adcBases) / sizeof(s_adcBases[0]));
47
48 /* Find the instance index from base address mappings. */
49 for (instance = 0; instance < adcArrayCount; instance++)
50 {
51 if (s_adcBases[instance] == base)
52 {
53 break;
54 }
55 }
56
57 assert(instance < adcArrayCount);
58
59 return instance;
60 }
61 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
62
63 /*!
64 * brief Initialize ADC module, including clock divider, power mode, and so on.
65 *
66 * param base ADC peripheral base address.
67 * param config The pointer to the structure adc_config_t.
68 */
ADC_Init(ADC_Type * base,const adc_config_t * config)69 void ADC_Init(ADC_Type *base, const adc_config_t *config)
70 {
71 assert(config != NULL);
72
73 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
74 /* Ungate the ADC clock*/
75 (void)CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]);
76 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
77 uint32_t tmp32;
78
79 ADC_DoSoftwareReset(base);
80
81 base->ADC_REG_GENERAL = (base->ADC_REG_GENERAL & ~(ADC_ADC_REG_GENERAL_CLK_DIV_RATIO_MASK)) |
82 ADC_ADC_REG_GENERAL_CLK_DIV_RATIO(config->clockDivider);
83
84 tmp32 = base->ADC_REG_CONFIG;
85 tmp32 &=
86 ~(ADC_ADC_REG_CONFIG_TRIGGER_SEL_MASK | ADC_ADC_REG_CONFIG_TRIGGER_EN_MASK |
87 ADC_ADC_REG_CONFIG_CONT_CONV_EN_MASK | ADC_ADC_REG_CONFIG_AVG_SEL_MASK | ADC_ADC_REG_CONFIG_SCAN_LENGTH_MASK);
88 tmp32 |= ADC_ADC_REG_CONFIG_CONT_CONV_EN(config->conversionMode) |
89 ADC_ADC_REG_CONFIG_AVG_SEL(config->averageLength) | ADC_ADC_REG_CONFIG_SCAN_LENGTH(config->scanLength);
90 if (config->triggerSource != kADC_TriggerSourceSoftware)
91 {
92 tmp32 |= ADC_ADC_REG_CONFIG_TRIGGER_EN_MASK | ADC_ADC_REG_CONFIG_TRIGGER_SEL(config->triggerSource);
93 }
94 base->ADC_REG_CONFIG = tmp32;
95
96 tmp32 = base->ADC_REG_INTERVAL;
97 if (config->warmupTime == kADC_WarmUpStateBypass)
98 {
99 tmp32 |= ADC_ADC_REG_INTERVAL_BYPASS_WARMUP_MASK;
100 }
101 else
102 {
103 tmp32 =
104 (tmp32 & ~(ADC_ADC_REG_INTERVAL_WARMUP_TIME_MASK)) | ADC_ADC_REG_INTERVAL_WARMUP_TIME(config->warmupTime);
105 }
106 base->ADC_REG_INTERVAL = tmp32;
107
108 tmp32 = base->ADC_REG_ANA;
109 tmp32 &= ~(ADC_ADC_REG_ANA_VREF_SEL_MASK | ADC_ADC_REG_ANA_SINGLEDIFF_MASK | ADC_ADC_REG_ANA_INBUF_GAIN_MASK |
110 ADC_ADC_REG_ANA_INBUF_EN_MASK | ADC_ADC_REG_ANA_BIAS_SEL_MASK | ADC_ADC_REG_ANA_RES_SEL_MASK |
111 ADC_ADC_REG_ANA_INBUF_CHOP_EN_MASK | ADC_ADC_REG_ANA_CHOP_EN_MASK);
112 tmp32 |= ADC_ADC_REG_ANA_VREF_SEL(config->vrefSource) | ADC_ADC_REG_ANA_SINGLEDIFF(config->inputMode) |
113 ADC_ADC_REG_ANA_INBUF_GAIN(config->inputGain) | ADC_ADC_REG_ANA_INBUF_EN(config->enableInputGainBuffer) |
114 ADC_ADC_REG_ANA_BIAS_SEL(config->powerMode) | ADC_ADC_REG_ANA_RES_SEL(config->resolution) |
115 ADC_ADC_REG_ANA_INBUF_CHOP_EN(config->enableInputBufferChop) | ADC_ADC_REG_ANA_CHOP_EN(config->enableChop);
116 base->ADC_REG_ANA = tmp32;
117
118 base->ADC_REG_RESULT_BUF = (base->ADC_REG_RESULT_BUF & ~(ADC_ADC_REG_RESULT_BUF_WIDTH_SEL_MASK)) |
119 ADC_ADC_REG_RESULT_BUF_WIDTH_SEL(config->resultWidth);
120
121 tmp32 = base->ADC_REG_DMAR;
122 tmp32 &= ~(ADC_ADC_REG_DMAR_DMA_EN_MASK | ADC_ADC_REG_DMAR_FIFO_THL_MASK);
123 tmp32 |= ADC_ADC_REG_DMAR_FIFO_THL(config->fifoThreshold) | ADC_ADC_REG_DMAR_DMA_EN(config->enableDMA);
124 base->ADC_REG_DMAR = tmp32;
125
126 if (config->enableADC)
127 {
128 base->ADC_REG_GENERAL |= ADC_ADC_REG_GENERAL_GLOBAL_EN_MASK;
129 }
130 }
131
132 /*!
133 * brief Get default configuration.
134 *
135 * code
136 * config->clockDivider = kADC_ClockDivider1;
137 * config->powerMode = kADC_PowerModeFullBiasingCurrent;
138 * config->resolution = kADC_Resolution12Bit;
139 * config->warmupTime = kADC_WarmUpTime16us;
140 * config->vrefSource = kADC_Vref1P2V;
141 * config->inputMode = kADC_InputSingleEnded;
142 * config->conversionMode = kADC_ConversionContinuous;
143 * config->scanLength = kADC_ScanLength_1;
144 * config->averageLength = kADC_AverageNone;
145 * config->triggerSource = kADC_TriggerSourceSoftware;
146 * config->inputGain = kADC_InputGain1;
147 * config->enableInputGainBuffer = false;
148 * config->resultWidth = kADC_ResultWidth16;
149 * config->fifoThreshold = kADC_FifoThresholdData1;
150 * config->enableDMA = false;
151 * config->enableADC = false;
152 * endcode
153 * param config Pointer to the structure adc_config_t.
154 */
ADC_GetDefaultConfig(adc_config_t * config)155 void ADC_GetDefaultConfig(adc_config_t *config)
156 {
157 assert(config != NULL);
158
159 (void)memset(config, 0, sizeof(adc_config_t));
160
161 config->clockDivider = kADC_ClockDivider1;
162 config->powerMode = kADC_PowerModeFullBiasingCurrent;
163 config->resolution = kADC_Resolution12Bit;
164 config->warmupTime = kADC_WarmUpTime16us;
165
166 config->vrefSource = kADC_Vref1P2V;
167 config->inputMode = kADC_InputSingleEnded;
168 config->conversionMode = kADC_ConversionContinuous;
169 config->scanLength = kADC_ScanLength_1;
170 config->averageLength = kADC_AverageNone;
171 config->triggerSource = kADC_TriggerSourceSoftware;
172 config->inputGain = kADC_InputGain1;
173 config->enableInputGainBuffer = false;
174 config->enableInputBufferChop = true;
175
176 config->resultWidth = kADC_ResultWidth16;
177 config->fifoThreshold = kADC_FifoThresholdData1;
178 config->enableDMA = false;
179 config->enableADC = false;
180 config->enableChop = true;
181 }
182
183 /*!
184 * brief De-initialize the ADC module.
185 *
186 * param base ADC peripheral base address.
187 */
ADC_Deinit(ADC_Type * base)188 void ADC_Deinit(ADC_Type *base)
189 {
190 ADC_DoSoftwareReset(base);
191
192 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
193 /* Ungate the ADC clock*/
194 (void)CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]);
195 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
196 }
197
198 /*!
199 * brief Set scan channel mux source.
200 *
201 * param base ADC peripheral base address.
202 * param scanChannel The selected channel, please refer to adc_scan_channel_t for details.
203 * param channelSource The mux source to be set to the selected channel,
204 * please refer to adc_channel_source_t for details.
205 */
ADC_SetScanChannel(ADC_Type * base,adc_scan_channel_t scanChannel,adc_channel_source_t channelSource)206 void ADC_SetScanChannel(ADC_Type *base, adc_scan_channel_t scanChannel, adc_channel_source_t channelSource)
207 {
208 if (scanChannel < kADC_ScanChannel8)
209 {
210 base->ADC_REG_SCN1 = (base->ADC_REG_SCN1 & ~(0xFUL << (uint32_t)(4UL * (uint32_t)scanChannel))) |
211 ((uint32_t)channelSource << (uint32_t)(4UL * (uint32_t)scanChannel));
212 }
213 else
214 {
215 base->ADC_REG_SCN2 = (base->ADC_REG_SCN2 & ~(0xFUL << (uint32_t)(4UL * ((uint32_t)scanChannel - 8UL)))) |
216 ((uint32_t)channelSource << (uint32_t)(4UL * ((uint32_t)scanChannel - 8UL)));
217 }
218 }
219
220 /*!
221 * brief Do automatic calibration measurement.
222 *
223 * note After auto calibrate successful, user can invoke ADC_GetAutoCalibrationData() to get self offset calibration
224 * value and self gain calibration value.
225 *
226 * param base ADC peripheral base address.
227 * param calVref The inpul reference channel for gain calibration,
228 * please refer to adc_calibration_ref_t for details.
229 * retval kStatus_Success Auto calibrate successfully.
230 * retval kStatus_Fail Auto calibrate failure.
231 */
ADC_DoAutoCalibration(ADC_Type * base,adc_calibration_ref_t calVref)232 status_t ADC_DoAutoCalibration(ADC_Type *base, adc_calibration_ref_t calVref)
233 {
234 uint32_t tmp32;
235
236 tmp32 = base->ADC_REG_CONFIG;
237 tmp32 &= ~(ADC_ADC_REG_CONFIG_CAL_VREF_SEL_MASK);
238 tmp32 |= ADC_ADC_REG_CONFIG_CAL_VREF_SEL(calVref);
239 base->ADC_REG_CONFIG = tmp32;
240
241 base->ADC_REG_CMD &= ~ADC_ADC_REG_CMD_CONV_START_MASK;
242 base->ADC_REG_GENERAL |= ADC_ADC_REG_GENERAL_ADC_CAL_EN_MASK;
243 base->ADC_REG_CMD |= ADC_ADC_REG_CMD_CONV_START_MASK;
244
245 /* Wait for self calibration done */
246 for (uint32_t i = 0UL; i < 1000000UL; i++)
247 {
248 if ((base->ADC_REG_GENERAL & ADC_ADC_REG_GENERAL_ADC_CAL_EN_MASK) == 0UL)
249 {
250 base->ADC_REG_CONFIG &= ~ADC_ADC_REG_CONFIG_CAL_DATA_SEL_MASK;
251 base->ADC_REG_CMD &= ~ADC_ADC_REG_CMD_CONV_START_MASK;
252 return kStatus_Success;
253 }
254 }
255
256 return kStatus_Fail;
257 }
258
259 /*!
260 * brief Configure audio voice level.
261 *
262 * param base ADC peripheral base address.
263 * param enableDetect Used to enable/disable voice level detection.
264 * - \b true Enable voice level detection.
265 * - \b false Disable voice level detection.
266 * param voiceLevel Selected voice level, please refer to adc_audio_voice_level_t.
267 */
ADC_ConfigAudioVoiceLevel(ADC_Type * base,bool enableDetect,adc_audio_voice_level_t voiceLevel)268 void ADC_ConfigAudioVoiceLevel(ADC_Type *base, bool enableDetect, adc_audio_voice_level_t voiceLevel)
269 {
270 uint32_t tmp32;
271
272 tmp32 = base->ADC_REG_VOICE_DET;
273 tmp32 &= ~(ADC_ADC_REG_VOICE_DET_DET_EN_MASK | ADC_ADC_REG_VOICE_DET_LEVEL_SEL_MASK);
274 tmp32 |= ADC_ADC_REG_VOICE_DET_DET_EN(enableDetect) | ADC_ADC_REG_VOICE_DET_LEVEL_SEL(voiceLevel);
275 base->ADC_REG_VOICE_DET = tmp32;
276 }
277
278 /*!
279 * brief Get status flags, including interrupt flags, raw flags, and so on.
280 *
281 * param base ADC peripheral base address.
282 * return The OR'ed value of ADC status flags, please refer to _adc_status_flags for details.
283 */
ADC_GetStatusFlags(ADC_Type * base)284 uint32_t ADC_GetStatusFlags(ADC_Type *base)
285 {
286 uint32_t tmp32;
287
288 tmp32 = base->ADC_REG_ISR;
289 tmp32 |= (base->ADC_REG_IRSR) << 7UL;
290 tmp32 |= (base->ADC_REG_STATUS) << 14UL;
291
292 return tmp32;
293 }
294