1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author           Notes
8  * 2018-12-04     Sundm75        the first version
9  */
10 #include <stdint.h>
11 #include <string.h>
12 #include <stdlib.h>
13 
14 #include <rtthread.h>
15 #include <rtdevice.h>
16 
17 #include "ls1c.h"
18 #include "../libraries/ls1c_public.h"
19 #include "../libraries/ls1c_regs.h"
20 #include "../libraries/ls1c_clock.h"
21 #include "../libraries/ls1c_pwm.h"
22 #include "../libraries/ls1c_pin.h"
23 
24 #define PWM_CHANNEL_MAX     (4) /* 0-3*/
25 
26 #ifdef RT_USING_PWM
27 
28 struct rt_ls1c_pwm
29 {
30     struct rt_device_pwm parent;
31 
32     rt_uint32_t period[PWM_CHANNEL_MAX];
33     rt_uint32_t pulse[PWM_CHANNEL_MAX];
34 };
35 
36 static struct rt_ls1c_pwm _ls1c_pwm_device;
37 
set(struct rt_device_pwm * device,struct rt_pwm_configuration * configuration)38 static rt_err_t set(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
39 {
40     rt_err_t result = RT_EOK;
41     struct rt_ls1c_pwm *ls1c_pwm_device = (struct rt_ls1c_pwm *)device;
42 
43     if (configuration->channel > (PWM_CHANNEL_MAX - 1))
44     {
45         result = -RT_EIO;
46         goto _exit;
47     }
48 
49     rt_kprintf("drv_pwm.c set channel %d: period: %d, pulse: %d\n", configuration->channel, configuration->period, configuration->pulse);
50 
51     ls1c_pwm_device->period[configuration->channel] = configuration->period;
52     ls1c_pwm_device->pulse[configuration->channel] = configuration->pulse;
53 
54 _exit:
55     return result;
56 }
57 
get(struct rt_device_pwm * device,struct rt_pwm_configuration * configuration)58 static rt_err_t get(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
59 {
60     rt_err_t result = RT_EOK;
61     struct rt_ls1c_pwm *ls1c_pwm_device = (struct rt_ls1c_pwm *)device;
62 
63     if (configuration->channel > (PWM_CHANNEL_MAX - 1))
64     {
65         result = -RT_EIO;
66         goto _exit;
67     }
68 
69     configuration->period = ls1c_pwm_device->period[configuration->channel];
70     configuration->pulse = ls1c_pwm_device->pulse[configuration->channel];
71     rt_kprintf("drv_pwm.c get channel %d: period: %d, pulse: %d\n", configuration->channel, configuration->period, configuration->pulse);
72 
73 _exit:
74     return result;
75 }
76 
control(struct rt_device_pwm * device,int cmd,void * arg)77 static rt_err_t control(struct rt_device_pwm *device, int cmd, void *arg)
78 {
79      rt_err_t result = RT_EOK;
80     struct rt_pwm_configuration * configuration = (struct rt_pwm_configuration *)arg;
81 
82     rt_kprintf("drv_pwm.c control cmd: %d. \n", cmd);
83 
84     if (cmd == PWM_CMD_ENABLE)
85     {
86         rt_kprintf("PWM_CMD_ENABLE\n");
87 
88         pwm_info_t pwm_info;
89         switch ( configuration->channel)
90         {
91         case 0:
92             pwm_info.gpio = LS1C_PWM0_GPIO06;
93             //pwm_info.gpio = LS1C_PWM0_GPIO04;
94             break;
95         case 1:
96             pwm_info.gpio = LS1C_PWM1_GPIO92;
97             //pwm_info.gpio = LS1C_PWM1_GPIO05;
98             break;
99         case 2:
100             pwm_info.gpio = LS1C_PWM2_GPIO52;
101             //pwm_info.gpio = LS1C_PWM2_GPIO46;
102             break;
103         case 3:
104             pwm_info.gpio = LS1C_PWM3_GPIO47;
105             //pwm_info.gpio = LS1C_PWM3_GPIO53;
106             break;
107         default:
108             break;
109         }
110         pwm_info.mode = PWM_MODE_NORMAL;
111         pwm_info.duty =  ( (float)configuration->pulse ) / ((float)configuration->period );
112         pwm_info.period_ns = configuration->period;
113         pwm_init(&pwm_info);
114         pwm_enable(&pwm_info);
115     }
116     else if (cmd == PWM_CMD_DISABLE)
117     {
118         rt_kprintf("PWM_CMD_DISABLE\n");
119         pwm_info_t pwm_info;
120         switch ( configuration->channel)
121         {
122         case 0:
123             pwm_info.gpio = LS1C_PWM0_GPIO06;
124             //pwm_info.gpio = LS1C_PWM0_GPIO04;
125             break;
126         case 1:
127             pwm_info.gpio = LS1C_PWM1_GPIO92;
128             //pwm_info.gpio = LS1C_PWM1_GPIO05;
129             break;
130         case 2:
131             pwm_info.gpio = LS1C_PWM2_GPIO52;
132             //pwm_info.gpio = LS1C_PWM2_GPIO46;
133             break;
134         case 3:
135             pwm_info.gpio = LS1C_PWM3_GPIO47;
136             //pwm_info.gpio = LS1C_PWM3_GPIO53;
137             break;
138         default:
139             break;
140         }
141         pwm_info.mode = PWM_MODE_NORMAL;
142         pwm_info.duty =  ( (float)configuration->pulse ) / ((float)configuration->period );
143         pwm_info.period_ns = configuration->period;
144         pwm_init(&pwm_info);
145         pwm_disable(&pwm_info);
146     }
147     else if (cmd == PWM_CMD_SET)
148     {
149         rt_kprintf("PWM_CMD_SET\n");
150         result = set(device, (struct rt_pwm_configuration *)arg);
151     }
152     else if (cmd == PWM_CMD_GET)
153     {
154         rt_kprintf("PWM_CMD_GET\n");
155         result = get(device, (struct rt_pwm_configuration *)arg);
156     }
157 
158     return result;
159 }
160 
161 static const struct rt_pwm_ops pwm_ops =
162 {
163     control,
164 };
165 
rt_hw_pwm_init(void)166 int rt_hw_pwm_init(void)
167 {
168     int ret = RT_EOK;
169 
170     /* add pwm initial. */
171 
172     ret = rt_device_pwm_register(&_ls1c_pwm_device.parent, "pwm", &pwm_ops, RT_NULL);
173 
174     return ret;
175 }
176 INIT_DEVICE_EXPORT(rt_hw_pwm_init);
177 
178 #endif /*RT_USING_PWM*/
179