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 #ifndef NRFX_QDEC_H__
35 #define NRFX_QDEC_H__
36 
37 #include <nrfx.h>
38 #include <haly/nrfy_qdec.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /* On devices with single instance (with no id) use instance 0. */
45 #if defined(NRF_QDEC) && defined(NRFX_QDEC_ENABLED) && !defined(NRFX_QDEC0_ENABLED)
46 #define NRFX_QDEC0_ENABLED 1
47 #endif
48 
49 /**
50  * @defgroup nrfx_qdec QDEC driver
51  * @{
52  * @ingroup nrf_qdec
53  * @brief   Quadrature Decoder (QDEC) peripheral driver.
54  */
55 
56 /** @brief Data structure of the Quadrature Decoder (QDEC) driver instance. */
57 typedef struct
58 {
59     NRF_QDEC_Type * p_reg;        ///< Pointer to a structure with QDEC registers.
60     uint8_t         drv_inst_idx; ///< Index of the driver instance. For internal use only.
61 } nrfx_qdec_t;
62 
63 /** @brief QDEC driver instance configuration structure. */
64 typedef struct
65 {
66     nrf_qdec_reportper_t reportper;          ///< Report period in samples.
67     nrf_qdec_sampleper_t sampleper;          ///< Sampling period in microseconds.
68     uint32_t             psela;              ///< Pin number for A input.
69     uint32_t             pselb;              ///< Pin number for B input.
70     uint32_t             pselled;            ///< Pin number for LED output.
71     uint32_t             ledpre;             ///< Time (in microseconds) how long LED is switched on before sampling.
72     nrf_qdec_ledpol_t    ledpol;             ///< Active LED polarity.
73     bool                 dbfen;              ///< State of debouncing filter.
74     bool                 sample_inten;       ///< Enabling sample ready interrupt.
75     bool                 reportper_inten;    ///< Enabling report ready interrupt.
76     uint8_t              interrupt_priority; ///< QDEC interrupt priority.
77     bool                 skip_gpio_cfg;      ///< Skip GPIO configuration of pins.
78                                              /**< When set to true, the driver does not modify
79                                               *   any GPIO parameters of the used pins. Those
80                                               *   parameters are supposed to be configured
81                                               *   externally before the driver is initialized. */
82     bool                 skip_psel_cfg;      ///< Skip pin selection configuration.
83                                              /**< When set to true, the driver does not modify
84                                               *   pin select registers in the peripheral.
85                                               *   Those registers are supposed to be set up
86                                               *   externally before the driver is initialized.
87                                               *   @note When both GPIO configuration and pin
88                                               *   selection are to be skipped, the structure
89                                               *   fields that specify pins can be omitted,
90                                               *   as they are ignored anyway. */
91 } nrfx_qdec_config_t;
92 
93 #ifndef __NRFX_DOXYGEN__
94 enum {
95     /* List all enabled driver instances (in the format NRFX_\<instance_name\>_INST_IDX). */
96     NRFX_INSTANCE_ENUM_LIST(QDEC)
97     NRFX_QDEC_ENABLED_COUNT
98 };
99 #endif
100 
101 /** @brief Macro for creating an instance of the QDEC driver. */
102 #define NRFX_QDEC_INSTANCE(id)                               \
103 {                                                            \
104     .p_reg        = NRFX_CONCAT(NRF_, QDEC, id),             \
105     .drv_inst_idx = NRFX_CONCAT(NRFX_QDEC, id, _INST_IDX),   \
106 }
107 
108 /**
109  * @brief QDEC driver default configuration.
110  *
111  * This configuration sets up QDEC with the following options:
112  * - report period: 10 samples
113  * - sampling period: 16384 us
114  * - LED enabled for 500 us before sampling
115  * - LED polarity: active high
116  * - debouncing filter disabled
117  * - sample ready interrupt disabled
118  *
119  * @param[in] _pin_a   Pin for A encoder channel input.
120  * @param[in] _pin_b   Pin for B encoder channel input.
121  * @param[in] _pin_led Pin for LED output.
122  */
123 #define NRFX_QDEC_DEFAULT_CONFIG(_pin_a, _pin_b, _pin_led)       \
124 {                                                                \
125     .reportper          = NRF_QDEC_REPORTPER_10,                 \
126     .sampleper          = NRF_QDEC_SAMPLEPER_16384US,            \
127     .psela              = _pin_a,                                \
128     .pselb              = _pin_b,                                \
129     .pselled            = _pin_led,                              \
130     .ledpre             = 500,                                   \
131     .ledpol             = NRF_QDEC_LEPOL_ACTIVE_HIGH,            \
132     .dbfen              = NRF_QDEC_DBFEN_DISABLE,                \
133     .sample_inten       = false,                                 \
134     .reportper_inten    = true,                                  \
135     .interrupt_priority = NRFX_QDEC_DEFAULT_CONFIG_IRQ_PRIORITY, \
136 }
137 
138 /** @brief QDEC sample event data. */
139 typedef struct
140 {
141     int8_t value; /**< Sample value. */
142 } nrfx_qdec_sample_data_evt_t;
143 
144 /** @brief QDEC report event data. */
145 typedef struct
146 {
147     int32_t  acc;    /**< Accumulated transitions. */
148     uint32_t accdbl; /**< Accumulated double transitions. */
149 } nrfx_qdec_report_data_evt_t;
150 
151 /** @brief QDEC event handler structure. */
152 typedef struct
153 {
154     nrf_qdec_event_t  type; /**< Event type. */
155     union
156     {
157         nrfx_qdec_sample_data_evt_t sample; /**< Sample event data. */
158         nrfx_qdec_report_data_evt_t report; /**< Report event data. */
159     } data;                                 /**< Union to store event data. */
160 } nrfx_qdec_event_t;
161 
162 /**
163  * @brief QDEC event handler.
164  *
165  * @param[in] event     QDEC event structure.
166  * @param[in] p_context Context passed to event handler.
167  */
168 typedef void (*nrfx_qdec_event_handler_t)(nrfx_qdec_event_t event, void * p_context);
169 
170 /**
171  * @brief Function for initializing QDEC.
172  *
173  * @param[in] p_instance Pointer to the driver instance structure.
174  * @param[in] p_config   Pointer to the structure with the initial configuration.
175  * @param[in] handler    Event handler provided by the user. Must not be NULL.
176  * @param[in] p_context  Context passed to event handler.
177  *
178  * @retval NRFX_SUCCESS             Initialization was successful.
179  * @retval NRFX_ERROR_ALREADY       The driver is already initialized.
180  * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
181  *                                  Deprecated - use @ref NRFX_ERROR_ALREADY instead.
182  */
183 nrfx_err_t nrfx_qdec_init(nrfx_qdec_t const *        p_instance,
184                           nrfx_qdec_config_t const * p_config,
185                           nrfx_qdec_event_handler_t  handler,
186                           void *                     p_context);
187 
188 /**
189  * @brief Function for reconfiguring QDEC.
190  *
191  * @param[in] p_instance Pointer to the driver instance structure.
192  * @param[in] p_config   Pointer to the structure with the configuration.
193  *
194  * @retval NRFX_SUCCESS             Reconfiguration was successful.
195  * @retval NRFX_ERROR_BUSY          The driver is enabled and cannot be reconfigured.
196  * @retval NRFX_ERROR_INVALID_STATE The driver is uninitialized.
197  */
198 nrfx_err_t nrfx_qdec_reconfigure(nrfx_qdec_t const *        p_instance,
199                                  nrfx_qdec_config_t const * p_config);
200 
201 /**
202  * @brief Function for uninitializing QDEC.
203  *
204  * @note Function asserts if module is uninitialized.
205  *
206  * @param[in]  p_instance Pointer to the driver instance structure.
207  */
208 void nrfx_qdec_uninit(nrfx_qdec_t const * p_instance);
209 
210 /**
211  * @brief Function for checking if the QDEC driver instance is initialized.
212  *
213  * @param[in] p_instance Pointer to the driver instance structure.
214  *
215  * @retval true  Instance is already initialized.
216  * @retval false Instance is not initialized.
217  */
218 bool nrfx_qdec_init_check(nrfx_qdec_t const * p_instance);
219 
220 /**
221  * @brief Function for enabling QDEC.
222  *
223  * @note Function asserts if module is uninitialized or enabled.
224  *
225  * @param[in] p_instance Pointer to the driver instance structure.
226  */
227 void nrfx_qdec_enable(nrfx_qdec_t const * p_instance);
228 
229 /**
230  * @brief Function for disabling QDEC.
231  *
232  * @note Function asserts if module is uninitialized or disabled.
233  *
234  * @param[in] p_instance Pointer to the driver instance structure.
235  */
236 void nrfx_qdec_disable(nrfx_qdec_t const * p_instance);
237 
238 /**
239  * @brief Function for reading accumulated transitions from the QDEC peripheral.
240  *
241  * @note Function asserts if module is not enabled.
242  * @note Accumulators are cleared after reading.
243  *
244  * @param[in]  p_instance Pointer to the driver instance structure.
245  * @param[out] p_acc      Pointer to store the accumulated transitions.
246  * @param[out] p_accdbl   Pointer to store the accumulated double transitions.
247  */
248 void nrfx_qdec_accumulators_read(nrfx_qdec_t const * p_instance,
249                                  int32_t *           p_acc,
250                                  uint32_t *          p_accdbl);
251 
252 /**
253  * @brief Function for returning the address of the specified QDEC task.
254  *
255  * @param[in] p_instance Pointer to the driver instance structure.
256  * @param[in] task       QDEC task.
257  *
258  * @return Task address.
259  */
260 NRFX_STATIC_INLINE uint32_t nrfx_qdec_task_address_get(nrfx_qdec_t const * p_instance,
261                                                        nrf_qdec_task_t     task);
262 
263 /**
264  * @brief Function for returning the address of the specified QDEC event.
265  *
266  * @param[in] p_instance Pointer to the driver instance structure.
267  * @param[in] event      QDEC event.
268  *
269  * @return Event address.
270  */
271 NRFX_STATIC_INLINE uint32_t nrfx_qdec_event_address_get(nrfx_qdec_t const * p_instance,
272                                                         nrf_qdec_event_t    event);
273 
274 #ifndef NRFX_DECLARE_ONLY
nrfx_qdec_task_address_get(nrfx_qdec_t const * p_instance,nrf_qdec_task_t task)275 NRFX_STATIC_INLINE uint32_t nrfx_qdec_task_address_get(nrfx_qdec_t const * p_instance,
276                                                        nrf_qdec_task_t     task)
277 {
278     return nrfy_qdec_task_address_get(p_instance->p_reg, task);
279 }
280 
nrfx_qdec_event_address_get(nrfx_qdec_t const * p_instance,nrf_qdec_event_t event)281 NRFX_STATIC_INLINE uint32_t nrfx_qdec_event_address_get(nrfx_qdec_t const * p_instance,
282                                                         nrf_qdec_event_t    event)
283 {
284     return nrfy_qdec_event_address_get(p_instance->p_reg, event);
285 }
286 #endif // NRFX_DECLARE_ONLY
287 
288 /** @} */
289 
290 /*
291  * Declare interrupt handlers for all enabled driver instances in the following format:
292  * nrfx_\<periph_name\>_\<idx\>_irq_handler (for example, nrfx_qdec_0_irq_handler).
293  *
294  * A specific interrupt handler for the driver instance can be retrieved by using
295  * the NRFX_QDEC_INST_HANDLER_GET macro.
296  *
297  * Here is a sample of using the NRFX_QDEC_INST_HANDLER_GET macro to map an interrupt handler
298  * in a Zephyr application:
299  *
300  * IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_QDEC_INST_GET(\<instance_index\>)), \<priority\>,
301  *             NRFX_QDEC_INST_HANDLER_GET(\<instance_index\>), 0, 0);
302  */
303 NRFX_INSTANCE_IRQ_HANDLERS_DECLARE(QDEC, qdec)
304 
305 #ifdef __cplusplus
306 }
307 #endif
308 
309 #endif // NRFX_QDEC_H__
310