1 /*
2  * Copyright (c) 2015 - 2023, 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        = NRF_QDEC##id,                            \
105     .drv_inst_idx = NRFX_CONCAT_3(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_INVALID_STATE The QDEC was already initialized.
180  */
181 nrfx_err_t nrfx_qdec_init(nrfx_qdec_t const *        p_instance,
182                           nrfx_qdec_config_t const * p_config,
183                           nrfx_qdec_event_handler_t  handler,
184                           void *                     p_context);
185 
186 /**
187  * @brief Function for reconfiguring QDEC.
188  *
189  * @param[in] p_instance Pointer to the driver instance structure.
190  * @param[in] p_config   Pointer to the structure with the configuration.
191  *
192  * @retval NRFX_SUCCESS             Reconfiguration was successful.
193  * @retval NRFX_ERROR_BUSY          The driver is enabled and cannot be reconfigured.
194  * @retval NRFX_ERROR_INVALID_STATE The driver is uninitialized.
195  */
196 nrfx_err_t nrfx_qdec_reconfigure(nrfx_qdec_t const *        p_instance,
197                                  nrfx_qdec_config_t const * p_config);
198 
199 /**
200  * @brief Function for uninitializing QDEC.
201  *
202  * @note Function asserts if module is uninitialized.
203  *
204  * @param[in]  p_instance Pointer to the driver instance structure.
205  */
206 void nrfx_qdec_uninit(nrfx_qdec_t const * p_instance);
207 
208 /**
209  * @brief Function for enabling QDEC.
210  *
211  * @note Function asserts if module is uninitialized or enabled.
212  *
213  * @param[in] p_instance Pointer to the driver instance structure.
214  */
215 void nrfx_qdec_enable(nrfx_qdec_t const * p_instance);
216 
217 /**
218  * @brief Function for disabling QDEC.
219  *
220  * @note Function asserts if module is uninitialized or disabled.
221  *
222  * @param[in] p_instance Pointer to the driver instance structure.
223  */
224 void nrfx_qdec_disable(nrfx_qdec_t const * p_instance);
225 
226 /**
227  * @brief Function for reading accumulated transitions from the QDEC peripheral.
228  *
229  * @note Function asserts if module is not enabled.
230  * @note Accumulators are cleared after reading.
231  *
232  * @param[in]  p_instance Pointer to the driver instance structure.
233  * @param[out] p_acc      Pointer to store the accumulated transitions.
234  * @param[out] p_accdbl   Pointer to store the accumulated double transitions.
235  */
236 void nrfx_qdec_accumulators_read(nrfx_qdec_t const * p_instance,
237                                  int32_t *           p_acc,
238                                  uint32_t *          p_accdbl);
239 
240 /**
241  * @brief Function for returning the address of the specified QDEC task.
242  *
243  * @param[in] p_instance Pointer to the driver instance structure.
244  * @param[in] task       QDEC task.
245  *
246  * @return Task address.
247  */
248 NRFX_STATIC_INLINE uint32_t nrfx_qdec_task_address_get(nrfx_qdec_t const * p_instance,
249                                                        nrf_qdec_task_t     task);
250 
251 /**
252  * @brief Function for returning the address of the specified QDEC event.
253  *
254  * @param[in] p_instance Pointer to the driver instance structure.
255  * @param[in] event      QDEC event.
256  *
257  * @return Event address.
258  */
259 NRFX_STATIC_INLINE uint32_t nrfx_qdec_event_address_get(nrfx_qdec_t const * p_instance,
260                                                         nrf_qdec_event_t    event);
261 
262 #ifndef NRFX_DECLARE_ONLY
nrfx_qdec_task_address_get(nrfx_qdec_t const * p_instance,nrf_qdec_task_t task)263 NRFX_STATIC_INLINE uint32_t nrfx_qdec_task_address_get(nrfx_qdec_t const * p_instance,
264                                                        nrf_qdec_task_t     task)
265 {
266     return nrfy_qdec_task_address_get(p_instance->p_reg, task);
267 }
268 
nrfx_qdec_event_address_get(nrfx_qdec_t const * p_instance,nrf_qdec_event_t event)269 NRFX_STATIC_INLINE uint32_t nrfx_qdec_event_address_get(nrfx_qdec_t const * p_instance,
270                                                         nrf_qdec_event_t    event)
271 {
272     return nrfy_qdec_event_address_get(p_instance->p_reg, event);
273 }
274 #endif // NRFX_DECLARE_ONLY
275 
276 /** @} */
277 
278 /*
279  * Declare interrupt handlers for all enabled driver instances in the following format:
280  * nrfx_\<periph_name\>_\<idx\>_irq_handler (for example, nrfx_qdec_0_irq_handler).
281  *
282  * A specific interrupt handler for the driver instance can be retrieved by using
283  * the NRFX_QDEC_INST_HANDLER_GET macro.
284  *
285  * Here is a sample of using the NRFX_QDEC_INST_HANDLER_GET macro to directly map
286  * an interrupt handler in a Zephyr application:
287  *
288  * IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_QDEC_INST_GET(\<instance_index\>)), \<priority\>,
289  *                    NRFX_QDEC_INST_HANDLER_GET(\<instance_index\>), 0);
290  */
291 NRFX_INSTANCE_IRQ_HANDLERS_DECLARE(QDEC, qdec)
292 
293 #ifdef __cplusplus
294 }
295 #endif
296 
297 #endif // NRFX_QDEC_H__
298