1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * o Redistributions of source code must retain the above copyright notice, this list
9 * of conditions and the following disclaimer.
10 *
11 * o Redistributions in binary form must reproduce the above copyright notice, this
12 * list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * o Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "fsl_cmp.h"
32
33 /*******************************************************************************
34 * Prototypes
35 ******************************************************************************/
36 /*!
37 * @brief Get instance number for CMP module.
38 *
39 * @param base CMP peripheral base address
40 */
41 static uint32_t CMP_GetInstance(CMP_Type *base);
42
43 /*******************************************************************************
44 * Variables
45 ******************************************************************************/
46 /*! @brief Pointers to CMP bases for each instance. */
47 static CMP_Type *const s_cmpBases[] = CMP_BASE_PTRS;
48 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
49 /*! @brief Pointers to CMP clocks for each instance. */
50 static const clock_ip_name_t s_cmpClocks[] = CMP_CLOCKS;
51 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
52
53 /*******************************************************************************
54 * Codes
55 ******************************************************************************/
CMP_GetInstance(CMP_Type * base)56 static uint32_t CMP_GetInstance(CMP_Type *base)
57 {
58 uint32_t instance;
59
60 /* Find the instance index from base address mappings. */
61 for (instance = 0; instance < ARRAY_SIZE(s_cmpBases); instance++)
62 {
63 if (s_cmpBases[instance] == base)
64 {
65 break;
66 }
67 }
68
69 assert(instance < ARRAY_SIZE(s_cmpBases));
70
71 return instance;
72 }
73
CMP_Init(CMP_Type * base,const cmp_config_t * config)74 void CMP_Init(CMP_Type *base, const cmp_config_t *config)
75 {
76 assert(NULL != config);
77
78 uint8_t tmp8;
79
80 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
81 /* Enable the clock. */
82 CLOCK_EnableClock(s_cmpClocks[CMP_GetInstance(base)]);
83 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
84
85 /* Configure. */
86 CMP_Enable(base, false); /* Disable the CMP module during configuring. */
87 /* CMPx_CR1. */
88 tmp8 = base->CR1 & ~(CMP_CR1_PMODE_MASK | CMP_CR1_INV_MASK | CMP_CR1_COS_MASK | CMP_CR1_OPE_MASK);
89 if (config->enableHighSpeed)
90 {
91 tmp8 |= CMP_CR1_PMODE_MASK;
92 }
93 if (config->enableInvertOutput)
94 {
95 tmp8 |= CMP_CR1_INV_MASK;
96 }
97 if (config->useUnfilteredOutput)
98 {
99 tmp8 |= CMP_CR1_COS_MASK;
100 }
101 if (config->enablePinOut)
102 {
103 tmp8 |= CMP_CR1_OPE_MASK;
104 }
105 #if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE
106 if (config->enableTriggerMode)
107 {
108 tmp8 |= CMP_CR1_TRIGM_MASK;
109 }
110 else
111 {
112 tmp8 &= ~CMP_CR1_TRIGM_MASK;
113 }
114 #endif /* FSL_FEATURE_CMP_HAS_TRIGGER_MODE */
115 base->CR1 = tmp8;
116
117 /* CMPx_CR0. */
118 tmp8 = base->CR0 & ~CMP_CR0_HYSTCTR_MASK;
119 tmp8 |= CMP_CR0_HYSTCTR(config->hysteresisMode);
120 base->CR0 = tmp8;
121
122 CMP_Enable(base, config->enableCmp); /* Enable the CMP module after configured or not. */
123 }
124
CMP_Deinit(CMP_Type * base)125 void CMP_Deinit(CMP_Type *base)
126 {
127 /* Disable the CMP module. */
128 CMP_Enable(base, false);
129
130 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
131 /* Disable the clock. */
132 CLOCK_DisableClock(s_cmpClocks[CMP_GetInstance(base)]);
133 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
134 }
135
CMP_GetDefaultConfig(cmp_config_t * config)136 void CMP_GetDefaultConfig(cmp_config_t *config)
137 {
138 assert(NULL != config);
139
140 config->enableCmp = true; /* Enable the CMP module after initialization. */
141 config->hysteresisMode = kCMP_HysteresisLevel0;
142 config->enableHighSpeed = false;
143 config->enableInvertOutput = false;
144 config->useUnfilteredOutput = false;
145 config->enablePinOut = false;
146 #if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE
147 config->enableTriggerMode = false;
148 #endif /* FSL_FEATURE_CMP_HAS_TRIGGER_MODE */
149 }
150
CMP_SetInputChannels(CMP_Type * base,uint8_t positiveChannel,uint8_t negativeChannel)151 void CMP_SetInputChannels(CMP_Type *base, uint8_t positiveChannel, uint8_t negativeChannel)
152 {
153 uint8_t tmp8 = base->MUXCR;
154
155 tmp8 &= ~(CMP_MUXCR_PSEL_MASK | CMP_MUXCR_MSEL_MASK);
156 tmp8 |= CMP_MUXCR_PSEL(positiveChannel) | CMP_MUXCR_MSEL(negativeChannel);
157 base->MUXCR = tmp8;
158 }
159
160 #if defined(FSL_FEATURE_CMP_HAS_DMA) && FSL_FEATURE_CMP_HAS_DMA
CMP_EnableDMA(CMP_Type * base,bool enable)161 void CMP_EnableDMA(CMP_Type *base, bool enable)
162 {
163 uint8_t tmp8 = base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK); /* To avoid change the w1c bits. */
164
165 if (enable)
166 {
167 tmp8 |= CMP_SCR_DMAEN_MASK;
168 }
169 else
170 {
171 tmp8 &= ~CMP_SCR_DMAEN_MASK;
172 }
173 base->SCR = tmp8;
174 }
175 #endif /* FSL_FEATURE_CMP_HAS_DMA */
176
CMP_SetFilterConfig(CMP_Type * base,const cmp_filter_config_t * config)177 void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config)
178 {
179 assert(NULL != config);
180
181 uint8_t tmp8;
182
183 #if defined(FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT) && FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT
184 /* Choose the clock source for sampling. */
185 if (config->enableSample)
186 {
187 base->CR1 |= CMP_CR1_SE_MASK; /* Choose the external SAMPLE clock. */
188 }
189 else
190 {
191 base->CR1 &= ~CMP_CR1_SE_MASK; /* Choose the internal divided bus clock. */
192 }
193 #endif /* FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT */
194 /* Set the filter count. */
195 tmp8 = base->CR0 & ~CMP_CR0_FILTER_CNT_MASK;
196 tmp8 |= CMP_CR0_FILTER_CNT(config->filterCount);
197 base->CR0 = tmp8;
198 /* Set the filter period. It is used as the divider to bus clock. */
199 base->FPR = CMP_FPR_FILT_PER(config->filterPeriod);
200 }
201
CMP_SetDACConfig(CMP_Type * base,const cmp_dac_config_t * config)202 void CMP_SetDACConfig(CMP_Type *base, const cmp_dac_config_t *config)
203 {
204 uint8_t tmp8 = 0U;
205
206 if (NULL == config)
207 {
208 /* Passing "NULL" as input parameter means no available configuration. So the DAC feature is disabled.*/
209 base->DACCR = 0U;
210 return;
211 }
212 /* CMPx_DACCR. */
213 tmp8 |= CMP_DACCR_DACEN_MASK; /* Enable the internal DAC. */
214 if (kCMP_VrefSourceVin2 == config->referenceVoltageSource)
215 {
216 tmp8 |= CMP_DACCR_VRSEL_MASK;
217 }
218 tmp8 |= CMP_DACCR_VOSEL(config->DACValue);
219
220 base->DACCR = tmp8;
221 }
222
CMP_EnableInterrupts(CMP_Type * base,uint32_t mask)223 void CMP_EnableInterrupts(CMP_Type *base, uint32_t mask)
224 {
225 uint8_t tmp8 = base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK); /* To avoid change the w1c bits. */
226
227 if (0U != (kCMP_OutputRisingInterruptEnable & mask))
228 {
229 tmp8 |= CMP_SCR_IER_MASK;
230 }
231 if (0U != (kCMP_OutputFallingInterruptEnable & mask))
232 {
233 tmp8 |= CMP_SCR_IEF_MASK;
234 }
235 base->SCR = tmp8;
236 }
237
CMP_DisableInterrupts(CMP_Type * base,uint32_t mask)238 void CMP_DisableInterrupts(CMP_Type *base, uint32_t mask)
239 {
240 uint8_t tmp8 = base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK); /* To avoid change the w1c bits. */
241
242 if (0U != (kCMP_OutputRisingInterruptEnable & mask))
243 {
244 tmp8 &= ~CMP_SCR_IER_MASK;
245 }
246 if (0U != (kCMP_OutputFallingInterruptEnable & mask))
247 {
248 tmp8 &= ~CMP_SCR_IEF_MASK;
249 }
250 base->SCR = tmp8;
251 }
252
CMP_GetStatusFlags(CMP_Type * base)253 uint32_t CMP_GetStatusFlags(CMP_Type *base)
254 {
255 uint32_t ret32 = 0U;
256
257 if (0U != (CMP_SCR_CFR_MASK & base->SCR))
258 {
259 ret32 |= kCMP_OutputRisingEventFlag;
260 }
261 if (0U != (CMP_SCR_CFF_MASK & base->SCR))
262 {
263 ret32 |= kCMP_OutputFallingEventFlag;
264 }
265 if (0U != (CMP_SCR_COUT_MASK & base->SCR))
266 {
267 ret32 |= kCMP_OutputAssertEventFlag;
268 }
269 return ret32;
270 }
271
CMP_ClearStatusFlags(CMP_Type * base,uint32_t mask)272 void CMP_ClearStatusFlags(CMP_Type *base, uint32_t mask)
273 {
274 uint8_t tmp8 = base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK); /* To avoid change the w1c bits. */
275
276 if (0U != (kCMP_OutputRisingEventFlag & mask))
277 {
278 tmp8 |= CMP_SCR_CFR_MASK;
279 }
280 if (0U != (kCMP_OutputFallingEventFlag & mask))
281 {
282 tmp8 |= CMP_SCR_CFF_MASK;
283 }
284 base->SCR = tmp8;
285 }
286