process_joystick.c 4.5 KB

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