8000 GitHub - rgoulter/smart-keymap: Nickel & Rust-powered Keyboard Firmware
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Nickel & Rust-powered Keyboard Firmware

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

rgoulter/smart-keymap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Smart Keymap

Build keyboard firmware by declaring keymaps in Nickel, powered by Rust.

A 'smart keyboard' is a keyboard with additional bells and whistles, such as alternate key functionality (layers, tap-hold keys, chords, etc.), or RGB effects, etc. -- e.g. QMK, ZMK are popular smart keyboard firmware frameworks.

This project provides a library which handles the keymap behaviour part of this.

  • Nickel allows for concise expression of keymaps, as semicolon's fak showed. (e.g. simple example keymap, a more sophisticated example keymap). Nickel is a configuration language along the lines of "JSON + functions"; its emphasis on correctness and modular configurations make it a powerful configuration language.

  • This project supports the cheap and powerful CH32X035, a 32-bit RISC-V MCU. -- In the same way that semicolon's fak enabled low-budget keyboard designs with the CH552, this project enables keyboard designs using CH32X035.

  • The smart keymap library can be built as a static native library, which makes it easy to integrate into USB HID keyboard examples written in C.

  • As Rust crate, the project also supports using Rust to write keyboard firmware, similar to what keyberon supports.

  • This project also draws inspiration from ideas explored in semickolon's kirei, which emphasised "keys as the main abstraction of keymap behaviour".

Usage

The main idea is write a keymap in Nickel (keymap.ncl), and build keyboard firmware which uses smart-keymap with this custom keymap, either using smart-keymap as a Rust crate, or using libsmart_keymap as a native library.

See the keyboard firmware section below for keyboard firmware which uses smart-keymap.

To make use of smart-keymap in a "user config" repository, see rgoulter/smart-keyboard-config.

Documentation and Examples

Documentation for features which have been implemented can be found at: https://rgoulter.com/smart-keymap/features.html

Some sample ncl keymaps can be found under tests/ncl/. In particular:

Published documentation for the Rust crates can be found at https://rgoulter.com/smart-keymap/doc/smart_keymap/index.html.

Keyboards using Smart Keymap

Pico42, rp2040-rtic-smart-keyboard firmware.

CH32X-36, ch32x035-usb-device-compositekm-c firmware

CH32X-48, ch32x035-usb-device-compositekm-c firmware

CH32X-75-LPR, ch32x035-usb-device-compositekm-c firmware

WABBLE-60, ch58x-ble-hid-keyboard-c firmware

MiniF4-36, stm32f4-rtic-smart-keyboard firmware, stm32-embassy-smart-keyboard firmware,

See the Keyboards wiki page.

Comparison to Other Keyboard Firmware

Smart Keymap provides a library of functions. In this sense, it's most similar to TeXitoi's keyberon, where the user has to implement their own keyboard firmware. -- This is in contrast to popular customisable keyboard firmwares such as QMK or ZMK, which are frameworks.

Configuring keymaps is done using Nickel. Keyberon's keymaps are written directly in Rust, QMK's keymaps are written either in C, or with its data-driven configuration using JSON. ZMK's keymaps are written with devicetree.

Smart Keymap draws a lot of inspiration from semickolon's fak and kirei projects, which also use Nickel. Similar to these projects, Smart Keymap supports low-cost MCUs from WCH (CH32X, CH58x).

Keyboard Firmware

Some keyboard firmware which uses smart-keymap:

RP2040 RTIC Keyboard firmware

The firmware under rp2040-rtic-smart-keyboard has been adapted from the rgoulter/keyboard-labs firmware/keyberon code.

In particular, the firmware under rp2040-rtic-smart-keyboard has an example for the Pico42.

Building

Dependencies

DevEnv is used to provide the toolchain dependencies.

Use devenv shell to enter a shell which has all the tooling installed.

A DevContainer is defined for the project, which can be used to easily get started using e.g. VSCode, GitHub Codespaces, etc..

Smart Keymap Dependencies

Using a keymap.ncl (or the keymap.rs generated from its definition), the keyboard firmware can be built with a command such as:

env SMART_KEYMAP_CUSTOM_KEYMAP="$(pwd)/tests/ncl/keymap-42key-dvorak-simple-with-tap_hold/keymap.ncl" \
  cargo build \
    --release \
    --target=thumbv6m-none-eabi \
    --package=rp2040-rtic-smart-keyboard

