1 /***************************************************************************//**
2 * \file cyhal_quaddec.h
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Quadrature Decoder.
6 * This interface abstracts out the chip specific details. If any chip specific
7 * functionality is necessary, or performance is critical the low level functions
8 * can be used directly.
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2020-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 
30 /**
31 * \addtogroup group_hal_quaddec Quadrature Decoder
32 * \ingroup group_hal
33 * \{
34 * High level interface for interacting with the Quadrature Decoder hardware resource.
35 *
36 * The quadrature decoder block is commonly used to measure the time of occurrence of an event,
37 * to measure the time difference between two events or perform an action after a specified
38 * period of time.
39 *
40 * The Quadrature Decoder block provides the ability to count transitions on a pair of digital
41 * signals. The signals are typically provided by a speed/position feedback system mounted on
42 * a motor or trackball. The driver allows the user to invoke a callback function when a
43 * particular event occurs.
44 * The signals, typically called A and B, are positioned 90° out-of-phase, which results in a Gray
45 * code output (a sequence where only one bit changes on each count). It also allows detection of
46 * direction and relative position. A third optional signal, named index, is used as a reference
47 * to establish an absolute position once per rotation.
48 *
49 * The Quadrature Decoder operates in one of three resolution modes.  (see \ref
50 * cyhal_quaddec_resolution_t)  The mode dictates the number of events that are counted.
51 *
52 * \image html quadrature_mode.png
53 *
54 * An index event causes the counter to be set to the midpoint.  For example, if the hardware
55 * has 16-bit resolution, the midpoint would be 0x8000.  For 32-bit resolution: 0x80000000.
56 *
57 * \image html quadrature_index.png
58 *
59 * For more details about this functionality, see the "Quadrature Decoder Mode" section of the
60 * Technical Reference Manual.
61 *
62 * Some use case scenarios of the Quadrature Decoder:
63 *
64 * * Decode the output of a quadrature encoder (e.g., mouse, trackball, robotic axles, etc.).
65 * * Precision measurement of speed, acceleration, and position of a motor's rotor and with rotary
66 * knobs to determine user input.
67 *
68 * \section subsection_quaddec_features Features
69 * * Configurable resolution - \ref cyhal_quaddec_resolution_t
70 * * Interrupt on various events - \ref cyhal_quaddec_event_t
71 *
72 * \section subsection_quaddec_quickstart Quick Start
73 *
74 * \ref cyhal_quaddec_init can be used for quadrature decoder initialization by providing the quaddec
75 * object - \ref cyhal_quaddec_t, input pins, and shared clock source - <b> clk </b> (optional).
76 *
77 *
78 * See \ref subsection_quaddec_snippet_1.
79 *
80 * \section subsection_quaddec_sample_snippets Code Snippets
81 *
82 * \subsection subsection_quaddec_snippet_1 Snippet 1: Initialization and direction detection
83 * The following snippet initializes a quadrature decoder and measures the counter to determine direction.
84 * The <b>clk</b> may be left NULL, in which case a clock resource is automatically assigned.
85 * \snippet hal_quaddec.c snippet_cyhal_quaddec_direction
86 *
87 * \subsection subsection_quaddec_snippet_2 Snippet 2: Handling an event in a callback function
88 * The following snippet initializes a quadrature decoder and triggers an event as changes happen.
89 * The <b>clk</b> need not be provided (NULL), in which case a clock resource is assigned.
90 * \snippet hal_quaddec.c snippet_cyhal_quaddec_event_interrupt
91 *
92 */
93 
94 #pragma once
95 
96 #include <stdint.h>
97 #include <stdbool.h>
98 
99 #include "cy_result.h"
100 #include "cyhal_hw_types.h"
101 
102 #if defined(__cplusplus)
103 extern "C" {
104 #endif
105 
106 /** \addtogroup group_hal_results_quaddec Quadrature Decoder HAL Results
107  *  Quadrature Decoder specific return codes
108  *  \ingroup group_hal_results
109  *  \{ *//**
110  */
111 
112 /** Bad argument. eg: null pointer */
113 #define CYHAL_QUADDEC_RSLT_ERR_BAD_ARGUMENT               \
114     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_QUADDEC, 0))
115 /** Failed to initialize the quadrature decoder clock */
116 #define CYHAL_QUADDEC_RSLT_ERR_CLOCK_INIT                 \
117     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_QUADDEC, 1))
118 /** The function is not supported with a particular device */
119 #define CYHAL_QUADDEC_RSLT_ERR_NOT_SUPPORTED              \
120     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_QUADDEC, 2))
121 
122 /**
123  * \}
124  */
125 
126 /*******************************************************************************
127 *       Enumerations
128 *******************************************************************************/
129 
130 /** Operating resolutions for the quadrature decoder */
131 typedef enum
132 {
133     CYHAL_QUADDEC_RESOLUTION_1X, //!< 1x resolution
134     CYHAL_QUADDEC_RESOLUTION_2X, //!< 2x resolution
135     CYHAL_QUADDEC_RESOLUTION_4X  //!< 4x resolution
136 } cyhal_quaddec_resolution_t;
137 
138 /** Quadrature decoder input signal */
139 typedef enum
140 {
141     CYHAL_QUADDEC_INPUT_PHI_A, //!< The "A" input of the quadrature decoder.
142     CYHAL_QUADDEC_INPUT_PHI_B, //!< The "B" input of the quadrature decoder.
143     CYHAL_QUADDEC_INPUT_STOP,  //!< Stops the counter from counting when activated.
144     CYHAL_QUADDEC_INPUT_INDEX  //!< A reference signal that resets the counter when activated.
145 } cyhal_quaddec_input_t;
146 
147 /** Quadrature decoder output signal */
148 typedef enum
149 {
150     CYHAL_QUADDEC_OUTPUT_COMPARE_MATCH  //!< Compare Match signal
151 } cyhal_quaddec_output_t;
152 
153 /** Interrupt triggers for the quadrature decoder */
154 typedef enum
155 {
156     CYHAL_QUADDEC_IRQ_NONE            = 0,            //!< No interrupt handled
157     CYHAL_QUADDEC_IRQ_TERMINAL_COUNT  = (1 << 0),     //!< Interrupt when terminal count is reached
158     CYHAL_QUADDEC_IRQ_CAPTURE         = (1 << 1),     //!< Interrupt when capture value is reached
159     CYHAL_QUADDEC_IRQ_ALL             = (1 << 2) - 1  //!< Interrupt on any event
160 } cyhal_quaddec_event_t;
161 
162 /*******************************************************************************
163 *       Typedefs
164 *******************************************************************************/
165 
166 /** Handler for quadrature decoder events */
167 typedef void(*cyhal_quaddec_event_callback_t)(void *callback_arg, cyhal_quaddec_event_t event);
168 
169 /*******************************************************************************
170 *       Functions
171 *******************************************************************************/
172 
173 /** Initialize the quadrature decoder peripheral and configure the pin. <br>
174  * See \ref subsection_quaddec_snippet_1.
175  *
176  * @param[out] obj  Pointer to a quadrature decoder object. The caller must allocate the memory
177  *  for this object but the init function will initialize its contents.
178  * @param[in]  phi_a - The "A" input of the quadrature decoder.
179  * @param[in]  phi_b - The "B" input of the quadrature decoder.
180  * @param[in]  index - Optional, resets the counter when active to act as a reference position
181  *                     for the quadrature decoder.
182  * @param[in]  resolution - The resolution that the quadrature decoder runs at
183  * @param[in]  clk - Optional, the shared clock to use, if not provided a new clock will be
184  *                   allocated and the quadrature decoder frequency will be set to the value passed
185  *                   in with the frequency parameter.
186  * @param[in]  frequency - This is the frequency, in hertz, to use with the clock allocated by this
187  *                         function.  This parameter is only used if the clk parameter is set to NULL.
188  *                         When the clk parameter is not NULL, this must be set to zero.  When the clk
189  *                         paramether is NULL, this must be set to something other than zero.
190  * @return The status of the init request
191  */
192 cy_rslt_t cyhal_quaddec_init(cyhal_quaddec_t *obj, cyhal_gpio_t phi_a, cyhal_gpio_t phi_b,
193                              cyhal_gpio_t index, cyhal_quaddec_resolution_t resolution,
194                              const cyhal_clock_t *clk, uint32_t frequency);
195 
196 /** Initialize the quadrature decoder peripheral using a configurator generated configuration struct
197   *
198  * @param[out] obj              Pointer to a quadrature decoder object. The caller must allocate the memory
199  *                              for this object but the init function will initialize its contents.
200  * @param[in] cfg               Configuration structure generated by a configurator.
201  * @return The status of the init request
202  */
203  cy_rslt_t cyhal_quaddec_init_cfg(cyhal_quaddec_t *obj, const cyhal_quaddec_configurator_t *cfg);
204 
205 /** Deinitialize the quadrature decoder object
206  *
207  * @param[in,out] obj The quadrature decoder object
208  */
209 void cyhal_quaddec_free(cyhal_quaddec_t *obj);
210 
211 /** Starts the quadrature decoder.  This function also acts as a reset, in that it will trigger
212  * reload/index the QuadDec.  When this function is called, the count value gets stored in the
213  * capture register and the count value is returned to the mid point. For example, if the hardware
214  * has 16-bit resolution, the midpoint would be 0x8000.  For 32-bit resolution: 0x80000000.
215  * See \ref subsection_quaddec_snippet_1.
216  *
217  * @param[in] obj     The quadrature decoder object
218  * @return The status of the start request
219  */
220 cy_rslt_t cyhal_quaddec_start(cyhal_quaddec_t *obj);
221 
222 /** Stops the quadrature decoder. Does not reset counter value. <br>
223  *
224  * @param[in] obj     The quadrature decoder object
225  * @return The status of the stop request
226  */
227 cy_rslt_t cyhal_quaddec_stop(cyhal_quaddec_t *obj);
228 
229 /** Gets the change in the quadrature decoder counter, either positive or negative, since the last
230  * time that this function was called.
231  *
232  * \note This function is not intended for applications requiring high speed or high accuracy such
233  * as getting motor positions.  It is intended for applications involving devices like radial dials.
234  *
235  * @param[in] obj     The quadrature decoder object
236  * @return The amount that the counter has changed
237  */
238 int32_t cyhal_quaddec_get_delta(cyhal_quaddec_t *obj);
239 
240 /** Reads the current value from the quadrature decoder <br>
241  * The read operation works even if the counter is stopped.
242  * See \ref subsection_quaddec_snippet_1.
243  *
244  * @param[in] obj     The quadrature decoder object
245  * @return The current value of the quadrature decoder counter register
246  */
247 uint32_t cyhal_quaddec_read_counter(const cyhal_quaddec_t *obj);
248 
249 /** Reads the value from the quadrature decoder's capture register <br>
250  * This function does not clear the counter value.  The capture register
251  * is updated whenever there is an index event.
252  *
253  * @param[in] obj     The quadrature decoder object
254  * @return The current value of the quadrature decoder capture register
255  */
256 uint32_t cyhal_quaddec_read_capture(const cyhal_quaddec_t *obj);
257 
258 /** Register a quadrature decoder callback handler<br>
259  * This function does not clear the counter value.
260  *
261  * This function will be called when one of the events enabled by \ref cyhal_quaddec_enable_event
262  * occurs.
263  *
264  * See \ref subsection_quaddec_snippet_2.
265  *
266  * @param[in] obj          The quadrature decoder object
267  * @param[in] callback     The callback handler which will be invoked when the event occurs
268  * @param[in] callback_arg Generic argument that will be provided to the callback when called
269  */
270 void cyhal_quaddec_register_callback(cyhal_quaddec_t *obj, cyhal_quaddec_event_callback_t callback,
271                                      void *callback_arg);
272 
273 /** Configure quadrature decoder event enable <br>
274  *
275  * When an enabled event occurs, the function specified by \ref cyhal_quaddec_register_callback
276  * will be called.
277  *
278  * See \ref subsection_quaddec_snippet_2.
279  *
280  * @param[in] obj           The quadrature decoder object
281  * @param[in] event         The quadrature decoder event type
282  * @param[in] intr_priority  The priority for NVIC interrupt events
283  * @param[in] enable        True to turn on interrupts, False to turn off
284  */
285 void cyhal_quaddec_enable_event(cyhal_quaddec_t *obj, cyhal_quaddec_event_t event,
286                                 uint8_t intr_priority, bool enable);
287 
288 /** Connects a source signal and configures and enables a quadrature decoder
289  * event to be triggered from that signal. These quadrature decoder events can
290  * be configured independently and connect to the same or different source
291  * signals.
292  * @note For "edge" signals, this function will default to rising edge. To control the edge type,
293  * use @ref cyhal_quaddec_connect_digital2
294  *
295  * @param[in] obj      Quadrature decoder obj
296  * @param[in] source   Source signal obtained from another driver's cyhal_<PERIPH>_enable_output
297  * @param[in] signal   The quadrature decoder input signal
298  * @return The status of the connection
299  * */
300 cy_rslt_t cyhal_quaddec_connect_digital(cyhal_quaddec_t *obj, cyhal_source_t source, cyhal_quaddec_input_t signal);
301 
302 /** Connects a source signal and configures and enables a quadrature decoder
303  * event to be triggered from that signal with a configurable edge type.
304  * These quadrature decoder events can be configured independently and connect
305  * to the same or different source signals.
306  *
307  * @param[in] obj       Quadrature decoder obj
308  * @param[in] source    Source signal obtained from another driver's cyhal_<PERIPH>_enable_output
309  * @param[in] signal    The quadrature decoder input signal
310  * @param[in] edge_type The edge type that should trigger the event. This must be consistent with the
311  *                      edge type of `source`. If `source` produces a "level" signal, the only valid
312  *                      value is @ref CYHAL_EDGE_TYPE_LEVEL. If `source` produces an "edge" signal, then
313  *                      @ref CYHAL_EDGE_TYPE_LEVEL is not a valid value.
314  * @return The status of the connection
315  * */
316 cy_rslt_t cyhal_quaddec_connect_digital2(cyhal_quaddec_t *obj, cyhal_source_t source, cyhal_quaddec_input_t signal, cyhal_edge_type_t edge_type);
317 
318 /** Disconnects a source signal and disables the quadrature decoder event.
319  *
320  * @param[in] obj      Quadrature decoder obj
321  * @param[in] source   Source signal from cyhal_<PERIPH>_enable_output to disable
322  * @param[in] signal   The quadrature decoder input signal
323  * @return The status of the disconnection
324  * */
325 cy_rslt_t cyhal_quaddec_disconnect_digital(cyhal_quaddec_t *obj, cyhal_source_t source, cyhal_quaddec_input_t signal);
326 
327 /** Enables the specified output signal from a quadrature decoder that will be
328  * triggered when the corresponding event occurs. Multiple output signals can
329  * be configured simultaneously.
330  *
331  * @param[in]  obj      Quadrature decoder obj
332  * @param[in]  signal   The quadrature decoder output signal
333  * @param[out] source   Pointer to user-allocated source signal object which
334  * will be initialized by enable_output. \p source should be passed to
335  * (dis)connect_digital functions to (dis)connect the associated endpoints.
336  * @return The status of the output enable
337  * */
338 cy_rslt_t cyhal_quaddec_enable_output(cyhal_quaddec_t *obj, cyhal_quaddec_output_t signal, cyhal_source_t *source);
339 
340 /** Disables the specified output signal from a quadrature decoder.
341  *
342  * @param[in]  obj      Quadrature decoder obj
343  * @param[in]  signal   The quadrature decoder output signal
344  * @return The status of the output disable
345  * */
346 cy_rslt_t cyhal_quaddec_disable_output(cyhal_quaddec_t *obj, cyhal_quaddec_output_t signal);
347 
348 #if defined(__cplusplus)
349 }
350 #endif
351 
352 #ifdef CYHAL_QUADDEC_IMPL_HEADER
353 #include CYHAL_QUADDEC_IMPL_HEADER
354 #endif /* CYHAL_QUADDEC_IMPL_HEADER */
355 
356 /** \} group_hal_quaddec */
357