azoteq_iqs5xx.c (20803B)
1 // Copyright 2023 Dasky (@daskygit) 2 // Copyright 2023 George Norton (@george-norton) 3 // SPDX-License-Identifier: GPL-2.0-or-later 4 5 #include "azoteq_iqs5xx.h" 6 #include "pointing_device_internal.h" 7 #include "wait.h" 8 9 #ifndef AZOTEQ_IQS5XX_ADDRESS 10 # define AZOTEQ_IQS5XX_ADDRESS (0x74 << 1) 11 #endif 12 #ifndef AZOTEQ_IQS5XX_TIMEOUT_MS 13 # define AZOTEQ_IQS5XX_TIMEOUT_MS 10 14 #endif 15 16 #define AZOTEQ_IQS5XX_REG_PRODUCT_NUMBER 0x0000 17 #define AZOTEQ_IQS5XX_REG_PREVIOUS_CYCLE_TIME 0x000C 18 #define AZOTEQ_IQS5XX_REG_SYSTEM_CONTROL_1 0x0432 19 #define AZOTEQ_IQS5XX_REG_REPORT_RATE_ACTIVE 0x057A 20 #define AZOTEQ_IQS5XX_REG_IDLE_MODE_TIMEOUT 0x0586 21 #define AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_0 0x058E 22 #define AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_1 0x058F 23 #define AZOTEQ_IQS5XX_REG_X_RESOLUTION 0x066E 24 #define AZOTEQ_IQS5XX_REG_XY_CONFIG_0 0x0669 25 #define AZOTEQ_IQS5XX_REG_Y_RESOLUTION 0x0670 26 #define AZOTEQ_IQS5XX_REG_SINGLE_FINGER_GESTURES 0x06B7 27 #define AZOTEQ_IQS5XX_REG_END_COMMS 0xEEEE 28 29 // Gesture configuration 30 #ifndef AZOTEQ_IQS5XX_TAP_ENABLE 31 # define AZOTEQ_IQS5XX_TAP_ENABLE true 32 #endif 33 #ifndef AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE 34 # define AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE false 35 #endif 36 #ifndef AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE 37 # define AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE true 38 #endif 39 #ifndef AZOTEQ_IQS5XX_SCROLL_ENABLE 40 # define AZOTEQ_IQS5XX_SCROLL_ENABLE true 41 #endif 42 #ifndef AZOTEQ_IQS5XX_SWIPE_X_ENABLE 43 # define AZOTEQ_IQS5XX_SWIPE_X_ENABLE false 44 #endif 45 #ifndef AZOTEQ_IQS5XX_SWIPE_Y_ENABLE 46 # define AZOTEQ_IQS5XX_SWIPE_Y_ENABLE false 47 #endif 48 #ifndef AZOTEQ_IQS5XX_ZOOM_ENABLE 49 # define AZOTEQ_IQS5XX_ZOOM_ENABLE false 50 #endif 51 #ifndef AZOTEQ_IQS5XX_TAP_TIME 52 # define AZOTEQ_IQS5XX_TAP_TIME 0x96 53 #endif 54 #ifndef AZOTEQ_IQS5XX_TAP_DISTANCE 55 # define AZOTEQ_IQS5XX_TAP_DISTANCE 0x19 56 #endif 57 #ifndef AZOTEQ_IQS5XX_HOLD_TIME 58 # define AZOTEQ_IQS5XX_HOLD_TIME 0x12C 59 #endif 60 #ifndef AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME 61 # define AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME 0x64 // 0x96 62 #endif 63 #ifndef AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE 64 # define AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE 0x12C 65 #endif 66 #ifndef AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME 67 # define AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME 0x0 68 #endif 69 #ifndef AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE 70 # define AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE 0x7D0 71 #endif 72 #ifndef AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE 73 # define AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE 0x32 74 #endif 75 #ifndef AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE 76 # define AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE 0x32 77 #endif 78 #ifndef AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE 79 # define AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE 0x19 80 #endif 81 #ifndef AZOTEQ_IQS5XX_EVENT_MODE 82 // Event mode can't be used until the pointing code has changed (stuck buttons) 83 # define AZOTEQ_IQS5XX_EVENT_MODE false 84 #endif 85 86 #if defined(AZOTEQ_IQS5XX_TPS43) 87 # define AZOTEQ_IQS5XX_WIDTH_MM 43 88 # define AZOTEQ_IQS5XX_HEIGHT_MM 40 89 # define AZOTEQ_IQS5XX_RESOLUTION_X 2048 90 # define AZOTEQ_IQS5XX_RESOLUTION_Y 1792 91 #elif defined(AZOTEQ_IQS5XX_TPS65) 92 # define AZOTEQ_IQS5XX_WIDTH_MM 65 93 # define AZOTEQ_IQS5XX_HEIGHT_MM 49 94 # define AZOTEQ_IQS5XX_RESOLUTION_X 3072 95 # define AZOTEQ_IQS5XX_RESOLUTION_Y 2048 96 #elif !defined(AZOTEQ_IQS5XX_WIDTH_MM) && !defined(AZOTEQ_IQS5XX_HEIGHT_MM) 97 # error "You must define one of the available azoteq trackpads or specify at least the width and height" 98 #endif 99 100 #define DIVIDE_UNSIGNED_ROUND(numerator, denominator) (((numerator) + ((denominator) / 2)) / (denominator)) 101 #define AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_X(inch) (DIVIDE_UNSIGNED_ROUND((inch) * (uint32_t)AZOTEQ_IQS5XX_WIDTH_MM * 10, 254)) 102 #define AZOTEQ_IQS5XX_RESOLUTION_X_TO_INCH(px) (DIVIDE_UNSIGNED_ROUND((px) * (uint32_t)254, AZOTEQ_IQS5XX_WIDTH_MM * 10)) 103 #define AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_Y(inch) (DIVIDE_UNSIGNED_ROUND((inch) * (uint32_t)AZOTEQ_IQS5XX_HEIGHT_MM * 10, 254)) 104 #define AZOTEQ_IQS5XX_RESOLUTION_Y_TO_INCH(px) (DIVIDE_UNSIGNED_ROUND((px) * (uint32_t)254, AZOTEQ_IQS5XX_HEIGHT_MM * 10)) 105 106 const pointing_device_driver_t azoteq_iqs5xx_pointing_device_driver = { 107 .init = azoteq_iqs5xx_init, 108 .get_report = azoteq_iqs5xx_get_report, 109 .set_cpi = azoteq_iqs5xx_set_cpi, 110 .get_cpi = azoteq_iqs5xx_get_cpi, 111 }; 112 113 static uint16_t azoteq_iqs5xx_product_number = AZOTEQ_IQS5XX_UNKNOWN; 114 115 static struct { 116 uint16_t resolution_x; 117 uint16_t resolution_y; 118 } azoteq_iqs5xx_device_resolution_t; 119 120 i2c_status_t azoteq_iqs5xx_end_session(void) { 121 const uint8_t END_BYTE = 1; // any data 122 return i2c_write_register16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_END_COMMS, &END_BYTE, 1, AZOTEQ_IQS5XX_TIMEOUT_MS); 123 } 124 125 i2c_status_t azoteq_iqs5xx_get_base_data(azoteq_iqs5xx_base_data_t *base_data) { 126 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); 127 if (status == I2C_STATUS_SUCCESS) { 128 azoteq_iqs5xx_end_session(); 129 } 130 return status; 131 } 132 133 i2c_status_t azoteq_iqs5xx_get_report_rate(azoteq_iqs5xx_report_rate_t *report_rate, azoteq_iqs5xx_charging_modes_t mode, bool end_session) { 134 if (mode > AZOTEQ_IQS5XX_LP2) { 135 pd_dprintf("IQS5XX - Invalid mode for get report rate.\n"); 136 return I2C_STATUS_ERROR; 137 } 138 uint16_t selected_reg = AZOTEQ_IQS5XX_REG_REPORT_RATE_ACTIVE + (2 * mode); 139 i2c_status_t status = i2c_read_register16(AZOTEQ_IQS5XX_ADDRESS, selected_reg, (uint8_t *)report_rate, 2, AZOTEQ_IQS5XX_TIMEOUT_MS); 140 if (end_session) { 141 azoteq_iqs5xx_end_session(); 142 } 143 return status; 144 } 145 146 i2c_status_t azoteq_iqs5xx_set_report_rate(uint16_t report_rate_ms, azoteq_iqs5xx_charging_modes_t mode, bool end_session) { 147 if (mode > AZOTEQ_IQS5XX_LP2) { 148 pd_dprintf("IQS5XX - Invalid mode for set report rate.\n"); 149 return I2C_STATUS_ERROR; 150 } 151 uint16_t selected_reg = AZOTEQ_IQS5XX_REG_REPORT_RATE_ACTIVE + (2 * mode); 152 azoteq_iqs5xx_report_rate_t report_rate = {0}; 153 report_rate.h = (uint8_t)((report_rate_ms >> 8) & 0xFF); 154 report_rate.l = (uint8_t)(report_rate_ms & 0xFF); 155 i2c_status_t status = i2c_write_register16(AZOTEQ_IQS5XX_ADDRESS, selected_reg, (uint8_t *)&report_rate, 2, AZOTEQ_IQS5XX_TIMEOUT_MS); 156 if (end_session) { 157 azoteq_iqs5xx_end_session(); 158 } 159 return status; 160 } 161 162 i2c_status_t azoteq_iqs5xx_set_reati(bool enabled, bool end_session) { 163 azoteq_iqs5xx_system_config_0_t config = {0}; 164 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); 165 if (status == I2C_STATUS_SUCCESS) { 166 config.reati = enabled; 167 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); 168 } 169 if (end_session) { 170 azoteq_iqs5xx_end_session(); 171 } 172 return status; 173 } 174 175 i2c_status_t azoteq_iqs5xx_set_event_mode(bool enabled, bool end_session) { 176 azoteq_iqs5xx_system_config_1_t config = {0}; 177 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); 178 if (status == I2C_STATUS_SUCCESS) { 179 config.event_mode = enabled; 180 config.touch_event = true; 181 config.tp_event = true; 182 config.prox_event = false; 183 config.snap_event = false; 184 config.reati_event = false; 185 config.alp_prox_event = false; 186 config.gesture_event = true; 187 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); 188 } 189 if (end_session) { 190 azoteq_iqs5xx_end_session(); 191 } 192 return status; 193 } 194 195 i2c_status_t azoteq_iqs5xx_set_gesture_config(bool end_session) { 196 azoteq_iqs5xx_gesture_config_t config = {0}; 197 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); 198 pd_dprintf("azo scroll: %d\n", config.multi_finger_gestures.scroll); 199 if (status == I2C_STATUS_SUCCESS) { 200 config.single_finger_gestures.single_tap = AZOTEQ_IQS5XX_TAP_ENABLE; 201 config.single_finger_gestures.press_and_hold = AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE; 202 config.single_finger_gestures.swipe_x_plus = AZOTEQ_IQS5XX_SWIPE_X_ENABLE; 203 config.single_finger_gestures.swipe_x_minus = AZOTEQ_IQS5XX_SWIPE_X_ENABLE; 204 config.single_finger_gestures.swipe_y_plus = AZOTEQ_IQS5XX_SWIPE_Y_ENABLE; 205 config.single_finger_gestures.swipe_y_minus = AZOTEQ_IQS5XX_SWIPE_Y_ENABLE; 206 config.multi_finger_gestures.two_finger_tap = AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE; 207 config.multi_finger_gestures.scroll = AZOTEQ_IQS5XX_SCROLL_ENABLE; 208 config.multi_finger_gestures.zoom = AZOTEQ_IQS5XX_ZOOM_ENABLE; 209 config.tap_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_TAP_TIME); 210 config.tap_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_TAP_DISTANCE); 211 config.hold_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_HOLD_TIME); 212 config.swipe_initial_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME); 213 config.swipe_initial_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE); 214 config.swipe_consecutive_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME); 215 config.swipe_consecutive_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE); 216 config.scroll_initial_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE); 217 config.zoom_initial_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE); 218 config.zoom_consecutive_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE); 219 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); 220 } 221 if (end_session) { 222 azoteq_iqs5xx_end_session(); 223 } 224 return status; 225 } 226 227 i2c_status_t azoteq_iqs5xx_set_xy_config(bool flip_x, bool flip_y, bool switch_xy, bool palm_reject, bool end_session) { 228 azoteq_iqs5xx_xy_config_0_t config = {0}; 229 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); 230 if (status == I2C_STATUS_SUCCESS) { 231 if (flip_x) { 232 config.flip_x = !config.flip_x; 233 } 234 if (flip_y) { 235 config.flip_y = !config.flip_y; 236 } 237 if (switch_xy) { 238 config.switch_xy_axis = !config.switch_xy_axis; 239 } 240 config.palm_reject = palm_reject; 241 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); 242 } 243 if (end_session) { 244 azoteq_iqs5xx_end_session(); 245 } 246 return status; 247 } 248 249 i2c_status_t azoteq_iqs5xx_reset_suspend(bool reset, bool suspend, bool end_session) { 250 azoteq_iqs5xx_system_control_1_t config = {0}; 251 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); 252 if (status == I2C_STATUS_SUCCESS) { 253 config.reset = reset; 254 config.suspend = suspend; 255 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); 256 } 257 if (end_session) { 258 azoteq_iqs5xx_end_session(); 259 } 260 return status; 261 } 262 263 void azoteq_iqs5xx_set_cpi(uint16_t cpi) { 264 if (azoteq_iqs5xx_product_number != AZOTEQ_IQS5XX_UNKNOWN) { 265 azoteq_iqs5xx_resolution_t resolution = {0}; 266 resolution.x_resolution = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(MIN(azoteq_iqs5xx_device_resolution_t.resolution_x, AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_X(cpi))); 267 resolution.y_resolution = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(MIN(azoteq_iqs5xx_device_resolution_t.resolution_y, AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_Y(cpi))); 268 i2c_write_register16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_X_RESOLUTION, (uint8_t *)&resolution, sizeof(azoteq_iqs5xx_resolution_t), AZOTEQ_IQS5XX_TIMEOUT_MS); 269 } 270 } 271 272 uint16_t azoteq_iqs5xx_get_cpi(void) { 273 if (azoteq_iqs5xx_product_number != AZOTEQ_IQS5XX_UNKNOWN) { 274 azoteq_iqs5xx_resolution_t resolution = {0}; 275 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); 276 if (status == I2C_STATUS_SUCCESS) { 277 return AZOTEQ_IQS5XX_RESOLUTION_X_TO_INCH(AZOTEQ_IQS5XX_SWAP_H_L_BYTES(resolution.x_resolution)); 278 } 279 } 280 return 0; 281 } 282 283 uint16_t azoteq_iqs5xx_get_product(void) { 284 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); 285 if (status == I2C_STATUS_SUCCESS) { 286 azoteq_iqs5xx_product_number = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(azoteq_iqs5xx_product_number); 287 } 288 pd_dprintf("AZOTEQ: Product number %u\n", azoteq_iqs5xx_product_number); 289 return azoteq_iqs5xx_product_number; 290 } 291 292 void azoteq_iqs5xx_setup_resolution(void) { 293 #if !defined(AZOTEQ_IQS5XX_RESOLUTION_X) && !defined(AZOTEQ_IQS5XX_RESOLUTION_Y) 294 switch (azoteq_iqs5xx_product_number) { 295 case AZOTEQ_IQS550: 296 azoteq_iqs5xx_device_resolution_t.resolution_x = 3584; 297 azoteq_iqs5xx_device_resolution_t.resolution_y = 2304; 298 break; 299 case AZOTEQ_IQS572: 300 azoteq_iqs5xx_device_resolution_t.resolution_x = 2048; 301 azoteq_iqs5xx_device_resolution_t.resolution_y = 1792; 302 break; 303 case AZOTEQ_IQS525: 304 azoteq_iqs5xx_device_resolution_t.resolution_x = 1280; 305 azoteq_iqs5xx_device_resolution_t.resolution_y = 768; 306 break; 307 default: 308 // shouldn't be here 309 azoteq_iqs5xx_device_resolution_t.resolution_x = 0; 310 azoteq_iqs5xx_device_resolution_t.resolution_y = 0; 311 break; 312 } 313 #endif 314 #ifdef AZOTEQ_IQS5XX_RESOLUTION_X 315 azoteq_iqs5xx_device_resolution_t.resolution_x = AZOTEQ_IQS5XX_RESOLUTION_X; 316 #endif 317 #ifdef AZOTEQ_IQS5XX_RESOLUTION_Y 318 azoteq_iqs5xx_device_resolution_t.resolution_y = AZOTEQ_IQS5XX_RESOLUTION_Y; 319 #endif 320 } 321 322 static i2c_status_t azoteq_iqs5xx_init_status = 1; 323 324 bool azoteq_iqs5xx_init(void) { 325 i2c_init(); 326 i2c_ping_address(AZOTEQ_IQS5XX_ADDRESS, 1); // wake 327 azoteq_iqs5xx_reset_suspend(true, false, true); 328 wait_ms(100); 329 i2c_ping_address(AZOTEQ_IQS5XX_ADDRESS, 1); // wake 330 if (azoteq_iqs5xx_get_product() != AZOTEQ_IQS5XX_UNKNOWN) { 331 azoteq_iqs5xx_setup_resolution(); 332 azoteq_iqs5xx_init_status = azoteq_iqs5xx_set_report_rate(AZOTEQ_IQS5XX_REPORT_RATE, AZOTEQ_IQS5XX_ACTIVE, false); 333 azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_report_rate(AZOTEQ_IQS5XX_REPORT_RATE, AZOTEQ_IQS5XX_IDLE, false); 334 azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_report_rate(AZOTEQ_IQS5XX_REPORT_RATE, AZOTEQ_IQS5XX_IDLE_TOUCH, false); 335 336 uint8_t no_timeout = 255; 337 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 338 azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_event_mode(AZOTEQ_IQS5XX_EVENT_MODE, false); 339 azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_reati(true, false); 340 #if defined(AZOTEQ_IQS5XX_ROTATION_90) 341 azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_xy_config(false, true, true, true, false); 342 #elif defined(AZOTEQ_IQS5XX_ROTATION_180) 343 azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_xy_config(true, true, false, true, false); 344 #elif defined(AZOTEQ_IQS5XX_ROTATION_270) 345 azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_xy_config(true, false, true, true, false); 346 #else 347 azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_xy_config(false, false, false, true, false); 348 #endif 349 azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_gesture_config(true); 350 wait_ms(AZOTEQ_IQS5XX_REPORT_RATE + 1); 351 } 352 353 return azoteq_iqs5xx_init_status == I2C_STATUS_SUCCESS; 354 }; 355 356 report_mouse_t azoteq_iqs5xx_get_report(report_mouse_t mouse_report) { 357 report_mouse_t temp_report = {0}; 358 359 azoteq_iqs5xx_base_data_t base_data = {0}; 360 i2c_status_t status = azoteq_iqs5xx_get_base_data(&base_data); 361 bool ignore_movement = false; 362 363 if (status == I2C_STATUS_SUCCESS) { 364 #ifdef POINTING_DEVICE_DEBUG 365 if (base_data.previous_cycle_time > AZOTEQ_IQS5XX_REPORT_RATE) { 366 pd_dprintf("IQS5XX - previous cycle time missed, took: %dms\n", base_data.previous_cycle_time); 367 } 368 #endif 369 if (base_data.gesture_events_0.single_tap || base_data.gesture_events_0.press_and_hold) { 370 pd_dprintf("IQS5XX - Single tap/hold.\n"); 371 temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON1); 372 } else if (base_data.gesture_events_1.two_finger_tap) { 373 pd_dprintf("IQS5XX - Two finger tap.\n"); 374 temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON2); 375 } else if (base_data.gesture_events_0.swipe_x_neg) { 376 pd_dprintf("IQS5XX - X-.\n"); 377 temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON4); 378 ignore_movement = true; 379 } else if (base_data.gesture_events_0.swipe_x_pos) { 380 pd_dprintf("IQS5XX - X+.\n"); 381 temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON5); 382 ignore_movement = true; 383 } else if (base_data.gesture_events_0.swipe_y_neg) { 384 pd_dprintf("IQS5XX - Y-.\n"); 385 temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON6); 386 ignore_movement = true; 387 } else if (base_data.gesture_events_0.swipe_y_pos) { 388 pd_dprintf("IQS5XX - Y+.\n"); 389 temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON3); 390 ignore_movement = true; 391 } else if (base_data.gesture_events_1.zoom) { 392 if (AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.x.h, base_data.x.l) < 0) { 393 pd_dprintf("IQS5XX - Zoom out.\n"); 394 temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON7); 395 } else if (AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.x.h, base_data.x.l) > 0) { 396 pd_dprintf("IQS5XX - Zoom in.\n"); 397 temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON8); 398 } 399 } else if (base_data.gesture_events_1.scroll) { 400 pd_dprintf("IQS5XX - Scroll.\n"); 401 temp_report.h = CONSTRAIN_HID(AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.x.h, base_data.x.l)); 402 temp_report.v = CONSTRAIN_HID(AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.y.h, base_data.y.l)); 403 } 404 if (base_data.number_of_fingers == 1 && !ignore_movement) { 405 temp_report.x = CONSTRAIN_HID_XY(AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.x.h, base_data.x.l)); 406 temp_report.y = CONSTRAIN_HID_XY(AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.y.h, base_data.y.l)); 407 } 408 409 } else { 410 pd_dprintf("IQS5XX - get report failed, i2c status: %d \n", status); 411 } 412 413 return temp_report; 414 }