2023-11-20 16:25:35 +00:00
// 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
2025-01-11 01:29:58 +00:00
# define AZOTEQ_IQS5XX_REG_IDLE_MODE_TIMEOUT 0x0586
2023-11-20 16:25:35 +00:00
# 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
2025-01-11 01:29:58 +00:00
# ifndef AZOTEQ_IQS5XX_EVENT_MODE
// Event mode can't be used until the pointing code has changed (stuck buttons)
# define AZOTEQ_IQS5XX_EVENT_MODE false
# endif
2023-11-20 16:25:35 +00:00
# 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))
2024-10-25 18:11:51 +01:00
const pointing_device_driver_t azoteq_iqs5xx_pointing_device_driver = {
. init = azoteq_iqs5xx_init ,
. get_report = azoteq_iqs5xx_get_report ,
. set_cpi = azoteq_iqs5xx_set_cpi ,
. get_cpi = azoteq_iqs5xx_get_cpi ,
} ;
2023-11-20 16:25:35 +00:00
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_end_session ( void ) {
const uint8_t END_BYTE = 1 ; // any data
2024-01-16 13:26:40 +11:00
return i2c_write_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_END_COMMS , & END_BYTE , 1 , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
}
i2c_status_t azoteq_iqs5xx_get_base_data ( azoteq_iqs5xx_base_data_t * base_data ) {
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_read_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_PREVIOUS_CYCLE_TIME , ( uint8_t * ) base_data , 10 , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
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 ) ;
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_read_register16 ( AZOTEQ_IQS5XX_ADDRESS , selected_reg , ( uint8_t * ) report_rate , 2 , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
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 ) ;
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_write_register16 ( AZOTEQ_IQS5XX_ADDRESS , selected_reg , ( uint8_t * ) & report_rate , 2 , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
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 } ;
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_read_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_0 , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_system_config_0_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
if ( status = = I2C_STATUS_SUCCESS ) {
config . reati = enabled ;
2024-01-16 13:26:40 +11:00
status = i2c_write_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_0 , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_system_config_0_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
}
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 } ;
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_read_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_1 , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_system_config_1_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
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 ;
2024-01-16 13:26:40 +11:00
status = i2c_write_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_1 , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_system_config_1_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
}
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 } ;
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_read_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_SINGLE_FINGER_GESTURES , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_gesture_config_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
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 ) ;
2024-01-16 13:26:40 +11:00
status = i2c_write_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_SINGLE_FINGER_GESTURES , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_gesture_config_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
}
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 } ;
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_read_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_XY_CONFIG_0 , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_xy_config_0_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
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 ;
2024-01-16 13:26:40 +11:00
status = i2c_write_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_XY_CONFIG_0 , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_xy_config_0_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
}
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 } ;
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_read_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_SYSTEM_CONTROL_1 , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_system_control_1_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
if ( status = = I2C_STATUS_SUCCESS ) {
config . reset = reset ;
config . suspend = suspend ;
2024-01-16 13:26:40 +11:00
status = i2c_write_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_SYSTEM_CONTROL_1 , ( uint8_t * ) & config , sizeof ( azoteq_iqs5xx_system_control_1_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
}
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 ) ) ) ;
2024-01-16 13:26:40 +11:00
i2c_write_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_X_RESOLUTION , ( uint8_t * ) & resolution , sizeof ( azoteq_iqs5xx_resolution_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
}
}
uint16_t azoteq_iqs5xx_get_cpi ( void ) {
if ( azoteq_iqs5xx_product_number ! = AZOTEQ_IQS5XX_UNKNOWN ) {
azoteq_iqs5xx_resolution_t resolution = { 0 } ;
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_read_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_X_RESOLUTION , ( uint8_t * ) & resolution , sizeof ( azoteq_iqs5xx_resolution_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
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 ) {
2024-01-16 13:26:40 +11:00
i2c_status_t status = i2c_read_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_PRODUCT_NUMBER , ( uint8_t * ) & azoteq_iqs5xx_product_number , sizeof ( uint16_t ) , AZOTEQ_IQS5XX_TIMEOUT_MS ) ;
2023-11-20 16:25:35 +00:00
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
}
2024-10-25 18:11:51 +01:00
static i2c_status_t azoteq_iqs5xx_init_status = 1 ;
void azoteq_iqs5xx_init ( void ) {
i2c_init ( ) ;
2025-01-11 01:29:58 +00:00
i2c_ping_address ( AZOTEQ_IQS5XX_ADDRESS , 1 ) ; // wake
2024-10-25 18:11:51 +01:00
azoteq_iqs5xx_reset_suspend ( true , false , true ) ;
wait_ms ( 100 ) ;
2025-01-11 01:29:58 +00:00
i2c_ping_address ( AZOTEQ_IQS5XX_ADDRESS , 1 ) ; // wake
2024-10-25 18:11:51 +01:00
if ( azoteq_iqs5xx_get_product ( ) ! = AZOTEQ_IQS5XX_UNKNOWN ) {
azoteq_iqs5xx_setup_resolution ( ) ;
azoteq_iqs5xx_init_status = azoteq_iqs5xx_set_report_rate ( AZOTEQ_IQS5XX_REPORT_RATE , AZOTEQ_IQS5XX_ACTIVE , false ) ;
2025-01-11 01:29:58 +00:00
azoteq_iqs5xx_init_status | = azoteq_iqs5xx_set_report_rate ( AZOTEQ_IQS5XX_REPORT_RATE , AZOTEQ_IQS5XX_IDLE , false ) ;
azoteq_iqs5xx_init_status | = azoteq_iqs5xx_set_report_rate ( AZOTEQ_IQS5XX_REPORT_RATE , AZOTEQ_IQS5XX_IDLE_TOUCH , false ) ;
uint8_t no_timeout = 255 ;
azoteq_iqs5xx_init_status | = i2c_write_register16 ( AZOTEQ_IQS5XX_ADDRESS , AZOTEQ_IQS5XX_REG_IDLE_MODE_TIMEOUT , & no_timeout , 1 , AZOTEQ_IQS5XX_TIMEOUT_MS ) ; // Don't enter LP1, LP2 states
azoteq_iqs5xx_init_status | = azoteq_iqs5xx_set_event_mode ( AZOTEQ_IQS5XX_EVENT_MODE , false ) ;
2024-10-25 18:11:51 +01:00
azoteq_iqs5xx_init_status | = azoteq_iqs5xx_set_reati ( true , false ) ;
# if defined(AZOTEQ_IQS5XX_ROTATION_90)
azoteq_iqs5xx_init_status | = azoteq_iqs5xx_set_xy_config ( false , true , true , true , false ) ;
# elif defined(AZOTEQ_IQS5XX_ROTATION_180)
azoteq_iqs5xx_init_status | = azoteq_iqs5xx_set_xy_config ( true , true , false , true , false ) ;
# elif defined(AZOTEQ_IQS5XX_ROTATION_270)
azoteq_iqs5xx_init_status | = azoteq_iqs5xx_set_xy_config ( true , false , true , true , false ) ;
# else
azoteq_iqs5xx_init_status | = azoteq_iqs5xx_set_xy_config ( false , false , false , true , false ) ;
# endif
azoteq_iqs5xx_init_status | = azoteq_iqs5xx_set_gesture_config ( true ) ;
wait_ms ( AZOTEQ_IQS5XX_REPORT_RATE + 1 ) ;
}
} ;
report_mouse_t azoteq_iqs5xx_get_report ( report_mouse_t mouse_report ) {
2025-01-11 01:29:58 +00:00
report_mouse_t temp_report = { 0 } ;
2024-10-25 18:11:51 +01:00
if ( azoteq_iqs5xx_init_status = = I2C_STATUS_SUCCESS ) {
2025-01-11 01:29:58 +00:00
azoteq_iqs5xx_base_data_t base_data = { 0 } ;
i2c_status_t status = azoteq_iqs5xx_get_base_data ( & base_data ) ;
bool ignore_movement = false ;
2024-10-25 18:11:51 +01:00
if ( status = = I2C_STATUS_SUCCESS ) {
2025-01-11 01:29:58 +00:00
# ifdef POINTING_DEVICE_DEBUG
if ( base_data . previous_cycle_time > AZOTEQ_IQS5XX_REPORT_RATE ) {
pd_dprintf ( " IQS5XX - previous cycle time missed, took: %dms \n " , base_data . previous_cycle_time ) ;
}
# endif
2024-10-25 18:11:51 +01:00
if ( base_data . gesture_events_0 . single_tap | | base_data . gesture_events_0 . press_and_hold ) {
pd_dprintf ( " IQS5XX - Single tap/hold. \n " ) ;
temp_report . buttons = pointing_device_handle_buttons ( temp_report . buttons , true , POINTING_DEVICE_BUTTON1 ) ;
} else if ( base_data . gesture_events_1 . two_finger_tap ) {
pd_dprintf ( " IQS5XX - Two finger tap. \n " ) ;
temp_report . buttons = pointing_device_handle_buttons ( temp_report . buttons , true , POINTING_DEVICE_BUTTON2 ) ;
} else if ( base_data . gesture_events_0 . swipe_x_neg ) {
pd_dprintf ( " IQS5XX - X-. \n " ) ;
temp_report . buttons = pointing_device_handle_buttons ( temp_report . buttons , true , POINTING_DEVICE_BUTTON4 ) ;
ignore_movement = true ;
} else if ( base_data . gesture_events_0 . swipe_x_pos ) {
pd_dprintf ( " IQS5XX - X+. \n " ) ;
temp_report . buttons = pointing_device_handle_buttons ( temp_report . buttons , true , POINTING_DEVICE_BUTTON5 ) ;
ignore_movement = true ;
} else if ( base_data . gesture_events_0 . swipe_y_neg ) {
pd_dprintf ( " IQS5XX - Y-. \n " ) ;
temp_report . buttons = pointing_device_handle_buttons ( temp_report . buttons , true , POINTING_DEVICE_BUTTON6 ) ;
ignore_movement = true ;
} else if ( base_data . gesture_events_0 . swipe_y_pos ) {
pd_dprintf ( " IQS5XX - Y+. \n " ) ;
temp_report . buttons = pointing_device_handle_buttons ( temp_report . buttons , true , POINTING_DEVICE_BUTTON3 ) ;
ignore_movement = true ;
} else if ( base_data . gesture_events_1 . zoom ) {
if ( AZOTEQ_IQS5XX_COMBINE_H_L_BYTES ( base_data . x . h , base_data . x . l ) < 0 ) {
pd_dprintf ( " IQS5XX - Zoom out. \n " ) ;
temp_report . buttons = pointing_device_handle_buttons ( temp_report . buttons , true , POINTING_DEVICE_BUTTON7 ) ;
} else if ( AZOTEQ_IQS5XX_COMBINE_H_L_BYTES ( base_data . x . h , base_data . x . l ) > 0 ) {
pd_dprintf ( " IQS5XX - Zoom in. \n " ) ;
temp_report . buttons = pointing_device_handle_buttons ( temp_report . buttons , true , POINTING_DEVICE_BUTTON8 ) ;
}
} else if ( base_data . gesture_events_1 . scroll ) {
pd_dprintf ( " IQS5XX - Scroll. \n " ) ;
temp_report . h = CONSTRAIN_HID ( AZOTEQ_IQS5XX_COMBINE_H_L_BYTES ( base_data . x . h , base_data . x . l ) ) ;
temp_report . v = CONSTRAIN_HID ( AZOTEQ_IQS5XX_COMBINE_H_L_BYTES ( base_data . y . h , base_data . y . l ) ) ;
}
if ( base_data . number_of_fingers = = 1 & & ! ignore_movement ) {
temp_report . x = CONSTRAIN_HID_XY ( AZOTEQ_IQS5XX_COMBINE_H_L_BYTES ( base_data . x . h , base_data . x . l ) ) ;
temp_report . y = CONSTRAIN_HID_XY ( AZOTEQ_IQS5XX_COMBINE_H_L_BYTES ( base_data . y . h , base_data . y . l ) ) ;
}
} else {
2025-01-11 01:29:58 +00:00
pd_dprintf ( " IQS5XX - get report failed, i2c status: %d \n " , status ) ;
2024-10-25 18:11:51 +01:00
}
} else {
2025-01-11 01:29:58 +00:00
pd_dprintf ( " IQS5XX - Init failed, i2c status: %d \n " , azoteq_iqs5xx_init_status ) ;
2024-10-25 18:11:51 +01:00
}
return temp_report ;
}