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