1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2018-02-08     Zhangyihong  the first version
9  */
10 
11 #include <rtconfig.h>
12 
13 #ifdef BSP_USING_TOUCH_CAP
14 #include "drv_touch.h"
15 #include <string.h>
16 
17 #define DBG_ENABLE
18 #define DBG_SECTION_NAME  "touch"
19 #define DBG_LEVEL         DBG_INFO
20 #define DBG_COLOR
21 #include <rtdbg.h>
22 
23 #ifdef PKG_USING_GUIENGINE
24 #include <rtgui/event.h>
25 #include <rtgui/rtgui_server.h>
26 #elif defined(PKG_USING_LITTLEVGL2RTT)
27 #include <littlevgl2rtt.h>
28 #elif defined(PKG_USING_LVGL)
29 #include <lvgl.h>
30 extern void lv_port_indev_input(rt_int16_t x, rt_int16_t y, lv_indev_state_t state);
31 static rt_bool_t touch_down = RT_FALSE;
32 #endif /* PKG_USING_GUIENGINE */
33 
34 #define BSP_TOUCH_SAMPLE_HZ    (50)
35 
36 static rt_list_t driver_list;
37 
rt_touch_drivers_register(touch_drv_t drv)38 void rt_touch_drivers_register(touch_drv_t drv)
39 {
40     rt_list_insert_before(&driver_list, &drv->list);
41 }
42 
post_down_event(rt_uint16_t x,rt_uint16_t y,rt_tick_t ts)43 static void post_down_event(rt_uint16_t x, rt_uint16_t y, rt_tick_t ts)
44 {
45 #ifdef PKG_USING_GUIENGINE
46     struct rtgui_event_mouse emouse;
47 
48     emouse.parent.sender = RT_NULL;
49     emouse.wid = RT_NULL;
50     emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
51     emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
52     emouse.x = x;
53     emouse.y = y;
54     emouse.ts = rt_tick_get();
55     emouse.id = ts;
56     rtgui_server_post_event(&emouse.parent, sizeof(emouse));
57 #elif defined(PKG_USING_LITTLEVGL2RTT)
58     littlevgl2rtt_send_input_event(x, y, LITTLEVGL2RTT_INPUT_DOWN);
59 #elif defined(PKG_USING_LVGL)
60     touch_down = RT_TRUE;
61     lv_port_indev_input(x, y, (touch_down == RT_TRUE) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
62 #endif
63 }
64 
post_motion_event(rt_uint16_t x,rt_uint16_t y,rt_tick_t ts)65 static void post_motion_event(rt_uint16_t x, rt_uint16_t y, rt_tick_t ts)
66 {
67 #ifdef PKG_USING_GUIENGINE
68     struct rtgui_event_mouse emouse;
69 
70     emouse.parent.sender = RT_NULL;
71     emouse.wid = RT_NULL;
72     emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
73     emouse.parent.type = RTGUI_EVENT_MOUSE_MOTION;
74     emouse.x = x;
75     emouse.y = y;
76     emouse.ts = rt_tick_get();
77     emouse.id = ts;
78     rtgui_server_post_event(&emouse.parent, sizeof(emouse));
79 #elif defined(PKG_USING_LITTLEVGL2RTT)
80     littlevgl2rtt_send_input_event(x, y, LITTLEVGL2RTT_INPUT_MOVE);
81 #elif defined(PKG_USING_LVGL)
82     lv_port_indev_input(x, y, (touch_down == RT_TRUE) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
83 #endif /* PKG_USING_GUIENGINE */
84 }
85 
post_up_event(rt_uint16_t x,rt_uint16_t y,rt_tick_t ts)86 static void post_up_event(rt_uint16_t x, rt_uint16_t y, rt_tick_t ts)
87 {
88 #ifdef PKG_USING_GUIENGINE
89     struct rtgui_event_mouse emouse;
90 
91     emouse.parent.sender = RT_NULL;
92     emouse.wid = RT_NULL;
93     emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
94     emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_UP;
95     emouse.x = x;
96     emouse.y = y;
97     emouse.ts = rt_tick_get();
98     emouse.id = ts;
99     rtgui_server_post_event(&emouse.parent, sizeof(emouse));
100 #elif defined(PKG_USING_LITTLEVGL2RTT)
101     littlevgl2rtt_send_input_event(x, y, LITTLEVGL2RTT_INPUT_MOVE);
102 #elif defined(PKG_USING_LVGL)
103     touch_down = RT_FALSE;
104     lv_port_indev_input(x, y, (touch_down == RT_TRUE) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
105 #endif /* PKG_USING_GUIENGINE */
106 }
107 
touch_thread_entry(void * parameter)108 static void touch_thread_entry(void *parameter)
109 {
110     touch_drv_t touch = (touch_drv_t)parameter;
111     struct touch_message msg;
112     rt_tick_t emouse_id = 0;
113     touch->ops->isr_enable(RT_TRUE);
114     while (1)
115     {
116         if (rt_sem_take(touch->isr_sem, 10) != RT_EOK)
117         {
118             continue;
119         }
120 
121         while(touch->ops->read_point(&msg) == RT_EOK)
122         {
123             switch (msg.event)
124             {
125             case TOUCH_EVENT_UP:
126                 post_up_event(msg.x, msg.y, emouse_id);
127                 break;
128             case TOUCH_EVENT_DOWN:
129                 emouse_id = rt_tick_get();
130                 post_down_event(msg.x, msg.y, emouse_id);
131                 break;
132             case TOUCH_EVENT_MOVE:
133                 post_motion_event(msg.x, msg.y, emouse_id);
134                 break;
135             default:
136                 break;
137             }
138             rt_thread_delay(RT_TICK_PER_SECOND / BSP_TOUCH_SAMPLE_HZ);
139         }
140         touch->ops->isr_enable(RT_TRUE);
141     }
142 }
143 
rt_touch_driver_init(void)144 static int rt_touch_driver_init(void)
145 {
146     rt_list_init(&driver_list);
147     return 0;
148 }
149 INIT_BOARD_EXPORT(rt_touch_driver_init);
150 
151 static struct rt_i2c_bus_device *i2c_bus = RT_NULL;
rt_touch_thread_init(void)152 static int rt_touch_thread_init(void)
153 {
154     rt_list_t *l;
155     touch_drv_t current_driver;
156     rt_thread_t tid = RT_NULL;
157     i2c_bus = (struct rt_i2c_bus_device *)rt_device_find("i2c2");
158     RT_ASSERT(i2c_bus);
159     current_driver = RT_NULL;
160     if (rt_device_open((rt_device_t)i2c_bus, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
161         return -1;
162     for (l = driver_list.next; l != &driver_list; l = l->next)
163     {
164         if (rt_list_entry(l, struct touch_drivers, list)->probe(i2c_bus))
165         {
166             current_driver = rt_list_entry(l, struct touch_drivers, list);
167             break;
168         }
169     }
170     if (current_driver == RT_NULL)
171     {
172         LOG_E("no touch screen or do not have driver");
173         rt_device_close((rt_device_t)i2c_bus);
174         return -1;
175     }
176     current_driver->ops->init(i2c_bus);
177     LOG_I("touch screen found driver");
178     tid = rt_thread_create("touch", touch_thread_entry, current_driver, 2048, 27, 20);
179     if (tid == RT_NULL)
180     {
181         current_driver->ops->deinit();
182         rt_device_close((rt_device_t)i2c_bus);
183         return -1;
184     }
185     rt_thread_startup(tid);
186     return 0;
187 }
188 
touch_init_thread_entry(void * parameter)189 static void touch_init_thread_entry(void *parameter)
190 {
191     rt_touch_thread_init();
192 }
193 
touc_bg_init(void)194 static int touc_bg_init(void)
195 {
196     rt_thread_t tid = RT_NULL;
197     tid = rt_thread_create("touchi", touch_init_thread_entry, RT_NULL, 2048, 28, 20);
198     if (tid == RT_NULL)
199     {
200         return -1;
201     }
202     rt_thread_startup(tid);
203     return 0;
204 }
205 INIT_APP_EXPORT(touc_bg_init);
206 
207 #endif
208