• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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