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