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-05-20 tyustli the first version
9 */
10
11 #include <rtdevice.h>
12 #include <string.h>
13
14 #define DBG_TAG "touch"
15 #define DBG_LVL DBG_INFO
16 #include <rtdbg.h>
17
18 /* ISR for touch interrupt */
rt_hw_touch_isr(rt_touch_t touch)19 void rt_hw_touch_isr(rt_touch_t touch)
20 {
21 RT_ASSERT(touch);
22 if (touch->parent.rx_indicate == RT_NULL)
23 {
24 return;
25 }
26
27 if (touch->irq_handle != RT_NULL)
28 {
29 touch->irq_handle(touch);
30 }
31
32 touch->parent.rx_indicate(&touch->parent, 1);
33 }
34
35 #ifdef RT_TOUCH_PIN_IRQ
touch_irq_callback(void * param)36 static void touch_irq_callback(void *param)
37 {
38 rt_hw_touch_isr((rt_touch_t)param);
39 }
40 #endif
41
42 /* touch interrupt initialization function */
rt_touch_irq_init(rt_touch_t touch)43 static rt_err_t rt_touch_irq_init(rt_touch_t touch)
44 {
45 #ifdef RT_TOUCH_PIN_IRQ
46 if (touch->config.irq_pin.pin == PIN_IRQ_PIN_NONE)
47 {
48 return -RT_EINVAL;
49 }
50
51 rt_pin_mode(touch->config.irq_pin.pin, touch->config.irq_pin.mode);
52
53 if (touch->config.irq_pin.mode == PIN_MODE_INPUT_PULLDOWN)
54 {
55 rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_RISING, touch_irq_callback, (void *)touch);
56 }
57 else if (touch->config.irq_pin.mode == PIN_MODE_INPUT_PULLUP)
58 {
59 rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_FALLING, touch_irq_callback, (void *)touch);
60 }
61 else if (touch->config.irq_pin.mode == PIN_MODE_INPUT)
62 {
63 rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_RISING_FALLING, touch_irq_callback, (void *)touch);
64 }
65
66 rt_pin_irq_enable(touch->config.irq_pin.pin, PIN_IRQ_ENABLE);
67 #endif
68
69 return RT_EOK;
70 }
71
72 /* touch interrupt enable */
rt_touch_irq_enable(rt_touch_t touch)73 static void rt_touch_irq_enable(rt_touch_t touch)
74 {
75 #ifdef RT_TOUCH_PIN_IRQ
76 if (touch->config.irq_pin.pin != PIN_IRQ_PIN_NONE)
77 {
78 rt_pin_irq_enable(touch->config.irq_pin.pin, RT_TRUE);
79 }
80 #else
81 touch->ops->touch_control(touch, RT_TOUCH_CTRL_ENABLE_INT, RT_NULL);
82 #endif
83 }
84
85 /* touch interrupt disable */
rt_touch_irq_disable(rt_touch_t touch)86 static void rt_touch_irq_disable(rt_touch_t touch)
87 {
88 #ifdef RT_TOUCH_PIN_IRQ
89 if (touch->config.irq_pin.pin != PIN_IRQ_PIN_NONE)
90 {
91 rt_pin_irq_enable(touch->config.irq_pin.pin, RT_FALSE);
92 }
93 #else
94 touch->ops->touch_control(touch, RT_TOUCH_CTRL_DISABLE_INT, RT_NULL);
95 #endif
96 }
97
rt_touch_open(rt_device_t dev,rt_uint16_t oflag)98 static rt_err_t rt_touch_open(rt_device_t dev, rt_uint16_t oflag)
99 {
100 rt_touch_t touch;
101 RT_ASSERT(dev != RT_NULL);
102 touch = (rt_touch_t)dev;
103
104 if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX)
105 {
106 /* Initialization touch interrupt */
107 rt_touch_irq_init(touch);
108 }
109
110 return RT_EOK;
111 }
112
rt_touch_close(rt_device_t dev)113 static rt_err_t rt_touch_close(rt_device_t dev)
114 {
115 rt_touch_t touch;
116 RT_ASSERT(dev != RT_NULL);
117 touch = (rt_touch_t)dev;
118
119 /* touch disable interrupt */
120 rt_touch_irq_disable(touch);
121
122 return RT_EOK;
123 }
124
rt_touch_read(rt_device_t dev,rt_off_t pos,void * buf,rt_size_t len)125 static rt_ssize_t rt_touch_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t len)
126 {
127 rt_touch_t touch;
128 rt_size_t result = 0;
129 RT_ASSERT(dev != RT_NULL);
130 touch = (rt_touch_t)dev;
131
132 if (buf == NULL || len == 0)
133 {
134 return 0;
135 }
136
137 result = touch->ops->touch_readpoint(touch, buf, len);
138
139 return result;
140 }
141
rt_touch_control(rt_device_t dev,int cmd,void * args)142 static rt_err_t rt_touch_control(rt_device_t dev, int cmd, void *args)
143 {
144 rt_touch_t touch;
145 rt_err_t result = RT_EOK;
146 RT_ASSERT(dev != RT_NULL);
147 touch = (rt_touch_t)dev;
148
149 switch (cmd)
150 {
151 case RT_TOUCH_CTRL_SET_MODE:
152 result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_MODE, args);
153
154 if (result == RT_EOK)
155 {
156 rt_uint16_t mode;
157 mode = *(rt_uint16_t*)args;
158 if (mode == RT_DEVICE_FLAG_INT_RX)
159 {
160 rt_touch_irq_enable(touch); /* enable interrupt */
161 }
162 }
163
164 break;
165 case RT_TOUCH_CTRL_SET_X_RANGE:
166 result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_X_RANGE, args);
167
168 if (result == RT_EOK)
169 {
170 touch->info.range_x = *(rt_int32_t *)args;
171 LOG_D("set x coordinate range :%d\n", touch->info.range_x);
172 }
173
174 break;
175 case RT_TOUCH_CTRL_SET_Y_RANGE:
176 result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_Y_RANGE, args);
177
178 if (result == RT_EOK)
179 {
180 touch->info.range_y = *(rt_uint32_t *)args;
181 LOG_D("set y coordinate range :%d \n", touch->info.range_x);
182 }
183
184 break;
185 case RT_TOUCH_CTRL_DISABLE_INT:
186 rt_touch_irq_disable(touch);
187 break;
188 case RT_TOUCH_CTRL_ENABLE_INT:
189 rt_touch_irq_enable(touch);
190 break;
191
192 case RT_TOUCH_CTRL_GET_ID:
193 case RT_TOUCH_CTRL_GET_INFO:
194 default:
195 return touch->ops->touch_control(touch, cmd, args);
196 }
197
198 return result;
199 }
200
201 #ifdef RT_USING_DEVICE_OPS
202 const static struct rt_device_ops rt_touch_ops =
203 {
204 RT_NULL,
205 rt_touch_open,
206 rt_touch_close,
207 rt_touch_read,
208 RT_NULL,
209 rt_touch_control
210 };
211 #endif
212
213 /*
214 * touch register
215 */
rt_hw_touch_register(rt_touch_t touch,const char * name,rt_uint32_t flag,void * data)216 int rt_hw_touch_register(rt_touch_t touch,
217 const char *name,
218 rt_uint32_t flag,
219 void *data)
220 {
221 rt_err_t result;
222 rt_device_t device;
223 RT_ASSERT(touch != RT_NULL);
224
225 device = &touch->parent;
226
227 #ifdef RT_USING_DEVICE_OPS
228 device->ops = &rt_touch_ops;
229 #else
230 device->init = RT_NULL;
231 device->open = rt_touch_open;
232 device->close = rt_touch_close;
233 device->read = rt_touch_read;
234 device->write = RT_NULL;
235 device->control = rt_touch_control;
236 #endif
237 device->type = RT_Device_Class_Touch;
238 device->rx_indicate = RT_NULL;
239 device->tx_complete = RT_NULL;
240 device->user_data = data;
241
242 result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_STANDALONE);
243
244 if (result != RT_EOK)
245 {
246 LOG_E("rt_touch register err code: %d", result);
247 return result;
248 }
249
250 LOG_I("rt_touch init success");
251
252 return RT_EOK;
253 }
254