mirror of
https://github.com/zmkfirmware/zmk.git
synced 2026-03-20 04:55:20 -05:00
feat(split): Runtime selection of split transport (#2886)
feat(split): Runtime selection of split transport Allow building multiple split transports, and select an active one based on the transport availability. Wired split availability depends on additional `detect-gpios` which must be a GPIO pin that goes active when a wired connection is present. feat(split): Suspend/resume wired UART devices. To better support runtime split support, suspend/resume the UART as necessary to save power when not using the UART. docs(split): Document adjusting nRF52 UART interrupt priorities For wired split on nRF52, you may need to adjust the priority for UART interrupts lower, to ensure the interrupts used for timing sensitive BT operations can run when needed, so document this in our pinctrl docs. refactor(split): Restore use of aync UART on nRF52. With fixes for Zephyr UART driver, re-enable using async API on nRF52. fix(split): Minor wired split fixes. Various minor fixes for wired split to avoid spurious TX in half duplex, etc. fix: Unconditionally define HID payloads to avoid error. Don't conditionally define HID indicator payload, to avoid compilation errors. docs(split): Expand on details of split transports. Expand the split keyboard documentation with a more fleshed out section on the available split trasnports, and what is and isn't supported by each, including the runtime selection functionality. --------- Co-authored-by: Nicolas Munnich <98408764+nmunnich@users.noreply.github.com>
This commit is contained in:
@@ -358,6 +358,28 @@ In the pin control file:
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 22)>, // EXT1
|
||||
<NRF_PSEL(UART_RX, 0, 21)>; // EXT2
|
||||
};
|
||||
};
|
||||
|
||||
uart0_sleep: uart0_sleep {
|
||||
group1 {
|
||||
/* configure P0.1 as UART_TX and P0.2 as UART_RTS */
|
||||
psels = <NRF_PSEL(UART_TX, 0, 1)>, <NRF_PSEL(UART_RTS, 0, 2)>;
|
||||
low-power-enable;
|
||||
};
|
||||
group2 {
|
||||
/* configure P0.3 as UART_RX and P0.4 as UART_CTS */
|
||||
psels = <NRF_PSEL(UART_RX, 0, 3)>, <NRF_PSEL(UART_CTS, 0, 4)>;
|
||||
/* both P0.3 and P0.4 are configured with pull-up */
|
||||
bias-pull-up;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
@@ -368,10 +390,35 @@ In the main file:
|
||||
|
||||
&uart0 {
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-1 = <&uart0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
```
|
||||
|
||||
On designs using wired split on nRF52840, using asynchronous UART APIs with DMA will help ensure that the interrupts used to handle timing sensitive BT interactions can respond when needed.
|
||||
|
||||
This can be accomplished by overwriding the `compatible` property to `"nordic,nrf-uarte"`, e.g.:
|
||||
|
||||
```dts
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-1 = <&uart0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
```
|
||||
|
||||
In addition to this `compatible` override, a setting needs to be tweaked to ensure that the UART isn't selected for interrupt mode when async is prefered.
|
||||
|
||||
The following should be added to the board's/shield's `Kconfig.defconfig`:
|
||||
|
||||
```dts
|
||||
config UART_0_INTERRUPT_DRIVEN
|
||||
depends on !ZMK_SPLIT_WIRED_UART_MODE_ASYNC
|
||||
```
|
||||
|
||||
for the correct `UART_#` prefix matching the numbered UART being used.
|
||||
|
||||
#### UART rp2040
|
||||
|
||||
In the pin control file:
|
||||
|
||||
@@ -5,20 +5,6 @@ sidebar_label: Split Keyboards
|
||||
|
||||
ZMK supports setups where a keyboard is split into two or more physical parts (also called "sides" or "halves" when split in two), each with their own controller running ZMK. The parts communicate with each other to work as a single keyboard device.
|
||||
|
||||
:::note[Split communication protocols]
|
||||
ZMK supports split keyboards that communicate with each other wirelessly over BLE.
|
||||
|
||||
Full-duplex UART, wired split support is currently experimental, and is available for advanced/technical users to test.
|
||||
|
||||
Future single-wire, half-duplex UART support, which is planned, will allow using wired ZMK with designs like Corne, Sweep, etc. that use only a single GPIO pin for bidirectional communication between split sides.
|
||||
:::
|
||||
|
||||
:::warning[Hot Plugging Cables]
|
||||
|
||||
Many popular cables, in particular, TRRS/TRS cables, can cause irreparable damage to controllers if they are inserted or removed when power is already present on them. Whether or not you are using the wired split functionality or not, _never_ insert or remove such a cable when a controller is powered by USB _or_ battery.
|
||||
|
||||
:::
|
||||
|
||||
## Central and Peripheral Roles
|
||||
|
||||
In split keyboards running ZMK, one part is assigned the "central" role which receives key position and sensor events from the other parts that are called "peripherals."
|
||||
@@ -46,6 +32,40 @@ Also see the reference section on [split keyboards configuration](../config/spli
|
||||
Since peripherals communicate through centrals, the key and sensor events originating from them will naturally have a larger latency, especially with a wireless split communication protocol.
|
||||
For the currently used BLE-based transport, split communication increases the average latency by 3.75ms with a worst case increase of 7.5ms.
|
||||
|
||||
## Split Transports
|
||||
|
||||
ZMK supports two transports for connecting split parts: Bluetooth and full-duplex wired UART. Only one transport can be active at a time, so designs involving some portions connected via Bluetooth and others via full-duplex wired are _not_ supported.
|
||||
|
||||
:::warning[Hot Plugging Cables]
|
||||
|
||||
Many popular cables, in particular, TRRS/TRS cables, can cause irreparable damage to controllers if they are inserted or removed when power is already present on them. Whether or not you are using the wired split functionality or not, _never_ insert or remove such a cable when a controller is powered by USB _or_ battery.
|
||||
|
||||
:::
|
||||
|
||||
### Bluetooth
|
||||
|
||||
[Bluetooth](./bluetooth.md) is the most well tested and flexible transport available in ZMK. Using Bluetooth, a central can connect to multiple peripherals, enabling the use of a [dongle](../development/hardware-integration/dongle.mdx) to improve battery life, or allowing for multi-part split keyboards.
|
||||
|
||||
This transport will be enabled for designs that set `CONFIG_ZMK_SPLIT=y` and have `CONFIG_ZMK_BLE=y` set by a supported MCU/controller.
|
||||
|
||||
### Full-Duplex Wired (UART)
|
||||
|
||||
The full-duplex wired UART transport is a recent addition, and is intended for testing by early adopters. It allows for fully functional communication between one central and one peripheral. Unlike the Bluetooth transport, the central cannot currently have more than one peripheral connected via wired split.
|
||||
|
||||
This transport will be enabled for designs that set `CONFIG_ZMK_SPLIT=y` and have a node with `compatible = "zmk,wired-split";` present in their devicetree configuration.
|
||||
|
||||
:::note[Full Duplex vs Half Duplex]
|
||||
Full-duplex UART requires the use of two wires connecting the halves. Future half-duplex (single-wire) UART support, which is planned, will allow using wired ZMK with designs such as the Corne, Sweep, etc. that use only a single GPIO pin for bidirectional communication between split sides.
|
||||
|
||||
Until half-duplex support is completed, those particular designs will not work with the wired split transport, and can only be used with the Bluetooth transport.
|
||||
:::
|
||||
|
||||
### Runtime Switching
|
||||
|
||||
ZMK features highly experimental support for switching between the two available transports. This requires specially designed hardware, and attempting to use this feature on a keyboard not explicitly designed for it (e.g. Corne, Sofle) _WILL_ cause permanent damage.
|
||||
|
||||
Currently, there are no open source/reference designs that implement this functionality, and only experienced designers with extensive EE knowledge should attempt to implement a design with this functionality.
|
||||
|
||||
## Building and Flashing Firmware
|
||||
|
||||
ZMK split keyboards require building and flashing different firmware files for each split part.
|
||||
|
||||
Reference in New Issue
Block a user