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 "st1663i"
17 #define DBG_LVL DBG_INFO
18 #include <rtdbg.h>
19 
20 #include "st1663i.h"
21 
22 static struct rt_i2c_client st1663i_client;
23 static void st1663i_touch_up(void *buf, rt_int8_t id);
st1663i_write_reg(struct rt_i2c_client * dev,rt_uint8_t reg,rt_uint8_t value)24 static rt_err_t st1663i_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 
st1663i_read_reg(struct rt_i2c_client * dev,rt_uint8_t reg,rt_uint8_t * data,rt_uint8_t len)47 static rt_err_t st1663i_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   = ST_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[ST_MAX_TOUCH];
72 static rt_int16_t pre_y[ST_MAX_TOUCH];
73 static rt_int16_t pre_w[ST_MAX_TOUCH];
74 static rt_uint8_t s_tp_dowm[ST_MAX_TOUCH];
75 
st1663i_touch_up(void * buf,rt_int8_t id)76 static void st1663i_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 
st1663i_touch_down(void * buf,rt_int8_t id,rt_int16_t x,rt_int16_t y,rt_int16_t w)103 static void st1663i_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[ST_MAX_TOUCH];
132 static S_ST_REGMAP sStRegMap;
133 static rt_uint8_t pre_touch = 0;
134 
st1663i_read_point(struct rt_touch_device * touch,void * buf,rt_size_t read_num)135 static rt_ssize_t st1663i_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 <= ST_MAX_TOUCH);
146 
147     error = st1663i_read_reg(&st1663i_client, 0x10, (rt_uint8_t *)&sStRegMap, sizeof(sStRegMap));
148     if (error)
149     {
150         LOG_E("get touch data failed, err:%d\n", error);
151         goto exit_read_point;
152     }
153 
154     if (sStRegMap.u8Fingers > ST_MAX_TOUCH)
155     {
156         LOG_E("FW report max point:%d > panel info. max:%d\n", sStRegMap.u8Fingers, ST_MAX_TOUCH);
157         goto exit_read_point;
158     }
159 
160     if (pre_touch > sStRegMap.u8Fingers)               /* point up */
161     {
162         for (i = 0; i < ST_MAX_TOUCH; i++)
163         {
164             rt_uint8_t j;
165             for (j = 0; j < sStRegMap.u8Fingers; j++)  /* this time touch num */
166             {
167                 touchid = i;
168 
169                 if (pre_id[i] == touchid)                /* this id is not free */
170                     break;
171             }
172 
173             if ((j == sStRegMap.u8Fingers) && (pre_id[i] != -1))         /* free this node */
174             {
175                 // LOG_I("free %d tid=%d\n", i, pre_id[i]);
176                 st1663i_touch_up(buf, pre_id[i]);
177                 pre_id[i] = -1;
178             }
179         }
180     }
181 
182     for (i = 0; i < sStRegMap.u8Fingers; i++)
183     {
184         touch_event = sStRegMap.m_sTP[i].u8Valid;
185         touchid = i;
186 
187         //LOG_I("(%d/%d) %d %d\n", i, sStRegMap.u8Fingers, touchid, touch_event);
188 
189         pre_id[i] = touchid;
190 
191         if (touch_event)
192         {
193             rt_uint16_t  x, y, w;
194 
195             x = ((uint16_t)sStRegMap.m_sTP[i].u8X0_H << 8) |  sStRegMap.m_sTP[i].m_u8X0_L;
196             y = ((uint16_t)sStRegMap.m_sTP[i].u8Y0_H << 8) |  sStRegMap.m_sTP[i].m_u8Y0_L;
197             w = sStRegMap.m_sTP[i].m_u8Z;
198 
199             //LOG_I("[%d] (%d %d %d %d)\n", touch_event, touchid, x, y, w);
200 
201             if (x >= touch->info.range_x || y >= touch->info.range_y)
202             {
203                 LOG_E("invalid position, X[%d,%u,%d], Y[%d,%u,%d]\n",
204                       0, x, touch->info.range_x,
205                       0, y, touch->info.range_y);
206                 continue;
207             }
208 
209             st1663i_touch_down(buf, touchid, x, y, w);
210         }
211         else
212         {
213             // Up
214             st1663i_touch_up(buf, touchid);
215         }
216 
217     } // for (i = 0; i < sStRegMap.u8TDStatus; i++)
218 
219     pre_touch = sStRegMap.u8Fingers;
220 
221     return read_num;
222 
223 exit_read_point:
224 
225     pre_touch = 0;
226 
227     return 0;
228 }
229 
st1663i_control(struct rt_touch_device * touch,int cmd,void * arg)230 static rt_err_t st1663i_control(struct rt_touch_device *touch, int cmd, void *arg)
231 {
232     switch (cmd)
233     {
234     case RT_TOUCH_CTRL_GET_INFO:
235     {
236         struct rt_touch_info *info = (struct rt_touch_info *)arg;
237         RT_ASSERT(arg);
238 
239         rt_memcpy(info, &touch->info, sizeof(struct rt_touch_info));
240         break;
241     }
242     case RT_TOUCH_CTRL_GET_ID:
243         break;
244     case RT_TOUCH_CTRL_SET_X_RANGE:
245         break;
246     case RT_TOUCH_CTRL_SET_Y_RANGE:
247         break;
248     case RT_TOUCH_CTRL_SET_X_TO_Y:
249         break;
250     case RT_TOUCH_CTRL_SET_MODE:
251         break;
252     default:
253         break;
254     }
255     return RT_EOK;
256 }
257 
258 static struct rt_touch_ops st1663i_touch_ops =
259 {
260     .touch_readpoint = st1663i_read_point,
261     .touch_control = st1663i_control,
262 };
263 
st1663i_init(struct rt_i2c_client * dev)264 static void st1663i_init(struct rt_i2c_client *dev)
265 {
266     st1663i_write_reg(dev, 0x0, 0);
267 }
268 
rt_hw_st1663i_init(const char * name,struct rt_touch_config * cfg)269 int rt_hw_st1663i_init(const char *name, struct rt_touch_config *cfg)
270 {
271     struct rt_touch_device *touch_device = RT_NULL;
272     rt_uint32_t bus_speed = 400000;
273 
274     touch_device = (struct rt_touch_device *)rt_malloc(sizeof(struct rt_touch_device));
275     if (touch_device == RT_NULL)
276     {
277         LOG_E("touch device malloc fail");
278         return -RT_ERROR;
279     }
280     rt_memset((void *)touch_device, 0, sizeof(struct rt_touch_device));
281 
282     /* hw init*/
283     rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT);
284 
285     rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_LOW);
286     rt_thread_delay(5);
287     rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_HIGH);
288     rt_thread_delay(200);
289 
290     rt_pin_mode(cfg->irq_pin.pin, cfg->irq_pin.mode);
291 
292     st1663i_client.bus = (struct rt_i2c_bus_device *)rt_device_find(cfg->dev_name);
293 
294     if (st1663i_client.bus == RT_NULL)
295     {
296         LOG_E("Can't find %s device", cfg->dev_name);
297         return -RT_ERROR;
298     }
299 
300     if (rt_device_open((rt_device_t)st1663i_client.bus, RT_DEVICE_FLAG_RDWR) != RT_EOK)
301     {
302         LOG_E("open %s device failed", cfg->dev_name);
303         return -RT_ERROR;
304     }
305 
306     if (rt_device_control((rt_device_t)st1663i_client.bus, RT_I2C_DEV_CTRL_CLK, &bus_speed) != RT_EOK)
307     {
308         LOG_E("control %s device failed", cfg->dev_name);
309         return -RT_ERROR;
310     }
311 
312     st1663i_client.client_addr = ST1663I_ADDRESS;
313 
314     st1663i_init(&st1663i_client);
315 
316     rt_memset(&pre_x[0], 0xff,  ST_MAX_TOUCH * sizeof(rt_int16_t));
317     rt_memset(&pre_y[0], 0xff,  ST_MAX_TOUCH * sizeof(rt_int16_t));
318     rt_memset(&pre_w[0], 0xff,  ST_MAX_TOUCH * sizeof(rt_int16_t));
319     rt_memset(&s_tp_dowm[0], 0, ST_MAX_TOUCH * sizeof(rt_int8_t));
320     rt_memset(&pre_id[0], 0xff,  ST_MAX_TOUCH * sizeof(rt_int8_t));
321 
322     /* register touch device */
323     touch_device->info.type = RT_TOUCH_TYPE_CAPACITANCE;
324     touch_device->info.vendor = RT_TOUCH_VENDOR_UNKNOWN;
325     touch_device->info.range_x = BSP_LCD_WIDTH;
326     touch_device->info.range_y = BSP_LCD_HEIGHT;
327     touch_device->info.point_num = ST_MAX_TOUCH;
328 
329     rt_memcpy(&touch_device->config, cfg, sizeof(struct rt_touch_config));
330     touch_device->ops = &st1663i_touch_ops;
331 
332     rt_hw_touch_register(touch_device, name, RT_DEVICE_FLAG_INT_RX, RT_NULL);
333 
334     LOG_I("touch device st1663i init success");
335 
336     return RT_EOK;
337 }
338