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 = ®
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