Skip to content

Instantly share code, notes, and snippets.

@petejohanson
Created October 22, 2021 17:45
Show Gist options
  • Save petejohanson/2ed65a4559ffd6eaa7ffef21b3ce9069 to your computer and use it in GitHub Desktop.
Save petejohanson/2ed65a4559ffd6eaa7ffef21b3ce9069 to your computer and use it in GitHub Desktop.
WIP - ZMK firmware enhancement RFC to support ZMK Studio

RFC: Studio Firmware Support

Needs

  • Support keys and encoders, as inputs.
    • Consider future pointer input settings, but not in the initial scope.
  • Support multiple layouts (e.g. board w/ ANSI and ISO layouts, or numpads w/ 1u and 2u options, etc.)
    • Ideally, the layout can be selected by studio as well, so you can flash one firmware to a board, and then configure which layout you've built/setup.
    • Each layout should be able to specify all the physical locations of the keys and encoders for that layout.
    • Have encoders as an optional layer on top of any given layout.
  • Ability to test changes to the layout/keymaps before persisting/saving them.
  • Ability to revert to built in default keymap for each available layout.
  • Supports both BLE and USB protocols for interacting w/ the layout/keymap settings.
    • protocol buffers for the message serialization, using nanopb on Zephyr

Modeling

General Runtime Keyboard Settings

  • Name - Zephyr allows setting a name that gets used later for things like BLE advertisement, USB name, etc in the settings system.
  • (future) NKRO vs. 6KRO setting?
  • Sleep timing

Behaviors

The system exposes a set of behaviors that can be bound to a given key position. Each behavior contains

  • 1x - compatible
  • 1x - label?
  • 1x - binding-cells (how many params it takes)
  • 1x - hint/url/metadata describing each parameter, what the taxonomy is?
  • ?x - extra configuration that can be written to? Do we force this part to be a compiled in set? How about combos?

Layout

A layout includes the following things:

  • 1x - Name
  • Nx - key position:
    • x/y location
    • rotation
    • units
  • Nx = encoders:
    • (optional) group ID (only one encoder in a given group can be selected)
    • One of:
      • key position, or
      • x/y location
  • 1x - Default keymap

Outstanding Questions

How to handle splits in this scenario? Does the existing matrix transform suffice, or need tweaks?

Keymap

A keymap contains:

  • Nx - behavior configurations (overrides of behavior settings!)
  • Nx - layers
    • (optional) name
    • 1x - layout index
    • Nx - key bindings (structure TBD)
    • Nx - sensor bindings

Combos

TODO: Document combos

Pointer devices?

Later?

BLE

Custom GATT service, with a set of characteristics

Keyboard Info Characteristic

Serialization of that high level name, sleep timing, etc. info via PB.

  • Permissions: Encrypted
  • Direction: R+W

Layouts

Serialization of the collection of available layouts on the device

  • Permissions: Encrypted
  • Direction: R

Layout + Keymap

The currently active layout + keymap for the keyboard, may be in-memory only if changes made but not persisted.

  • Permissions: Encrypted
  • Direction: R+W

Settings Action

A characteristic to perform certain actions on the device.

Message body is an enum of possible actions to perform.

  • Save - saves latest layout/keymap settings to flash.
  • Revert - reverts to the previously persistend settings in flash.
  • Reset - Resets to the stock layout/keymap built into the keyboard
  • ???

USB

Need to do a lot more research here, I've not done custom USB classes before. Probably an endpoint that has several descriptors for each of the above BLE characteristics, but over USB?

Major TODO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment