logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

azoteq_iqs5xx.c (21106B)


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