doubao_chat/apps/common/ui/touch_panel/ft6236.c

469 lines
12 KiB
C

#include "system/includes.h"
#include "asm/port_waked_up.h"
#include "typedef.h"
#include "os/os_api.h"
#include "asm/iic.h"
#include "device/iic.h"
#include "device/device.h"
#include "lcd_config.h"
#include "app_config.h"
#include "system/includes.h"
#include "gpio.h"
#include "ui_api.h"
#include "touch_event.h"
#include "sys_common.h"
#if TCFG_TOUCH_FT6236_ENABLE
#define TEST 0
#if 1
#define log_info(x, ...) printf("\n[touch]>" x " \n", ## __VA_ARGS__)
#else
#define log_info(...)
#endif
struct touch_hdl {
u16 x;
u16 y;
u8 status;
};
struct touch_hdl lvgl_touch_hdl;
static OS_SEM touch_sem;
static u8 touch_en = 1 ;
void *get_touch_x_y(void)
{
return &lvgl_touch_hdl;
}
void get_touch_x_y_status(u16 *x, u16 *y, u8 *status)
{
#if HORIZONTAL_SCREEN==1
*x = lvgl_touch_hdl.y;
*y = 320 - lvgl_touch_hdl.x;
if (*y > LCD_H) {
*y = LCD_H;
}
#else
*x = lvgl_touch_hdl.x;
*y = lvgl_touch_hdl.y;
#endif
*status = lvgl_touch_hdl.status;
}
extern int ui_touch_msg_post(struct touch_event *event);
//I2C读写命令
#define FT6236_WRCMD 0X70 //写命令
#define FT6236_RDCMD 0X71 //读命令
#define FTS_REG_INT_CNT 0x8F
#define FTS_REG_FLOW_WORK_CNT 0x91
#define FTS_REG_WORKMODE 0x00
#define FTS_REG_WORKMODE_FACTORY_VALUE 0x40
#define FTS_REG_WORKMODE_WORK_VALUE 0x00
#define FTS_REG_ESDCHECK_DISABLE 0x8D
#define FTS_REG_CHIP_ID 0xA3
#define FTS_REG_CHIP_ID2 0x9F
#define FTS_REG_POWER_MODE 0xA5
#define FTS_REG_POWER_MODE_SLEEP_VALUE 0x03
#define FTS_REG_FW_VER 0xA6
#define FTS_REG_VENDOR_ID 0xA8
#define FTS_REG_LCD_BUSY_NUM 0xAB
#define FTS_REG_FACE_DEC_MODE_EN 0xB0
#define FTS_REG_FACE_DEC_MODE_STATUS 0x01
#define FTS_REG_IDE_PARA_VER_ID 0xB5
#define FTS_REG_IDE_PARA_STATUS 0xB6
#define FTS_REG_GLOVE_MODE_EN 0xC0
#define FTS_REG_COVER_MODE_EN 0xC1
#define FTS_REG_CHARGER_MODE_EN 0x8B
#define FTS_REG_GESTURE_EN 0xD0
#define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3
#define FTS_REG_MODULE_ID 0xE3
#define FTS_REG_LIC_VER 0xE4
#define FTS_REG_ESD_SATURATE 0xED
static void *iic = NULL;
//I2C读写命令
#define FT_CMD_WR 0X70 //写命令
#define FT_CMD_RD 0X71 //读命令
//FT6236 部分寄存器定义
#define FT_DEVIDE_MODE 0x00 //FT6236模式控制寄存器
#define FT_REG_NUM_FINGER 0x02 //触摸状态寄存器
#define FT_TP1_REG 0X03 //第一个触摸点数据地址
#define FT_ID_G_LIB_VERSION 0xA1 //版本
#define FT_ID_G_MODE 0xA4 //FT6236中断模式控制寄存器
#define FT_ID_G_THGROUP 0x80 //触摸有效值设置寄存器
#define FT_ID_G_PERIODACTIVE 0x88 //激活状态周期设置寄存器
#define Chip_Vendor_ID 0xA3 //芯片ID(0x36)
#define ID_G_FT6236ID 0xA8 //0x11
#define Y_MIRROR 0
#define X_MIRROR 0
/*#define VK_Y LCD_W*/
/*#define VK_X LCD_H*/
#define VK_Y 480
#define VK_X 320
#define VK_Y_MOVE 50
#define VK_X_MOVE 50
#define VK_X_Y_DIFF 30
//由FT6236芯片手册查询得到各部分寄存器地址
#define FI_DEVIDE_MODE 0x00 //FT6236模式控制寄存器
#define FI_REG_NUM_FINGER 0x02 //触摸状态寄存器
#define FI_TP1_REG 0x03 //第一个触摸点数据地址
#define FI_TP2_REG 0x09 //第一个触摸点数据地址
#define FI_TP3_REG 0x0F //第一个触摸点数据地址
#define FI_TP4_REG 0x15 //第一个触摸点数据地址
#define FI_TP5_REG 0x1B //第一个触摸点数据地址
static u8 touch_status = 0;
static unsigned char wrFT6236Reg(u8 regID, unsigned char regDat)
{
u8 ret = 1;
dev_ioctl(iic, IIC_IOCTL_START, 0);
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_START_BIT, FT6236_WRCMD)) {
ret = 0;
log_info("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(100);
if (dev_ioctl(iic, IIC_IOCTL_TX, regID & 0xff)) {
ret = 0;
log_info("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(100);
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_STOP_BIT, regDat)) {
ret = 0;
log_info("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(100);
exit:
dev_ioctl(iic, IIC_IOCTL_STOP, 0);
return ret;
}
static unsigned char rdFT6236Reg(u8 regID, u8 *regDat)
{
u8 ret = 1;
dev_ioctl(iic, IIC_IOCTL_START, 0);
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_START_BIT, FT6236_WRCMD)) {
ret = 0;
log_info("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(100);
if (dev_ioctl(iic, IIC_IOCTL_TX, regID & 0xff)) {
ret = 0;;
log_info("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(100);
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_START_BIT, FT6236_RDCMD)) {
ret = 0;
goto exit;
}
delay(100);
dev_ioctl(iic, IIC_IOCTL_RX_WITH_STOP_BIT, (u32)regDat);
exit:
dev_ioctl(iic, IIC_IOCTL_STOP, 0);
return ret;
}
void set_touch_enable(void)
{
touch_en = 1;
}
void set_touch_disable(void)
{
touch_en = 0;
}
int get_FT6236_pid(void)
{
u8 temp = 0;
rdFT6236Reg(FTS_REG_CHIP_ID, &temp);
if (temp != 100) {
return 1;
}
log_info(">>>>>>>>>>>hell touch FT6236<<<<<<<<<<<");
return 0;
}
static void get_FT6236_xy(u16 addr, u16 *x, u16 *y)
{
u8 buf[4];
for (u8 i = 0; i < 4; i++) {
rdFT6236Reg((addr + i), &buf[i]); //读取XY坐标值
}
*y = (((u16)(buf[2] & 0X0F) << 8) + buf[3]);
*x = ((u16)(buf[0] & 0X0F) << 8) + buf[1];
}
static u8 tp_last_staus = ELM_EVENT_TOUCH_UP;
static int tp_down_cnt = 0;
static void tpd_down(int x, int y)
{
struct touch_event t;
static u8 move_flag = 0;
static int first_x = 0;
static int first_y = 0;
if (x < 0) {
x = 0;
}
if (x > (VK_X - 1)) {
x = VK_X - 1;
}
if (y < 0) {
y = 0;
}
if (y > (VK_Y - 1)) {
y = VK_Y - 1;
}
#if Y_MIRROR
x = VK_X - x - 1;
#endif
#if X_MIRROR
y = VK_Y - y - 1;
#endif
if ((tp_last_staus == ELM_EVENT_TOUCH_DOWN) && (x == first_x) && (y == first_y)) {
tp_down_cnt++;
if (tp_down_cnt < 30) {
return;
}
tp_last_staus = ELM_EVENT_TOUCH_HOLD;
tp_down_cnt = 0;
t.action = tp_last_staus;
#if HORIZONTAL_SCREEN
t.x = LCD_W - y;
t.y = x;
#else
t.x = x;
t.y = y;
#endif
log_info("----tpd_hold----x=%d, y=%d", x, y);
lvgl_touch_hdl.x = x;
lvgl_touch_hdl.y = y;
lvgl_touch_hdl.status = 1;
if (touch_en) {
ui_touch_msg_post(&t);
}
return;
}
if (tp_last_staus != ELM_EVENT_TOUCH_UP) {
int x_move = abs(x - first_x);
int y_move = abs(y - first_y);
if (!move_flag && (x_move >= VK_X_MOVE || y_move >= VK_Y_MOVE) && (abs(x_move - y_move) >= VK_X_Y_DIFF)) {
if (x_move > y_move) {
if (x > first_x) {
tp_last_staus = ELM_EVENT_TOUCH_R_MOVE;
log_info("----tpd_rigth_move----x=%d, y=%d", x, y);
} else {
tp_last_staus = ELM_EVENT_TOUCH_L_MOVE;
log_info("----tpd_left_move----x=%d, y=%d", x, y);
}
} else {
if (y > first_y) {
tp_last_staus = ELM_EVENT_TOUCH_D_MOVE;
log_info("----tpd_down_move----x=%d, y=%d", x, y);
} else {
tp_last_staus = ELM_EVENT_TOUCH_U_MOVE;
log_info("----tpd_up_move----x=%d, y=%d", x, y);
}
}
move_flag = 1;
} else {
if ((x == first_x) && (y == first_y)) {
return;
}
tp_last_staus = ELM_EVENT_TOUCH_MOVE;
log_info("----tpd_move----x=%d, y=%d", x, y);
}
#if HORIZONTAL_SCREEN
t.x = LCD_W - y;
t.y = x;
#else
t.x = x;
t.y = y;
#endif
#if defined USE_GUIX_UI_DEMO
gx_jl_touch_event_process(t.x, t.y, 2);
#endif
#if defined USE_UGFX_UI_DEMO
ugfx_touch_event_process(t.x, t.y, 2);
#endif
} else {
tp_last_staus = ELM_EVENT_TOUCH_DOWN;
move_flag = 0;
log_info("----tpd_down----x=%d, y=%d", x, y);
}
first_x = x;
first_y = y;
t.action = tp_last_staus;
#if HORIZONTAL_SCREEN
t.x = LCD_W - y;
t.y = x;
#else
t.x = x;
t.y = y;
#endif
lvgl_touch_hdl.x = x;
lvgl_touch_hdl.y = y;
lvgl_touch_hdl.status = 1;
if (touch_en) {
ui_touch_msg_post(&t);
}
#if defined USE_GUIX_UI_DEMO
gx_jl_touch_event_process(t.x, t.y, 1);
#endif
#if defined USE_UGFX_UI_DEMO
ugfx_touch_event_process(t.x, t.y, 1);
#endif
}
static void tpd_up(int x, int y)
{
struct touch_event t;
if (x < 0) {
x = 0;
}
if (x > (VK_X - 1)) {
x = VK_X - 1;
}
if (y < 0) {
y = 0;
}
if (y > (VK_Y - 1)) {
y = VK_Y - 1;
}
#if Y_MIRROR
x = VK_X - x - 1;
#endif
#if X_MIRROR
y = VK_Y - y - 1;
#endif
/* log_info("U[%4d %4d %4d]\n", x, y, 0); */
tp_last_staus = ELM_EVENT_TOUCH_UP;
tp_down_cnt = 0;
t.action = tp_last_staus;
#if HORIZONTAL_SCREEN
t.x = LCD_W - y;
t.y = x;
#else
t.x = x;
t.y = y;
#endif
log_info("----tpd_up----x=%d, y=%d", x, y);
lvgl_touch_hdl.x = x;
lvgl_touch_hdl.y = y;
lvgl_touch_hdl.status = 0;
if (touch_en) {
ui_touch_msg_post(&t);
}
#if defined USE_GUIX_UI_DEMO
gx_jl_touch_event_process(t.x, t.y, 0);
#endif
#if defined USE_UGFX_UI_DEMO
ugfx_touch_event_process(t.x, t.y, 0);
#endif
}
static void FT6236_interrupt(void)
{
os_sem_post(&touch_sem);
}
void FT6236_init(void)
{
static u8 status = 0;
static int x, y;
static u16 touch_x = 0;
static u16 touch_y = 0;
u8 read_data = 0;
os_sem_create(&touch_sem, 0);
extern const struct ui_devices_cfg ui_cfg_data;
static const struct ui_lcd_platform_data *pdata;
pdata = (struct ui_lcd_platform_data *)ui_cfg_data.private_data;
gpio_direction_output(pdata->touch_reset_pin, 0);
os_time_dly(6);
gpio_direction_output(pdata->touch_reset_pin, 1);
iic = dev_open("iic0", NULL);
os_time_dly(10);
//注册中断注意触摸用的事件0 屏幕TE用的事件1
port_wakeup_reg(EVENT_IO_0, pdata->touch_int_pin, EDGE_NEGATIVE, FT6236_interrupt);
wrFT6236Reg(FT_DEVIDE_MODE, 0);
wrFT6236Reg(FT_ID_G_THGROUP, 22);
rdFT6236Reg(FT_ID_G_THGROUP, &read_data);
printf("[touch FT_ID_G_THGROUP]>>>>>>>>>>>read_data=%d", read_data);
wrFT6236Reg(FT_ID_G_PERIODACTIVE, 13);
rdFT6236Reg(FT_ID_G_PERIODACTIVE, &read_data);
printf("[touch FT_ID_G_PERIODACTIVE]>>>>>>>>>>>read_data=%d", read_data);
wrFT6236Reg(FT_ID_G_MODE, 1);
rdFT6236Reg(FT_ID_G_MODE, &read_data);
printf("[touch FT_ID_G_MODE]>>>>>>>>>>>read_data=%d", read_data);
if (get_FT6236_pid()) {
log_info("[err]>>>>>FT6236 err!!!");
}
while (1) {
os_sem_pend(&touch_sem, 0);
rdFT6236Reg(FT_REG_NUM_FINGER, &status); //读取触摸点的状态 // BIT7表示有数据 ,bit0-3 表示触摸点个数
if (status) { //有触摸值
get_FT6236_xy(FT_TP1_REG, &touch_x, &touch_y);
tpd_down(touch_x, touch_y);//做触摸运算
touch_status = 1;//标记触摸按下
} else {
if (touch_status) { //这样做的目的是使得发消息做处理只有一次
tpd_up(touch_x, touch_y);//做触摸运算
os_time_dly(40);//保证两次触摸的最小时间间隔 UI有问题占时这样解决
os_sem_set(&touch_sem, 0);
}
touch_status = 0;//标记触摸抬起
}
status = 0;
}
}
static void my_touch_test_task(void *priv)
{
FT6236_init();
}
int FT6236_task_init(void)
{
return thread_fork("my_touch_test_task", 29, 1024, 0, NULL, my_touch_test_task, NULL);
}
#endif