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