split_util.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #include <avr/io.h>
  2. #include <avr/wdt.h>
  3. #include <avr/power.h>
  4. #include <avr/interrupt.h>
  5. #include <util/delay.h>
  6. #include <avr/eeprom.h>
  7. #include "split_util.h"
  8. #include "matrix.h"
  9. #include "keyboard.h"
  10. #include "wait.h"
  11. #ifdef USE_MATRIX_I2C
  12. # include "i2c.h"
  13. #else
  14. # include "split_scomm.h"
  15. #endif
  16. #ifdef EE_HANDS
  17. # include "eeconfig.h"
  18. #endif
  19. #ifndef SPLIT_USB_TIMEOUT
  20. #define SPLIT_USB_TIMEOUT 2500
  21. #endif
  22. volatile bool isLeftHand = true;
  23. bool waitForUsb(void) {
  24. for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / 100); i++) {
  25. // This will return true of a USB connection has been established
  26. if (UDADDR & _BV(ADDEN)) {
  27. return true;
  28. }
  29. wait_ms(100);
  30. }
  31. // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
  32. (USBCON &= ~(_BV(USBE) | _BV(OTGPADE)));
  33. return false;
  34. }
  35. __attribute__((weak)) bool is_keyboard_left(void) {
  36. #if defined(SPLIT_HAND_PIN)
  37. // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
  38. setPinInput(SPLIT_HAND_PIN);
  39. return readPin(SPLIT_HAND_PIN);
  40. #elif defined(EE_HANDS)
  41. return eeconfig_read_handedness();
  42. #elif defined(MASTER_RIGHT)
  43. return !has_usb();
  44. #endif
  45. return has_usb();
  46. }
  47. __attribute__((weak)) bool has_usb(void) {
  48. static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN;
  49. // only check once, as this is called often
  50. if (usbstate == UNKNOWN) {
  51. #if defined(SPLIT_USB_DETECT)
  52. usbstate = waitForUsb() ? MASTER : SLAVE;
  53. #elif defined(__AVR__)
  54. USBCON |= (1 << OTGPADE); // enables VBUS pad
  55. wait_us(5);
  56. usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE; // checks state of VBUS
  57. #else
  58. usbstate = MASTER;
  59. #endif
  60. }
  61. return (usbstate == MASTER);
  62. }
  63. static void keyboard_master_setup(void) {
  64. #ifdef USE_MATRIX_I2C
  65. i2c_master_init();
  66. #else
  67. serial_master_init();
  68. #endif
  69. }
  70. static void keyboard_slave_setup(void) {
  71. #ifdef USE_MATRIX_I2C
  72. i2c_slave_init(SLAVE_I2C_ADDRESS);
  73. #else
  74. serial_slave_init();
  75. #endif
  76. }
  77. void split_keyboard_setup(void) {
  78. isLeftHand = is_keyboard_left();
  79. if (has_usb()) {
  80. keyboard_master_setup();
  81. } else {
  82. keyboard_slave_setup();
  83. }
  84. sei();
  85. }