aboutsummaryrefslogtreecommitdiffhomepage
path: root/docs
diff options
context:
space:
mode:
authorPeter Johanson <[email protected]>2024-08-14 11:45:11 -0600
committerPete Johanson <[email protected]>2024-09-05 12:22:08 -0600
commit3975d2fdafe0a71f87187402a10b8db02171475c (patch)
treef617e545ceef17bc5d5f5750b1e520e4e82c50d0 /docs
parent5176fbea6acb5255e9323641a1a5858f0cc46063 (diff)
downloadzmk-3975d2fdafe0a71f87187402a10b8db02171475c.tar.gz
zmk-3975d2fdafe0a71f87187402a10b8db02171475c.zip
feat: Add studio related documentation.
* Document setting up studio for a new keyboard definition. * Document how to enable ZMK Studio for a build, adding reserved layers, and controlling which behaviors are built into a studio firmware. * Document `&studio_unlock` behavior. * Document studio configuration options. Co-authored-by: Cem Aksoylar <[email protected]>
Diffstat (limited to 'docs')
-rw-r--r--docs/docs/config/studio.md41
-rw-r--r--docs/docs/development/hardware-integration/studio-setup.md140
-rw-r--r--docs/docs/development/studio-rpc-protocol.md10
-rw-r--r--docs/docs/features/studio.md111
-rw-r--r--docs/docs/keymaps/behaviors/index.mdx6
-rw-r--r--docs/docs/keymaps/behaviors/studio-unlock.md25
-rw-r--r--docs/sidebars.js4
7 files changed, 332 insertions, 5 deletions
diff --git a/docs/docs/config/studio.md b/docs/docs/config/studio.md
new file mode 100644
index 0000000000..ddfb25df21
--- /dev/null
+++ b/docs/docs/config/studio.md
@@ -0,0 +1,41 @@
+---
+title: ZMK Studio Configuration
+sidebar_label: ZMK Studio
+---
+
+:::warning[Alpha Feature]
+
+ZMK Studio is still in active development and the below information is for development purposes only. For up to date information, join the [ZMK Discord](https://zmk.dev/community/discord/invite) server and discuss in `#studio-development`.
+
+:::
+
+The following settings affect the ZMK Studio portions of ZMK. See the [ZMK Studio feature](../features/studio.md) for more information on enabling and building with ZMK Studio enabled.
+
+See [Configuration Overview](index.md) for instructions on how to change these settings.
+
+## Kconfig
+
+Definition file: [zmk/app/src/studio/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/studio/Kconfig)
+
+### Keymaps
+
+| Config | Type | Description | Default |
+| -------------------------------------- | ---- | --------------------------------------- | ------- |
+| `CONFIG_ZMK_KEYMAP_LAYER_NAME_MAX_LEN` | int | Max allowable keymap layer display name | 20 |
+
+### Locking
+
+| Config | Type | Description | Default |
+| ----------------------------------------- | ---- | ----------------------------------------------------------------------------------- | ------- |
+| `CONFIG_ZMK_STUDIO_LOCKING` | bool | Enable/disable locking for ZMK Studio | y |
+| `CONFIG_ZMK_STUDIO_LOCK_IDLE_TIMEOUT_SEC` | int | Seconds of inactivity in ZMK Studio before automatically locking | 500 |
+| `CONFIG_ZMK_STUDIO_LOCK_ON_DISCONNECT` | bool | Whether to automatically lock again whenever ZMK Studio disconnects from the device | y |
+
+### Transport/Protocol Details
+
+| Config | Type | Description | Default |
+| ---------------------------------------------- | ---- | ----------------------------------------------------------------------------- | ------- |
+| `CONFIG_ZMK_STUDIO_TRANSPORT_BLE_PREF_LATENCY` | int | Lower latency to request while ZMK Studio is active to improve responsiveness | 10 |
+| `CONFIG_ZMK_STUDIO_RPC_THREAD_STACK_SIZE` | int | Stack size for the dedicated RPC thread | 1800 |
+| `CONFIG_ZMK_STUDIO_RPC_RX_BUF_SIZE` | int | Number of bytes available for buffering incoming messages | 30 |
+| `CONFIG_ZMK_STUDIO_RPC_TX_BUF_SIZE` | int | Number of bytes available for buffering outgoing messages | 64 |
diff --git a/docs/docs/development/hardware-integration/studio-setup.md b/docs/docs/development/hardware-integration/studio-setup.md
new file mode 100644
index 0000000000..d00f7de21b
--- /dev/null
+++ b/docs/docs/development/hardware-integration/studio-setup.md
@@ -0,0 +1,140 @@
+---
+title: ZMK Studio Setup
+---
+
+:::warning[Alpha Feature]
+
+ZMK Studio support is in alpha. Although best efforts are being made, backwards compatibility during active development is not guaranteed.
+
+:::
+
+This guide will walk you through enabling ZMK Studio support for a keyboard.
+
+The main additional pieces needed for ZMK Studio support involve additional metadata needed in order
+to properly to display the physical layouts available for the particular keyboard.
+
+# Physical Layout Positions
+
+Physical layouts are described as part of the [new shield guide](./new-shield.mdx#physical-layouts) with the exception of the `keys` property that is required for ZMK Studio support. This is used to describe the physical attributes of each key position present in that layout and its items are listed in the same order as keymap bindings, matrix transforms, etc. The properties available are:
+
+| Property | Type | Description | Unit |
+| ---------- | -------- | ------------------------------------ | ------------------------------------------------------- |
+| Width | int (>0) | Key(cap) width | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
+| Height | int (>0) | Key(cap) height | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
+| X | uint | Key X position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
+| Y | uint | Key Y position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
+| Rotation | int | Key rotation (positive => clockwise) | [centi-](https://en.wikipedia.org/wiki/Centi-)degree |
+| Rotation X | int | Rotation origin X position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
+| Rotation Y | int | Rotation origin Y position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
+
+:::note
+You can specify negative values in devicetree using parentheses around it, e.g. `(-3000)` for a 30 degree counterclockwise rotation.
+:::
+
+## Header Include
+
+To pull in the necessary definition for creating physical layouts, a new include should be added to the top of the devicetree file:
+
+```
+#include <physical_layouts.dtsi>
+```
+
+## Example
+
+Here is an example physical layout for a 2x2 macropad:
+
+```dts
+ macropad_physical_layout: macropad_physical_layout {
+ compatible = "zmk,physical-layout";
+ display-name = "Macro Pad";
+
+ keys // w h x y rot rx ry
+ = <&key_physical_attrs 100 100 0 0 0 0 0>
+ , <&key_physical_attrs 100 100 100 0 0 0 0>
+ , <&key_physical_attrs 100 100 0 100 0 0 0>
+ , <&key_physical_attrs 100 100 100 100 0 0 0>
+ ;
+ };
+```
+
+# Position Map
+
+When switching between layouts with ZMK Studio, the keymap of the previously selected layout is used to populate the keymap in the new layout. To determine which keymap entry maps to which entry in the new layout, keys between the two layouts that share the exact same physical attributes are matched.
+
+However, keys between layouts might not be in exactly the same positions, in which case a position map can be used. The position map includes a sequence for every relevant layout, and the corresponding entries in `positions` property will be used to determine the mapping between layouts. By default, the physical attribute matching behavior will be used as a fallback for positions not specified in the map, but the `complete` property can be added to the map to specify that no matching fallback should occur.
+
+:::info
+
+Key positions in the maps are numbered like the keys in your keymap, starting at 0. So the first position in the layout is position `0`, the next key position is `1`, etc.
+
+:::
+
+## Examples
+
+### Basic Map
+
+For example, the following position map correctly maps the 5-column and 6-column Corne keymap layouts.
+
+```dts
+ foostan_corne_position_map {
+ compatible = "zmk,physical-layout-position-map";
+
+ complete;
+
+ twelve {
+ physical-layout = <&foostan_corne_6col_layout>;
+ positions
+ = < 1 2 3 4 5 6 7 8 9 10>
+ , <13 14 15 16 17 18 19 20 21 22>
+ , <25 26 27 28 29 30 31 32 33 34>
+ , < 36 37 38 39 40 41 >;
+ };
+
+ ten {
+ physical-layout = <&foostan_corne_5col_layout>;
+ positions
+ = < 0 1 2 3 4 5 6 7 8 9>
+ , <10 11 12 13 14 15 16 17 18 19>
+ , <20 21 22 23 24 25 26 27 28 29>
+ , < 30 31 32 33 34 35 >;
+ };
+ };
+```
+
+The first entries in the two mappings have values `1` and `0` respectively, which means that position `1` in the 6-column layout will map to position `0` in the 5-column layout, the second entries show that position `2` in the 6-column layout corresponds to position `1` in the 5-column layout, etc.
+
+### Full Preserving Map
+
+The above basic example has one major downside. Because the keys on the outer columns of the 6-column layout aren't mapped into any locations in the 5-column layout, when a user switches to the 5-column layout and then back to the 6-column layout, the bindings for those outer columns will have been lost/dropped at the first step.
+
+In order to preserve those bindings that are in "missing" keys in other layouts, we can include those locations in the map, but map them "off the end" of the smaller layout key positions.
+
+Here is a fixed up Corne mapping:
+
+```dts
+ foostan_corne_position_map {
+ compatible = "zmk,physical-layout-position-map";
+
+ complete;
+
+ twelve {
+ physical-layout = <&foostan_corne_6col_layout>;
+ positions
+ = < 0 1 2 3 4 5 6 7 8 9 10 11>
+ , <12 13 14 15 16 17 18 19 20 21 22 23>
+ , <24 25 26 27 28 29 30 31 32 33 34 35>
+ , < 36 37 38 39 40 41 >;
+ };
+
+ ten {
+ physical-layout = <&foostan_corne_5col_layout>;
+ positions
+ = <36 0 1 2 3 4 5 6 7 8 9 37>
+ , <38 10 11 12 13 14 15 16 17 18 19 39>
+ , <40 20 21 22 23 24 25 26 27 28 29 41>
+ , < 30 31 32 33 34 35 >;
+ };
+ };
+```
+
+Notice how the outer column positions in the 6-column layout are mapped to positions 36, 37, etc. in the 5-column layout. The 5-column layout only uses key positions up to 35, so those bindings in the outer columns will get migrated into the "extra space" that is ignored by the smaller layout, preserved to get mapped back in place when the user switches back.
diff --git a/docs/docs/development/studio-rpc-protocol.md b/docs/docs/development/studio-rpc-protocol.md
index da737a131d..5cfafbba72 100644
--- a/docs/docs/development/studio-rpc-protocol.md
+++ b/docs/docs/development/studio-rpc-protocol.md
@@ -1,5 +1,5 @@
---
-title: Studio RPC Protocol
+title: ZMK Studio RPC Protocol
---
:::warning[Alpha Feature]
@@ -20,13 +20,13 @@ The protocol consists of [protocol buffer](https://protobuf.dev/programming-guid
## Protobuf Messages
-The messages for ZMK Studio are defined in a dedicated [zmk-studio-messages](https://github.com/zmkfirmware/zmk-studio-messages) repository. Fundamentally, the [`Request`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L11) message is used to send any requests from the Studio client to the ZMK device, and the [`Response`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L21) messages are sent from the ZMK device to the Studio client.
+The messages for ZMK Studio are defined in a dedicated [zmk-studio-messages](https://github.com/zmkfirmware/zmk-studio-messages) repository. Fundamentally, the [`Request`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L11) message is used to send any requests from the ZMK Studio client to the ZMK device, and the [`Response`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L21) messages are sent from the ZMK device to the Studio client.
-Responses can either be [`RequestResponses`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L28) that are sent in response to an incoming `Request` or a [`Notification`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L38) which is sent at any point from the ZMK device to the Studio client to inform the client about state changes on the device, e.g. that the device is unlocked.
+Responses can either be [`RequestResponses`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L28) that are sent in response to an incoming `Request` or a [`Notification`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L38) which is sent at any point from the ZMK device to the ZMK Studio client to inform the client about state changes on the device, e.g. that the device is unlocked.
## Message Framing
-Studio uses a simple framing protocol to easily identify the start and end of a given message, with basic escaping to allow for unrestricted content.
+ZMK Studio uses a simple framing protocol to easily identify the start and end of a given message, with basic escaping to allow for unrestricted content.
The following special bytes are used for the framing protocol:
@@ -136,7 +136,7 @@ Two transports are available right now, over USB or Bluetooth connections.
### USB (Serial)
-The USB transport is actually a basic serial/UART transport, that happens to use the CDC/ACM USB class for a serial connection. Framed messages are sent between Studio client and ZMK device using simple UART transmission.
+The USB transport is actually a basic serial/UART transport, that happens to use the CDC/ACM USB class for a serial connection. Framed messages are sent between ZMK Studio client and ZMK device using simple UART transmission.
### Bluetooth (GATT)
diff --git a/docs/docs/features/studio.md b/docs/docs/features/studio.md
new file mode 100644
index 0000000000..f8d4059b95
--- /dev/null
+++ b/docs/docs/features/studio.md
@@ -0,0 +1,111 @@
+---
+title: ZMK Studio
+---
+
+:::warning[Alpha Feature]
+
+ZMK Studio support is in alpha. Although best efforts are being made, keeping compatibility during active development is not guaranteed.
+
+:::
+
+ZMK Studio provides runtime update functionality to ZMK powered devices, allowing users to change their keymap layers without flashing new firmware to their keyboards. Studio is still under active development, and is not yet ready for casual end user use.
+
+## Building
+
+Building for ZMK Studio involves two main additional items.
+
+- Build with the `studio-rpc-usb-uart` snippet to enable the endpoint used for ZMK Studio communication over USB.
+- Enable the `ZMK_STUDIO` Kconfig setting.
+
+### GitHub Actions
+
+First add a `studio-rpc-usb-uart` to the `snippet` property of your build configuration. For a split keyboard, you should do this _only_ for your central/left side, e.g.:
+
+```
+---
+include:
+ - board: nice_nano_v2
+ shield: corne_left
+ snippet: studio-rpc-usb-uart
+ - board: nice_nano_v2
+ shield: corne_right
+```
+
+Next, enable the `ZMK_STUDIO` Kconfig symbol, for example by adding the following line to your .conf file:
+
+```
+CONFIG_ZMK_STUDIO=y
+```
+
+### Local Build
+
+When building locally, use the `-S` parameter to include the `studio-rpc-usb-uart` snippet. Instead of adding it to your config file, you can also append the `ZMK_STUDIO` Kconfig as an additional CMake argument, e.g.:
+
+```bash
+west build -d build/cl_studio -b nice_nano_v2 \
+ -S studio-rpc-usb-uart -- -DSHIELD=corne_left -DCONFIG_ZMK_STUDIO=y
+```
+
+## Including Unreferenced Behaviors
+
+Normally, ZMK will only build and include behaviors that are referenced by your keymap and unused behavior will be skipped. However, ZMK Studio builds using the `studio-rpc-usb-uart` snippet will automatically define the `ZMK_BEHAVIORS_KEEP_ALL` value, which changes the approach and builds all possible behaviors into the firmware. This lets those behaviors be used in ZMK Studio.
+
+A few controls are available to override this behavior for fine-grained control of what behaviors are built. Behaviors can be kept or omitted by defining certain values in the top of your keymap file, _before_ the standard `behaviors.dtsi` file is included.
+
+By convention, the defines used to keep/omit a given behavior are typically upper-cased versions of the behavior label, e.g. for the `&kt` behavior, the suffix to use would be `_KT`.
+
+### Omit Specific Behaviors
+
+You can omit a specific behaviors by defining a variable like `ZMK_BEHAVIORS_OMIT_KT` at the top of your keymap:
+
+```dts
+#define ZMK_BEHAVIORS_OMIT_KT
+
+#include <behaviors.dtsi>
+```
+
+### Keep Only Selective Behaviors
+
+To override the default "keep all" functionality, you can undefine the `ZMK_BEHAVIORS_KEEP_ALL` flag, and then keep only specific behaviors with a flag like `ZMK_BEHAVIORS_KEEP_KT`, e.g.:
+
+```dts
+#undef ZMK_BEHAVIORS_KEEP_ALL
+
+#define ZMK_BEHAVIORS_KEEP_SK
+#define ZMK_BEHAVIORS_KEEP_MT
+#define ZMK_BEHAVIORS_KEEP_KT
+
+#include <behaviors.dtsi>
+```
+
+## Including Extra Layers
+
+By default, a build with ZMK Studio enabled will only allow as many layers as are defined in your standard keymap. To make additional layers available for use through ZMK Studio, you simply add new empty layers to your keymap with a status of `reserved`, e.g.:
+
+```dts
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ base {
+ display-name = "Base";
+ bindings = // etc.
+ };
+
+ fn_layer {
+ display-name = "Fn";
+ bindings = // etc.
+ };
+
+ extra1 {
+ status = "reserved";
+ };
+
+ extra2 {
+ status = "reserved";
+ };
+ }
+}
+```
+
+The reserved layers will be ignored during regular ZMK builds but will become available for ZMK Studio enabled builds.
diff --git a/docs/docs/keymaps/behaviors/index.mdx b/docs/docs/keymaps/behaviors/index.mdx
index bdacc209ad..c9d0fbe49c 100644
--- a/docs/docs/keymaps/behaviors/index.mdx
+++ b/docs/docs/keymaps/behaviors/index.mdx
@@ -72,6 +72,12 @@ Below is a summary of pre-defined behavior bindings and user-definable behaviors
| `&ext_power` | [Power management](power.md#behavior-binding) | Allows enabling or disabling the VCC power output to save power |
| `&soft_off` | [Soft off](soft-off.md#behavior-binding) | Turns the keyboard off. |
+## ZMK Studio Behaviors
+
+| Binding | Behavior | Description |
+| ---------------- | ------------------------------------------------------ | --------------------------------------------------------- |
+| `&studio_unlock` | [ZMK Studio Unlock](studio-unlock.md#behavior-binding) | Unlocks the device so that ZMK Studio UI can make changes |
+
## User-Defined Behaviors
| Behavior | Description |
diff --git a/docs/docs/keymaps/behaviors/studio-unlock.md b/docs/docs/keymaps/behaviors/studio-unlock.md
new file mode 100644
index 0000000000..d6e87b835d
--- /dev/null
+++ b/docs/docs/keymaps/behaviors/studio-unlock.md
@@ -0,0 +1,25 @@
+---
+title: ZMK Studio Unlock Behavior
+sidebar_label: ZMK Studio Unlock
+---
+
+:::warning
+ZMK Studio is still in active development. This behavior is documented in preparation for its general availability.
+:::
+
+## Summary
+
+## ZMK Studio Unlock
+
+The ZMK Studio unlock behavior is used to grant [ZMK Studio](../../features/studio.md) access to make changes to your ZMK device. The device will remain unlocked until a certain amount of time of inactivity in ZMK Studio, or on disconnect. Those trigger events for relocking can be configured with [studio configuration](../../config/studio.md).
+
+### Behavior Binding
+
+- Reference: `&studio_unlock`
+- Parameters: None
+
+Example:
+
+```dts
+&studio_unlock
+```
diff --git a/docs/sidebars.js b/docs/sidebars.js
index da619e5ec4..daff5c7f76 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -41,6 +41,7 @@ module.exports = {
"features/displays",
"features/backlight",
"features/underglow",
+ "features/studio",
],
},
{
@@ -83,6 +84,7 @@ module.exports = {
"keymaps/behaviors/backlight",
"keymaps/behaviors/power",
"keymaps/behaviors/soft-off",
+ "keymaps/behaviors/studio-unlock",
],
},
"keymaps/modifiers",
@@ -112,6 +114,7 @@ module.exports = {
"config/power",
"config/underglow",
"config/system",
+ "config/studio",
],
},
{
@@ -124,6 +127,7 @@ module.exports = {
"development/hardware-integration/new-shield",
"development/hardware-integration/hardware-metadata-files",
"development/hardware-integration/boards-shields-keymaps",
+ "development/hardware-integration/studio-setup",
],
},
{