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