mcu_hi3321_watch/tjd/driver/tp/ft6146/tp_drv_ft6146.c
2025-05-26 20:15:20 +08:00

445 lines
11 KiB
C

/*----------------------------------------------------------------------------
* Copyright (c) TJD Technologies Co., Ltd. 2024. All rights reserved.
*
* Description: tp_drv_ft6146.c
*
* Author: luziquan@ss-tjd.com
*
* Create: 2024-04-18
*--------------------------------------------------------------------------*/
#include "tp_drv_ft6146.h"
#include "cmsis_os2.h"
#include "common_def.h"
#include "osal_mutex.h"
#include "osal_timer.h"
#include "soc_errno.h"
#include "sys_config.h"
#include "tcxo.h"
#include "tp_port_ctrl.h"
#define ENABLE_PRINT_INFO 1
#if ENABLE_PRINT_INFO
#define static_print_info(...) sys_tp_log_i(__VA_ARGS__) // 一般信息打印宏控制
#define static_print_warn(...) sys_tp_log_w(__VA_ARGS__) // 警告信息打印一般常开
#define static_print_error(...) sys_tp_log_e(__VA_ARGS__) // 错误信息打印一般常开
#else
#define static_print_info(...)
#define static_print_warn(...)
#define static_print_error(...)
#endif
#ifndef FT6146_I2C_ADDR
#define FT6146_I2C_ADDR 0x38
#endif
ft6146_drv_data g_ft6146_drv = {
.chip_status = FT6146_NOT_READY,
.ops_mux = {0},
.work_status = TP_WORK_INVALID,
.fw_upgrade_flag = TD_TRUE,
.gesture_wakeup = TD_FALSE,
};
ext_errno ft6146_get_rawdata(uint8_t *ret_buf)
{
ext_errno ret;
ret = tp_i2c_data_read(FT6146_I2C_ADDR, TP_RAWDATA, 1, ret_buf, TP_DATA_LEN);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
return ret;
}
ext_errno ft6146_get_chip_id(uint16_t *ret_buf)
{
ext_errno ret;
uint8_t hw_id_high = 0;
uint8_t hw_id_low = 0;
ret = tp_i2c_data_read(FT6146_I2C_ADDR, TP_CHIP_ID_HIGH, 1, &hw_id_high, TP_DATA_LEN);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
ret = tp_i2c_data_read(FT6146_I2C_ADDR, TP_CHIP_ID_LOW, 1, &hw_id_low, TP_DATA_LEN);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
*ret_buf = ((uint16_t)hw_id_high << OFFSET_8_BITS) | hw_id_low;
return ret;
}
ext_errno ft6146_get_version(uint16_t *ret_buf)
{
ext_errno ret;
uint8_t firm_vers[TP_FIRMWARE_VERSION_LEN];
ret = tp_i2c_data_read(FT6146_I2C_ADDR, TP_FIRMWARE_VERSION, 1, firm_vers, TP_FIRMWARE_VERSION_LEN);
if (ret != EXT_ERR_SUCCESS) {
return EXT_ERR_FAILURE;
}
*ret_buf = ((firm_vers[TP_I2C_SEND_INDEX0] & 0x0F) << OFFSET_8_BITS) | firm_vers[TP_I2C_SEND_INDEX1];
return ret;
}
static ext_errno ft6146_parse_touch_input(void)
{
uint8_t touch_input[FT6146_TOUCHINFO_LEN] = {0};
uint32_t x_axis;
uint32_t y_axis;
ext_errno ret = tp_i2c_data_read(FT6146_I2C_ADDR, FT6146_TP_REG_X1, 1, touch_input, FT6146_TOUCHINFO_LEN);
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: touch input read error! ret = 0x%x", ret);
return EXT_ERR_FAILURE;
}
x_axis = (uint32_t)((touch_input[FT6146_XH_OFFSET] & 0X0F) << 8) | touch_input[FT6146_XL_OFFSET];
y_axis = (uint32_t)((touch_input[FT6146_YH_OFFSET] & 0X0F) << 8) | touch_input[FT6146_YL_OFFSET];
uint8_t event_value = touch_input[FT6146_EVENT_OFFSET] & 0XC0;
switch (event_value) {
case PRESS_DOWN:
g_ft6146_drv.touch_msg.tp_event = MC_TP_PRESS;
break;
case LIFT_UP:
g_ft6146_drv.touch_msg.tp_event = MC_TP_RELEASE;
break;
case CONTACT:
g_ft6146_drv.touch_msg.tp_event = MC_TP_MOVE;
break;
default:
return EXT_ERR_FAILURE;
}
g_ft6146_drv.touch_msg.tp_event_info.x_axis[FT6146_POINT1_INDEX] = x_axis;
g_ft6146_drv.touch_msg.tp_event_info.y_axis[FT6146_POINT1_INDEX] = y_axis;
g_ft6146_drv.touch_msg.tv_usec = (uint32_t)uapi_tcxo_get_ms();
return EXT_ERR_SUCCESS;
}
static ext_errno ft6146_parse_input(void)
{
ext_errno ret = EXT_ERR_FAILURE;
uint16_t reg_write;
ret = ft6146_parse_touch_input();
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: parse touch input fail 0x%x", ret);
return EXT_ERR_FAILURE;
}
return EXT_ERR_SUCCESS;
}
ext_errno ft6146_irq_callback(uint8_t *data_buf, uint8_t data_len)
{
unused(data_len);
ext_errno ret;
int32_t mem_ret;
uint16_t reg_write;
g_ft6146_drv.touch_msg.tp_event = MC_TP_INVALID;
if ((g_ft6146_drv.work_status == TP_WORK_NORMAL) || (g_ft6146_drv.work_status == TP_WORK_STANDBY)) {
ret = ft6146_parse_input();
if (ret != EXT_ERR_SUCCESS) {
ft6146_init();
static_print_error("TOUCH: touch parse input fail, ret = 0x%x", ret);
return EXT_ERR_FAILURE;
}
}
mem_ret = memcpy_s(data_buf, sizeof(input_event_info), &(g_ft6146_drv.touch_msg), sizeof(input_event_info));
if (mem_ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: mem cpy error, ret = 0x%x", mem_ret);
return EXT_ERR_FAILURE;
}
return EXT_ERR_SUCCESS;
}
static ext_errno ft6146_write_power_mode(ft6146_event_status power_mode)
{
ext_errno ret;
uint16_t reg_write;
uint8_t retry_times = 0;
/* Send Sleep Cmd */
reg_write = FT6146_POWER_MODE;
for (retry_times = 0; retry_times < TP_INIT_RETRY_TIMERS; retry_times++) {
ret = tp_i2c_reg_write(FT6146_I2C_ADDR, FT6146_POWER_MODE, 1, power_mode);
if (ret == EXT_ERR_SUCCESS) {
break;
}
tp_delay(FT6146_GENERAL_DELAY_10);
}
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
tp_delay(FT6146_GENERAL_DELAY_10);
return EXT_ERR_SUCCESS;
}
static ext_errno ft6146_set_normal_mode(void)
{
ext_errno ret;
if (g_ft6146_drv.work_status == TP_WORK_NORMAL) {
static_print_info("TOUCH: alread normal");
return EXT_ERR_SUCCESS;
}
if (g_ft6146_drv.work_status == TP_WORK_SLEEP || g_ft6146_drv.work_status == TP_WORK_INVALID) {
tp_reset();
}
ret = ft6146_write_power_mode(WORK_MODE);
if (ret != EXT_ERR_SUCCESS) {
return EXT_ERR_FAILURE;
}
g_ft6146_drv.work_status = WORK_MODE;
static_print_info("TOUCH: normal mode");
return EXT_ERR_SUCCESS;
}
static ext_errno ft6146_set_standby_mode(void)
{
ext_errno ret;
if (g_ft6146_drv.work_status == TP_WORK_STANDBY) {
static_print_info("TOUCH: alread standby");
return EXT_ERR_SUCCESS;
}
if (g_ft6146_drv.work_status == TP_WORK_SLEEP || g_ft6146_drv.work_status == TP_WORK_INVALID) {
tp_reset();
}
ret = ft6146_write_power_mode(MONITOR_MODE);
if (ret != EXT_ERR_SUCCESS) {
return EXT_ERR_FAILURE;
}
g_ft6146_drv.work_status = MONITOR_MODE;
static_print_info("TOUCH: low power");
return EXT_ERR_SUCCESS;
}
static ext_errno ft6146_set_sleep_mode(void)
{
ext_errno ret;
if (g_ft6146_drv.work_status == SLEEP_MODE) {
static_print_info("TOUCH: alread sleep");
return EXT_ERR_SUCCESS;
}
ret = ft6146_write_power_mode(SLEEP_MODE);
if (ret != EXT_ERR_SUCCESS) {
return EXT_ERR_FAILURE;
}
g_ft6146_drv.work_status = SLEEP_MODE;
static_print_info("TOUCH: sleep");
return EXT_ERR_SUCCESS;
}
ext_errno ft6146_set_power_mode(uint8_t power_mode)
{
ext_errno ret = EXT_ERR_SUCCESS;
switch (power_mode) {
case TP_WORK_NORMAL:
ret = ft6146_set_normal_mode();
break;
case TP_WORK_SLEEP:
ret = ft6146_set_sleep_mode();
break;
case TP_WORK_STANDBY:
ret = ft6146_set_standby_mode();
break;
default:
static_print_error("TOUCH: ft6146 not support powermode 0x%x", power_mode);
ret = EXT_ERR_FAILURE;
break;
}
return ret;
}
static ext_errno ft6146_configuration(void)
{
ext_errno ret;
/* Read Firmware Version */
ret = ft6146_get_version(&g_ft6146_drv.firmware_version);
if (ret != EXT_ERR_SUCCESS) {
return EXT_ERR_FAILURE;
}
/* Read Hw ID */
ret = ft6146_get_chip_id(&g_ft6146_drv.chip_id);
if (ret != EXT_ERR_SUCCESS) {
return EXT_ERR_FAILURE;
}
static_print_info("TOUCH: TP_FIRMWARE_VERSION[0x%x] FT6146_CHIP_ID[0x%x]", g_ft6146_drv.firmware_version,
g_ft6146_drv.chip_id);
return EXT_ERR_SUCCESS;
}
static ext_errno ft6146_resource_deinit(void)
{
g_ft6146_drv.work_status = TP_WORK_INVALID;
g_ft6146_drv.fw_upgrade_flag = TD_FALSE;
osal_mutex_destroy(&g_ft6146_drv.ops_mux);
return EXT_ERR_SUCCESS;
}
static ext_errno ft6146_config(void)
{
ext_errno ret;
/* Step 1 hardware reset */
tp_reset();
/* Step 2 configuration */
ret = ft6146_configuration();
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: init config fail 0x%x", ret);
return EXT_ERR_FAILURE;
}
/* Step 4 check upgrade */
if (g_ft6146_drv.fw_upgrade_flag == TD_TRUE) {
ret = fts_fwupg_auto_upgrade();
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: auto upgrade fail 0x%x", ret);
return EXT_ERR_FAILURE;
}
}
/* Record Status For Init */
g_ft6146_drv.chip_status = FT6146_READY;
g_ft6146_drv.work_status = TP_WORK_NORMAL;
return EXT_ERR_SUCCESS;
}
ext_errno ft6146_init(void)
{
ext_errno ret = EXT_ERR_FAILURE;
ext_errno err_ret;
/* create tp operation mutex */
if (g_ft6146_drv.ops_mux.mutex == NULL) {
ret = osal_mutex_init(&(g_ft6146_drv.ops_mux));
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: ft6146 init create mux lock fail 0x%x", ret);
return EXT_ERR_FAILURE;
}
}
/* get tp operater mutex */
ret = osal_mutex_lock_timeout(&g_ft6146_drv.ops_mux, FT6146_OPERATER_MUTEX_WAIT_TIME);
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: ft6146 init wait mux lock fail 0x%x", ret);
goto init_fail;
}
/* tp hardware reset and init */
ret = ft6146_config();
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: ft6146 init fail 0x%x", ret);
goto init_fail;
}
/* release tp operater mutex */
osal_mutex_unlock(&g_ft6146_drv.ops_mux);
static_print_info("TOUCH: FT6146 INIT Success!");
return EXT_ERR_SUCCESS;
init_fail:
/* release tp operater mutex */
osal_mutex_unlock(&g_ft6146_drv.ops_mux);
err_ret = ft6146_resource_deinit();
if (err_ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: delete mux lock err! ret = 0x%x", err_ret);
}
return ret;
}
ext_errno ft6146_deinit(void)
{
ext_errno ret = ft6146_resource_deinit();
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: ft6146 deinit fail! ret = 0x%x", ret);
return ret;
}
return EXT_ERR_SUCCESS;
}
ext_errno ft6146_resume(void)
{
ext_errno ret;
uint8_t retry_times = 0;
tp_reset();
if (retry_times == TP_INIT_RETRY_TIMERS) {
static_print_error("resume: overtimes %d", retry_times);
goto resume_exit;
}
g_ft6146_drv.work_status = TP_WORK_NORMAL;
#ifdef FT6146_GESTURE_WAKEUP
g_ft6146_drv.gesture_wakeup = TD_FALSE;
#endif
return EXT_ERR_SUCCESS;
resume_exit:
static_print_error("TOUCH: resume failed 0x%x", ret);
return EXT_ERR_FAILURE;
}
ext_errno ft6146_suspend(void)
{
ext_errno ret;
ret = ft6146_set_power_mode(TP_WORK_SLEEP);
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: suspend fail 0x%x", ret);
return EXT_ERR_FAILURE;
}
return EXT_ERR_SUCCESS;
}
ext_errno ft6146_sleep(void)
{
ext_errno ret;
ret = ft6146_set_power_mode(TP_WORK_SLEEP);
if (ret != EXT_ERR_SUCCESS) {
static_print_error("TOUCH: sleep fail 0x%x", ret);
return EXT_ERR_FAILURE;
}
return EXT_ERR_SUCCESS;
}