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  * 2022-04-11     Wayne        First version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 
14 #include <string.h>
15 
16 #define DBG_TAG "ft5446"
17 #define DBG_LVL DBG_INFO
18 #include <rtdbg.h>
19 
20 #include "ft5446.h"
21 
22 static struct rt_i2c_client ft5446_client;
23 static void ft5446_touch_up(void *buf, rt_int8_t id);
ft5446_write_reg(struct rt_i2c_client * dev,rt_uint8_t reg,rt_uint8_t value)24 static rt_err_t ft5446_write_reg(struct rt_i2c_client *dev, rt_uint8_t reg, rt_uint8_t value)
25 {
26     struct rt_i2c_msg msgs;
27     rt_uint8_t buf[2];
28 
29     buf[0] = reg;
30     buf[1] = value;
31 
32     msgs.addr  = dev->client_addr;
33     msgs.flags = RT_I2C_WR;
34     msgs.buf   = buf;
35     msgs.len   = sizeof(buf);
36 
37     if (rt_i2c_transfer(dev->bus, &msgs, 1) == 1)
38     {
39         return RT_EOK;
40     }
41     else
42     {
43         return -RT_ERROR;
44     }
45 }
46 
ft5446_read_reg(struct rt_i2c_client * dev,rt_uint8_t reg,rt_uint8_t * data,rt_uint8_t len)47 static rt_err_t ft5446_read_reg(struct rt_i2c_client *dev, rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t len)
48 {
49     struct rt_i2c_msg msgs[2];
50 
51     msgs[0].addr  = dev->client_addr;
52     msgs[0].flags = RT_I2C_WR;
53     msgs[0].buf   = &reg;
54     msgs[0].len   = FT_REGITER_LEN;
55 
56     msgs[1].addr  = dev->client_addr;
57     msgs[1].flags = RT_I2C_RD;
58     msgs[1].buf   = data;
59     msgs[1].len   = len;
60 
61     if (rt_i2c_transfer(dev->bus, msgs, 2) == 2)
62     {
63         return RT_EOK;
64     }
65     else
66     {
67         return -RT_ERROR;
68     }
69 }
70 
71 static rt_int16_t pre_x[FT_MAX_TOUCH];
72 static rt_int16_t pre_y[FT_MAX_TOUCH];
73 static rt_int16_t pre_w[FT_MAX_TOUCH];
74 static rt_uint8_t s_tp_dowm[FT_MAX_TOUCH];
75 
ft5446_touch_up(void * buf,rt_int8_t id)76 static void ft5446_touch_up(void *buf, rt_int8_t id)
77 {
78     struct rt_touch_data *read_data = (struct rt_touch_data *)buf;
79 
80     if (s_tp_dowm[id] == 1)
81     {
82         s_tp_dowm[id] = 0;
83         read_data[id].event = RT_TOUCH_EVENT_UP;
84     }
85     else
86     {
87         read_data[id].event = RT_TOUCH_EVENT_NONE;
88     }
89 
90     read_data[id].timestamp = rt_touch_get_ts();
91     read_data[id].width = pre_w[id];
92     read_data[id].x_coordinate = pre_x[id];
93     read_data[id].y_coordinate = pre_y[id];
94     read_data[id].track_id = id;
95 
96     pre_x[id] = -1;  /* last point is none */
97     pre_y[id] = -1;
98     pre_w[id] = -1;
99 
100     //LOG_I("%s (%d)\n", __func__, id);
101 }
102 
ft5446_touch_down(void * buf,rt_int8_t id,rt_int16_t x,rt_int16_t y,rt_int16_t w)103 static void ft5446_touch_down(void *buf, rt_int8_t id, rt_int16_t x, rt_int16_t y, rt_int16_t w)
104 {
105     struct rt_touch_data *read_data = (struct rt_touch_data *)buf;
106 
107     if (s_tp_dowm[id] == 1)
108     {
109         read_data[id].event = RT_TOUCH_EVENT_MOVE;
110 
111     }
112     else
113     {
114         read_data[id].event = RT_TOUCH_EVENT_DOWN;
115         s_tp_dowm[id] = 1;
116     }
117 
118     read_data[id].timestamp = rt_touch_get_ts();
119     read_data[id].width = w;
120     read_data[id].x_coordinate = x;
121     read_data[id].y_coordinate = y;
122     read_data[id].track_id = id;
123 
124     pre_x[id] = x; /* save last point */
125     pre_y[id] = y;
126     pre_w[id] = w;
127 
128     //LOG_I("%s (%d %d %d %d)\n", __func__, id, x, y, w );
129 }
130 
131 static int8_t pre_id[FT_MAX_TOUCH];
132 static S_FT_REGMAP sFtRegMap;
133 static rt_uint8_t pre_touch = 0;
134 
ft5446_read_point(struct rt_touch_device * touch,void * buf,rt_size_t read_num)135 static rt_ssize_t ft5446_read_point(struct rt_touch_device *touch, void *buf, rt_size_t read_num)
136 {
137     int i;
138 
139     rt_err_t error = 0;
140     rt_int32_t   touch_event, touchid;
141 
142     RT_ASSERT(touch);
143     RT_ASSERT(buf);
144     RT_ASSERT(read_num != 0);
145     RT_ASSERT(read_num <= FT_MAX_TOUCH);
146 
147     error = ft5446_read_reg(&ft5446_client, 0, (rt_uint8_t *)&sFtRegMap, sizeof(sFtRegMap));
148     if (error)
149     {
150         LOG_E("get touch data failed, err:%d\n", error);
151         goto exit_read_point;
152     }
153 
154     if (sFtRegMap.u8TDStatus > FT_MAX_TOUCH)
155     {
156         LOG_E("FW report max point:%d > panel info. max:%d\n", sFtRegMap.u8TDStatus, FT_MAX_TOUCH);
157         goto exit_read_point;
158     }
159 
160     if (pre_touch > sFtRegMap.u8TDStatus)               /* point up */
161     {
162         for (i = 0; i < FT_MAX_TOUCH; i++)
163         {
164             rt_uint8_t j;
165             for (j = 0; j < sFtRegMap.u8TDStatus; j++)  /* this time touch num */
166             {
167                 touchid = sFtRegMap.m_sTP[j].u8TouchID;
168                 if (touchid >= 0x0f)
169                     continue;
170 
171                 if (pre_id[i] == touchid)                /* this id is not free */
172                     break;
173             }
174 
175             if ((j == sFtRegMap.u8TDStatus) && (pre_id[i] != -1))         /* free this node */
176             {
177                 // LOG_I("free %d tid=%d\n", i, pre_id[i]);
178                 ft5446_touch_up(buf, pre_id[i]);
179                 pre_id[i] = -1;
180             }
181         }
182     }
183 
184     for (i = 0; i < sFtRegMap.u8TDStatus; i++)
185     {
186         touch_event = sFtRegMap.m_sTP[i].u8EvtFlag;
187         touchid = sFtRegMap.m_sTP[i].u8TouchID;
188 
189         //LOG_I("(%d/%d) %d %d\n", i, sFtRegMap.u8TDStatus, touchid, touch_event );
190 
191         if (touchid >= 0x0f)
192             continue;
193 
194         pre_id[i] = touchid;
195 
196         if ((touch_event == FT_EVENTFLAG_PRESS_DOWN) || (touch_event == FT_EVENTFLAG_CONTACT))
197         {
198             rt_uint16_t  x, y, w;
199 
200             x = ((uint16_t)sFtRegMap.m_sTP[i].u8X_11_8 << 8) |  sFtRegMap.m_sTP[i].u8X_7_0;
201             y = ((uint16_t)sFtRegMap.m_sTP[i].u8Y_11_8 << 8) |  sFtRegMap.m_sTP[i].u8Y_7_0;
202             w = sFtRegMap.m_sTP[i].m_u8Weight;
203 
204             //LOG_I("[%d] (%d %d %d %d)\n", touch_event, touchid, x, y, w );
205 
206             if (x >= touch->info.range_x || y >= touch->info.range_y)
207             {
208                 LOG_E("invalid position, X[%d,%u,%d], Y[%d,%u,%d]\n",
209                       0, x, touch->info.range_x,
210                       0, y, touch->info.range_y);
211                 continue;
212             }
213 
214             ft5446_touch_down(buf, touchid, x, y, w);
215         }
216         else
217         {
218             // Up
219             ft5446_touch_up(buf, touchid);
220         }
221 
222     } // for (i = 0; i < sFtRegMap.u8TDStatus; i++)
223 
224     pre_touch = sFtRegMap.u8TDStatus;
225 
226     return read_num;
227 
228 exit_read_point:
229 
230     pre_touch = 0;
231 
232     return 0;
233 }
234 
ft5446_control(struct rt_touch_device * touch,int cmd,void * arg)235 static rt_err_t ft5446_control(struct rt_touch_device *touch, int cmd, void *arg)
236 {
237     switch (cmd)
238     {
239     case RT_TOUCH_CTRL_GET_INFO:
240     {
241         struct rt_touch_info *info = (struct rt_touch_info *)arg;
242         RT_ASSERT(arg);
243 
244         rt_memcpy(info, &touch->info, sizeof(struct rt_touch_info));
245         break;
246     }
247     case RT_TOUCH_CTRL_GET_ID:
248         break;
249     case RT_TOUCH_CTRL_SET_X_RANGE:
250         break;
251     case RT_TOUCH_CTRL_SET_Y_RANGE:
252         break;
253     case RT_TOUCH_CTRL_SET_X_TO_Y:
254         break;
255     case RT_TOUCH_CTRL_SET_MODE:
256         break;
257     default:
258         break;
259     }
260     return RT_EOK;
261 }
262 
263 static struct rt_touch_ops ft5446_touch_ops =
264 {
265     .touch_readpoint = ft5446_read_point,
266     .touch_control = ft5446_control,
267 };
268 
ft5446_init(struct rt_i2c_client * dev)269 static void ft5446_init(struct rt_i2c_client *dev)
270 {
271     ft5446_write_reg(dev, 0x0, 0);
272 }
273 
rt_hw_ft5446_init(const char * name,struct rt_touch_config * cfg)274 int rt_hw_ft5446_init(const char *name, struct rt_touch_config *cfg)
275 {
276     struct rt_touch_device *touch_device = RT_NULL;
277     rt_uint32_t bus_speed = 400000;
278 
279     touch_device = (struct rt_touch_device *)rt_malloc(sizeof(struct rt_touch_device));
280     if (touch_device == RT_NULL)
281     {
282         LOG_E("touch device malloc fail");
283         return -RT_ERROR;
284     }
285     rt_memset((void *)touch_device, 0, sizeof(struct rt_touch_device));
286 
287     /* hw init*/
288     rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT);
289 
290     rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_LOW);
291     rt_thread_delay(5);
292     rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_HIGH);
293     rt_thread_delay(200);
294 
295     rt_pin_mode(cfg->irq_pin.pin, cfg->irq_pin.mode);
296 
297     ft5446_client.bus = (struct rt_i2c_bus_device *)rt_device_find(cfg->dev_name);
298 
299     if (ft5446_client.bus == RT_NULL)
300     {
301         LOG_E("Can't find %s device", cfg->dev_name);
302         return -RT_ERROR;
303     }
304 
305     if (rt_device_open((rt_device_t)ft5446_client.bus, RT_DEVICE_FLAG_RDWR) != RT_EOK)
306     {
307         LOG_E("open %s device failed", cfg->dev_name);
308         return -RT_ERROR;
309     }
310 
311     if (rt_device_control((rt_device_t)ft5446_client.bus, RT_I2C_DEV_CTRL_CLK, &bus_speed) != RT_EOK)
312     {
313         LOG_E("control %s device failed", cfg->dev_name);
314         return -RT_ERROR;
315     }
316 
317     ft5446_client.client_addr = FT5446_ADDRESS;
318 
319     ft5446_init(&ft5446_client);
320 
321     rt_memset(&pre_x[0], 0xff,  FT_MAX_TOUCH * sizeof(rt_int16_t));
322     rt_memset(&pre_y[0], 0xff,  FT_MAX_TOUCH * sizeof(rt_int16_t));
323     rt_memset(&pre_w[0], 0xff,  FT_MAX_TOUCH * sizeof(rt_int16_t));
324     rt_memset(&s_tp_dowm[0], 0, FT_MAX_TOUCH * sizeof(rt_int8_t));
325     rt_memset(&pre_id[0], 0xff,  FT_MAX_TOUCH * sizeof(rt_int8_t));
326 
327     /* register touch device */
328     touch_device->info.type = RT_TOUCH_TYPE_CAPACITANCE;
329     touch_device->info.vendor = RT_TOUCH_VENDOR_FT;
330     touch_device->info.range_x = BSP_LCD_WIDTH;
331     touch_device->info.range_y = BSP_LCD_HEIGHT;
332     touch_device->info.point_num = FT_MAX_TOUCH;
333 
334     rt_memcpy(&touch_device->config, cfg, sizeof(struct rt_touch_config));
335     touch_device->ops = &ft5446_touch_ops;
336 
337     rt_hw_touch_register(touch_device, name, RT_DEVICE_FLAG_INT_RX, RT_NULL);
338 
339     LOG_I("touch device ft5446 init success");
340 
341     return RT_EOK;
342 }
343