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