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