1 /*
2 * Copyright 2017-2019 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_acmp.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.acmp_1"
17 #endif
18
19 /*******************************************************************************
20 * Prototypes
21 ******************************************************************************/
22 /*!
23 * @brief Get the ACMP instance from the peripheral base address.
24 *
25 * @param base ACMP peripheral base address.
26 * @return ACMP instance.
27 */
28 static uint32_t ACMP_GetInstance(ACMP_Type *base);
29
30 /*******************************************************************************
31 * Variables
32 ******************************************************************************/
33 /* Array of ACMP peripheral base address. */
34 static ACMP_Type *const s_acmpBases[] = ACMP_BASE_PTRS;
35 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
36 /* Clock name of ACMP. */
37 static const clock_ip_name_t s_acmpClock[] = ACMP_CLOCKS;
38 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
39
40 /*******************************************************************************
41 * Codes
42 ******************************************************************************/
ACMP_GetInstance(ACMP_Type * base)43 static uint32_t ACMP_GetInstance(ACMP_Type *base)
44 {
45 uint32_t instance = 0U;
46
47 /* Find the instance index from base address mappings. */
48 for (instance = 0; instance < ARRAY_SIZE(s_acmpBases); instance++)
49 {
50 if (s_acmpBases[instance] == base)
51 {
52 break;
53 }
54 }
55
56 assert(instance < ARRAY_SIZE(s_acmpBases));
57
58 return instance;
59 }
60
61 /*!
62 * brief Initialize the ACMP.
63 *
64 * The default configuration can be got by calling ACMP_GetDefaultConfig().
65 *
66 * param base ACMP peripheral base address.
67 * param config Pointer to ACMP configuration structure.
68 */
ACMP_Init(ACMP_Type * base,const acmp_config_t * config)69 void ACMP_Init(ACMP_Type *base, const acmp_config_t *config)
70 {
71 assert(NULL != config);
72
73 uint8_t tmp8;
74
75 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
76 /* Open clock gate. */
77 CLOCK_EnableClock(s_acmpClock[ACMP_GetInstance(base)]);
78 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
79
80 /* Disable the module before configuring it. */
81 ACMP_Enable(base, false);
82
83 /* ACMP_CS register. */
84 tmp8 = base->CS & (uint8_t)(~(ACMP_CS_HYST_MASK | ACMP_CS_ACOPE_MASK));
85
86 tmp8 |= ACMP_CS_HYST(config->hysteresisMode);
87 if (config->enablePinOut)
88 {
89 tmp8 |= ACMP_CS_ACOPE_MASK;
90 }
91 base->CS = tmp8;
92 }
93
94 /*!
95 * brief De-Initialize the ACMP.
96 *
97 * param base ACMP peripheral basic address.
98 */
ACMP_Deinit(ACMP_Type * base)99 void ACMP_Deinit(ACMP_Type *base)
100 {
101 /* Disable the ACMP module. */
102 ACMP_Enable(base, false);
103 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
104 /* Close clock gate. */
105 CLOCK_DisableClock(s_acmpClock[ACMP_GetInstance(base)]);
106 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
107 }
108
109 /*!
110 * brief Gets the default configuration for ACMP.
111 *
112 * This function initializes the user configuration structure to default value. The default value are:
113 * Example:
114 * code
115 * config->enablePinOut = false;
116 * config->hysteresisMode = kACMP_HysterisisLevel1;
117 * endcode
118 *
119 * param config Pointer to ACMP configuration structure.
120 */
ACMP_GetDefaultConfig(acmp_config_t * config)121 void ACMP_GetDefaultConfig(acmp_config_t *config)
122 {
123 assert(NULL != config);
124
125 /* Initializes the configure structure to zero. */
126 (void)memset(config, 0, sizeof(*config));
127
128 config->enablePinOut = false;
129 config->hysteresisMode = kACMP_HysterisisLevel1;
130 }
131
132 /*!
133 * brief Enable the ACMP interrupt and determines the sensitivity modes of the interrupt trigger.
134 *
135 *
136 * param base ACMP peripheral base address.
137 * param mode Select one interrupt mode to generate interrupt.
138 */
ACMP_EnableInterrupt(ACMP_Type * base,acmp_interrupt_mode_t mode)139 void ACMP_EnableInterrupt(ACMP_Type *base, acmp_interrupt_mode_t mode)
140 {
141 uint8_t tmp8;
142
143 /* ACMP_CS register. */
144 tmp8 = base->CS & (uint8_t)(~ACMP_CS_ACMOD_MASK);
145
146 tmp8 |= ACMP_CS_ACIE_MASK | ACMP_CS_ACMOD(mode);
147 base->CS = tmp8;
148 }
149
150 /*!
151 * brief Configure the ACMP positive and negative input channel.
152 *
153 * param base ACMP peripheral base address.
154 * param PositiveInput ACMP Positive Input Select. Refer to "acmp_input_channel_selection_t".
155 * param negativeInout ACMP Negative Input Select. Refer to "acmp_input_channel_selection_t".
156 */
ACMP_SetChannelConfig(ACMP_Type * base,acmp_input_channel_selection_t PositiveInput,acmp_input_channel_selection_t negativeInout)157 void ACMP_SetChannelConfig(ACMP_Type *base,
158 acmp_input_channel_selection_t PositiveInput,
159 acmp_input_channel_selection_t negativeInout)
160 {
161 uint8_t tmp8;
162
163 /* ACMP_C0 register. */
164 tmp8 = ACMP_C0_ACPSEL(PositiveInput) | ACMP_C0_ACNSEL(negativeInout);
165 base->C0 = tmp8;
166 }
167
168 /*
169 * brief Configure the internal DAC.
170 *
171 * param base ACMP peripheral base address.
172 * param config Pointer to DAC configuration structure. "NULL" is for disabling the feature.
173 */
ACMP_SetDACConfig(ACMP_Type * base,const acmp_dac_config_t * config)174 void ACMP_SetDACConfig(ACMP_Type *base, const acmp_dac_config_t *config)
175 {
176 uint8_t tmp8;
177
178 /* "NULL" is for disabling the feature. */
179 if (NULL == config)
180 {
181 tmp8 = 0U;
182 }
183 else
184 {
185 /* ACMP_C1 register. */
186 tmp8 = ACMP_C1_DACEN_MASK | ACMP_C1_DACREF(config->referenceVoltageSource) | ACMP_C1_DACVAL(config->DACValue);
187 }
188 base->C1 = tmp8;
189 }
190
191 /*!
192 * brief Enable/Disable ACMP input pin.
193 * The API controls if the corresponding ACMP external pin can be driven by an analog input
194 *
195 * param base ACMP peripheral base address.
196 * param mask The mask of the pin associated with channel ADx. Valid range is AD0:0x1U ~ AD3:0x4U.
197 * For example: If enable AD0, AD1 and AD2 pins, mask should be set to 0x7U(0x1 | 0x2 | 0x4).
198 */
ACMP_EnableInputPin(ACMP_Type * base,uint32_t mask,bool enable)199 void ACMP_EnableInputPin(ACMP_Type *base, uint32_t mask, bool enable)
200 {
201 assert(mask <= ACMP_C2_ACIPE_MASK);
202
203 if (enable)
204 {
205 base->C2 |= ACMP_C2_ACIPE(mask);
206 }
207 else
208 {
209 base->C2 &= ~ACMP_C2_ACIPE(mask);
210 }
211 }
212