1085 lines
29 KiB
C
1085 lines
29 KiB
C
#include "app_config.h"
|
|
#include "system/includes.h"
|
|
#include "gpio.h"
|
|
#include "ui/ui_api.h"
|
|
#include "clock_manager/clock_manager.h"
|
|
#include "perf_counter/perf_counter.h"
|
|
|
|
#if (defined CONFIG_LVGL_UI_ENABLE && CONFIG_LVGL_UI_ENABLE)
|
|
#include "ui_core.h"
|
|
#define TP_TASK_NAME "touch_task" ///< 触摸面板任务名
|
|
#endif
|
|
|
|
#if TCFG_TOUCH_PANEL_ENABLE
|
|
#if TCFG_TP_CST816D_ENABLE//CST816D_UPGRADE==1
|
|
|
|
#if ((defined TCFG_LCD_QSPI_jd9161c_ENABLE) && (TCFG_LCD_QSPI_jd9161c_ENABLE))
|
|
#include "capacitive_hynitron_cst816d_jd9161c_480x480_update.h"
|
|
#elif ((defined TCFG_LCD_SPI_SH8501A_ENABLE) && (TCFG_LCD_SPI_SH8501A_ENABLE))
|
|
#include "capacitive_hynitron_cst816d_240x296_update.h"
|
|
#elif ((defined TCFG_LCD_SPI_ICNA3306_ENABLE) &&(TCFG_LCD_SPI_ICNA3306_ENABLE))
|
|
#include "capacitive_hynitron_cst816d_240x296_update.h"
|
|
#elif ((defined TCFG_LCD_SPI_ST77916_ENABLE) && (TCFG_LCD_SPI_ST77916_ENABLE))
|
|
#include "capacitive_hynitron_cst816d_st77916_320x365_update.h"
|
|
#elif ((defined TCFG_CAT1_UNISOC_BOARD_TEST) && (TCFG_CAT1_UNISOC_BOARD_TEST))
|
|
#include "capacitive_hynitron_cst816d_qcwx_update.h"
|
|
#elif ((defined TCFG_LCD_GC9307_172X320) && (TCFG_LCD_GC9307_172X320))
|
|
#include "capacitive_hynitron_cst816d_GC9307_172x320_update.h"
|
|
#else
|
|
#include "capacitive_hynitron_cst816d_update.h"
|
|
#endif
|
|
|
|
#define _IIC_USE_HW
|
|
#include "iic_api.h"
|
|
|
|
|
|
#define LOG_TAG "[TP]"
|
|
#define PRINTF(format, ...) printf(format, ## __VA_ARGS__)
|
|
#if 0
|
|
#define log_info(format, ...) PRINTF(LOG_TAG "info:" format, ## __VA_ARGS__)
|
|
#define log_debug(format, ...) PRINTF(LOG_TAG "debug:" format, ## __VA_ARGS__)
|
|
#define log_error(format, ...) PRINTF(LOG_TAG "error:" format, ## __VA_ARGS__)
|
|
#else
|
|
#define log_info(format, ...) //PRINTF(LOG_TAG "info:" format, ## __VA_ARGS__)
|
|
#define log_debug(format, ...)
|
|
#define log_error(format, ...) PRINTF(LOG_TAG "error:" format, ## __VA_ARGS__)
|
|
#endif
|
|
|
|
#define abs(x) __builtin_abs(x)//((x)>0?(x):-(x) )
|
|
|
|
// 触摸信息配置
|
|
#if (defined TCFG_LCD_SPI_SH8501A_ENABLE && TCFG_LCD_SPI_SH8501A_ENABLE)
|
|
#define X_MIRROR 0
|
|
#define Y_MIRROR 0
|
|
#define VK_X 240
|
|
#define VK_Y 296
|
|
#define TP_FPS 60
|
|
#elif ((defined TCFG_LCD_SPI_ICNA3306_ENABLE) &&(TCFG_LCD_SPI_ICNA3306_ENABLE))
|
|
#define X_MIRROR 0
|
|
#define Y_MIRROR 0
|
|
#define VK_X 240
|
|
#define VK_Y 296
|
|
#define TP_FPS 60
|
|
#elif (defined TCFG_LCD_SPI_GC9B71_ENABLE && TCFG_LCD_SPI_GC9B71_ENABLE)
|
|
#define X_MIRROR 0
|
|
#define Y_MIRROR 0
|
|
#define VK_X 320
|
|
#define VK_Y 386
|
|
#define TP_FPS 60
|
|
#elif (defined TCFG_LCD_SPI_ST77916_ENABLE && TCFG_LCD_SPI_ST77916_ENABLE)
|
|
#define X_MIRROR 0
|
|
#define Y_MIRROR 0
|
|
#define VK_X 320
|
|
#define VK_Y 386
|
|
#define TP_FPS 60
|
|
#elif (defined TCFG_LCD_QSPI_ST77903_V2_ENABLE && TCFG_LCD_QSPI_ST77903_V2_ENABLE)
|
|
#define X_MIRROR 0
|
|
#define Y_MIRROR 0
|
|
#define VK_X 400
|
|
#define VK_Y 400
|
|
#define TP_FPS 60
|
|
#elif (defined TCFG_LCD_QSPI_jd9161c_ENABLE && TCFG_LCD_QSPI_jd9161c_ENABLE)
|
|
#define X_MIRROR 0
|
|
#define Y_MIRROR 0
|
|
#define VK_X 480
|
|
#define VK_Y 480
|
|
#define TP_FPS 60
|
|
#elif (defined TCFG_LCD_GC9307_172X320 && TCFG_LCD_GC9307_172X320)
|
|
#define X_MIRROR 1
|
|
#define Y_MIRROR 0
|
|
#define VK_X 320
|
|
#define VK_Y 172
|
|
#define TP_FPS 60
|
|
#else
|
|
#define Y_MIRROR 1
|
|
#define X_MIRROR 1
|
|
#define VK_X 360
|
|
#define VK_Y 360
|
|
#define TP_FPS 60
|
|
#endif
|
|
#define VK_MIN (VK_X < VK_Y ? VK_X : VK_Y)
|
|
#define VK_MAX (VK_X > VK_Y ? VK_X : VK_Y)
|
|
|
|
// 滑屏阈值
|
|
#define VK_X_MOVE (VK_MIN/5)
|
|
#define VK_Y_MOVE (VK_MIN/5)
|
|
#define VK_X_Y_DIFF (VK_MIN/10)
|
|
#if defined TCFG_COLOR_SCREEN_CHARGING_CASE_ENABLE
|
|
#define SINGLE_SLIDING (10) //保证只有一个方向滑动阈值
|
|
#endif
|
|
|
|
// 惯性阈值
|
|
#define ENERGY_XDISTANCE 4//(VK_MIN/30)
|
|
#define ENERGY_YDISTANCE 4//(VK_MIN/30)
|
|
|
|
#define ENERGY_NUM 3 //取最后n次中最大差值
|
|
#define ENERGY_T_MS (1000000/TP_FPS/1000)
|
|
|
|
// reset gpio
|
|
#define CST816S_RESET_H() gpio_set_mode(IO_PORT_SPILT(TCFG_TP_RESET_IO), PORT_OUTPUT_HIGH)
|
|
#define CST816S_RESET_L() gpio_set_mode(IO_PORT_SPILT(TCFG_TP_RESET_IO), PORT_OUTPUT_LOW)
|
|
|
|
// iic
|
|
#define CST816S_IIC_DELAY 1
|
|
#define CST816S_IIC_ADDR 0x46
|
|
#define SLAVE_DEV_ADDR (0x15) //固有,不可配置,用于 chipID 读取,固件烧录操作
|
|
|
|
#define PER_LEN 512
|
|
#define CST816S_UPGRADE_ADD (0x6A) /* 7-bit i2c addr */
|
|
#define HYN_I2C_ADDR 0x15 /* 7-bit i2c addr */ //0x38
|
|
|
|
#define I2C_MASTER_CI2C0 0
|
|
#define i2c_t uint8_t
|
|
|
|
typedef enum {
|
|
TP_RUN_STEP_STOP = 0,
|
|
TP_RUN_STEP_INIT,
|
|
TP_RUN_STEP_RUN_IDLE,
|
|
TP_RUN_STEP_RUN,
|
|
} TP_RUN_STEP_E;
|
|
|
|
// iic
|
|
typedef struct {
|
|
u8 init;
|
|
hw_iic_dev iic_hdl;
|
|
} ft_param;
|
|
|
|
// 惯性
|
|
struct touch_kinetic_energy {
|
|
u16 x;
|
|
u16 y;
|
|
};
|
|
|
|
static struct touch_kinetic_energy tke[ENERGY_NUM]; // 惯性
|
|
|
|
static volatile TP_RUN_STEP_E tp_step = TP_RUN_STEP_STOP;
|
|
static u8 tp_last_staus = ELM_EVENT_TOUCH_UP; // 状态记录
|
|
static int tp_down_cnt = 0; // 长按计数
|
|
static bool touch_flag = 0; // 触摸标记
|
|
static OS_SEM touch_sem; // 触摸中断post
|
|
|
|
static ft_param module_param = {0}; // iic
|
|
#define __this (&module_param)
|
|
|
|
#if CONFIG_LVGL_UI_ENABLE
|
|
struct point {
|
|
int x;
|
|
int y;
|
|
};
|
|
typedef struct {
|
|
struct point point;
|
|
int state;
|
|
} lv_touch_data_t;
|
|
static lv_touch_data_t g_touch_data;
|
|
|
|
#define LV_INDEV_STATE_PR 0
|
|
#define LV_INDEV_STATE_REL 1
|
|
static int vk_state = LV_INDEV_STATE_REL;
|
|
|
|
#endif /* #if CONFIG_LVGL_UI_ENABLE */
|
|
|
|
|
|
static void cst816d_reset();
|
|
|
|
static void ctp_delay_us(unsigned int time)
|
|
{
|
|
udelay(time);
|
|
}
|
|
static void ctp_delay_ms(unsigned short time)
|
|
{
|
|
if (time >= 10) {
|
|
os_time_dly(time / 10 + 1);
|
|
} else {
|
|
mdelay(time);
|
|
}
|
|
}
|
|
|
|
#if TCFG_COLOR_SCREEN_CHARGING_CASE_ENABLE
|
|
static void tp_port_wakeup_callback(P33_IO_WKUP_EDGE edge)
|
|
{
|
|
log_info("tp_port_wakeup_callback\n");
|
|
bool get_touch_switch_flag(void);
|
|
if (get_screen_saver_status() && get_touch_switch_flag()) {
|
|
ui_screen_recover(1);
|
|
return;
|
|
}
|
|
if (!get_touch_switch_flag()) {
|
|
log_debug("get_touch_switch_flag 0\n");
|
|
}
|
|
}
|
|
|
|
static const struct _p33_io_wakeup_config tp_port = {
|
|
.edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿\双边沿
|
|
// .filter = PORT_FLT_16ms,
|
|
.gpio = TCFG_TP_INT_IO, //唤醒口选择
|
|
.callback = tp_port_wakeup_callback,
|
|
};
|
|
#endif
|
|
|
|
/*------------------
|
|
* tp中断配置
|
|
* -----------------*/
|
|
static void tp_irq_callback(enum gpio_port port, u32 pin, enum gpio_irq_edge edge)
|
|
{
|
|
log_debug("port%d.%d:%d-cb1\n", port, pin, edge);
|
|
|
|
touch_flag = 1;
|
|
os_sem_post(&touch_sem);
|
|
}
|
|
|
|
struct gpio_irq_config_st tp_int_irq_config = {
|
|
.pin = NO_CONFIG_PORT,
|
|
.irq_edge = PORT_IRQ_EDGE_FALL,
|
|
.callback = tp_irq_callback,
|
|
.irq_priority = 3,
|
|
};
|
|
|
|
void tp_irq_init(void)
|
|
{
|
|
u8 port_x = TCFG_TP_INT_IO / IO_GROUP_NUM;
|
|
u16 port_pin_x = BIT(TCFG_TP_INT_IO % IO_GROUP_NUM);
|
|
tp_int_irq_config.pin = port_pin_x;
|
|
log_debug("[%s] port_x:%x, port_pin_x:%x", __func__, port_x, port_pin_x);
|
|
#if TCFG_COLOR_SCREEN_CHARGING_CASE_ENABLE
|
|
#if (!TP_POWER_DOWN_EN)
|
|
p33_io_wakeup_port_init(&tp_port);
|
|
p33_io_wakeup_enable(TCFG_TP_INT_IO, 1);
|
|
#endif
|
|
#endif
|
|
gpio_set_mode(IO_PORT_SPILT(TCFG_TP_INT_IO), PORT_INPUT_PULLUP_10K);
|
|
gpio_irq_config(port_x, &tp_int_irq_config);
|
|
}
|
|
|
|
void tp_irq_deinit(void)
|
|
{
|
|
gpio_irq_deinit(IO_PORT_SPILT(TCFG_TP_INT_IO));
|
|
gpio_set_mode(IO_PORT_SPILT(TCFG_TP_INT_IO), PORT_HIGHZ);
|
|
}
|
|
|
|
static int i2c_write_regs(i2c_t dev, uint16_t address, uint16_t reg,
|
|
void *data, size_t length, uint8_t flags)
|
|
{
|
|
int ret;
|
|
/* printf("i2c_read_regs_ex.\n"); */
|
|
|
|
iic_start(__this->iic_hdl);
|
|
if (0 == iic_tx_byte(__this->iic_hdl, address << 1)) {
|
|
iic_stop(__this->iic_hdl);
|
|
log_error("iic_tx_byte fail1!\n");
|
|
return -1;
|
|
}
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
/* ret = iic_write_buf(__this->iic_hdl, reg & 0xff, 1); */
|
|
iic_tx_byte(__this->iic_hdl, reg);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
ret = iic_write_buf(__this->iic_hdl, data, length);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
iic_stop(__this->iic_hdl);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int i2c_read_regs(i2c_t dev, uint16_t address, uint16_t reg,
|
|
void *data, size_t length, uint8_t flags)
|
|
{
|
|
int ret;
|
|
/* printf("i2c_read_regs_ex.\n"); */
|
|
|
|
iic_start(__this->iic_hdl);
|
|
if (0 == iic_tx_byte(__this->iic_hdl, address << 1)) {
|
|
iic_stop(__this->iic_hdl);
|
|
log_error("iic_tx_byte fail2!\n");
|
|
return -1;
|
|
}
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
/* ret = iic_write_buf(__this->iic_hdl, reg & 0xff, 1); */
|
|
iic_tx_byte(__this->iic_hdl, reg);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
|
|
iic_start(__this->iic_hdl);
|
|
if (0 == iic_tx_byte(__this->iic_hdl, (address << 1) | 0x01)) {
|
|
iic_stop(__this->iic_hdl);
|
|
return -1;
|
|
}
|
|
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
ret = iic_read_buf(__this->iic_hdl, data, length);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
iic_stop(__this->iic_hdl);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int i2c_read_regs_ex(i2c_t dev, uint16_t address, void *reg,
|
|
void *data, size_t length, uint8_t flags)
|
|
{
|
|
int ret;
|
|
/* printf("i2c_read_regs_ex.\n"); */
|
|
|
|
iic_start(__this->iic_hdl);
|
|
if (0 == iic_tx_byte(__this->iic_hdl, address << 1)) {
|
|
iic_stop(__this->iic_hdl);
|
|
log_error("iic_tx_byte fail3!\n");
|
|
return -1;
|
|
}
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
ret = iic_write_buf(__this->iic_hdl, reg, 2);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
|
|
iic_start(__this->iic_hdl);
|
|
if (0 == iic_tx_byte(__this->iic_hdl, (address << 1) | 0x01)) {
|
|
iic_stop(__this->iic_hdl);
|
|
return -1;
|
|
}
|
|
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
ret = iic_read_buf(__this->iic_hdl, data, length);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
iic_stop(__this->iic_hdl);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int i2c_write_regs_ex(i2c_t dev, uint16_t address, void *reg,
|
|
const void *data, size_t length, uint8_t flags)
|
|
{
|
|
int ret;
|
|
int i;
|
|
u8 *_reg = (u8 *)reg;
|
|
u8 *_data = (u8 *)data;
|
|
|
|
/* printf("i2c_write_regs_ex. reg:0x%02x%02x\n",_reg[0],_reg[1]); */
|
|
/* printf("data:\n"); */
|
|
/* for(i=0;i<length;i++) { */
|
|
/* printf("%02x ",_data[i]); */
|
|
/* } */
|
|
/* printf("\n"); */
|
|
/* printf("address = 0x%x\n",address<<1); */
|
|
|
|
iic_start(__this->iic_hdl);
|
|
if (0 == iic_tx_byte(__this->iic_hdl, address << 1)) {
|
|
iic_stop(__this->iic_hdl);
|
|
log_error("iic_tx_byte fail4!\n");/*tp升级时,boot_mode有时间窗口限制,会打印识别,看最终能否成功就行*/
|
|
return -1;
|
|
}
|
|
/* ret = iic_write_buf(__this->iic_hdl, reg, 2); */
|
|
iic_tx_byte(__this->iic_hdl, _reg[0]);
|
|
iic_tx_byte(__this->iic_hdl, _reg[1]);
|
|
/* printf("ret = %d\n",ret); */
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
ret = iic_write_buf(__this->iic_hdl, data, length);
|
|
/* printf("ret = %d\n",ret); */
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
iic_stop(__this->iic_hdl);
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static u16 ctp_flash_iic_write(u8 slave_addr, u8 *buf, u16 len)
|
|
{
|
|
u16 i = 0;
|
|
iic_start(__this->iic_hdl);
|
|
if (0 == iic_tx_byte(__this->iic_hdl, slave_addr)) {
|
|
iic_stop(__this->iic_hdl);
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
if (0 == iic_tx_byte(__this->iic_hdl, buf[i])) {
|
|
iic_stop(__this->iic_hdl);
|
|
return i;
|
|
}
|
|
}
|
|
iic_stop(__this->iic_hdl);
|
|
return i;
|
|
}
|
|
|
|
//return =len:ok; other:fail
|
|
static u16 ctp_flash_iic_read(u8 slave_addr, u8 *buf, u16 len)
|
|
{
|
|
u16 i = 0;
|
|
iic_start(__this->iic_hdl);
|
|
if (0 == iic_tx_byte(__this->iic_hdl, slave_addr + 1)) {
|
|
iic_stop(__this->iic_hdl);
|
|
return 0;
|
|
}
|
|
for (i = 0; i < len - 1; i++) {
|
|
ctp_delay_us(CST816S_IIC_DELAY);
|
|
*buf++ = iic_rx_byte(__this->iic_hdl, 1, NULL);
|
|
}
|
|
i++;
|
|
*buf = iic_rx_byte(__this->iic_hdl, 0, NULL);
|
|
iic_stop(__this->iic_hdl);
|
|
return i;
|
|
}
|
|
|
|
|
|
static int cst816d_enter_bootmode(void)
|
|
{
|
|
uint8_t retryCnt = 10;
|
|
|
|
#if 0
|
|
gpio_output_set(GPIO15, 0);
|
|
uos_sleep(4);/* 20 ms */
|
|
gpio_output_set(GPIO15, 1);
|
|
uos_sleep(1);/* 5ms */
|
|
#else
|
|
cst816d_reset();
|
|
#endif
|
|
log_debug("%s %d \r\n", __FUNCTION__, __LINE__);
|
|
|
|
while (retryCnt--) {
|
|
uint8_t cmd[3];
|
|
cmd[0] = 0xAB;
|
|
|
|
unsigned char reg[2] = {0xA0, 0x01};
|
|
if (0 == system_iic_write_nbytes(__this->iic_hdl, CST816S_UPGRADE_ADD, reg, 2, cmd, 1)) { // enter program mode
|
|
ctp_delay_ms(2); // 4ms
|
|
continue;
|
|
}
|
|
|
|
unsigned char reg1[2] = {0xA0, 0x03};
|
|
if (0 == system_iic_read_nbytes(__this->iic_hdl, CST816S_UPGRADE_ADD, reg1, 2, cmd, 1)) { // read flag
|
|
ctp_delay_ms(2); // 4ms
|
|
continue;
|
|
} else {
|
|
log_debug("cmd[0] = 0x%02x\n", cmd[0]);
|
|
if (cmd[0] != /*0x55*/0xc1) {
|
|
ctp_delay_ms(2); // 4ms
|
|
continue;
|
|
} else {
|
|
/* printf("%s %d \r\n", __FUNCTION__, __LINE__); */
|
|
log_info("cst816d_enter_bootmode succ!\n");
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
log_debug("%s %d retryCnt %d\r\n", __FUNCTION__, __LINE__, retryCnt);
|
|
return -1;
|
|
}
|
|
|
|
static int cst816d_update(uint16_t startAddr, uint16_t len, uint8_t *src)
|
|
{
|
|
uint16_t sum_len;
|
|
uint8_t cmd[10];
|
|
|
|
if (cst816d_enter_bootmode() == -1) {
|
|
//printf("%s %d \r\n", __FUNCTION__, __LINE__);
|
|
return -1;
|
|
}
|
|
sum_len = 0;
|
|
do {
|
|
if (sum_len >= len) {
|
|
return -1;
|
|
}
|
|
|
|
// send address
|
|
cmd[0] = startAddr & 0xFF;
|
|
cmd[1] = startAddr >> 8;
|
|
|
|
unsigned char reg0[2] = {0xA0, 0x14};
|
|
system_iic_write_nbytes(__this->iic_hdl, CST816S_UPGRADE_ADD, reg0, 2, cmd, 2);
|
|
unsigned char reg1[2] = {0xA0, 0x18};
|
|
system_iic_write_nbytes(__this->iic_hdl, CST816S_UPGRADE_ADD, reg1, 2, src, PER_LEN);
|
|
|
|
cmd[0] = 0xEE;
|
|
unsigned char reg2[2] = {0xA0, 0x04};
|
|
system_iic_write_nbytes(__this->iic_hdl, CST816S_UPGRADE_ADD, reg2, 2, cmd, 1);
|
|
ctp_delay_ms(100);
|
|
//printf("%s %d \r\n", __FUNCTION__, __LINE__);
|
|
uint8_t retrycnt = 50;
|
|
while (retrycnt--) {
|
|
cmd[0] = 0;
|
|
unsigned char reg_read[2] = {0xA0, 0x05};
|
|
system_iic_read_nbytes(__this->iic_hdl, CST816S_UPGRADE_ADD, reg_read, 2, cmd, 1);
|
|
//printf("%s %d \r\n", __FUNCTION__, __LINE__);
|
|
if (cmd[0] == 0x55) {
|
|
// success
|
|
break;
|
|
}
|
|
ctp_delay_ms(10);
|
|
}
|
|
|
|
startAddr += PER_LEN;
|
|
src += PER_LEN;
|
|
sum_len += PER_LEN;
|
|
//printf("%s %d \r\n", __FUNCTION__, __LINE__);
|
|
} while (len);
|
|
|
|
// exit program mode
|
|
cmd[0] = 0x00;
|
|
unsigned char reg3[2] = {0xA0, 0x03};
|
|
system_iic_write_nbytes(__this->iic_hdl, CST816S_UPGRADE_ADD, reg3, 2, cmd, 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t cst816d_read_checksum(uint16_t startAddr, uint16_t len)
|
|
{
|
|
union {
|
|
uint32_t sum;
|
|
uint8_t buf[4];
|
|
} checksum;
|
|
|
|
unsigned char cmd[3];
|
|
char readback[4] = {0};
|
|
|
|
if (cst816d_enter_bootmode() == -1) {
|
|
return -1;
|
|
}
|
|
|
|
cmd[0] = 0;
|
|
unsigned char reg[2] = {0xA0, 0x03};
|
|
if (0 == system_iic_write_nbytes(__this->iic_hdl, CST816S_UPGRADE_ADD, reg, 2, cmd, 1)) {
|
|
return -1;
|
|
}
|
|
ctp_delay_ms(500);
|
|
|
|
checksum.sum = 0;
|
|
unsigned char reg_read[2] = {0xA0, 0x08};
|
|
if (0 == system_iic_read_nbytes(__this->iic_hdl, CST816S_UPGRADE_ADD, reg_read, 2, checksum.buf, 2)) {
|
|
return -1;
|
|
}
|
|
log_debug("%s checksum.sum 0x%x \r\n", __FUNCTION__, checksum.sum);
|
|
return checksum.sum;
|
|
}
|
|
|
|
static bool cst816d_upgrade(void)
|
|
{
|
|
uint8_t lvalue;
|
|
|
|
if (cst816d_enter_bootmode() == 0) {
|
|
log_debug("%s %d \r\n", __FUNCTION__, __LINE__);
|
|
if (sizeof(app_bin) > 10) {
|
|
log_debug("%s %d \r\n", __FUNCTION__, __LINE__);
|
|
uint16_t startAddr = app_bin[1];
|
|
uint16_t length = app_bin[3];
|
|
uint16_t checksum = app_bin[5];
|
|
startAddr <<= 8;
|
|
startAddr |= app_bin[0];
|
|
length <<= 8;
|
|
length |= app_bin[2];
|
|
checksum <<= 8;
|
|
checksum |= app_bin[4];
|
|
|
|
log_debug("checksum = 0x%x\n", checksum);
|
|
if (cst816d_read_checksum(startAddr, length) != checksum) {
|
|
#if CONFIG_JL_UI_ENABLE
|
|
ui_auto_shut_down_disable();//防止息屏时间太短导致升级出现异常
|
|
#endif
|
|
cst816d_update(startAddr, length, (uint8_t *)(app_bin + 6));
|
|
cst816d_read_checksum(startAddr, length);
|
|
#if CONFIG_JL_UI_ENABLE
|
|
ui_auto_shut_down_enable();
|
|
#endif
|
|
log_debug("%s %d \r\n", __FUNCTION__, __LINE__);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static void cst816d_reset()
|
|
{
|
|
CST816S_RESET_H();
|
|
log_debug("cst816d_reset_h\n");
|
|
ctp_delay_ms(10);
|
|
CST816S_RESET_L();
|
|
log_debug("cst816d_reset_l\n");
|
|
ctp_delay_ms(10);
|
|
CST816S_RESET_H();
|
|
log_debug("cst816d_reset_h\n");
|
|
//ctp_delay_us(5000);//5ms
|
|
ctp_delay_ms(10);
|
|
}
|
|
|
|
static void ctp_sleep_cst816d(void)
|
|
{
|
|
unsigned char data = 0;
|
|
unsigned char aa = 0, bb = 0;
|
|
|
|
/* unsigned char sleepCmd[] = {0xa5, 0x03}; */
|
|
#if TP_DOUBLE_CLICK_WAKEUP
|
|
CST816S_RESET_L();
|
|
ctp_delay_ms(10);
|
|
CST816S_RESET_H();
|
|
ctp_delay_ms(100);
|
|
unsigned char double_click_Cmd[] = {0xe5, 0x01};
|
|
int ret = system_iic_write_nbytes(__this->iic_hdl, SLAVE_DEV_ADDR, NULL, 0, double_click_Cmd, sizeof(double_click_Cmd));
|
|
unsigned char sleepCmd[] = {0xfe, 0x00};
|
|
system_iic_write_nbytes(__this->iic_hdl, SLAVE_DEV_ADDR, NULL, 0, sleepCmd, 1);
|
|
/* system_iic_read_nbytes(__this->iic_hdl, SLAVE_DEV_ADDR + 1, NULL, 0, &aa, 1); */
|
|
ctp_delay_ms(10);
|
|
bb = system_iic_write_nbytes(__this->iic_hdl, SLAVE_DEV_ADDR, NULL, 0, sleepCmd, sizeof(sleepCmd));
|
|
log_info("ctp_sleep_cst816d aa=%d,bb=%d", aa, bb);
|
|
#else
|
|
unsigned char sleepCmd[] = {0xe5, 0x03};
|
|
system_iic_write_nbytes(__this->iic_hdl, SLAVE_DEV_ADDR, NULL, 0, sleepCmd, 1);
|
|
system_iic_read_nbytes(__this->iic_hdl, SLAVE_DEV_ADDR + 1, NULL, 0, &aa, 1);
|
|
|
|
ctp_delay_ms(10);
|
|
bb = system_iic_write_nbytes(__this->iic_hdl, SLAVE_DEV_ADDR, NULL, 0, sleepCmd, sizeof(sleepCmd));
|
|
log_info("ctp_sleep_cst816d aa=%d,bb=%d", aa, bb);
|
|
#endif
|
|
// ctp_delay_ms(100); //和显示屏共用delay耗时
|
|
|
|
/* #ifdef INT_PIN_WAKEUP */
|
|
/* bl_ts_set_intmode(0); */
|
|
/* bl_ts_set_intup(1); */
|
|
/* #endif */
|
|
|
|
system_iic_deinit(__this->iic_hdl);
|
|
|
|
#if (defined TCFG_COLOR_SCREEN_CHARGING_CASE_ENABLE) && TCFG_COLOR_SCREEN_CHARGING_CASE_ENABLE
|
|
// gpio_set_mode(IO_PORT_SPILT(TCFG_TP_INT_IO), PORT_HIGHZ);
|
|
#else
|
|
gpio_set_mode(IO_PORT_SPILT(TCFG_TP_INT_IO), PORT_HIGHZ);
|
|
#endif
|
|
gpio_set_mode(IO_PORT_SPILT(TCFG_TP_RESET_IO), PORT_HIGHZ);
|
|
|
|
log_info("ctp_sleep_cst816d");
|
|
}
|
|
|
|
static void ctp_wakeup_cst816d(void)
|
|
{
|
|
/* #ifdef RESET_PIN_WAKEUP */
|
|
cst816d_reset();
|
|
#if (defined TCFG_COLOR_SCREEN_CHARGING_CASE_ENABLE) && TCFG_COLOR_SCREEN_CHARGING_CASE_ENABLE
|
|
// gpio_set_mode(IO_PORT_SPILT(TCFG_TP_INT_IO), PORT_INPUT_PULLUP_10K);
|
|
#else
|
|
gpio_set_mode(IO_PORT_SPILT(TCFG_TP_INT_IO), PORT_INPUT_PULLUP_10K);
|
|
#endif
|
|
system_iic_init(__this->iic_hdl, get_iic_config(__this->iic_hdl));
|
|
/* #endif */
|
|
/* #ifdef INT_PIN_WAKEUP */
|
|
/* bl_ts_int_wakeup(); */
|
|
/* #endif */
|
|
/* bl_ts_set_intmode(1);//开io中断 */
|
|
log_info("ctp_wakeup_cst816d");
|
|
}
|
|
|
|
|
|
#if (!CONFIG_LVGL_UI_ENABLE)
|
|
|
|
static void tke_start(int x, int y)
|
|
{
|
|
memcpy(&tke[0], &tke[1], sizeof(struct touch_kinetic_energy) * (ENERGY_NUM - 1));
|
|
|
|
tke[ENERGY_NUM - 1].x = x;
|
|
tke[ENERGY_NUM - 1].y = y;
|
|
log_info("tke start %d, %d\n", x, y);
|
|
}
|
|
|
|
static void tke_stop(int x, int y, struct touch_event *up_t)
|
|
{
|
|
struct touch_event t = {0};
|
|
int tke_x = 0;
|
|
int tke_y = 0;
|
|
u8 xdir, ydir;
|
|
|
|
for (int i = 0; i < (ENERGY_NUM - 1); i++) {
|
|
if ((tke[i].x == 0xffff) || (tke[i].y == 0xffff)) {
|
|
continue;
|
|
}
|
|
int tmp_x = (int)tke[i + 1].x - (int)tke[i].x;
|
|
int tmp_y = (int)tke[i + 1].y - (int)tke[i].y;
|
|
if (abs(tke_x) < abs(tmp_x)) {
|
|
tke_x = tmp_x;
|
|
}
|
|
if (abs(tke_y) < abs(tmp_y)) {
|
|
tke_y = tmp_y;
|
|
}
|
|
log_info("[%d], x:0x%x, y:0x%x", i, tke[i].x, tke[i].y);
|
|
log_info("stke %d, %d\n", tke_x, tke_y);
|
|
}
|
|
log_info("stke end %d, %d\n", tke_x, tke_y);
|
|
|
|
if (((abs(tke_x) >= ENERGY_XDISTANCE) || abs(tke_y) >= ENERGY_YDISTANCE)) {
|
|
up_t->has_energy = 1;
|
|
ui_touch_msg_post(up_t);
|
|
|
|
if (abs(tke_x) < ENERGY_XDISTANCE) {
|
|
tke_x = 0;
|
|
}
|
|
if (abs(tke_y) < ENERGY_YDISTANCE) {
|
|
tke_y = 0;
|
|
}
|
|
xdir = (tke_x < 0) ? 1 : 2;
|
|
ydir = (tke_y < 0) ? 1 : 2;
|
|
/* printf("xdir %d, ydir %d\n", xdir, ydir); */
|
|
|
|
t.event = ELM_EVENT_TOUCH_ENERGY;
|
|
t.x = (tke_x << 16) | (ENERGY_T_MS & 0xffff);
|
|
t.y = (tke_y << 16) | (ydir << 8) | (xdir & 0xff);
|
|
ui_touch_msg_post(&t);
|
|
|
|
/* printf("tke out %d, %d, %d, %d, %d\n", (t.x & 0xffff), (t.x >> 16), (t.y >> 16), (t.y & 0xff), (t.y >> 8) & 0xff); */
|
|
|
|
} else {
|
|
//在这里发送up消息,因为没有惯性,所以直接发送
|
|
ui_touch_msg_post(up_t);
|
|
}
|
|
|
|
memset(&tke, 0xff, sizeof(tke));
|
|
|
|
}
|
|
|
|
|
|
static void tpd_down(int raw_x, int raw_y, int x, int y, int p)
|
|
{
|
|
struct touch_event t;
|
|
static int first_x = 0;
|
|
static int first_y = 0;
|
|
static u8 move_flag = 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.event = tp_last_staus;
|
|
t.x = x;
|
|
t.y = y;
|
|
ui_touch_msg_post(&t);
|
|
return;
|
|
}
|
|
|
|
log_info("D[%4d %4d %4d]\n", x, y, p);
|
|
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) {
|
|
#if TCFG_COLOR_SCREEN_CHARGING_CASE_ENABLE
|
|
if (y_move < SINGLE_SLIDING) {
|
|
tp_last_staus = ELM_EVENT_TOUCH_R_MOVE;
|
|
}
|
|
#else
|
|
tp_last_staus = ELM_EVENT_TOUCH_R_MOVE;
|
|
#endif
|
|
} else {
|
|
tp_last_staus = ELM_EVENT_TOUCH_L_MOVE;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (y > first_y) {
|
|
tp_last_staus = ELM_EVENT_TOUCH_D_MOVE;
|
|
} else {
|
|
tp_last_staus = ELM_EVENT_TOUCH_U_MOVE;
|
|
}
|
|
}
|
|
move_flag = 1;
|
|
} else {
|
|
if ((x == first_x) && (y == first_y)) {
|
|
return;
|
|
}
|
|
tp_last_staus = ELM_EVENT_TOUCH_MOVE;
|
|
/* return; */
|
|
}
|
|
/* tp_last_staus = ELM_EVENT_TOUCH_HOLD; */
|
|
tke_start(x, y);
|
|
} else {
|
|
tp_last_staus = ELM_EVENT_TOUCH_DOWN;
|
|
first_x = x;
|
|
first_y = y;
|
|
move_flag = 0;
|
|
tke_start(x, y);
|
|
}
|
|
|
|
t.event = tp_last_staus;
|
|
t.x = x;
|
|
t.y = y;
|
|
ui_touch_msg_post(&t);
|
|
}
|
|
|
|
|
|
|
|
static void tpd_up(int raw_x, int raw_y, int x, int y, int p)
|
|
{
|
|
struct touch_event t = {0};
|
|
|
|
if (tp_last_staus == ELM_EVENT_TOUCH_UP) {
|
|
return ; // 重复
|
|
}
|
|
|
|
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.event = tp_last_staus;
|
|
t.x = x;
|
|
t.y = y;
|
|
|
|
//不在这里发送up消息,在tke_stop里面!!!
|
|
/* ui_touch_msg_post(&t); */
|
|
|
|
tke_stop(x, y, &t);
|
|
|
|
}
|
|
|
|
static bool cst816d_read(void)
|
|
{
|
|
unsigned char buf[5];
|
|
u8 reg_addr[1] = {0x2};
|
|
system_iic_read_nbytes(__this->iic_hdl, HYN_I2C_ADDR, ®_addr[0], 1, &buf[0], 5);
|
|
int point_x = buf[2] | ((buf[1] & 0xF) << 8);
|
|
int point_y = buf[4] | ((buf[3] & 0xF) << 8);
|
|
if (buf[0] != 0) {
|
|
tpd_down(0, 0, point_x, point_y, 0);
|
|
} else {
|
|
tpd_up(0, 0, point_x, point_y, 0);
|
|
}
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_LVGL_UI_ENABLE
|
|
void get_touch_x_y_status(int32_t *x, int32_t *y, uint8_t *status)
|
|
{
|
|
*x = g_touch_data.point.x;
|
|
*y = g_touch_data.point.y;
|
|
*status = g_touch_data.state;
|
|
}
|
|
|
|
static bool cst816d_lvgl_read(lv_touch_data_t *data)
|
|
{
|
|
unsigned irq_state;
|
|
unsigned char buf[5];
|
|
int update = 0;
|
|
static int x_last, y_last;
|
|
u8 reg_addr[1] = {0x2};
|
|
|
|
/* if (update) { */
|
|
system_iic_read_nbytes(__this->iic_hdl, HYN_I2C_ADDR, ®_addr[0], 1, &buf[0], 5);
|
|
data->point.x = buf[2] | ((buf[1] & 0xF) << 8);
|
|
data->point.y = buf[4] | ((buf[3] & 0xF) << 8);
|
|
x_last = data->point.x;
|
|
y_last = data->point.y;
|
|
data->state = (buf[0] != 0) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
|
log_debug("finger:%d, (%d, %d), %s\n", buf[0], data->point.x, data->point.y, (data->state == LV_INDEV_STATE_PR) ? "pressed" : "released");
|
|
if ((data->point.x == VK_X) && (data->point.y == VK_Y)) {
|
|
vk_state = data->state;
|
|
//printf("vk %s\n", (vk_state == LV_INDEV_STATE_PR) ? "press" : "release");
|
|
}
|
|
/* } else { */
|
|
/* data->point.x = x_last; */
|
|
/* data->point.y = y_last; */
|
|
/* data->state = LV_INDEV_STATE_REL; */
|
|
/* } */
|
|
|
|
return false; /* no more data to read */
|
|
}
|
|
|
|
static void CST816D_get_touch_xy(void)
|
|
{
|
|
if (!touch_flag) {
|
|
return ;
|
|
}
|
|
|
|
touch_flag = 0;
|
|
|
|
lv_touch_data_t touch_data;
|
|
cst816d_lvgl_read(&touch_data);
|
|
g_touch_data.point.x = touch_data.point.x;
|
|
g_touch_data.point.y = touch_data.point.y;
|
|
g_touch_data.state = (touch_data.state == LV_INDEV_STATE_PR) ? 1 : 0;
|
|
}
|
|
|
|
|
|
__attribute__((weak)) int lcd_touch_interrupt_event(const char *tp_task_name, u16 x, u16 y, u8 status)
|
|
{
|
|
log_info("Please implement this function to post coordinate data to UI!");
|
|
return 0;
|
|
}
|
|
#endif /* #if CONFIG_LVGL_UI_ENABLE */
|
|
|
|
|
|
static void cst816d_hw_init(void)
|
|
{
|
|
u8 buf[1];
|
|
u8 reg_addr[1];
|
|
int i;
|
|
int ret;
|
|
|
|
memset(&tke, 0xff, sizeof(tke));
|
|
|
|
log_info("cst816d init...\n");
|
|
ret = system_iic_init(__this->iic_hdl, get_iic_config(__this->iic_hdl));
|
|
log_debug("[%s] iic_init ret:%d", __func__, ret);
|
|
|
|
cst816d_reset();
|
|
ctp_delay_ms(100);
|
|
buf[0] = 0;
|
|
reg_addr[0] = 0xa7;
|
|
system_iic_read_nbytes(__this->iic_hdl, HYN_I2C_ADDR, ®_addr[0], 1, &buf[0], 1);
|
|
log_info("tp id : 0x%x\n", buf[0]);
|
|
|
|
buf[0] = 0;
|
|
reg_addr[0] = 0xa9;
|
|
system_iic_read_nbytes(__this->iic_hdl, HYN_I2C_ADDR, ®_addr[0], 1, &buf[0], 1);
|
|
log_info("tp version : 0x%x\n", buf[0]);
|
|
|
|
if (!cst816d_upgrade()) {
|
|
log_error("cst816d_upgrade fail!\n");
|
|
/* ASSERT(0); */
|
|
}
|
|
cst816d_reset();
|
|
|
|
//配置触摸脉冲报点时间间隔不要超过屏帧率, ~20ms
|
|
//buf[0]=0x4;
|
|
//i2c_write_regs(I2C_MASTER_CI2C0, HYN_I2C_ADDR, 0xee, &buf[0], 1, 0);
|
|
}
|
|
|
|
static void touch_interupt_task(void *p)
|
|
{
|
|
int sem_timeout = 0;
|
|
|
|
cst816d_hw_init();
|
|
|
|
os_sem_create(&touch_sem, 0);
|
|
tp_irq_init();
|
|
|
|
while (1) {
|
|
tp_step = TP_RUN_STEP_RUN_IDLE;
|
|
os_sem_pend(&touch_sem, sem_timeout);
|
|
tp_step = TP_RUN_STEP_RUN;
|
|
|
|
#if CONFIG_LVGL_UI_ENABLE
|
|
|
|
CST816D_get_touch_xy(); //每次都读出触摸坐标,防止延迟读取读的是旧坐标
|
|
|
|
|
|
if (lcd_touch_interrupt_event(TP_TASK_NAME, g_touch_data.point.x, g_touch_data.point.y, g_touch_data.state)) { //UI线程跑得慢,触摸事件处理不过来
|
|
sem_timeout = 2; //按压坐标可丢失,抬起事件不可丢失,特意延后20ms再次读取坐标推送事件
|
|
continue;
|
|
}
|
|
|
|
sem_timeout = 0;
|
|
|
|
#else /* #if CONFIG_LVGL_UI_ENABLE */
|
|
|
|
if (touch_flag) {
|
|
touch_flag = 0;
|
|
cst816d_read();
|
|
}
|
|
#endif /* #if CONFIG_LVGL_UI_ENABLE */
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void ctp_enter_sleep(void)
|
|
{
|
|
ctp_sleep_cst816d();
|
|
}
|
|
void ctp_exit_sleep(void)
|
|
{
|
|
ctp_wakeup_cst816d();
|
|
}
|
|
|
|
void cst816d_wait_init()
|
|
{
|
|
while (tp_step == TP_RUN_STEP_INIT) {
|
|
os_time_dly(1);
|
|
}
|
|
}
|
|
|
|
void cst816d_init()
|
|
{
|
|
tp_step = TP_RUN_STEP_INIT;
|
|
task_create(touch_interupt_task, NULL, "touch_task");
|
|
}
|
|
|
|
void cst816d_deinit()
|
|
{
|
|
cst816d_wait_init();
|
|
|
|
tp_irq_deinit();
|
|
while (tp_step == TP_RUN_STEP_RUN) {
|
|
os_time_dly(1);
|
|
}
|
|
int ret = task_kill("touch_task");
|
|
ASSERT(!ret);
|
|
os_sem_del(&touch_sem, OS_DEL_ALWAYS);
|
|
system_iic_deinit(__this->iic_hdl);
|
|
|
|
gpio_set_mode(IO_PORT_SPILT(TCFG_TP_RESET_IO), PORT_HIGHZ);
|
|
|
|
tp_step = TP_RUN_STEP_STOP;
|
|
}
|
|
static u8 tp_idle_query(void)
|
|
{
|
|
return !tp_step;
|
|
}
|
|
|
|
#if (!TP_DOUBLE_CLICK_WAKEUP)
|
|
REGISTER_LP_TARGET(tp_lp_target) = {
|
|
.name = "tp_cst816d",
|
|
.is_idle = tp_idle_query,
|
|
};
|
|
#endif
|
|
|
|
|
|
#endif //CST816S_COB==1
|
|
|
|
#endif
|
|
|
|
|
|
|