1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019 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
FT6X06_EventHandler(ft6x06_handle_t * handle,uint32_t i2c_event)34 void FT6X06_EventHandler(ft6x06_handle_t *handle, uint32_t i2c_event)
35 {
36 handle->i2c_event = i2c_event;
37 handle->i2c_event_received = true;
38 }
39
FT_6X06_WaitEvent(ft6x06_handle_t * handle)40 static uint32_t FT_6X06_WaitEvent(ft6x06_handle_t *handle)
41 {
42 uint32_t i2c_event;
43
44 while (!(handle->i2c_event_received))
45 ;
46
47 i2c_event = handle->i2c_event;
48 handle->i2c_event_received = false;
49
50 return i2c_event;
51 }
52
FT6X06_Init(ft6x06_handle_t * handle,ARM_DRIVER_I2C * i2c_driver)53 status_t FT6X06_Init(ft6x06_handle_t *handle, ARM_DRIVER_I2C *i2c_driver)
54 {
55 status_t status = kStatus_Success;
56 uint8_t i2c_buf[2];
57
58 assert(handle);
59 assert(i2c_driver);
60
61 if (!handle || !i2c_driver)
62 {
63 return kStatus_InvalidArgument;
64 }
65
66 handle->i2c_driver = i2c_driver;
67
68 /* clear transfer structure and buffer */
69 memset(handle->touch_buf, 0, FT6X06_TOUCH_DATA_LEN);
70
71 /* set device mode to normal operation */
72 i2c_buf[0] = 0; /* mode register address */
73 i2c_buf[1] = 0; /* normal operation mode */
74
75 if (handle->i2c_driver->MasterTransmit(FT6X06_I2C_ADDRESS, i2c_buf, 2, false) != ARM_DRIVER_OK)
76 {
77 status = kStatus_Fail;
78 }
79 else if (FT_6X06_WaitEvent(handle) != ARM_I2C_EVENT_TRANSFER_DONE)
80 {
81 status = kStatus_Fail;
82 }
83
84 return status;
85 }
86
FT6X06_Denit(ft6x06_handle_t * handle)87 status_t FT6X06_Denit(ft6x06_handle_t *handle)
88 {
89 assert(handle);
90
91 if (!handle)
92 {
93 return kStatus_InvalidArgument;
94 }
95
96 handle->i2c_driver = NULL;
97 return kStatus_Success;
98 }
99
FT6X06_ReadTouchData(ft6x06_handle_t * handle)100 status_t FT6X06_ReadTouchData(ft6x06_handle_t *handle)
101 {
102 status_t status = kStatus_Success;
103 uint8_t i2c_buf[1];
104
105 assert(handle);
106
107 if (!handle || !(handle->i2c_driver))
108 {
109 return kStatus_InvalidArgument;
110 }
111
112 i2c_buf[0] = F6X06_TOUCH_DATA_SUBADDR;
113
114 if (handle->i2c_driver->MasterTransmit(FT6X06_I2C_ADDRESS, i2c_buf, 1, true) != ARM_DRIVER_OK)
115 {
116 status = kStatus_Fail;
117 }
118 else if (FT_6X06_WaitEvent(handle) != ARM_I2C_EVENT_TRANSFER_DONE)
119 {
120 status = kStatus_Fail;
121 }
122 else if (handle->i2c_driver->MasterReceive(FT6X06_I2C_ADDRESS, handle->touch_buf, FT6X06_TOUCH_DATA_LEN, false) !=
123 ARM_DRIVER_OK)
124 {
125 status = kStatus_Fail;
126 }
127 else if (FT_6X06_WaitEvent(handle) != ARM_I2C_EVENT_TRANSFER_DONE)
128 {
129 status = kStatus_Fail;
130 }
131
132 return status;
133 }
134
FT6X06_GetSingleTouch(ft6x06_handle_t * handle,touch_event_t * touch_event,int * touch_x,int * touch_y)135 status_t FT6X06_GetSingleTouch(ft6x06_handle_t *handle, touch_event_t *touch_event, int *touch_x, int *touch_y)
136 {
137 status_t status;
138 touch_event_t touch_event_local;
139
140 status = FT6X06_ReadTouchData(handle);
141
142 if (status == kStatus_Success)
143 {
144 ft6x06_touch_data_t *touch_data = (ft6x06_touch_data_t *)(void *)(handle->touch_buf);
145
146 if (touch_event == NULL)
147 {
148 touch_event = &touch_event_local;
149 }
150 *touch_event = TOUCH_POINT_GET_EVENT(touch_data->TOUCH[0]);
151
152 /* Update coordinates only if there is touch detected */
153 if ((*touch_event == kTouch_Down) || (*touch_event == kTouch_Contact))
154 {
155 if (touch_x)
156 {
157 *touch_x = TOUCH_POINT_GET_X(touch_data->TOUCH[0]);
158 }
159 if (touch_y)
160 {
161 *touch_y = TOUCH_POINT_GET_Y(touch_data->TOUCH[0]);
162 }
163 }
164 }
165
166 return status;
167 }
168
FT6X06_GetMultiTouch(ft6x06_handle_t * handle,int * touch_count,touch_point_t touch_array[FT6X06_MAX_TOUCHES])169 status_t FT6X06_GetMultiTouch(ft6x06_handle_t *handle, int *touch_count, touch_point_t touch_array[FT6X06_MAX_TOUCHES])
170 {
171 status_t status;
172
173 status = FT6X06_ReadTouchData(handle);
174
175 if (status == kStatus_Success)
176 {
177 ft6x06_touch_data_t *touch_data = (ft6x06_touch_data_t *)(void *)(handle->touch_buf);
178 int i;
179
180 /* check for valid number of touches - otherwise ignore touch information...
181 workaround added msy */
182 if (touch_data->TD_STATUS > FT6X06_MAX_TOUCHES)
183 touch_data->TD_STATUS = 0;
184
185 /* Decode number of touches */
186 if (touch_count)
187 {
188 *touch_count = touch_data->TD_STATUS;
189 }
190
191 /* Decode valid touch points */
192 for (i = 0; i < touch_data->TD_STATUS; i++)
193 {
194 touch_array[i].TOUCH_ID = TOUCH_POINT_GET_ID(touch_data->TOUCH[i]);
195 touch_array[i].TOUCH_EVENT = TOUCH_POINT_GET_EVENT(touch_data->TOUCH[i]);
196 touch_array[i].TOUCH_X = TOUCH_POINT_GET_X(touch_data->TOUCH[i]);
197 touch_array[i].TOUCH_Y = TOUCH_POINT_GET_Y(touch_data->TOUCH[i]);
198 }
199
200 /* Clear vacant elements of touch_array */
201 for (; i < FT6X06_MAX_TOUCHES; i++)
202 {
203 touch_array[i].TOUCH_ID = 0;
204 touch_array[i].TOUCH_EVENT = kTouch_Reserved;
205 touch_array[i].TOUCH_X = 0;
206 touch_array[i].TOUCH_Y = 0;
207 }
208 }
209
210 return status;
211 }
212