浏览代码

ARM split - detect USB to select master/slave (#6424)

* Initial split refactor to allow usb master detection

* Add split USB detect docs

* Add SPLIT_USB_DETECT demo mode limitation

* fix rebase issues

* clang-format
Joel Challis 5 年之前
父节点
当前提交
76378d74f5

+ 8 - 0
docs/config_options.md

@@ -267,6 +267,14 @@ There are a few different ways to set handedness for split keyboards (listed in
     * 4: about 26kbps
     * 5: about 20kbps
 
+* `#define SPLIT_USB_DETECT`
+  * Detect (with timeout) USB connection when delegating master/slave
+  * Default behavior for ARM
+  * Required for AVR Teensy
+
+* `#define SPLIT_USB_TIMEOUT 2500`
+  * Maximum timeout when detecting master/slave when using `SPLIT_USB_DETECT`
+
 # The `rules.mk` File
 
 This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features.

+ 12 - 0
docs/feature_split_keyboard.md

@@ -190,6 +190,18 @@ This sets how many LEDs are directly connected to each controller.  The first nu
 ?> This setting implies that `RGBLIGHT_SPLIT` is enabled, and will forcibly enable it, if it's not.
 
 
+```c
+#define SPLIT_USB_DETECT
+```
+This option changes the startup behavior to detect an active USB connection when delegating master/slave. If this operation times out, then the half is assume to be a slave. This is the default behavior for ARM, and required for AVR Teensy boards (due to hardware limitations).
+
+?> This setting will stop the ability to demo using battery packs.
+
+```c
+#define SPLIT_USB_TIMEOUT 2500
+```
+This sets the maximum timeout when detecting master/slave when using `SPLIT_USB_DETECT`.
+
 ## Additional Resources
 
 Nicinabox has a [very nice and detailed guide](https://github.com/nicinabox/lets-split-guide) for the Let's Split keyboard, that covers most everything you need to know, including troubleshooting information. 

+ 1 - 3
quantum/split_common/matrix.c

@@ -246,9 +246,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
 #endif
 
 void matrix_init(void) {
-    debug_enable = true;
-    debug_matrix = true;
-    debug_mouse  = true;
+    keyboard_split_setup();
 
     // Set pinout for right half if pinout for that half is defined
     if (!isLeftHand) {

+ 27 - 6
quantum/split_common/split_util.c

@@ -14,8 +14,27 @@
 #    include "rgblight.h"
 #endif
 
+#ifndef SPLIT_USB_TIMEOUT
+#    define SPLIT_USB_TIMEOUT 2500
+#endif
+
 volatile bool isLeftHand = true;
 
+bool waitForUsb(void) {
+    for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / 100); i++) {
+        // This will return true of a USB connection has been established
+#if defined(__AVR__)
+        if (UDADDR & _BV(ADDEN)) {
+#else
+        if (usbGetDriverStateI(&USBD1) == USB_ACTIVE) {
+#endif
+            return true;
+        }
+        wait_ms(100);
+    }
+    return false;
+}
+
 __attribute__((weak)) bool is_keyboard_left(void) {
 #if defined(SPLIT_HAND_PIN)
     // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
@@ -31,21 +50,23 @@ __attribute__((weak)) bool is_keyboard_left(void) {
 }
 
 __attribute__((weak)) bool is_keyboard_master(void) {
-#ifdef __AVR__
     static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN;
 
     // only check once, as this is called often
     if (usbstate == UNKNOWN) {
+#if defined(SPLIT_USB_DETECT) || defined(PROTOCOL_CHIBIOS)
+        usbstate = waitForUsb() ? MASTER : SLAVE;
+#elif defined(__AVR__)
         USBCON |= (1 << OTGPADE);  // enables VBUS pad
         wait_us(5);
 
         usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE;  // checks state of VBUS
+#else
+        usbstate = MASTER;
+#endif
     }
 
     return (usbstate == MASTER);
-#else
-    return true;
-#endif
 }
 
 static void keyboard_master_setup(void) {
@@ -59,8 +80,8 @@ static void keyboard_master_setup(void) {
 
 static void keyboard_slave_setup(void) { transport_slave_init(); }
 
-// this code runs before the usb and keyboard is initialized
-void matrix_setup(void) {
+// this code runs before the keyboard is fully initialized
+void keyboard_split_setup(void) {
     isLeftHand = is_keyboard_left();
 
 #if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT)

+ 1 - 0
quantum/split_common/split_util.h

@@ -8,3 +8,4 @@
 extern volatile bool isLeftHand;
 
 void matrix_master_OLED_init(void);
+void keyboard_split_setup(void);