1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2018-05-07 aozima the first version
9 */
10
11 #include <string.h>
12
13 #include <drivers/rt_drv_pwm.h>
14
_pwm_control(rt_device_t dev,int cmd,void * args)15 static rt_err_t _pwm_control(rt_device_t dev, int cmd, void *args)
16 {
17 rt_err_t result = RT_EOK;
18 struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev;
19
20 if (pwm->ops->control)
21 {
22 result = pwm->ops->control(pwm, cmd, args);
23 }
24
25 return result;
26 }
27
28
29 /*
30 pos: channel
31 void *buffer: rt_uint32_t pulse[size]
32 size : number of pulse, only set to sizeof(rt_uint32_t).
33 */
_pwm_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)34 static rt_size_t _pwm_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
35 {
36 rt_err_t result = RT_EOK;
37 struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev;
38 rt_uint32_t *pulse = (rt_uint32_t *)buffer;
39 struct rt_pwm_configuration configuration = {0};
40
41 configuration.channel = pos;
42
43 if (pwm->ops->control)
44 {
45 result = pwm->ops->control(pwm, PWM_CMD_GET, &configuration);
46 if (result != RT_EOK)
47 {
48 return 0;
49 }
50
51 *pulse = configuration.pulse;
52 }
53
54 return size;
55 }
56
57 /*
58 pos: channel
59 void *buffer: rt_uint32_t pulse[size]
60 size : number of pulse, only set to sizeof(rt_uint32_t).
61 */
_pwm_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)62 static rt_size_t _pwm_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
63 {
64 rt_err_t result = RT_EOK;
65 struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev;
66 rt_uint32_t *pulse = (rt_uint32_t *)buffer;
67 struct rt_pwm_configuration configuration = {0};
68
69 configuration.channel = pos;
70
71 if (pwm->ops->control)
72 {
73 result = pwm->ops->control(pwm, PWM_CMD_GET, &configuration);
74 if (result != RT_EOK)
75 {
76 return 0;
77 }
78
79 configuration.pulse = *pulse;
80
81 result = pwm->ops->control(pwm, PWM_CMD_SET, &configuration);
82 if (result != RT_EOK)
83 {
84 return 0;
85 }
86 }
87
88 return size;
89 }
90
91 #ifdef RT_USING_DEVICE_OPS
92 static const struct rt_device_ops pwm_device_ops =
93 {
94 RT_NULL,
95 RT_NULL,
96 RT_NULL,
97 _pwm_read,
98 _pwm_write,
99 _pwm_control
100 };
101 #endif /* RT_USING_DEVICE_OPS */
102
rt_device_pwm_register(struct rt_device_pwm * device,const char * name,const struct rt_pwm_ops * ops,const void * user_data)103 rt_err_t rt_device_pwm_register(struct rt_device_pwm *device, const char *name, const struct rt_pwm_ops *ops, const void *user_data)
104 {
105 rt_err_t result = RT_EOK;
106
107 memset(device, 0, sizeof(struct rt_device_pwm));
108
109 #ifdef RT_USING_DEVICE_OPS
110 device->parent.ops = &pwm_device_ops;
111 #else
112 device->parent.init = RT_NULL;
113 device->parent.open = RT_NULL;
114 device->parent.close = RT_NULL;
115 device->parent.read = _pwm_read;
116 device->parent.write = _pwm_write;
117 device->parent.control = _pwm_control;
118 #endif /* RT_USING_DEVICE_OPS */
119
120 device->parent.type = RT_Device_Class_Miscellaneous;
121 device->ops = ops;
122 device->parent.user_data = (void *)user_data;
123
124 result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR);
125
126 return result;
127 }
128
rt_pwm_enable(struct rt_device_pwm * device,int channel)129 rt_err_t rt_pwm_enable(struct rt_device_pwm *device, int channel)
130 {
131 rt_err_t result = RT_EOK;
132 struct rt_pwm_configuration configuration = {0};
133
134 if (!device)
135 {
136 return -RT_EIO;
137 }
138
139 configuration.channel = channel;
140 result = rt_device_control(&device->parent, PWM_CMD_ENABLE, &configuration);
141
142 return result;
143 }
144
rt_pwm_disable(struct rt_device_pwm * device,int channel)145 rt_err_t rt_pwm_disable(struct rt_device_pwm *device, int channel)
146 {
147 rt_err_t result = RT_EOK;
148 struct rt_pwm_configuration configuration = {0};
149
150 if (!device)
151 {
152 return -RT_EIO;
153 }
154
155 configuration.channel = channel;
156 result = rt_device_control(&device->parent, PWM_CMD_DISABLE, &configuration);
157
158 return result;
159 }
160
rt_pwm_set(struct rt_device_pwm * device,int channel,rt_uint32_t period,rt_uint32_t pulse)161 rt_err_t rt_pwm_set(struct rt_device_pwm *device, int channel, rt_uint32_t period, rt_uint32_t pulse)
162 {
163 rt_err_t result = RT_EOK;
164 struct rt_pwm_configuration configuration = {0};
165
166 if (!device)
167 {
168 return -RT_EIO;
169 }
170
171 configuration.channel = channel;
172 configuration.period = period;
173 configuration.pulse = pulse;
174 result = rt_device_control(&device->parent, PWM_CMD_SET, &configuration);
175
176 return result;
177 }
178
179 #ifdef RT_USING_FINSH
180 #include <finsh.h>
181
182 FINSH_FUNCTION_EXPORT_ALIAS(rt_pwm_enable, pwm_enable, enable pwm by channel.);
183 FINSH_FUNCTION_EXPORT_ALIAS(rt_pwm_set, pwm_set, set pwm.);
184
185 #ifdef FINSH_USING_MSH
pwm_enable(int argc,char ** argv)186 static int pwm_enable(int argc, char **argv)
187 {
188 int result = 0;
189 struct rt_device_pwm *device = RT_NULL;
190
191 if (argc != 3)
192 {
193 rt_kprintf("Usage: pwm_enable pwm1 1\n");
194 result = -RT_ERROR;
195 goto _exit;
196 }
197
198 device = (struct rt_device_pwm *)rt_device_find(argv[1]);
199 if (!device)
200 {
201 result = -RT_EIO;
202 goto _exit;
203 }
204
205 result = rt_pwm_enable(device, atoi(argv[2]));
206
207 _exit:
208 return result;
209 }
210 MSH_CMD_EXPORT(pwm_enable, pwm_enable pwm1 1);
211
pwm_disable(int argc,char ** argv)212 static int pwm_disable(int argc, char **argv)
213 {
214 int result = 0;
215 struct rt_device_pwm *device = RT_NULL;
216
217 if (argc != 3)
218 {
219 rt_kprintf("Usage: pwm_enable pwm1 1\n");
220 result = -RT_ERROR;
221 goto _exit;
222 }
223
224 device = (struct rt_device_pwm *)rt_device_find(argv[1]);
225 if (!device)
226 {
227 result = -RT_EIO;
228 goto _exit;
229 }
230
231 result = rt_pwm_disable(device, atoi(argv[2]));
232
233 _exit:
234 return result;
235 }
236 MSH_CMD_EXPORT(pwm_disable, pwm_disable pwm1 1);
237
pwm_set(int argc,char ** argv)238 static int pwm_set(int argc, char **argv)
239 {
240 int result = 0;
241 struct rt_device_pwm *device = RT_NULL;
242
243 if (argc != 5)
244 {
245 rt_kprintf("Usage: pwm_set pwm1 1 100 50\n");
246 result = -RT_ERROR;
247 goto _exit;
248 }
249
250 device = (struct rt_device_pwm *)rt_device_find(argv[1]);
251 if (!device)
252 {
253 result = -RT_EIO;
254 goto _exit;
255 }
256
257 result = rt_pwm_set(device, atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
258
259 _exit:
260 return result;
261 }
262 MSH_CMD_EXPORT(pwm_set, pwm_set 1 100 50);
263
264 #endif /* FINSH_USING_MSH */
265 #endif /* RT_USING_FINSH */
266