Added ITE IT7259 touch sensor.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
parent
954c38ac5a
commit
dd9e014464
|
@ -12,6 +12,7 @@ set(IMSENSORS_SRCS
|
|||
"src/imu/imu_lsm6dsl.c"
|
||||
"src/magnetic/magnetic_bmm150.c"
|
||||
"src/ppg/ppg_pah8001.c"
|
||||
"src/touch/tp_it7259.c"
|
||||
)
|
||||
|
||||
set(IMSENSORS_INCS
|
||||
|
@ -22,6 +23,7 @@ set(IMSENSORS_INCS
|
|||
"include/imsensors/imu"
|
||||
"include/imsensors/magnetic"
|
||||
"include/imsensors/ppg"
|
||||
"include/imsensors/touch"
|
||||
)
|
||||
|
||||
set(IMSENSORS_INTF_INCS
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef TP_IT7259_H
|
||||
#define TP_IT7259_H
|
||||
|
||||
#include "imsensors/common/sensors_common.h"
|
||||
|
||||
typedef enum {
|
||||
IT7259_PRES_NONE = 0U,
|
||||
IT7259_PRES_HOVER = 1U,
|
||||
IT7259_PRES_LIGHT = 2U,
|
||||
IT7259_PRES_NORMAL = 4U,
|
||||
IT7259_PRES_HIGH = 8U,
|
||||
IT7259_PRES_HEAVY = 0x0FU,
|
||||
} ims_it7259_pres_t;
|
||||
|
||||
typedef struct {
|
||||
ims_i2c_xfer_t i2c_xfer;
|
||||
ims_delay_t delay;
|
||||
} ims_it7259_cb_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t rom_version;
|
||||
uint32_t fw_version;
|
||||
uint8_t vendor_fw_version;
|
||||
} ims_it7259_sensor_fw_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t id;
|
||||
uint16_t pos_x;
|
||||
uint16_t pos_y;
|
||||
ims_it7259_pres_t pres;
|
||||
} ims_it7259_point_t;
|
||||
|
||||
typedef struct {
|
||||
ims_it7259_cb_t cb;
|
||||
void *pdev;
|
||||
|
||||
ims_it7259_sensor_fw_info_t fw_info;
|
||||
|
||||
uint16_t resolution_x;
|
||||
uint16_t resolution_y;
|
||||
} ims_it7259_t;
|
||||
|
||||
ims_ret_t ims_it7259_init(ims_it7259_t *tp);
|
||||
ims_ret_t ims_it7259_read_points(ims_it7259_t *tp, uint8_t *num_tp, ims_it7259_point_t *points);
|
||||
|
||||
#endif // TP_IT7259_H
|
|
@ -0,0 +1,300 @@
|
|||
#include "tp_it7259.h"
|
||||
|
||||
#define ITE_BUF_LEN (18) /* This assumes the maximum payload length does not exceed this value */
|
||||
|
||||
#define ITE_QUERY_TIMEOUT (10) /* The device sometimes gives NAK for query command */
|
||||
|
||||
#define ITE_BUF_Pos (5U)
|
||||
#define ITE_BUF_Msk (7U << ITE_BUF_Pos)
|
||||
|
||||
#define ITE_QUERY_STAT_Pos (0U)
|
||||
#define ITE_QUERY_STAT_Msk (3U << ITE_QUERY_STAT_Pos)
|
||||
|
||||
#define ITE_CMD_DEVICE_NAME (0x00U)
|
||||
#define ITE_CMD_DEVICE_NAME_LEN (0x0AU)
|
||||
#define ITE_CMD_SENSOR_INFO (0x01U)
|
||||
#define ITE_SUBCMD_FW_INFO (0x00U)
|
||||
#define ITE_SUBCMD_FW_INFO_LEN (0x0AU)
|
||||
#define ITE_SUBCMD_2D_RES (0x02U)
|
||||
#define ITE_SUBCMD_2D_RES_LEN (0x0CU)
|
||||
|
||||
#define ITE_POINT_INFO_LEN (0x0EU)
|
||||
|
||||
typedef enum {
|
||||
ITE_BUF_CMD = 1U,
|
||||
ITE_BUF_QUERY = 4U,
|
||||
ITE_BUF_CMD_RESP = 5U,
|
||||
ITE_BUF_POINT = 7U,
|
||||
} ite_buf_type_t;
|
||||
|
||||
typedef enum {
|
||||
ITE_STAT_DONE = 0U,
|
||||
ITE_STAT_BUSY = 1U,
|
||||
ITE_STAT_ERROR = 2U,
|
||||
ITE_STAT_RESERVED = 3U,
|
||||
} ite_query_stat_t;
|
||||
|
||||
typedef struct __packed {
|
||||
uint8_t cmd;
|
||||
uint8_t sub;
|
||||
uint8_t params[ITE_BUF_LEN - 2];
|
||||
uint8_t sub_len;
|
||||
uint8_t params_len;
|
||||
} ite_cmd_t;
|
||||
|
||||
static const uint8_t ims_it7259_dev_name[] = {'I', 'T', 'E', '7', '2', '5', '9'};
|
||||
|
||||
static ims_ret_t ims_it7259_validate_device_name(ims_it7259_t *tp);
|
||||
static ims_ret_t ims_it7259_sensor_fw_info(ims_it7259_t *tp, ims_it7259_sensor_fw_info_t *info);
|
||||
static ims_ret_t ims_it7259_sensor_resoluion(ims_it7259_t *tp, uint16_t *res_x, uint16_t *res_y);
|
||||
static ims_ret_t ims_it7259_buf_read(ims_it7259_t *tp, ite_buf_type_t type, uint8_t *data, uint8_t len);
|
||||
static ims_ret_t ims_it7259_buf_write(ims_it7259_t *tp, ite_buf_type_t type, uint8_t *data, uint8_t len);
|
||||
static ims_ret_t ims_it7259_query(ims_it7259_t *tp, uint8_t *query_result);
|
||||
static ims_ret_t ims_it7259_command_send(ims_it7259_t *tp, ite_cmd_t *cmd);
|
||||
static ims_ret_t ims_it7259_command_recv(ims_it7259_t *tp, uint8_t *data, uint8_t len);
|
||||
static ims_ret_t ims_it7259_command_wait(ims_it7259_t *tp);
|
||||
|
||||
ims_ret_t ims_it7259_init(ims_it7259_t *tp) {
|
||||
ims_ret_t ret = ims_it7259_validate_device_name(tp);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ims_it7259_sensor_fw_info(tp, &tp->fw_info);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ims_it7259_sensor_resoluion(tp, &tp->resolution_x, &tp->resolution_y);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return IMS_SUCCESS;
|
||||
}
|
||||
|
||||
ims_ret_t ims_it7259_read_points(ims_it7259_t *tp, uint8_t *num_tp, ims_it7259_point_t *points) {
|
||||
uint8_t rx_buf[ITE_POINT_INFO_LEN];
|
||||
|
||||
uint8_t query;
|
||||
|
||||
ims_ret_t ret = ims_it7259_query(tp, &query);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((query >> 6U) == 0U) {
|
||||
*num_tp = 0U;
|
||||
|
||||
return IMS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Two conditions on query [7:6]: 1xb: New touch, 01b: Still touched */
|
||||
|
||||
ret = ims_it7259_buf_read(tp, ITE_BUF_POINT, rx_buf, ITE_POINT_INFO_LEN);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check whether this is a Point Data report */
|
||||
if ((rx_buf[0] & 0xF0) != 0x00) {
|
||||
return IMS_FAIL;
|
||||
}
|
||||
|
||||
uint8_t array_num = *num_tp;
|
||||
uint8_t current_id = 0;
|
||||
uint8_t i;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (rx_buf[0] & (1U << i)) {
|
||||
points[current_id].id = i;
|
||||
points[current_id].pos_x = rx_buf[i + 2] | (rx_buf[i + 3] & 0x0FU) << 8U;
|
||||
points[current_id].pos_y = rx_buf[i + 4] | (rx_buf[i + 3] & 0xF0U) << 4U;
|
||||
points[current_id].pres = rx_buf[i + 5] & 0x0FU;
|
||||
|
||||
current_id++;
|
||||
/* Do not exceed buffer length */
|
||||
if (array_num == current_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*num_tp = current_id;
|
||||
|
||||
return IMS_SUCCESS;
|
||||
}
|
||||
|
||||
static ims_ret_t ims_it7259_validate_device_name(ims_it7259_t *tp) {
|
||||
uint8_t name[ITE_CMD_DEVICE_NAME_LEN];
|
||||
|
||||
ite_cmd_t cmd = {
|
||||
.cmd = ITE_CMD_DEVICE_NAME,
|
||||
.sub_len = 0,
|
||||
.params_len = 0,
|
||||
};
|
||||
|
||||
ims_ret_t ret = ims_it7259_command_send(tp, &cmd);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ims_it7259_command_wait(tp);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ims_it7259_command_recv(tp, name, ITE_CMD_DEVICE_NAME_LEN);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Compare string revision. */
|
||||
for (uint8_t i = 0; i < sizeof(ims_it7259_dev_name); i++) {
|
||||
/* The first byte is length */
|
||||
if (name[i + 1] != ims_it7259_dev_name[i]) {
|
||||
return IMS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return IMS_SUCCESS;
|
||||
}
|
||||
|
||||
static ims_ret_t ims_it7259_sensor_fw_info(ims_it7259_t *tp, ims_it7259_sensor_fw_info_t *info) {
|
||||
uint8_t rx_buf[ITE_SUBCMD_FW_INFO_LEN];
|
||||
|
||||
ite_cmd_t cmd = {
|
||||
.cmd = ITE_CMD_SENSOR_INFO,
|
||||
.sub = ITE_SUBCMD_FW_INFO,
|
||||
.sub_len = 1,
|
||||
.params_len = 0,
|
||||
};
|
||||
|
||||
ims_ret_t ret = ims_it7259_command_send(tp, &cmd);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ims_it7259_command_wait(tp);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ims_it7259_command_recv(tp, rx_buf, ITE_SUBCMD_FW_INFO_LEN);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
info->rom_version = (rx_buf[1] << 24) | (rx_buf[2] << 16) | (rx_buf[3] << 8) | rx_buf[4];
|
||||
info->fw_version = (rx_buf[5] << 24) | (rx_buf[6] << 16) | (rx_buf[7] << 8) | rx_buf[8];
|
||||
info->vendor_fw_version = rx_buf[9];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ims_ret_t ims_it7259_sensor_resoluion(ims_it7259_t *tp, uint16_t *res_x, uint16_t *res_y) {
|
||||
uint8_t rx_buf[ITE_SUBCMD_2D_RES_LEN];
|
||||
|
||||
ite_cmd_t cmd = {
|
||||
.cmd = ITE_CMD_SENSOR_INFO,
|
||||
.sub = ITE_SUBCMD_2D_RES,
|
||||
.sub_len = 1,
|
||||
.params_len = 0,
|
||||
};
|
||||
|
||||
ims_ret_t ret = ims_it7259_command_send(tp, &cmd);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ims_it7259_command_wait(tp);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ims_it7259_command_recv(tp, rx_buf, ITE_SUBCMD_2D_RES_LEN);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*res_x = ((rx_buf[3] << 16U) | rx_buf[2]) + 1;
|
||||
*res_y = ((rx_buf[5] << 16U) | rx_buf[4]) + 1;
|
||||
|
||||
return IMS_SUCCESS;
|
||||
}
|
||||
|
||||
static ims_ret_t ims_it7259_buf_read(ims_it7259_t *tp, ite_buf_type_t type, uint8_t *data, uint8_t len) {
|
||||
uint8_t tx_buf[] = {(type << ITE_BUF_Pos) & ITE_BUF_Msk};
|
||||
|
||||
ims_i2c_xfer_desc_t xfer_desc = {
|
||||
.tx_data = tx_buf,
|
||||
.tx_size = 1U,
|
||||
.rx_data = data,
|
||||
.rx_size = len,
|
||||
};
|
||||
|
||||
ims_ret_t ret = tp->cb.i2c_xfer(tp->pdev, &xfer_desc);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return IMS_SUCCESS;
|
||||
}
|
||||
|
||||
static ims_ret_t ims_it7259_buf_write(ims_it7259_t *tp, ite_buf_type_t type, uint8_t *data, uint8_t len) {
|
||||
uint8_t tx_buf[ITE_BUF_LEN + 1] = {(type << ITE_BUF_Pos) & ITE_BUF_Msk};
|
||||
|
||||
memcpy(&tx_buf[1], data, len); /* ! WATCH BOUNDARY ! */
|
||||
|
||||
ims_i2c_xfer_desc_t xfer_desc = {
|
||||
.tx_data = tx_buf,
|
||||
.tx_size = len + 1,
|
||||
.rx_data = NULL,
|
||||
.rx_size = 0,
|
||||
};
|
||||
|
||||
ims_ret_t ret = tp->cb.i2c_xfer(tp->pdev, &xfer_desc);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return IMS_SUCCESS;
|
||||
}
|
||||
|
||||
static ims_ret_t ims_it7259_query(ims_it7259_t *tp, uint8_t *query_result) {
|
||||
return ims_it7259_buf_read(tp, ITE_BUF_QUERY, query_result, 0x01);
|
||||
}
|
||||
|
||||
static ims_ret_t ims_it7259_command_send(ims_it7259_t *tp, ite_cmd_t *cmd) {
|
||||
return ims_it7259_buf_write(tp, ITE_BUF_CMD, (uint8_t *)cmd, (cmd->sub_len + cmd->params_len + 1));
|
||||
}
|
||||
|
||||
static ims_ret_t ims_it7259_command_recv(ims_it7259_t *tp, uint8_t *data, uint8_t len) {
|
||||
return ims_it7259_buf_read(tp, ITE_BUF_CMD_RESP, data, len);
|
||||
}
|
||||
|
||||
static ims_ret_t ims_it7259_command_wait(ims_it7259_t *tp) {
|
||||
uint8_t query;
|
||||
while (true) {
|
||||
ims_ret_t ret = ims_it7259_query(tp, &query);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
tp->cb.delay(tp->pdev, ITE_QUERY_TIMEOUT);
|
||||
|
||||
ret = ims_it7259_query(tp, &query);
|
||||
if (ret != IMS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t stat = (query & ITE_QUERY_STAT_Msk) >> ITE_QUERY_STAT_Pos;
|
||||
|
||||
if (stat == ITE_STAT_ERROR) {
|
||||
return IMS_FAIL;
|
||||
}
|
||||
|
||||
if (stat == ITE_STAT_DONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IMS_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue