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