forked from kofal.net/zmk
Feature: Full-Duplex Wired Split (#2766)
refactor(split): Refactor split code for extension Extract central/peripheral code to allow for plugging in alternate transports, instead of tying all split logic to BT. feat(split): Add full-duplex wired split support * Depends on full-duplex hardware UART for communication. * Supports all existing central commands/peripheral events, including sensors/inputs from peripherals. * Only one wired split peripheral supported (for now) * Relies on chosen `zmk,split-uart` referencing the UART device. docs: Add wired split config docs. Migrate split to its own dedicated config file, and add details on wired split config. Co-authored-by: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> fix: Properly override stack size on RP2040 Move the system work queue stack size override on RP2040 ouf of a `ZMK_BLE` conditional so it is properly applied generally for that SoC. --------- Co-authored-by: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com>
This commit is contained in:
@@ -30,7 +30,7 @@ On macOS the BLE battery reporting packets can cause the computer to wakeup from
|
||||
|
||||
### Peripheral Battery Monitoring
|
||||
|
||||
You can [configure ZMK to allow support for peripheral battery monitoring over BLE](system.md#split-keyboards) (e.g. when having a split keyboard with two independent and wirelessly connected sides).
|
||||
You can [configure ZMK to allow support for peripheral battery monitoring over BLE](split.md) (e.g. when having a split keyboard with two independent and wirelessly connected sides).
|
||||
If you want to report the battery levels of both sides of a split keyboard, you should have both `CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_PROXY` and `CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING` set to `y`.
|
||||
|
||||
:::note[Displaying both battery levels on your host]
|
||||
|
||||
90
docs/docs/config/split.md
Normal file
90
docs/docs/config/split.md
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Split Configuration
|
||||
sidebar_label: Split
|
||||
---
|
||||
|
||||
These are settings that control how split keyboards behave.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## Kconfig
|
||||
|
||||
Following [split keyboard](../features/split-keyboards.md) settings are defined in [zmk/app/src/split/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/split/Kconfig).
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| -------------------------------------------- | ---- | ------------------------------------------------------------------------ | ------- |
|
||||
| `CONFIG_ZMK_SPLIT` | bool | Enable split keyboard support | n |
|
||||
| `CONFIG_ZMK_SPLIT_ROLE_CENTRAL` | bool | `y` for central device, `n` for peripheral | n |
|
||||
| `CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS` | bool | Enable split keyboard support for passing indicator state to peripherals | n |
|
||||
|
||||
### Bluetooth Splits
|
||||
|
||||
Following bluetooth [split keyboard](../features/split-keyboards.md) settings are defined in [zmk/app/src/split/bluetooth/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/split/bluetooth/Kconfig).
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------------------------- | ---- | -------------------------------------------------------------------------- | ------------------------------------------ |
|
||||
| `CONFIG_ZMK_SPLIT_BLE` | bool | Use BLE to communicate between split keyboard halves | y |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS` | int | Number of peripherals that will connect to the central | 1 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING` | bool | Enable fetching split peripheral battery levels to the central side | n |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_PROXY` | bool | Enable central reporting of split battery levels to hosts | n |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_QUEUE_SIZE` | int | Max number of battery level events to queue when received from peripherals | `CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS` |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue when received from peripherals | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_STACK_SIZE` | int | Stack size of the BLE split central write thread | 512 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE` | int | Max number of behavior run events to queue to send to the peripheral(s) | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE` | int | Stack size of the BLE split peripheral notify thread | 756 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY` | int | Priority of the BLE split peripheral notify thread | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue to send to the central | 10 |
|
||||
|
||||
### Wired Splits
|
||||
|
||||
Hardware UARTs have a few different modes/approaches to sending and receiving data, with different levels of complexity and performance. Not all hardware nor drivers support all modes, so ZMK has code to support different interaction modes with the UART as needed. The default mode should be properly selected based on the platform's report support, but you can choose to override the mode if needed.
|
||||
|
||||
- Polling Mode - The least efficient mode, this requires the MCU to constantly poll the UART to see if more data has been received, taking time away from other processing. This is basic mode supported by all UART drivers.
|
||||
- Interrupt Mode - This mode allows the MCU to do other processing until the UART raises an interrupt to signal new data has been received. On platforms where this is combined with a FIFO, there is even less superfluous processing, and high speeds can be achieved while allowing other processing to continue. Examples:
|
||||
- RP2040
|
||||
- nRF52
|
||||
- Async (DMA) Mode - Similar to interrupt mode, data reception can occur without involving the MCU. Additionally, larger volumes can be copied directly into accessible memory without the use of the MCU, allowing even further efficiency/rates without tying up the MCU. Only some drivers support this mode (and the current Zephyr 3.5 version of the nRF52 UART has some bugs that prevent its use). Examples:
|
||||
- SAM0 (e.g. SAMD21)
|
||||
- STM32 (e.g. stm32f072)
|
||||
|
||||
Following wired [split keyboard](../features/split-keyboards.md) settings are defined in [zmk/app/src/split/wired/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/split/wired/Kconfig).
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| -------------------------------------------- | ---- | ----------------------------------------------------------------- | ------------------------------------------------------------- |
|
||||
| `CONFIG_ZMK_SPLIT_WIRED` | bool | Use wired connection to communicate between split keyboard halves | y (if no BLE split and devicetree is set appropriately) |
|
||||
| `CONFIG_ZMK_SPLIT_WIRED_UART_MODE_ASYNC` | bool | Async (DMA) mode | y if the driver supports it (excluding nRF52 with known bugs) |
|
||||
| `CONFIG_ZMK_SPLIT_WIRED_UART_MODE_INTERRUPT` | bool | Interrupt mode | y if the hardware supports it |
|
||||
| `CONFIG_ZMK_SPLIT_WIRED_UART_MODE_POLLING` | bool | Polling mode | y if neither other mode is supported |
|
||||
|
||||
#### Async (DMA) Mode
|
||||
|
||||
The following settings only apply when using wired split in async (DMA) mode:
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ----------------------------------------- | ---- | ----------------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_SPLIT_WIRED_ASYNC_RX_TIMEOUT` | int | RX Timeout (in microseconds) before reporting received data | 20 |
|
||||
|
||||
#### Polling Mode
|
||||
|
||||
The following settings only apply when using wired split in polling mode:
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------------ | ---- | ---------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_SPLIT_WIRED_POLLING_RX_PERIOD` | int | Number of ticks between calls to poll for split data | 10 |
|
||||
|
||||
## Devicetree
|
||||
|
||||
### Wired Split
|
||||
|
||||
Wired splits require a properly configured UART to function. If writing a shield, you may be able to use the standard UART already provided by the board, e.g. `&pro_micro_serial`. See [predefined nodes](../development/hardware-integration/pinctrl.mdx#predefined-nodes) for details on the UART node labels provided by various interconnects. If you are creating your own board, or using custom pins for the UART, see the documentation on [pin control](../development/hardware-integration/pinctrl.mdx#additional-examples) to configure the pins for your UART.
|
||||
|
||||
Once you have a properly configured UART device, it needs to be assigned in a new node with a compatible value of `"zmk,wired-split"`. For example:
|
||||
|
||||
```dts
|
||||
/ {
|
||||
wired_split {
|
||||
compatible = "zmk,wired-split";
|
||||
device = <&pro_micro_serial>;
|
||||
};
|
||||
};
|
||||
```
|
||||
@@ -115,27 +115,6 @@ Note that `CONFIG_BT_MAX_CONN` and `CONFIG_BT_MAX_PAIRED` should be set to the s
|
||||
| `CONFIG_ZMK_USB_LOGGING` | bool | Enable USB CDC ACM logging for debugging | n |
|
||||
| `CONFIG_ZMK_LOG_LEVEL` | int | Log level for ZMK debug messages | 4 |
|
||||
|
||||
### Split keyboards
|
||||
|
||||
Following [split keyboard](../features/split-keyboards.md) settings are defined in [zmk/app/src/split/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/split/Kconfig) (generic) and [zmk/app/src/split/bluetooth/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/split/bluetooth/Kconfig) (bluetooth).
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------------------------- | ---- | -------------------------------------------------------------------------- | ------------------------------------------ |
|
||||
| `CONFIG_ZMK_SPLIT` | bool | Enable split keyboard support | n |
|
||||
| `CONFIG_ZMK_SPLIT_ROLE_CENTRAL` | bool | `y` for central device, `n` for peripheral | |
|
||||
| `CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS` | bool | Enable split keyboard support for passing indicator state to peripherals | n |
|
||||
| `CONFIG_ZMK_SPLIT_BLE` | bool | Use BLE to communicate between split keyboard halves | y |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS` | int | Number of peripherals that will connect to the central | 1 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING` | bool | Enable fetching split peripheral battery levels to the central side | n |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_PROXY` | bool | Enable central reporting of split battery levels to hosts | n |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_QUEUE_SIZE` | int | Max number of battery level events to queue when received from peripherals | `CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS` |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue when received from peripherals | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_STACK_SIZE` | int | Stack size of the BLE split central write thread | 512 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE` | int | Max number of behavior run events to queue to send to the peripheral(s) | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE` | int | Stack size of the BLE split peripheral notify thread | 756 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY` | int | Priority of the BLE split peripheral notify thread | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue to send to the central | 10 |
|
||||
|
||||
## Snippets
|
||||
|
||||
:::danger
|
||||
|
||||
@@ -513,6 +513,30 @@ If all of your physical layouts use the same `kscan` node under the hood, you ca
|
||||
|
||||
:::
|
||||
|
||||
### Wired Split
|
||||
|
||||
<SplitTabs>
|
||||
<TabItem value="unibody">This is only required for wired split keyboards.</TabItem>
|
||||
<TabItem value="split">
|
||||
|
||||
If testing the experimental [wired split](../../features/split-keyboards.md) support, you should assign a [predefined](./pinctrl.mdx#predefined-nodes) or [pinctrl configured](./pinctrl.mdx) UART to the `device` property of a new node with `compatible` value of `"zmk,wired-split"`:
|
||||
|
||||
```dts
|
||||
/ {
|
||||
wired_split {
|
||||
compatible = "zmk,wired-split";
|
||||
device = <&pro_micro_serial>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
See the [wired split](../../config/split.md#wired-split) configuration for more details.
|
||||
|
||||
For wireless split keyboards, this step should be skipped, especially since the UART pins on your controller might already be in use for other functionality.
|
||||
|
||||
</TabItem>
|
||||
</SplitTabs>
|
||||
|
||||
## Default Keymap
|
||||
|
||||
Each keyboard should provide a default keymap to be used when building the firmware, which can be overridden and customized by user configs.
|
||||
|
||||
@@ -55,7 +55,7 @@ Please see the [explainer on boards & shields](development/hardware-integration/
|
||||
|
||||
### Does ZMK support wired split?
|
||||
|
||||
Currently, ZMK only supports wireless split, but wired split is possible and we welcome contributions!
|
||||
Currently, ZMK only supports wireless [split keyboards](features/split-keyboards.md). Experimental wired split support for some specific hardware designs is available for advanced users to test.
|
||||
|
||||
### How is the latency?
|
||||
|
||||
|
||||
@@ -6,10 +6,17 @@ 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]
|
||||
Currently ZMK only supports split keyboards that communicate with each other wirelessly over BLE.
|
||||
As such, only controllers that support BLE can be used with ZMK split keyboards.
|
||||
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.
|
||||
|
||||
Supporting split communication over wired protocols is planned, allowing for ZMK split keyboards using non-wireless controllers.
|
||||
:::
|
||||
|
||||
## Central and Peripheral Roles
|
||||
@@ -32,7 +39,7 @@ You can refer to the [power profiler](/power-profiler) to see battery life estim
|
||||
|
||||
The [new shield guide](../development/hardware-integration/new-shield.mdx) details how to define a split keyboard shield with two parts, enabling the split feature and setting up the necessary roles for each part.
|
||||
|
||||
Also see the reference section on [split keyboards configuration](../config/system.md#split-keyboards) where the relevant symbols include `CONFIG_ZMK_SPLIT` that enables the feature, `CONFIG_ZMK_SPLIT_ROLE_CENTRAL` which sets the central role and `CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS` that sets the number of peripherals.
|
||||
Also see the reference section on [split keyboards configuration](../config/split.md) where the relevant symbols include `CONFIG_ZMK_SPLIT` that enables the feature, `CONFIG_ZMK_SPLIT_ROLE_CENTRAL` which sets the central role and `CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS` that sets the number of peripherals.
|
||||
|
||||
### Latency Considerations
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ module.exports = {
|
||||
"config/layout",
|
||||
"config/kscan",
|
||||
"config/power",
|
||||
"config/split",
|
||||
"config/system",
|
||||
"config/studio",
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user