Skip to content

Commit

Permalink
feat: Add studio related documentation.
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
petejohanson and caksoylar committed Aug 27, 2024
1 parent f4039de commit cc7bbf7
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 0 deletions.
35 changes: 35 additions & 0 deletions docs/docs/config/studio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
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)

### 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 |
87 changes: 87 additions & 0 deletions docs/docs/development/studio-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: 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 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 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:

- Width
- Height
- X
- Y
- Rotation
- Rotation X
- Rotation Y

All X/Y/Width/Height values are in "key unit" units, with a 100th of a key unit resolution. Rotations are in degrees, with a 100th of a degree resolution. Due to the nature of devicetree, all values are stored in the devicetree without decimals as hundredths of a value, e.g. one key unit is represented as `100`, twenty degrees is represented as `2000`, etc.

Width/Height values should be positive and X/Y should be nonnegative.
If the Rotation value is non-zero, the key will be rotated by that angle around the coordinates specified by Rotation X/Y values, after it is translated to X/Y coordinates. Rotation is clockwise for positive values and counterclockwise otherwise.

:::note
You can specify negative values in devicetree using parentheses around it, e.g. `(-3000)` for a 30 degree counterclockwise rotation.
:::

Here is an example physical layout for a 2x2 macropad:

```
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.

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 the zero-th entry in the 5-column will map to the first entry in the 6-column layout, the second entries show that the second 6-column keymap entry corresponds to the first 5-column entry, etc.
109 changes: 109 additions & 0 deletions docs/docs/features/studio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
title: ZMK Studio
sidebar_label: 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. 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 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
```

## Behaviors

Normally, ZMK will only build and include behaviors that are referenced by your keymap and unused behavior will be skipped. However, 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 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.

### Omit Specific Behaviors

You can omit a specific behaviors by defining a variable like `ZMK_BEHAVIORS_OMIT_FOO` at the top of your keymap:

```dts
#define ZMK_BEHAVIORS_OMIT_KEY_TOGGLE
#include <behaviors.dtsi>
```

### Keep Only Selective Behaviors

To override the default "keep all" functionality, you can define the `ZMK_BEHAVIORS_KEEP_SELECTIVE` flag, and then keep only specific behaviors with a flag like `ZMK_BEHAVIORS_KEEP_FOO`, e.g.:

```dts
#define ZMK_BEHAVIORS_KEEP_SELECTIVE
#define ZMK_BEHAVIORS_KEEP_STICKY_KEY
#define ZMK_BEHAVIORS_KEEP_MOD_TAP
#include <behaviors.dtsi>
```

## 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 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.
6 changes: 6 additions & 0 deletions docs/docs/keymaps/behaviors/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
25 changes: 25 additions & 0 deletions docs/docs/keymaps/behaviors/studio-unlock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: Studio Unlock Behavior
sidebar_label: Studio Unlock
---

:::warn
ZMK Studio is still in active development. This behavior is documented in preparation for its general availability.
:::

## Summary

## Studio Unlock

The 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
```
4 changes: 4 additions & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ module.exports = {
"features/displays",
"features/backlight",
"features/underglow",
"features/studio",
],
},
{
Expand Down Expand Up @@ -83,6 +84,7 @@ module.exports = {
"keymaps/behaviors/backlight",
"keymaps/behaviors/power",
"keymaps/behaviors/soft-off",
"keymaps/behaviors/studio-unlock",
],
},
"keymaps/modifiers",
Expand Down Expand Up @@ -112,6 +114,7 @@ module.exports = {
"config/power",
"config/underglow",
"config/system",
"config/studio",
],
},
{
Expand Down Expand Up @@ -144,6 +147,7 @@ module.exports = {
"development/new-shield",
"development/hardware-metadata-files",
"development/new-behavior",
"development/studio-setup",
],
},
],
Expand Down

0 comments on commit cc7bbf7

Please sign in to comment.