1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2019-08-23 balanceTWK first version
9 * 2021-01-19 Leslie Lee port to imxrt series
10 */
11
12 #include <rtthread.h>
13 #include <rtdevice.h>
14 #ifdef BSP_USING_PULSE_ENCODER
15
16 #include "fsl_common.h"
17 #include "fsl_enc.h"
18
19 #define LOG_TAG "drv.pulse_encoder"
20 #include <drv_log.h>
21
22 #if !defined(BSP_USING_PULSE_ENCODER1) && !defined(BSP_USING_PULSE_ENCODER2) && !defined(BSP_USING_PULSE_ENCODER3) \
23 && !defined(BSP_USING_PULSE_ENCODER4)
24 #error "Please define at least one BSP_USING_PULSE_ENCODERx"
25 /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
26 #elif (defined(BSP_USING_PULSE_ENCODER2) || defined(BSP_USING_PULSE_ENCODER3) || defined(BSP_USING_PULSE_ENCODER4)) || defined(SOC_IMXRT1015_SERIES)
27 #error "IMXRT1015 had only one quadrature decoder module"
28 #elif (defined(BSP_USING_PULSE_ENCODER3) || defined(BSP_USING_PULSE_ENCODER4)) || defined(SOC_IMXRT1020_SERIES)
29 #error "IMXRT1020 had only two quadrature decoder module"
30 #endif
31
32 enum
33 {
34 #ifdef BSP_USING_PULSE_ENCODER1
35 PULSE_ENCODER1_INDEX,
36 #endif
37 #ifdef BSP_USING_PULSE_ENCODER2
38 PULSE_ENCODER2_INDEX,
39 #endif
40 #ifdef BSP_USING_PULSE_ENCODER3
41 PULSE_ENCODER3_INDEX,
42 #endif
43 #ifdef BSP_USING_PULSE_ENCODER4
44 PULSE_ENCODER4_INDEX,
45 #endif
46 };
47
48 struct imxrt_pulse_encoder_device
49 {
50 struct rt_pulse_encoder_device pulse_encoder;
51 ENC_Type *base;
52 char *name;
53 };
54 typedef struct imxrt_pulse_encoder_device imxrt_pulse_enccoder_device_t;
55
56 static imxrt_pulse_enccoder_device_t imxrt_pulse_encoder_obj[] =
57 {
58 #ifdef BSP_USING_PULSE_ENCODER1
59 {
60 .base = ENC1,
61 .name = "pulse1"
62 },
63 #endif
64 #ifdef BSP_USING_PULSE_ENCODER2
65 {
66 .base = ENC2,
67 .name = "pulse2"
68 },
69 #endif
70 #ifdef BSP_USING_PULSE_ENCODER3
71 {
72 .base = ENC3,
73 .name = "pulse3"
74 },
75 #endif
76 #ifdef BSP_USING_PULSE_ENCODER4
77 {
78 .base = ENC4,
79 .name = "pulse4"
80 },
81 #endif
82 };
83
84
85
pulse_encoder_init(struct rt_pulse_encoder_device * pulse_encoder)86 rt_err_t pulse_encoder_init(struct rt_pulse_encoder_device *pulse_encoder)
87 {
88 ENC_Type *base = ((imxrt_pulse_enccoder_device_t *)(pulse_encoder->parent.user_data))->base;
89 enc_config_t enc_config;
90 ENC_GetDefaultConfig(&enc_config);
91 ENC_Init(base, &enc_config);
92 ENC_DoSoftwareLoadInitialPositionValue(base); /* Update the position counter with initial value. */
93 return RT_EOK;
94 }
95
pulse_encoder_clear_count(struct rt_pulse_encoder_device * pulse_encoder)96 rt_err_t pulse_encoder_clear_count(struct rt_pulse_encoder_device *pulse_encoder)
97 {
98 ENC_SetInitialPositionValue(((imxrt_pulse_enccoder_device_t *)(pulse_encoder->parent.user_data))->base, 0);
99 return RT_EOK;
100 }
101
pulse_encoder_get_count(struct rt_pulse_encoder_device * pulse_encoder)102 rt_int32_t pulse_encoder_get_count(struct rt_pulse_encoder_device *pulse_encoder)
103 {
104 return (rt_int32_t)ENC_GetPositionValue(((imxrt_pulse_enccoder_device_t *)(pulse_encoder->parent.user_data))->base);
105 }
106
pulse_encoder_control(struct rt_pulse_encoder_device * pulse_encoder,rt_uint32_t cmd,void * args)107 rt_err_t pulse_encoder_control(struct rt_pulse_encoder_device *pulse_encoder, rt_uint32_t cmd, void *args)
108 {
109 rt_err_t result;
110
111 result = RT_EOK;
112
113 switch (cmd)
114 {
115 case PULSE_ENCODER_CMD_ENABLE:
116 result = pulse_encoder->ops->init(pulse_encoder);
117 break;
118 case PULSE_ENCODER_CMD_DISABLE:
119 ENC_Deinit(((imxrt_pulse_enccoder_device_t *)(pulse_encoder->parent.user_data))->base);
120 break;
121 default:
122 result = -RT_ENOSYS;
123 break;
124 }
125
126 return result;
127 }
128
129 static const struct rt_pulse_encoder_ops _ops =
130 {
131 .init = pulse_encoder_init,
132 .get_count = pulse_encoder_get_count,
133 .clear_count = pulse_encoder_clear_count,
134 .control = pulse_encoder_control,
135 };
136
rt_hw_pulse_encoder_init(void)137 int rt_hw_pulse_encoder_init(void)
138 {
139 int i;
140 int result;
141
142 result = RT_EOK;
143 for (i = 0; i < sizeof(imxrt_pulse_encoder_obj) / sizeof(imxrt_pulse_encoder_obj[0]); i++)
144 {
145 imxrt_pulse_encoder_obj[i].pulse_encoder.type = AB_PHASE_PULSE_ENCODER;
146 imxrt_pulse_encoder_obj[i].pulse_encoder.ops = &_ops;
147 imxrt_pulse_encoder_obj[i].pulse_encoder.parent.user_data = &(imxrt_pulse_encoder_obj[i]);
148
149 if (rt_device_pulse_encoder_register(&imxrt_pulse_encoder_obj[i].pulse_encoder, imxrt_pulse_encoder_obj[i].name, &imxrt_pulse_encoder_obj[i]) != RT_EOK)
150 {
151 LOG_E("%s register failed", imxrt_pulse_encoder_obj[i].name);
152 result = -RT_ERROR;
153 }
154 }
155
156 return result;
157 }
158 INIT_BOARD_EXPORT(rt_hw_pulse_encoder_init);
159
160 #endif
161