1 /***************************************************************************/ /**
2 * \file cyhal_comp.c
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Infineon analog
6 * comparator. This interface abstracts out the chip specific details. If any chip
7 * specific functionality is necessary, or performance is critical the low level
8 * functions can be used directly.
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
13 * an affiliate of Cypress Semiconductor Corporation
14 *
15 * SPDX-License-Identifier: Apache-2.0
16 *
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 *
21 * http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
28 *******************************************************************************/
29 #include "cyhal_comp.h"
30 #include "cyhal_comp_ctb.h"
31 #include "cyhal_comp_lp.h"
32 #include "cyhal_gpio.h"
33 #include "cyhal_system.h"
34
35 #include <string.h> // For memset
36
37 /**
38 * \addtogroup group_hal_impl_comp COMP (Analog Comparator)
39 * \ingroup group_hal_impl
40 * \{
41 * On CAT1 & CAT2, the comparator driver can use either of two underlying hardware blocks:
42 * - Opamp (configured as analog comparator)
43 * - LPComp (Low Power Comparator)
44 *
45 * Generally, a set of pins can only connect to either an Opamp or an LPComp but not both. In the event
46 * that both connections are possible, the LPComp will be preferred.
47 *
48 * \section group_hal_impl_comp_power Power Level Mapping
49 * The following table shows how the HAL-defined power levels map to the hardware-specific power levels.
50 * For the LPComp, some levels are named differently between CAT1 & CAT2. In this case, the differences
51 * are in brackets, with the first item being for CAT1 and the second for CAT2.
52 * | HAL Power Level | Opamp Power Level | LPComp Power Level |
53 * | ------------------------------ | ------------------- | ---------------------------- |
54 * | @ref CYHAL_POWER_LEVEL_HIGH | CY_CTB_POWER_HIGH | CY_LPCOMP_MODE_[NORMAL/FAST] |
55 * | @ref CYHAL_POWER_LEVEL_MEDIUM | CY_CTB_POWER_MEDIUM | CY_LPCOMP_MODE_[LP/SLOW] |
56 * | @ref CYHAL_POWER_LEVEL_LOW | CY_CTB_POWER_LOW | CY_LPCOMP_MODE_ULP |
57 * | @ref CYHAL_POWER_LEVEL_DEFAULT | CY_CTB_POWER_MEDIUM | CY_LPCOMP_MODE_[LP/SLOW] |
58 *
59 * \} group_hal_impl_comp
60 */
61
62 /* This file is the top-level wrapper. Comp can be implemented on top of either LPComp or the CTB Opamps */
63 #if (CYHAL_DRIVER_AVAILABLE_COMP)
64
65 #if defined(__cplusplus)
66 extern "C"
67 {
68 #endif
69
cyhal_comp_init(cyhal_comp_t * obj,cyhal_gpio_t vin_p,cyhal_gpio_t vin_m,cyhal_gpio_t output,cyhal_comp_config_t * cfg)70 cy_rslt_t cyhal_comp_init(cyhal_comp_t *obj, cyhal_gpio_t vin_p, cyhal_gpio_t vin_m, cyhal_gpio_t output, cyhal_comp_config_t *cfg)
71 {
72 cy_rslt_t result;
73 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
74 result = _cyhal_comp_lp_init(obj, vin_p, vin_m, output, cfg);
75 #endif
76 #if (_CYHAL_DRIVER_AVAILABLE_COMP_CTB)
77 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
78 if (CY_RSLT_SUCCESS != result)
79 #endif
80 {
81 result = _cyhal_comp_ctb_init(obj, vin_p, vin_m, output, cfg);
82 }
83 #endif
84 return result;
85 }
86
cyhal_comp_init_cfg(cyhal_comp_t * obj,const cyhal_comp_configurator_t * cfg)87 cy_rslt_t cyhal_comp_init_cfg(cyhal_comp_t *obj, const cyhal_comp_configurator_t *cfg)
88 {
89 cy_rslt_t result = CYHAL_COMP_RSLT_ERR_BAD_ARGUMENT;
90 memset(obj, 0, sizeof(cyhal_comp_t));
91 obj->owned_by_configurator = true;
92 obj->resource = *cfg->resource;
93 obj->pin_vin_p = NC;
94 obj->pin_vin_m = NC;
95 obj->pin_out = NC;
96
97 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
98 if (CYHAL_RSC_LPCOMP == cfg->resource->type)
99 {
100 result = _cyhal_comp_lp_init_cfg(obj, cfg);
101 }
102 #endif
103
104 #if (_CYHAL_DRIVER_AVAILABLE_COMP_CTB)
105 if (CYHAL_RSC_OPAMP == cfg->resource->type)
106 {
107 result = _cyhal_comp_ctb_init_cfg(obj, cfg);
108 }
109 #endif
110
111 return result;
112 }
113
cyhal_comp_free(cyhal_comp_t * obj)114 void cyhal_comp_free(cyhal_comp_t *obj)
115 {
116 #if (_CYHAL_DRIVER_AVAILABLE_COMP_CTB)
117 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
118 if(obj->resource.type == CYHAL_RSC_OPAMP)
119 #endif
120 {
121 _cyhal_comp_ctb_free(obj);
122 }
123 #endif
124 {
125 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
126 #if (_CYHAL_DRIVER_AVAILABLE_COMP_CTB)
127 if(obj->resource.type == CYHAL_RSC_LPCOMP)
128 #endif
129 {
130 _cyhal_comp_lp_free(obj);
131 }
132 #endif
133 }
134 }
135
cyhal_comp_set_power(cyhal_comp_t * obj,cyhal_power_level_t power)136 cy_rslt_t cyhal_comp_set_power(cyhal_comp_t *obj, cyhal_power_level_t power)
137 {
138 #if (_CYHAL_DRIVER_AVAILABLE_COMP_CTB)
139 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
140 if(obj->resource.type == CYHAL_RSC_OPAMP)
141 #endif
142 {
143 return _cyhal_comp_ctb_set_power(obj, power);
144 }
145 #endif
146 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
147 CY_ASSERT(obj->resource.type == CYHAL_RSC_LPCOMP);
148 return _cyhal_comp_lp_set_power(obj, power);
149 #endif
150 }
151
cyhal_comp_configure(cyhal_comp_t * obj,cyhal_comp_config_t * cfg)152 cy_rslt_t cyhal_comp_configure(cyhal_comp_t *obj, cyhal_comp_config_t *cfg)
153 {
154 #if (_CYHAL_DRIVER_AVAILABLE_COMP_CTB)
155 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
156 if(obj->resource.type == CYHAL_RSC_OPAMP)
157 #endif
158 {
159 return _cyhal_comp_ctb_configure(obj, cfg);
160 }
161 #endif
162 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
163 CY_ASSERT(obj->resource.type == CYHAL_RSC_LPCOMP);
164 return _cyhal_comp_lp_configure(obj, cfg);
165 #endif
166 }
167
cyhal_comp_read(cyhal_comp_t * obj)168 bool cyhal_comp_read(cyhal_comp_t *obj)
169 {
170 #if (_CYHAL_DRIVER_AVAILABLE_COMP_CTB)
171 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
172 if(obj->resource.type == CYHAL_RSC_OPAMP)
173 #endif
174 {
175 return _cyhal_comp_ctb_read(obj);
176 }
177 #endif
178 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
179 CY_ASSERT(obj->resource.type == CYHAL_RSC_LPCOMP);
180 return _cyhal_comp_lp_read(obj);
181 #endif
182 }
183
cyhal_comp_register_callback(cyhal_comp_t * obj,cyhal_comp_event_callback_t callback,void * callback_arg)184 void cyhal_comp_register_callback(cyhal_comp_t *obj, cyhal_comp_event_callback_t callback, void *callback_arg)
185 {
186 CY_UNUSED_PARAMETER(obj);
187 CY_ASSERT(NULL != obj);
188
189 uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
190 obj->callback_data.callback = (cy_israddress) callback;
191 obj->callback_data.callback_arg = callback_arg;
192 cyhal_system_critical_section_exit(savedIntrStatus);
193 }
194
cyhal_comp_enable_event(cyhal_comp_t * obj,cyhal_comp_event_t event,uint8_t intr_priority,bool enable)195 void cyhal_comp_enable_event(cyhal_comp_t *obj, cyhal_comp_event_t event, uint8_t intr_priority, bool enable)
196 {
197 #if (_CYHAL_DRIVER_AVAILABLE_COMP_CTB)
198 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
199 if(obj->resource.type == CYHAL_RSC_OPAMP)
200 #endif
201 {
202 _cyhal_comp_ctb_enable_event(obj, event, intr_priority, enable);
203 return;
204 }
205 #endif
206 #if (_CYHAL_DRIVER_AVAILABLE_COMP_LP)
207 CY_ASSERT(obj->resource.type == CYHAL_RSC_LPCOMP);
208 _cyhal_comp_lp_enable_event(obj, event, intr_priority, enable);
209 #endif
210 }
211
212 #if defined(__cplusplus)
213 }
214 #endif
215
216 #endif /* CYHAL_DRIVER_AVAILABLE_COMP */
217