1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2017-08-08 Yang the first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <finsh.h>
14
15 #ifdef RT_USING_RTGUI
16 #include <rtgui/event.h>
17 #include <rtgui/rtgui_server.h>
18 #endif
19
20 #include "board.h"
21
22 #include "fsl_iocon.h"
23 #include "fsl_gpio.h"
24 #include "fsl_i2c.h"
25 #include "fsl_gint.h"
26
27 #define LCD_WIDTH 480
28 #define LCD_HEIGHT 272
29 #define BSP_TOUCH_SAMPLE_HZ 30
30
31 #define I2CBUS_NAME "i2c2"
32
33 #if 0
34 #define FTDEBUG rt_kprintf
35 #else
36 #define FTDEBUG(...)
37 #endif
38
39 #define TOUCH_SLP_TIME (RT_TICK_PER_SECOND * 5)
40
41 #define FT5206_TS_ADDR 0x38
42 #define TP_MAX_TOUCH_POINT 2
43
44 enum ft5x0x_ts_regs
45 {
46 FT5X0X_REG_THGROUP = 0x80,
47 FT5X0X_REG_THPEAK = 0x81,
48 FT5X0X_REG_THCAL = 0x82,
49 FT5X0X_REG_THWATER = 0x83,
50 FT5X0X_REG_THTEMP = 0x84,
51 FT5X0X_REG_THDIFF = 0x85,
52 FT5X0X_REG_CTRL = 0x86,
53 FT5X0X_REG_TIMEENTERMONITOR = 0x87,
54 FT5X0X_REG_PERIODACTIVE = 0x88,
55 FT5X0X_REG_PERIODMONITOR = 0x89,
56 FT5X0X_REG_HEIGHT_B = 0x8a,
57 FT5X0X_REG_MAX_FRAME = 0x8b,
58 FT5X0X_REG_DIST_MOVE = 0x8c,
59 FT5X0X_REG_DIST_POINT = 0x8d,
60 FT5X0X_REG_FEG_FRAME = 0x8e,
61 FT5X0X_REG_SINGLE_CLICK_OFFSET = 0x8f,
62 FT5X0X_REG_DOUBLE_CLICK_TIME_MIN = 0x90,
63 FT5X0X_REG_SINGLE_CLICK_TIME = 0x91,
64 FT5X0X_REG_LEFT_RIGHT_OFFSET = 0x92,
65 FT5X0X_REG_UP_DOWN_OFFSET = 0x93,
66 FT5X0X_REG_DISTANCE_LEFT_RIGHT = 0x94,
67 FT5X0X_REG_DISTANCE_UP_DOWN = 0x95,
68 FT5X0X_REG_ZOOM_DIS_SQR = 0x96,
69 FT5X0X_REG_RADIAN_VALUE = 0x97,
70 FT5X0X_REG_MAX_X_HIGH = 0x98,
71 FT5X0X_REG_MAX_X_LOW = 0x99,
72 FT5X0X_REG_MAX_Y_HIGH = 0x9a,
73 FT5X0X_REG_MAX_Y_LOW = 0x9b,
74 FT5X0X_REG_K_X_HIGH = 0x9c,
75 FT5X0X_REG_K_X_LOW = 0x9d,
76 FT5X0X_REG_K_Y_HIGH = 0x9e,
77 FT5X0X_REG_K_Y_LOW = 0x9f,
78 FT5X0X_REG_AUTO_CLB_MODE = 0xa0,
79 FT5X0X_REG_LIB_VERSION_H = 0xa1,
80 FT5X0X_REG_LIB_VERSION_L = 0xa2,
81 FT5X0X_REG_CIPHER = 0xa3,
82 FT5X0X_REG_G_MODE = 0xa4,
83 FT5X0X_REG_PMODE = 0xa5, /* Power Consume Mode */
84 FT5X0X_REG_FIRMID = 0xa6,
85 FT5X0X_REG_STATE = 0xa7,
86 FT5X0X_REG_VENDID = 0xa8,
87 FT5X0X_REG_ERR = 0xa9,
88 FT5X0X_REG_CLB = 0xaa,
89 };
90
91 #define CTRL_NOAUTO_MONITOR 0x00
92 #define CTRL_AUTO_MONITOR 0x01
93
94 #define PMODE_ACTIVE 0x00
95 #define PMODE_MONITOR 0x01
96 #define PMODE_STANDBY 0x02
97 #define PMODE_HIBERNATE 0x03
98
99 #define G_MODE_POLLING 0x00
100 #define G_MODE_TRIGGER 0x01
101
102 typedef enum _touch_event
103 {
104 kTouch_Down = 0, /*!< The state changed to touched. */
105 kTouch_Up = 1, /*!< The state changed to not touched. */
106 kTouch_Contact = 2, /*!< There is a continuous touch being detected. */
107 kTouch_Reserved = 3 /*!< No touch information available. */
108 } touch_event_t;
109
110 typedef struct _touch_point
111 {
112 touch_event_t TOUCH_EVENT; /*!< Indicates the state or event of the touch point. */
113 uint8_t TOUCH_ID; /*!< Id of the touch point. This numeric value stays constant between down and up event. */
114 uint16_t TOUCH_X; /*!< X coordinate of the touch point */
115 uint16_t TOUCH_Y; /*!< Y coordinate of the touch point */
116 } touch_point_t;
117
118 typedef struct _ft5406_touch_point
119 {
120 uint8_t XH;
121 uint8_t XL;
122 uint8_t YH;
123 uint8_t YL;
124 uint8_t RESERVED[2];
125 } ft5406_touch_point_t;
126
127 typedef struct _ft5406_touch_data
128 {
129 uint8_t GEST_ID;
130 uint8_t TD_STATUS;
131 ft5406_touch_point_t TOUCH;
132 } ft5406_touch_data_t;
133
134 #define TOUCH_POINT_GET_EVENT(T) ((touch_event_t)((T).XH >> 6))
135 #define TOUCH_POINT_GET_ID(T) ((T).YH >> 4)
136 #define TOUCH_POINT_GET_X(T) ((((T).XH & 0x0f) << 8) | (T).XL)
137 #define TOUCH_POINT_GET_Y(T) ((((T).YH & 0x0f) << 8) | (T).YL)
138
139 static struct rt_i2c_bus_device *_i2c_bus;
140 static struct rt_semaphore _tp_sem;
141
_ft5406_read(unsigned char cmd,void * buf,size_t len)142 static int _ft5406_read(unsigned char cmd,
143 void *buf,
144 size_t len)
145 {
146 struct rt_i2c_msg msgs[2];
147
148 msgs[0].addr = FT5206_TS_ADDR;
149 msgs[0].flags = RT_I2C_WR;
150 msgs[0].buf = &cmd;
151 msgs[0].len = sizeof(cmd);
152
153 msgs[1].addr = FT5206_TS_ADDR;
154 msgs[1].flags = RT_I2C_RD;
155 msgs[1].buf = buf;
156 msgs[1].len = len;
157
158 if (rt_i2c_transfer(_i2c_bus, msgs, 2) == 2)
159 return len;
160 else
161 return -1;
162 }
163
ft5406_read_touch(touch_point_t * dp)164 static int ft5406_read_touch(touch_point_t *dp)
165 {
166 ft5406_touch_data_t touch_data;
167
168 _ft5406_read(0, &touch_data, sizeof(ft5406_touch_data_t));
169
170 dp->TOUCH_X = TOUCH_POINT_GET_Y(touch_data.TOUCH);
171 dp->TOUCH_Y = TOUCH_POINT_GET_X(touch_data.TOUCH);
172
173 FTDEBUG(" ==> status : %d (%d, %d)\n", touch_data.TD_STATUS, dp->TOUCH_X, dp->TOUCH_Y);
174
175 if (touch_data.TD_STATUS != 0)
176 return 0;
177 else
178 return -1;
179 }
180
_touch_session()181 static void _touch_session()
182 {
183 touch_point_t tpd;
184 #ifdef RT_USING_RTGUI
185 struct rtgui_event_mouse emouse;
186 #endif
187
188 ft5406_read_touch(&tpd);
189
190 #ifdef RT_USING_RTGUI
191 emouse.parent.sender = RT_NULL;
192 emouse.wid = RT_NULL;
193
194 emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
195 emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
196 emouse.x = tpd.TOUCH_X;
197 emouse.y = tpd.TOUCH_Y;
198 emouse.ts = rt_tick_get();
199 emouse.id = emouse.ts;
200 if (emouse.id == 0) emouse.id = 1;
201 rtgui_server_post_event(&emouse.parent, sizeof(emouse));
202 #endif
203
204 do
205 {
206 rt_thread_delay(RT_TICK_PER_SECOND / BSP_TOUCH_SAMPLE_HZ);
207 if (ft5406_read_touch(&tpd) != 0)
208 break;
209
210 #ifdef RT_USING_RTGUI
211 emouse.parent.type = RTGUI_EVENT_MOUSE_MOTION;
212 emouse.x = tpd.TOUCH_X;
213 emouse.y = tpd.TOUCH_Y;
214 emouse.ts = rt_tick_get();
215 rtgui_server_post_event(&emouse.parent, sizeof(emouse));
216 #endif
217 }
218 while (1);
219
220 #ifdef RT_USING_RTGUI
221 /* Always send touch up event. */
222 emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
223 emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_UP;
224 emouse.x = tpd.TOUCH_X;
225 emouse.y = tpd.TOUCH_Y;
226 emouse.ts = rt_tick_get();
227 rtgui_server_post_event(&emouse.parent, sizeof(emouse));
228 #endif
229
230 //} while (rt_sem_take(&_tp_sem, TOUCH_SLP_TIME) == RT_EOK);
231 }
232
touch_down(void)233 void touch_down(void)
234 {
235 rt_sem_release(&_tp_sem);
236 }
237
_touch(void * p)238 static void _touch(void *p)
239 {
240 int io_s;
241
242 gpio_pin_config_t pin_config =
243 {
244 kGPIO_DigitalInput, 0,
245 };
246
247 CLOCK_EnableClock(kCLOCK_Gpio4);
248
249 /* Enable touch panel controller */
250 GPIO_PinInit(GPIO, 4, 0, &pin_config);
251
252 while(1)
253 {
254 rt_thread_delay(RT_TICK_PER_SECOND / 60);
255
256 io_s = GPIO_ReadPinInput(GPIO, 4, 0);
257 if (io_s == 0)
258 {
259 _touch_session();
260 }
261 else
262 continue;
263 }
264 }
265
ft5406_hw_init(void)266 int ft5406_hw_init(void)
267 {
268 rt_thread_t tid;
269 rt_device_t dev;
270
271 dev = rt_device_find(I2CBUS_NAME);
272 if (!dev) return -1;
273
274 if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
275 return -1;
276
277 FTDEBUG("ft5406 set i2c bus to %s\n", I2CBUS_NAME);
278 _i2c_bus = (struct rt_i2c_bus_device *)dev;
279
280 {
281 gpio_pin_config_t pin_config =
282 {
283 kGPIO_DigitalOutput, 0,
284 };
285
286 CLOCK_EnableClock(kCLOCK_Gpio2);
287
288 /* Enable touch panel controller */
289 GPIO_PinInit(GPIO, 2, 27, &pin_config);
290 GPIO_WritePinOutput(GPIO, 2, 27, 1);
291 rt_thread_delay(50);
292 GPIO_WritePinOutput(GPIO, 2, 27, 0);
293 rt_thread_delay(50);
294 GPIO_WritePinOutput(GPIO, 2, 27, 1);
295 }
296
297 rt_sem_init(&_tp_sem, "touch", 0, RT_IPC_FLAG_FIFO);
298 tid = rt_thread_create("touch", _touch, RT_NULL,
299 2048, 10, 20);
300 if (!tid)
301 {
302 rt_device_close(dev);
303 return -1;
304 }
305
306 rt_thread_startup(tid);
307
308 return 0;
309 }
310 INIT_APP_EXPORT(ft5406_hw_init);
311