analog_joystick.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. // Set Parameters
  23. #ifndef ANALOG_JOYSTICK_AUTO_AXIS
  24. uint16_t minAxisValue = ANALOG_JOYSTICK_AXIS_MIN;
  25. uint16_t maxAxisValue = ANALOG_JOYSTICK_AXIS_MAX;
  26. #else
  27. int16_t minAxisValues[2];
  28. int16_t maxAxisValues[2];
  29. #endif
  30. uint8_t maxCursorSpeed = ANALOG_JOYSTICK_SPEED_MAX;
  31. uint8_t speedRegulator = ANALOG_JOYSTICK_SPEED_REGULATOR; // Lower Values Create Faster Movement
  32. #ifdef ANALOG_JOYSTICK_WEIGHTS
  33. int8_t weights[101] = ANALOG_JOYSTICK_WEIGHTS;
  34. #endif
  35. int16_t xOrigin, yOrigin;
  36. uint16_t lastCursor = 0;
  37. uint8_t prevValues[2] = {0, 0};
  38. int16_t axisCoordinate(pin_t pin, uint16_t origin, uint8_t axis) {
  39. int8_t direction;
  40. int16_t distanceFromOrigin;
  41. int16_t range;
  42. int16_t position = analogReadPin(pin);
  43. if (origin == position) {
  44. return 0;
  45. } else if (origin > position) {
  46. distanceFromOrigin = origin - position;
  47. #ifdef ANALOG_JOYSTICK_AUTO_AXIS
  48. if (position < minAxisValues[axis]) {
  49. minAxisValues[axis] = position;
  50. }
  51. range = origin - minAxisValues[axis];
  52. #else
  53. range = origin - minAxisValue;
  54. #endif
  55. direction = -1;
  56. } else {
  57. distanceFromOrigin = position - origin;
  58. #ifdef ANALOG_JOYSTICK_AUTO_AXIS
  59. if (position > maxAxisValues[axis]) {
  60. maxAxisValues[axis] = position;
  61. }
  62. range = maxAxisValues[axis] - origin;
  63. #else
  64. range = maxAxisValue - origin;
  65. #endif
  66. direction = 1;
  67. }
  68. float percent = (float)distanceFromOrigin / range;
  69. int16_t coordinate = (int16_t)(percent * 100);
  70. if (coordinate < 0) {
  71. return 0;
  72. } else if (coordinate > 100) {
  73. return 100 * direction;
  74. } else {
  75. return coordinate * direction;
  76. }
  77. }
  78. int8_t axisToMouseComponent(pin_t pin, int16_t origin, uint8_t maxSpeed, uint8_t axis) {
  79. int16_t coordinate = axisCoordinate(pin, origin, axis);
  80. int8_t result;
  81. #ifndef ANALOG_JOYSTICK_WEIGHTS
  82. if (coordinate != 0) {
  83. float percent = (float)coordinate / 100;
  84. result = percent * maxCursorSpeed * (abs(coordinate) / speedRegulator);
  85. } else {
  86. return 0;
  87. }
  88. #else
  89. result = weights[abs(coordinate)] * (coordinate < 0 ? -1 : 1) * maxCursorSpeed / speedRegulator;
  90. #endif
  91. #ifdef ANALOG_JOYSTICK_CUTOFF
  92. uint8_t pv = prevValues[axis];
  93. prevValues[axis] = abs(result);
  94. if (pv > abs(result)) {
  95. return 0;
  96. }
  97. #endif
  98. return result;
  99. }
  100. report_analog_joystick_t analog_joystick_read(void) {
  101. report_analog_joystick_t report = {0};
  102. if (timer_elapsed(lastCursor) > ANALOG_JOYSTICK_READ_INTERVAL) {
  103. lastCursor = timer_read();
  104. report.x = axisToMouseComponent(ANALOG_JOYSTICK_X_AXIS_PIN, xOrigin, maxCursorSpeed, 0);
  105. report.y = axisToMouseComponent(ANALOG_JOYSTICK_Y_AXIS_PIN, yOrigin, maxCursorSpeed, 1);
  106. }
  107. #ifdef ANALOG_JOYSTICK_CLICK_PIN
  108. report.button = !gpio_read_pin(ANALOG_JOYSTICK_CLICK_PIN);
  109. #endif
  110. return report;
  111. }
  112. void analog_joystick_init(void) {
  113. gpio_set_pin_input_high(ANALOG_JOYSTICK_X_AXIS_PIN);
  114. gpio_set_pin_input_high(ANALOG_JOYSTICK_Y_AXIS_PIN);
  115. #ifdef ANALOG_JOYSTICK_CLICK_PIN
  116. gpio_set_pin_input_high(ANALOG_JOYSTICK_CLICK_PIN);
  117. #endif
  118. // Account for drift
  119. xOrigin = analogReadPin(ANALOG_JOYSTICK_X_AXIS_PIN);
  120. yOrigin = analogReadPin(ANALOG_JOYSTICK_Y_AXIS_PIN);
  121. #ifdef ANALOG_JOYSTICK_AUTO_AXIS
  122. minAxisValues[0] = xOrigin - 100;
  123. minAxisValues[1] = yOrigin - 100;
  124. maxAxisValues[0] = xOrigin + 100;
  125. maxAxisValues[1] = yOrigin + 100;
  126. #endif
  127. }