joystick.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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 "analog.h"
  18. #include "wait.h"
  19. joystick_t joystick_state = {
  20. .buttons = {0},
  21. .axes =
  22. {
  23. #if JOYSTICK_AXIS_COUNT > 0
  24. 0
  25. #endif
  26. },
  27. .dirty = false,
  28. };
  29. // array defining the reading of analog values for each axis
  30. __attribute__((weak)) joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = {};
  31. __attribute__((weak)) void joystick_task(void) {
  32. joystick_read_axes();
  33. }
  34. void joystick_flush(void) {
  35. if (joystick_state.dirty) {
  36. host_joystick_send(&joystick_state);
  37. joystick_state.dirty = false;
  38. }
  39. }
  40. void register_joystick_button(uint8_t button) {
  41. if (button >= JOYSTICK_BUTTON_COUNT) return;
  42. joystick_state.buttons[button / 8] |= 1 << (button % 8);
  43. joystick_state.dirty = true;
  44. joystick_flush();
  45. }
  46. void unregister_joystick_button(uint8_t button) {
  47. if (button >= JOYSTICK_BUTTON_COUNT) return;
  48. joystick_state.buttons[button / 8] &= ~(1 << (button % 8));
  49. joystick_state.dirty = true;
  50. joystick_flush();
  51. }
  52. int16_t joystick_read_axis(uint8_t axis) {
  53. if (axis >= JOYSTICK_AXIS_COUNT) return 0;
  54. // disable pull-up resistor
  55. writePinLow(joystick_axes[axis].input_pin);
  56. // if pin was a pull-up input, we need to uncharge it by turning it low
  57. // before making it a low input
  58. setPinOutput(joystick_axes[axis].input_pin);
  59. wait_us(10);
  60. if (joystick_axes[axis].output_pin != JS_VIRTUAL_AXIS) {
  61. setPinOutput(joystick_axes[axis].output_pin);
  62. writePinHigh(joystick_axes[axis].output_pin);
  63. }
  64. if (joystick_axes[axis].ground_pin != JS_VIRTUAL_AXIS) {
  65. setPinOutput(joystick_axes[axis].ground_pin);
  66. writePinLow(joystick_axes[axis].ground_pin);
  67. }
  68. wait_us(10);
  69. setPinInput(joystick_axes[axis].input_pin);
  70. wait_us(10);
  71. #if defined(ANALOG_JOYSTICK_ENABLE) && (defined(__AVR__) || defined(PROTOCOL_CHIBIOS))
  72. int16_t axis_val = analogReadPin(joystick_axes[axis].input_pin);
  73. #else
  74. // default to resting position
  75. int16_t axis_val = joystick_axes[axis].mid_digit;
  76. #endif
  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_read_axes() {
  92. #if JOYSTICK_AXIS_COUNT > 0
  93. for (int i = 0; i < JOYSTICK_AXIS_COUNT; ++i) {
  94. if (joystick_axes[i].input_pin == JS_VIRTUAL_AXIS) {
  95. continue;
  96. }
  97. joystick_set_axis(i, joystick_read_axis(i));
  98. }
  99. joystick_flush();
  100. #endif
  101. }
  102. void joystick_set_axis(uint8_t axis, int16_t value) {
  103. if (axis >= JOYSTICK_AXIS_COUNT) return;
  104. if (value != joystick_state.axes[axis]) {
  105. joystick_state.axes[axis] = value;
  106. joystick_state.dirty = true;
  107. }
  108. }