split_util.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include "split_util.h"
  2. #include "matrix.h"
  3. #include "keyboard.h"
  4. #include "config.h"
  5. #include "timer.h"
  6. #include "transport.h"
  7. #include "quantum.h"
  8. #include "wait.h"
  9. #ifdef PROTOCOL_LUFA
  10. # include <LUFA/Drivers/USB/USB.h>
  11. #endif
  12. #ifdef PROTOCOL_VUSB
  13. # include <usbdrv/usbdrv.h>
  14. #endif
  15. #ifdef EE_HANDS
  16. # include "eeconfig.h"
  17. #endif
  18. #if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT)
  19. # include "rgblight.h"
  20. #endif
  21. #ifndef SPLIT_USB_TIMEOUT
  22. # define SPLIT_USB_TIMEOUT 2000
  23. #endif
  24. #ifndef SPLIT_USB_TIMEOUT_POLL
  25. # define SPLIT_USB_TIMEOUT_POLL 10
  26. #endif
  27. #ifdef PROTOCOL_CHIBIOS
  28. # define SPLIT_USB_DETECT // Force this on for now
  29. #endif
  30. volatile bool isLeftHand = true;
  31. #if defined(SPLIT_USB_DETECT)
  32. # if defined(PROTOCOL_LUFA)
  33. static inline bool usbHasActiveConnection(void) { return USB_Device_IsAddressSet(); }
  34. static inline void usbDisable(void) {
  35. USB_Disable();
  36. USB_DeviceState = DEVICE_STATE_Unattached;
  37. }
  38. # elif defined(PROTOCOL_CHIBIOS)
  39. static inline bool usbHasActiveConnection(void) { return usbGetDriverStateI(&USBD1) == USB_ACTIVE; }
  40. static inline void usbDisable(void) { usbStop(&USBD1); }
  41. # elif defined(PROTOCOL_VUSB)
  42. static inline bool usbHasActiveConnection(void) {
  43. usbPoll();
  44. return usbConfiguration;
  45. }
  46. static inline void usbDisable(void) { usbDeviceDisconnect(); }
  47. # else
  48. static inline bool usbHasActiveConnection(void) { return true; }
  49. static inline void usbDisable(void) {}
  50. # endif
  51. bool usbIsActive(void) {
  52. for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {
  53. // This will return true if a USB connection has been established
  54. if (usbHasActiveConnection()) {
  55. return true;
  56. }
  57. wait_ms(SPLIT_USB_TIMEOUT_POLL);
  58. }
  59. // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
  60. usbDisable();
  61. return false;
  62. }
  63. #elif defined(PROTOCOL_LUFA) && defined(OTGPADE)
  64. static inline bool usbIsActive(void) {
  65. USB_OTGPAD_On(); // enables VBUS pad
  66. wait_us(5);
  67. return USB_VBUS_GetStatus(); // checks state of VBUS
  68. }
  69. #else
  70. static inline bool usbIsActive(void) { return true; }
  71. #endif
  72. #ifdef SPLIT_HAND_MATRIX_GRID
  73. void matrix_io_delay(void);
  74. static uint8_t peek_matrix_intersection(pin_t out_pin, pin_t in_pin) {
  75. setPinInputHigh(in_pin);
  76. setPinOutput(out_pin);
  77. writePinLow(out_pin);
  78. // It's almost unnecessary, but wait until it's down to low, just in case.
  79. wait_us(1);
  80. uint8_t pin_state = readPin(in_pin);
  81. // Set out_pin to a setting that is less susceptible to noise.
  82. setPinInputHigh(out_pin);
  83. matrix_io_delay(); // Wait for the pull-up to go HIGH.
  84. return pin_state;
  85. }
  86. #endif
  87. __attribute__((weak)) bool is_keyboard_left(void) {
  88. #if defined(SPLIT_HAND_PIN)
  89. // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
  90. setPinInput(SPLIT_HAND_PIN);
  91. return readPin(SPLIT_HAND_PIN);
  92. #elif defined(SPLIT_HAND_MATRIX_GRID)
  93. # ifdef SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT
  94. return peek_matrix_intersection(SPLIT_HAND_MATRIX_GRID);
  95. # else
  96. return !peek_matrix_intersection(SPLIT_HAND_MATRIX_GRID);
  97. # endif
  98. #elif defined(EE_HANDS)
  99. return eeconfig_read_handedness();
  100. #elif defined(MASTER_RIGHT)
  101. return !is_keyboard_master();
  102. #endif
  103. return is_keyboard_master();
  104. }
  105. __attribute__((weak)) bool is_keyboard_master(void) {
  106. static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN;
  107. // only check once, as this is called often
  108. if (usbstate == UNKNOWN) {
  109. usbstate = usbIsActive() ? MASTER : SLAVE;
  110. }
  111. return (usbstate == MASTER);
  112. }
  113. // this code runs before the keyboard is fully initialized
  114. void split_pre_init(void) {
  115. isLeftHand = is_keyboard_left();
  116. #if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT)
  117. uint8_t num_rgb_leds_split[2] = RGBLED_SPLIT;
  118. if (isLeftHand) {
  119. rgblight_set_clipping_range(0, num_rgb_leds_split[0]);
  120. } else {
  121. rgblight_set_clipping_range(num_rgb_leds_split[0], num_rgb_leds_split[1]);
  122. }
  123. #endif
  124. if (is_keyboard_master()) {
  125. #if defined(USE_I2C) && defined(SSD1306OLED)
  126. matrix_master_OLED_init();
  127. #endif
  128. transport_master_init();
  129. }
  130. }
  131. // this code runs after the keyboard is fully initialized
  132. // - avoids race condition during matrix_init_quantum where slave can start
  133. // receiving before the init process has completed
  134. void split_post_init(void) {
  135. if (!is_keyboard_master()) {
  136. transport_slave_init();
  137. }
  138. }