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_COMP_ENABLED)
37 
38 #include <nrfx_comp.h>
39 #include "prs/nrfx_prs.h"
40 
41 #define NRFX_LOG_MODULE COMP
42 #include <nrfx_log.h>
43 
44 #define EVT_TO_STR(event)                                     \
45     (event == NRF_COMP_EVENT_READY ? "NRF_COMP_EVENT_READY" : \
46     (event == NRF_COMP_EVENT_DOWN  ? "NRF_COMP_EVENT_DOWN"  : \
47     (event == NRF_COMP_EVENT_UP    ? "NRF_COMP_EVENT_UP"    : \
48     (event == NRF_COMP_EVENT_CROSS ? "NRF_COMP_EVENT_CROSS" : \
49                                      "UNKNOWN ERROR"))))
50 
51 
52 static nrfx_comp_event_handler_t    m_comp_event_handler = NULL;
53 static nrfx_drv_state_t             m_state = NRFX_DRV_STATE_UNINITIALIZED;
54 
comp_configure(nrfx_comp_config_t const * p_config)55 static void comp_configure(nrfx_comp_config_t const * p_config)
56 {
57     nrfy_comp_config_t nrfy_config =
58     {
59         .reference  = p_config->reference,
60         .ext_ref    = p_config->ext_ref,
61         .main_mode  = p_config->main_mode,
62         .threshold  = p_config->threshold,
63         .speed_mode = p_config->speed_mode,
64         .hyst       = p_config->hyst,
65         NRFX_COND_CODE_1(NRF_COMP_HAS_ISOURCE, (.isource = p_config->isource,), ())
66         .input      = p_config->input
67     };
68 
69     nrfy_comp_periph_configure(NRF_COMP, &nrfy_config);
70     nrfy_comp_int_init(NRF_COMP,
71                        NRF_COMP_INT_READY_MASK |
72                        NRF_COMP_INT_DOWN_MASK |
73                        NRF_COMP_INT_UP_MASK |
74                        NRF_COMP_INT_CROSS_MASK,
75                        p_config->interrupt_priority,
76                        false);
77 }
78 
comp_execute_handler(nrf_comp_event_t event,uint32_t event_mask)79 static void comp_execute_handler(nrf_comp_event_t event, uint32_t event_mask)
80 {
81     if (event_mask & nrfy_comp_int_enable_check(NRF_COMP, NRFY_EVENT_TO_INT_BITMASK(event)))
82     {
83         NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(event));
84 
85         m_comp_event_handler(event);
86     }
87 }
88 
nrfx_comp_irq_handler(void)89 void nrfx_comp_irq_handler(void)
90 {
91     uint32_t evt_mask = nrfy_comp_events_process(NRF_COMP,
92                                                  NRF_COMP_INT_READY_MASK |
93                                                  NRF_COMP_INT_DOWN_MASK |
94                                                  NRF_COMP_INT_UP_MASK |
95                                                  NRF_COMP_INT_CROSS_MASK);
96     comp_execute_handler(NRF_COMP_EVENT_READY, evt_mask);
97     comp_execute_handler(NRF_COMP_EVENT_DOWN,  evt_mask);
98     comp_execute_handler(NRF_COMP_EVENT_UP,    evt_mask);
99     comp_execute_handler(NRF_COMP_EVENT_CROSS, evt_mask);
100 }
101 
102 
nrfx_comp_init(nrfx_comp_config_t const * p_config,nrfx_comp_event_handler_t event_handler)103 nrfx_err_t nrfx_comp_init(nrfx_comp_config_t const * p_config,
104                           nrfx_comp_event_handler_t  event_handler)
105 {
106     NRFX_ASSERT(p_config);
107     NRFX_ASSERT(event_handler);
108     nrfx_err_t err_code;
109 
110     if (m_state != NRFX_DRV_STATE_UNINITIALIZED)
111     { // COMP driver is already initialized
112 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
113         err_code = NRFX_ERROR_ALREADY;
114 #else
115         err_code = NRFX_ERROR_INVALID_STATE;
116 #endif
117         NRFX_LOG_WARNING("Function: %s, error code: %s.",
118                          __func__,
119                          NRFX_LOG_ERROR_STRING_GET(err_code));
120         return err_code;
121     }
122 
123     m_comp_event_handler = event_handler;
124 
125 #if NRFX_CHECK(NRFX_PRS_ENABLED)
126     if (nrfx_prs_acquire(NRF_COMP, nrfx_comp_irq_handler) != NRFX_SUCCESS)
127     {
128         err_code = NRFX_ERROR_BUSY;
129         NRFX_LOG_WARNING("Function: %s, error code: %s.",
130                          __func__,
131                          NRFX_LOG_ERROR_STRING_GET(err_code));
132         return err_code;
133     }
134 #endif
135     nrfy_comp_shorts_disable(NRF_COMP,
136                              NRFX_COMP_SHORT_STOP_AFTER_CROSS_EVT |
137                              NRFX_COMP_SHORT_STOP_AFTER_UP_EVT |
138                              NRFX_COMP_SHORT_STOP_AFTER_DOWN_EVT);
139     nrfy_comp_int_disable(NRF_COMP,
140                           NRF_COMP_INT_READY_MASK |
141                           NRF_COMP_INT_DOWN_MASK |
142                           NRF_COMP_INT_UP_MASK |
143                           NRF_COMP_INT_CROSS_MASK);
144 
145     if (p_config)
146     {
147         comp_configure(p_config);
148     }
149 
150     nrfy_comp_enable(NRF_COMP);
151     nrfy_comp_task_trigger(NRF_COMP, NRF_COMP_TASK_STOP);
152 
153     m_state = NRFX_DRV_STATE_INITIALIZED;
154 
155     err_code = NRFX_SUCCESS;
156     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
157     return err_code;
158 }
159 
nrfx_comp_reconfigure(nrfx_comp_config_t const * p_config)160 nrfx_err_t nrfx_comp_reconfigure(nrfx_comp_config_t const * p_config)
161 {
162     NRFX_ASSERT(p_config);
163     nrfx_err_t err_code;
164 
165     if (m_state == NRFX_DRV_STATE_UNINITIALIZED)
166     {
167         err_code = NRFX_ERROR_INVALID_STATE;
168         NRFX_LOG_WARNING("Function: %s, error code: %s.",
169                          __func__,
170                          NRFX_LOG_ERROR_STRING_GET(err_code));
171         return err_code;
172 
173     }
174     else if (m_state == NRFX_DRV_STATE_POWERED_ON)
175     {
176         err_code = NRFX_ERROR_BUSY;
177         NRFX_LOG_WARNING("Function: %s, error code: %s.",
178                          __func__,
179                          NRFX_LOG_ERROR_STRING_GET(err_code));
180         return err_code;
181     }
182     nrfy_comp_disable(NRF_COMP);
183     comp_configure(p_config);
184     nrfy_comp_enable(NRF_COMP);
185     return NRFX_SUCCESS;
186 }
187 
nrfx_comp_uninit(void)188 void nrfx_comp_uninit(void)
189 {
190     NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
191 
192     nrfy_comp_shorts_disable(NRF_COMP, UINT32_MAX);
193     nrfy_comp_int_disable(NRF_COMP, UINT32_MAX);
194     nrfy_comp_task_trigger(NRF_COMP, NRF_COMP_TASK_STOP);
195     nrfy_comp_int_uninit(NRF_COMP);
196     nrfy_comp_disable(NRF_COMP);
197 #if NRFX_CHECK(NRFX_PRS_ENABLED)
198     nrfx_prs_release(NRF_COMP);
199 #endif
200     m_state = NRFX_DRV_STATE_UNINITIALIZED;
201     m_comp_event_handler = NULL;
202     NRFX_LOG_INFO("Uninitialized.");
203 }
204 
nrfx_comp_init_check(void)205 bool nrfx_comp_init_check(void)
206 {
207     return (m_state != NRFX_DRV_STATE_UNINITIALIZED);
208 }
209 
nrfx_comp_pin_select(nrf_comp_input_t psel)210 void nrfx_comp_pin_select(nrf_comp_input_t psel)
211 {
212     NRFX_ASSERT(m_state != NRFX_DRV_STATE_UNINITIALIZED);
213 
214     bool comp_enable_state = nrfy_comp_enable_check(NRF_COMP);
215     nrfy_comp_task_trigger(NRF_COMP, NRF_COMP_TASK_STOP);
216     if (m_state == NRFX_DRV_STATE_POWERED_ON)
217     {
218         m_state = NRFX_DRV_STATE_INITIALIZED;
219     }
220     nrfy_comp_disable(NRF_COMP);
221     nrfy_comp_input_select(NRF_COMP, psel);
222     if (comp_enable_state == true)
223     {
224         nrfy_comp_enable(NRF_COMP);
225     }
226 }
227 
nrfx_comp_start(uint32_t comp_int_mask,uint32_t comp_shorts_mask)228 void nrfx_comp_start(uint32_t comp_int_mask, uint32_t comp_shorts_mask)
229 {
230     NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
231 
232     (void)nrfy_comp_events_process(NRF_COMP, comp_int_mask);
233     nrfy_comp_int_enable(NRF_COMP, comp_int_mask);
234     nrfy_comp_shorts_enable(NRF_COMP, comp_shorts_mask);
235     m_state = NRFX_DRV_STATE_POWERED_ON;
236     nrfy_comp_task_trigger(NRF_COMP, NRF_COMP_TASK_START);
237     NRFX_LOG_INFO("Enabled.");
238 }
239 
nrfx_comp_stop(void)240 void nrfx_comp_stop(void)
241 {
242     NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
243 
244     nrfy_comp_shorts_disable(NRF_COMP, UINT32_MAX);
245     nrfy_comp_int_disable(NRF_COMP, UINT32_MAX);
246     nrfy_comp_task_trigger(NRF_COMP, NRF_COMP_TASK_STOP);
247     m_state = NRFX_DRV_STATE_INITIALIZED;
248     NRFX_LOG_INFO("Disabled.");
249 }
250 
nrfx_comp_sample()251 uint32_t nrfx_comp_sample()
252 {
253     NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
254 
255     return nrfy_comp_sample(NRF_COMP);
256 }
257 
258 #endif // NRFX_CHECK(NRFX_COMP_ENABLED)
259