diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 865e955..269893d 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -1,48 +1,76 @@ -import { defineConfig } from "astro/config"; -import starlight from "@astrojs/starlight"; +import starlight from '@astrojs/starlight' +import { defineConfig } from 'astro/config' // https://astro.build/config export default defineConfig({ - site: "https://univa.github.io", - base: "/rumcake", - trailingSlash: "always", + site: 'https://univa.github.io', + base: '/rumcake', + trailingSlash: 'always', build: { - format: "directory", + format: 'directory', }, integrations: [ starlight({ - title: "rumcake", + title: 'rumcake', + defaultLocale: 'root', + locales: { + // English docs in `src/content/docs/en/` + root: { + label: 'English', + lang: 'en', + }, + // Simplified Chinese docs in `src/content/docs/zh-cn/` + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + }, lastUpdated: true, tableOfContents: { minHeadingLevel: 1, }, social: { - github: "https://github.com/Univa/rumcake", + github: 'https://github.com/Univa/rumcake', }, pagination: false, sidebar: [ { - label: "Information", + label: 'Information', + translations: { + 'zh-CN': '信息', + }, items: [ { - label: "Introduction", - link: "/", + label: 'Introduction', + translations: { + 'zh-CN': '介绍', + }, + link: '/', }, ], }, { - label: "Getting Started", - autogenerate: { directory: "getting-started" }, + label: 'Getting Started', + translations: { + 'zh-CN': '快速开始', + }, + autogenerate: { directory: 'getting-started' }, }, { - label: "Features", - autogenerate: { directory: "features" }, + label: 'Features', + translations: { + 'zh-CN': '特性', + }, + autogenerate: { directory: 'features' }, }, { - label: "API Reference", - link: "api/", + label: 'API Reference', + translations: { + 'zh-CN': 'API 参考', + }, + link: 'api/', }, ], }), ], -}); +}) diff --git a/docs/src/content/docs/features/feature-display.md b/docs/src/content/docs/features/feature-display.md index 3f59822..f3992a5 100644 --- a/docs/src/content/docs/features/feature-display.md +++ b/docs/src/content/docs/features/feature-display.md @@ -134,6 +134,7 @@ impl Ssd1306I2cDisplayDriver for MyKeyboard { .draw(display) .unwrap(); } +} ``` # Available Drivers diff --git a/docs/src/content/docs/zh-cn/features/feature-backlight.md b/docs/src/content/docs/zh-cn/features/feature-backlight.md new file mode 100644 index 0000000..1bf8339 --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-backlight.md @@ -0,0 +1,260 @@ +--- +title: 背光 +description: 如何给你的键盘添加背光 +--- + +:::caution +该功能仍在开发中。要查看尚需实现的功能列表,请查看 [待办事项列表](#待办事项列表)。 +::: + +背光可以用于为键帽下方提供照明,通常通过位于或位于各个开关内部的 LED 实现。`rumcake` 支持根据 LED 类型以及 LED 是否可单独寻址来支持不同类型的背光。 + +# 设置 + +## 必需的 Cargo 功能 + +您必须启用以下 `rumcake` 功能: + +- 恰好其中一个: + - `simple-backlight`(单色背光,所有 LED 具有相同的亮度) + - `simple-backlight-matrix`(单色背光,矩阵中的每个 LED 都可以单独寻址) + - `rgb-backlight-matrix`(RGB 背光,矩阵中的每个 LED 都可以单独寻址) +- 对于您想要使用的[可用背光驱动程序](#可用驱动程序)的特性标志 +- `storage`(可选,如果您想保存背光设置) + +某些驱动程序可能无法支持所有背光类型。 + +## 必需的代码 + +要设置背光,您必须创建一个新类型以实现 traits。然后,您可以在您的 `#[keyboard]` 宏调用中添加 `(id = , driver_setup_fn = )`。您的新类型必须根据您使用的灯光类型实现适当的 traits: + +- `simple_backlight`:[`SimpleBacklightDevice`](/rumcake/api/nrf52840/rumcake/lighting/simple_backlight/trait.SimpleBacklightDevice.html) +- `simple_backlight_matrix`:[`SimpleBacklightMatrixDevice`](/rumcake/api/nrf52840/rumcake/lighting/simple_backlight_matrix/trait.SimpleBacklightMatrixDevice.html) +- `rgb_backlight_matrix`:[`RGBBacklightMatrixDevice`](/rumcake/api/nrf52840/rumcake/lighting/rgb_backlight_matrix/trait.RGBBacklightMatrixDevice.html) + +`driver_setup_fn` 必须是一个没有参数的异步函数,并返回一个实现适当驱动程序 trait 的类型: + +- `simple_backlight`:[`SimpleBacklightDriver`](/rumcake/api/nrf52840/rumcake/lighting/simple_backlight/trait.SimpleBacklightDriver.html) +- `simple_backlight_matrix`:[`SimpleBacklightMatrixDriver`](/rumcake/api/nrf52840/rumcake/lighting/simple_backlight_matrix/trait.SimpleBacklightMatrixDriver.html) +- `rgb_backlight_matrix`:[`RGBBacklightMatrixDriver`](/rumcake/api/nrf52840/rumcake/lighting/rgb_backlight_matrix/trait.RGBBacklightMatrixDriver.html) + +```rust ins={5-8,13-22} +use rumcake::keyboard; + +#[keyboard( + // 在您的键盘宏调用中的某处 ... + simple_backlight_matrix( // TODO: 如果您需要,请将此更改为 `rgb_backlight_matrix` 或 `simple_backlight`。 + id = MyKeyboardLighting, + driver_setup_fn = my_backlight_setup, + ) +)] +struct MyKeyboard; + +// 背光配置 +use rumcake::lighting::simple_backlight_matrix::{SimpleBacklightMatrixDevice, SimpleBacklightMatrixDriver}; +struct MyKeyboardLighting; // 用于实现灯光 traits 的新类型 +async fn my_backlight_setup() -> impl SimpleBacklightMatrixDriver { + // TODO: 我们很快会填写这个! + todo!() +} +impl SimpleBacklightMatrixDevice for MyKeyboardLighting { + // 可选,设置 FPS + const FPS: usize = 20; +} +``` + +:::caution +默认情况下,在键盘打开时(例如更改亮度、色调、饱和度、效果等)所做的背光设置将**不会**被保存。 + +可选择的,您可以添加 `use_storage` 和一个 `storage` 驱动程序来保存背光配置数据。 + +```rust ins={8,10} +use rumcake::keyboard; + +#[keyboard( + // 在您的键盘宏调用中的某处 ... + simple_backlight_matrix( // TODO: 如果您需要,请将此更改为 `rgb_backlight_matrix` 或 `simple_backlight`。 + id = MyKeyboardLighting, + driver_setup_fn = my_backlight_setup, + use_storage // 可选,如果您想保存背光配置 + ), + storage(driver = "internal") // 如果启用了 `use_storage`,则需要指定存储驱动程序。有关更多信息,请参见 feature-storage.md。 +)] +struct MyKeyboard; +``` + +您还需要为所选的存储驱动程序进行额外的设置。有关更多信息,请参见 [存储功能](../feature-storage/) 文档。 +::: + + +如果您正在实现背光矩阵(`simple-backlight-matrix` 或 `rgb-backlight-matrix`),您的键盘还必须实现 `BacklightMatrixDevice` 特性: + +```rust ins={14,25-42} +use rumcake::keyboard; + +#[keyboard( + // 在键盘宏调用中的某个位置... + simple_backlight_matrix( // 如果需要,请将此更改为 `rgb_backlight_matrix` 或 `simple_backlight`。 + id = MyKeyboardLighting, + driver_setup_fn = my_backlight_setup, + ) +)] +struct MyKeyboard; + +// 背光配置 +use rumcake::lighting::simple_backlight_matrix::{SimpleBacklightMatrixDevice, SimpleBacklightMatrixDriver}; +use rumcake::lighting::{BacklightMatrixDevice, setup_backlight_matrix}; +struct MyKeyboardLighting; +async fn my_backlight_setup() -> impl SimpleBacklightMatrixDriver { + // TODO: 待填充! + todo!() +} +impl SimpleBacklightMatrixDevice for MyKeyboardLighting { + // 可选,设置 FPS + const FPS: usize = 20; +} + +impl BacklightMatrixDevice for MyKeyboardLighting { + setup_backlight_matrix! { + led_layout: { + [ (0,0) (17,0) (34,0) (51,0) (68,0) (85,0) (102,0) (119,0) (136,0) (153,0) (170,0) (187,0) (204,0) (221,0) (238,0) (255,0) ] + [ (4,17) (26,17) (43,17) (60,17) (77,17) (94,17) (111,17) (128,17) (145,17) (162,17) (178,17) (196,17) (213,17) (234,17) (255,17) ] + [ (6,34) (30,34) (47,34) (64,34) (81,34) (98,34) (115,34) (132,34) (149,34) (166,34) (183,34) (200,34) (227,34) (227,34) (255,34) ] + [ (11,51) (0,0) (38,51) (55,51) (72,51) (89,51) (106,51) (123,51) (140,51) (157,51) (174,51) (191,51) (208,51) (231,51) (255,51) ] + [ (28,68) (49,68) (79,68) (121,68) (155,68) (176,68) (196,68) (213,68) (230,68) ] + }, + led_flags: { // 必须与上述布局的行数和列数相同 + [ NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE ] + [ NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE ] + [ NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE ] + [ NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE NONE ] + [ NONE NONE NONE NONE NONE NONE NONE NONE NONE ] + } + } +} +``` + +:::note +您的背光矩阵不一定需要与您的开关矩阵具有相同的尺寸。 + +请注意,对于反应式效果,矩阵位置将直接映射到 LED 位置。例如,按下位于开关矩阵位置行 0、列 0 的键将对应于 LED 矩阵上行 0、列 0 的 LED。 +::: + +最后,您必须设置驱动程序。为此,您需要完成您的 `driver_setup_fn`,通过构造驱动程序。您可以[检查所选驱动程序的 API 参考](/rumcake/api/nrf52840/rumcake/drivers/index.html)以获取用于简化此过程的设置函数或宏。 + +根据驱动程序,您可能还需要实现与您选择的驱动程序相对应的适当 trait。检查 [可用背光驱动程序列表](#可用驱动程序) 以获取此信息。 + +例如,对于 `is31fl3731`,您必须实现 `IS31FL3731BacklightDriver`,并且您可以使用 `setup_is31fl3731!` 宏设置驱动程序: + +```rust del={9-10} ins={3-5,11-23,25-34} +use rumcake::lighting::simple + +_backlight_matrix::{SimpleBacklightMatrixDevice, SimpleBacklightMatrixDriver}; +use rumcake::lighting::{BacklightMatrixDevice, setup_backlight_matrix}; +use rumcake::hw::platform::setup_i2c; +use rumcake::drivers::is31fl3731::{ + get_led_from_matrix_coordinates, setup_is31fl3731, IS31FL3731BacklightDriver +}; +struct MyKeyboardLighting; +async fn my_backlight_setup() -> impl SimpleBacklightMatrixDriver { + // TODO: We will fill this out soon! + todo!() + setup_is31fl3731! { + device: MyKeyboardLighting, // 必须是 IS31FL3731BacklightDriver 的一个实现 + address: 0b1110100, // see https://github.com/qmk/qmk_firmware/blob/d9fa80c0b0044bb951694aead215d72e4a51807c/docs/feature_rgb_matrix.md#is31fl3731-idis31fl3731 + i2c: setup_i2c! { // 注意:setup_i2c 的参数可能会根据平台而变化。此处假定为 STM32。 + event_interrupt: I2C1_EV, + error_interrupt: I2C1_ER, + i2c: I2C1, + scl: PB6, + sda: PB7, + rx_dma: DMA1_CH7, + tx_dma: DMA1_CH6, + } + } +} +impl IS31FL3731BacklightDriver for MyKeyboardLighting { + // 这个数组必须与您的 `BacklightMatrixDevice` 实现中指定的行数和列数相同。 + get_led_from_matrix_coordinates! { + [ C1_1 C1_2 C1_3 C1_4 C1_5 C1_6 C1_7 C1_8 C1_9 C1_10 C1_11 C1_12 C1_13 C1_14 C1_15 C2_15 ] + [ C2_1 C2_2 C2_3 C2_4 C2_5 C2_6 C2_7 C2_8 C2_9 C2_10 C2_11 C2_12 C2_13 C2_14 C3_15 ] + [ C3_1 C3_2 C3_3 C3_4 C3_5 C3_6 C3_7 C3_8 C3_9 C3_10 C3_11 C3_12 C3_13 C3_14 C4_15 ] + [ C4_1 C4_2 C4_3 C4_4 C4_5 C4_6 C4_7 C4_8 C4_9 C4_10 C4_11 C4_12 C4_13 C4_14 C5_15 ] + [ C5_2 C5_3 C5_6 C5_7 C5_10 C5_11 C5_12 C5_13 C5_14 ] + } +} + +impl SimpleBacklightMatrixDevice for MyKeyboardLighting { /* ... */ } +impl BacklightMatrixDevice for MyKeyboardLighting { /* ... */ } + +``` + +:::note +以上的 IS31FL3731 驱动程序设置假定使用了 `simple-backlight-matrix`。如果您想要 RGB 矩阵,则有一个单独的 `rumcake::drivers::is31fl3731::backlight::get_led_from_rgb_matrix_coordinates` 宏。 +::: + +# 键值 + +根据您选择的背光类型,您可以在您的 `keyberon` 布局中使用特定版本的 `BacklightCommand` 枚举: + +- [Simple Backlight Commands](/rumcake/api/nrf52840/rumcake/backlight/simple_backlight/animations/enum.BacklightCommand.html) +- [Simple Backlight Matrix Commands](/rumcake/api/nrf52840/rumcake/backlight/simple_backlight_matrix/animations/enum.BacklightCommand.html) +- [RGB Backlight Matrix Commands](/rumcake/api/nrf52840/rumcake/backlight/rgb_backlight_matrix/animations/enum.BacklightCommand.html) + +```rust +Toggle, +TurnOn, +TurnOff, +NextEffect, +PrevEffect, +SetEffect(BacklightEffect), // 可用效果的列表取决于所选择的背光模式。 +SetHue(u8), // 仅 RGB Matrix +IncreaseHue(u8), // 仅 RGB Matrix +DecreaseHue(u8), // 仅 RGB Matrix +SetSaturation(u8), // 仅 RGB Matrix +IncreaseSaturation(u8), // 仅 RGB Matrix +DecreaseSaturation(u8), // 仅 RGB Matrix +SetValue(u8), +IncreaseValue(u8), +DecreaseValue(u8), +SetSpeed(u8), +IncreaseSpeed(u8), +DecreaseSpeed(u8), +SaveConfig, // 通常在背光配置更改时内部调用,仅当 `storage` 已启用时可用。 +ResetTime, // 通常在内部用于同步分体键盘的 LED。 +``` + +在您的 `keyberon` 布局中,您可以使用 `{Custom(SimpleBacklight())}`、`{Custom(SimpleBacklightMatrix())}`、`{Custom(RGBBacklightMatrix())}`,具体取决于您使用的背光系统。 + +此外,您必须选择与键码对应的背光系统,方法是实现一个关联类型 `SimpleBacklightDeviceType`、`SimpleBacklightMatrixDeviceType`、`RGBBacklightDeviceType` 中的一个。 + +用法示例: + +```rust ins={14} +use keyberon::action::Action::*; +use rumcake::lighting::simple_backlight_matrix::SimpleBacklightMatrixCommand::*; +use rumcake::keyboard::{build_layout, Keyboard, Keycode::*}; + +impl KeyboardLayout for MyKeyboard { + /* ... */ + + build_layout! { + { + [ Escape {Custom(SimpleBacklightMatrix(Toggle))} A B C] + } + } + + type SimpleBacklightMatrixDeviceType = MyKeyboardLighting; +} +``` + +# 待办事项列表 + +- [ ] RGB 背光动画 + +# 可用驱动程序 + +| 名称 | 特性标志 | 必需特性 | +| -------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| IS31FL3731 | `is31fl3731` | [`IS31FL3731BacklightDriver`](/rumcake/api/nrf52840/rumcake/drivers/is31fl3731/backlight/trait.IS31FL3731BacklightDriver.html) | +| WS2812 Bitbang | `ws2812_bitbang` | [`WS2812BitbangBacklightDriver`](/rumcake/api/nrf52840/rumcake/drivers/ws2812_bitbang/backlight/trait.WS2812BitbangBacklightDriver.html) | \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/features/feature-bluetooth-host.md b/docs/src/content/docs/zh-cn/features/feature-bluetooth-host.md new file mode 100644 index 0000000..f79b851 --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-bluetooth-host.md @@ -0,0 +1,91 @@ +--- +title: 蓝牙 +description: 如何设置键盘通过蓝牙与设备通信。 +--- + +:::caution +此功能仍在开发中。有关仍需要实现的功能列表,请查看[待办事项列表](#待办事项列表)。 +::: + +这份文档包含了关于如何通过蓝牙(低功耗)与主机设备通信的信息。 + +# 设置 + +## 必需的 Cargo 功能 + +您必须启用以下 `rumcake` 功能: + +- `bluetooth` +- 如果您使用基于 nRF 的键盘,则需要启用 `nrf-ble` + +:::danger +对于基于 nRF5x 的微控制器(MCU),使用 [`nrf-softdevice` crate](https://github.com/embassy-rs/nrf-softdevice) 来实现蓝牙支持。 +由于 `nrf-softdevice` 具有自己的关键段实现,**您必须禁用任何其他关键段实现**。 +例如,如果您使用了 rumcake 模板之一,则可能需要从 `cortex-m` 依赖项中删除 `critical-section-single-core`: + +```toml del={1} ins={2} +cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } +cortex-m = { version = "0.7.6" } +``` + +::: + +## 必需的代码 + +为了使您的键盘支持与蓝牙主机的通信,您必须在 `#[keyboard]` 宏调用中添加 `bluetooth`,并且您的键盘必须实现 `BluetoothKeyboard` 和 `BluetoothDevice` trait: + +```rust ins={5,9-21} +use rumcake::keyboard; + +#[keyboard( + // 在您的键盘宏调用中的某处 ... + bluetooth +)] +struct MyKeyboard; + +use rumcake::hw::platform::BluetoothDevice; +impl BluetoothDevice for WingpairLeft { + // 此地址可以是任何您想要的地址,只要它是有效的“Random Static”蓝牙地址。 + // 请参阅此链接中的“Random Static Address”:https://novelbits.io/bluetooth-address-privacy-ble/ + const BLUETOOTH_ADDRESS: [u8; 6] = [0x41, 0x5A, 0xE3, 0x1E, 0x83, 0xE7]; // TODO: 更改此处 +} + +// 蓝牙配置 +use rumcake::bluetooth::BluetoothKeyboard; +impl BluetoothKeyboard for MyKeyboard { + const BLE_VID: u16 = 0x0000; // 更改此处 + const BLE_PID: u16 = 0x0000; // 更改此处 +} +``` + +:::tip +您可以在同一个键盘上同时使用蓝牙和 USB 主机通信。 + +如果您使用的是模板,则 USB 应该已经配置好,但如果您手动设置了 Cargo 工作空间,则请参阅 [USB 主机通信文档](../feature-usb-host/)。 + +此外,请查看下面的章节以获取更多信息。 +::: + +# 按键码 + +在您的 keyberon 布局中,您可以使用 `HardwareCommand` 中定义的任何枚举成员: + +```rust +ToggleOutput +OutputUSB +OutputBluetooth +``` + +更多信息如下。 + +## USB 主机通信互操作性 + +默认情况下,您的键盘将使用蓝牙与您的设备通信。 +您可以使用 `ToggleOutput`、`OutputUSB` 或 `OutputBluetooth` 按键码来在 USB 和蓝牙之间切换。 +这不会断开您的键盘与 USB 或蓝牙主机的连接。它只是确定要发送键盘报告到的设备。 + +# 待办事项列表 + +- [ ] Multiple bluetooth profiles +- [ ] LE Secure Connections (I believe this requires `nrf-softdevice` changes) +- [ ] Automatic output selection \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/features/feature-display.md b/docs/src/content/docs/zh-cn/features/feature-display.md new file mode 100644 index 0000000..ae384b1 --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-display.md @@ -0,0 +1,132 @@ +--- +title: 显示 +description: 如何配置带有显示屏的键盘。 +--- + +显示屏可以添加到您的键盘上以显示各种图形。这对于显示诸如电池电量、输出模式等实时信息特别有用。 + +# 设置 + +## 需要的 Cargo 特性 + +您必须启用以下 `rumcake` 特性: + +- `display` +- 您希望使用的[可用显示驱动程序](#可用驱动程序)的特性标志 + +## 需要的代码 + +要设置显示屏,您必须在 `#[keyboard]` 宏调用中添加 `display(driver_setup_fn = )`,并且您的键盘必须实现 `DisplayDevice` 特性。 + +`driver_setup_fn` 必须是一个没有参数并返回实现 [`DisplayDriver`](/rumcake/api/nrf52840/rumcake/display/drivers/index.html) 特性的类型的异步函数。 + +```rust ins={5-7,11-21} +use rumcake::keyboard; + +#[keyboard( + // 在键盘宏调用中的某处 ... + display( + driver_setup_fn = my_display_setup + ) +)] +struct MyKeyboard; + +// 显示配置 +use rumcake::display::{DisplayDevice, DisplayDriver}; +async fn my_display_setup() -> impl DisplayDriver { + // TODO: 我们很快会填充这部分内容! + todo!() +} +impl DisplayDevice for MyKeyboard { + // 可选:设置超时和帧率 + const FPS: usize = 0 // 只有当信息更改时才更新显示。如果正在显示动画,请更改此设置。 + const TIMEOUT: usize = 20 +} +``` + +最后,您必须设置驱动程序。为此,您需要完成您的 `driver_setup_fn`,通过构建驱动程序来完成。您可以[查看所选驱动程序的 API 参考](/rumcake/api/nrf52840/rumcake/drivers/index.html)以获得设置函数或宏以使此过程更轻松的信息。 + +根据驱动程序,您可能还需要实现与您选择的驱动程序相对应的适当特性。查看[可用显示驱动程序的列表](#可用驱动程序)以获取此信息。 + +例如,对于 `ssd1306`,您必须实现 `Ssd1306I2cDisplayDriver`,并且您可以使用 `setup_ssd1306!` 宏来设置驱动程序: + +```rust del={4-5} ins={2,6-19,21} +use rumcake::display::{DisplayDevice, DisplayDriver}; +use rumcake::drivers::ssd1306::{setup_ssd1306, Ssd1306I2cDisplayDriver}; +async fn my_display_setup() -> impl DisplayDriver { + // TODO: 我们很快会填充这部分内容! + todo!() + setup_ssd1306! { + i2c: setup_i2c! { // 注意:setup_i2c 的参数可能会根据平台而变化。这假设 STM32。 + event_interrupt: I2C1_EV, + error_interrupt: I2C1_ER, + i2c: I2C1, + scl: PB6, + sda: PB7, + rx_dma: DMA1_CH7, + tx_dma: DMA1_CH6, + }, + // 有关 `size` 和 `rotation` 值,请参阅 ssd1306 crate 的 API 参考:https://docs.rs/ssd1306/latest/ssd1306/ + size: DisplaySize96x16, + rotation: Rotate90, + } +} +impl Ssd1306I2cDisplayDriver for MyKeyboard {} +impl DisplayDevice for MyKeyboard { /* ... */ } +``` + +# 自定义图形 + +默认情况下,显示将显示与正在使用的功能相关的键盘信息。如果您正在使用任何蓝牙功能(例如 `bluetooth`),则会显示电池电量。如果您正在通过 USB 和蓝牙与主机设备通信(启用了 `usb` 和 `bluetooth`),则还会显示操作模式。 + +您还可以使用 `embedded-graphics` crate 显示自定义内容。在每个驱动程序特性中,您可以更改 `on_update` 的默认实现,该实现将根据您设置 `DisplayDevice::FPS` 的值在每帧调用,如果将其设置为 0,则仅在信息更改时调用。 + +以下是一个示例,显示屏上显示文本“test”: + +```rust +use embedded_graphics::mono_font::ascii::FONT_5X8; +use embedded_graphics::mono_font::{MonoTextStyle, MonoTextStyleBuilder}; +use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics::prelude::Point; +use embedded_graphics::text::Text; +use embedded_graphics::Drawable; +use rumcake::drivers::ssd1306::driver::mode::BufferedGraphicsMode; +use rumcake::drivers::ssd1306::driver::prelude::I2CInterface; +use rumcake::drivers::ssd1306::driver::size::{DisplaySize, DisplaySize128x32}; +use rumcake::drivers::ssd1306::driver::Ssd1306; +use rumcake::drivers::ssd1306::Ssd1306I2cDisplayDriver; + +pub static DEFAULT_STYLE: MonoTextStyle<'_, BinaryColor> = MonoTextStyleBuilder::new() + .font(&FONT_5X8) + .text_color(BinaryColor::On) + .build(); + +impl Ssd1306I2cDisplayDriver for MyKeyboard { + /* ... 在您的特性实现中 ... */ + + fn on_update( + display: &mut Ssd1306< + I2CInterface>, + S, + BufferedGraphicsMode, + >, + ) { + Text::with_baseline( + "test", + Point::new(0, 16), + DEFAULT_STYLE, + embedded_graphics::text::Baseline::Top, + ) + .draw(display) + .unwrap(); + } +} +``` + +# 可用驱动程序 + +| 名称 | 特性标志 | 必需特性 | +| ----------- | --------- | --------------------------------------------------------------------------------------------------------------------- | +| SSD1306[^1] | `ssd1306` | [`Ssd1306I2cDisplayDriver`](/rumcake/api/nrf52840/rumcake/drivers/ssd1306/display/trait.Ssd1306I2cDisplayDriver.html) | + +[^1]: 仅支持 I2C \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/features/feature-encoders.md b/docs/src/content/docs/zh-cn/features/feature-encoders.md new file mode 100644 index 0000000..26b56b3 --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-encoders.md @@ -0,0 +1,90 @@ +--- +title: 编码器 +description: 如何将 EC11 兼容编码器添加到您的设备。 +--- + +:::caution +此功能仍在开发中。有关尚需实现的功能列表,请查看[待办事项列表](#待办事项列表)。 +::: + +本文档包含有关如何将 EC11 兼容编码器添加到您的设备的信息。 + +# 设置 + +## 需要的代码 + +要为您的键盘设置编码器,您必须在 `#[keyboard]` 宏调用中添加 `encoders`,并且您的键盘必须实现 `DeviceWithEncoders` 特性。 + +您可以通过使用 `setup_encoders!` 宏轻松完成此操作: + +```rust ins={5,9-31} +use rumcake::keyboard; + +#[keyboard( + // 在键盘宏调用中的某处 ... + encoders +)] +struct MyKeyboard; + +use rumcake::keyboard::DeviceWithEncoders; +impl DeviceWithEncoders for MyKeyboard { + type Layout = Self; + + setup_encoders! { + Encoder { + sw_pin: input_pin!(PB12, EXTI12), + sw_pos: (0, 0), + output_a_pin: input_pin!(PB2, EXTI2), + output_b_pin: input_pin!(PB1), + cw_pos: (0, 1), + ccw_pos: (0, 2), + }, + Encoder { + sw_pin: input_pin!(PA11, EXTI11), + sw_pos: (1, 0), + output_a_pin: input_pin!(PA3, EXTI3), + output_b_pin: input_pin!(PA1), + cw_pos: (1, 1), + ccw_pos: (1, 2), + }, + }; +} + +use rumcake::keyboard::{build_layout, KeyboardLayout}; +impl KeyboardLayout for MyKeyboard { + build_layout! { + { + [ A B C ] + [ D E F ] + } + { + [ G H I ] + [ J K L ] + } + } +} +``` + +`sw_pin` 对应于连接到编码器按钮的引脚。 `output_a_pin` 和 `output_b_pin` 对应于随着编码器旋转而脉冲的引脚。 + +:::note +编码器的当前实现依赖于中断以避免不断轮询编码器。 + +对于 STM32,这意味着您需要为 `sw_pin` 和 `output_a_pin` 指定 EXTI 通道。这可以通过向 `input_pin!` 宏添加额外的参数来完成,如上例所示。对于其他平台,可以省略此步骤。 +::: + +编码器通过将其输出映射到布局上的位置来工作。 +`type Layout = Self` 告诉 rumcake 将编码器事件重定向到 `MyKeyboard` 实现的 `KeyboardLayout`。 + +在上面的示例中,以下是以下映射: + +- 编码器 1 按钮:`A` 键(或第二层上的 `G`) +- 编码器 1 顺时针旋转:`B` 键(或第二层上的 `H`) +- 编码器 1 逆时针旋转:`C` 键(或第二层上的 `I`) +- 编码器 2 按钮:`D` 键(或第二层上的 `J`) +- 编码器 2 顺时针旋转:`H` 键(或第二层上的 `K`) +- 编码器 2 逆时针旋转:`I` 键(或第二层上的 `L`) + +# 待办事项列表 + +- [ ] Via(l) 支持 \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/features/feature-media-keys.md b/docs/src/content/docs/zh-cn/features/feature-media-keys.md new file mode 100644 index 0000000..9876102 --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-media-keys.md @@ -0,0 +1,35 @@ +--- +title: 媒体键 / 消费者控制 +description: 如何为您的键盘布局启用媒体键。 +--- + +`rumcake` 可以配置为发送由 [USB 消费者使用页面中的变体](https://docs.rs/usbd-human-interface-device/latest/usbd_human_interface_device/page/enum.Consumer.html) 组成的 HID 报告。 +这包括媒体控制、应用程序启动器、应用程序控制等。 + +# 设置 + +## 需要的 Cargo 特性 + +您必须启用以下 `rumcake` 特性: + +- `media-keycodes` + +## 需要的代码 + +启用了 `media-keycodes` 特性后,您可以开始在您的 `KeyboardLayout` 实现中使用 `Keycode::Media` 变体: +`Keycode::Media` 变体必须包含一个 `usbd_human_interface_device::page::Consumer` 变体,该变体作为 `rumcake::keyboard::Consumer` 重新导出。 + +使用示例: + +```rust ins={2} ins="{Custom(Media(VolumeIncrement))}" +use keyberon::action::Action::*; +use rumcake::keyboard::{build_layout, Consumer::*, Keycode::Media}; + +/* ... */ + + build_layout! { + { + [ Escape {Custom(Media(VolumeIncrement))} A B C] + } + } +``` \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/features/feature-split.md b/docs/src/content/docs/zh-cn/features/feature-split.md new file mode 100644 index 0000000..d34e93a --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-split.md @@ -0,0 +1,343 @@ +--- +title: 分体键盘 +description: 如何配置分体键盘系统。 +--- + +:::caution +此功能仍在开发中。有关尚需实现的功能列表,请查看[待办事项列表](#待办事项列表)。 +::: + +分体键盘由一个或多个外围设备组成,这些设备向一个中央设备通信以传输矩阵事件,然后该中央设备创建 HID 键盘报告发送到主机设备。 + +通常,分体键盘需要编译多个二进制文件,每个设备/分体键盘的一部分一个二进制文件。例如,您将需要一个左半部分的二进制文件,以及一个右半部分的二进制文件。 + +继续阅读以了解如何使用 `rumcake` 实现“中央”和“外围”设备。 + +# 示例 + +以下文档将展示一个左右分体键盘的示例,无需配对设备。 + +中央设备的代码将放置在 `left.rs` 中,外围设备的代码将放置在 `right.rs` 中。 + +要查看如何实现分体键盘的完整示例,请查看[模板仓库](https://github.com/Univa/rumcake-templates)。 + +# 中央设备设置 + +分体键盘设置中的“中央”设备定义了键盘布局,与主机设备通信,并从其他外围设备接收矩阵事件。应该只有一个中央设备。 +如果分体键盘还使用额外功能,如背光或底部发光,则中央设备还负责将其相关命令发送到外围设备。 + +通常,中央设备可以是一个配对设备(有助于节省电池寿命),或者是键盘的一半。 + +## 中央设备所需的 Cargo 特性 + +您必须使用以下 `rumcake` 特性编译一个二进制文件: + +- `split-central` +- 您希望使用的[可用驱动程序](#可用驱动程序)的特性标志 + +## 中央设备所需的代码 + +要设置中央设备,您必须在 `#[keyboard]` 宏调用中添加 `split_central(driver_setup_fn = )`, +并且您的键盘必须实现 `CentralDevice` 特性。您的 `CentralDevice` 实现应包括 `type Layout = Self;`。 +这将告诉 rumcake 将矩阵事件(从其他外围设备接收)重定向到布局,以处理为按键码。 + +`driver_setup_fn` 必须是一个没有参数并返回实现 [`CentralDeviceDriver`](/rumcake/api/nrf52840/rumcake/split/drivers/trait.CentralDeviceDriver.html) 特性的类型的异步函数。 + + +```rust ins={6-8,17-24} +// left.rs +use rumcake::keyboard; + +#[keyboard( + // 在您的键盘宏调用的某处 + split_central( + driver_setup_fn = my_central_setup + ) +)] +struct MyKeyboardLeftHalf; + +// KeyboardLayout 必须已经被实现 +use rumcake::keyboard::KeyboardLayout; +impl KeyboardLayout for MyKeyboardLeftHalf { /* ... */ } + +// 主机设置 +use rumcake::split::central::{CentralDevice, CentralDeviceDriver}; +async fn my_central_setup() -> impl CentralDeviceDriver { + // TODO: 我们将很快补充... + todo!() +} +impl CentralDevice for MyKeyboardLeftHalf { + type Layout = Self; +} +``` +:::caution +确保您的中央设备通过 [USB](../feature-usb-host/) 或 [蓝牙](../feature-bluetooth-host/) 与主机设备通信。请按照这些文档实现您需要的功能。 + +尽管可以编译一个没有它们的中央设备,但您的键盘将无法与您想要使用它的主机设备通信。 +::: + +最后,您必须设置驱动程序。为此,您需要完成您的 `driver_setup_fn`,通过构建驱动程序来完成。您可以[查看所选驱动程序的 API 参考](/rumcake/api/nrf52840/rumcake/drivers/index.html)以获得设置函数或宏以使此过程更轻松的信息。 + +根据驱动程序,您可能还需要在 `#[keyboard]` 宏中实现对应于所选驱动程序的适当特性。 +查看[可用驱动程序](#可用驱动程序)以获取此信息。 + +例如,使用 `SerialSplitDriver` 结构,您可以像这样构造它: + +```rust del={11-12} ins={13-23} +// KeyboardLayout should already be implemented +use rumcake::keyboard::KeyboardLayout; +impl KeyboardLayout for MyKeyboardLeftHalf { /* ... */ } + +// 分割中央设置 +use rumcake::split::central::{CentralDevice, CentralDeviceDriver}; +use rumcake::drivers::SerialSplitDriver; +use rumcake::hw::platform::setup_buffered_uarte; +async fn my_central_setup() -> impl CentralDeviceDriver { + // TODO: 我们很快会填充这部分内容! + todo!() + SerialSplitDriver { + serial: setup_buffered_uarte! { // 注意:这假设 nRF5x,其他 MCU 有自己的宏和参数。 + interrupt: UARTE0_UART0, + uarte: UARTE0, + timer: TIMER1, + ppi_ch0: PPI_CH0, + ppi_ch1: PPI_CH1, + ppi_group: PPI_GROUP0, + rx_pin: P0_29, + tx_pin: P0_31, + }, + } +} +impl CentralDevice for MyKeyboardLeftHalf { + type Layout = Self; +} +``` + +:::note +如果您想要使用 nRF BLE 作为分体键盘通信的驱动程序,请查看[nRF-BLE](#nrf-ble-驱动程序) 部分以获取更多指导。 +::: + +# 外围设备设置 + +分体键盘设置中的“外围”设备具有开关矩阵,并将矩阵事件发送到中央设备。一个分体键盘设置可以有多个外围设备。 +如果分体键盘还使用了额外功能,则所有外围设备都应从中央设备接收相关命令。 + +## 外围设备的 Cargo 特性 + +您必须使用以下 `rumcake` 特性编译一个二进制文件: + +- `split-peripheral` +- 您希望使用的[可用驱动程序](#可用驱动程序)的特性标志 + +## 外围设备的必需代码 + +要设置外围设备,您必须在 `#[keyboard]` 宏调用中添加 `split_peripheral(driver_setup_fn = )`, +并且您的键盘必须实现 `PeripheralDevice` 特性。您的 `KeyboardMatrix` 实现(应该已经实现)应包括 `type PeripheralDeviceType = Self`。 +这将告诉 rumcake 将矩阵事件重定向到外围设备驱动程序,以发送到中央设备。 + +`driver_setup_fn` 必须是一个没有参数并返回实现 [`PeripheralDeviceDriver`](/rumcake/api/nrf52840/rumcake/split/drivers/trait.PeripheralDeviceDriver.html) 特性的类型的异步函数。 + +```rust ins={6-8,12-24} +// right.rs +use rumcake::keyboard; + +#[keyboard( + // 在键盘宏调用中的某处 ... + split_peripheral( + driver_setup_fn = my_peripheral_setup + ) +)] +struct MyKeyboardRightHalf; + +// KeyboardMatrix 应该已经实现 +use rumcake::keyboard::KeyboardMatrix; +impl KeyboardMatrix for MyKeyboardRightHalf { + type PeripheralDeviceType = Self; +} + +// 分割外围设置 +use rumcake::split::peripheral::{PeripheralDevice, PeripheralDeviceDriver}; +async fn my_peripheral_setup() -> impl PeripheralDeviceDriver { + // TODO: 我们很快会填充这部分内容! + todo!() +} +impl PeripheralDevice for MyKeyboardRightHalf {} +``` + +:::note +对于外围设备,您不必实现 `KeyboardLayout`。只需要实现 `KeyboardMatrix`。 +::: + +最后,您必须设置驱动程序。为此,您需要完成您的 `driver_setup_fn`,通过构建驱动程序来完成。您可以[查看所选驱动程序的 API 参考](/rumcake/api/nrf52840/rumcake/drivers/index.html)以获得设置函数或宏以使此过程更轻松的信息。 + +根据驱动程序,您可能还需要在 `#[keyboard]` 宏中实现对应于所选驱动程序的适当特性。 +查看[可用驱动程序](#可用驱动程序)以获取此信息。 + +例如,使用 `SerialSplitDriver` 结构,您可以像这样构造它: + +```rust del={10-11} ins={12-23} +// KeyboardLayout should already be implemented +use rumcake::keyboard::KeyboardLayout; +impl KeyboardLayout for MyKeyboardLeftHalf { /* ... */ } + +// 分割外围设置 +use rumcake::drivers::SerialSplitDriver; +use rumcake::hw::platform::setup_buffered_uarte; +use rumcake::split::peripheral::{PeripheralDevice, PeripheralDeviceDriver}; +async fn my_peripheral_setup() -> impl PeripheralDeviceDriver { + // TODO: 我们很快会填充这部分内容! + todo!() + SerialSplitDriver { + serial: setup_buffered_uarte! { // 注意:这假设 nRF5x,其他 MCU 有自己的宏和参数。 + interrupt: UARTE0_UART0, + uarte: UARTE0, + timer: TIMER1, + ppi_ch0: PPI_CH0, + ppi_ch1: PPI_CH1, + ppi_group: PPI_GROUP0, + rx_pin: P0_31, + tx_pin: P0_29, + }, + } +} +impl PeripheralDevice for MyKeyboardRightHalf {} +``` + +:::note +如果您想要使用 nRF BLE 作为分体键盘通信的驱动程序,请查看[nRF-BLE](#nrf-ble-驱动程序) 部分以获取更多指导。 +::: + +# 无矩阵的中央设备(Dongle) + +没有矩阵的中央设备的一个示例是一个 dongle。如果您想要实现这样的设备,您可以在您的 `#[keyboard]` 宏调用中添加 `no_matrix`。 + +这样做将消除实现 `KeyboardMatrix` 的需要,因此您只需实现 `KeyboardLayout`。 + +```rust ins={6} +// dongle.rs +use rumcake::keyboard; + +#[keyboard( + // 在键盘宏调用中的某处 ... + no_matrix, + split_central( + driver = "ble" // TODO: 更改为您所需的分割驱动程序,并实现适当的特性 + ) +)] +struct MyKeyboardDongle; + +// 其余的配置 ... +``` + +# nRF-BLE 驱动程序 + +如果您使用的是 nRF5x MCU,并希望使用 BLE 进行分体键盘通信,则需要进行额外的更改才能使其正常工作。 + +对于中央设备和外围设备,都必须实现 [`BluetoothDevice`](/rumcake/api/nrf52840/rumcake/hw/platform/trait.BluetoothDevice.html) 特性: + +`BLUETOOTH_ADDRESS` 可以是任何您想要的值,只要它是有效的“随机静态”蓝牙地址。 +参见这里的“Random Static Address”:https://novelbits.io/bluetooth-address-privacy-ble/ + +```rust ins={2-5} +// 中央文件 +use rumcake::hw::platform::BluetoothDevice; +impl BluetoothDevice for MyKeyboardLeftHalf { + const BLUETOOTH_ADDRESS: [u8; 6] = [0x41, 0x5A, 0xE3, 0x1E, 0x83, 0xE7]; // TODO: 更改为其他值 +} +``` + +```rust ins={2-5} +// 外围文件 +use rumcake::hw::platform::BluetoothDevice; +impl BluetoothDevice for MyKeyboardRightHalf { + const BLUETOOTH_ADDRESS: [u8; 6] = [0x92, 0x32, 0x98, 0xC7, 0xF6, 0xF8]; // TODO: 更改为其他值 +} +``` + +:::note +如果您使用的是 `ble` 驱动程序,并且您的键盘还使用蓝牙与主机设备进行通信(基本上如果您遵循了[蓝牙文档](../feature-bluetooth-host/)或选择了带有蓝牙的模板), +那么 `BluetoothDevice` 特性应该已经为您实现。 +::: + +您还需要更改 `#[keyboard]` 宏调用以添加 `driver_type = "nrf-ble"`。 +这将更改 `driver_setup_fn` 的签名要求。 + +```rust ins={6} +// 中央文件 +#[keyboard( + // 在键盘宏调用中的某处 ... + split_central( + driver_setup_fn = my_central_setup, + driver_type = "nrf-ble" + ) +)] +struct MyKeyboardLeftHalf; +``` + +```rust ins={6} +// 外围文件 +#[keyboard( + // 在键盘宏调用中的某处 ... + split_peripheral( + driver_setup_fn = my_peripheral_setup, + driver_type = "nrf-ble" + ) +)] +struct MyKeyboardRightHalf; +``` + +现在,您的 `driver_setup_fn` 将需要更改其签名。 + +对于中央设备,它需要返回: + +- `CentralDeviceDriver` 实现者 +- 包含要连接的外围设备地址的切片 + +对于外围设备,它需要返回: + +- `PeripheralDeviceDriver` 实现者 +- 要连接的中央设备的地址 + +`setup_nrf_ble_split_central!` 和 `setup_nrf_ble_split_peripheral!` 驱动程序可以用来实现您的 `driver_setup_fn`。 + +```rust del={3} ins={4-9} +// 中央文件 +use rumcake::drivers::nrf_ble::central::setup_nrf_ble_split_central; +async fn my_central_setup() -> (impl CentralDeviceDriver, &'static [[u8; 6]]) { + setup_nrf_ble_split_central! { + peripheral_addresses: [ + [0x92, 0x32, 0x98, 0xC7, 0xF6, 0xF8] // 我们在外围设备文件中指定的外围设备地址 + ] + } +} +``` + +```rust del={3} ins={4-7} +// 外围文件 +use rumcake::drivers::nrf_ble::peripheral::setup_nrf_ble_split_peripheral; +async fn my_peripheral_setup() -> impl PeripheralDeviceDriver { +async fn my_peripheral_setup() -> (impl PeripheralDeviceDriver, [u8; 6]) { + setup_nrf_ble_split_peripheral! { + central_address: [0x41, 0x5A, 0xE3, 0x1E, 0x83, 0xE7] // 我们在中央设备文件中指定的中央设备地址 + } +} +``` + +# 待办事项列表 + +- [ ] 在分割键盘设置中从中央设备同步背光和底部灯光命令的方法 +- [ ] 单个设备可以同时充当外围设备和中央设备 +- [ ] 串行(半双工)驱动程序 +- [ ] I2C 驱动程序 + +# 可用驱动程序 + +| 名称 | 特性标志 | 必需特性 | +| ---------------- | -------------- | ------------------------------------------------------------------------------------ | +| Serial[^1] | 无(默认可用) | 无 | +| nRF Bluetooth LE | `nrf-ble` | [`BluetoothDevice`](/rumcake/api/nrf52840/rumcake/hw/mcu/trait.BluetoothDevice.html) | + +[^1]: + 兼容任何同时实现 `embedded_io_async::Read` 和 `embedded_io_async::Write` 的类型。 + 这包括 `embassy_nrf::buffered_uarte::BufferedUarte`(nRF UARTE)和 `embassy_stm32::usart::BufferedUart`(STM32 UART)。 + diff --git a/docs/src/content/docs/zh-cn/features/feature-storage.md b/docs/src/content/docs/zh-cn/features/feature-storage.md new file mode 100644 index 0000000..499f1fa --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-storage.md @@ -0,0 +1,115 @@ +--- +title: 存储 +description: 如何配置键盘以在板载上存储设置。 +--- + +:::caution +这项功能仍在开发中。有关仍需要的功能列表,请参见实现,请检查[待办事项列表](#待办事项列表)。 +::: + +存储提供了一种机制,使您的设备能够保存数据,在电源循环之间保持数据的持久性。这使您能够根据自己的喜好配置键盘,而不会在重新启动之间丢失您所做的任何更改。 + +## 设置 + +### 所需 Cargo 功能 + +你必须启用以下 `rumcake` 功能: + +- `storage` + +目前,以下功能可以使用存储: + +- `backlight`(用于存储背光色调、饱和度、亮度、速度、效果等) +- `underglow`(用于存储底部灯光色调、饱和度、亮度、速度、效果等) +- `via`/`vial`(用于存储动态按键映射) + +请查看它们各自的文档,了解如何为这些功能启用存储使用。通常,任何能够将数据存储到存储外设的功能都需要在 `#[keyboard]` 宏调用中明确指定 `use_storage`。 + +如果你的 `#[keyboard]` 宏调用中没有在任何地方指定 `use_storage`,则无需设置存储驱动。 + +### 使用 MCU 闪存作为存储的必要代码 + +接下来的说明适用于**如果你想使用选定 MCU 上的现有闪存空间作为存储**。 + +要设置存储,你必须在 `memory.x` 文件中添加一个 `CONFIG` 部分,并使用 `__config_start` 和 `__config_end` 指定 `CONFIG` 部分的起始和结束地址。这将涉及从 `FLASH` 部分中获取一些空间,因此请确保你仍有足够的空间来刷写编译后的固件二进制文件。 + +如果不确定要为存储分配多少空间,请参阅[此部分](#存储空间注意事项)。 + +以下示例显示了 `STM32F303CBx` 芯片的 `memory.x` 可能是什么样子: + +``` +MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 120K /* 减少为芯片的最大 128K 中的 8K,用于下面 CONFIG 部分 */ + CONFIG: ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 8K /* 添加此行 */ + RAM : ORIGIN = 0x20000000, LENGTH = 32K +} + +__config_start = ORIGIN(CONFIG) - ORIGIN(FLASH); /* 添加此行 */ +__config_end = __config_start + LENGTH(CONFIG); /* 添加此行 */ +``` + +**`CONFIG` 部分的要求:** + +- 大小必须是闪存外设的“擦除大小”的倍数。有时这也称为“页面大小”或“区域大小”。 + - 在上面的示例中,STM32F303CBx 的擦除大小为 2KiB。因此,`CONFIG` 部分的大小为 4 页。 +- 起始地址(`__config_start`)必须对齐到擦除大小的倍数。 +- `__config_start` 和 `__config_end` 的值必须**相对于 FLASH 部分的起始地址**。 + - 请注意,在上面的示例中,我们为此目的减去了 `ORIGIN(FLASH)`。 + +最后,你可以将 `storage(driver = "internal")` 添加到你的 `#[keyboard]` 宏调用中。 + +```rust ins={5,7-13} +#[keyboard( + // 你的键盘宏调用中的某处... + underglow( + driver_setup_fn = my_underglow_setup, + use_storage // 此底部灯光功能使用存储 + ), + storage( + driver = "internal", + // 下面的 `flash_size` 仅适用于 RP2040。如果你不使用 RP2040,则省略。 + // 应该等于闪存芯片的总大小(不是你的 CONFIG 分区的大小) + flash_size = 2097152, + // RP2040 上用于处理闪存操作的 `dma` 通道。如果不使用 RP2040,则省略。 + dma = DMA_CH0 + ) +)] +struct MyKeyboard; +``` + +:::note +**对于 RP2040 用户**:`#[keyboard]` 宏调用还必须包括 `flash_size` 和上面示例中显示的 `dma` 通道。如果你不使用 RP2040,则这些内容可以省略。 +::: + +:::tip +默认情况下,`StorageDevice` 特性中的 `setup_storage_buffer()` 函数创建一个大小为 1024 字节的缓冲区。你可以覆盖实现,将缓冲区的大小增加到存储可能更大的值,或者你可以减小大小以节省内存。这可以通过在你的宏调用中添加 `buffer_size` 来实现: + +```rust ins={10} +#[keyboard( + // 你的键盘宏调用中的某处... + storage( + driver = "internal", + // 下面的 `flash_size` 仅适用于 RP2040。如果你不使用 RP2040,则省略。 + // 应该等于闪存芯片的总大小(不是你的 CONFIG 分区的大小) + flash_size = 2097152, + // RP2040 上用于处理闪存操作的 `dma` 通道。如果不使用 RP2040,则省略。 + dma = DMA_CH0, + buffer_size = 512 + ) +)] +struct MyKeyboard; +``` + +请注意,该缓冲区的大小必须足够大,以存储你从存储外设中读取或写入的可能最大值。 +::: + +## 存储空间注意事项 + +为存储分配的空间量取决于你的键盘使用了哪些功能。 + +在底层,TicKV 用作文件系统来存储数据。有关更多信息,请参阅他们的[规范文档](https://github.com/tock/tock/blob/master/libraries/tickv/SPEC.md)。你可能希望考虑分配多个页面以提高闪存的寿命(即使你可能不一定需要所有空间)。 + +# 待办事项列表 + +- [ ] QSPI 驱动 \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/features/feature-underglow.md b/docs/src/content/docs/zh-cn/features/feature-underglow.md new file mode 100644 index 0000000..3887064 --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-underglow.md @@ -0,0 +1,147 @@ +--- +title: Underglow +description: 如何配置键盘以启用底部照明。 +--- + +以下是配置键盘使用底部照明的步骤: + +# 设置 + +## 必要的 Cargo 功能 + +您必须启用以下 `rumcake` 功能: + +- `underglow` +- 选择您想要使用的[可用底部照明驱动程序](#可用驱动程序)之一的功能标志 +- `storage`(可选,如果您想要保存背光设置) + +## 必要的代码 + +要设置底部照明,您必须添加一个新的类型来实现特性。然后,您可以在您的 `#[keyboard]` 宏调用中添加 `underglow(id = , driver_setup_fn = )`。您的新类型必须实现 `UnderglowDevice` 特性。 + +`driver_setup_fn` 必须是一个没有参数的异步函数,并返回一个实现 [`UnderglowDriver`](/rumcake/api/nrf52840/rumcake/lighting/underglow/trait.UnderglowDriver.html) 特性的类型。 + +```rust ins={5-7,13-22} +use rumcake::keyboard; + +#[keyboard( + // 在您的键盘宏调用中的某处... + underglow( + id = MyKeyboardUnderglow, + driver_setup_fn = my_underglow_setup, + ) +)] +struct MyKeyboard; + +// 底部照明配置 +use rumcake::lighting::underglow::{UnderglowDevice, UnderglowDriver}; +struct MyKeyboardUnderglow; // 实现底部照明特性的新类型 +async fn my_underglow_setup() -> impl UnderglowDriver { + // TODO: 我们很快会填写这部分! + todo!() +} +impl UnderglowDevice for MyKeyboardUnderglow { + // 必填项:设置 LED 的数量 + const NUM_LEDS: usize = 20 +} +``` + +:::caution +默认情况下,当键盘处于开启状态时(例如更改亮度、色调、饱和度、效果等),对底部照明设置所做的更改**不会**被默认保存。 + +可选地,您可以添加 `use_storage`,以及一个 `storage` 驱动程序来保存底部照明配置数据。 + +```rust ins={8,10} +use rumcake::keyboard; + +#[keyboard( + // 在键盘宏调用的某处... + underglow( + id = MyKeyboardUnderglow, + driver_setup_fn = my_underglow_setup, + use_storage // 可选项,如果您想要保存底部照明配置 + ) + storage(driver = "internal") // 如果您指定了 `use_storage`,则需要指定存储驱动程序。有关更多信息,请参阅 feature-storage.md。 +)] +struct MyKeyboard; +``` + +您还需要为所选的存储驱动程序进行额外的设置。有关更多信息,请参阅[存储功能](../feature-storage/)的文档。 +::: + +最后,您必须设置驱动程序。为此,您需要完成您的 `driver_setup_fn`,构建驱动程序。 +您可以[检查您选择的驱动程序的 API 参考](/rumcake/api/nrf52840/rumcake/drivers/index.html)以查找设置函数或宏,以使此过程更加简单。 + +根据驱动程序的不同,您可能还需要在 `#[keyboard]` 宏中实现与您选择的驱动程序对应的适当特性。 +查看[可用底部照明驱动程序列表](#可用驱动程序)以获取此信息。 + +例如,对于 `ws2812_bitbang`,您可以使用 `setup_ws2812_bitbang!` 宏来设置驱动程序: + +```rust del={7-8} ins={4,9} +// 在您的文件中的后面... + +use rumcake::lighting::underglow::{UnderglowDevice, UnderglowDriver}; +use rumcake::drivers::ws2812_bitbang::setup_ws2812_bitbang; +struct MyKeyboardUnderglow; // 新类型以实现底部照明特性 +async fn my_underglow_setup() -> impl UnderglowDriver { + // TODO: 我们很快会填写这部分! + todo!() + setup_ws2812_bitbang! { pin: PA10 } +} +impl UnderglowDevice for MyKeyboardUnderglow { /* ... */ } +``` + +# 键值 + +在您的 Keyberon 布局中,您可以使用 `UnderglowCommand` 中定义的任何枚举成员: + +```rust +Toggle, +TurnOn, +TurnOff, +NextEffect, +PrevEffect, +SetEffect(UnderglowEffect), +SetHue(u8), +IncreaseHue(u8), +DecreaseHue(u8), +SetSaturation(u8), +IncreaseSaturation(u8), +DecreaseSaturation(u8), +SetValue(u8), +IncreaseValue(u8), +DecreaseValue(u8), +SetSpeed(u8), +IncreaseSpeed(u8), +DecreaseSpeed(u8), +SaveConfig,// 通常在底部照明配置更改时在内部调用,仅在启用了 `storage` 时可用 +ResetTime,// 通常在分割键盘中用于同步 LED +``` + +在您的 `KeyboardLayout` 实现中,您必须通过实现 `UnderglowDeviceType` 来选择与按键码对应的底部照明系统。 + +使用示例: + +```rust ins={14} +use keyberon::action::Action::*; +use rumcake::lighting::underglow::UnderglowCommand::*; +use rumcake::keyboard::{build_layout, Keyboard, Keycode::*}; + +impl KeyboardLayout for MyKeyboard { + /* ... */ + + build_layout! { + { + [ Escape {Custom(Underglow(Toggle))} A B C] + } + } + + type UnderglowDeviceType = MyKeyboardUnderglow; +} +``` + +# 可用驱动程序 + +| 名称 | 特性标志 | 必需特性 | +| -------------- | ---------------- | -------- | +| WS2812 Bitbang | `ws2812-bitbang` | N/A | diff --git a/docs/src/content/docs/zh-cn/features/feature-usb-host.md b/docs/src/content/docs/zh-cn/features/feature-usb-host.md new file mode 100644 index 0000000..0504f38 --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-usb-host.md @@ -0,0 +1,40 @@ +--- +title: USB +description: 如何配置您的键盘以通过 USB 与设备通信。 +--- + +这份文档包含了关于如何使您的键盘通过 USB 与主机设备通信的信息。 + +# 设置 + +## 必需的 Cargo 功能 + +您必须启用以下 `rumcake` 功能: + +- `usb` + +## 必需的代码 + +为了设置您的键盘进行 USB 主机通信,您的键盘必须实现 `USBKeyboard` trait,并在您的 `keyboard` 宏调用中添加 `usb`: + +```rust ins={5,9-14} +use rumcake::keyboard; + +#[keyboard( + // 在您的键盘宏调用中的某处 ... + usb +)] +struct MyKeyboard; + +// USB 配置 +use rumcake::usb::USBKeyboard; +impl USBKeyboard for MyKeyboard { + const USB_VID: u16 = 0x0000; + const USB_PID: u16 = 0x0000; +} +``` + +:::note +如果您使用的是模板,这些配置大部分应该已经为您完成。 +如果是这样,请确保更改 `USB_VID` 和 `USB_PID`。 +::: \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/features/feature-via-vial.md b/docs/src/content/docs/zh-cn/features/feature-via-vial.md new file mode 100644 index 0000000..2882d4e --- /dev/null +++ b/docs/src/content/docs/zh-cn/features/feature-via-vial.md @@ -0,0 +1,489 @@ +--- +title: Via 与 Vial +description: 如何配置您的键盘以支持 Via 和 Vial 应用程序。 +--- + +:::caution +这项功能仍在开发中。有关仍需要的功能列表,请参见实现,请检查[待办事项列表](#待办事项列表)。 +::: + +[Via](https://www.caniusevia.com/) 提供了使用 [Via 应用程序](https://usevia.app/) 重新配置您的键盘的能力,而不是构建和重新刷新您的固件。Via 通过读取特定于您的键盘的 JSON 定义来工作。为了 Via 应用程序支持您的键盘,这些定义需要提交到 [存储库](https://github.com/the-via/keyboards),或者通过 Via 的设计选项卡进行侧载。 + +[Vial](https://get.vial.today/) 是一种替代方案,旨在去中心化。为了支持您的键盘,JSON 定义内置到固件中,并且 Vial 应用程序将在运行时加载 JSON 数据。这消除了将 JSON 定义上传到中央存储库的需要。 + +`rumcake` 提供了使用 Via 或 Vial 的选项。 + +目前,`rumcake` 实现了: + +- Via 协议版本 12,需要 Via V3 定义。 +- Vial 协议版本 6,基于 Via V2。 + +# 设置 + +## 必须的 Cargo 特性 + +您必须启用以下 `rumcake` 功能: + +- `via` 或 `vial`(取决于您想要使用哪个) +- `storage`(可选项,如果您希望保存在 Via/Vial 应用程序中所做的更改) + +## 必要的代码 + +要设置 Via 和 Vial 支持,您必须添加一个新类型来实现 `ViaKeyboard` 特性。然后,您可以在您的 `keyboard` 宏调用中添加 `via(id = )`。 + +某些 Via 功能还需要手动配置: + +- 对于宏,您需要实现 [`DYNAMIC_KEYMAP_MACRO_BUFFER_SIZE`](/rumcake/api/nrf52840/rumcake/via/trait.ViaKeyboard.html#associatedconstant.DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE) 和 [`DYNAMIC_KEYMAP_MACRO_COUNT`](/rumcake/api/nrf52840/rumcake/via/trait.ViaKeyboard.html#associatedconstant.DYNAMIC_KEYMAP_MACRO_COUNT) + - 这可以通过 `setup_macro_buffer` 宏轻松完成 +- 如果您正在使用某种形式的背光(`simple-backlight`、`simple-backlight-matrix` 或 `rgb-backlight-matrix`),您需要更改 [`BACKLIGHT_TYPE`](https://univa.github.io/rumcake/api/nrf52840/rumcake/via/trait.ViaKeyboard.html#associatedconstant.BACKLIGHT_TYPE)。 + 这控制了 `QK_BACKLIGHT` 按键码如何转换为 `keyberon` 动作。换句话说,它控制了 Via 应用程序中以 `BL_` 为前缀的按键码的行为。 + +对于其他可配置的 Via 选项,请参阅 [`ViaKeyboard` 特性](/rumcake/api/nrf52840/rumcake/via/trait.ViaKeyboard.html)。 + +```rust ins={5-7,16-26} +use rumcake::keyboard; + +#[keyboard( + // 在键盘宏调用的某处... + via( + id = MyKeyboardVia + ) +)] +struct MyKeyboard; + +impl KeyboardLayout for MyKeyboard { + /* ... */ +} + +// Via 设置 +use rumcake::via::{BacklightType, setup_macro_buffer, ViaKeyboard}; +struct MyKeyboardVia; +impl ViaKeyboard for MyKeyboardVia { + type Layout = MyKeyboard; // 必须是实现 `KeyboardLayout` 的类型 + + // 可选的,此示例假设您正在使用 simple-backlight-matrix。 + const BACKLIGHT_TYPE: Option = Some(BacklightType::SimpleBacklightMatrix) + + // 可选的,如果您想要使用 Via 应用程序创建宏,请包括此内容。 + setup_macro_buffer!(buffer_size: 512, macro_count: 16) // 宏所占用的最大字节数,然后是可以创建的最大宏数。 +} + +``` + +:::caution +默认情况下,在 Via 应用程序中对键盘所做的更改(例如更改布局、灯光设置等)**不会**被默认保存。 + +可选地,您可以添加 `use_storage` 和一个 `storage` 驱动程序来保存 Via 数据。 + +另外,您需要在您的 `ViaKeyboard` 实现中调用 `connect_storage_service`。 + +```rust del={5} ins={6-10,18} +use rumcake::keyboard; + +#[keyboard( + // 在键盘宏调用的某处... + via, + via( + id = MyKeyboardVia, + use_storage // 如果您想要保存 Via 配置,则为可选项 + ), + storage(driver = "internal") // 如果您指定了 `use_storage`,则需要指定存储驱动程序。有关更多信息,请参阅 feature-storage.md。 +)] +struct MyKeyboard; + +//... +use rumcake::via::connect_storage_service; +impl ViaKeyboard for MyKeyboardVia { + //... + connect_storage_service!(MyKeyboard) +} +``` + +您还需要对所选的存储驱动程序进行额外的设置。 +有关更多信息,请参阅 [存储功能](../feature-storage/) 的文档。 +::: + +如果您正在使用 Vial,除了实现 `ViaKeyboard` 外,还必须实现 `VialKeyboard`。 +在您的 `keyboard` 宏调用中,您应该使用 `vial`,而不是 `via`。 + +以下代码示例展示了如何实现 `VialKeyboard` 特性,并使用构建脚本实现 `KEYBOARD_DEFINITION`。请按照 [Vial 定义](#compiling-vial-definitions) 部分的说明操作。 + +对于其他可配置的 Vial 选项,请参阅 [`VialKeyboard` 特性](/rumcake/api/nrf52840/rumcake/vial/trait.VialKeyboard.html)。 + +```rust del={7} ins={1-3,10,30-35} +// GENERATED_KEYBOARD_DEFINITION 来自 _generated.rs,由 build.rs 脚本生成。 +#[cfg(vial)] +include!(concat!(env!("OUT_DIR"), "/_generated.rs")); + +#[keyboard( + // 在键盘宏调用的某处... + via( + id = MyKeyboardVia + ) + vial( + id = MyKeyboardVia + ) +)] +struct MyKeyboard; + +// ... + +// Via 设置 +use rumcake::via::{setup_macro_buffer, ViaKeyboard}; +impl ViaKeyboard for MyKeyboard { + type Layout = MyKeyboard; // 必须是实现 `KeyboardLayout` 的类型 + + // 可选的,此示例假设您正在使用 simple-backlight-matrix。 + const BACKLIGHT_TYPE: Option = Some(BacklightType::SimpleBacklightMatrix) + + // 可选的,如果您想要使用 Via 应用程序创建宏,请包括此内容。 + setup_macro_buffer!(buffer_size: 512, macro_count: 16) // 宏所占用的最大字节数,然后是可以创建的最大宏数。 +} + +use rumcake::vial::VialKeyboard; +impl VialKeyboard for MyKeyboard { + const VIAL_KEYBOARD_UID: [u8; 8] = [0; 8]; // 更改此处 + const VIAL_UNLOCK_COMBO: &'static [(u8, u8)] = &[(0, 1), (0, 0)]; // 用于解锁 VIAL 的矩阵位置 (行, 列),可以设置为您想要的任何值 + const KEYBOARD_DEFINITION: &'static [u8] = &GENERATED_KEYBOARD_DEFINITION; +} +``` + +:::caution +与之前的警告类似,您需要指定 `use_storage`,以保存 Vial 数据。 +`connect_storage_service!` 仍然在 `ViaKeyboard` 内部实现: + +```rust del={5} ins={6-10,18} +use rumcake::keyboard; + +#[keyboard( + // 在键盘宏调用的某处... + vial, + vial( + id = MyKeyboardVia, + use_storage // 如果您想要保存 Vial 配置,则为可选项 + ), + storage = "internal" // 如果您指定了 `use_storage`,则需要指定存储驱动程序。有关更多信息,请参阅 feature-storage.md。 +)] +struct MyKeyboard; + +//... +use rumcake::via::connect_storage_service; +impl ViaKeyboard for MyKeyboardVia { + //... + connect_storage_service!(MyKeyboard) +} +``` + +::: + +## 编译 Vial 定义 + +要将您的 Vial 定义编译到固件中,您必须将您的 JSON 定义文件进行缩小和 LZMA 压缩,并将原始字节传递给 `VialKeyboard` 特性实现中的 `KEYBOARD_DEFINITION`。 + +[基本模板](https://github.com/Univa/rumcake-templates/tree/main/rumcake-basic-template) 展示了您如何使用构建脚本 (`build.rs`) 实现此目的。 +构建脚本执行以下操作: + +- 构建脚本将搜索并打开您键盘的 JSON 定义文件。将其放置在 `./src/definition.json`。 +- 构建脚本将检查 `vial` 特性标志,然后对 JSON 数据进行缩小和 LZMA 压缩。 +- 结果字节被写入 `GENERATED_KEYBOARD_DEFINITION` 常量中。 + +`GENERATED_KEYBOARD_DEFINITION` 常量可以在您的 `VialKeyboard` 特性实现中用于 `KEYBOARD_DEFINITION`。 +请查看先前显示的代码示例,了解如何使用此常量。 + +## 推荐的 Via V3 自定义 UI 定义 + +如果您正在使用常规的 Via(非 Vial),建议使用下面提供的自定义 UI 菜单与 `rumcake` 的额外功能进行交互。请随意选择您需要的菜单。 + +要添加所需的菜单,请直接将 JSON 添加到您键盘定义文件中的 `"menus"` 字段中。 + +:::note +尽管 Via V3 提供了[内置的 `qmk_*` 菜单](https://www.caniusevia.com/docs/built_in_menus)来使用灯光功能,但 `rumcake` 的灯光系统并不设计为与这些菜单兼容。 +这是因为 `rumcake` 处理效果 ID、灯光速度、启用/禁用等方面的微妙差异,因此,如果您使用常规的 Via,则更倾向于使用下面的自定义 UI。如果您使用 Vial,`rumcake` 将尝试支持 Via/Vial 应用程序的内置灯光菜单。 +::: + +:::note +未提供 RGB 矩阵的菜单。RGB 背光动画仍需实现。 +::: + +### Underglow 菜单 + +```json ins={10-79} +{ + "name": "My Keyboard", + "vendorId": "0xDEAD", + "productId": "0xBEEF", + // ... + "menus": [ + { + "label": "Lighting", + "content": [ + { + "label": "Underglow", + "content": [ + { + "label": "Enabled", + "type": "toggle", + "content": [ + "rumcake__via__protocol_12__ViaRGBLightValue__Enabled", + 2, + 5 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaRGBLightValue__Enabled} == 1", + "label": "Brightness", + "type": "range", + "options": [0, 255], + "content": [ + "rumcake__via__protocol_12__ViaRGBLightValue__Brightness", + 2, + 1 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaRGBLightValue__Enabled} == 1", + "label": "Color", + "type": "color", + "content": [ + "rumcake__via__protocol_12__ViaRGBLightValue__Color", + 2, + 4 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaRGBLightValue__Enabled} == 1", + "label": "Speed", + "type": "range", + "options": [0, 255], + "content": [ + "rumcake__via__protocol_12__ViaRGBLightValue__EffectSpeed", + 2, + 3 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaRGBLightValue__Enabled} == 1", + "label": "Effect", + "type": "dropdown", + "options": [ + "Solid", + "Breathing", + "Rainbow Mood", + "Rainbow Swirl", + "Snake", + "Knight", + "Christmas", + "Static Gradient", + "RGB Test", + "Alternating", + "Twinkle", + "Reactive" + ], + "content": [ + "rumcake__via__protocol_12__ViaRGBLightValue__Effect", + 2, + 2 + ] + } + ] + } + ] + } + ] + // ... +} +``` + +### Simple Backlight 菜单 + +```json ins={10-56} +{ + "name": "My Keyboard", + "vendorId": "0xDEAD", + "productId": "0xBEEF", + // ... + "menus": [ + { + "label": "Lighting", + "content": [ + { + "label": "Backlight", + "content": [ + { + "label": "Enabled", + "type": "toggle", + "content": [ + "rumcake__via__protocol_12__ViaBacklightValue__Enabled", + 1, + 4 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaBacklightValue__Enabled} == 1", + "label": "Brightness", + "type": "range", + "options": [0, 255], + "content": [ + "rumcake__via__protocol_12__ViaBacklightValue__Brightness", + 1, + 1 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaBacklightValue__Enabled} == 1", + "label": "Speed", + "type": "range", + "options": [0, 255], + "content": [ + "rumcake__via__protocol_12__ViaBacklightValue__EffectSpeed", + 1, + 3 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaBacklightValue__Enabled} == 1", + "label": "Effect", + "type": "dropdown", + "options": ["Solid", "Breathing", "Reactive"], + "content": [ + "rumcake__via__protocol_12__ViaBacklightValue__Effect", + 1, + 2 + ] + } + ] + } + ] + } + ] + // ... +} +``` + +### Simple Backlight Matrix 菜单 + +```json ins={10-81} +{ + "name": "My Keyboard", + "vendorId": "0xDEAD", + "productId": "0xBEEF", + // ... + "menus": [ + { + "label": "Lighting", + "content": [ + { + "label": "Backlight", + "content": [ + { + "label": "Enabled", + "type": "toggle", + "content": [ + "rumcake__via__protocol_12__ViaLEDMatrixValue__Enabled", + 5, + 4 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaLEDMatrixValue__Enabled} == 1", + "label": "Brightness", + "type": "range", + "options": [0, 255], + "content": [ + "rumcake__via__protocol_12__ViaLEDMatrixValue__Brightness", + 5, + 1 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaLEDMatrixValue__Enabled} == 1", + "label": "Speed", + "type": "range", + "options": [0, 255], + "content": [ + "rumcake__via__protocol_12__ViaLEDMatrixValue__EffectSpeed", + 5, + 3 + ] + }, + { + "showIf": "{rumcake__via__protocol_12__ViaLEDMatrixValue__Enabled} == 1", + "label": "Effect", + "type": "dropdown", + "options": [ + "Solid", + "Alphas Mods", + "Gradient Up Down", + "Gradient Left Right", + "Breathing", + "Band", + "Band Pin Wheel", + "Band Spiral", + "Cycle Left Right", + "Cycle Up Down", + "Cycle Out In", + "Raindrops", + "Dual Beacon", + "Wave Left Right", + "Wave Up Down", + "Reactive", + "Reactive Wide", + "Reactive Cross", + "Reactive Nexus", + "Reactive Splash" + ], + "content": [ + "rumcake__via__protocol_12__ViaLEDMatrixValue__Effect", + 5, + 2 + ] + } + ] + } + ] + } + ] + // ... +} +``` + +# 按键码支持 + +`rumcake` 并不支持 Via/Vial 应用程序中显示的所有按键码。目前,以下按键码是可用的: + +- 基本按键码(在 Via/Vial 的基本选项卡中,或在 HID 键盘报告中可用的按键码) +- 灯光按键码,除了 `QK_BACKLIGHT_TOGGLE_BREATHING`。RGB 按键码仅适用于底部照明,而不适用于 RGB 背光矩阵。 +- 瞬时层(`MO(x)`) +- 默认层(`DF(x)`) +- 切换层(`TG(x)`) +- 单次触发层(`OSL(x)`) +- 宏按键码(`M0`、`M1`、`M2` ...) +- 自定义按键码(在您的 JSON 定义中的 `customKeycodes`) +- 某些媒体按键码。必须手动启用此功能。请查看 ["媒体按键" 文档](../feature-media-keys/) +- QK_OUTPUT_BLUETOOTH 和 QK_OUTPUT_USB + +您可以假设上述未列出的任何按键码都不受支持。 + +尝试使用不支持的按键码将不会对您的布局产生任何更改。它可能会在 Via 应用程序中短暂显示,但重新加载应用程序将会将按键码恢复到其先前的状态。 + +有关这些按键码如何转换为 `keyberon` 动作的更多信息,请参阅 [rumcake/src/via/protocol_12/keycodes.rs](https://github.com/Univa/rumcake/blob/4a7dfb8f9b04c321a43c35bc0d96fbc6afaabad2/rumcake/src/via/protocol_12/keycodes.rs#L1082)。 + +## 限制 + +对于支持的按键码,仍然存在一些限制。通常,这些限制是由于内存限制,同时仍然允许 `keyberon` 的动作提供的灵活性。 + +建议将任何非基本动作直接编译到固件中,而不是通过 Via 分配它们。 + +- 通过 Via 分配的单次触发层按键码仅适用于层 0 到 15。 + - 已经编译到您的 `keyberon` 布局中的单次触发动作仍然可以在更大的层编号下工作。 +- 编译到您的 `keyberon` 布局中的序列动作不会显示在 Via 应用程序中,它将显示为 `0xFFFF`。 +- 对于 Vial,使用延迟事件和在宏中使用非基本按键码(大于 0x00FF)的轻击/按/释放事件将无效。在执行事件时使用它们将中止宏。 +- 要使背光按键码起作用,您需要修改您的 `ViaKeyboard` 实现中的 `BACKLIGHT_TYPE` 常量。这定义了如何转换背光按键码。 +- RGB 按键码仅适用于底部照明,而不适用于 RGB 背光矩阵。 + +# 待办事项列表 + +- [ ] 轻击切换,单次触发修改按键码(以及“层”子菜单中的其他按键码) +- [ ] QMK 设置(Vial) +- [ ] 动态按键映射轻击舞蹈,组合,按键覆盖(Vial) +- [ ] Vial 宏支持(延迟和非基本按键码) diff --git a/docs/src/content/docs/zh-cn/getting-started/matrix-and-layout.md b/docs/src/content/docs/zh-cn/getting-started/matrix-and-layout.md new file mode 100644 index 0000000..d39267f --- /dev/null +++ b/docs/src/content/docs/zh-cn/getting-started/matrix-and-layout.md @@ -0,0 +1,344 @@ +--- +title: 设备信息,矩阵与布局 +description: 如何配置你的键盘矩阵和布局。 +sidebar: + order: 3 +--- + +本文档包含一些有关如何定义键盘基本信息的信息、以及如何为键盘设置基本矩阵和布局设置的信息。 + +:::note +以下示例针对的是非分体式键盘,它将 `KeyboardMatrix` 和 `KeyboardLayout` 实现放在同一个入口点中。 +如果您使用的是分体式键盘,可以继续阅读以了解 `KeyboardMatrix`和 `KeyboardLayout` 特质的实现,但 `impl` 块的位置将取决于取决于您的分体式键盘设置。 + +有关详细信息,请参阅[拆分键盘文档](../../features/feature-split)。 +::: + +# 键盘信息 + +每个设备必须实现 `rumcake` 的基本特质 `Keyboard` 才能使用。在这里,您可以定义一些基本信息,包括键盘的名称、制造商、版本号等。 + +```rust ins={6-11} +use rumcake::keyboard; + +#[keyboard(usb)] +pub struct MyKeyboard; + +use rumcake::keyboard::Keyboard; +impl Keyboard for MyKeyboard { + const MANUFACTURER: &'static str = "Me"; // 制造商名称 + const PRODUCT: &'static str = "MyKeyboard"; // 键盘名称 + const SERIAL_NUMBER: &'static str = "1"; // 版本号 +} +``` + +# 键盘矩阵 + +在[模板](https://github.com/Univa/rumcake-templates)中,您将看到要实现键盘矩阵,您需要使用一个 `build__matrix!` 宏来实现 `KeyboardMatrix` 特质: + +```rust ins={13-21} +use rumcake::keyboard; + +#[keyboard(usb)] +pub struct MyKeyboard; + +use rumcake::keyboard::Keyboard; +impl Keyboard for MyKeyboard { + const MANUFACTURER: &'static str = "Me"; + const PRODUCT: &'static str = "MyKeyboard"; + const SERIAL_NUMBER: &'static str = "1"; +} + +use rumcake::keyboard::{build_standard_matrix, KeyboardMatrix}; +impl KeyboardMatrix for MyKeyboard { + type Layout = Self; // 先不用担心这里的错误。一旦你实现了`KeyboardLayout`,它就会被修复 + + build_standard_matrix! { + rows: [ PB2 PB10 PB11 PA3 ], + cols: [ PB12 PB1 PB0 PA7 PA6 PA5 PA4 PA2 PB3 PB4 PA15 PB5 ] + } +} +``` + +如果您看到有关 `Self` 未实现 `KeyboardLayout` 的错误,请不要担心。一旦您按照下一节进行操作,此问题就会得到解决。请注意,此关联类型用于将矩阵事件重定向到已实现的布局。 + +用于矩阵引脚的标识符必须与 MCU 的相应 HAL(硬件抽象库)使用的标识符相匹配。下面链接的网站顶部有一个下拉菜单,可让您选择芯片。选择您的芯片以查看可用的引脚: + +- 对于基于 nRF 的键盘,[embassy-nrf](https://docs.embassy.dev/embassy-nrf/git/nrf52840/gpio/trait.Pin.html#implementors) +- 对于基于 STM32 的键盘,[embassy-stm32](https://docs.embassy.dev/embassy-stm32/git/stm32f072cb/gpio/trait.Pin.html#implementors) + +定义矩阵后,您可以设置[键盘布局]((#键盘布局))。如果您有双工矩阵,请考虑在设置键盘布局之前[检查该部分](#双工矩阵)。 + +:::note +上面的例子假设一个矩阵是一个标准矩阵(开关按行和列连接,带有二极管)。首先定义行,然后定义列。行和列从 0 开始从左到右枚举。在此示例中, `PB2` 是第 0 行, `PA3` 是第 3 行。 + +对于其他矩阵类型,请参阅[其他矩阵类型](#其他矩阵类型)部分。 +::: + +# 键盘布局 + +要实现键盘布局,您必须实现 `KeyboardLayout` 特征。建议使用 rumcake 的 `build_layout!` 宏,它只是 `keyberon` 的 [`layout!`](https://github.com/TeXitoi/keyberon/blob/a423de29a9cf0e9e4d3bdddc6958657662c46e01/src/layout.rs#L5) 宏的包装。 + +请按照 `keyberon` 的宏说明设置您的键盘布局。 + +以下示例展示了一个 3 层键盘布局,旨在与我们之前定义的矩阵一起使用: + + +```rust ins={24-46} +use rumcake::keyboard; + +#[keyboard(usb)] +pub struct MyKeyboard; + +use rumcake::keyboard::Keyboard; +impl Keyboard for MyKeyboard { + const MANUFACTURER: &'static str = "Me"; + const PRODUCT: &'static str = "MyKeyboard"; + const SERIAL_NUMBER: &'static str = "1"; +} + +use rumcake::keyboard::{build_standard_matrix, KeyboardMatrix}; +impl KeyboardMatrix for MyKeyboard { + type Layout = Self; + + build_standard_matrix! { + rows: [ PB2 PB10 PB11 PA3 ], + cols: [ PB12 PB1 PB0 PA7 PA6 PA5 PA4 PA2 PB3 PB4 PA15 PB5 ] + } +} + + +use rumcake::keyboard::{build_layout, KeyboardLayout}; +impl KeyboardLayout for MyKeyboard { + build_layout! { + { + [ Tab Q W E R T Y U I O P '[' ] + [ LCtrl A S D F G H J K L ; '\'' ] + [ Escape Z X C V B N M , . / ']' ] + [ No No No (1) LShift LAlt BSpace Space (2) No No No ] + } + { + [ LGui F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 ] + [ t t t t t t Left Down Up Right t t ] + [ t t t t t t Home PgDown PgUp End t F12 ] + [ t t t t t t PScreen Enter t t t t ] + } + { + [ t 1 2 3 4 5 6 7 8 9 0 '(' ] + [ t t t t t t - = t t t t ] + [ '`' t t t t t t t t t '\\' ')' ] + [ t t t t t Delete t t t t t t ] + } + } +} +``` + +恭喜!您已经实现了一个基本的键盘。您现在可以继续构建和刷写固件,或者尝试在 “功能” 侧栏中实现的其他功能。 + +# 其他矩阵类型 + +## 直接引脚矩阵(无二极管矩阵) + +如果您的 MCU 引脚直接连接到开关(而不是引脚连接到一行/列开关),那么您可以使用 `build_direct_pin_matrix!` 宏来代替。 + + +```rust ins={3-11} +// 其余的配置... + +use rumcake::keyboard::{build_direct_pin_matrix, KeyboardMatrix}; +impl KeyboardMatrix for MyKeyboard { + type Layout = Self; + + build_direct_pin_matrix! { + [ PB2 PB10 PB11 PA3 ] + [ PB12 PB1 PB0 No ] + } +} + +use rumcake::keyboard::{build_layout, KeyboardLayout}; +impl KeyboardLayout for MyKeyboard { + build_layout! { + { + [ Tab Q W E ] + [ LCtrl A S D ] + } + { + [ LGui F1 F2 F3 ] + [ t t t t ] + } + } +} +``` + +每个引脚将直接映射到一个(行,列)位置,这决定了它对应的布局中的键。每行必须具有相同的列数。如果有未使用的矩阵位置,可以使用 `No` 忽略它们。 + +在此示例中,连接到 `PB10` 的开关映射到第 0 行、第 1 列。基于 `KeyboardLayout` 的实现,该开关将对应于 `Q`/`F1` 键。 + +## 模拟矩阵 + +:::caution +模拟矩阵仍在开发中,可能并不完全稳定。 +::: + +如果您的开关由模数转换外设供电(例如,霍尔效应开关通常就是这种情况),那么您可以使用 `build_analog_matrix!` 宏。此外,您还需要使用 `setup_adc_sampler!` 宏指定 ADC 采样器配置。 + + +```rust ins={4-15,17-31} +// 其他配置... + +// 创建一个 ADC 采样器,其中 MCU 的引脚连接到多路复用器,或者直接连接到模拟源 +setup_adc_sampler! { + (interrupt: ADC1_2, adc: ADC2) => { + Multiplexer { + pin: PA2, // 连接到多路复用器的 MCU 模拟引脚 + select_pins: [ PA3 No PA4 ] // 连接到多路复用器上的选择引脚的引脚 + }, + Direct { + pin: PA5 // MCU 模拟引脚直接连接到模拟源 + }, + } +} + +use rumcake::keyboard::{build_analog_matrix, KeyboardMatrix}; +impl KeyboardMatrix for MyKeyboard { + type Layout = Self; + + build_analog_matrix! { + channels: { + [ (1,0) (0,1) (0,4) (0,5) ] + [ (0,0) No No No ] + }, + ranges: { + [ 3040..4080 3040..4080 3040..4080 3040..4080 ] + [ 3040..4080 No No No ] + } + } +} +``` + +首先,提供 ADC 采样器定义。在此示例中, `ADC2` 外设(由 `ADC1_2` 中断控制)连接到两个引脚。引脚 `PA2` 连接到多路复用器,引脚 `PA5` 直接连接到模拟源(本例中为开关)。 + +对于 `PA2` ,多路复用器输出选择由 `PA3` 和 `PA4` 控制。第二个选择引脚未使用,因此用 `No` 表示。引脚按最低有效位在前排列。因此,如果 `PA4` 为高电平且 `PA2` 为低电平,则选择多路复用器输出 `4` 。 + +:::note +`setup_adc_sampler!` 中的所有多路复用器定义必须具有相同数量的选择引脚。如果您的多路复用器具有不同数量的选择引脚,则可以使用 `No` 填充较小的多路复用器,直到定义具有相同数量的选择引脚。 +::: + +:::note +请注意,`setup_adc_sampler!` 宏的参数将取决于您构建的平台。检查 API 参考以获取需要调用的特定参数 `setup_adc_sampler!` +::: + +`build_analog_matrix!` 提供的矩阵有两个用途: + +- 定义从矩阵位置(行、列)到模拟引脚索引和多路复用器输出(如果适用)的映射。 +- 定义模拟源可以从 ADC 过程生成的可能值范围。 + +当我们查看矩阵的第 0 行、第 0 列时,我们发现: + +- 它对应于 ADC 引脚 `0` (连接到多路复用器 `PA2` )和多路复用器输出 `0` (当选择引脚 `PA3` 和 `PA4` 设置为低)。 +- ADC 预计会产生范围从 `3040` 到 `4080` 的值。 + +对于矩阵的第 1 行第 0 列,我们发现: + +- 它对应于 ADC 引脚 `1` (通过 `PA5` 直接连接到模拟源)。 `(1,0)` 中的 `0` 被忽略,因为它没有连接到多路复用器。 +- ADC 预计会产生范围从 `3040` 到 `4080` 的值。 + +请注意,未使用的矩阵位置由 `No` 表示。 + +# 重新可视化矩阵(例如双工矩阵) + +有时,您的键盘可能具有复杂的矩阵方案,这可能会导致您难以阅读部分配置。 + +例如,某些键盘使用“双工矩阵”来节省 MCU 引脚。这通常是通过使电气列跨越两个物理列并通过每个物理行使用两个电气行来实现的。 + +这是双工矩阵的示例部分: + +![image](https://github.com/Univa/rumcake/assets/41708691/96d35331-ee9d-4be0-990c-64aaed083c3d) + +正如您可以想象的那样,这将很难在您的固件代码中进行跟踪。 + +因此,`rumcake` 包含一个 `remap_matrix` 宏来帮助“重新可视化”矩阵,使其看起来更具可读性。它创建一个 `remap` 宏供您在需要您配置类似于矩阵的代码部分中使用。 + +这对于您的键盘布局配置或背光矩阵配置很有用: + + +```rust del={52-65} ins={1-26,66-77} +// 这将创建一个 `remap!` 宏,您可以在配置的其他部分使用它。 +remap_matrix! { + // 它的行数和列数与您在矩阵中指定的相同。 + // 请注意,`No` 用于表示未使用的矩阵位置。 + original: { + [ K00 K01 K02 K03 K04 K05 K06 K07 ] + [ K08 K09 K10 K11 K12 K13 K14 No ] + [ K15 K16 K17 K18 K19 K20 K21 K22 ] + [ K23 K24 K25 K26 K27 K28 K29 No ] + [ K30 K31 K32 K33 K34 K35 K36 K37 ] + [ K38 K39 K40 K41 K42 K43 K44 No ] + [ K45 K46 K47 K48 K49 K50 K51 K52 ] + [ K53 K54 K55 K56 K57 K58 K59 No ] + [ K60 K61 K62 K63 K64 K65 K66 K67 ] + [ No No No No No K68 K69 No ] + }, + + // 这可以是你想要的任何样子。让它看起来像你的物理布局! + remapped: { + [ K00 K08 K01 K09 K02 K10 K03 K11 K04 K12 K05 K13 K06 K14 K07 K22 ] + [ K15 K23 K16 K24 K17 K25 K18 K26 K19 K27 K20 K28 K21 K29 K37 ] + [ K30 K38 K31 K39 K32 K40 K33 K41 K34 K42 K35 K43 K36 K44 K52 ] + [ K45 K53 K46 K54 K47 K55 K48 K56 K49 K57 K50 K58 K51 K59 K67 ] + [ K60 K61 K62 K63 K64 K65 K68 K66 K69 ] + } +} + +use rumcake::keyboard; + +#[keyboard(usb)] +pub struct MyKeyboard; + +use rumcake::keyboard::Keyboard; +impl Keyboard for MyKeyboard { + const MANUFACTURER: &'static str = "Me"; + const PRODUCT: &'static str = "MyKeyboard"; + const SERIAL_NUMBER: &'static str = "1"; +} + +use rumcake::keyboard::{build_standard_matrix, KeyboardMatrix}; +impl KeyboardMatrix for MyKeyboard { + type Layout = Self; + + build_standard_matrix! { + rows: [ PB3 PB4 PA15 PB5 PA0 PA1 PB2 PB10 PB11 PA3 ], + cols: [ PB12 PB1 PB0 PA7 PA6 PA5 PA4 PA2 ] + } +} + +use rumcake::keyboard::{build_layout, KeyboardLayout}; +impl KeyboardLayout for MyKeyboard { + build_layout! { // 不使用 remap! + { + [ Escape 2 4 6 8 0 = Delete ] + [ 1 3 5 7 9 - '\\' No ] + [ Tab W R Y I P ']' Home ] + [ Q E T U O '[' BSpace No ] + [ LCtrl S F H K ; No PgUp ] + [ A D G J L '\'' Enter No ] + [ LShift Z C B M . Up PgDown ] + [ No X V N , / No No ] + [ LGui LAlt Space Space RAlt No Down End ] + [ No No No No No Left Right No ] + } + } + // 使用 `remap!` 创建键盘布局 + remap! { + build_layout! { + { + [ Escape 1 2 3 4 5 6 7 8 9 0 - = '\\' Delete Home ] + [ Tab Q W E R T Y U I O P '[' ']' BSpace PgUp ] + [ LCtrl A S D F G H J K L ; '\'' No Enter PgDown ] + [ LShift No Z X C V B N M , . / Up No End ] + [ LGui LAlt Space Space RAlt No Left Down Right ] + } + } + } +} +``` diff --git a/docs/src/content/docs/zh-cn/getting-started/setup-template.md b/docs/src/content/docs/zh-cn/getting-started/setup-template.md new file mode 100644 index 0000000..9b969cb --- /dev/null +++ b/docs/src/content/docs/zh-cn/getting-started/setup-template.md @@ -0,0 +1,49 @@ +--- +title: Setup - 选择一个模板 +description: 如何使用模板配置你的Cargo工作区。 +next: + label: 矩阵与布局 + link: ../matrix-and-layout/ +sidebar: + order: 1 +--- + +开始使用 `rumcake` 的最简单方法是使用提供的模板之一。 + +[请在继续之前查阅模板存储库中的 README.md 以了解每个模板。](https://github.com/Univa/rumcake-templates) + +# 克隆模板 + +要从模板开始,您必须安装 [cargo-generate](https://github.com/cargo-generate/cargo-generate#quickstart), +然后运行以下命令来选择模板: + +````bash +cargo generate --git https://github.com/Univa/rumcake-templates +```` + +## 模板结构 + +一般来说,`rumcake` 模板提供以下内容: + +- `.cargo/config.toml` 文件,用于配置您的 Cargo 运行程序(使用 [`probe-rs`](https://probe.rs/)),指定您的芯片。 +- `Cargo.toml` 文件,其中已经包含编译固件所需的依赖项和功能标志。 + - 对于 `rumcake` ,除了其他额外功能外,还将启用与所选芯片相对应的功能标志。 +- `src/main.rs` 文件,其中包含部分完成的 `rumcake` 键盘实现。 +- `README.md` 文件,其中包含有关如何编译固件并将其刷写到芯片的信息。 +- `rust-toolchain.toml` 文件,包含有关将使用的 Rust 工具链的信息 + 用于您的 Cargo 工作区,包括芯片和工具链版本的构建目标。 +- `memory.x` 文件,由 [`cortex-m-rt`](https://docs.rs/cortex-m-rt/latest/cortex_m_rt/#memoryx) 使用,定义目标的内存布局 芯片。 + +要了解如何向键盘添加额外功能,请参阅[模板](https://github.com/Univa/rumcake-templates)或参阅侧栏中的“功能”部分。 + +:::note +有些模板有额外的文件。 例如,`rumcake-basic-template` 有一个构建脚本来生成 Vial 定义。 `rumcake-split-template` 在 `src/` 中有多个入口,左半部分和右半部分各一个,需要单独刷写。 + +有关上面未列出的任何内容的更多信息,请参阅相应模板的 `README.md` 文件。 +::: + +# 下一步 + +完成克隆模板后,请继续设置键盘矩阵和布局。 + +根据所选模板的不同,在编译和刷写固件之前,您还需要搜索要处理的 `// TODO` 注释。 \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/index.md b/docs/src/content/docs/zh-cn/index.md new file mode 100644 index 0000000..c340b5d --- /dev/null +++ b/docs/src/content/docs/zh-cn/index.md @@ -0,0 +1,90 @@ +--- +title: rumcake +description: 开始在键盘上使用 rumcake 固件。 +template: doc +hero: + tagline: 一个基于 rust 的键盘固件。 + actions: + - text: 开始 + link: getting-started/setup-template/ + icon: right-arrow + variant: primary + - text: 阅读 API 文档 + link: api/ + icon: external +--- + +:::caution +rumcake 仍处于 WIP 中。 预计会出现一些错误和破坏性更改。 +::: + +`rumcake` 是一个 Rust 库,可让您轻松构建功能强大的键盘固件。 +在底层, `rumcake` 使用 [`embassy-rs`](https://github.com/embassy-rs/embassy) 作为嵌入式框架。 +提供 `rumcake` 作为库允许您在自己的 Cargo 工作区中构建固件,而无需将代码推送到中央 `rumcake` 存储库。 + +`rumcake` 库: + +- 为常见键盘活动提供 `embassy-executor` 任务,包括矩阵轮询、主机通信、LED 渲染等。 +- 提供宏,允许您以易于理解的方式配置键盘固件。 [`keyberon`](https://github.com/TeXitoi/keyberon) 也用于键盘布局配置。 +- 目标是与平台无关,并在底层使用不同的 HAL(硬件抽象库),具体取决于您决定构建的芯片。 + +# 支持的最低 Rust 版本 + +`rumcake` 使用了一些只存在于 `nightly` 工具链的功能. +当你编译你的固件时,请使用最新的 nightly 工具链。 + +# MCUs + +请注意,构建和刷写指令可能会根据 MCU 的不同而变化。 +请参阅[模板](https://github.com/Univa/rumcake-templates)了解一些常见设置的构建以及刷写说明。 + +## 已测试的MCU + +- STM32F072CBx +- STM32F303CBx +- nRF52840 (使用 nice!nano v2 测试) +- RP2040 + +# 特性 + +## 可用的 + +以下功能 _可用_ ,但可能不稳定或缺少组件。 + +- USB通讯 +- 蓝牙通讯 (只适用于 nRF-based 键盘) +- 背光灯(Backlighting) +- 轴灯(Underglow) +- 分体键盘 +- 显示(e.g. SSD1306) +- 存储(Storage) +- Via/Vial +- 媒体键(Media keys) +- 编码器(Encoders) + +# 为什么叫 "rumcake" + +"**RU**st **M**e**C**h**A**nical **KE**yboard" + +# 致谢 + +如果没有其他社区项目所做的工作,这个固件是不可能实现的。 + +非常感谢以下项目: + +- [QMK](https://github.com/qmk/qmk_firmware) + - A lot of backlighting and underglow animations have been adapted from QMK. + - WS2812 Bitbang driver is also loosely based on their implementation. +- [ZMK](https://github.com/zmkfirmware/zmk/) + - Their existing bluetooth, and split keyboard implementations have been helpful references for rumcake's implementation +- [TeXitoi's `keyberon` crate](https://github.com/TeXitoi/keyberon) + - For powering the logic for keyboard matrix and layouts +- [jtroo's `keyberon` fork](https://github.com/jtroo/kanata/tree/main/keyberon) + - For the implementation of extra layout actions, like one shot and tap dance keys +- [riskable and borisfaure](https://github.com/TeXitoi/keyberon/pull/122) + - For the implementation of sequences/macros in `keyberon` +- [simmsb's corne firmware](https://github.com/simmsb/keyboard) + - Very helpful reference for developing a keyboard firmware using [embassy-rs](https://github.com/embassy-rs/embassy) +- [TeXitoi's keyseebee project](https://github.com/TeXitoi/keyseebee) + - Another helpful reference for a rust-based keyboard firmware +- Any dependency used by rumcake. Building this would be a lot more difficult without them!