1 /*
2  * COPYRIGHT (C) 2012-2024, Shanghai Real-Thread Technology Co., Ltd
3  * All rights reserved.
4  * Change Logs:
5  * Date           Author       Notes
6  * 2018-02-08     RT-Thread  the first version
7  */
8 #include <rtthread.h>
9 #include <rtdevice.h>
10 #include "drv_touch.h"
11 #include "drv_pin.h"
12 // #include "lcd_cfg.h"
13 
14 #ifndef TOUCH_I2C_NAME
15 #define TOUCH_I2C_NAME "i2c2"
16 #endif
17 #define DBG_TAG "TOUCH"
18 #define DBG_LVL DBG_LOG
19 #include <rtdbg.h>
20 
21 #define COORD_Y_REVERSE (1 << 0)
22 #define COORD_X_REVERSE (1 << 1)
23 #define COORD_XY_EXCHANGE (1 << 2)
24 
25 #ifdef BSP_USING_MANGOPI                             // mango board
26 #define TP_INT_PIN GET_PIN(GPIO_PORT_D, GPIO_PIN_22) /* GPIO_PORT_D GPIO_PIN_22 */
27 #elif defined(BSP_USING_M7)
28 #define TP_INT_PIN GET_PIN(GPIO_PORT_G, GPIO_PIN_14) /* GPIO_PORT_G GPIO_PIN_14 */
29 #endif
30 
31 static rt_slist_t _driver_list;
32 static struct rt_i2c_bus_device *i2c_bus = RT_NULL;
33 static struct touch_driver *current_driver = RT_NULL;
34 static struct rt_touch_device touch_device;
35 static rt_timer_t touch_timer = RT_NULL;
36 static int tp_convert_flag;
37 // static const struct lcd_cfg_panel_info *_panel_info;
38 
touch_coord_convert(int * x,int * y,int range_x,int range_y,int flag)39 void touch_coord_convert(int *x, int *y, int range_x, int range_y, int flag)
40 {
41     int xbuf, ybuf;
42 
43     if (flag & COORD_XY_EXCHANGE)
44     {
45         xbuf = range_x;
46         range_x = range_y;
47         range_y = xbuf;
48         xbuf = *y;
49         ybuf = *x;
50 
51         if (flag & COORD_X_REVERSE)
52         {
53             ybuf = range_y - ybuf;
54         }
55 
56         if (flag & COORD_Y_REVERSE)
57         {
58             xbuf = range_x - xbuf;
59         }
60     }
61     else
62     {
63         xbuf = *x;
64         ybuf = *y;
65 
66         if (flag & COORD_X_REVERSE)
67         {
68             xbuf = range_x - xbuf;
69         }
70 
71         if (flag & COORD_Y_REVERSE)
72         {
73             ybuf = range_y - ybuf;
74         }
75     }
76 
77     *x = xbuf;
78     *y = ybuf;
79 }
80 
rt_touch_drivers_register(touch_driver_t drv)81 rt_err_t rt_touch_drivers_register(touch_driver_t drv)
82 {
83     RT_ASSERT(drv != RT_NULL);
84     RT_ASSERT(drv->ops != RT_NULL);
85     RT_ASSERT(drv->probe != RT_NULL);
86 
87     rt_slist_append(&_driver_list, &drv->list);
88 
89     return RT_EOK;
90 }
91 
rt_touch_list_init(void)92 int rt_touch_list_init(void)
93 {
94     rt_slist_init(&_driver_list);
95 
96     return RT_EOK;
97 }
98 INIT_BOARD_EXPORT(rt_touch_list_init);
99 
touch_timeout_handle(void * parameter)100 static void touch_timeout_handle(void *parameter)
101 {
102     rt_touch_t touch = (rt_touch_t)parameter;
103     rt_device_t device = &touch->parent;
104 
105     device->control(device, RT_TOUCH_CTRL_ENABLE_INT, RT_NULL); // enable tp irq
106 
107     // rt_kprintf("[%s:%d]touch_timeout_handle\n", __FUNCTION__, __LINE__);
108 }
109 
tp_irq_handle(rt_touch_t touch)110 static rt_err_t tp_irq_handle(rt_touch_t touch)
111 {
112     rt_device_t device;
113     device = &touch->parent;
114 
115     device->control(device, RT_TOUCH_CTRL_DISABLE_INT, RT_NULL); // disable tp irq
116 
117     return RT_EOK;
118 }
119 
rt_touch_read(rt_uint16_t addr,void * cmd_buf,size_t cmd_len,void * data_buf,size_t data_len)120 int rt_touch_read(rt_uint16_t addr, void *cmd_buf, size_t cmd_len, void *data_buf, size_t data_len)
121 {
122     struct rt_i2c_msg msgs[2];
123 
124     msgs[0].addr = addr;
125     msgs[0].flags = RT_I2C_WR;
126     msgs[0].buf = cmd_buf;
127     msgs[0].len = cmd_len;
128 
129     msgs[1].addr = addr;
130     msgs[1].flags = RT_I2C_RD;
131     msgs[1].buf = data_buf;
132     msgs[1].len = data_len;
133 
134     if (rt_i2c_transfer(i2c_bus, msgs, 2) == 2)
135         return 0;
136     else
137         return -1;
138 }
139 
rt_touch_write(rt_uint16_t addr,void * data_buf,size_t data_len)140 int rt_touch_write(rt_uint16_t addr, void *data_buf, size_t data_len)
141 {
142     struct rt_i2c_msg msgs[1];
143 
144     msgs[0].addr = addr;
145     msgs[0].flags = RT_I2C_WR;
146     msgs[0].buf = data_buf;
147     msgs[0].len = data_len;
148 
149     if (rt_i2c_transfer(i2c_bus, msgs, 1) == 1)
150         return 0;
151     else
152         return -1;
153 }
154 
touch_readpoint(struct rt_touch_device * touch,void * buf,rt_size_t touch_num)155 static rt_ssize_t touch_readpoint(struct rt_touch_device *touch, void *buf, rt_size_t touch_num)
156 {
157     rt_device_t device;
158     struct rt_touch_data *data = (struct rt_touch_data *)buf;
159     int x, y;
160     device = &touch->parent;
161 
162     current_driver->ops->read_point(data, touch_num);
163 
164     /* touch up事件是上次转换后的,所以不需要执行转换 */
165     if ((RT_TOUCH_EVENT_NONE != data->event) && (RT_TOUCH_EVENT_UP != data->event))
166     {
167         x = data->x_coordinate;
168         y = data->y_coordinate;
169         // touch_coord_convert(&x, &y, _panel_info->width, _panel_info->height, tp_convert_flag);
170         data->x_coordinate = x;
171         data->y_coordinate = y;
172     }
173 
174     if ((touch_timer != RT_NULL) && (current_driver->read_interval != 0))
175     {
176         rt_timer_start(touch_timer);
177     }
178     else if ((TOUCH_INT_MODE == current_driver->check_mode) && (0 != current_driver->read_interval))
179     {
180         device->control(device, RT_TOUCH_CTRL_ENABLE_INT, RT_NULL); // enable tp irq
181     }
182     else
183     {
184     }
185 
186     return 1;
187 }
188 
touch_control(struct rt_touch_device * touch,int cmd,void * arg)189 static rt_err_t touch_control(struct rt_touch_device *touch, int cmd, void *arg)
190 {
191     return RT_EOK;
192 }
193 
194 static struct rt_touch_ops touch_ops =
195     {
196         .touch_readpoint = touch_readpoint,
197         .touch_control = touch_control,
198 };
199 
touch_poll_entry(void * parameter)200 static void touch_poll_entry(void *parameter)
201 {
202     rt_tick_t read_interval = current_driver->read_interval;
203 
204     if (0 == read_interval)
205     {
206         read_interval = rt_tick_from_millisecond(20);
207     }
208 
209     while (1)
210     {
211         rt_thread_delay(read_interval);
212         if (RT_NULL != touch_device.parent.rx_indicate)
213         {
214             /* Notify the application layer to get data */
215             touch_device.parent.rx_indicate(&touch_device.parent, 1);
216         }
217     }
218 }
219 
rt_touch_init(void)220 int rt_touch_init(void)
221 {
222     rt_slist_t *driver_list = RT_NULL;
223     rt_uint16_t irq_pin = TP_INT_PIN;
224     int range_x, range_y;
225 
226     i2c_bus = rt_i2c_bus_device_find(TOUCH_I2C_NAME);
227     RT_ASSERT(i2c_bus);
228 
229     if (rt_device_open(&i2c_bus->parent, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
230     {
231         rt_kprintf("[TP] open i2c dvice failed.\n");
232         return -RT_EIO;
233     }
234 
235     rt_slist_for_each(driver_list, &_driver_list)
236     {
237         current_driver = (struct touch_driver *)driver_list;
238         if (current_driver->probe(i2c_bus) == RT_TRUE)
239         {
240             break;
241         }
242         current_driver = RT_NULL;
243     }
244 
245     if (current_driver == RT_NULL)
246     {
247         rt_kprintf("[TP] No touch pad or driver.\n");
248         rt_device_close((rt_device_t)i2c_bus);
249         return -RT_EIO;
250     }
251 
252     if ((TOUCH_INT_MODE == current_driver->check_mode) && (0 != current_driver->read_interval))
253     {
254         touch_timer = rt_timer_create("touch", touch_timeout_handle,
255                                       &touch_device, current_driver->read_interval,
256                                       RT_TIMER_FLAG_ONE_SHOT);
257         if (touch_timer == RT_NULL)
258         {
259             rt_kprintf("[TP] touch timer create failed.\n");
260             rt_device_close((rt_device_t)i2c_bus);
261             return -RT_EIO;
262         }
263     }
264     else if (TOUCH_POLL_MODE == current_driver->check_mode)
265     {
266         rt_thread_t thread;
267         irq_pin = PIN_IRQ_PIN_NONE; // No interrupt pins are used
268         thread = rt_thread_create("touch", touch_poll_entry, RT_NULL, 2048, 16, 20);
269         if (thread == RT_NULL)
270         {
271             rt_kprintf("[TP] touch poll thread create failed.\n");
272             rt_device_close((rt_device_t)i2c_bus);
273             return -RT_ERROR;
274         }
275         rt_thread_startup(thread);
276     }
277 
278     /* loading the touchscreen configuration */
279     // _panel_info = load_lcd_config_from_xml();
280     // range_x = _panel_info->width;
281     // range_y = _panel_info->height;
282     // tp_convert_flag = 0;
283     // /* touch screen xy swap */
284     // if (_panel_info->ctp_flag & COORD_XY_EXCHANGE)
285     // {
286     //     tp_convert_flag |= COORD_XY_EXCHANGE;
287     //     touch_coord_convert(&range_x, &range_y, _panel_info->width, _panel_info->height, COORD_XY_EXCHANGE);
288     // }
289 
290     // if (_panel_info->ctp_flag & COORD_Y_REVERSE)
291     // {
292     //     tp_convert_flag |= COORD_Y_REVERSE;
293     // }
294 
295     // if (_panel_info->ctp_flag & COORD_X_REVERSE)
296     // {
297     //     tp_convert_flag |= COORD_X_REVERSE;
298     // }
299 
300     current_driver->ops->init(i2c_bus);
301 
302     /* touch infomation */
303     touch_device.info.type = RT_TOUCH_TYPE_CAPACITANCE;
304     touch_device.info.vendor = RT_TOUCH_VENDOR_UNKNOWN;
305     touch_device.info.point_num = 1;
306     touch_device.info.range_x = 480;
307     touch_device.info.range_y = 272;
308     touch_device.config.user_data = RT_NULL;
309     touch_device.ops = &touch_ops;
310     touch_device.irq_handle = tp_irq_handle;
311     touch_device.config.irq_pin.pin = irq_pin;
312     touch_device.config.irq_pin.mode = PIN_MODE_INPUT_PULLUP;
313 
314     return rt_hw_touch_register(&touch_device, "touch", RT_DEVICE_FLAG_INT_RX, RT_NULL);
315 }
316 INIT_ENV_EXPORT(rt_touch_init);
317