process_joystick.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #include "joystick.h"
  2. #include "process_joystick.h"
  3. #ifdef __AVR__
  4. # include "analog.h"
  5. #endif
  6. #include <string.h>
  7. #include <math.h>
  8. bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record);
  9. bool process_joystick(uint16_t keycode, keyrecord_t *record) {
  10. if (process_joystick_buttons(keycode, record) && (joystick_status.status & JS_UPDATED) > 0) {
  11. send_joystick_packet(&joystick_status);
  12. joystick_status.status &= ~JS_UPDATED;
  13. }
  14. return true;
  15. }
  16. void joystick_task(void) {
  17. if (process_joystick_analogread() && (joystick_status.status & JS_UPDATED)) {
  18. send_joystick_packet(&joystick_status);
  19. joystick_status.status &= ~JS_UPDATED;
  20. }
  21. }
  22. bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record) {
  23. if (keycode < JS_BUTTON0 || keycode > JS_BUTTON_MAX) {
  24. return true;
  25. } else {
  26. if (record->event.pressed) {
  27. joystick_status.buttons[(keycode - JS_BUTTON0) / 8] |= 1 << (keycode % 8);
  28. } else {
  29. joystick_status.buttons[(keycode - JS_BUTTON0) / 8] &= ~(1 << (keycode % 8));
  30. }
  31. joystick_status.status |= JS_UPDATED;
  32. }
  33. return true;
  34. }
  35. uint8_t savePinState(uint8_t pin) {
  36. #ifdef __AVR__
  37. uint8_t pinNumber = pin & 0xF;
  38. return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1);
  39. #else
  40. return 0;
  41. #endif
  42. }
  43. void restorePinState(uint8_t pin, uint8_t restoreState) {
  44. #ifdef __AVR__
  45. uint8_t pinNumber = pin & 0xF;
  46. PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber);
  47. DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber);
  48. #else
  49. return;
  50. #endif
  51. }
  52. __attribute__((weak)) bool process_joystick_analogread() { return process_joystick_analogread_quantum(); }
  53. bool process_joystick_analogread_quantum() {
  54. #if JOYSTICK_AXES_COUNT > 0
  55. for (int axis_index = 0; axis_index < JOYSTICK_AXES_COUNT; ++axis_index) {
  56. if (joystick_axes[axis_index].input_pin == JS_VIRTUAL_AXIS) {
  57. continue;
  58. }
  59. // save previous input pin status as well
  60. uint8_t inputSavedState = savePinState(joystick_axes[axis_index].input_pin);
  61. // disable pull-up resistor
  62. writePinLow(joystick_axes[axis_index].input_pin);
  63. // if pin was a pull-up input, we need to uncharge it by turning it low
  64. // before making it a low input
  65. setPinOutput(joystick_axes[axis_index].input_pin);
  66. wait_us(10);
  67. // save and apply output pin status
  68. uint8_t outputSavedState = 0;
  69. if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) {
  70. // save previous output pin status
  71. outputSavedState = savePinState(joystick_axes[axis_index].output_pin);
  72. setPinOutput(joystick_axes[axis_index].output_pin);
  73. writePinHigh(joystick_axes[axis_index].output_pin);
  74. }
  75. uint8_t groundSavedState = 0;
  76. if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) {
  77. // save previous output pin status
  78. groundSavedState = savePinState(joystick_axes[axis_index].ground_pin);
  79. setPinOutput(joystick_axes[axis_index].ground_pin);
  80. writePinLow(joystick_axes[axis_index].ground_pin);
  81. }
  82. wait_us(10);
  83. setPinInput(joystick_axes[axis_index].input_pin);
  84. wait_us(10);
  85. # ifdef __AVR__
  86. int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin);
  87. # else
  88. // default to resting position
  89. int16_t axis_val = joystick_axes[axis_index].mid_digit;
  90. # endif
  91. // test the converted value against the lower range
  92. uint16_t ref = joystick_axes[axis_index].mid_digit;
  93. uint16_t range = joystick_axes[axis_index].min_digit;
  94. int16_t ranged_val = -127 * fminf(1.f, (axis_val - (float)(ref)) / (range - (float)ref));
  95. if (ranged_val > 0) {
  96. // the value is in the higher range
  97. range = joystick_axes[axis_index].max_digit;
  98. ranged_val = 127 * fminf(1.f, (axis_val - (float)(ref)) / (range - (float)ref));
  99. }
  100. if (ranged_val != joystick_status.axes[axis_index]) {
  101. joystick_status.axes[axis_index] = ranged_val;
  102. joystick_status.status |= JS_UPDATED;
  103. }
  104. // restore output, ground and input status
  105. if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) {
  106. restorePinState(joystick_axes[axis_index].output_pin, outputSavedState);
  107. }
  108. if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) {
  109. restorePinState(joystick_axes[axis_index].ground_pin, groundSavedState);
  110. }
  111. restorePinState(joystick_axes[axis_index].input_pin, inputSavedState);
  112. }
  113. #endif
  114. return true;
  115. }