You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

303 lines
10 KiB

  1. /* Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com>
  2. * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
  3. * Copyright 2021 Dasky (@daskygit)
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "pointing_device.h"
  19. #include "debug.h"
  20. #include "wait.h"
  21. #include "timer.h"
  22. #include <stddef.h>
  23. // hid mouse reports cannot exceed -127 to 127, so constrain to that value
  24. #define constrain_hid(amt) ((amt) < -127 ? -127 : ((amt) > 127 ? 127 : (amt)))
  25. // get_report functions should probably be moved to their respective drivers.
  26. #if defined(POINTING_DEVICE_DRIVER_adns5050)
  27. report_mouse_t adns5050_get_report(report_mouse_t mouse_report) {
  28. report_adns5050_t data = adns5050_read_burst();
  29. if (data.dx != 0 || data.dy != 0) {
  30. # ifdef CONSOLE_ENABLE
  31. if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy);
  32. # endif
  33. mouse_report.x = data.dx;
  34. mouse_report.y = data.dy;
  35. }
  36. return mouse_report;
  37. }
  38. // clang-format off
  39. const pointing_device_driver_t pointing_device_driver = {
  40. .init = adns5050_init,
  41. .get_report = adns5050_get_report,
  42. .set_cpi = adns5050_set_cpi,
  43. .get_cpi = adns5050_get_cpi,
  44. };
  45. // clang-format on
  46. #elif defined(POINTING_DEVICE_DRIVER_adns9800)
  47. report_mouse_t adns9800_get_report_driver(report_mouse_t mouse_report) {
  48. report_adns9800_t sensor_report = adns9800_get_report();
  49. int8_t clamped_x = constrain_hid(sensor_report.x);
  50. int8_t clamped_y = constrain_hid(sensor_report.y);
  51. mouse_report.x = clamped_x;
  52. mouse_report.y = clamped_y;
  53. return mouse_report;
  54. }
  55. // clang-format off
  56. const pointing_device_driver_t pointing_device_driver = {
  57. .init = adns9800_init,
  58. .get_report = adns9800_get_report_driver,
  59. .set_cpi = adns9800_set_cpi,
  60. .get_cpi = adns9800_get_cpi
  61. };
  62. // clang-format on
  63. #elif defined(POINTING_DEVICE_DRIVER_analog_joystick)
  64. report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) {
  65. report_analog_joystick_t data = analog_joystick_read();
  66. # ifdef CONSOLE_ENABLE
  67. if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
  68. # endif
  69. mouse_report.x = data.x;
  70. mouse_report.y = data.y;
  71. mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, data.button, POINTING_DEVICE_BUTTON1);
  72. return mouse_report;
  73. }
  74. // clang-format off
  75. const pointing_device_driver_t pointing_device_driver = {
  76. .init = analog_joystick_init,
  77. .get_report = analog_joystick_get_report,
  78. .set_cpi = NULL,
  79. .get_cpi = NULL
  80. };
  81. // clang-format on
  82. #elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
  83. # ifndef CIRQUE_PINNACLE_TAPPING_TERM
  84. # ifdef TAPPING_TERM_PER_KEY
  85. # include "action.h"
  86. # include "action_tapping.h"
  87. # define CIRQUE_PINNACLE_TAPPING_TERM get_tapping_term(KC_BTN1, &(keyrecord_t){})
  88. # else
  89. # ifdef TAPPING_TERM
  90. # define CIRQUE_PINNACLE_TAPPING_TERM TAPPING_TERM
  91. # else
  92. # define CIRQUE_PINNACLE_TAPPING_TERM 200
  93. # endif
  94. # endif
  95. # endif
  96. # ifndef CIRQUE_PINNACLE_TOUCH_DEBOUNCE
  97. # define CIRQUE_PINNACLE_TOUCH_DEBOUNCE (CIRQUE_PINNACLE_TAPPING_TERM * 8)
  98. # endif
  99. report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
  100. pinnacle_data_t touchData = cirque_pinnacle_read_data();
  101. static uint16_t x = 0, y = 0, mouse_timer = 0;
  102. int8_t report_x = 0, report_y = 0;
  103. static bool is_z_down = false;
  104. cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); // Scale coordinates to arbitrary X, Y resolution
  105. if (x && y && touchData.xValue && touchData.yValue) {
  106. report_x = (int8_t)(touchData.xValue - x);
  107. report_y = (int8_t)(touchData.yValue - y);
  108. }
  109. x = touchData.xValue;
  110. y = touchData.yValue;
  111. if ((bool)touchData.zValue != is_z_down) {
  112. is_z_down = (bool)touchData.zValue;
  113. if (!touchData.zValue) {
  114. if (timer_elapsed(mouse_timer) < CIRQUE_PINNACLE_TAPPING_TERM && mouse_timer != 0) {
  115. mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
  116. pointing_device_set_report(mouse_report);
  117. pointing_device_send();
  118. # if TAP_CODE_DELAY > 0
  119. wait_ms(TAP_CODE_DELAY);
  120. # endif
  121. mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
  122. pointing_device_set_report(mouse_report);
  123. pointing_device_send();
  124. }
  125. }
  126. mouse_timer = timer_read();
  127. }
  128. if (timer_elapsed(mouse_timer) > (CIRQUE_PINNACLE_TOUCH_DEBOUNCE)) {
  129. mouse_timer = 0;
  130. }
  131. mouse_report.x = report_x;
  132. mouse_report.y = report_y;
  133. return mouse_report;
  134. }
  135. // clang-format off
  136. const pointing_device_driver_t pointing_device_driver = {
  137. .init = cirque_pinnacle_init,
  138. .get_report = cirque_pinnacle_get_report,
  139. .set_cpi = cirque_pinnacle_set_scale,
  140. .get_cpi = cirque_pinnacle_get_scale
  141. };
  142. // clang-format on
  143. #elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
  144. report_mouse_t pimoroni_trackball_get_report(report_mouse_t mouse_report) {
  145. static uint16_t debounce = 0;
  146. static uint8_t error_count = 0;
  147. pimoroni_data_t pimoroni_data = {0};
  148. static int16_t x_offset = 0, y_offset = 0;
  149. if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT) {
  150. i2c_status_t status = read_pimoroni_trackball(&pimoroni_data);
  151. if (status == I2C_STATUS_SUCCESS) {
  152. error_count = 0;
  153. if (!(pimoroni_data.click & 128)) {
  154. mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
  155. if (!debounce) {
  156. x_offset += pimoroni_trackball_get_offsets(pimoroni_data.right, pimoroni_data.left, PIMORONI_TRACKBALL_SCALE);
  157. y_offset += pimoroni_trackball_get_offsets(pimoroni_data.down, pimoroni_data.up, PIMORONI_TRACKBALL_SCALE);
  158. pimoroni_trackball_adapt_values(&mouse_report.x, &x_offset);
  159. pimoroni_trackball_adapt_values(&mouse_report.y, &y_offset);
  160. } else {
  161. debounce--;
  162. }
  163. } else {
  164. mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
  165. debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES;
  166. }
  167. } else {
  168. error_count++;
  169. }
  170. }
  171. return mouse_report;
  172. }
  173. // clang-format off
  174. const pointing_device_driver_t pointing_device_driver = {
  175. .init = pimoroni_trackball_device_init,
  176. .get_report = pimoroni_trackball_get_report,
  177. .set_cpi = pimoroni_trackball_set_cpi,
  178. .get_cpi = pimoroni_trackball_get_cpi
  179. };
  180. // clang-format on
  181. #elif defined(POINTING_DEVICE_DRIVER_pmw3360)
  182. static void pmw3360_device_init(void) {
  183. pmw3360_init();
  184. }
  185. report_mouse_t pmw3360_get_report(report_mouse_t mouse_report) {
  186. report_pmw3360_t data = pmw3360_read_burst();
  187. static uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
  188. if (data.isOnSurface && data.isMotion) {
  189. // Reset timer if stopped moving
  190. if (!data.isMotion) {
  191. if (MotionStart != 0) MotionStart = 0;
  192. return mouse_report;
  193. }
  194. // Set timer if new motion
  195. if ((MotionStart == 0) && data.isMotion) {
  196. # ifdef CONSOLE_ENABLE
  197. if (debug_mouse) dprintf("Starting motion.\n");
  198. # endif
  199. MotionStart = timer_read();
  200. }
  201. mouse_report.x = constrain_hid(data.dx);
  202. mouse_report.y = constrain_hid(data.dy);
  203. }
  204. return mouse_report;
  205. }
  206. // clang-format off
  207. const pointing_device_driver_t pointing_device_driver = {
  208. .init = pmw3360_device_init,
  209. .get_report = pmw3360_get_report,
  210. .set_cpi = pmw3360_set_cpi,
  211. .get_cpi = pmw3360_get_cpi
  212. };
  213. // clang-format on
  214. #elif defined(POINTING_DEVICE_DRIVER_pmw3389)
  215. static void pmw3389_device_init(void) {
  216. pmw3389_init();
  217. }
  218. report_mouse_t pmw3389_get_report(report_mouse_t mouse_report) {
  219. report_pmw3389_t data = pmw3389_read_burst();
  220. static uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
  221. if (data.isOnSurface && data.isMotion) {
  222. // Reset timer if stopped moving
  223. if (!data.isMotion) {
  224. if (MotionStart != 0) MotionStart = 0;
  225. return mouse_report;
  226. }
  227. // Set timer if new motion
  228. if ((MotionStart == 0) && data.isMotion) {
  229. # ifdef CONSOLE_ENABLE
  230. if (debug_mouse) dprintf("Starting motion.\n");
  231. # endif
  232. MotionStart = timer_read();
  233. }
  234. mouse_report.x = constrain_hid(data.dx);
  235. mouse_report.y = constrain_hid(data.dy);
  236. }
  237. return mouse_report;
  238. }
  239. // clang-format off
  240. const pointing_device_driver_t pointing_device_driver = {
  241. .init = pmw3389_device_init,
  242. .get_report = pmw3389_get_report,
  243. .set_cpi = pmw3389_set_cpi,
  244. .get_cpi = pmw3389_get_cpi
  245. };
  246. // clang-format on
  247. #else
  248. __attribute__((weak)) void pointing_device_driver_init(void) {}
  249. __attribute__((weak)) report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) {
  250. return mouse_report;
  251. }
  252. __attribute__((weak)) uint16_t pointing_device_driver_get_cpi(void) {
  253. return 0;
  254. }
  255. __attribute__((weak)) void pointing_device_driver_set_cpi(uint16_t cpi) {}
  256. // clang-format off
  257. const pointing_device_driver_t pointing_device_driver = {
  258. .init = pointing_device_driver_init,
  259. .get_report = pointing_device_driver_get_report,
  260. .get_cpi = pointing_device_driver_get_cpi,
  261. .set_cpi = pointing_device_driver_set_cpi
  262. };
  263. // clang-format on
  264. #endif