1 /*
2 * Copyright (c) 2015 - 2025, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <nrfx.h>
35
36 #if NRFX_CHECK(NRFX_LPCOMP_ENABLED)
37
38 #include <nrfx_lpcomp.h>
39 #include "prs/nrfx_prs.h"
40
41 #define NRFX_LOG_MODULE LPCOMP
42 #include <nrfx_log.h>
43
44 #define EVT_TO_STR(event) \
45 (event == NRF_LPCOMP_EVENT_READY ? "NRF_LPCOMP_EVENT_READY" : \
46 (event == NRF_LPCOMP_EVENT_DOWN ? "NRF_LPCOMP_EVENT_DOWN" : \
47 (event == NRF_LPCOMP_EVENT_UP ? "NRF_LPCOMP_EVENT_UP" : \
48 (event == NRF_LPCOMP_EVENT_CROSS ? "NRF_LPCOMP_EVENT_CROSS" : \
49 "UNKNOWN EVENT"))))
50
51 static nrfx_lpcomp_event_handler_t m_lpcomp_event_handler = NULL;
52 static nrfx_drv_state_t m_state = NRFX_DRV_STATE_UNINITIALIZED;
53
lpcomp_configure(nrfx_lpcomp_config_t const * p_config)54 static void lpcomp_configure(nrfx_lpcomp_config_t const * p_config)
55 {
56 nrfy_lpcomp_config_t nrfy_config =
57 {
58 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
59 .reference = p_config->reference,
60 .ext_ref = p_config->ext_ref,
61 .detection = p_config->detection,
62 NRFX_COND_CODE_1(LPCOMP_FEATURE_HYST_PRESENT, (.hyst = p_config->config.hyst), ())
63 #else
64 .config =
65 {
66 .reference = p_config->config.reference,
67 .detection = p_config->config.detection,
68 NRFX_COND_CODE_1(LPCOMP_FEATURE_HYST_PRESENT, (.hyst = p_config->config.hyst), ())
69 },
70 #endif
71 .input = p_config->input
72 };
73
74 nrfy_lpcomp_periph_configure(NRF_LPCOMP, &nrfy_config);
75
76 uint32_t int_mask = 0;
77
78 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
79 switch (p_config->detection)
80 #else
81 switch (p_config->config.detection)
82 #endif
83 {
84 case NRF_LPCOMP_DETECT_UP:
85 int_mask = NRF_LPCOMP_INT_UP_MASK;
86 break;
87
88 case NRF_LPCOMP_DETECT_DOWN:
89 int_mask = NRF_LPCOMP_INT_DOWN_MASK;
90 break;
91
92 case NRF_LPCOMP_DETECT_CROSS:
93 int_mask = NRF_LPCOMP_INT_CROSS_MASK;
94 break;
95
96 default:
97 break;
98 }
99 nrfy_lpcomp_int_init(NRF_LPCOMP, int_mask, p_config->interrupt_priority, true);
100 }
101
lpcomp_execute_handler(nrf_lpcomp_event_t event,uint32_t event_mask)102 static void lpcomp_execute_handler(nrf_lpcomp_event_t event, uint32_t event_mask)
103 {
104 if (event_mask & nrfy_lpcomp_int_enable_check(NRF_LPCOMP, NRFY_EVENT_TO_INT_BITMASK(event)))
105 {
106 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(event));
107
108 m_lpcomp_event_handler(event);
109 }
110 }
111
nrfx_lpcomp_irq_handler(void)112 void nrfx_lpcomp_irq_handler(void)
113 {
114 uint32_t evt_mask = nrfy_lpcomp_events_process(NRF_LPCOMP,
115 NRF_LPCOMP_INT_READY_MASK |
116 NRF_LPCOMP_INT_DOWN_MASK |
117 NRF_LPCOMP_INT_UP_MASK |
118 NRF_LPCOMP_INT_CROSS_MASK);
119
120 lpcomp_execute_handler(NRF_LPCOMP_EVENT_READY, evt_mask);
121 lpcomp_execute_handler(NRF_LPCOMP_EVENT_DOWN, evt_mask);
122 lpcomp_execute_handler(NRF_LPCOMP_EVENT_UP, evt_mask);
123 lpcomp_execute_handler(NRF_LPCOMP_EVENT_CROSS, evt_mask);
124 }
125
nrfx_lpcomp_init(nrfx_lpcomp_config_t const * p_config,nrfx_lpcomp_event_handler_t event_handler)126 nrfx_err_t nrfx_lpcomp_init(nrfx_lpcomp_config_t const * p_config,
127 nrfx_lpcomp_event_handler_t event_handler)
128 {
129 NRFX_ASSERT(p_config);
130 NRFX_ASSERT(event_handler);
131 nrfx_err_t err_code;
132
133 if (m_state != NRFX_DRV_STATE_UNINITIALIZED)
134 { // LPCOMP driver is already initialized
135 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
136 err_code = NRFX_ERROR_ALREADY;
137 #else
138 err_code = NRFX_ERROR_INVALID_STATE;
139 #endif
140 NRFX_LOG_WARNING("Function: %s, error code: %s.",
141 __func__,
142 NRFX_LOG_ERROR_STRING_GET(err_code));
143 return err_code;
144 }
145
146 m_lpcomp_event_handler = event_handler;
147
148 #if NRFX_CHECK(NRFX_PRS_ENABLED)
149 if (nrfx_prs_acquire(NRF_LPCOMP, nrfx_lpcomp_irq_handler) != NRFX_SUCCESS)
150 {
151 err_code = NRFX_ERROR_BUSY;
152 NRFX_LOG_WARNING("Function: %s, error code: %s.",
153 __func__,
154 NRFX_LOG_ERROR_STRING_GET(err_code));
155 return err_code;
156 }
157 #endif
158 nrfy_lpcomp_task_trigger(NRF_LPCOMP, NRF_LPCOMP_TASK_STOP);
159 nrfy_lpcomp_disable(NRF_LPCOMP);
160
161 nrfy_lpcomp_shorts_disable(NRF_LPCOMP,
162 NRF_LPCOMP_SHORT_CROSS_STOP_MASK |
163 NRF_LPCOMP_SHORT_UP_STOP_MASK |
164 NRF_LPCOMP_SHORT_DOWN_STOP_MASK |
165 NRF_LPCOMP_SHORT_READY_STOP_MASK |
166 NRF_LPCOMP_SHORT_READY_SAMPLE_MASK);
167 nrfy_lpcomp_int_disable(NRF_LPCOMP,
168 NRF_LPCOMP_INT_READY_MASK |
169 NRF_LPCOMP_INT_DOWN_MASK |
170 NRF_LPCOMP_INT_UP_MASK |
171 NRF_LPCOMP_INT_CROSS_MASK);
172
173 lpcomp_configure(p_config);
174
175 nrfy_lpcomp_enable(NRF_LPCOMP);
176
177 nrfy_lpcomp_shorts_enable(NRF_LPCOMP, NRF_LPCOMP_SHORT_READY_SAMPLE_MASK);
178
179 m_state = NRFX_DRV_STATE_INITIALIZED;
180
181 err_code = NRFX_SUCCESS;
182 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
183 return err_code;
184 }
185
nrfx_lpcomp_reconfigure(nrfx_lpcomp_config_t const * p_config)186 nrfx_err_t nrfx_lpcomp_reconfigure(nrfx_lpcomp_config_t const * p_config)
187 {
188 NRFX_ASSERT(p_config);
189 nrfx_err_t err_code;
190
191 if (m_state == NRFX_DRV_STATE_POWERED_ON)
192 {
193 err_code = NRFX_ERROR_BUSY;
194 NRFX_LOG_WARNING("Function: %s, error code: %s.",
195 __func__,
196 NRFX_LOG_ERROR_STRING_GET(err_code));
197 return err_code;
198 }
199 else if (m_state == NRFX_DRV_STATE_INITIALIZED)
200 {
201 nrfy_lpcomp_disable(NRF_LPCOMP);
202 lpcomp_configure(p_config);
203 nrfy_lpcomp_enable(NRF_LPCOMP);
204 return NRFX_SUCCESS;
205 }
206 else
207 {
208 NRFX_ASSERT(m_state == NRFX_DRV_STATE_UNINITIALIZED);
209
210 err_code = NRFX_ERROR_INVALID_STATE;
211 NRFX_LOG_WARNING("Function: %s, error code: %s.",
212 __func__,
213 NRFX_LOG_ERROR_STRING_GET(err_code));
214 return err_code;
215 }
216 }
217
nrfx_lpcomp_uninit(void)218 void nrfx_lpcomp_uninit(void)
219 {
220 NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
221 nrfy_lpcomp_int_uninit(NRF_LPCOMP);
222 nrfx_lpcomp_disable();
223 #if NRFX_CHECK(NRFX_PRS_ENABLED)
224 nrfx_prs_release(NRF_LPCOMP);
225 #endif
226 m_state = NRFX_DRV_STATE_UNINITIALIZED;
227 m_lpcomp_event_handler = NULL;
228 NRFX_LOG_INFO("Uninitialized.");
229 }
230
nrfx_lpcomp_init_check(void)231 bool nrfx_lpcomp_init_check(void)
232 {
233 return (m_state != NRFX_DRV_STATE_UNINITIALIZED);
234 }
235
nrfx_lpcomp_start(uint32_t lpcomp_evt_en_mask,uint32_t lpcomp_shorts_mask)236 void nrfx_lpcomp_start(uint32_t lpcomp_evt_en_mask, uint32_t lpcomp_shorts_mask)
237 {
238 NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
239 nrfy_lpcomp_enable(NRF_LPCOMP);
240 (void)nrfy_lpcomp_events_process(NRF_LPCOMP, lpcomp_evt_en_mask);
241 nrfy_lpcomp_int_enable(NRF_LPCOMP, lpcomp_evt_en_mask);
242 nrfy_lpcomp_shorts_enable(NRF_LPCOMP, lpcomp_shorts_mask);
243 m_state = NRFX_DRV_STATE_POWERED_ON;
244 nrfy_lpcomp_task_trigger(NRF_LPCOMP, NRF_LPCOMP_TASK_START);
245 NRFX_LOG_INFO("Enabled.");
246 }
247
nrfx_lpcomp_stop(void)248 void nrfx_lpcomp_stop(void)
249 {
250 NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
251 nrfy_lpcomp_disable(NRF_LPCOMP);
252 nrfy_lpcomp_task_trigger(NRF_LPCOMP, NRF_LPCOMP_TASK_STOP);
253 nrfy_lpcomp_int_disable(NRF_LPCOMP,
254 NRF_LPCOMP_INT_READY_MASK |
255 NRF_LPCOMP_INT_DOWN_MASK |
256 NRF_LPCOMP_INT_UP_MASK |
257 NRF_LPCOMP_INT_CROSS_MASK);
258 m_state = NRFX_DRV_STATE_INITIALIZED;
259 NRFX_LOG_INFO("Disabled.");
260 }
261
nrfx_lpcomp_sample(void)262 uint32_t nrfx_lpcomp_sample(void)
263 {
264 NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
265
266 return nrfy_lpcomp_sample(NRF_LPCOMP);
267 }
268
269 #endif // NRFX_CHECK(NRFX_LPCOMP_ENABLED)
270