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 * 2018-11-16 Ernest Chen add finsh command and update adc function 10 */ 11 12 #include <rtthread.h> 13 #include <rtdevice.h> 14 15 #include <string.h> 16 #include <stdlib.h> 17 18 #define DBG_ENABLE 19 #define DBG_SECTION_NAME "adc" 20 #define DBG_LEVEL DBG_INFO 21 #define DBG_COLOR 22 #include <rtdbg.h> 23 24 static rt_size_t _adc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) 25 { 26 rt_err_t result = RT_EOK; 27 rt_size_t i; 28 struct rt_adc_device *adc = (struct rt_adc_device *)dev; 29 rt_uint32_t *value = (rt_uint32_t *)buffer; 30 31 for (i = 0; i < size; i += sizeof(int)) 32 { 33 result = adc->ops->convert(adc, pos + i, value); 34 if (result != RT_EOK) 35 { 36 return 0; 37 } 38 value++; 39 } 40 41 return i; 42 } 43 44 static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args) 45 { 46 rt_err_t result = RT_EOK; 47 rt_adc_device_t adc = (struct rt_adc_device *)dev; 48 49 if (adc->ops->enabled == RT_NULL) 50 { 51 return -RT_ENOSYS; 52 } 53 if (cmd == RT_ADC_CMD_ENABLE) 54 { 55 result = adc->ops->enabled(adc, (rt_uint32_t)args, RT_TRUE); 56 } 57 else if (cmd == RT_ADC_CMD_DISABLE) 58 { 59 result = adc->ops->enabled(adc, (rt_uint32_t)args, RT_FALSE); 60 } 61 62 return result; 63 } 64 65 rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data) 66 { 67 rt_err_t result = RT_EOK; 68 RT_ASSERT(ops != RT_NULL && ops->convert != RT_NULL); 69 70 device->parent.type = RT_Device_Class_Miscellaneous; 71 device->parent.init = RT_NULL; 72 device->parent.open = RT_NULL; 73 device->parent.close = RT_NULL; 74 device->parent.read = _adc_read; 75 device->parent.write = RT_NULL; 76 device->parent.control = _adc_control; 77 78 device->ops = ops; 79 device->parent.user_data = (void *)user_data; 80 81 result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); 82 83 return result; 84 } 85 86 rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_uint32_t channel) 87 { 88 rt_uint32_t value; 89 90 RT_ASSERT(dev); 91 92 dev->ops->convert(dev, channel, &value); 93 94 return value; 95 } 96 97 rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_uint32_t channel) 98 { 99 rt_err_t result = RT_EOK; 100 101 RT_ASSERT(dev); 102 if (dev->ops->enabled != RT_NULL) 103 { 104 result = dev->ops->enabled(dev, channel, RT_TRUE); 105 } 106 else 107 { 108 result = -RT_ENOSYS; 109 } 110 111 return result; 112 } 113 114 rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_uint32_t channel) 115 { 116 rt_err_t result = RT_EOK; 117 118 RT_ASSERT(dev); 119 if (dev->ops->enabled != RT_NULL) 120 { 121 result = dev->ops->enabled(dev, channel, RT_FALSE); 122 } 123 else 124 { 125 result = -RT_ENOSYS; 126 } 127 128 return result; 129 } 130 131 #ifdef FINSH_USING_MSH 132 133 static int adc(int argc, char **argv) 134 { 135 int value = 0; 136 int result = RT_EOK; 137 static rt_adc_device_t adc_device = RT_NULL; 138 char *result_str; 139 140 if (argc > 1) 141 { 142 if (!strcmp(argv[1], "probe")) 143 { 144 if (argc == 3) 145 { 146 adc_device = (rt_adc_device_t)rt_device_find(argv[2]); 147 result_str = (adc_device == RT_NULL) ? "failure" : "success"; 148 rt_kprintf("probe %s %s \n", argv[2], result_str); 149 } 150 else 151 { 152 rt_kprintf("adc probe <adc_name> - probe adc by name\n"); 153 } 154 } 155 else 156 { 157 if (adc_device == RT_NULL) 158 { 159 rt_kprintf("Please using 'adc probe <adc_name>' first\n"); 160 return -RT_ERROR; 161 } 162 if (!strcmp(argv[1], "enable")) 163 { 164 if (argc == 3) 165 { 166 result = rt_adc_enable(adc_device, atoi(argv[2])); 167 result_str = (result == RT_EOK) ? "success" : "failure"; 168 rt_kprintf("%s channel %d enables %s \n", adc_device->parent.parent.name, atoi(argv[2]), result_str); 169 } 170 else 171 { 172 rt_kprintf("adc enable <channel> - enable adc channel\n"); 173 } 174 } 175 else if (!strcmp(argv[1], "read")) 176 { 177 if (argc == 3) 178 { 179 value = rt_adc_read(adc_device, atoi(argv[2])); 180 rt_kprintf("%s channel %d read value is 0x%08X \n", adc_device->parent.parent.name, atoi(argv[2]), value); 181 } 182 else 183 { 184 rt_kprintf("adc read <channel> - read adc value on the channel\n"); 185 } 186 } 187 else if (!strcmp(argv[1], "disable")) 188 { 189 if (argc == 3) 190 { 191 result = rt_adc_disable(adc_device, atoi(argv[2])); 192 result_str = (result == RT_EOK) ? "success" : "failure"; 193 rt_kprintf("%s channel %d disable %s \n", adc_device->parent.parent.name, atoi(argv[2]), result_str); 194 } 195 else 196 { 197 rt_kprintf("adc disable <channel> - disable adc channel\n"); 198 } 199 } 200 else 201 { 202 rt_kprintf("Unknown command. Please enter 'adc' for help\n"); 203 } 204 } 205 } 206 else 207 { 208 rt_kprintf("Usage: \n"); 209 rt_kprintf("adc probe <adc_name> - probe adc by name\n"); 210 rt_kprintf("adc read <channel> - read adc value on the channel\n"); 211 rt_kprintf("adc disable <channel> - disable adc channel\n"); 212 rt_kprintf("adc enable <channel> - enable adc channel\n"); 213 result = -RT_ERROR; 214 } 215 return RT_EOK; 216 } 217 MSH_CMD_EXPORT(adc, adc function); 218 219 #endif /* FINSH_USING_MSH */ 220