1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_QEI_DRV_H
9 #define HPM_QEI_DRV_H
10
11 #include "hpm_common.h"
12 #include "hpm_qei_regs.h"
13 /**
14 * @brief QEI driver APIs
15 * @defgroup qei_interface QEI driver APIs
16 * @ingroup io_interfaces
17 * @{
18 *
19 */
20 #define QEI_EVENT_WDOG_FLAG_MASK (1U << 31) /**< watchdog flag */
21 #define QEI_EVENT_HOME_FLAG_MASK (1U << 30) /**< home flag */
22 #define QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK (1U << 29) /**< postion compare match flag */
23 #define QEI_EVENT_Z_PHASE_FLAG_MASK (1U << 28) /**< z input flag */
24
25 /**
26 * @brief counting mode of Z-phase counter
27 *
28 */
29 typedef enum qei_z_count_inc_mode {
30 qei_z_count_inc_on_z_input_assert = 0, /**< zcnt will increment or decrement when Z input assert */
31 qei_z_count_inc_on_phase_count_max = 1, /**< zcnt will increment when phcnt upcount to phmax, decrement when phcnt downcount to 0 */
32 } qei_z_count_inc_mode_t;
33
34 /**
35 * @brief motor rotation direction
36 *
37 */
38 typedef enum qei_rotation_dir_cmp {
39 qei_rotation_dir_cmp_positive = 0, /**< position compare need positive rotation */
40 qei_rotation_dir_cmp_negative = 1, /**< position compare need negative rotation */
41 qei_rotation_dir_cmp_ignore = 2, /**< ignore */
42 } qei_rotation_dir_cmp_t;
43
44 /**
45 * @brief counter type
46 *
47 */
48 typedef enum qei_counter_type {
49 qei_counter_type_z = 0, /**< Z counter */
50 qei_counter_type_phase = 1, /**< Phase counter */
51 qei_counter_type_speed = 2, /**< Speed counter */
52 qei_counter_type_timer = 3, /**< Timer counter */
53 } qei_counter_type_t;
54
55 /**
56 * @brief qei work mode
57 *
58 */
59 typedef enum qei_work_mode {
60 qei_work_mode_abz = 0, /**< Orthogonal decoder mode */
61 qei_work_mode_pd = 1, /**< Directional (PD) mode */
62 qei_work_mode_ud = 2, /**< Up and Down (UD) mode */
63 } qei_work_mode_t;
64
65 #ifdef __cplusplus
66 extern "C" {
67 #endif
68
69 /**
70 * @brief enable qei watchdog
71 *
72 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
73 */
qei_wdog_enable(QEI_Type * qei_x)74 static inline void qei_wdog_enable(QEI_Type *qei_x)
75 {
76 qei_x->WDGCFG |= QEI_WDGCFG_WDGEN_MASK;
77 }
78
79 /**
80 * @brief disable qei watchdog
81 *
82 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
83 */
qei_wdog_disable(QEI_Type * qei_x)84 static inline void qei_wdog_disable(QEI_Type *qei_x)
85 {
86 qei_x->WDGCFG &= ~QEI_WDGCFG_WDGEN_MASK;
87 }
88
89 /**
90 * @brief config watchdog
91 *
92 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
93 * @param[in] timeout watchdog timeout time
94 * @param[in] enable
95 * @arg 1 - enable watchdog, You can use the @ref qei_wdog_disable open watchdog
96 * @arg 0 - disable watchdog, You can use the @ref qei_wdog_enable open watchdog
97 */
qei_wdog_config(QEI_Type * qei_x,uint32_t timeout,bool enable)98 static inline void qei_wdog_config(QEI_Type *qei_x, uint32_t timeout, bool enable)
99 {
100 qei_x->WDGCFG = QEI_WDGCFG_WDGTO_SET(timeout) | QEI_WDGCFG_WDGEN_SET(enable);
101 }
102
103 /**
104 * @brief
105 *
106 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
107 * @param[in] phase_count maximum phcnt number, phcnt will rollover to 0 when it upcount to phmax
108 * @param[in] mode
109 * @arg 1 zcnt will increment when phcnt upcount to phmax, decrement when phcnt downcount to 0
110 * @arg 0 zcnt will increment or decrement when Z input assert
111 * @param[in] z_calibrate 1- phcnt will set to phidx when Z input assert
112 */
qei_phase_config(QEI_Type * qei_x,uint32_t phase_count,qei_z_count_inc_mode_t mode,bool z_calibrate)113 static inline void qei_phase_config(QEI_Type *qei_x, uint32_t phase_count,
114 qei_z_count_inc_mode_t mode, bool z_calibrate)
115 {
116 qei_x->PHCFG = QEI_PHCFG_ZCNTCFG_SET(mode) | QEI_PHCFG_PHCALIZ_SET(z_calibrate)
117 | QEI_PHCFG_PHMAX_SET(phase_count - 1);
118 }
119
120 /**
121 * @brief set phase index
122 *
123 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
124 * @param[in] phase_index phcnt reset value, phcnt will reset to phidx when phcaliz set to 1
125 */
qei_phase_set_index(QEI_Type * qei_x,uint32_t phase_index)126 static inline void qei_phase_set_index(QEI_Type *qei_x, uint32_t phase_index)
127 {
128 qei_x->PHIDX = QEI_PHIDX_PHIDX_SET(phase_index);
129 }
130
131 /**
132 * @brief enable trigger event
133 *
134 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
135 * @param[in] event_mask
136 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
137 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
138 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
139 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
140 */
qei_output_trigger_event_enable(QEI_Type * qei_x,uint32_t event_mask)141 static inline void qei_output_trigger_event_enable(QEI_Type *qei_x, uint32_t event_mask)
142 {
143 qei_x->TRGOEN |= event_mask;
144 }
145
146 /**
147 * @brief disable trigger event
148 *
149 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
150 * @param[in] event_mask
151 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
152 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
153 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
154 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
155 */
qei_output_trigger_event_disable(QEI_Type * qei_x,uint32_t event_mask)156 static inline void qei_output_trigger_event_disable(QEI_Type *qei_x, uint32_t event_mask)
157 {
158 qei_x->TRGOEN &= ~event_mask;
159 }
160
161 /**
162 * @brief enable load read trigger event
163 *
164 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
165 * @param[in] event_mask
166 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
167 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
168 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
169 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
170 */
qei_load_read_trigger_event_enable(QEI_Type * qei_x,uint32_t event_mask)171 static inline void qei_load_read_trigger_event_enable(QEI_Type *qei_x, uint32_t event_mask)
172 {
173 qei_x->READEN |= event_mask;
174 }
175
176 /**
177 * @brief disable load read trigger event
178 *
179 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
180 * @param[in] event_mask
181 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
182 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
183 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
184 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
185 */
qei_load_read_trigger_event_disable(QEI_Type * qei_x,uint32_t event_mask)186 static inline void qei_load_read_trigger_event_disable(QEI_Type *qei_x, uint32_t event_mask)
187 {
188 qei_x->READEN &= ~event_mask;
189 }
190
191 /**
192 * @brief set zcnt postion compare value
193 *
194 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
195 * @param[in] cmp zcnt postion compare value
196 */
qei_z_cmp_set(QEI_Type * qei_x,uint32_t cmp)197 static inline void qei_z_cmp_set(QEI_Type *qei_x, uint32_t cmp)
198 {
199 qei_x->ZCMP = QEI_ZCMP_ZCMP_SET(cmp);
200 }
201
202 /**
203 * @brief set spdcnt position compare value
204 *
205 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
206 * @param[in] cmp spdcnt position compare value
207 */
qei_speed_cmp_set(QEI_Type * qei_x,uint32_t cmp)208 static inline void qei_speed_cmp_set(QEI_Type *qei_x, uint32_t cmp)
209 {
210 qei_x->SPDCMP = QEI_SPDCMP_SPDCMP_SET(cmp);
211 }
212
213 /**
214 * @brief set Phase comparator value
215 *
216 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
217 * @param[in] cmp phcnt position compare value
218 * @param[in] cmp_z 1- postion compare not include zcnt
219 * @param[in] rotation_dir @ref qei_rotation_dir_cmp_t
220 */
qei_phase_cmp_set(QEI_Type * qei_x,uint32_t cmp,bool cmp_z,qei_rotation_dir_cmp_t rotation_dir)221 static inline void qei_phase_cmp_set(QEI_Type *qei_x, uint32_t cmp,
222 bool cmp_z, qei_rotation_dir_cmp_t rotation_dir)
223 {
224 qei_x->PHCMP = QEI_PHCMP_PHCMP_SET(cmp)
225 | QEI_PHCMP_ZCMPDIS_SET(!cmp_z)
226 | ((rotation_dir == qei_rotation_dir_cmp_ignore)
227 ? QEI_PHCMP_DIRCMPDIS_MASK : (QEI_PHCMP_DIRCMP_SET(rotation_dir)));
228 }
229
230 /**
231 * @brief clear qei status register
232 *
233 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
234 * @param[in] mask
235 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
236 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
237 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
238 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
239 */
qei_clear_status(QEI_Type * qei_x,uint32_t mask)240 static inline void qei_clear_status(QEI_Type *qei_x, uint32_t mask)
241 {
242 qei_x->SR = mask;
243 }
244
245 /**
246 * @brief get qei status
247 *
248 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
249 * @retval qei status:
250 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
251 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
252 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
253 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
254 */
qei_get_status(QEI_Type * qei_x)255 static inline uint32_t qei_get_status(QEI_Type *qei_x)
256 {
257 return qei_x->SR;
258 }
259
260 /**
261 * @brief get qei bit status
262 *
263 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
264 * @param[in] mask
265 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
266 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
267 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
268 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
269 * @retval true or false
270 */
qei_get_bit_status(QEI_Type * qei_x,uint32_t mask)271 static inline bool qei_get_bit_status(QEI_Type *qei_x, uint32_t mask)
272 {
273 if ((qei_x->SR & mask) == mask) {
274 return true;
275 } else {
276 return false;
277 }
278 }
279
280 /**
281 * @brief enable qei irq
282 *
283 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
284 * @param[in] mask
285 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
286 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
287 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
288 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
289 */
qei_irq_enable(QEI_Type * qei_x,uint32_t mask)290 static inline void qei_irq_enable(QEI_Type *qei_x, uint32_t mask)
291 {
292 qei_x->IRQEN |= mask;
293 }
294
295 /**
296 * @brief disable qei irq
297 *
298 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
299 * @param[in] mask
300 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
301 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
302 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
303 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
304 */
qei_irq_disable(QEI_Type * qei_x,uint32_t mask)305 static inline void qei_irq_disable(QEI_Type *qei_x, uint32_t mask)
306 {
307 qei_x->IRQEN &= ~mask;
308 }
309
310 /**
311 * @brief enable dma request
312 *
313 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
314 * @param[in] mask
315 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
316 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
317 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
318 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
319 */
qei_dma_request_enable(QEI_Type * qei_x,uint32_t mask)320 static inline void qei_dma_request_enable(QEI_Type *qei_x, uint32_t mask)
321 {
322 qei_x->DMAEN |= mask;
323 }
324
325 /**
326 * @brief disable qei dma
327 *
328 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
329 * @param[in] mask
330 * @arg @ref QEI_EVENT_WDOG_FLAG_MASK
331 * @arg @ref QEI_EVENT_HOME_FLAG_MASK
332 * @arg @ref QEI_EVENT_POSITIVE_COMPARE_FLAG_MASK
333 * @arg @ref QEI_EVENT_Z_PHASE_FLAG_MASK
334 */
qei_dma_request_disable(QEI_Type * qei_x,uint32_t mask)335 static inline void qei_dma_request_disable(QEI_Type *qei_x, uint32_t mask)
336 {
337 qei_x->DMAEN &= ~mask;
338 }
339
340 /**
341 * @brief get current counter value
342 *
343 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
344 * @param[in] type @ref qei_counter_type_t
345 * @retval counter value
346 */
qei_get_current_count(QEI_Type * qei_x,qei_counter_type_t type)347 static inline uint32_t qei_get_current_count(QEI_Type *qei_x,
348 qei_counter_type_t type)
349 {
350 return *(&qei_x->COUNT[QEI_COUNT_CURRENT].Z + type);
351 }
352
353 /**
354 * @brief get read event count value
355 *
356 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
357 * @param[in] type @ref qei_counter_type_t
358 * @retval counter value
359 */
qei_get_count_on_read_event(QEI_Type * qei_x,qei_counter_type_t type)360 static inline uint32_t qei_get_count_on_read_event(QEI_Type *qei_x,
361 qei_counter_type_t type)
362 {
363 return *(&(qei_x->COUNT[QEI_COUNT_READ].Z) + type);
364 }
365
366 /**
367 * @brief read the value of each phase snapshot 0 counter
368 *
369 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
370 * @param[in] type @ref qei_counter_type_t
371 * @retval counter value
372 */
qei_get_count_on_snap0_event(QEI_Type * qei_x,qei_counter_type_t type)373 static inline uint32_t qei_get_count_on_snap0_event(QEI_Type *qei_x,
374 qei_counter_type_t type)
375 {
376 return *(&qei_x->COUNT[QEI_COUNT_SNAP0].Z + type);
377 }
378
379 /**
380 * @brief read the value of each phase snapshot 1 counter
381 *
382 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
383 * @param[in] type @ref qei_counter_type_t
384 * @retval counter value
385 */
qei_get_count_on_snap1_event(QEI_Type * qei_x,qei_counter_type_t type)386 static inline uint32_t qei_get_count_on_snap1_event(QEI_Type *qei_x,
387 qei_counter_type_t type)
388 {
389 return *(&qei_x->COUNT[QEI_COUNT_SNAP1].Z + type);
390 }
391
392 /**
393 * @brief get speed history
394 *
395 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
396 * @param[in] hist_index @ref QEI_SPDHIS_SPDHIS1 ,QEI_SPDHIS_SPDHISx(x=0...n)
397 * @retval speed history value
398 * @arg 0 - hist_index out of range
399 * @arg counter value
400 */
qei_get_speed_history(QEI_Type * qei_x,uint8_t hist_index)401 static inline uint32_t qei_get_speed_history(QEI_Type *qei_x, uint8_t hist_index)
402 {
403 if (hist_index > QEI_SPDHIS_SPDHIS3) {
404 return 0;
405 }
406 return QEI_SPDHIS_SPDHIS0_GET(qei_x->SPDHIS[hist_index]);
407 }
408
409 /**
410 * @brief load phcnt, zcnt, spdcnt and tmrcnt into their read registers
411 *
412 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
413 */
qei_load_counter_to_read_registers(QEI_Type * qei_x)414 static inline void qei_load_counter_to_read_registers(QEI_Type *qei_x)
415 {
416 qei_x->CR |= QEI_CR_READ_MASK;
417 }
418
419 /**
420 * @brief reset spdcnt/phcnt/zcnt
421 *
422 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
423 * @param[in] counter_mask
424 * @arg 1 reset zcnt when H assert
425 * @arg (1<<1) reset phcnt when H assert
426 * @arg (1<<2) reset spdcnt when H assert
427 */
qei_reset_counter_on_h_assert(QEI_Type * qei_x,uint32_t counter_mask)428 static inline void qei_reset_counter_on_h_assert(QEI_Type *qei_x,
429 uint32_t counter_mask)
430 {
431 qei_x->CR |= counter_mask << 16;
432 }
433
434 /**
435 * @brief pause spdcnt when PAUSE assert
436 *
437 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
438 * @param[in] counter_mask
439 * @arg 1 pause spdcnt when PAUSE assert
440 * @arg (1<<1) pause spdcnt when PAUSE assert
441 * @arg (1<<2) pause spdcnt when PAUSE assert
442 */
qei_pause_counter_on_pause(QEI_Type * qei_x,uint32_t counter_mask)443 static inline void qei_pause_counter_on_pause(QEI_Type *qei_x,
444 uint32_t counter_mask)
445 {
446 qei_x->CR |= counter_mask << 12;
447 }
448
449 /**
450 * @brief load phcnt, zcnt, spdcnt and tmrcnt into their snap registers
451 *
452 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
453 */
qei_snap_enable(QEI_Type * qei_x)454 static inline void qei_snap_enable(QEI_Type *qei_x)
455 {
456 qei_x->CR |= QEI_CR_SNAPEN_MASK;
457 }
458
459 /**
460 * @brief disable snap
461 *
462 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
463 */
qei_snap_disable(QEI_Type * qei_x)464 static inline void qei_snap_disable(QEI_Type *qei_x)
465 {
466 qei_x->CR &= ~QEI_CR_SNAPEN_MASK;
467 }
468
469 /**
470 * @brief reset zcnt, spdcnt and tmrcnt to 0
471 *
472 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
473 */
qei_counter_reset_assert(QEI_Type * qei_x)474 static inline void qei_counter_reset_assert(QEI_Type *qei_x)
475 {
476 qei_x->CR |= QEI_CR_RSTCNT_MASK;
477 }
478
479 /**
480 * @brief qei counter reset release
481 *
482 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
483 */
qei_counter_reset_release(QEI_Type * qei_x)484 static inline void qei_counter_reset_release(QEI_Type *qei_x)
485 {
486 qei_x->CR &= ~QEI_CR_RSTCNT_MASK;
487 }
488
489 /**
490 * @brief set work mode
491 *
492 * @param[in] qei_x QEI base address, HPM_QEIx(x=0...n)
493 * @param[in] mode @ref qei_work_mode_t
494 */
qei_set_work_mode(QEI_Type * qei_x,qei_work_mode_t mode)495 static inline void qei_set_work_mode(QEI_Type *qei_x, qei_work_mode_t mode)
496 {
497 qei_x->CR = (qei_x->CR & ~QEI_CR_ENCTYP_MASK) | QEI_CR_ENCTYP_SET(mode);
498 }
499
500 #ifdef __cplusplus
501 }
502 #endif
503 /**
504 * @}
505 */
506 #endif /* HPM_QEI_DRV_H */
507