split_util.c 2.4 KB

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