1 | /* |
2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. |
3 | * Copyright 2016-2019 NXP |
4 | * All rights reserved. |
5 | * |
6 | * SPDX-License-Identifier: BSD-3-Clause |
7 | */ |
8 | |
9 | #include "fsl_cmp.h" |
10 | |
11 | /* Component ID definition, used by tools. */ |
12 | #ifndef FSL_COMPONENT_ID |
13 | #define FSL_COMPONENT_ID "platform.drivers.cmp" |
14 | #endif |
15 | |
16 | /******************************************************************************* |
17 | * Prototypes |
18 | ******************************************************************************/ |
19 | /*! |
20 | * @brief Get instance number for CMP module. |
21 | * |
22 | * @param base CMP peripheral base address |
23 | */ |
24 | static uint32_t CMP_GetInstance(CMP_Type *base); |
25 | |
26 | /******************************************************************************* |
27 | * Variables |
28 | ******************************************************************************/ |
29 | /*! @brief Pointers to CMP bases for each instance. */ |
30 | static CMP_Type *const s_cmpBases[] = CMP_BASE_PTRS; |
31 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
32 | /*! @brief Pointers to CMP clocks for each instance. */ |
33 | static const clock_ip_name_t s_cmpClocks[] = CMP_CLOCKS; |
34 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
35 | |
36 | /******************************************************************************* |
37 | * Codes |
38 | ******************************************************************************/ |
39 | static uint32_t CMP_GetInstance(CMP_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_cmpBases); instance++) |
45 | { |
46 | if (s_cmpBases[instance] == base) |
47 | { |
48 | break; |
49 | } |
50 | } |
51 | |
52 | assert(instance < ARRAY_SIZE(s_cmpBases)); |
53 | |
54 | return instance; |
55 | } |
56 | |
57 | /*! |
58 | * brief Initializes the CMP. |
59 | * |
60 | * This function initializes the CMP module. The operations included are as follows. |
61 | * - Enabling the clock for CMP module. |
62 | * - Configuring the comparator. |
63 | * - Enabling the CMP module. |
64 | * Note that for some devices, multiple CMP instances share the same clock gate. In this case, to enable the clock for |
65 | * any instance enables all CMPs. See the appropriate MCU reference manual for the clock assignment of the CMP. |
66 | * |
67 | * param base CMP peripheral base address. |
68 | * param config Pointer to the configuration structure. |
69 | */ |
70 | void CMP_Init(CMP_Type *base, const cmp_config_t *config) |
71 | { |
72 | assert(NULL != config); |
73 | |
74 | uint8_t tmp8; |
75 | |
76 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
77 | /* Enable the clock. */ |
78 | CLOCK_EnableClock(s_cmpClocks[CMP_GetInstance(base)]); |
79 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
80 | |
81 | /* Configure. */ |
82 | CMP_Enable(base, false); /* Disable the CMP module during configuring. */ |
83 | /* CMPx_CR1. */ |
84 | tmp8 = (uint8_t)(base->CR1 & ~(CMP_CR1_PMODE_MASK | CMP_CR1_INV_MASK | CMP_CR1_COS_MASK | CMP_CR1_OPE_MASK)); |
85 | if (true == config->enableHighSpeed) |
86 | { |
87 | tmp8 |= CMP_CR1_PMODE_MASK; |
88 | } |
89 | if (true == config->enableInvertOutput) |
90 | { |
91 | tmp8 |= CMP_CR1_INV_MASK; |
92 | } |
93 | if (true == config->useUnfilteredOutput) |
94 | { |
95 | tmp8 |= CMP_CR1_COS_MASK; |
96 | } |
97 | if (true == config->enablePinOut) |
98 | { |
99 | tmp8 |= CMP_CR1_OPE_MASK; |
100 | } |
101 | #if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE |
102 | if (true == config->enableTriggerMode) |
103 | { |
104 | tmp8 |= CMP_CR1_TRIGM_MASK; |
105 | } |
106 | else |
107 | { |
108 | tmp8 &= ~(uint8_t)CMP_CR1_TRIGM_MASK; |
109 | } |
110 | #endif /* FSL_FEATURE_CMP_HAS_TRIGGER_MODE */ |
111 | base->CR1 = tmp8; |
112 | |
113 | /* CMPx_CR0. */ |
114 | tmp8 = base->CR0 & ~(uint8_t)CMP_CR0_HYSTCTR_MASK; |
115 | tmp8 |= CMP_CR0_HYSTCTR(config->hysteresisMode); |
116 | base->CR0 = tmp8; |
117 | |
118 | CMP_Enable(base, config->enableCmp); /* Enable the CMP module after configured or not. */ |
119 | } |
120 | |
121 | /*! |
122 | * brief De-initializes the CMP module. |
123 | * |
124 | * This function de-initializes the CMP module. The operations included are as follows. |
125 | * - Disabling the CMP module. |
126 | * - Disabling the clock for CMP module. |
127 | * |
128 | * This function disables the clock for the CMP. |
129 | * Note that for some devices, multiple CMP instances share the same clock gate. In this case, before disabling the |
130 | * clock for the CMP, ensure that all the CMP instances are not used. |
131 | * |
132 | * param base CMP peripheral base address. |
133 | */ |
134 | void CMP_Deinit(CMP_Type *base) |
135 | { |
136 | /* Disable the CMP module. */ |
137 | CMP_Enable(base, false); |
138 | |
139 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
140 | /* Disable the clock. */ |
141 | CLOCK_DisableClock(s_cmpClocks[CMP_GetInstance(base)]); |
142 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
143 | } |
144 | |
145 | /*! |
146 | * brief Initializes the CMP user configuration structure. |
147 | * |
148 | * This function initializes the user configuration structure to these default values. |
149 | * code |
150 | * config->enableCmp = true; |
151 | * config->hysteresisMode = kCMP_HysteresisLevel0; |
152 | * config->enableHighSpeed = false; |
153 | * config->enableInvertOutput = false; |
154 | * config->useUnfilteredOutput = false; |
155 | * config->enablePinOut = false; |
156 | * config->enableTriggerMode = false; |
157 | * endcode |
158 | * param config Pointer to the configuration structure. |
159 | */ |
160 | void CMP_GetDefaultConfig(cmp_config_t *config) |
161 | { |
162 | assert(NULL != config); |
163 | |
164 | /* Initializes the configure structure to zero. */ |
165 | (void)memset(config, 0, sizeof(*config)); |
166 | |
167 | config->enableCmp = true; /* Enable the CMP module after initialization. */ |
168 | config->hysteresisMode = kCMP_HysteresisLevel0; |
169 | config->enableHighSpeed = false; |
170 | config->enableInvertOutput = false; |
171 | config->useUnfilteredOutput = false; |
172 | config->enablePinOut = false; |
173 | #if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE |
174 | config->enableTriggerMode = false; |
175 | #endif /* FSL_FEATURE_CMP_HAS_TRIGGER_MODE */ |
176 | } |
177 | |
178 | /*! |
179 | * brief Sets the input channels for the comparator. |
180 | * |
181 | * This function sets the input channels for the comparator. |
182 | * Note that two input channels cannot be set the same way in the application. When the user selects the same input |
183 | * from the analog mux to the positive and negative port, the comparator is disabled automatically. |
184 | * |
185 | * param base CMP peripheral base address. |
186 | * param positiveChannel Positive side input channel number. Available range is 0-7. |
187 | * param negativeChannel Negative side input channel number. Available range is 0-7. |
188 | */ |
189 | void CMP_SetInputChannels(CMP_Type *base, uint8_t positiveChannel, uint8_t negativeChannel) |
190 | { |
191 | uint8_t tmp8 = base->MUXCR; |
192 | |
193 | tmp8 &= ~(uint8_t)(CMP_MUXCR_PSEL_MASK | CMP_MUXCR_MSEL_MASK); |
194 | tmp8 |= CMP_MUXCR_PSEL(positiveChannel) | CMP_MUXCR_MSEL(negativeChannel); |
195 | base->MUXCR = tmp8; |
196 | } |
197 | |
198 | #if defined(FSL_FEATURE_CMP_HAS_DMA) && FSL_FEATURE_CMP_HAS_DMA |
199 | /*! |
200 | * brief Enables/disables the DMA request for rising/falling events. |
201 | * |
202 | * This function enables/disables the DMA request for rising/falling events. Either event triggers the generation of |
203 | * the DMA request from CMP if the DMA feature is enabled. Both events are ignored for generating the DMA request from |
204 | * the CMP |
205 | * if the DMA is disabled. |
206 | * |
207 | * param base CMP peripheral base address. |
208 | * param enable Enables or disables the feature. |
209 | */ |
210 | void CMP_EnableDMA(CMP_Type *base, bool enable) |
211 | { |
212 | uint8_t tmp8 = (uint8_t)(base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK)); /* To avoid change the w1c bits. */ |
213 | |
214 | if (enable) |
215 | { |
216 | tmp8 |= CMP_SCR_DMAEN_MASK; |
217 | } |
218 | else |
219 | { |
220 | tmp8 &= ~(uint8_t)CMP_SCR_DMAEN_MASK; |
221 | } |
222 | base->SCR = tmp8; |
223 | } |
224 | #endif /* FSL_FEATURE_CMP_HAS_DMA */ |
225 | |
226 | /*! |
227 | * brief Configures the filter. |
228 | * |
229 | * param base CMP peripheral base address. |
230 | * param config Pointer to the configuration structure. |
231 | */ |
232 | void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config) |
233 | { |
234 | assert(NULL != config); |
235 | |
236 | uint8_t tmp8; |
237 | |
238 | #if defined(FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT) && FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT |
239 | /* Choose the clock source for sampling. */ |
240 | if (config->enableSample) |
241 | { |
242 | base->CR1 |= CMP_CR1_SE_MASK; /* Choose the external SAMPLE clock. */ |
243 | } |
244 | else |
245 | { |
246 | base->CR1 &= (uint8_t)(~CMP_CR1_SE_MASK); /* Choose the internal divided bus clock. */ |
247 | } |
248 | #endif /* FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT */ |
249 | /* Set the filter count. */ |
250 | tmp8 = (uint8_t)(base->CR0 & ~CMP_CR0_FILTER_CNT_MASK); |
251 | tmp8 |= CMP_CR0_FILTER_CNT(config->filterCount); |
252 | base->CR0 = tmp8; |
253 | /* Set the filter period. It is used as the divider to bus clock. */ |
254 | base->FPR = CMP_FPR_FILT_PER(config->filterPeriod); |
255 | } |
256 | |
257 | /*! |
258 | * brief Configures the internal DAC. |
259 | * |
260 | * param base CMP peripheral base address. |
261 | * param config Pointer to the configuration structure. "NULL" disables the feature. |
262 | */ |
263 | void CMP_SetDACConfig(CMP_Type *base, const cmp_dac_config_t *config) |
264 | { |
265 | uint8_t tmp8 = 0U; |
266 | |
267 | if (NULL == config) |
268 | { |
269 | /* Passing "NULL" as input parameter means no available configuration. So the DAC feature is disabled.*/ |
270 | base->DACCR = 0U; |
271 | return; |
272 | } |
273 | /* CMPx_DACCR. */ |
274 | tmp8 |= CMP_DACCR_DACEN_MASK; /* Enable the internal DAC. */ |
275 | if (kCMP_VrefSourceVin2 == config->referenceVoltageSource) |
276 | { |
277 | tmp8 |= CMP_DACCR_VRSEL_MASK; |
278 | } |
279 | tmp8 |= CMP_DACCR_VOSEL(config->DACValue); |
280 | |
281 | base->DACCR = tmp8; |
282 | } |
283 | |
284 | /*! |
285 | * brief Enables the interrupts. |
286 | * |
287 | * param base CMP peripheral base address. |
288 | * param mask Mask value for interrupts. See "_cmp_interrupt_enable". |
289 | */ |
290 | void CMP_EnableInterrupts(CMP_Type *base, uint32_t mask) |
291 | { |
292 | uint8_t tmp8 = (uint8_t)(base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK)); /* To avoid change the w1c bits. */ |
293 | |
294 | if (0U != ((uint32_t)kCMP_OutputRisingInterruptEnable & mask)) |
295 | { |
296 | tmp8 |= CMP_SCR_IER_MASK; |
297 | } |
298 | if (0U != ((uint32_t)kCMP_OutputFallingInterruptEnable & mask)) |
299 | { |
300 | tmp8 |= CMP_SCR_IEF_MASK; |
301 | } |
302 | base->SCR = tmp8; |
303 | } |
304 | |
305 | /*! |
306 | * brief Disables the interrupts. |
307 | * |
308 | * param base CMP peripheral base address. |
309 | * param mask Mask value for interrupts. See "_cmp_interrupt_enable". |
310 | */ |
311 | void CMP_DisableInterrupts(CMP_Type *base, uint32_t mask) |
312 | { |
313 | uint8_t tmp8 = (uint8_t)(base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK)); /* To avoid change the w1c bits. */ |
314 | |
315 | if (0U != ((uint32_t)kCMP_OutputRisingInterruptEnable & mask)) |
316 | { |
317 | tmp8 &= ~(uint8_t)CMP_SCR_IER_MASK; |
318 | } |
319 | if (0U != ((uint32_t)kCMP_OutputFallingInterruptEnable & mask)) |
320 | { |
321 | tmp8 &= ~(uint8_t)CMP_SCR_IEF_MASK; |
322 | } |
323 | base->SCR = tmp8; |
324 | } |
325 | |
326 | /*! |
327 | * brief Gets the status flags. |
328 | * |
329 | * param base CMP peripheral base address. |
330 | * |
331 | * return Mask value for the asserted flags. See "_cmp_status_flags". |
332 | */ |
333 | uint32_t CMP_GetStatusFlags(CMP_Type *base) |
334 | { |
335 | uint32_t ret32 = 0U; |
336 | |
337 | if (0U != (CMP_SCR_CFR_MASK & base->SCR)) |
338 | { |
339 | ret32 |= (uint32_t)kCMP_OutputRisingEventFlag; |
340 | } |
341 | if (0U != (CMP_SCR_CFF_MASK & base->SCR)) |
342 | { |
343 | ret32 |= (uint32_t)kCMP_OutputFallingEventFlag; |
344 | } |
345 | if (0U != (CMP_SCR_COUT_MASK & base->SCR)) |
346 | { |
347 | ret32 |= (uint32_t)kCMP_OutputAssertEventFlag; |
348 | } |
349 | return ret32; |
350 | } |
351 | |
352 | /*! |
353 | * brief Clears the status flags. |
354 | * |
355 | * param base CMP peripheral base address. |
356 | * param mask Mask value for the flags. See "_cmp_status_flags". |
357 | */ |
358 | void CMP_ClearStatusFlags(CMP_Type *base, uint32_t mask) |
359 | { |
360 | uint8_t tmp8 = (uint8_t)(base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK)); /* To avoid change the w1c bits. */ |
361 | |
362 | if (0U != ((uint32_t)kCMP_OutputRisingEventFlag & mask)) |
363 | { |
364 | tmp8 |= CMP_SCR_CFR_MASK; |
365 | } |
366 | if (0U != ((uint32_t)kCMP_OutputFallingEventFlag & mask)) |
367 | { |
368 | tmp8 |= CMP_SCR_CFF_MASK; |
369 | } |
370 | base->SCR = tmp8; |
371 | } |
372 | |