joystick.c 4.0 KB

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