drv_qei.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-4-20 FYChou First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_QEI)
  14. #include <rtdevice.h>
  15. #include "NuMicro.h"
  16. /* Private define ---------------------------------------------------------------*/
  17. /* Private typedef --------------------------------------------------------------*/
  18. struct nu_qei
  19. {
  20. struct rt_pulse_encoder_device dev;
  21. char *name;
  22. QEI_T *qei_base;
  23. rt_uint32_t max_cntval;
  24. rt_uint32_t cmp_val;
  25. IRQn_Type IRQn;
  26. rt_uint8_t qei_type;
  27. rt_uint8_t qei_flag;
  28. };
  29. typedef struct nu_qei *nu_qei_t;
  30. /* Private functions ------------------------------------------------------------*/
  31. static rt_uint32_t nu_qei_type(struct rt_pulse_encoder_device *pulse_encoder);
  32. static rt_err_t nu_qei_init(struct rt_pulse_encoder_device *pulse_encoder);
  33. static rt_int32_t nu_qei_get_count(struct rt_pulse_encoder_device *pulse_encoder);
  34. static rt_err_t nu_qei_clear_count(struct rt_pulse_encoder_device *pulse_encoder);
  35. static rt_err_t nu_qei_control(struct rt_pulse_encoder_device *pulse_encoder, rt_uint32_t cmd, void *args);
  36. /* Public functions -------------------------------------------------------------*/
  37. rt_int32_t nu_qei_get_maxval(rt_device_t *pulse_encoder);
  38. rt_int32_t nu_qei_get_cmpval(rt_device_t *pulse_encoder);
  39. rt_int32_t nu_qei_get_type(rt_device_t *pulse_encoder);
  40. void nu_qei_set_maxval_type(rt_device_t *pulse_encoder, rt_uint32_t u32val, rt_uint8_t u8type);
  41. void nu_qei_set_cmpval(rt_device_t *pulse_encoder, rt_uint32_t u32val);
  42. /* Private variables ------------------------------------------------------------*/
  43. static struct nu_qei nu_qei_arr [] =
  44. {
  45. #if defined(BSP_USING_QEI0)
  46. {
  47. .name = "qei0",
  48. .qei_base = QEI0,
  49. .max_cntval = 1000,
  50. .cmp_val = 100,
  51. .IRQn = QEI0_IRQn,
  52. .qei_type = AB_PHASE_PULSE_ENCODER,
  53. .qei_flag = 0
  54. },
  55. #endif
  56. #if defined(BSP_USING_QEI1)
  57. {
  58. .name = "qei1",
  59. .qei_base = QEI1,
  60. .max_cntval = 1000,
  61. .cmp_val = 100,
  62. .IRQn = QEI1_IRQn,
  63. .qei_type = AB_PHASE_PULSE_ENCODER,
  64. .qei_flag = 0
  65. },
  66. #endif
  67. {0}
  68. };
  69. static const struct rt_pulse_encoder_ops nu_qei_ops =
  70. {
  71. .init = nu_qei_init,
  72. .get_count = nu_qei_get_count,
  73. .clear_count = nu_qei_clear_count,
  74. .control = nu_qei_control,
  75. };
  76. typedef struct rt_pulse_encoder_ops *nu_qei_ops_t;
  77. /* Public variables -------------------------------------------------------------*/
  78. static rt_uint32_t nu_qei_type(struct rt_pulse_encoder_device *pulse_encoder)
  79. {
  80. rt_uint32_t u32type;
  81. switch (pulse_encoder->type)
  82. {
  83. case SINGLE_PHASE_PULSE_ENCODER:
  84. u32type = (((nu_qei_t)pulse_encoder)->cmp_val) ? QEI_CTL_X2_COMPARE_COUNTING_MODE : QEI_CTL_X2_FREE_COUNTING_MODE;
  85. break;
  86. case UNKNOWN_PULSE_ENCODER_TYPE:
  87. case AB_PHASE_PULSE_ENCODER:
  88. default:
  89. u32type = (((nu_qei_t)pulse_encoder)->cmp_val) ? QEI_CTL_X4_COMPARE_COUNTING_MODE : QEI_CTL_X4_FREE_COUNTING_MODE;
  90. break;
  91. }
  92. return u32type;
  93. }
  94. static rt_err_t nu_qei_init(struct rt_pulse_encoder_device *pulse_encoder)
  95. {
  96. rt_uint32_t u32type;
  97. QEI_T *qui_base;
  98. RT_ASSERT(pulse_encoder != RT_NULL);
  99. qui_base = ((nu_qei_t)pulse_encoder)->qei_base;
  100. /* enable noise filter */
  101. QEI_ENABLE_NOISE_FILTER(qui_base, QEI_CTL_NFCLKSEL_DIV2);
  102. /* set qei mode */
  103. u32type = nu_qei_type(pulse_encoder);
  104. /* set compare value and interrupt */
  105. if (((nu_qei_t)pulse_encoder)->cmp_val)
  106. {
  107. QEI_SET_CNT_CMP(qui_base, ((nu_qei_t)pulse_encoder)->cmp_val);
  108. QEI_EnableInt(qui_base, QEI_CTL_CMPIEN_Msk);
  109. QEI_ENABLE_CNT_CMP(qui_base);
  110. NVIC_EnableIRQ(((nu_qei_t)pulse_encoder)->IRQn);
  111. }
  112. QEI_Open(qui_base, u32type, ((nu_qei_t)pulse_encoder)->max_cntval);
  113. return RT_EOK;
  114. }
  115. static rt_int32_t nu_qei_get_count(struct rt_pulse_encoder_device *pulse_encoder)
  116. {
  117. QEI_T *qui_base;
  118. RT_ASSERT(pulse_encoder != RT_NULL);
  119. qui_base = ((nu_qei_t)pulse_encoder)->qei_base;
  120. return (rt_int32_t)QEI_GET_CNT_VALUE(qui_base);
  121. }
  122. static rt_err_t nu_qei_clear_count(struct rt_pulse_encoder_device *pulse_encoder)
  123. {
  124. QEI_T *qui_base;
  125. RT_ASSERT(pulse_encoder != RT_NULL);
  126. qui_base = ((nu_qei_t)pulse_encoder)->qei_base;
  127. QEI_Stop(qui_base);
  128. QEI_SET_CNT_VALUE(qui_base, 0);
  129. QEI_Start(qui_base);
  130. return RT_EOK;
  131. }
  132. static rt_err_t nu_qei_control(struct rt_pulse_encoder_device *pulse_encoder, rt_uint32_t cmd, void *args)
  133. {
  134. rt_err_t result;
  135. QEI_T *qui_base;
  136. RT_ASSERT(pulse_encoder != RT_NULL);
  137. qui_base = ((nu_qei_t)pulse_encoder)->qei_base;
  138. RT_ASSERT(cmd != RT_NULL);
  139. result = RT_EOK;
  140. switch (cmd)
  141. {
  142. case PULSE_ENCODER_CMD_ENABLE:
  143. QEI_Start(qui_base);
  144. if (((nu_qei_t)pulse_encoder)->cmp_val)
  145. {
  146. QEI_EnableInt(qui_base, QEI_CTL_CMPIEN_Msk);
  147. QEI_ENABLE_CNT_CMP(qui_base);
  148. NVIC_EnableIRQ(((nu_qei_t)pulse_encoder)->IRQn);
  149. }
  150. break;
  151. case PULSE_ENCODER_CMD_DISABLE:
  152. if (((nu_qei_t)pulse_encoder)->cmp_val)
  153. {
  154. QEI_DisableInt(qui_base, QEI_CTL_CMPIEN_Msk);
  155. QEI_DISABLE_CNT_CMP(qui_base);
  156. NVIC_DisableIRQ(((nu_qei_t)pulse_encoder)->IRQn);
  157. }
  158. QEI_Stop(qui_base);
  159. break;
  160. default:
  161. result = -RT_ENOSYS;
  162. break;
  163. }
  164. return result;
  165. }
  166. #if defined(BSP_USING_QEI0)
  167. /* QEI0 interrupt entry */
  168. void QEI0_IRQHandler(void)
  169. {
  170. /* enter interrupt */
  171. rt_interrupt_enter();
  172. if (QEI_GET_INT_FLAG(nu_qei_arr[0].qei_base, QEI_STATUS_CMPF_Msk))
  173. {
  174. nu_qei_arr[0].qei_flag = 1;
  175. QEI_CLR_INT_FLAG(nu_qei_arr[0].qei_base, QEI_STATUS_CMPF_Msk);
  176. rt_kprintf("QEI0 CMP flag rising\n") ;
  177. }
  178. /* leave interrupt */
  179. rt_interrupt_leave();
  180. }
  181. #endif
  182. #if defined(BSP_USING_QEI1)
  183. /* QEI1 interrupt entry */
  184. void QEI1_IRQHandler(void)
  185. {
  186. /* enter interrupt */
  187. rt_interrupt_enter();
  188. if (QEI_GET_INT_FLAG(nu_qei_arr[1].qei_base, QEI_STATUS_CMPF_Msk))
  189. {
  190. nu_qei_arr[1].qei_flag = 1;
  191. QEI_CLR_INT_FLAG(nu_qei_arr[1].qei_base, QEI_STATUS_CMPF_Msk);
  192. rt_kprintf("QEI1 CMP flag rising\n") ;
  193. }
  194. /* leave interrupt */
  195. rt_interrupt_leave();
  196. }
  197. #endif
  198. rt_int32_t nu_qei_get_maxval(rt_device_t *pulse_encoder)
  199. {
  200. return ((nu_qei_t) * pulse_encoder)->max_cntval;
  201. }
  202. rt_int32_t nu_qei_get_cmpval(rt_device_t *pulse_encoder)
  203. {
  204. return ((nu_qei_t) * pulse_encoder)->cmp_val;
  205. }
  206. rt_int32_t nu_qei_get_type(rt_device_t *pulse_encoder)
  207. {
  208. return ((nu_qei_t) * pulse_encoder)->qei_type;
  209. }
  210. void nu_qei_set_maxval_type(rt_device_t *pulse_encoder, rt_uint32_t u32val, rt_uint8_t u8type)
  211. {
  212. QEI_T *qui_base;
  213. RT_ASSERT(pulse_encoder != RT_NULL);
  214. qui_base = ((nu_qei_t) * pulse_encoder)->qei_base;
  215. RT_ASSERT(u8type <= AB_PHASE_PULSE_ENCODER);
  216. ((nu_qei_t)*pulse_encoder)->qei_type = u8type;
  217. ((nu_qei_t)*pulse_encoder)->dev.type = (enum rt_pulse_encoder_type)u8type;
  218. ((nu_qei_t)*pulse_encoder)->max_cntval = u32val;
  219. QEI_Open(qui_base, nu_qei_type(&(((nu_qei_t)*pulse_encoder)->dev)), u32val);
  220. }
  221. void nu_qei_set_cmpval(rt_device_t *pulse_encoder, rt_uint32_t u32val)
  222. {
  223. QEI_T *qui_base;
  224. RT_ASSERT(pulse_encoder != RT_NULL);
  225. qui_base = ((nu_qei_t) * pulse_encoder)->qei_base;
  226. ((nu_qei_t)*pulse_encoder)->cmp_val = u32val;
  227. QEI_SET_CNT_CMP(qui_base, ((nu_qei_t)*pulse_encoder)->cmp_val);
  228. if (((nu_qei_t)*pulse_encoder)->cmp_val)
  229. {
  230. QEI_EnableInt(qui_base, QEI_CTL_CMPIEN_Msk);
  231. QEI_ENABLE_CNT_CMP(qui_base);
  232. NVIC_EnableIRQ(((nu_qei_t)*pulse_encoder)->IRQn);
  233. }
  234. else
  235. {
  236. QEI_DisableInt(qui_base, QEI_CTL_CMPIEN_Msk);
  237. QEI_DISABLE_CNT_CMP(qui_base);
  238. NVIC_DisableIRQ(((nu_qei_t)*pulse_encoder)->IRQn);
  239. }
  240. }
  241. int rt_hw_qei_init(void)
  242. {
  243. int result = RT_ERROR;
  244. int nu_sel = 0;
  245. while (nu_qei_arr[nu_sel].name != 0)
  246. {
  247. nu_qei_arr[nu_sel].dev.type = (enum rt_pulse_encoder_type)nu_qei_arr[nu_sel].qei_type;
  248. nu_qei_arr[nu_sel].dev.ops = &nu_qei_ops;
  249. result = rt_device_pulse_encoder_register((void *)&nu_qei_arr[nu_sel], nu_qei_arr[nu_sel].name, &(nu_qei_arr[nu_sel].qei_flag));
  250. RT_ASSERT(result == RT_EOK);
  251. nu_sel++;
  252. }
  253. return result;
  254. }
  255. INIT_APP_EXPORT(rt_hw_qei_init);
  256. #endif /* BSP_USING_QEI */