logo

qmk_firmware

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

analog_joystick.c (5052B)


  1. /* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "analog_joystick.h"
  17. #include "analog.h"
  18. #include "gpio.h"
  19. #include "wait.h"
  20. #include "timer.h"
  21. #include <stdlib.h>
  22. #include "pointing_device_internal.h"
  23. const pointing_device_driver_t analog_joystick_pointing_device_driver = {
  24. .init = analog_joystick_init,
  25. .get_report = analog_joystick_get_report,
  26. .set_cpi = NULL,
  27. .get_cpi = NULL,
  28. };
  29. // Set Parameters
  30. #ifndef ANALOG_JOYSTICK_AUTO_AXIS
  31. uint16_t minAxisValue = ANALOG_JOYSTICK_AXIS_MIN;
  32. uint16_t maxAxisValue = ANALOG_JOYSTICK_AXIS_MAX;
  33. #else
  34. int16_t minAxisValues[2];
  35. int16_t maxAxisValues[2];
  36. #endif
  37. uint8_t maxCursorSpeed = ANALOG_JOYSTICK_SPEED_MAX;
  38. uint8_t speedRegulator = ANALOG_JOYSTICK_SPEED_REGULATOR; // Lower Values Create Faster Movement
  39. #ifdef ANALOG_JOYSTICK_WEIGHTS
  40. int8_t weights[101] = ANALOG_JOYSTICK_WEIGHTS;
  41. #endif
  42. int16_t xOrigin, yOrigin;
  43. uint16_t lastCursor = 0;
  44. uint8_t prevValues[2] = {0, 0};
  45. int16_t axisCoordinate(pin_t pin, uint16_t origin, uint8_t axis) {
  46. int8_t direction;
  47. int16_t distanceFromOrigin;
  48. int16_t range;
  49. int16_t position = analogReadPin(pin);
  50. if (origin == position) {
  51. return 0;
  52. } else if (origin > position) {
  53. distanceFromOrigin = origin - position;
  54. #ifdef ANALOG_JOYSTICK_AUTO_AXIS
  55. if (position < minAxisValues[axis]) {
  56. minAxisValues[axis] = position;
  57. }
  58. range = origin - minAxisValues[axis];
  59. #else
  60. range = origin - minAxisValue;
  61. #endif
  62. direction = -1;
  63. } else {
  64. distanceFromOrigin = position - origin;
  65. #ifdef ANALOG_JOYSTICK_AUTO_AXIS
  66. if (position > maxAxisValues[axis]) {
  67. maxAxisValues[axis] = position;
  68. }
  69. range = maxAxisValues[axis] - origin;
  70. #else
  71. range = maxAxisValue - origin;
  72. #endif
  73. direction = 1;
  74. }
  75. float percent = (float)distanceFromOrigin / range;
  76. int16_t coordinate = (int16_t)(percent * 100);
  77. if (coordinate < 0) {
  78. return 0;
  79. } else if (coordinate > 100) {
  80. return 100 * direction;
  81. } else {
  82. return coordinate * direction;
  83. }
  84. }
  85. int8_t axisToMouseComponent(pin_t pin, int16_t origin, uint8_t maxSpeed, uint8_t axis) {
  86. int16_t coordinate = axisCoordinate(pin, origin, axis);
  87. int8_t result;
  88. #ifndef ANALOG_JOYSTICK_WEIGHTS
  89. if (coordinate != 0) {
  90. float percent = (float)coordinate / 100;
  91. result = percent * maxCursorSpeed * (abs(coordinate) / speedRegulator);
  92. } else {
  93. return 0;
  94. }
  95. #else
  96. result = weights[abs(coordinate)] * (coordinate < 0 ? -1 : 1) * maxCursorSpeed / speedRegulator;
  97. #endif
  98. #ifdef ANALOG_JOYSTICK_CUTOFF
  99. uint8_t pv = prevValues[axis];
  100. prevValues[axis] = abs(result);
  101. if (pv > abs(result)) {
  102. return 0;
  103. }
  104. #endif
  105. return result;
  106. }
  107. report_analog_joystick_t analog_joystick_read(void) {
  108. report_analog_joystick_t report = {0};
  109. if (timer_elapsed(lastCursor) > ANALOG_JOYSTICK_READ_INTERVAL) {
  110. lastCursor = timer_read();
  111. report.x = axisToMouseComponent(ANALOG_JOYSTICK_X_AXIS_PIN, xOrigin, maxCursorSpeed, 0);
  112. report.y = axisToMouseComponent(ANALOG_JOYSTICK_Y_AXIS_PIN, yOrigin, maxCursorSpeed, 1);
  113. }
  114. #ifdef ANALOG_JOYSTICK_CLICK_PIN
  115. report.button = !gpio_read_pin(ANALOG_JOYSTICK_CLICK_PIN);
  116. #endif
  117. return report;
  118. }
  119. void analog_joystick_init(void) {
  120. gpio_set_pin_input_high(ANALOG_JOYSTICK_X_AXIS_PIN);
  121. gpio_set_pin_input_high(ANALOG_JOYSTICK_Y_AXIS_PIN);
  122. #ifdef ANALOG_JOYSTICK_CLICK_PIN
  123. gpio_set_pin_input_high(ANALOG_JOYSTICK_CLICK_PIN);
  124. #endif
  125. // Account for drift
  126. xOrigin = analogReadPin(ANALOG_JOYSTICK_X_AXIS_PIN);
  127. yOrigin = analogReadPin(ANALOG_JOYSTICK_Y_AXIS_PIN);
  128. #ifdef ANALOG_JOYSTICK_AUTO_AXIS
  129. minAxisValues[0] = xOrigin - 100;
  130. minAxisValues[1] = yOrigin - 100;
  131. maxAxisValues[0] = xOrigin + 100;
  132. maxAxisValues[1] = yOrigin + 100;
  133. #endif
  134. }
  135. report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) {
  136. report_analog_joystick_t data = analog_joystick_read();
  137. pd_dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
  138. mouse_report.x = data.x;
  139. mouse_report.y = data.y;
  140. mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, data.button, POINTING_DEVICE_BUTTON1);
  141. return mouse_report;
  142. }