Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from
Oct 12, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/config_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,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.
Expand Down
12 changes: 12 additions & 0 deletions docs/feature_split_keyboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,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.
Expand Down
4 changes: 1 addition & 3 deletions quantum/split_common/matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
33 changes: 27 additions & 6 deletions quantum/split_common/split_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,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++) {
zvecr marked this conversation as resolved.
Show resolved Hide resolved
// 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
Expand All @@ -32,21 +51,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) {
Expand All @@ -60,8 +81,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)
Expand Down
1 change: 1 addition & 0 deletions quantum/split_common/split_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
extern volatile bool isLeftHand;

void matrix_master_OLED_init(void);
void keyboard_split_setup(void);