luat_tp_ft3x68.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #include "luat_base.h"
  2. #include "luat_tp.h"
  3. #include "luat_gpio.h"
  4. #include "luat_mem.h"
  5. #include "luat_rtos.h"
  6. #include "luat_tp_reg.h"
  7. #define LUAT_LOG_TAG "ft3x68"
  8. #include "luat_log.h"
  9. #define FT3X68_DEVIDE_MODE 0x00 //模式控制
  10. #define FT3X68_TD_STATUS 0x02 //触摸状态
  11. #define FT3X68_TP1_REG 0X03
  12. #define FT3X68_TP2_REG 0X09
  13. #define FT3X68_TP3_REG 0X0F
  14. #define FT3X68_TP4_REG 0X15
  15. #define FT3X68_TP5_REG 0X1B
  16. #define ID_G_CIPHER_HIGH 0xA3
  17. #define ID_G_CIPHER_MID 0x9F
  18. #define ID_G_CIPHER_LOW 0xA0
  19. #define FT3X68_ID_G_LIB_VERSION 0xA1
  20. #define FT3X68_CHIP_VENDOR_ID 0xA3
  21. #define FT3X68_ID_G_MODE 0xA4 //中断控制
  22. #define FT3X68_ID_G_THGROUP 0x80 //触摸有效值
  23. #define FT3X68_ID_G_PERIODACTIVE 0x88 //激活状态周期
  24. #define FTS_CHIP_IDH 0x64
  25. #define FTS_CHIP_IDL 0x56
  26. #define FTS_FW_VER 0x02
  27. #define FTS_CMD_READ_ID 0x90
  28. #define FTS_UPGRADE_AA 0xAA
  29. #define FTS_UPGRADE_55 0x55
  30. #define FTS_REG_FW_VER 0xA6
  31. #define FTS_REG_UPGRADE 0xFC
  32. #define FTS_RETRIES_CHECK_ID 20
  33. #define FTS_DELAY_UPGRADE_AA 10
  34. #define FTS_DELAY_UPGRADE_RESET 400
  35. #define FTS_DELAY_READ_ID 20
  36. #define FTS_DELAY_UPGRADE 80
  37. #define FTS_RETRIES_UPGRADE 2
  38. #define FTS_CMD_RESET 0x07
  39. #define FTS_CMD_FLASH_MODE 0x09
  40. #define FTS_FLASH_MODE_UPGRADE_VALUE 0x0B
  41. #define FTS_CMD_FLASH_STATUS 0x6A
  42. #define FTS_CMD_ERASE_APP 0x61
  43. #define FTS_CMD_START_DELAY 12
  44. /* register address */
  45. #define FTS_REG_WORKMODE 0x00
  46. #define FTS_REG_WORKMODE_FACTORY_VALUE 0x40
  47. #define FTS_REG_WORKMODE_SCAN_VALUE 0xC0
  48. #define FTS_REG_FLOW_WORK_CNT 0x91
  49. #define FTS_REG_POWER_MODE 0xA5
  50. #define FTS_REG_GESTURE_EN 0xD0
  51. #define FTS_REG_GESTURE_ENABLE 0x01
  52. #define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3
  53. #define FT3X68_I2C_ADDRESS (0x38)
  54. #define FT3X68_TOUCH_NUMBER_MAX (5)
  55. typedef struct{
  56. uint8_t x_h;
  57. uint8_t x_l;
  58. uint8_t y_h;
  59. uint8_t y_l;
  60. uint8_t w;
  61. }luat_tp_touch_t;
  62. typedef struct ft3x68_tp{
  63. uint8_t is_inited;
  64. uint8_t scan_time;
  65. uint8_t is_scan;
  66. uint8_t touch_num;
  67. luat_tp_touch_t point[FT3X68_TOUCH_NUMBER_MAX];
  68. }luat_tp_info_t;
  69. static int16_t pre_x[FT3X68_TOUCH_NUMBER_MAX] = {-1, -1, -1, -1, -1};
  70. static int16_t pre_y[FT3X68_TOUCH_NUMBER_MAX] = {-1, -1, -1, -1, -1};
  71. static int16_t pre_w[FT3X68_TOUCH_NUMBER_MAX] = {-1, -1, -1, -1, -1};
  72. static uint8_t s_tp_down[FT3X68_TOUCH_NUMBER_MAX];
  73. static uint8_t pre_touch = 0;
  74. static int8_t pre_id[FT3X68_TOUCH_NUMBER_MAX] = {0};
  75. static luat_tp_info_t ft3x68_tp;
  76. static int luat_tp_irq_cb(int pin, void *args){
  77. if (ft3x68_tp.is_inited == 0){
  78. return -1;
  79. }
  80. luat_tp_config_t* luat_tp_config = (luat_tp_config_t*)args;
  81. luat_tp_irq_enable(luat_tp_config, 0);
  82. luat_rtos_message_send(luat_tp_config->task_handle, 1, args);
  83. return 0;
  84. }
  85. static int tp_ft3x68_init(luat_tp_config_t* luat_tp_config)
  86. {
  87. if (luat_tp_config->pin_rst != LUAT_GPIO_NONE){
  88. luat_gpio_mode(luat_tp_config->pin_rst, Luat_GPIO_OUTPUT, Luat_GPIO_DEFAULT, Luat_GPIO_LOW);
  89. luat_gpio_set(luat_tp_config->pin_rst, Luat_GPIO_HIGH);
  90. luat_rtos_task_sleep(5);
  91. luat_gpio_set(luat_tp_config->pin_rst, Luat_GPIO_LOW);
  92. luat_rtos_task_sleep(20);
  93. luat_gpio_set(luat_tp_config->pin_rst, Luat_GPIO_HIGH);
  94. luat_rtos_task_sleep(50);
  95. }
  96. if (luat_tp_config->soft_i2c != NULL){
  97. i2c_soft_setup(luat_tp_config->soft_i2c);
  98. }else{
  99. luat_i2c_setup(luat_tp_config->i2c_id, I2C_SPEED_SLOW);
  100. }
  101. luat_tp_config->address = FT3X68_I2C_ADDRESS;
  102. uint8_t id[4] = {FT3X68_CHIP_VENDOR_ID, 0, 0, 0};
  103. tp_i2c_read(luat_tp_config, id, 1, id, 4, 1);
  104. if (id[0] == FTS_CHIP_IDH)
  105. {
  106. LLOGD("find ft3x68");
  107. if (luat_tp_config->pin_int != LUAT_GPIO_NONE)
  108. {
  109. luat_gpio_t gpio = {0};
  110. gpio.pin = luat_tp_config->pin_int;
  111. gpio.mode = Luat_GPIO_IRQ;
  112. gpio.pull = Luat_GPIO_PULLUP;
  113. gpio.irq = LUAT_GPIO_FALLING_IRQ;
  114. gpio.irq_cb = luat_tp_irq_cb;
  115. gpio.irq_args = luat_tp_config;
  116. luat_gpio_setup(&gpio);
  117. }
  118. ft3x68_tp.is_inited = 1;
  119. }
  120. return 0;
  121. }
  122. static int tp_ft3x68_deinit(luat_tp_config_t* luat_tp_config){
  123. ft3x68_tp.is_inited = 0;
  124. if (luat_tp_config->pin_int != LUAT_GPIO_NONE){
  125. luat_gpio_close(luat_tp_config->pin_int);
  126. }
  127. if (luat_tp_config->pin_rst != LUAT_GPIO_NONE){
  128. luat_gpio_close(luat_tp_config->pin_rst);
  129. }
  130. return 0;
  131. }
  132. static void tp_ft3x68_read_done(luat_tp_config_t * luat_tp_config){
  133. if (luat_gpio_get(luat_tp_config->pin_int)){
  134. luat_tp_irq_enable(luat_tp_config, 1);
  135. }else{
  136. luat_rtos_message_send(luat_tp_config->task_handle, 1, luat_tp_config);
  137. }
  138. }
  139. void ft3x68_touch_up(void *buf, int8_t id){
  140. luat_tp_data_t *read_data = (luat_tp_data_t *)buf;
  141. if (pre_x[id] == -1 && pre_y[id] == -1)
  142. {
  143. read_data[id].event = TP_EVENT_TYPE_NONE;
  144. return;
  145. }
  146. if(s_tp_down[id] == 1){
  147. s_tp_down[id] = 0;
  148. read_data[id].event = TP_EVENT_TYPE_UP;
  149. }else{
  150. read_data[id].event = TP_EVENT_TYPE_NONE;
  151. }
  152. read_data[id].timestamp = luat_mcu_ticks();
  153. read_data[id].width = pre_w[id];
  154. read_data[id].x_coordinate = pre_x[id];
  155. read_data[id].y_coordinate = pre_y[id];
  156. read_data[id].track_id = id;
  157. pre_x[id] = -1; /* last point is none */
  158. pre_y[id] = -1;
  159. pre_w[id] = -1;
  160. }
  161. void ft3x68_touch_down(void *buf, int8_t id, int16_t x, int16_t y, int16_t w){
  162. luat_tp_data_t *read_data = (luat_tp_data_t *)buf;
  163. if (x == pre_x[id] && y == pre_y[id])
  164. {
  165. read_data[id].event = TP_EVENT_TYPE_NONE;
  166. return;
  167. }
  168. if (s_tp_down[id] == 1){
  169. read_data[id].event = TP_EVENT_TYPE_MOVE;
  170. }else{
  171. read_data[id].event = TP_EVENT_TYPE_DOWN;
  172. s_tp_down[id] = 1;
  173. }
  174. read_data[id].timestamp = luat_mcu_ticks();
  175. read_data[id].width = w;
  176. read_data[id].x_coordinate = x;
  177. read_data[id].y_coordinate = y;
  178. read_data[id].track_id = id;
  179. pre_x[id] = x; /* save last point */
  180. pre_y[id] = y;
  181. pre_w[id] = w;
  182. }
  183. void ft3x68_read_point(luat_tp_config_t* luat_tp_config, luat_tp_touch_t *input_buff, void *buf, uint8_t touch_num){
  184. luat_tp_touch_t *read_buf = input_buff;
  185. uint8_t read_index;
  186. int8_t read_id = 0;
  187. int16_t input_x = 0;
  188. int16_t input_y = 0;
  189. int16_t input_w = 0;
  190. if (pre_touch > touch_num){ /* point up */
  191. for (read_index = 0; read_index < pre_touch; read_index++){
  192. uint8_t j;
  193. for (j = 0; j < touch_num; j++){ /* this time touch num */
  194. read_id = j;
  195. if (pre_id[read_index] == read_id) /* this id is not free */
  196. break;
  197. if (j >= touch_num - 1){
  198. uint8_t up_id;
  199. up_id = pre_id[read_index];
  200. ft3x68_touch_up(buf, up_id);
  201. }
  202. }
  203. }
  204. }
  205. if (touch_num){ /* point down */
  206. for (read_index = 0; read_index < touch_num; read_index++){
  207. pre_id[read_index] = read_index;
  208. input_x = read_buf[read_index].x_h<<8 | read_buf[read_index].x_l; /* x */
  209. input_y = read_buf[read_index].y_h<<8 | read_buf[read_index].y_l; /* y */
  210. if (input_x>luat_tp_config->w || input_y>luat_tp_config->h){
  211. return;
  212. }
  213. input_w = read_buf[read_index].w; /* w */
  214. ft3x68_touch_down(buf, read_index, input_x, input_y, input_w);
  215. }
  216. }else if (pre_touch){
  217. for(read_index = 0; read_index < pre_touch; read_index++){
  218. ft3x68_touch_up(buf, pre_id[read_index]);
  219. }
  220. }
  221. pre_touch = touch_num;
  222. }
  223. const int FT3X68_TPX_TBL[5]={FT3X68_TP1_REG,FT3X68_TP2_REG,FT3X68_TP3_REG,FT3X68_TP4_REG,FT3X68_TP5_REG};
  224. static int tp_ft3x68_read(luat_tp_config_t* luat_tp_config, luat_tp_data_t *luat_tp_data){
  225. uint8_t touch_num=0, point_status=0;
  226. uint8_t temp[1] = {FT3X68_TD_STATUS};
  227. if (!tp_i2c_read(luat_tp_config, temp, 1, temp, 4, 1))
  228. {
  229. touch_num = temp[0] & 0x0f;
  230. if(touch_num && (touch_num <= FT3X68_TOUCH_NUMBER_MAX))
  231. {
  232. for(int i = 0; i < touch_num; i++)
  233. {
  234. temp[0] = FT3X68_TPX_TBL[i];
  235. if (!tp_i2c_read(luat_tp_config, temp, 1, &ft3x68_tp.point[i], 4, 1))
  236. {
  237. // LLOGD("point %d data%x,%x,%x,%x", i, ft3x68_tp.point[i].x_h, ft3x68_tp.point[i].x_l, ft3x68_tp.point[i].y_h, ft3x68_tp.point[i].y_l);
  238. if (0x80 != (ft3x68_tp.point[i].x_h & 0xF0))
  239. {
  240. // LLOGE("point %d data error %x,%x,%x,%x", i, ft3x68_tp.point[i].x_h, ft3x68_tp.point[i].x_l, ft3x68_tp.point[i].y_h, ft3x68_tp.point[i].y_l);
  241. memset(&ft3x68_tp.point[i], 0, sizeof(ft3x68_tp.point[i]));
  242. touch_num--;
  243. }
  244. else
  245. {
  246. ft3x68_tp.point[i].x_h &= 0x0f;
  247. point_status = 1;
  248. }
  249. }
  250. }
  251. }
  252. }
  253. if (point_status || pre_touch)
  254. {
  255. ft3x68_tp.touch_num = touch_num;
  256. ft3x68_read_point(luat_tp_config, ft3x68_tp.point, luat_tp_data, ft3x68_tp.touch_num);
  257. }
  258. else
  259. {
  260. if (!pre_touch && !touch_num)
  261. {
  262. memset(luat_tp_data, 0, sizeof(luat_tp_data_t) * LUAT_TP_TOUCH_MAX);
  263. }
  264. }
  265. return touch_num;
  266. }
  267. luat_tp_opts_t tp_config_ft3x68 = {
  268. .name = "ft3x68",
  269. .init = tp_ft3x68_init,
  270. .deinit = tp_ft3x68_deinit,
  271. .read = tp_ft3x68_read,
  272. .read_done = tp_ft3x68_read_done,
  273. };