logo

qmk_firmware

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

joystick.c (4306B)


  1. /* Copyright 2022
  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 "joystick.h"
  17. #include "wait.h"
  18. #if defined(JOYSTICK_ANALOG)
  19. # include "analog.h"
  20. #endif
  21. joystick_t joystick_state = {
  22. .buttons = {0},
  23. .axes =
  24. {
  25. #if JOYSTICK_AXIS_COUNT > 0
  26. 0
  27. #endif
  28. },
  29. #ifdef JOYSTICK_HAS_HAT
  30. .hat = -1,
  31. #endif
  32. .dirty = false,
  33. };
  34. // array defining the reading of analog values for each axis
  35. __attribute__((weak)) joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = {
  36. #if JOYSTICK_AXIS_COUNT > 0
  37. [0 ...(JOYSTICK_AXIS_COUNT - 1)] = JOYSTICK_AXIS_VIRTUAL
  38. #endif
  39. };
  40. __attribute__((weak)) void joystick_axis_init(uint8_t axis) {
  41. if (axis >= JOYSTICK_AXIS_COUNT) return;
  42. #if defined(JOYSTICK_ANALOG)
  43. gpio_set_pin_input(joystick_axes[axis].input_pin);
  44. #endif
  45. }
  46. __attribute__((weak)) uint16_t joystick_axis_sample(uint8_t axis) {
  47. if (axis >= JOYSTICK_AXIS_COUNT) return 0;
  48. #if defined(JOYSTICK_ANALOG)
  49. return analogReadPin(joystick_axes[axis].input_pin);
  50. #else
  51. // default to resting position
  52. return joystick_axes[axis].mid_digit;
  53. #endif
  54. }
  55. static inline bool is_virtual_axis(uint8_t axis) {
  56. return joystick_axes[axis].input_pin == NO_PIN;
  57. }
  58. void joystick_flush(void) {
  59. if (!joystick_state.dirty) return;
  60. // TODO: host.h?
  61. void host_joystick_send(joystick_t * joystick);
  62. host_joystick_send(&joystick_state);
  63. joystick_state.dirty = false;
  64. }
  65. void register_joystick_button(uint8_t button) {
  66. if (button >= JOYSTICK_BUTTON_COUNT) return;
  67. joystick_state.buttons[button / 8] |= 1 << (button % 8);
  68. joystick_state.dirty = true;
  69. joystick_flush();
  70. }
  71. void unregister_joystick_button(uint8_t button) {
  72. if (button >= JOYSTICK_BUTTON_COUNT) return;
  73. joystick_state.buttons[button / 8] &= ~(1 << (button % 8));
  74. joystick_state.dirty = true;
  75. joystick_flush();
  76. }
  77. int16_t joystick_read_axis(uint8_t axis) {
  78. if (axis >= JOYSTICK_AXIS_COUNT) return 0;
  79. int16_t axis_val = joystick_axis_sample(axis);
  80. // test the converted value against the lower range
  81. int32_t ref = joystick_axes[axis].mid_digit;
  82. int32_t range = joystick_axes[axis].min_digit;
  83. int32_t ranged_val = ((axis_val - ref) * -JOYSTICK_MAX_VALUE) / (range - ref);
  84. if (ranged_val > 0) {
  85. // the value is in the higher range
  86. range = joystick_axes[axis].max_digit;
  87. ranged_val = ((axis_val - ref) * JOYSTICK_MAX_VALUE) / (range - ref);
  88. }
  89. // clamp the result in the valid range
  90. ranged_val = ranged_val < -JOYSTICK_MAX_VALUE ? -JOYSTICK_MAX_VALUE : ranged_val;
  91. ranged_val = ranged_val > JOYSTICK_MAX_VALUE ? JOYSTICK_MAX_VALUE : ranged_val;
  92. return ranged_val;
  93. }
  94. void joystick_init_axes(void) {
  95. #if JOYSTICK_AXIS_COUNT > 0
  96. for (int i = 0; i < JOYSTICK_AXIS_COUNT; ++i) {
  97. if (is_virtual_axis(i)) {
  98. continue;
  99. }
  100. joystick_axis_init(i);
  101. }
  102. #endif
  103. }
  104. void joystick_read_axes(void) {
  105. #if JOYSTICK_AXIS_COUNT > 0
  106. for (int i = 0; i < JOYSTICK_AXIS_COUNT; ++i) {
  107. if (is_virtual_axis(i)) {
  108. continue;
  109. }
  110. joystick_set_axis(i, joystick_read_axis(i));
  111. }
  112. joystick_flush();
  113. #endif
  114. }
  115. void joystick_set_axis(uint8_t axis, int16_t value) {
  116. if (axis >= JOYSTICK_AXIS_COUNT) return;
  117. if (value != joystick_state.axes[axis]) {
  118. joystick_state.axes[axis] = value;
  119. joystick_state.dirty = true;
  120. }
  121. }
  122. #ifdef JOYSTICK_HAS_HAT
  123. void joystick_set_hat(int8_t value) {
  124. joystick_state.hat = value;
  125. joystick_state.dirty = true;
  126. }
  127. #endif
  128. void joystick_init(void) {
  129. joystick_init_axes();
  130. }
  131. void joystick_task(void) {
  132. joystick_read_axes();
  133. }