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.

215 lines
6.5 KiB

  1. /* Copyright 2021 Colin Lam (Ploopy Corporation)
  2. * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
  3. * Copyright 2019 Sunjun Kim
  4. * Copyright 2019 Hiroyuki Okada
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "trackball_mini.h"
  20. #include "wait.h"
  21. #include "debug.h"
  22. #ifndef OPT_DEBOUNCE
  23. # define OPT_DEBOUNCE 5 // (ms) Time between scroll events
  24. #endif
  25. #ifndef SCROLL_BUTT_DEBOUNCE
  26. # define SCROLL_BUTT_DEBOUNCE 100 // (ms) Time between scroll events
  27. #endif
  28. #ifndef OPT_THRES
  29. # define OPT_THRES 150 // (0-1024) Threshold for actication
  30. #endif
  31. #ifndef OPT_SCALE
  32. # define OPT_SCALE 1 // Multiplier for wheel
  33. #endif
  34. #ifndef PLOOPY_DPI_OPTIONS
  35. # define PLOOPY_DPI_OPTIONS \
  36. { 375, 750, 1375 }
  37. # ifndef PLOOPY_DPI_DEFAULT
  38. # define PLOOPY_DPI_DEFAULT 1
  39. # endif
  40. #endif
  41. #ifndef PLOOPY_DPI_DEFAULT
  42. # define PLOOPY_DPI_DEFAULT 0
  43. #endif
  44. #ifndef PLOOPY_DRAGSCROLL_DPI
  45. # define PLOOPY_DRAGSCROLL_DPI 375 // Fixed-DPI Drag Scroll
  46. #endif
  47. #ifndef PLOOPY_DRAGSCROLL_MULTIPLIER
  48. # define PLOOPY_DRAGSCROLL_MULTIPLIER 0.75 // Variable-DPI Drag Scroll
  49. #endif
  50. keyboard_config_t keyboard_config;
  51. uint16_t dpi_array[] = PLOOPY_DPI_OPTIONS;
  52. #define DPI_OPTION_SIZE ARRAY_SIZE(dpi_array)
  53. // TODO: Implement libinput profiles
  54. // https://wayland.freedesktop.org/libinput/doc/latest/pointer-acceleration.html
  55. // Compile time accel selection
  56. // Valid options are ACC_NONE, ACC_LINEAR, ACC_CUSTOM, ACC_QUADRATIC
  57. // Trackball State
  58. bool is_scroll_clicked = false;
  59. bool BurstState = false; // init burst state for Trackball module
  60. uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
  61. uint16_t lastScroll = 0; // Previous confirmed wheel event
  62. uint16_t lastMidClick = 0; // Stops scrollwheel from being read if it was pressed
  63. uint8_t OptLowPin = OPT_ENC1;
  64. bool debug_encoder = false;
  65. bool is_drag_scroll = false;
  66. __attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; }
  67. bool encoder_update_kb(uint8_t index, bool clockwise) {
  68. if (!encoder_update_user(index, clockwise)) {
  69. return false;
  70. }
  71. #ifdef MOUSEKEY_ENABLE
  72. tap_code(clockwise ? KC_WH_U : KC_WH_D);
  73. #else
  74. mouse_report_t mouse_report = pointing_device_get_report();
  75. mouse_report.v = clockwise ? 1 : -1;
  76. pointing_device_set_report(mouse_report);
  77. pointing_device_send();
  78. #endif
  79. return true;
  80. }
  81. void process_wheel(void) {
  82. // If the mouse wheel was just released, do not scroll.
  83. if (timer_elapsed(lastMidClick) < SCROLL_BUTT_DEBOUNCE) return;
  84. // Limit the number of scrolls per unit time.
  85. if (timer_elapsed(lastScroll) < OPT_DEBOUNCE) return;
  86. // Don't scroll if the middle button is depressed.
  87. if (is_scroll_clicked) {
  88. #ifndef IGNORE_SCROLL_CLICK
  89. return;
  90. #endif
  91. }
  92. lastScroll = timer_read();
  93. uint16_t p1 = adc_read(OPT_ENC1_MUX);
  94. uint16_t p2 = adc_read(OPT_ENC2_MUX);
  95. if (debug_encoder) dprintf("OPT1: %d, OPT2: %d\n", p1, p2);
  96. int8_t dir = opt_encoder_handler(p1, p2);
  97. if (dir == 0) return;
  98. encoder_update_kb(0, dir > 0);
  99. }
  100. void pointing_device_init_kb(void) {
  101. opt_encoder_init();
  102. // set the DPI.
  103. pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
  104. }
  105. report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
  106. process_wheel();
  107. if (is_drag_scroll) {
  108. mouse_report.h = mouse_report.x;
  109. #ifdef PLOOPY_DRAGSCROLL_INVERT
  110. // Invert vertical scroll direction
  111. mouse_report.v = -mouse_report.y;
  112. #else
  113. mouse_report.v = mouse_report.y;
  114. #endif
  115. mouse_report.x = 0;
  116. mouse_report.y = 0;
  117. }
  118. return pointing_device_task_user(mouse_report);
  119. }
  120. bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
  121. xprintf("KL: kc: %u, col: %u, row: %u, pressed: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed);
  122. // Update Timer to prevent accidental scrolls
  123. if ((record->event.key.col == 1) && (record->event.key.row == 0)) {
  124. lastMidClick = timer_read();
  125. is_scroll_clicked = record->event.pressed;
  126. }
  127. if (!process_record_user(keycode, record)) return false;
  128. if (keycode == DPI_CONFIG && record->event.pressed) {
  129. keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE;
  130. eeconfig_update_kb(keyboard_config.raw);
  131. pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
  132. }
  133. if (keycode == DRAG_SCROLL) {
  134. #ifndef PLOOPY_DRAGSCROLL_MOMENTARY
  135. if (record->event.pressed)
  136. #endif
  137. {
  138. is_drag_scroll ^= 1;
  139. }
  140. pointing_device_set_cpi(is_drag_scroll ? PLOOPY_DRAGSCROLL_DPI : dpi_array[keyboard_config.dpi_config]);
  141. }
  142. return true;
  143. }
  144. // Hardware Setup
  145. void keyboard_pre_init_kb(void) {
  146. // debug_enable = true;
  147. // debug_matrix = true;
  148. // debug_mouse = true;
  149. // debug_encoder = true;
  150. setPinInput(OPT_ENC1);
  151. setPinInput(OPT_ENC2);
  152. /* Ground all output pins connected to ground. This provides additional
  153. * pathways to ground. If you're messing with this, know this: driving ANY
  154. * of these pins high will cause a short. On the MCU. Ka-blooey.
  155. */
  156. #ifdef UNUSABLE_PINS
  157. const pin_t unused_pins[] = UNUSABLE_PINS;
  158. for (uint8_t i = 0; i < ARRAY_SIZE(unused_pins); i++) {
  159. setPinOutput(unused_pins[i]);
  160. writePinLow(unused_pins[i]);
  161. }
  162. #endif
  163. keyboard_pre_init_user();
  164. }
  165. void eeconfig_init_kb(void) {
  166. keyboard_config.dpi_config = PLOOPY_DPI_DEFAULT;
  167. eeconfig_update_kb(keyboard_config.raw);
  168. eeconfig_init_user();
  169. }
  170. void matrix_init_kb(void) {
  171. // is safe to just read DPI setting since matrix init
  172. // comes before pointing device init.
  173. keyboard_config.raw = eeconfig_read_kb();
  174. if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
  175. eeconfig_init_kb();
  176. }
  177. matrix_init_user();
  178. }