The firmware can be deployed to an RP2040 board (in bootloader mode) by using cargo run instead of cargo build.

The pico42 example can be built / run by adding --example pico42.

A custom board.ncl file can be built by setting the SMART_KEYBOARD_CUSTOM_BOARD variable to its path, and building the rp2040-rtic-smart-keyboard package's binary.

Building with Custom Keymap and Board

e.g. with 42key-dvorak/keymap.ncl,

let K = import "keys.ncl" in

# Define tap_hold keys
# by merging a `K.hold` modifier
# with a key.
let A_A = K.A & K.hold K.LeftAlt in
let G_O = K.O & K.hold K.LeftGUI in
let C_E = K.E & K.hold K.LeftCtrl in
let S_U = K.U & K.hold K.LeftShift in
let S_H = K.H & K.hold K.RightShift in
let C_T = K.T & K.hold K.RightCtrl in
let G_N = K.N & K.hold K.RightGUI in
let A_S = K.S & K.hold K.RightAlt in

{
  keys = [
    K.QUOT, K.COMM, K.DOT,  K.P,   K.Y,                  K.F,   K.G,   K.C,    K.R,    K.L,
    A_A,    G_O,    C_E,    S_U,   K.I,                  K.D,   S_H,   C_T,    G_N,    A_S,
    K.SCLN, K.Q,    K.J,    K.K,   K.X,                  K.B,   K.M,   K.W,    K.V,    K.Z,
    K.LCTL, K.LGUI, K.LALT, K.TAB, K.ESC, K.SPC, K.BSPC, K.RET, K.DEL, K.RALT, K.RGUI, K.RCTL,
  ],
}

and board-pico42.ncl (for the Pico42).

let C = import "../ncl/codegen/contracts.ncl" in
{
  gpio_pins | { _ | C.GpioPin },

  board | C.Board = {
    usb = {
      vid = 0xCAFE,
      pid = 0x0005,
      manufacturer = "rgoulter keyboard-labs",
      product = "Pico42"
    },

    matrix =
      let p = gpio_pins in
      {
        cols = [
          p.GP0,
          p.GP1,
          p.GP2,
          p.GP3,
          p.GP4,
          p.GP5,
          p.GP6,
          p.GP7,
          p.GP8,
          p.GP9,
          p.GP10,
          p.GP11,
        ],
        rows = [
          p.GP14,
          p.GP15,
          p.GP16,
          p.GP17,
        ],
        key_count = 42,
      },

    keymap_index_for_key = fun { column_index, row_index } =>
      let NO = null in
      let keymap_indices = [
        [ 0,  1,  2,  3,  4, NO, NO,  5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14, NO, NO, 15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24, NO, NO, 25, 26, 27, 28, 29],
        [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41],
      ]
      in
      let row = std.array.at row_index keymap_indices in
      std.array.at column_index row
      |> match {
        idx if idx != null => 'Key idx,
        _ => 'NoKey,
      },
  },
}

the keyboard firmware can be built & flashed to the RP2040 bootloader with:

env \
  SMART_KEYMAP_CUSTOM_KEYMAP="$(pwd)/tests/ncl/keymap-42key-dvorak-simple-with-tap_hold/keymap.ncl" \
  SMART_KEYBOARD_CUSTOM_BOARD="$(pwd)/rp2040-rtic-smart-keyboard/examples/board-pico42.ncl" \
    cargo run \
      --release \
      --target=thumbv6m-none-eabi \
      --package=rp2040-rtic-smart-keyboard

STM32F4 RTIC & Embassy Keyboard firmware

Firmware for MiniF4-36 rev2021.4 split halves are implemented under stm32f4-rtic-smart-keyboard/examples.

Firmware for MiniF4-36 rev2021.5 split halves are implemented under stm32-embassy-smart-keyboard/examples.

The memory.x used to link the firmware assumes tinyuf2 is used as the bootloader.

The STM32F4-RTIC examples can be built by running:

make minif4_36-rev2021_4-lhs.uf2
make minif4_36-rev2021_4-rhs.uf2

The keymap file used can be changed by setting SMART_KEYMAP_CUSTOM_KEYMAP in the make invocation:

make minif4_36-rev2021_4-lhs.uf2 SMART_KEYMAP_CUSTOM_KEYMAP=path/to/keymap.ncl

CH32X035 USB HID Keyboard

The example USB HID keyboard software from the EVT has been adapted to work with smart_keymap lib.

See firmware/ch32x035-usb-device-compositekm-c for more details.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

0