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  * 2020-06-19     thread-liu   the first version
9  */
10 
11 #include <rtdevice.h>
12 
13 #include <string.h>
14 #include <stdlib.h>
15 
16 #define DBG_TAG "dac"
17 #define DBG_LVL DBG_INFO
18 #include <rtdbg.h>
19 
_dac_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)20 static rt_ssize_t _dac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
21 {
22     rt_err_t result = RT_EOK;
23     rt_size_t i;
24     struct rt_dac_device *dac = (struct rt_dac_device *)dev;
25     rt_uint32_t *value = (rt_uint32_t *)buffer;
26 
27     for (i = 0; i < size; i += sizeof(int))
28     {
29         result = dac->ops->convert(dac, pos + i, value);
30         if (result != RT_EOK)
31         {
32             return 0;
33         }
34         value++;
35     }
36 
37     return i;
38 }
39 
_dac_control(rt_device_t dev,int cmd,void * args)40 static rt_err_t _dac_control(rt_device_t dev, int cmd, void *args)
41 {
42     rt_err_t result = -RT_EINVAL;
43     rt_dac_device_t dac = (struct rt_dac_device *)dev;
44 
45     if (cmd == RT_DAC_CMD_ENABLE && dac->ops->enabled)
46     {
47         result = dac->ops->enabled(dac, (rt_uint32_t)args);
48     }
49     else if (cmd == RT_DAC_CMD_DISABLE && dac->ops->enabled)
50     {
51         result = dac->ops->disabled(dac, (rt_uint32_t)args);
52     }
53     else if (cmd == RT_DAC_CMD_GET_RESOLUTION && dac->ops->get_resolution)
54     {
55         rt_uint8_t resolution = dac->ops->get_resolution(dac);
56         if(resolution != 0)
57         {
58             *((rt_uint8_t*)args) = resolution;
59             LOG_D("resolution: %d bits", resolution);
60             result = RT_EOK;
61         }
62     }
63 
64     return result;
65 }
66 
67 #ifdef RT_USING_DEVICE_OPS
68 const static struct rt_device_ops dac_ops =
69 {
70     RT_NULL,
71     RT_NULL,
72     RT_NULL,
73     RT_NULL,
74     _dac_write,
75     _dac_control,
76 };
77 #endif
78 
rt_hw_dac_register(rt_dac_device_t device,const char * name,const struct rt_dac_ops * ops,const void * user_data)79 rt_err_t rt_hw_dac_register(rt_dac_device_t device, const char *name, const struct rt_dac_ops *ops, const void *user_data)
80 {
81     rt_err_t result = RT_EOK;
82     RT_ASSERT(ops != RT_NULL && ops->convert != RT_NULL);
83 
84     device->parent.type = RT_Device_Class_DAC;
85     device->parent.rx_indicate = RT_NULL;
86     device->parent.tx_complete = RT_NULL;
87 
88 #ifdef RT_USING_DEVICE_OPS
89     device->parent.ops         = &dac_ops;
90 #else
91     device->parent.init        = RT_NULL;
92     device->parent.open        = RT_NULL;
93     device->parent.close       = RT_NULL;
94     device->parent.read        = RT_NULL;
95     device->parent.write       = _dac_write;
96     device->parent.control     = _dac_control;
97 #endif
98     device->ops = ops;
99     device->parent.user_data = (void *)user_data;
100 
101     result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR);
102 
103     return result;
104 }
105 
rt_dac_write(rt_dac_device_t dev,rt_uint32_t channel,rt_uint32_t value)106 rt_err_t rt_dac_write(rt_dac_device_t dev, rt_uint32_t channel, rt_uint32_t value)
107 {
108     RT_ASSERT(dev);
109 
110     return dev->ops->convert(dev, channel, &value);
111 }
112 
rt_dac_enable(rt_dac_device_t dev,rt_uint32_t channel)113 rt_err_t rt_dac_enable(rt_dac_device_t dev, rt_uint32_t channel)
114 {
115     rt_err_t result = RT_EOK;
116 
117     RT_ASSERT(dev);
118     if (dev->ops->enabled != RT_NULL)
119     {
120         result = dev->ops->enabled(dev, channel);
121     }
122     else
123     {
124         result = -RT_ENOSYS;
125     }
126 
127     return result;
128 }
129 
rt_dac_disable(rt_dac_device_t dev,rt_uint32_t channel)130 rt_err_t rt_dac_disable(rt_dac_device_t dev, rt_uint32_t channel)
131 {
132     rt_err_t result = RT_EOK;
133 
134     RT_ASSERT(dev);
135     if (dev->ops->disabled != RT_NULL)
136     {
137         result = dev->ops->disabled(dev, channel);
138     }
139     else
140     {
141         result = -RT_ENOSYS;
142     }
143 
144     return result;
145 }
146 
147 #ifdef RT_USING_FINSH
148 
dac(int argc,char ** argv)149 static int dac(int argc, char **argv)
150 {
151     int result = RT_EOK;
152     static rt_dac_device_t dac_device = RT_NULL;
153     char *result_str;
154 
155     if (argc > 1)
156     {
157         if (!strcmp(argv[1], "probe"))
158         {
159             if (argc == 3)
160             {
161                 dac_device = (rt_dac_device_t)rt_device_find(argv[2]);
162                 result_str = (dac_device == RT_NULL) ? "failure" : "success";
163                 rt_kprintf("probe %s %s \n", argv[2], result_str);
164             }
165             else
166             {
167                 rt_kprintf("dac probe <dac_name>   - probe dac by name\n");
168             }
169         }
170         else
171         {
172             if (dac_device == RT_NULL)
173             {
174                 rt_kprintf("Please using 'dac probe <dac_name>' first\n");
175                 return -RT_ERROR;
176             }
177             if (!strcmp(argv[1], "enable"))
178             {
179                 if (argc == 3)
180                 {
181                     result = rt_dac_enable(dac_device, atoi(argv[2]));
182                     result_str = (result == RT_EOK) ? "success" : "failure";
183                     rt_kprintf("%s channel %d enables %s \n", dac_device->parent.parent.name, atoi(argv[2]), result_str);
184                 }
185                 else
186                 {
187                     rt_kprintf("dac enable <channel>   - enable dac channel\n");
188                 }
189             }
190             else if (!strcmp(argv[1], "write"))
191             {
192                 if (argc == 4)
193                 {
194                     rt_dac_write(dac_device, atoi(argv[2]), atoi(argv[3]));
195                     rt_kprintf("%s channel %d write value is %d \n", dac_device->parent.parent.name, atoi(argv[2]), atoi(argv[3]));
196                 }
197                 else
198                 {
199                     rt_kprintf("dac write <channel> <value>     - write dac value on the channel\n");
200                 }
201             }
202             else if (!strcmp(argv[1], "disable"))
203             {
204                 if (argc == 3)
205                 {
206                     result = rt_dac_disable(dac_device, atoi(argv[2]));
207                     result_str = (result == RT_EOK) ? "success" : "failure";
208                     rt_kprintf("%s channel %d disable %s \n", dac_device->parent.parent.name, atoi(argv[2]), result_str);
209                 }
210                 else
211                 {
212                     rt_kprintf("dac disable <channel>  - disable dac channel\n");
213                 }
214             }
215             else
216             {
217                 rt_kprintf("Unknown command. Please enter 'dac' for help\n");
218             }
219         }
220     }
221     else
222     {
223         rt_kprintf("Usage: \n");
224         rt_kprintf("dac probe <dac_name>           - probe dac by name\n");
225         rt_kprintf("dac write <channel> <value>    - write dac value on the channel\n");
226         rt_kprintf("dac disable <channel>          - disable dac channel\n");
227         rt_kprintf("dac enable <channel>           - enable dac channel\n");
228         result = -RT_ERROR;
229     }
230     return RT_EOK;
231 }
232 MSH_CMD_EXPORT(dac, dac function);
233 
234 #endif /* RT_USING_FINSH */
235