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