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 * 2017-08-08 Yang the first version
9 * 2019-04-23 WillianChan porting to ft6206
10 * 2021-12-28 xiangxistu copy by stm32f429-atk-apollo
11 * 2021-04-23 xiangxistu porting to GT9147
12 */
13
14 #include <rtthread.h>
15 #include <rthw.h>
16 #include <rtdevice.h>
17 #include "drv_touch.h"
18
19 #include <stdint.h>
20 #include <string.h>
21
22 #ifdef BSP_USING_TOUCH_CAP
23
24 #define DBG_ENABLE
25 #define DBG_SECTION_NAME "TOUCH.ft"
26 #define DBG_LEVEL TOUCH_DBG_LEVEL
27 #define DBG_COLOR
28 #include <rtdbg.h>
29
30 static struct rt_i2c_bus_device *ft_i2c_bus;
31 static struct touch_drivers ft_driver;
32
ft_read(struct rt_i2c_bus_device * i2c_bus,rt_uint16_t addr,rt_uint8_t * buffer,rt_size_t length)33 static int ft_read(struct rt_i2c_bus_device *i2c_bus, rt_uint16_t addr, rt_uint8_t *buffer, rt_size_t length)
34 {
35 int ret = -1;
36 int retries = 0;
37 rt_uint8_t register_16[3];
38 register_16[0] = addr >> 8;
39 register_16[1] = addr & 0xff;
40
41 struct rt_i2c_msg msgs[] =
42 {
43 {
44 .addr = ft_driver.address,
45 .flags = RT_I2C_WR,
46 .len = 2,
47 .buf = register_16,
48 },
49 {
50 .addr = ft_driver.address,
51 .flags = RT_I2C_RD,
52 .len = length,
53 .buf = buffer,
54 },
55 };
56
57 while (retries < IIC_RETRY_NUM)
58 {
59 ret = rt_i2c_transfer(i2c_bus, msgs, sizeof(msgs)/sizeof(struct rt_i2c_msg));
60 if (ret == 2)break;
61 retries++;
62 }
63
64 if (retries >= IIC_RETRY_NUM)
65 {
66 LOG_E("%s i2c read error: %d", __func__, ret);
67 return -1;
68 }
69
70 return ret;
71 }
72
ft_write(struct rt_i2c_bus_device * i2c_bus,rt_uint16_t addr,rt_uint8_t * buffer,rt_size_t length)73 static void ft_write(struct rt_i2c_bus_device *i2c_bus, rt_uint16_t addr, rt_uint8_t *buffer, rt_size_t length)
74 {
75 rt_uint8_t *send_buffer = rt_malloc(length + 2);
76
77 RT_ASSERT(send_buffer);
78
79 send_buffer[0] = addr >> 8;;
80 send_buffer[1] = addr & 0xff;
81 memcpy(send_buffer + 2, buffer, length);
82
83 struct rt_i2c_msg msgs[] =
84 {
85 {
86 .addr = ft_driver.address,
87 .flags = RT_I2C_WR,
88 .len = length + 2,
89 .buf = send_buffer,
90 }
91 };
92
93 length = rt_i2c_transfer(i2c_bus, msgs, 1);
94 rt_free(send_buffer);
95 send_buffer = RT_NULL;
96 }
97
ft_isr_enable(rt_bool_t enable)98 static void ft_isr_enable(rt_bool_t enable)
99 {
100 rt_pin_irq_enable(BSP_TOUCH_INT_PIN, enable);
101 }
102
ft_touch_isr(void * parameter)103 static void ft_touch_isr(void *parameter)
104 {
105 ft_isr_enable(RT_FALSE);
106 rt_sem_release(ft_driver.isr_sem);
107 }
108
ft_read_point(touch_msg_t msg)109 static rt_err_t ft_read_point(touch_msg_t msg)
110 {
111 int ret = -1;
112 uint8_t state = 0;
113 uint8_t clear_state = 0;
114 static uint8_t s_tp_down = 0;
115 uint8_t point[5];
116 ret = ft_read(ft_i2c_bus, 0X814E, &state, 1);
117 if (ret < 0)
118 {
119 return -RT_ERROR;
120 }
121
122 /* According this state, to get point info */
123 if(state&0X80&&((state&0XF)<6))
124 {
125 clear_state = 0;
126 ft_write(ft_i2c_bus, 0X814E, &clear_state, 1);
127 }
128 else
129 {
130 if (s_tp_down)
131 {
132 s_tp_down = 0;
133 msg->event = TOUCH_EVENT_UP;
134 return RT_EOK;
135 }
136 msg->event = TOUCH_EVENT_NONE;
137 return -RT_ERROR;
138 }
139
140 /* Only support one point */
141 ret = ft_read(ft_i2c_bus, 0X8150, point, 4);
142 if (ret < 0)
143 {
144 return -RT_ERROR;
145 }
146
147 msg->x = (point[1]&0x0F) << 8 | point[0];
148 msg->y = (point[3]&0x0F) << 8 | point[2];
149 LOG_D("x:%03d, y:%03d", msg->x, msg->y);
150
151 if (s_tp_down)
152 {
153 msg->event = TOUCH_EVENT_MOVE;
154 return RT_EOK;
155 }
156 msg->event = TOUCH_EVENT_DOWN;
157 s_tp_down = 1;
158
159 return RT_EOK;
160 }
161
ft_init(struct rt_i2c_bus_device * i2c_bus)162 static void ft_init(struct rt_i2c_bus_device *i2c_bus)
163 {
164 if (ft_i2c_bus == RT_NULL)
165 {
166 ft_i2c_bus = i2c_bus;
167 }
168 ft_driver.isr_sem = rt_sem_create("ft", 0, RT_IPC_FLAG_FIFO);
169 RT_ASSERT(ft_driver.isr_sem);
170
171 rt_pin_mode(BSP_TOUCH_INT_PIN, PIN_MODE_INPUT_PULLUP);
172 rt_pin_attach_irq(BSP_TOUCH_INT_PIN, PIN_IRQ_MODE_FALLING, ft_touch_isr, RT_NULL);
173
174 rt_thread_mdelay(200);
175 }
176
ft_deinit(void)177 static void ft_deinit(void)
178 {
179 if (ft_driver.isr_sem)
180 {
181 rt_sem_delete(ft_driver.isr_sem);
182 ft_driver.isr_sem = RT_NULL;
183 }
184 }
185
186 struct touch_ops ft_ops =
187 {
188 ft_isr_enable,
189 ft_read_point,
190 ft_init,
191 ft_deinit,
192 };
193
ft_probe(struct rt_i2c_bus_device * i2c_bus)194 static rt_bool_t ft_probe(struct rt_i2c_bus_device *i2c_bus)
195 {
196 #define TOUCH_CID_SIZE 4
197 int err = 0;
198 uint8_t cid[TOUCH_CID_SIZE + 1] = {0};
199
200 ft_i2c_bus = i2c_bus;
201 /* FT6206 Chip identification register address is 0xA8
202 *
203 * GT9147 -> 0X8140, CID
204 *
205 **/
206 rt_memset(cid, 0, TOUCH_CID_SIZE + 1);
207 err = ft_read(ft_i2c_bus, 0X8140, (uint8_t *)&cid, TOUCH_CID_SIZE);
208 if (err < 0)
209 {
210 LOG_E("%s failed: %d", __func__, err);
211 return RT_FALSE;
212 }
213 LOG_I("touch CID:0x%c%c%c%c", cid[0], cid[1], cid[2], cid[3]);
214
215 /* FT6206 ID Value is 0x11
216 * GT9147 ID will be 0x9147
217 */
218 if(rt_strncmp((char *)cid, "9147", TOUCH_CID_SIZE) == 0x0)
219 {
220 return RT_TRUE;
221 }
222 return RT_FALSE;
223 }
224
ft_driver_register(void)225 int ft_driver_register(void)
226 {
227 /* TouchScreen FT6206 Slave I2C address is 0x54
228 * 0x54 << 1 = 0x2A
229 * 0x5D, 0x14 ------> GT9147
230 */
231 ft_driver.address = 0x14;
232 ft_driver.probe = ft_probe;
233 ft_driver.ops = &ft_ops;
234 ft_driver.user_data = RT_NULL;
235 rt_touch_drivers_register(&ft_driver);
236 return 0;
237 }
238 INIT_DEVICE_EXPORT(ft_driver_register);
239
240 #endif
241