drv_eqei.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. * 2021-10-21 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_EQEI)
  14. #include <rtdevice.h>
  15. #include "drv_sys.h"
  16. #include "drv_eqei.h"
  17. /* Private define ---------------------------------------------------------------*/
  18. enum
  19. {
  20. EQEI_START = -1,
  21. #if defined(BSP_USING_EQEI0)
  22. EQEI0_IDX,
  23. #endif
  24. #if defined(BSP_USING_EQEI1)
  25. EQEI1_IDX,
  26. #endif
  27. #if defined(BSP_USING_EQEI2)
  28. EQEI2_IDX,
  29. #endif
  30. #if defined(BSP_USING_EQEI3)
  31. EQEI3_IDX,
  32. #endif
  33. EQEI_CNT
  34. };
  35. /* Private typedef --------------------------------------------------------------*/
  36. struct nu_qei
  37. {
  38. struct rt_pulse_encoder_device dev;
  39. char *name;
  40. EQEI_T *base;
  41. IRQn_Type irqn;
  42. uint32_t rstidx;
  43. uint32_t modid;
  44. rt_uint32_t max_cntval;
  45. rt_uint32_t cmp_val;
  46. rt_uint8_t qei_flag;
  47. };
  48. typedef struct nu_qei *nu_eqei_t;
  49. /* Private functions ------------------------------------------------------------*/
  50. static rt_uint32_t nu_eqei_type(struct rt_pulse_encoder_device *pulse_encoder);
  51. static rt_err_t nu_eqei_init(struct rt_pulse_encoder_device *pulse_encoder);
  52. static rt_int32_t nu_eqei_get_count(struct rt_pulse_encoder_device *pulse_encoder);
  53. static rt_err_t nu_eqei_clear_count(struct rt_pulse_encoder_device *pulse_encoder);
  54. static rt_err_t nu_eqei_control(struct rt_pulse_encoder_device *pulse_encoder, rt_uint32_t cmd, void *args);
  55. static void nu_eqei_isr(nu_eqei_t psNuEqei);
  56. /* Public functions -------------------------------------------------------------*/
  57. /* Private variables ------------------------------------------------------------*/
  58. static struct nu_qei nu_eqei_arr [] =
  59. {
  60. #if defined(BSP_USING_EQEI0)
  61. {
  62. .name = "eqei0",
  63. .base = EQEI0,
  64. .irqn = EQEI0_IRQn,
  65. .rstidx = EQEI0_RST,
  66. .modid = EQEI0_MODULE,
  67. .max_cntval = 1000,
  68. .cmp_val = 100,
  69. },
  70. #endif
  71. #if defined(BSP_USING_EQEI1)
  72. {
  73. .name = "eqei1",
  74. .base = EQEI1,
  75. .irqn = EQEI1_IRQn,
  76. .rstidx = EQEI1_RST,
  77. .modid = EQEI1_MODULE,
  78. .max_cntval = 1000,
  79. .cmp_val = 100,
  80. },
  81. #endif
  82. #if defined(BSP_USING_EQEI2)
  83. {
  84. .name = "eqei2",
  85. .base = EQEI2,
  86. .irqn = EQEI2_IRQn,
  87. .rstidx = EQEI2_RST,
  88. .modid = EQEI2_MODULE,
  89. .max_cntval = 1000,
  90. .cmp_val = 100,
  91. },
  92. #endif
  93. #if defined(BSP_USING_EQEI3)
  94. {
  95. .name = "eqei3",
  96. .base = EQEI3,
  97. .irqn = EQEI3_IRQn,
  98. .rstidx = EQEI3_RST,
  99. .modid = EQEI3_MODULE,
  100. .max_cntval = 1000,
  101. .cmp_val = 100,
  102. },
  103. #endif
  104. };
  105. static const struct rt_pulse_encoder_ops nu_eqei_ops =
  106. {
  107. .init = nu_eqei_init,
  108. .get_count = nu_eqei_get_count,
  109. .clear_count = nu_eqei_clear_count,
  110. .control = nu_eqei_control,
  111. };
  112. #if defined(BSP_USING_EQEI0)
  113. void EQEI0_IRQHandler(void)
  114. {
  115. rt_interrupt_enter();
  116. nu_eqei_isr((void *)&nu_eqei_arr[EQEI0_IDX]);
  117. rt_interrupt_leave();
  118. }
  119. #endif
  120. #if defined(BSP_USING_EQEI1)
  121. void EQEI1_IRQHandler(void)
  122. {
  123. rt_interrupt_enter();
  124. nu_eqei_isr((void *)&nu_eqei_arr[EQEI1_IDX]);
  125. rt_interrupt_leave();
  126. }
  127. #endif
  128. #if defined(BSP_USING_EQEI2)
  129. void EQEI2_IRQHandler(void)
  130. {
  131. rt_interrupt_enter();
  132. nu_eqei_isr((void *)&nu_eqei_arr[EQEI2_IDX]);
  133. rt_interrupt_leave();
  134. }
  135. #endif
  136. #if defined(BSP_USING_EQEI3)
  137. void EQEI3_IRQHandler(void)
  138. {
  139. rt_interrupt_enter();
  140. nu_eqei_isr((void *)&nu_eqei_arr[EQEI3_IDX]);
  141. rt_interrupt_leave();
  142. }
  143. #endif
  144. static rt_uint32_t nu_eqei_type(struct rt_pulse_encoder_device *pulse_encoder)
  145. {
  146. rt_uint32_t u32type;
  147. nu_eqei_t psNuEqei = (nu_eqei_t)pulse_encoder;
  148. RT_ASSERT(pulse_encoder != RT_NULL);
  149. switch (pulse_encoder->type)
  150. {
  151. case SINGLE_PHASE_PULSE_ENCODER:
  152. u32type = (psNuEqei->cmp_val) ? EQEI_CTL_X2_COMPARE_COUNTING_MODE : EQEI_CTL_X2_FREE_COUNTING_MODE;
  153. break;
  154. case UNKNOWN_PULSE_ENCODER_TYPE:
  155. case AB_PHASE_PULSE_ENCODER:
  156. default:
  157. u32type = (psNuEqei->cmp_val) ? EQEI_CTL_X4_COMPARE_COUNTING_MODE : EQEI_CTL_X4_FREE_COUNTING_MODE;
  158. break;
  159. }
  160. rt_kprintf("[%d %d %d]\n", pulse_encoder->type, psNuEqei->cmp_val, u32type);
  161. return u32type;
  162. }
  163. void nu_eqei_set_cmpval(rt_device_t pulse_encoder, rt_uint32_t u32val)
  164. {
  165. nu_eqei_t psNuEqei = (nu_eqei_t)pulse_encoder;
  166. RT_ASSERT(pulse_encoder != RT_NULL);
  167. psNuEqei->cmp_val = u32val;
  168. if (u32val > 0)
  169. {
  170. EQEI_DisableInt(psNuEqei->base, EQEI_CTL_CMPIEN_Msk);
  171. EQEI_SET_CNT_CMP(psNuEqei->base, u32val);
  172. EQEI_ENABLE_CNT_CMP(psNuEqei->base);
  173. EQEI_EnableInt(psNuEqei->base, EQEI_CTL_CMPIEN_Msk);
  174. }
  175. else
  176. {
  177. EQEI_DisableInt(psNuEqei->base, EQEI_CTL_CMPIEN_Msk);
  178. EQEI_DISABLE_CNT_CMP(psNuEqei->base);
  179. EQEI_SET_CNT_CMP(psNuEqei->base, 0);
  180. }
  181. }
  182. static rt_err_t nu_eqei_init(struct rt_pulse_encoder_device *pulse_encoder)
  183. {
  184. nu_eqei_t psNuEqei = (nu_eqei_t)pulse_encoder;
  185. RT_ASSERT(pulse_encoder != RT_NULL);
  186. /* enable noise filter */
  187. EQEI_ENABLE_NOISE_FILTER(psNuEqei->base, EQEI_CTL_NFCLKSEL_DIV2);
  188. /* set compare value and interrupt */
  189. nu_eqei_set_cmpval((rt_device_t)pulse_encoder, psNuEqei->cmp_val);
  190. /* set qei mode */
  191. EQEI_Open(psNuEqei->base, nu_eqei_type(pulse_encoder), psNuEqei->max_cntval);
  192. return RT_EOK;
  193. }
  194. static rt_int32_t nu_eqei_get_count(struct rt_pulse_encoder_device *pulse_encoder)
  195. {
  196. nu_eqei_t psNuEqei = (nu_eqei_t)pulse_encoder;
  197. RT_ASSERT(pulse_encoder != RT_NULL);
  198. return (rt_int32_t)EQEI_GET_CNT_VALUE(psNuEqei->base);
  199. }
  200. static rt_err_t nu_eqei_clear_count(struct rt_pulse_encoder_device *pulse_encoder)
  201. {
  202. nu_eqei_t psNuEqei = (nu_eqei_t)pulse_encoder;
  203. RT_ASSERT(pulse_encoder != RT_NULL);
  204. EQEI_Stop(psNuEqei->base);
  205. EQEI_SET_CNT_VALUE(psNuEqei->base, 0);
  206. EQEI_Start(psNuEqei->base);
  207. return RT_EOK;
  208. }
  209. static rt_err_t nu_eqei_control(struct rt_pulse_encoder_device *pulse_encoder, rt_uint32_t cmd, void *args)
  210. {
  211. rt_err_t result = RT_EOK;
  212. nu_eqei_t psNuEqei = (nu_eqei_t)pulse_encoder;
  213. RT_ASSERT(pulse_encoder != RT_NULL);
  214. switch (cmd)
  215. {
  216. case PULSE_ENCODER_CMD_ENABLE:
  217. /* set compare value and interrupt */
  218. EQEI_Start(psNuEqei->base);
  219. nu_eqei_set_cmpval((rt_device_t)pulse_encoder, psNuEqei->cmp_val);
  220. break;
  221. case PULSE_ENCODER_CMD_DISABLE:
  222. EQEI_Stop(psNuEqei->base);
  223. nu_eqei_set_cmpval((rt_device_t)pulse_encoder, 0);
  224. break;
  225. default:
  226. result = -RT_ENOSYS;
  227. break;
  228. }
  229. return result;
  230. }
  231. static void nu_eqei_isr(nu_eqei_t psNuEqei)
  232. {
  233. if (EQEI_GET_INT_FLAG(psNuEqei->base, EQEI_STATUS_CMPF_Msk))
  234. {
  235. psNuEqei->qei_flag = 1;
  236. EQEI_CLR_INT_FLAG(psNuEqei->base, EQEI_STATUS_CMPF_Msk);
  237. rt_kprintf("%s: CMP flag rising\n", psNuEqei->name) ;
  238. }
  239. }
  240. rt_int32_t nu_eqei_get_maxval(rt_device_t pulse_encoder)
  241. {
  242. nu_eqei_t psNuEqei = (nu_eqei_t)pulse_encoder;
  243. RT_ASSERT(pulse_encoder != RT_NULL);
  244. return psNuEqei->max_cntval;
  245. }
  246. rt_int32_t nu_eqei_get_cmpval(rt_device_t pulse_encoder)
  247. {
  248. nu_eqei_t psNuEqei = (nu_eqei_t)pulse_encoder;
  249. RT_ASSERT(pulse_encoder != RT_NULL);
  250. return psNuEqei->cmp_val;
  251. }
  252. rt_int32_t nu_eqei_get_type(rt_device_t pulse_encoder)
  253. {
  254. RT_ASSERT(pulse_encoder != RT_NULL);
  255. return nu_eqei_type((struct rt_pulse_encoder_device *)pulse_encoder);
  256. }
  257. void nu_eqei_set_maxval_type(rt_device_t pulse_encoder, rt_uint32_t u32val, enum rt_pulse_encoder_type eType)
  258. {
  259. nu_eqei_t psNuEqei = (nu_eqei_t)pulse_encoder;
  260. RT_ASSERT(pulse_encoder != RT_NULL);
  261. RT_ASSERT(eType <= AB_PHASE_PULSE_ENCODER);
  262. psNuEqei->dev.type = eType;
  263. psNuEqei->max_cntval = u32val;
  264. EQEI_Open(psNuEqei->base, nu_eqei_type(&psNuEqei->dev), u32val);
  265. }
  266. int rt_hw_qei_init(void)
  267. {
  268. int i;
  269. rt_err_t result = RT_EOK;
  270. for (i = (EQEI_START + 1); i < EQEI_CNT; i++)
  271. {
  272. nu_eqei_t psNuEqei = &nu_eqei_arr[i];
  273. psNuEqei->dev.type = AB_PHASE_PULSE_ENCODER;
  274. psNuEqei->dev.ops = &nu_eqei_ops;
  275. /* Enable QEI module */
  276. CLK_EnableModuleClock(psNuEqei->modid);
  277. SYS_ResetModule(psNuEqei->rstidx);
  278. result = rt_device_pulse_encoder_register((struct rt_pulse_encoder_device *)&nu_eqei_arr[i].dev, nu_eqei_arr[i].name, (void *)&psNuEqei->qei_flag);
  279. RT_ASSERT(result == RT_EOK);
  280. }
  281. return (int)result;
  282. }
  283. INIT_APP_EXPORT(rt_hw_qei_init);
  284. #endif /* BSP_USING_EQEI */