分体键盘
分体键盘由一个或多个外围设备组成,这些设备向一个中央设备通信以传输矩阵事件,然后该中央设备创建 HID 键盘报告发送到主机设备。
通常,分体键盘需要编译多个二进制文件,每个设备/分体键盘的一部分一个二进制文件。例如,您将需要一个左半部分的二进制文件,以及一个右半部分的二进制文件。
继续阅读以了解如何使用 rumcake
实现“中央”和“外围”设备。
示例
以下文档将展示一个左右分体键盘的示例,无需配对设备。
中央设备的代码将放置在 left.rs
中,外围设备的代码将放置在 right.rs
中。
要查看如何实现分体键盘的完整示例,请查看模板仓库。
中央设备设置
分体键盘设置中的“中央”设备定义了键盘布局,与主机设备通信,并从其他外围设备接收矩阵事件。应该只有一个中央设备。 如果分体键盘还使用额外功能,如背光或底部发光,则中央设备还负责将其相关命令发送到外围设备。
通常,中央设备可以是一个配对设备(有助于节省电池寿命),或者是键盘的一半。
中央设备所需的 Cargo 特性
您必须使用以下 rumcake
特性编译一个二进制文件:
split-central
- 您希望使用的可用驱动程序的特性标志
中央设备所需的代码
要设置中央设备,您必须在 #[keyboard]
宏调用中添加 split_central(driver_setup_fn = <setup_fn>)
,
并且您的键盘必须实现 CentralDevice
特性。您的 CentralDevice
实现应包括 type Layout = Self;
。
这将告诉 rumcake 将矩阵事件(从其他外围设备接收)重定向到布局,以处理为按键码。
driver_setup_fn
必须是一个没有参数并返回实现 CentralDeviceDriver
特性的类型的异步函数。
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;}
最后,您必须设置驱动程序。为此,您需要完成您的 driver_setup_fn
,通过构建驱动程序来完成。您可以查看所选驱动程序的 API 参考以获得设置函数或宏以使此过程更轻松的信息。
根据驱动程序,您可能还需要在 #[keyboard]
宏中实现对应于所选驱动程序的适当特性。
查看可用驱动程序以获取此信息。
例如,使用 SerialSplitDriver
结构,您可以像这样构造它:
// KeyboardLayout should already be implementeduse 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;}
外围设备设置
分体键盘设置中的“外围”设备具有开关矩阵,并将矩阵事件发送到中央设备。一个分体键盘设置可以有多个外围设备。 如果分体键盘还使用了额外功能,则所有外围设备都应从中央设备接收相关命令。
外围设备的 Cargo 特性
您必须使用以下 rumcake
特性编译一个二进制文件:
split-peripheral
- 您希望使用的可用驱动程序的特性标志
外围设备的必需代码
要设置外围设备,您必须在 #[keyboard]
宏调用中添加 split_peripheral(driver_setup_fn = <setup_fn>)
,
并且您的键盘必须实现 PeripheralDevice
特性。您的 KeyboardMatrix
实现(应该已经实现)应包括 type PeripheralDeviceType = Self
。
这将告诉 rumcake 将矩阵事件重定向到外围设备驱动程序,以发送到中央设备。
driver_setup_fn
必须是一个没有参数并返回实现 PeripheralDeviceDriver
特性的类型的异步函数。
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 {}
最后,您必须设置驱动程序。为此,您需要完成您的 driver_setup_fn
,通过构建驱动程序来完成。您可以查看所选驱动程序的 API 参考以获得设置函数或宏以使此过程更轻松的信息。
根据驱动程序,您可能还需要在 #[keyboard]
宏中实现对应于所选驱动程序的适当特性。
查看可用驱动程序以获取此信息。
例如,使用 SerialSplitDriver
结构,您可以像这样构造它:
// KeyboardLayout should already be implementeduse 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 {}
无矩阵的中央设备(Dongle)
没有矩阵的中央设备的一个示例是一个 dongle。如果您想要实现这样的设备,您可以在您的 #[keyboard]
宏调用中添加 no_matrix
。
这样做将消除实现 KeyboardMatrix
的需要,因此您只需实现 KeyboardLayout
。
use rumcake::keyboard;
#[keyboard( // 在键盘宏调用中的某处 ... no_matrix, split_central( driver = "ble" // TODO: 更改为您所需的分割驱动程序,并实现适当的特性 ))]struct MyKeyboardDongle;
// 其余的配置 ...
nRF-BLE 驱动程序
如果您使用的是 nRF5x MCU,并希望使用 BLE 进行分体键盘通信,则需要进行额外的更改才能使其正常工作。
对于中央设备和外围设备,都必须实现 BluetoothDevice
特性:
BLUETOOTH_ADDRESS
可以是任何您想要的值,只要它是有效的“随机静态”蓝牙地址。
参见这里的“Random Static Address”:https://novelbits.io/bluetooth-address-privacy-ble/
// 中央文件use rumcake::hw::platform::BluetoothDevice;impl BluetoothDevice for MyKeyboardLeftHalf { const BLUETOOTH_ADDRESS: [u8; 6] = [0x41, 0x5A, 0xE3, 0x1E, 0x83, 0xE7]; // TODO: 更改为其他值}
// 外围文件use rumcake::hw::platform::BluetoothDevice;impl BluetoothDevice for MyKeyboardRightHalf { const BLUETOOTH_ADDRESS: [u8; 6] = [0x92, 0x32, 0x98, 0xC7, 0xF6, 0xF8]; // TODO: 更改为其他值}
您还需要更改 #[keyboard]
宏调用以添加 driver_type = "nrf-ble"
。
这将更改 driver_setup_fn
的签名要求。
// 中央文件#[keyboard( // 在键盘宏调用中的某处 ... split_central( driver_setup_fn = my_central_setup, driver_type = "nrf-ble" ))]struct MyKeyboardLeftHalf;
// 外围文件#[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
。
// 中央文件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] // 我们在外围设备文件中指定的外围设备地址 ] }}
// 外围文件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 驱动程序
可用驱动程序
名称 | 特性标志 | 必需特性 |
---|---|---|
Serial1 | 无(默认可用) | 无 |
nRF Bluetooth LE | nrf-ble | BluetoothDevice |
Footnotes
-
兼容任何同时实现
embedded_io_async::Read
和embedded_io_async::Write
的类型。 这包括embassy_nrf::buffered_uarte::BufferedUarte
(nRF UARTE)和embassy_stm32::usart::BufferedUart
(STM32 UART)。 ↩