forked from mirrors/qmk_userspace
Azoteq IQS5xx support (#22280)
This commit is contained in:
parent
dda6e7fb36
commit
68722d35a3
6 changed files with 692 additions and 1 deletions
315
drivers/sensors/azoteq_iqs5xx.c
Normal file
315
drivers/sensors/azoteq_iqs5xx.c
Normal file
|
@ -0,0 +1,315 @@
|
|||
// Copyright 2023 Dasky (@daskygit)
|
||||
// Copyright 2023 George Norton (@george-norton)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "azoteq_iqs5xx.h"
|
||||
#include "pointing_device_internal.h"
|
||||
#include "wait.h"
|
||||
|
||||
#ifndef AZOTEQ_IQS5XX_ADDRESS
|
||||
# define AZOTEQ_IQS5XX_ADDRESS (0x74 << 1)
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_TIMEOUT_MS
|
||||
# define AZOTEQ_IQS5XX_TIMEOUT_MS 10
|
||||
#endif
|
||||
|
||||
#define AZOTEQ_IQS5XX_REG_PRODUCT_NUMBER 0x0000
|
||||
#define AZOTEQ_IQS5XX_REG_PREVIOUS_CYCLE_TIME 0x000C
|
||||
#define AZOTEQ_IQS5XX_REG_SYSTEM_CONTROL_1 0x0432
|
||||
#define AZOTEQ_IQS5XX_REG_REPORT_RATE_ACTIVE 0x057A
|
||||
#define AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_0 0x058E
|
||||
#define AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_1 0x058F
|
||||
#define AZOTEQ_IQS5XX_REG_X_RESOLUTION 0x066E
|
||||
#define AZOTEQ_IQS5XX_REG_XY_CONFIG_0 0x0669
|
||||
#define AZOTEQ_IQS5XX_REG_Y_RESOLUTION 0x0670
|
||||
#define AZOTEQ_IQS5XX_REG_SINGLE_FINGER_GESTURES 0x06B7
|
||||
#define AZOTEQ_IQS5XX_REG_END_COMMS 0xEEEE
|
||||
|
||||
// Gesture configuration
|
||||
#ifndef AZOTEQ_IQS5XX_TAP_ENABLE
|
||||
# define AZOTEQ_IQS5XX_TAP_ENABLE true
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE
|
||||
# define AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE false
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE
|
||||
# define AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE true
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SCROLL_ENABLE
|
||||
# define AZOTEQ_IQS5XX_SCROLL_ENABLE true
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_X_ENABLE
|
||||
# define AZOTEQ_IQS5XX_SWIPE_X_ENABLE false
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_Y_ENABLE
|
||||
# define AZOTEQ_IQS5XX_SWIPE_Y_ENABLE false
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_ZOOM_ENABLE
|
||||
# define AZOTEQ_IQS5XX_ZOOM_ENABLE false
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_TAP_TIME
|
||||
# define AZOTEQ_IQS5XX_TAP_TIME 0x96
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_TAP_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_TAP_DISTANCE 0x19
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_HOLD_TIME
|
||||
# define AZOTEQ_IQS5XX_HOLD_TIME 0x12C
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME
|
||||
# define AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME 0x64 // 0x96
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE 0x12C
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME
|
||||
# define AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME 0x0
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE 0x7D0
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE 0x32
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE 0x32
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE 0x19
|
||||
#endif
|
||||
|
||||
#if defined(AZOTEQ_IQS5XX_TPS43)
|
||||
# define AZOTEQ_IQS5XX_WIDTH_MM 43
|
||||
# define AZOTEQ_IQS5XX_HEIGHT_MM 40
|
||||
# define AZOTEQ_IQS5XX_RESOLUTION_X 2048
|
||||
# define AZOTEQ_IQS5XX_RESOLUTION_Y 1792
|
||||
#elif defined(AZOTEQ_IQS5XX_TPS65)
|
||||
# define AZOTEQ_IQS5XX_WIDTH_MM 65
|
||||
# define AZOTEQ_IQS5XX_HEIGHT_MM 49
|
||||
# define AZOTEQ_IQS5XX_RESOLUTION_X 3072
|
||||
# define AZOTEQ_IQS5XX_RESOLUTION_Y 2048
|
||||
#elif !defined(AZOTEQ_IQS5XX_WIDTH_MM) && !defined(AZOTEQ_IQS5XX_HEIGHT_MM)
|
||||
# error "You must define one of the available azoteq trackpads or specify at least the width and height"
|
||||
#endif
|
||||
|
||||
#define DIVIDE_UNSIGNED_ROUND(numerator, denominator) (((numerator) + ((denominator) / 2)) / (denominator))
|
||||
#define AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_X(inch) (DIVIDE_UNSIGNED_ROUND((inch) * (uint32_t)AZOTEQ_IQS5XX_WIDTH_MM * 10, 254))
|
||||
#define AZOTEQ_IQS5XX_RESOLUTION_X_TO_INCH(px) (DIVIDE_UNSIGNED_ROUND((px) * (uint32_t)254, AZOTEQ_IQS5XX_WIDTH_MM * 10))
|
||||
#define AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_Y(inch) (DIVIDE_UNSIGNED_ROUND((inch) * (uint32_t)AZOTEQ_IQS5XX_HEIGHT_MM * 10, 254))
|
||||
#define AZOTEQ_IQS5XX_RESOLUTION_Y_TO_INCH(px) (DIVIDE_UNSIGNED_ROUND((px) * (uint32_t)254, AZOTEQ_IQS5XX_HEIGHT_MM * 10))
|
||||
|
||||
static uint16_t azoteq_iqs5xx_product_number = AZOTEQ_IQS5XX_UNKNOWN;
|
||||
|
||||
static struct {
|
||||
uint16_t resolution_x;
|
||||
uint16_t resolution_y;
|
||||
} azoteq_iqs5xx_device_resolution_t;
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_wake(void) {
|
||||
uint8_t data = 0;
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_PREVIOUS_CYCLE_TIME, (uint8_t *)&data, sizeof(data), 1);
|
||||
i2c_stop();
|
||||
wait_us(150);
|
||||
return status;
|
||||
}
|
||||
i2c_status_t azoteq_iqs5xx_end_session(void) {
|
||||
const uint8_t END_BYTE = 1; // any data
|
||||
return i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_END_COMMS, &END_BYTE, 1, AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_get_base_data(azoteq_iqs5xx_base_data_t *base_data) {
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_PREVIOUS_CYCLE_TIME, (uint8_t *)base_data, 10, AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_get_report_rate(azoteq_iqs5xx_report_rate_t *report_rate, azoteq_iqs5xx_charging_modes_t mode, bool end_session) {
|
||||
if (mode > AZOTEQ_IQS5XX_LP2) {
|
||||
pd_dprintf("IQS5XX - Invalid mode for get report rate.\n");
|
||||
return I2C_STATUS_ERROR;
|
||||
}
|
||||
uint16_t selected_reg = AZOTEQ_IQS5XX_REG_REPORT_RATE_ACTIVE + (2 * mode);
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, selected_reg, (uint8_t *)report_rate, 2, AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_report_rate(uint16_t report_rate_ms, azoteq_iqs5xx_charging_modes_t mode, bool end_session) {
|
||||
if (mode > AZOTEQ_IQS5XX_LP2) {
|
||||
pd_dprintf("IQS5XX - Invalid mode for set report rate.\n");
|
||||
return I2C_STATUS_ERROR;
|
||||
}
|
||||
uint16_t selected_reg = AZOTEQ_IQS5XX_REG_REPORT_RATE_ACTIVE + (2 * mode);
|
||||
azoteq_iqs5xx_report_rate_t report_rate = {0};
|
||||
report_rate.h = (uint8_t)((report_rate_ms >> 8) & 0xFF);
|
||||
report_rate.l = (uint8_t)(report_rate_ms & 0xFF);
|
||||
i2c_status_t status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, selected_reg, (uint8_t *)&report_rate, 2, AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_reati(bool enabled, bool end_session) {
|
||||
azoteq_iqs5xx_system_config_0_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_0, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_config_0_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
config.reati = enabled;
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_0, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_config_0_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_event_mode(bool enabled, bool end_session) {
|
||||
azoteq_iqs5xx_system_config_1_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_1, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_config_1_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
config.event_mode = enabled;
|
||||
config.touch_event = true;
|
||||
config.tp_event = true;
|
||||
config.prox_event = false;
|
||||
config.snap_event = false;
|
||||
config.reati_event = false;
|
||||
config.alp_prox_event = false;
|
||||
config.gesture_event = true;
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_1, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_config_1_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_gesture_config(bool end_session) {
|
||||
azoteq_iqs5xx_gesture_config_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SINGLE_FINGER_GESTURES, (uint8_t *)&config, sizeof(azoteq_iqs5xx_gesture_config_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
pd_dprintf("azo scroll: %d\n", config.multi_finger_gestures.scroll);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
config.single_finger_gestures.single_tap = AZOTEQ_IQS5XX_TAP_ENABLE;
|
||||
config.single_finger_gestures.press_and_hold = AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE;
|
||||
config.single_finger_gestures.swipe_x_plus = AZOTEQ_IQS5XX_SWIPE_X_ENABLE;
|
||||
config.single_finger_gestures.swipe_x_minus = AZOTEQ_IQS5XX_SWIPE_X_ENABLE;
|
||||
config.single_finger_gestures.swipe_y_plus = AZOTEQ_IQS5XX_SWIPE_Y_ENABLE;
|
||||
config.single_finger_gestures.swipe_y_minus = AZOTEQ_IQS5XX_SWIPE_Y_ENABLE;
|
||||
config.multi_finger_gestures.two_finger_tap = AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE;
|
||||
config.multi_finger_gestures.scroll = AZOTEQ_IQS5XX_SCROLL_ENABLE;
|
||||
config.multi_finger_gestures.zoom = AZOTEQ_IQS5XX_ZOOM_ENABLE;
|
||||
config.tap_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_TAP_TIME);
|
||||
config.tap_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_TAP_DISTANCE);
|
||||
config.hold_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_HOLD_TIME);
|
||||
config.swipe_initial_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME);
|
||||
config.swipe_initial_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE);
|
||||
config.swipe_consecutive_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME);
|
||||
config.swipe_consecutive_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE);
|
||||
config.scroll_initial_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE);
|
||||
config.zoom_initial_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE);
|
||||
config.zoom_consecutive_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE);
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SINGLE_FINGER_GESTURES, (uint8_t *)&config, sizeof(azoteq_iqs5xx_gesture_config_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_xy_config(bool flip_x, bool flip_y, bool switch_xy, bool palm_reject, bool end_session) {
|
||||
azoteq_iqs5xx_xy_config_0_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_XY_CONFIG_0, (uint8_t *)&config, sizeof(azoteq_iqs5xx_xy_config_0_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
if (flip_x) {
|
||||
config.flip_x = !config.flip_x;
|
||||
}
|
||||
if (flip_y) {
|
||||
config.flip_y = !config.flip_y;
|
||||
}
|
||||
if (switch_xy) {
|
||||
config.switch_xy_axis = !config.switch_xy_axis;
|
||||
}
|
||||
config.palm_reject = palm_reject;
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_XY_CONFIG_0, (uint8_t *)&config, sizeof(azoteq_iqs5xx_xy_config_0_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_reset_suspend(bool reset, bool suspend, bool end_session) {
|
||||
azoteq_iqs5xx_system_control_1_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONTROL_1, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_control_1_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
config.reset = reset;
|
||||
config.suspend = suspend;
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONTROL_1, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_control_1_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void azoteq_iqs5xx_set_cpi(uint16_t cpi) {
|
||||
if (azoteq_iqs5xx_product_number != AZOTEQ_IQS5XX_UNKNOWN) {
|
||||
azoteq_iqs5xx_resolution_t resolution = {0};
|
||||
resolution.x_resolution = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(MIN(azoteq_iqs5xx_device_resolution_t.resolution_x, AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_X(cpi)));
|
||||
resolution.y_resolution = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(MIN(azoteq_iqs5xx_device_resolution_t.resolution_y, AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_Y(cpi)));
|
||||
i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_X_RESOLUTION, (uint8_t *)&resolution, sizeof(azoteq_iqs5xx_resolution_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t azoteq_iqs5xx_get_cpi(void) {
|
||||
if (azoteq_iqs5xx_product_number != AZOTEQ_IQS5XX_UNKNOWN) {
|
||||
azoteq_iqs5xx_resolution_t resolution = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_X_RESOLUTION, (uint8_t *)&resolution, sizeof(azoteq_iqs5xx_resolution_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
return AZOTEQ_IQS5XX_RESOLUTION_X_TO_INCH(AZOTEQ_IQS5XX_SWAP_H_L_BYTES(resolution.x_resolution));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t azoteq_iqs5xx_get_product(void) {
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_PRODUCT_NUMBER, (uint8_t *)&azoteq_iqs5xx_product_number, sizeof(uint16_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
azoteq_iqs5xx_product_number = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(azoteq_iqs5xx_product_number);
|
||||
}
|
||||
pd_dprintf("AZOTEQ: Product number %u\n", azoteq_iqs5xx_product_number);
|
||||
return azoteq_iqs5xx_product_number;
|
||||
}
|
||||
|
||||
void azoteq_iqs5xx_setup_resolution(void) {
|
||||
#if !defined(AZOTEQ_IQS5XX_RESOLUTION_X) && !defined(AZOTEQ_IQS5XX_RESOLUTION_Y)
|
||||
switch (azoteq_iqs5xx_product_number) {
|
||||
case AZOTEQ_IQS550:
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = 3584;
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = 2304;
|
||||
break;
|
||||
case AZOTEQ_IQS572:
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = 2048;
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = 1792;
|
||||
break;
|
||||
case AZOTEQ_IQS525:
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = 1280;
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = 768;
|
||||
break;
|
||||
default:
|
||||
// shouldn't be here
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = 0;
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef AZOTEQ_IQS5XX_RESOLUTION_X
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = AZOTEQ_IQS5XX_RESOLUTION_X;
|
||||
#endif
|
||||
#ifdef AZOTEQ_IQS5XX_RESOLUTION_Y
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = AZOTEQ_IQS5XX_RESOLUTION_Y;
|
||||
#endif
|
||||
}
|
193
drivers/sensors/azoteq_iqs5xx.h
Normal file
193
drivers/sensors/azoteq_iqs5xx.h
Normal file
|
@ -0,0 +1,193 @@
|
|||
// Copyright 2023 Dasky (@daskygit)
|
||||
// Copyright 2023 George Norton (@george-norton)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "i2c_master.h"
|
||||
#include "pointing_device.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef enum {
|
||||
AZOTEQ_IQS5XX_UNKNOWN,
|
||||
AZOTEQ_IQS550 = 40,
|
||||
AZOTEQ_IQS525 = 52,
|
||||
AZOTEQ_IQS572 = 58,
|
||||
} azoteq_iqs5xx_product_numbers_t;
|
||||
typedef enum {
|
||||
AZOTEQ_IQS5XX_ACTIVE,
|
||||
AZOTEQ_IQS5XX_IDLE_TOUCH,
|
||||
AZOTEQ_IQS5XX_IDLE,
|
||||
AZOTEQ_IQS5XX_LP1,
|
||||
AZOTEQ_IQS5XX_LP2,
|
||||
} azoteq_iqs5xx_charging_modes_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t h : 8;
|
||||
uint8_t l : 8;
|
||||
} azoteq_iqs5xx_report_rate_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool single_tap : 1; // Single tap gesture status
|
||||
bool press_and_hold : 1; // Press and hold gesture status
|
||||
bool swipe_x_neg : 1; // Swipe in negative X direction status
|
||||
bool swipe_x_pos : 1; // Swipe in positive X direction status
|
||||
bool swipe_y_pos : 1; // Swipe in positive Y direction status
|
||||
bool swipe_y_neg : 1; // Swipe in negative Y direction status
|
||||
uint8_t _unused : 2; // unused
|
||||
} azoteq_iqs5xx_gesture_events_0_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool two_finger_tap : 1; // Two finger tap gesture status
|
||||
bool scroll : 1; // Scroll status
|
||||
bool zoom : 1; // Zoom gesture status
|
||||
uint8_t _unused : 5; // unused
|
||||
} azoteq_iqs5xx_gesture_events_1_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
azoteq_iqs5xx_charging_modes_t charging_mode : 3; // Indicates current mode
|
||||
bool ati_error : 1; //
|
||||
bool reati_occurred : 1; //
|
||||
bool alp_ati_error : 1; //
|
||||
bool alp_reati_occurred : 1; //
|
||||
bool show_reset : 1; //
|
||||
} azoteq_iqs5xx_system_info_0_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool tp_movement : 1; //
|
||||
bool palm_detect : 1; // Palm detect status
|
||||
bool too_many_fingers : 1; // Total finger status
|
||||
bool rr_missed : 1; // Report rate status
|
||||
bool snap_toggle : 1; // Change in any snap channel status
|
||||
bool switch_state : 1; // Status of input pin SW_IN
|
||||
uint8_t _unused : 2; // unused
|
||||
} azoteq_iqs5xx_system_info_1_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t h : 8;
|
||||
uint8_t l : 8;
|
||||
} azoteq_iqs5xx_relative_xy_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t previous_cycle_time;
|
||||
azoteq_iqs5xx_gesture_events_0_t gesture_events_0;
|
||||
azoteq_iqs5xx_gesture_events_1_t gesture_events_1;
|
||||
azoteq_iqs5xx_system_info_0_t system_info_0;
|
||||
azoteq_iqs5xx_system_info_1_t system_info_1;
|
||||
uint8_t number_of_fingers;
|
||||
azoteq_iqs5xx_relative_xy_t x;
|
||||
azoteq_iqs5xx_relative_xy_t y;
|
||||
} azoteq_iqs5xx_base_data_t;
|
||||
|
||||
_Static_assert(sizeof(azoteq_iqs5xx_base_data_t) == 10, "azoteq_iqs5xx_basic_report_t should be 10 bytes");
|
||||
|
||||
typedef struct {
|
||||
uint8_t number_of_fingers;
|
||||
azoteq_iqs5xx_relative_xy_t x;
|
||||
azoteq_iqs5xx_relative_xy_t y;
|
||||
} azoteq_iqs5xx_report_data_t;
|
||||
|
||||
_Static_assert(sizeof(azoteq_iqs5xx_report_data_t) == 5, "azoteq_iqs5xx_report_data_t should be 5 bytes");
|
||||
|
||||
typedef struct PACKED {
|
||||
bool sw_input : 1;
|
||||
bool sw_input_select : 1;
|
||||
bool reati : 1;
|
||||
bool alp_reati : 1;
|
||||
bool sw_input_event : 1;
|
||||
bool wdt : 1;
|
||||
bool setup_complete : 1;
|
||||
bool manual_control : 1;
|
||||
} azoteq_iqs5xx_system_config_0_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool event_mode : 1;
|
||||
bool gesture_event : 1;
|
||||
bool tp_event : 1;
|
||||
bool reati_event : 1;
|
||||
bool alp_prox_event : 1;
|
||||
bool snap_event : 1;
|
||||
bool touch_event : 1;
|
||||
bool prox_event : 1;
|
||||
} azoteq_iqs5xx_system_config_1_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool flip_x : 1;
|
||||
bool flip_y : 1;
|
||||
bool switch_xy_axis : 1;
|
||||
bool palm_reject : 1;
|
||||
uint8_t _unused : 4;
|
||||
} azoteq_iqs5xx_xy_config_0_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool suspend : 1;
|
||||
bool reset : 1;
|
||||
int8_t _unused : 6;
|
||||
} azoteq_iqs5xx_system_control_1_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool single_tap : 1;
|
||||
bool press_and_hold : 1;
|
||||
bool swipe_x_minus : 1;
|
||||
bool swipe_x_plus : 1;
|
||||
bool swipe_y_plus : 1;
|
||||
bool swipe_y_minus : 1;
|
||||
int8_t _unused : 2;
|
||||
} azoteq_iqs5xx_single_finger_gesture_enable_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool two_finger_tap : 1;
|
||||
bool scroll : 1;
|
||||
bool zoom : 1;
|
||||
int8_t _unused : 5;
|
||||
} azoteq_iqs5xx_multi_finger_gesture_enable_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
azoteq_iqs5xx_single_finger_gesture_enable_t single_finger_gestures;
|
||||
azoteq_iqs5xx_multi_finger_gesture_enable_t multi_finger_gestures;
|
||||
uint16_t tap_time;
|
||||
uint16_t tap_distance;
|
||||
uint16_t hold_time;
|
||||
uint16_t swipe_initial_time;
|
||||
uint16_t swipe_initial_distance;
|
||||
uint16_t swipe_consecutive_time;
|
||||
uint16_t swipe_consecutive_distance;
|
||||
int8_t swipe_angle;
|
||||
uint16_t scroll_initial_distance;
|
||||
int8_t scroll_angle;
|
||||
uint16_t zoom_initial_distance;
|
||||
uint16_t zoom_consecutive_distance;
|
||||
} azoteq_iqs5xx_gesture_config_t;
|
||||
|
||||
_Static_assert(sizeof(azoteq_iqs5xx_gesture_config_t) == 24, "azoteq_iqs5xx_gesture_config_t should be 24 bytes");
|
||||
|
||||
typedef struct {
|
||||
uint16_t x_resolution;
|
||||
uint16_t y_resolution;
|
||||
} azoteq_iqs5xx_resolution_t;
|
||||
|
||||
#define AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(h, l) ((int16_t)(h << 8) | l)
|
||||
#define AZOTEQ_IQS5XX_SWAP_H_L_BYTES(b) ((uint16_t)((b & 0xff) << 8) | (b >> 8))
|
||||
|
||||
#ifndef AZOTEQ_IQS5XX_REPORT_RATE
|
||||
# define AZOTEQ_IQS5XX_REPORT_RATE 10
|
||||
#endif
|
||||
#if !defined(POINTING_DEVICE_TASK_THROTTLE_MS) && !defined(POINTING_DEVICE_MOTION_PIN)
|
||||
# define POINTING_DEVICE_TASK_THROTTLE_MS AZOTEQ_IQS5XX_REPORT_RATE
|
||||
#endif
|
||||
|
||||
void azoteq_iqs5xx_init(void);
|
||||
i2c_status_t azoteq_iqs5xx_wake(void);
|
||||
report_mouse_t azoteq_iqs5xx_get_report(report_mouse_t mouse_report);
|
||||
i2c_status_t azoteq_iqs5xx_get_report_rate(azoteq_iqs5xx_report_rate_t *report_rate, azoteq_iqs5xx_charging_modes_t mode, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_report_rate(uint16_t report_rate_ms, azoteq_iqs5xx_charging_modes_t mode, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_event_mode(bool enabled, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_reati(bool enabled, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_gesture_config(bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_xy_config(bool flip_x, bool flip_y, bool switch_xy, bool palm_reject, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_reset_suspend(bool reset, bool suspend, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_get_base_data(azoteq_iqs5xx_base_data_t *base_data);
|
||||
void azoteq_iqs5xx_set_cpi(uint16_t cpi);
|
||||
uint16_t azoteq_iqs5xx_get_cpi(void);
|
||||
uint16_t azoteq_iqs5xx_get_product(void);
|
||||
void azoteq_iqs5xx_setup_resolution(void);
|
Loading…
Add table
Add a link
Reference in a new issue