1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019, 2024 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_common.h"
10 #include "fsl_ft6x06.h"
11
12 typedef struct _ft6x06_touch_point
13 {
14 uint8_t XH;
15 uint8_t XL;
16 uint8_t YH;
17 uint8_t YL;
18 uint8_t WEIGHT;
19 uint8_t MISC;
20 } ft6x06_touch_point_t;
21
22 typedef struct _ft6x06_touch_data
23 {
24 uint8_t GEST_ID;
25 uint8_t TD_STATUS;
26 ft6x06_touch_point_t TOUCH[FT6X06_MAX_TOUCHES];
27 } ft6x06_touch_data_t;
28
29 #define TOUCH_POINT_GET_EVENT(T) ((touch_event_t)((T).XH >> 6))
30 #define TOUCH_POINT_GET_ID(T) ((T).YH >> 4)
31 #define TOUCH_POINT_GET_X(T) ((((T).XH & 0x0f) << 8) | (T).XL)
32 #define TOUCH_POINT_GET_Y(T) ((((T).YH & 0x0f) << 8) | (T).YL)
33
34 #if FT6X06_USE_CMSIS_DRIVER
FT6X06_EventHandler(ft6x06_handle_t * handle,uint32_t i2c_event)35 void FT6X06_EventHandler(ft6x06_handle_t *handle, uint32_t i2c_event)
36 {
37 handle->i2c_event = i2c_event;
38 handle->i2c_event_received = true;
39 }
40
FT_6X06_WaitEvent(ft6x06_handle_t * handle)41 static uint32_t FT_6X06_WaitEvent(ft6x06_handle_t *handle)
42 {
43 uint32_t i2c_event;
44
45 while (!(handle->i2c_event_received))
46 ;
47
48 i2c_event = handle->i2c_event;
49 handle->i2c_event_received = false;
50
51 return i2c_event;
52 }
53 #endif /* FT6X06_USE_CMSIS_DRIVER */
54
55 #if (FT6X06_USE_CMSIS_DRIVER)
FT6X06_Init(ft6x06_handle_t * handle,ARM_DRIVER_I2C * i2c_driver)56 status_t FT6X06_Init(ft6x06_handle_t *handle, ARM_DRIVER_I2C *i2c_driver)
57 {
58 status_t status = kStatus_Success;
59 uint8_t i2c_buf[2];
60
61 assert(handle);
62 assert(i2c_driver);
63
64 if (!handle || !i2c_driver)
65 {
66 return kStatus_InvalidArgument;
67 }
68
69 handle->i2c_driver = i2c_driver;
70
71 /* clear transfer structure and buffer */
72 memset(handle->touch_buf, 0, FT6X06_TOUCH_DATA_LEN);
73
74 /* set device mode to normal operation */
75 i2c_buf[0] = 0; /* mode register address */
76 i2c_buf[1] = 0; /* normal operation mode */
77
78 if (handle->i2c_driver->MasterTransmit(FT6X06_I2C_ADDRESS, i2c_buf, 2, false) != ARM_DRIVER_OK)
79 {
80 status = kStatus_Fail;
81 }
82 else if (FT_6X06_WaitEvent(handle) != ARM_I2C_EVENT_TRANSFER_DONE)
83 {
84 status = kStatus_Fail;
85 }
86
87 return status;
88 }
89 #else /* !FT6X06_USE_CMSIS_DRIVER */
FT6X06_Init(ft6x06_handle_t * handle,const ft6x06_config_t * config)90 status_t FT6X06_Init(ft6x06_handle_t *handle, const ft6x06_config_t *config)
91 {
92 assert(handle != NULL);
93
94 handle->I2C_SendFunc = config->I2C_SendFunc;
95 handle->I2C_ReceiveFunc = config->I2C_ReceiveFunc;
96 /* clear transfer structure and buffer */
97 memset(handle->touch_buf, 0, FT6X06_TOUCH_DATA_LEN);
98
99 /* set device mode to normal operation */
100 return handle->I2C_SendFunc(FT6X06_I2C_ADDRESS, 0, 1, (const uint8_t[]){0U}, 1);
101 }
102 #endif /* FT6X06_USE_CMSIS_DRIVER */
103
FT6X06_Denit(ft6x06_handle_t * handle)104 status_t FT6X06_Denit(ft6x06_handle_t *handle)
105 {
106 assert(handle);
107
108 if (!handle)
109 {
110 return kStatus_InvalidArgument;
111 }
112
113 #if FT6X06_USE_CMSIS_DRIVER
114 handle->i2c_driver = NULL;
115 #endif /* FT6X06_USE_CMSIS_DRIVER */
116 return kStatus_Success;
117 }
118
119 #if FT6X06_USE_CMSIS_DRIVER
FT6X06_ReadTouchData(ft6x06_handle_t * handle)120 status_t FT6X06_ReadTouchData(ft6x06_handle_t *handle)
121 {
122 status_t status = kStatus_Success;
123 uint8_t i2c_buf[1];
124
125 assert(handle);
126
127 if (!handle || !(handle->i2c_driver))
128 {
129 return kStatus_InvalidArgument;
130 }
131
132 i2c_buf[0] = F6X06_TOUCH_DATA_SUBADDR;
133
134 if (handle->i2c_driver->MasterTransmit(FT6X06_I2C_ADDRESS, i2c_buf, 1, true) != ARM_DRIVER_OK)
135 {
136 status = kStatus_Fail;
137 }
138 else if (FT_6X06_WaitEvent(handle) != ARM_I2C_EVENT_TRANSFER_DONE)
139 {
140 status = kStatus_Fail;
141 }
142 else if (handle->i2c_driver->MasterReceive(FT6X06_I2C_ADDRESS, handle->touch_buf, FT6X06_TOUCH_DATA_LEN, false) !=
143 ARM_DRIVER_OK)
144 {
145 status = kStatus_Fail;
146 }
147 else if (FT_6X06_WaitEvent(handle) != ARM_I2C_EVENT_TRANSFER_DONE)
148 {
149 status = kStatus_Fail;
150 }
151
152 return status;
153 }
154 #else /* !FT6X06_USE_CMSIS_DRIVER */
FT6X06_ReadTouchData(ft6x06_handle_t * handle)155 status_t FT6X06_ReadTouchData(ft6x06_handle_t *handle)
156 {
157 return handle->I2C_ReceiveFunc(FT6X06_I2C_ADDRESS, F6X06_TOUCH_DATA_SUBADDR, 1, handle->touch_buf,
158 FT6X06_TOUCH_DATA_LEN);
159 }
160 #endif /* FT6X06_USE_CMSIS_DRIVER */
161
FT6X06_GetSingleTouch(ft6x06_handle_t * handle,touch_event_t * touch_event,int * touch_x,int * touch_y)162 status_t FT6X06_GetSingleTouch(ft6x06_handle_t *handle, touch_event_t *touch_event, int *touch_x, int *touch_y)
163 {
164 status_t status;
165 touch_event_t touch_event_local;
166
167 status = FT6X06_ReadTouchData(handle);
168
169 if (status == kStatus_Success)
170 {
171 ft6x06_touch_data_t *touch_data = (ft6x06_touch_data_t *)(void *)(handle->touch_buf);
172
173 if (touch_event == NULL)
174 {
175 touch_event = &touch_event_local;
176 }
177 *touch_event = TOUCH_POINT_GET_EVENT(touch_data->TOUCH[0]);
178
179 /* Update coordinates only if there is touch detected */
180 if ((*touch_event == kTouch_Down) || (*touch_event == kTouch_Contact))
181 {
182 if (touch_x)
183 {
184 *touch_x = TOUCH_POINT_GET_X(touch_data->TOUCH[0]);
185 }
186 if (touch_y)
187 {
188 *touch_y = TOUCH_POINT_GET_Y(touch_data->TOUCH[0]);
189 }
190 }
191 }
192
193 return status;
194 }
195
FT6X06_GetMultiTouch(ft6x06_handle_t * handle,int * touch_count,touch_point_t touch_array[FT6X06_MAX_TOUCHES])196 status_t FT6X06_GetMultiTouch(ft6x06_handle_t *handle, int *touch_count, touch_point_t touch_array[FT6X06_MAX_TOUCHES])
197 {
198 status_t status;
199
200 status = FT6X06_ReadTouchData(handle);
201
202 if (status == kStatus_Success)
203 {
204 ft6x06_touch_data_t *touch_data = (ft6x06_touch_data_t *)(void *)(handle->touch_buf);
205 int i;
206
207 /* check for valid number of touches - otherwise ignore touch information...
208 workaround added msy */
209 if (touch_data->TD_STATUS > FT6X06_MAX_TOUCHES)
210 touch_data->TD_STATUS = 0;
211
212 /* Decode number of touches */
213 if (touch_count)
214 {
215 *touch_count = touch_data->TD_STATUS;
216 }
217
218 /* Decode valid touch points */
219 for (i = 0; i < touch_data->TD_STATUS; i++)
220 {
221 touch_array[i].TOUCH_ID = TOUCH_POINT_GET_ID(touch_data->TOUCH[i]);
222 touch_array[i].TOUCH_EVENT = TOUCH_POINT_GET_EVENT(touch_data->TOUCH[i]);
223 touch_array[i].TOUCH_X = TOUCH_POINT_GET_X(touch_data->TOUCH[i]);
224 touch_array[i].TOUCH_Y = TOUCH_POINT_GET_Y(touch_data->TOUCH[i]);
225 }
226
227 /* Clear vacant elements of touch_array */
228 for (; i < FT6X06_MAX_TOUCHES; i++)
229 {
230 touch_array[i].TOUCH_ID = 0;
231 touch_array[i].TOUCH_EVENT = kTouch_Reserved;
232 touch_array[i].TOUCH_X = 0;
233 touch_array[i].TOUCH_Y = 0;
234 }
235 }
236
237 return status;
238 }
239