Merge branch 'main' into battery-report-ble-config-2

This commit is contained in:
ReFil 2023-11-15 18:01:11 +00:00
commit 0267e15f1a
84 changed files with 1402 additions and 153 deletions

View file

@ -91,10 +91,17 @@ menu "Output Types"
config ZMK_USB config ZMK_USB
bool "USB" bool "USB"
depends on (!ZMK_SPLIT || (ZMK_SPLIT && ZMK_SPLIT_ROLE_CENTRAL))
select USB select USB
select USB_DEVICE_STACK select USB_DEVICE_STACK
select USB_DEVICE_HID select USB_DEVICE_HID
config ZMK_USB_BOOT
bool "USB Boot Protocol Support"
depends on ZMK_USB
select USB_HID_BOOT_PROTOCOL
select USB_DEVICE_SOF
if ZMK_USB if ZMK_USB
config USB_NUMOF_EP_WRITE_RETRIES config USB_NUMOF_EP_WRITE_RETRIES
@ -575,4 +582,3 @@ osource "$(ZMK_CONFIG)/boards/shields/*/Kconfig.shield"
source "Kconfig.zephyr" source "Kconfig.zephyr"

View file

@ -11,9 +11,6 @@ config BOARD
config ZMK_KEYBOARD_NAME config ZMK_KEYBOARD_NAME
default "BDN9 Rev2" default "BDN9 Rev2"
config ZMK_USB
default y
config ZMK_RGB_UNDERGLOW config ZMK_RGB_UNDERGLOW
select SPI select SPI
select WS2812_STRIP select WS2812_STRIP

View file

@ -23,3 +23,4 @@ CONFIG_HEAP_MEM_POOL_SIZE=1024
# clock configuration # clock configuration
CONFIG_CLOCK_CONTROL=y CONFIG_CLOCK_CONTROL=y
CONFIG_ZMK_USB=y

View file

@ -18,10 +18,4 @@ endif # USB_DEVICE_STACK
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
endif # BOARD_BLUEMICRO840_V1 endif # BOARD_BLUEMICRO840_V1

View file

@ -21,3 +21,6 @@ CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -19,12 +19,6 @@ endif # USB
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
config ZMK_KEYBOARD_NAME config ZMK_KEYBOARD_NAME
default "BT60" default "BT60"

View file

@ -23,3 +23,6 @@ CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -23,3 +23,6 @@ CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -25,10 +25,4 @@ endif # USB
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
endif # BOARD_BT60_V2 || BOARD_BT65_V1 || BOARD_BT75_V1 endif # BOARD_BT60_V2 || BOARD_BT65_V1 || BOARD_BT75_V1

View file

@ -36,3 +36,6 @@ CONFIG_WS2812_STRIP=y
CONFIG_SPI=y CONFIG_SPI=y
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -36,3 +36,6 @@ CONFIG_WS2812_STRIP=y
CONFIG_SPI=y CONFIG_SPI=y
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -36,3 +36,6 @@ CONFIG_WS2812_STRIP=y
CONFIG_SPI=y CONFIG_SPI=y
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -25,12 +25,6 @@ config ZMK_SPLIT
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
if USB if USB
config USB_NRFX config USB_NRFX

View file

@ -39,6 +39,9 @@ CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_30PPM=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_30PPM=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y
# enable display drivers # enable display drivers
CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED=y CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED=y
CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_STACK_SIZE=2048 CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_STACK_SIZE=2048

View file

@ -39,6 +39,9 @@ CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_30PPM=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_30PPM=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y
# enable display drivers # enable display drivers
CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED=y CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED=y
CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_STACK_SIZE=2048 CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_STACK_SIZE=2048

View file

@ -35,6 +35,9 @@ CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_30PPM=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_30PPM=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y
# enable display drivers # enable display drivers
CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED=y CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED=y
CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_STACK_SIZE=2048 CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_STACK_SIZE=2048

View file

@ -35,6 +35,9 @@ CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_30PPM=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_30PPM=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y
# enable display drivers # enable display drivers
CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED=y CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED=y
CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_STACK_SIZE=2048 CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_STACK_SIZE=2048

View file

@ -8,7 +8,4 @@ if BOARD_DZ60RGB_REV1
config ZMK_KEYBOARD_NAME config ZMK_KEYBOARD_NAME
default "DZ60RGB Rev 1" default "DZ60RGB Rev 1"
config ZMK_USB
default y
endif # BOARD_DZ60RGB_REV1 endif # BOARD_DZ60RGB_REV1

View file

@ -25,3 +25,5 @@ CONFIG_CLOCK_STM32_PLL_MULTIPLIER=9
CONFIG_CLOCK_STM32_AHB_PRESCALER=1 CONFIG_CLOCK_STM32_AHB_PRESCALER=1
CONFIG_CLOCK_STM32_APB1_PRESCALER=2 CONFIG_CLOCK_STM32_APB1_PRESCALER=2
CONFIG_CLOCK_STM32_APB2_PRESCALER=1 CONFIG_CLOCK_STM32_APB2_PRESCALER=1
CONFIG_ZMK_USB=y

View file

@ -11,9 +11,6 @@ config BOARD
config ZMK_KEYBOARD_NAME config ZMK_KEYBOARD_NAME
default "Ferris rev 0.2" default "Ferris rev 0.2"
config ZMK_USB
default y
config ZMK_KSCAN_MATRIX_POLLING config ZMK_KSCAN_MATRIX_POLLING
default y default y

View file

@ -0,0 +1,3 @@
zephyr_library()
zephyr_library_sources(usb_serial_number.c)
zephyr_library_include_directories(${ZEPHYR_BASE}/drivers)

View file

@ -0,0 +1,8 @@
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
config BOARD_ENABLE_DCDC
bool "Enable DCDC mode"
select SOC_DCDC_NRF52X
default y
depends on (BOARD_GLOVE80_LH || BOARD_GLOVE80_RH)

View file

@ -0,0 +1,10 @@
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
config BOARD_GLOVE80_LH
bool "Glove80 LH"
depends on SOC_NRF52840_QIAA
config BOARD_GLOVE80_RH
bool "Glove80 RH"
depends on SOC_NRF52840_QIAA

View file

@ -0,0 +1,65 @@
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
if BOARD_GLOVE80_LH
config BOARD
default "glove80 lh"
config ZMK_SPLIT_BLE_ROLE_CENTRAL
default y
endif # BOARD_GLOVE80_LH
if BOARD_GLOVE80_RH
config BOARD
default "glove80 rh"
endif # BOARD_GLOVE80_RH
if BOARD_GLOVE80_LH || BOARD_GLOVE80_RH
config ZMK_SPLIT
default y
config BT_CTLR
default BT
config ZMK_KSCAN_MATRIX_WAIT_BETWEEN_OUTPUTS
default 5
config PINCTRL
default y
if USB
config USB_NRFX
default y
config USB_DEVICE_STACK
default y
endif # USB
if ZMK_BACKLIGHT
config PWM
default y
config LED_PWM
default y
endif # ZMK_BACKLIGHT
if ZMK_RGB_UNDERGLOW
config SPI
default y
config WS2812_STRIP
default y
endif # ZMK_RGB_UNDERGLOW
endif # BOARD_GLOVE80_LH || BOARD_GLOVE80_RH

View file

@ -0,0 +1,6 @@
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)

View file

@ -0,0 +1,107 @@
/*
* Copyright (c) 2021 The ZMK Contributors
* SPDX-License-Identifier: MIT
*/
/dts-v1/;
#include <nordic/nrf52840_qiaa.dtsi>
#include <dt-bindings/zmk/matrix_transform.h>
/ {
chosen {
zmk,kscan = &kscan0;
zmk,matrix_transform = &default_transform;
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
};
default_transform: keymap_transform_0 {
compatible = "zmk,matrix-transform";
columns = <14>;
rows = <6>;
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13)
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,8) RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13)
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13)
RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12) RC(3,13)
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(0,6) RC(1,6) RC(2,6) RC(2,7) RC(1,7) RC(0,7) RC(4,8) RC(4,9) RC(4,10) RC(4,11) RC(4,12) RC(4,13)
RC(5,0) RC(5,1) RC(5,2) RC(5,3) RC(5,4) RC(3,6) RC(4,6) RC(5,6) RC(5,7) RC(4,7) RC(3,7) RC(5,9) RC(5,10) RC(5,11) RC(5,12) RC(5,13)
>;
};
kscan0: kscan {
compatible = "zmk,kscan-gpio-matrix";
label = "KSCAN";
diode-direction = "col2row";
debounce-press-ms = <4>;
debounce-release-ms = <20>;
};
};
&adc {
status = "okay";
};
&gpiote {
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_0";
};
};
&flash0 {
/*
* For more information, see:
* http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html
*/
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
sd_partition: partition@0 {
label = "softdevice";
reg = <0x00000000 0x00026000>;
};
code_partition: partition@26000 {
label = "code_partition";
reg = <0x00026000 0x000c6000>;
};
/*
* The flash starting at 0x000ec000 and ending at
* 0x000f3fff is reserved for use by the application.
*/
/*
* Storage partition will be used by FCB/LittleFS/NVS
* if enabled.
*/
storage_partition: partition@ec000 {
label = "storage";
reg = <0x000ec000 0x00008000>;
};
boot_partition: partition@f4000 {
label = "adafruit_boot";
reg = <0x000f4000 0x0000c000>;
};
};
};

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/bt.h>
#include <dt-bindings/zmk/ext_power.h>
#include <dt-bindings/zmk/outputs.h>
#include <dt-bindings/zmk/rgb.h>
// layers
#define DEFAULT 0
#define LOWER 1
#define MAGIC 2
/ {
behaviors {
// For the "layer" key, it'd nice to be able to use it as either a shift or a toggle.
// Configure it as a tap dance, so the first tap (or hold) is a &mo and the second tap is a &to
layer_td: tap_dance_0 {
compatible = "zmk,behavior-tap-dance";
label = "LAYER_TAP_DANCE";
#binding-cells = <0>;
tapping-term-ms = <200>;
bindings = <&mo LOWER>, <&to LOWER>;
};
};
macros {
bt_0: bt_profile_macro_0 {
label = "BT_0";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&out OUT_BLE>,
<&bt BT_SEL 0>;
};
bt_1: bt_profile_macro_1 {
label = "BT_1";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&out OUT_BLE>,
<&bt BT_SEL 1>;
};
bt_2: bt_profile_macro_2 {
label = "BT_2";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&out OUT_BLE>,
<&bt BT_SEL 2>;
};
bt_3: bt_profile_macro_3 {
label = "BT_3";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&out OUT_BLE>,
<&bt BT_SEL 3>;
};
};
keymap {
compatible = "zmk,keymap";
default_layer {
// ---------------------------------------------------------------------------------------------------------------------------------
// | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 |
// | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | - |
// | TAB | Q | W | E | R | T | | Y | U | I | O | P | \ |
// | ESC | A | S | D | F | G | | H | J | K | L | ; | ' |
// | ` | Z | X | C | V | B | LSHFT | LCTRL | LOWER | | LGUI | RCTRL | RSHFT | N | M | , | . | / | PGUP |
// | MAGIC | HOME| END | LEFT | RIGHT| | BSPC | DEL | LALT | | RALT | RET | SPACE | | UP | DOWN | [ | ] | PGDN |
bindings = <
&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10
&kp EQUAL &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
&kp ESC &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT
&kp GRAVE &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LCTRL &layer_td &kp LGUI &kp RCTRL &kp RSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp PG_UP
&mo MAGIC &kp HOME &kp END &kp LEFT &kp RIGHT &kp BSPC &kp DEL &kp LALT &kp RALT &kp RET &kp SPACE &kp UP &kp DOWN &kp LBKT &kp RBKT &kp PG_DN
>;
};
lower_layer {
bindings = <
&kp C_BRI_DN &kp C_BRI_UP &kp C_PREV &kp C_NEXT &kp C_PP &kp C_MUTE &kp C_VOL_DN &kp C_VOL_UP &none &kp PAUSE_BREAK
&trans &none &none &none &none &kp HOME &kp LPAR &kp KP_NUM &kp KP_EQUAL &kp KP_DIVIDE &kp KP_MULTIPLY &kp PSCRN
&trans &none &none &kp UP &none &kp END &kp RPAR &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_MINUS &kp SLCK
&trans &none &kp LEFT &kp DOWN &kp RIGHT &kp PG_UP &kp PRCNT &kp KP_N4 &kp KP_N5 &kp KP_N6 &kp KP_PLUS &none
&trans &kp K_CMENU &none &kp F11 &kp F12 &kp PG_DN &trans &trans &to DEFAULT &trans &trans &trans &kp COMMA &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_ENTER &trans
&trans &kp CAPS &kp INS &kp F11 &kp F12 &trans &trans &trans &trans &trans &trans &kp KP_N0 &kp KP_N0 &kp KP_DOT &kp KP_ENTER &trans
>;
};
magic_layer {
bindings = <
&bt BT_CLR &none &none &none &none &none &none &none &none &none
&none &none &none &none &none &none &none &none &none &none &none &none
&none &rgb_ug RGB_SPI &rgb_ug RGB_SAI &rgb_ug RGB_HUI &rgb_ug RGB_BRI &rgb_ug RGB_TOG &none &none &none &none &none &none
&bootloader &rgb_ug RGB_SPD &rgb_ug RGB_SAD &rgb_ug RGB_HUD &rgb_ug RGB_BRD &rgb_ug RGB_EFF &none &none &none &none &none &bootloader
&sys_reset &none &none &none &none &none &bt_2 &bt_3 &none &none &none &none &none &none &none &none &none &sys_reset
&none &none &none &none &none &bt_0 &bt_1 &out OUT_USB &none &none &none &none &none &none &none &none
>;
};
};
};

View file

@ -0,0 +1,19 @@
identifier: glove80
name: Glove80
url: https://www.moergo.com/
type: mcu
arch: arm
toolchain:
- zephyr
- gnuarmemb
- xtools
supported:
- adc
- usb_device
- ble
- ieee802154
- pwm
- watchdog
- gpio
- i2c
- spi

View file

@ -0,0 +1,16 @@
file_format: "1"
id: glove80
name: Glove80
type: board
arch: arm
url: https://www.moergo.com/
features:
- keys
- underglow
- backlight
outputs:
- usb
- ble
siblings:
- glove80_lh
- glove80_rh

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2021 The ZMK Contributors
* SPDX-License-Identifier: MIT
*/
&pinctrl {
spi3_default: spi3_default {
group1 {
psels = <NRF_PSEL(SPIM_MOSI, 0, 27)>; // WS2812_VEXT_DATA
};
};
spi3_sleep: spi3_sleep {
group1 {
psels = <NRF_PSEL(SPIM_MOSI, 0, 27)>;
low-power-enable;
};
};
pwm0_default: pwm0_default {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 1, 15)>; // rear LED
};
};
pwm0_sleep: pwm0_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 1, 15)>;
bias-pull-down;
};
};
uart0_default: uart0_default {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 22)>, // EXT1
<NRF_PSEL(UART_RX, 0, 21)>; // EXT2
};
};
uart0_sleep: uart0_sleep {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 22)>,
<NRF_PSEL(UART_RX, 0, 21)>;
low-power-enable;
};
};
};

View file

@ -0,0 +1,101 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include "glove80.dtsi"
#include "glove80_lh-pinctrl.dtsi"
#include <dt-bindings/led/led.h>
/ {
model = "glove80_lh";
compatible = "glove80_lh";
chosen {
zmk,underglow = &led_strip;
zmk,backlight = &back_led_backlight;
zmk,battery = &vbatt;
};
back_led_backlight: pwmleds {
compatible = "pwm-leds";
label = "BACK LED";
pwm_led_0 {
pwms = <&pwm0 0 PWM_USEC(20) PWM_POLARITY_NORMAL>;
label = "Back LED configured as backlight";
};
};
ext-power {
compatible = "zmk,ext-power-generic";
label = "EXT_POWER";
control-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; /* WS2812_CE */
init-delay-ms = <100>;
};
vbatt: vbatt {
compatible = "zmk,battery-nrf-vddh";
label = "BATTERY";
};
};
&spi3 {
compatible = "nordic,nrf-spim";
status = "okay";
pinctrl-0 = <&spi3_default>;
pinctrl-1 = <&spi3_sleep>;
pinctrl-names = "default", "sleep";
led_strip: ws2812@0 {
compatible = "worldsemi,ws2812-spi";
label = "WS2812C-2020";
/* SPI */
reg = <0>; /* ignored, but necessary for SPI bindings */
spi-max-frequency = <4000000>;
/* WS2812 */
chain-length = <40>; /* 40 keys have underglow at the moment */
spi-one-frame = <0x70>;
spi-zero-frame = <0x40>;
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
};
};
&pwm0 {
status = "okay";
pinctrl-0 = <&pwm0_default>;
pinctrl-1 = <&pwm0_sleep>;
pinctrl-names = "default", "sleep";
};
&uart0 {
compatible = "nordic,nrf-uarte";
pinctrl-0 = <&uart0_default>;
pinctrl-1 = <&uart0_sleep>;
pinctrl-names = "default", "sleep";
};
&kscan0 {
row-gpios
= <&gpio0 26 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW1
, <&gpio0 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW2
, <&gpio0 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW3
, <&gpio0 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW4
, <&gpio0 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW5
, <&gpio1 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // LH ROW6
;
col-gpios
= <&gpio1 8 GPIO_ACTIVE_HIGH> // LH COL6
, <&gpio1 4 GPIO_ACTIVE_HIGH> // LH COL5
, <&gpio1 6 GPIO_ACTIVE_HIGH> // LH COL4
, <&gpio1 7 GPIO_ACTIVE_HIGH> // LH COL3
, <&gpio1 5 GPIO_ACTIVE_HIGH> // LH COL2
, <&gpio1 3 GPIO_ACTIVE_HIGH> // LH COL1
, <&gpio1 1 GPIO_ACTIVE_HIGH> // LH Thumb
;
};

View file

@ -0,0 +1,7 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include "glove80.keymap"

View file

@ -0,0 +1,92 @@
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
CONFIG_SOC_SERIES_NRF52X=y
CONFIG_SOC_NRF52840_QIAA=y
CONFIG_BOARD_GLOVE80_LH=y
# Enable both USB and BLE
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y
# Keyboard IDs
CONFIG_ZMK_KEYBOARD_NAME="Glove80 Left"
CONFIG_USB_DEVICE_PID=0x27db
CONFIG_USB_DEVICE_VID=0x16c0
CONFIG_USB_DEVICE_MANUFACTURER="MoErgo"
CONFIG_USB_DEVICE_SN="moergo.com:GLV80-0123456789ABCDEF"
CONFIG_BT_DIS_PNP_PID=0x27db
CONFIG_BT_DIS_PNP_VID=0x16c0
CONFIG_BT_DIS_MANUF="MoErgo"
CONFIG_BT_DIS_MODEL="Glove80"
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
# Work-around for Windows bug with battery notifications
CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n
# Enable MPU
CONFIG_ARM_MPU=y
# Enable GPIO
CONFIG_GPIO=y
# Build configurations
CONFIG_BUILD_OUTPUT_UF2=y
CONFIG_BUILD_OUTPUT_UF2_FAMILY_ID="0x9807B007"
CONFIG_USE_DT_CODE_PARTITION=y
# Flash configuration
CONFIG_MPU_ALLOW_FLASH_WRITE=y
CONFIG_NVS=y
CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
# Enable 32kHz crystal
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
# Enable RGB underglow
CONFIG_ZMK_RGB_UNDERGLOW=y
CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER=y
CONFIG_ZMK_RGB_UNDERGLOW_ON_START=n
CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP=4
CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN=4
# DO NOT CHANGE CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX TO ABOVE 80. Configuring
# BRT_MAX above 80% will draw additional current and can potentially damage your
# computer. WARRANTY IS VOID IF BRT_MAX SET ABOVE 80.
CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX=80
CONFIG_ZMK_RGB_UNDERGLOW_EFF_START=3
CONFIG_ZMK_RGB_UNDERGLOW_HUE_START=285
CONFIG_ZMK_RGB_UNDERGLOW_SAT_START=75
CONFIG_ZMK_RGB_UNDERGLOW_BRT_START=16
# The power LED is implemented as a backlight
# For now, the power LED is acting as a "USB connected" indicator
CONFIG_ZMK_BACKLIGHT=y
CONFIG_ZMK_BACKLIGHT_ON_START=y
CONFIG_ZMK_BACKLIGHT_BRT_START=5
CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE=y
CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB=y
# The full two-byte consumer report space has compatibility issues with some
# operating systems, most notably macOS. Use the more basic single-byte usage
# space.
CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y
# Turn on debugging to disable optimization. Debug messages can result in larger
# stacks, so enable stack protection and particularly a larger BLE peripheral stack.
# CONFIG_DEBUG=y
# CONFIG_DEBUG_THREAD_INFO=y
# CONFIG_EXCEPTION_STACK_TRACE=y
# CONFIG_HW_STACK_PROTECTION=y
# CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE=1300
# Log via USB or Segger RTT
CONFIG_ZMK_USB_LOGGING=n
CONFIG_ZMK_RTT_LOGGING=n

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2021 The ZMK Contributors
* SPDX-License-Identifier: MIT
*/
&pinctrl {
spi3_default: spi3_default {
group1 {
psels = <NRF_PSEL(SPIM_MOSI, 0, 13)>; // WS2812_VEXT_DATA
};
};
spi3_sleep: spi3_sleep {
group1 {
psels = <NRF_PSEL(SPIM_MOSI, 0, 13)>;
low-power-enable;
};
};
pwm0_default: pwm0_default {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 16)>; // Rear LED
};
};
pwm0_sleep: pwm0_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 16)>;
bias-pull-down;
};
};
uart0_default: uart0_default {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 21)>, // EXT1
<NRF_PSEL(UART_RX, 0, 24)>; // EXT2
};
};
uart0_sleep: uart0_sleep {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 21)>,
<NRF_PSEL(UART_RX, 0, 24)>;
low-power-enable;
};
};
};

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include "glove80.dtsi"
#include "glove80_rh-pinctrl.dtsi"
#include <dt-bindings/led/led.h>
/ {
model = "glove80_rh";
compatible = "glove80_rh";
chosen {
zmk,underglow = &led_strip;
zmk,backlight = &back_led_backlight;
zmk,battery = &vbatt;
};
back_led_backlight: pwmleds {
compatible = "pwm-leds";
label = "BACK LED";
pwm_led_0 {
pwms = <&pwm0 0 PWM_USEC(20) PWM_POLARITY_NORMAL>;
label = "Back LED configured as backlight";
};
};
ext-power {
compatible = "zmk,ext-power-generic";
label = "EXT_POWER";
control-gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>; /* WS2812_CE */
init-delay-ms = <100>;
};
vbatt: vbatt {
compatible = "zmk,battery-nrf-vddh";
label = "BATTERY";
};
};
&spi3 {
compatible = "nordic,nrf-spim";
status = "okay";
pinctrl-0 = <&spi3_default>;
pinctrl-1 = <&spi3_sleep>;
pinctrl-names = "default", "sleep";
led_strip: ws2812@0 {
compatible = "worldsemi,ws2812-spi";
label = "WS2812C-2020";
/* SPI */
reg = <0>; /* ignored, but necessary for SPI bindings */
spi-max-frequency = <4000000>;
/* WS2812 */
chain-length = <40>; /* 40 keys have underglow at the moment */
spi-one-frame = <0x70>;
spi-zero-frame = <0x40>;
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
};
};
&pwm0 {
status = "okay";
pinctrl-0 = <&pwm0_default>;
pinctrl-1 = <&pwm0_sleep>;
pinctrl-names = "default", "sleep";
};
&uart0 {
compatible = "nordic,nrf-uarte";
pinctrl-0 = <&uart0_default>;
pinctrl-1 = <&uart0_sleep>;
pinctrl-names = "default", "sleep";
};
/* For right hand, the columns are offset by 7 */
&default_transform {
col-offset = <7>;
};
&kscan0 {
row-gpios
= <&gpio0 26 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW1
, <&gpio0 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW2
, <&gpio0 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW3
, <&gpio1 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW4
, <&gpio0 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW5
, <&gpio0 12 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // RH ROW6
;
col-gpios
= <&gpio1 6 GPIO_ACTIVE_HIGH> // RH Thumb
, <&gpio1 4 GPIO_ACTIVE_HIGH> // RH COL1
, <&gpio0 2 GPIO_ACTIVE_HIGH> // RH COL2
, <&gpio1 7 GPIO_ACTIVE_HIGH> // RH COL3
, <&gpio1 5 GPIO_ACTIVE_HIGH> // RH COL4
, <&gpio1 3 GPIO_ACTIVE_HIGH> // RH COL5
, <&gpio1 1 GPIO_ACTIVE_HIGH> // RH COL6
;
};

View file

@ -0,0 +1,7 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include "glove80.keymap"

View file

@ -0,0 +1,89 @@
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
CONFIG_SOC_SERIES_NRF52X=y
CONFIG_SOC_NRF52840_QIAA=y
CONFIG_BOARD_GLOVE80_RH=y
# Enable both USB and BLE
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y
# Keyboard IDs
CONFIG_ZMK_KEYBOARD_NAME="Glove80 Right"
CONFIG_USB_DEVICE_PID=0x27d9
CONFIG_USB_DEVICE_VID=0x16c0
CONFIG_USB_DEVICE_MANUFACTURER="MoErgo"
CONFIG_USB_DEVICE_SN="moergo.com:GLV80-0123456789ABCDEF"
CONFIG_BT_DIS_PNP_PID=0x27d9
CONFIG_BT_DIS_PNP_VID=0x16c0
CONFIG_BT_DIS_MANUF="MoErgo"
CONFIG_BT_DIS_MODEL="Glove80 Right"
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
# Enable MPU
CONFIG_ARM_MPU=y
# Enable GPIO
CONFIG_GPIO=y
# Build configurations
CONFIG_BUILD_OUTPUT_UF2=y
CONFIG_BUILD_OUTPUT_UF2_FAMILY_ID="0x9808B007"
CONFIG_USE_DT_CODE_PARTITION=y
# Flash configuration
CONFIG_MPU_ALLOW_FLASH_WRITE=y
CONFIG_NVS=y
CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
# Enable 32kHz crystal
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
# Enable RGB underglow
CONFIG_ZMK_RGB_UNDERGLOW=y
CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER=y
CONFIG_ZMK_RGB_UNDERGLOW_ON_START=n
CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP=4
CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN=4
# DO NOT CHANGE CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX TO ABOVE 80. Configuring
# BRT_MAX above 80% will draw additional current and can potentially damage your
# computer. WARRANTY IS VOID IF BRT_MAX SET ABOVE 80.
CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX=80
CONFIG_ZMK_RGB_UNDERGLOW_EFF_START=3
CONFIG_ZMK_RGB_UNDERGLOW_HUE_START=285
CONFIG_ZMK_RGB_UNDERGLOW_SAT_START=75
CONFIG_ZMK_RGB_UNDERGLOW_BRT_START=16
# The power LED is implemented as a backlight
# For now, the power LED is acting as a "USB connected" indicator
CONFIG_ZMK_BACKLIGHT=y
CONFIG_ZMK_BACKLIGHT_ON_START=y
CONFIG_ZMK_BACKLIGHT_BRT_START=5
CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE=y
CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB=y
# The full two-byte consumer report space has compatibility issues with some
# operating systems, most notably macOS. Use the more basic single-byte usage
# space.
CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y
# Turn on debugging to disable optimization. Debug messages can result in larger
# stacks, so enable stack protection and particularly a larger BLE peripheral stack.
# CONFIG_DEBUG=y
# CONFIG_DEBUG_THREAD_INFO=y
# CONFIG_EXCEPTION_STACK_TRACE=y
# CONFIG_HW_STACK_PROTECTION=y
# CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE=1300
# Log via USB or Segger RTT
CONFIG_ZMK_USB_LOGGING=n
CONFIG_ZMK_RTT_LOGGING=n

View file

@ -0,0 +1,13 @@
## MoErgo Glove80
This board definition provides ZMK support for the [MoErgo Glove80](https://www.moergo.com)
keyboard.
MoErgo additionally offers a customized version of ZMK which adds additional functionality such as
RGB status indicators, available on GitHub at [moergo-sc/zmk](https://github.com/moergo-sc/zmk). The
MoErgo customized ZMK fork is regularly updated to include the latest changes from mainline ZMK, but
will not always be completely up-to-date. MoErgo also offers an online layout configurator and
firmware builder application using the customized fork at [my.glove80.com](https://my.glove80.com).
While mainline ZMK is expected to work well with Glove80, MoErgo only provides support for use of
their customized fork. Likewise, the ZMK community cannot directly provide support for MoErgo's fork.

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <string.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/drivers/hwinfo.h>
#include "usb_descriptor.h"
#define LOG_LEVEL CONFIG_USB_DEVICE_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(usb_descriptor);
int base16_encode(const uint8_t *data, int length, uint8_t *result, int bufSize);
uint8_t *usb_update_sn_string_descriptor(void) {
/*
* nrf52840 hwinfo returns a 64-bit hardware id. Glove80 uses this as a
* serial number, encoded as base16 into the last 16 characters of the
* CONFIG_USB_DEVICE_SN template. If insufficient template space is
* available, instead return the static serial number string.
*/
const uint8_t template_len = sizeof(CONFIG_USB_DEVICE_SN);
const uint8_t sn_len = 16;
if (template_len < sn_len + 1) {
LOG_DBG("Serial number template too short");
return CONFIG_USB_DEVICE_SN;
}
static uint8_t serial[sizeof(CONFIG_USB_DEVICE_SN)];
strncpy(serial, CONFIG_USB_DEVICE_SN, template_len);
uint8_t hwid[8];
memset(hwid, 0, sizeof(hwid));
uint8_t hwlen = hwinfo_get_device_id(hwid, sizeof(hwid));
if (hwlen > 0) {
const uint8_t offset = template_len - sn_len - 1;
LOG_HEXDUMP_DBG(&hwid, sn_len, "Serial Number");
base16_encode(hwid, hwlen, serial + offset, sn_len + 1);
}
return serial;
}
int base16_encode(const uint8_t *data, int length, uint8_t *result, int bufSize) {
const char hex[] = "0123456789ABCDEF";
int i = 0;
while (i < bufSize && i < length * 2) {
uint8_t nibble;
if (i % 2 == 0) {
nibble = data[i / 2] >> 4;
} else {
nibble = data[i / 2] & 0xF;
}
result[i] = hex[nibble];
++i;
}
if (i < bufSize) {
result[i] = '\0';
}
return i;
}

View file

@ -9,7 +9,4 @@ config ZMK_KEYBOARD_NAME
config RP2_FLASH_W25Q080 config RP2_FLASH_W25Q080
default y default y
config ZMK_USB
default y
endif # BOARD_KBDFANS_TOFU65_V2 endif # BOARD_KBDFANS_TOFU65_V2

View file

@ -18,3 +18,5 @@ CONFIG_USE_DT_CODE_PARTITION=y
# Output UF2 by default, native bootloader supports it. # Output UF2 by default, native bootloader supports it.
CONFIG_BUILD_OUTPUT_UF2=y CONFIG_BUILD_OUTPUT_UF2=y
CONFIG_ZMK_USB=y

View file

@ -21,12 +21,6 @@ endif # USB
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
config PINMUX config PINMUX
default y default y

View file

@ -21,3 +21,6 @@ CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -16,10 +16,4 @@ endif # USB_DEVICE_STACK
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
endif # BOARD_NICE60 endif # BOARD_NICE60

View file

@ -28,3 +28,7 @@ CONFIG_WS2812_STRIP=y
CONFIG_ZMK_RGB_UNDERGLOW_HUE_START=160 CONFIG_ZMK_RGB_UNDERGLOW_HUE_START=160
CONFIG_ZMK_RGB_UNDERGLOW_EFF_START=3 CONFIG_ZMK_RGB_UNDERGLOW_EFF_START=3
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -16,10 +16,4 @@ endif # USB_DEVICE_STACK
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
endif # BOARD_NICE_NANO || BOARD_NICE_NANO_V2 endif # BOARD_NICE_NANO || BOARD_NICE_NANO_V2

View file

@ -22,3 +22,6 @@ CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -22,3 +22,6 @@ CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_ZMK_BLE=y
CONFIG_ZMK_USB=y

View file

@ -16,10 +16,4 @@ endif # USB_DEVICE_STACK
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
endif # BOARD_NRF52840_M2 endif # BOARD_NRF52840_M2

View file

@ -20,3 +20,6 @@ CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -18,12 +18,6 @@ endif # USB_DEVICE_STACK
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
config PINMUX config PINMUX
default y default y

View file

@ -23,3 +23,6 @@ CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF=y CONFIG_CLOCK_CONTROL_NRF=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -23,3 +23,6 @@ CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF=y CONFIG_CLOCK_CONTROL_NRF=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -23,3 +23,6 @@ CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF=y CONFIG_CLOCK_CONTROL_NRF=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -23,3 +23,6 @@ CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF=y CONFIG_CLOCK_CONTROL_NRF=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -16,10 +16,4 @@ endif # USB_DEVICE_STACK
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
endif # BOARD_PILLBUG endif # BOARD_PILLBUG

View file

@ -23,3 +23,6 @@ CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -8,9 +8,6 @@ if BOARD_PLANCK_REV6
config ZMK_KEYBOARD_NAME config ZMK_KEYBOARD_NAME
default "Planck V6" default "Planck V6"
config ZMK_USB
default y
config ZMK_KSCAN_MATRIX_POLLING config ZMK_KSCAN_MATRIX_POLLING
default y default y

View file

@ -15,3 +15,5 @@ CONFIG_GPIO=y
# clock configuration # clock configuration
CONFIG_CLOCK_CONTROL=y CONFIG_CLOCK_CONTROL=y
CONFIG_ZMK_USB=y

View file

@ -8,9 +8,6 @@ if BOARD_PREONIC_REV3
config ZMK_KEYBOARD_NAME config ZMK_KEYBOARD_NAME
default "Preonic V3" default "Preonic V3"
config ZMK_USB
default y
config ZMK_KSCAN_MATRIX_POLLING config ZMK_KSCAN_MATRIX_POLLING
default y default y

View file

@ -13,3 +13,5 @@ CONFIG_GPIO=y
# clock configuration # clock configuration
CONFIG_CLOCK_CONTROL=y CONFIG_CLOCK_CONTROL=y
CONFIG_ZMK_USB=y

View file

@ -8,7 +8,4 @@ if BOARD_QMK_PROTON_C
config BOARD config BOARD
default "proton_c" default "proton_c"
config ZMK_USB
default y
endif # BOARD_QMK_PROTON_C endif # BOARD_QMK_PROTON_C

View file

@ -17,3 +17,4 @@ CONFIG_GPIO=y
# clock configuration # clock configuration
CONFIG_CLOCK_CONTROL=y CONFIG_CLOCK_CONTROL=y
CONFIG_ZMK_USB=y

View file

@ -16,12 +16,6 @@ endif # USB_DEVICE_STACK
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
config PINMUX config PINMUX
default y default y

View file

@ -25,3 +25,6 @@ CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF=y CONFIG_CLOCK_CONTROL_NRF=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -19,10 +19,4 @@ endif # USB
config BT_CTLR config BT_CTLR
default BT default BT
config ZMK_BLE
default y
config ZMK_USB
default y
endif # BOARD_S40NC endif # BOARD_S40NC

View file

@ -20,3 +20,6 @@ CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y CONFIG_FLASH_MAP=y
CONFIG_ZMK_USB=y
CONFIG_ZMK_BLE=y

View file

@ -6,10 +6,6 @@ if SHIELD_NIBBLE
config ZMK_KEYBOARD_NAME config ZMK_KEYBOARD_NAME
default "NIBBLE" default "NIBBLE"
config ZMK_USB
default y
if ZMK_DISPLAY if ZMK_DISPLAY
config I2C config I2C

View file

@ -15,13 +15,43 @@
#define ZMK_HID_KEYBOARD_NKRO_MAX_USAGE HID_USAGE_KEY_KEYPAD_EQUAL #define ZMK_HID_KEYBOARD_NKRO_MAX_USAGE HID_USAGE_KEY_KEYPAD_EQUAL
#define COLLECTION_REPORT 0x03 // See https://www.usb.org/sites/default/files/hid1_11.pdf section 6.2.2.4 Main Items
#define ZMK_HID_MAIN_VAL_DATA (0x00 << 0)
#define ZMK_HID_MAIN_VAL_CONST (0x01 << 0)
#define ZMK_HID_MAIN_VAL_ARRAY (0x00 << 1)
#define ZMK_HID_MAIN_VAL_VAR (0x01 << 1)
#define ZMK_HID_MAIN_VAL_ABS (0x00 << 2)
#define ZMK_HID_MAIN_VAL_REL (0x01 << 2)
#define ZMK_HID_MAIN_VAL_NO_WRAP (0x00 << 3)
#define ZMK_HID_MAIN_VAL_WRAP (0x01 << 3)
#define ZMK_HID_MAIN_VAL_LIN (0x00 << 4)
#define ZMK_HID_MAIN_VAL_NON_LIN (0x01 << 4)
#define ZMK_HID_MAIN_VAL_PREFERRED (0x00 << 5)
#define ZMK_HID_MAIN_VAL_NO_PREFERRED (0x01 << 5)
#define ZMK_HID_MAIN_VAL_NO_NULL (0x00 << 6)
#define ZMK_HID_MAIN_VAL_NULL (0x01 << 6)
#define ZMK_HID_MAIN_VAL_NON_VOL (0x00 << 7)
#define ZMK_HID_MAIN_VAL_VOL (0x01 << 7)
#define ZMK_HID_MAIN_VAL_BIT_FIELD (0x00 << 8)
#define ZMK_HID_MAIN_VAL_BUFFERED_BYTES (0x01 << 8)
#define ZMK_HID_REPORT_ID_KEYBOARD 0x01
#define ZMK_HID_REPORT_ID_CONSUMER 0x02
static const uint8_t zmk_hid_report_desc[] = { static const uint8_t zmk_hid_report_desc[] = {
HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP), HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP),
HID_USAGE(HID_USAGE_GD_KEYBOARD), HID_USAGE(HID_USAGE_GD_KEYBOARD),
HID_COLLECTION(HID_COLLECTION_APPLICATION), HID_COLLECTION(HID_COLLECTION_APPLICATION),
HID_REPORT_ID(0x01), HID_REPORT_ID(ZMK_HID_REPORT_ID_KEYBOARD),
HID_USAGE_PAGE(HID_USAGE_KEY), HID_USAGE_PAGE(HID_USAGE_KEY),
HID_USAGE_MIN8(HID_USAGE_KEY_KEYBOARD_LEFTCONTROL), HID_USAGE_MIN8(HID_USAGE_KEY_KEYBOARD_LEFTCONTROL),
HID_USAGE_MAX8(HID_USAGE_KEY_KEYBOARD_RIGHT_GUI), HID_USAGE_MAX8(HID_USAGE_KEY_KEYBOARD_RIGHT_GUI),
@ -30,14 +60,12 @@ static const uint8_t zmk_hid_report_desc[] = {
HID_REPORT_SIZE(0x01), HID_REPORT_SIZE(0x01),
HID_REPORT_COUNT(0x08), HID_REPORT_COUNT(0x08),
/* INPUT (Data,Var,Abs) */ HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),
HID_INPUT(0x02),
HID_USAGE_PAGE(HID_USAGE_KEY), HID_USAGE_PAGE(HID_USAGE_KEY),
HID_REPORT_SIZE(0x08), HID_REPORT_SIZE(0x08),
HID_REPORT_COUNT(0x01), HID_REPORT_COUNT(0x01),
/* INPUT (Cnst,Var,Abs) */ HID_INPUT(ZMK_HID_MAIN_VAL_CONST | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),
HID_INPUT(0x03),
HID_USAGE_PAGE(HID_USAGE_KEY), HID_USAGE_PAGE(HID_USAGE_KEY),
@ -48,8 +76,7 @@ static const uint8_t zmk_hid_report_desc[] = {
HID_USAGE_MAX8(ZMK_HID_KEYBOARD_NKRO_MAX_USAGE), HID_USAGE_MAX8(ZMK_HID_KEYBOARD_NKRO_MAX_USAGE),
HID_REPORT_SIZE(0x01), HID_REPORT_SIZE(0x01),
HID_REPORT_COUNT(ZMK_HID_KEYBOARD_NKRO_MAX_USAGE + 1), HID_REPORT_COUNT(ZMK_HID_KEYBOARD_NKRO_MAX_USAGE + 1),
/* INPUT (Data,Ary,Abs) */ HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),
HID_INPUT(0x02),
#elif IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_HKRO) #elif IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_HKRO)
HID_LOGICAL_MIN8(0x00), HID_LOGICAL_MIN8(0x00),
HID_LOGICAL_MAX16(0xFF, 0x00), HID_LOGICAL_MAX16(0xFF, 0x00),
@ -57,8 +84,7 @@ static const uint8_t zmk_hid_report_desc[] = {
HID_USAGE_MAX8(0xFF), HID_USAGE_MAX8(0xFF),
HID_REPORT_SIZE(0x08), HID_REPORT_SIZE(0x08),
HID_REPORT_COUNT(CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE), HID_REPORT_COUNT(CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE),
/* INPUT (Data,Ary,Abs) */ HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_ARRAY | ZMK_HID_MAIN_VAL_ABS),
HID_INPUT(0x00),
#else #else
#error "A proper HID report type must be selected" #error "A proper HID report type must be selected"
#endif #endif
@ -67,7 +93,7 @@ static const uint8_t zmk_hid_report_desc[] = {
HID_USAGE_PAGE(HID_USAGE_CONSUMER), HID_USAGE_PAGE(HID_USAGE_CONSUMER),
HID_USAGE(HID_USAGE_CONSUMER_CONSUMER_CONTROL), HID_USAGE(HID_USAGE_CONSUMER_CONSUMER_CONTROL),
HID_COLLECTION(HID_COLLECTION_APPLICATION), HID_COLLECTION(HID_COLLECTION_APPLICATION),
HID_REPORT_ID(0x02), HID_REPORT_ID(ZMK_HID_REPORT_ID_CONSUMER),
HID_USAGE_PAGE(HID_USAGE_CONSUMER), HID_USAGE_PAGE(HID_USAGE_CONSUMER),
#if IS_ENABLED(CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC) #if IS_ENABLED(CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC)
@ -86,17 +112,28 @@ static const uint8_t zmk_hid_report_desc[] = {
#error "A proper consumer HID report usage range must be selected" #error "A proper consumer HID report usage range must be selected"
#endif #endif
HID_REPORT_COUNT(CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE), HID_REPORT_COUNT(CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE),
/* INPUT (Data,Ary,Abs) */ HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_ARRAY | ZMK_HID_MAIN_VAL_ABS),
HID_INPUT(0x00),
HID_END_COLLECTION, HID_END_COLLECTION,
}; };
// struct zmk_hid_boot_report #if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
// {
// uint8_t modifiers; #define HID_ERROR_ROLLOVER 0x1
// uint8_t _unused; #define HID_BOOT_KEY_LEN 6
// uint8_t keys[6];
// } __packed; #if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_HKRO) && \
CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE == HID_BOOT_KEY_LEN
typedef struct zmk_hid_keyboard_report_body zmk_hid_boot_report_t;
#else
struct zmk_hid_boot_report {
zmk_mod_flags_t modifiers;
uint8_t _reserved;
uint8_t keys[HID_BOOT_KEY_LEN];
} __packed;
typedef struct zmk_hid_boot_report zmk_hid_boot_report_t;
#endif
#endif
struct zmk_hid_keyboard_report_body { struct zmk_hid_keyboard_report_body {
zmk_mod_flags_t modifiers; zmk_mod_flags_t modifiers;
@ -154,3 +191,7 @@ bool zmk_hid_is_pressed(uint32_t usage);
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report(); struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report();
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report(); struct zmk_hid_consumer_report *zmk_hid_get_consumer_report();
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
zmk_hid_boot_report_t *zmk_hid_get_boot_report();
#endif

View file

@ -6,4 +6,8 @@
#pragma once #pragma once
int zmk_usb_hid_send_report(const uint8_t *report, size_t len); #include <stdint.h>
int zmk_usb_hid_send_keyboard_report();
int zmk_usb_hid_send_consumer_report();
void zmk_usb_hid_set_protocol(uint8_t protocol);

View file

@ -121,12 +121,10 @@ struct zmk_endpoint_instance zmk_endpoints_selected(void) {
} }
static int send_keyboard_report(void) { static int send_keyboard_report(void) {
struct zmk_hid_keyboard_report *keyboard_report = zmk_hid_get_keyboard_report();
switch (current_instance.transport) { switch (current_instance.transport) {
#if IS_ENABLED(CONFIG_ZMK_USB) #if IS_ENABLED(CONFIG_ZMK_USB)
case ZMK_TRANSPORT_USB: { case ZMK_TRANSPORT_USB: {
int err = zmk_usb_hid_send_report((uint8_t *)keyboard_report, sizeof(*keyboard_report)); int err = zmk_usb_hid_send_keyboard_report();
if (err) { if (err) {
LOG_ERR("FAILED TO SEND OVER USB: %d", err); LOG_ERR("FAILED TO SEND OVER USB: %d", err);
} }
@ -136,6 +134,7 @@ static int send_keyboard_report(void) {
#if IS_ENABLED(CONFIG_ZMK_BLE) #if IS_ENABLED(CONFIG_ZMK_BLE)
case ZMK_TRANSPORT_BLE: { case ZMK_TRANSPORT_BLE: {
struct zmk_hid_keyboard_report *keyboard_report = zmk_hid_get_keyboard_report();
int err = zmk_hog_send_keyboard_report(&keyboard_report->body); int err = zmk_hog_send_keyboard_report(&keyboard_report->body);
if (err) { if (err) {
LOG_ERR("FAILED TO SEND OVER HOG: %d", err); LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
@ -150,12 +149,10 @@ static int send_keyboard_report(void) {
} }
static int send_consumer_report(void) { static int send_consumer_report(void) {
struct zmk_hid_consumer_report *consumer_report = zmk_hid_get_consumer_report();
switch (current_instance.transport) { switch (current_instance.transport) {
#if IS_ENABLED(CONFIG_ZMK_USB) #if IS_ENABLED(CONFIG_ZMK_USB)
case ZMK_TRANSPORT_USB: { case ZMK_TRANSPORT_USB: {
int err = zmk_usb_hid_send_report((uint8_t *)consumer_report, sizeof(*consumer_report)); int err = zmk_usb_hid_send_consumer_report();
if (err) { if (err) {
LOG_ERR("FAILED TO SEND OVER USB: %d", err); LOG_ERR("FAILED TO SEND OVER USB: %d", err);
} }
@ -165,6 +162,7 @@ static int send_consumer_report(void) {
#if IS_ENABLED(CONFIG_ZMK_BLE) #if IS_ENABLED(CONFIG_ZMK_BLE)
case ZMK_TRANSPORT_BLE: { case ZMK_TRANSPORT_BLE: {
struct zmk_hid_consumer_report *consumer_report = zmk_hid_get_consumer_report();
int err = zmk_hog_send_consumer_report(&consumer_report->body); int err = zmk_hog_send_consumer_report(&consumer_report->body);
if (err) { if (err) {
LOG_ERR("FAILED TO SEND OVER HOG: %d", err); LOG_ERR("FAILED TO SEND OVER HOG: %d", err);

View file

@ -12,9 +12,17 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <dt-bindings/zmk/modifiers.h> #include <dt-bindings/zmk/modifiers.h>
static struct zmk_hid_keyboard_report keyboard_report = { static struct zmk_hid_keyboard_report keyboard_report = {
.report_id = 1, .body = {.modifiers = 0, ._reserved = 0, .keys = {0}}}; .report_id = ZMK_HID_REPORT_ID_KEYBOARD, .body = {.modifiers = 0, ._reserved = 0, .keys = {0}}};
static struct zmk_hid_consumer_report consumer_report = {.report_id = 2, .body = {.keys = {0}}}; static struct zmk_hid_consumer_report consumer_report = {.report_id = ZMK_HID_REPORT_ID_CONSUMER,
.body = {.keys = {0}}};
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
static zmk_hid_boot_report_t boot_report = {.modifiers = 0, ._reserved = 0, .keys = {0}};
static uint8_t keys_held = 0;
#endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */
// Keep track of how often a modifier was pressed. // Keep track of how often a modifier was pressed.
// Only release the modifier if the count is 0. // Only release the modifier if the count is 0.
@ -84,15 +92,58 @@ int zmk_hid_unregister_mods(zmk_mod_flags_t modifiers) {
return ret; return ret;
} }
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
static zmk_hid_boot_report_t *boot_report_rollover(uint8_t modifiers) {
boot_report.modifiers = modifiers;
for (int i = 0; i < HID_BOOT_KEY_LEN; i++) {
boot_report.keys[i] = HID_ERROR_ROLLOVER;
}
return &boot_report;
}
#endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */
#if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_NKRO) #if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_NKRO)
#define TOGGLE_KEYBOARD(code, val) WRITE_BIT(keyboard_report.body.keys[code / 8], code % 8, val) #define TOGGLE_KEYBOARD(code, val) WRITE_BIT(keyboard_report.body.keys[code / 8], code % 8, val)
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
zmk_hid_boot_report_t *zmk_hid_get_boot_report() {
if (keys_held > HID_BOOT_KEY_LEN) {
return boot_report_rollover(keyboard_report.body.modifiers);
}
boot_report.modifiers = keyboard_report.body.modifiers;
memset(&boot_report.keys, 0, HID_BOOT_KEY_LEN);
int ix = 0;
uint8_t base_code = 0;
for (int i = 0; i < (ZMK_HID_KEYBOARD_NKRO_MAX_USAGE + 1) / 8; ++i) {
if (ix == keys_held) {
break;
}
if (!keyboard_report.body.keys[i]) {
continue;
}
base_code = i * 8;
for (int j = 0; j < 8; ++j) {
if (keyboard_report.body.keys[i] & BIT(j)) {
boot_report.keys[ix++] = base_code + j;
}
}
}
return &boot_report;
}
#endif
static inline int select_keyboard_usage(zmk_key_t usage) { static inline int select_keyboard_usage(zmk_key_t usage) {
if (usage > ZMK_HID_KEYBOARD_NKRO_MAX_USAGE) { if (usage > ZMK_HID_KEYBOARD_NKRO_MAX_USAGE) {
return -EINVAL; return -EINVAL;
} }
TOGGLE_KEYBOARD(usage, 1); TOGGLE_KEYBOARD(usage, 1);
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
++keys_held;
#endif
return 0; return 0;
} }
@ -101,6 +152,9 @@ static inline int deselect_keyboard_usage(zmk_key_t usage) {
return -EINVAL; return -EINVAL;
} }
TOGGLE_KEYBOARD(usage, 0); TOGGLE_KEYBOARD(usage, 0);
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
--keys_held;
#endif
return 0; return 0;
} }
@ -124,13 +178,52 @@ static inline bool check_keyboard_usage(zmk_key_t usage) {
} \ } \
} }
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
zmk_hid_boot_report_t *zmk_hid_get_boot_report() {
if (keys_held > HID_BOOT_KEY_LEN) {
return boot_report_rollover(keyboard_report.body.modifiers);
}
#if CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE != HID_BOOT_KEY_LEN
// Form a boot report from a report of different size.
boot_report.modifiers = keyboard_report.body.modifiers;
int out = 0;
for (int i = 0; i < CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE; i++) {
uint8_t key = keyboard_report.body.keys[i];
if (key) {
boot_report.keys[out++] = key;
if (out == keys_held) {
break;
}
}
}
while (out < HID_BOOT_KEY_LEN) {
boot_report.keys[out++] = 0;
}
return &boot_report;
#else
return &keyboard_report.body;
#endif /* CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE != HID_BOOT_KEY_LEN */
}
#endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */
static inline int select_keyboard_usage(zmk_key_t usage) { static inline int select_keyboard_usage(zmk_key_t usage) {
TOGGLE_KEYBOARD(0U, usage); TOGGLE_KEYBOARD(0U, usage);
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
++keys_held;
#endif
return 0; return 0;
} }
static inline int deselect_keyboard_usage(zmk_key_t usage) { static inline int deselect_keyboard_usage(zmk_key_t usage) {
TOGGLE_KEYBOARD(usage, 0U); TOGGLE_KEYBOARD(usage, 0U);
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
--keys_held;
#endif
return 0; return 0;
} }

View file

@ -47,12 +47,12 @@ enum {
}; };
static struct hids_report input = { static struct hids_report input = {
.id = 0x01, .id = ZMK_HID_REPORT_ID_KEYBOARD,
.type = HIDS_INPUT, .type = HIDS_INPUT,
}; };
static struct hids_report consumer_input = { static struct hids_report consumer_input = {
.id = 0x02, .id = ZMK_HID_REPORT_ID_CONSUMER,
.type = HIDS_INPUT, .type = HIDS_INPUT,
}; };

View file

@ -62,9 +62,6 @@ config ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE
int "Max number of key position state events to queue to send to the central" int "Max number of key position state events to queue to send to the central"
default 10 default 10
config ZMK_USB
default n
config BT_MAX_PAIRED config BT_MAX_PAIRED
default 1 default 1

View file

@ -15,6 +15,8 @@
#include <zmk/event_manager.h> #include <zmk/event_manager.h>
#include <zmk/events/usb_conn_state_changed.h> #include <zmk/events/usb_conn_state_changed.h>
#include <zmk/usb_hid.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN; static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN;
@ -35,6 +37,7 @@ enum zmk_usb_conn_state zmk_usb_get_conn_state() {
case USB_DC_CONFIGURED: case USB_DC_CONFIGURED:
case USB_DC_RESUME: case USB_DC_RESUME:
case USB_DC_CLEAR_HALT: case USB_DC_CLEAR_HALT:
case USB_DC_SOF:
return ZMK_USB_CONN_HID; return ZMK_USB_CONN_HID;
case USB_DC_DISCONNECTED: case USB_DC_DISCONNECTED:
@ -47,6 +50,17 @@ enum zmk_usb_conn_state zmk_usb_get_conn_state() {
} }
void usb_status_cb(enum usb_dc_status_code status, const uint8_t *params) { void usb_status_cb(enum usb_dc_status_code status, const uint8_t *params) {
// Start-of-frame events are too frequent and noisy to notify, and they're
// not used within ZMK
if (status == USB_DC_SOF) {
return;
}
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
if (status == USB_DC_RESET) {
zmk_usb_hid_set_protocol(HID_PROTOCOL_REPORT);
}
#endif
usb_status = status; usb_status = status;
k_work_submit(&usb_status_notifier_work); k_work_submit(&usb_status_notifier_work);
}; };

View file

@ -23,11 +23,75 @@ static K_SEM_DEFINE(hid_sem, 1, 1);
static void in_ready_cb(const struct device *dev) { k_sem_give(&hid_sem); } static void in_ready_cb(const struct device *dev) { k_sem_give(&hid_sem); }
#define HID_GET_REPORT_TYPE_MASK 0xff00
#define HID_GET_REPORT_ID_MASK 0x00ff
#define HID_REPORT_TYPE_INPUT 0x100
#define HID_REPORT_TYPE_OUTPUT 0x200
#define HID_REPORT_TYPE_FEATURE 0x300
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
static uint8_t hid_protocol = HID_PROTOCOL_REPORT;
static void set_proto_cb(const struct device *dev, uint8_t protocol) { hid_protocol = protocol; }
void zmk_usb_hid_set_protocol(uint8_t protocol) { hid_protocol = protocol; }
#endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */
static uint8_t *get_keyboard_report(size_t *len) {
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
if (hid_protocol != HID_PROTOCOL_REPORT) {
zmk_hid_boot_report_t *boot_report = zmk_hid_get_boot_report();
*len = sizeof(*boot_report);
return (uint8_t *)boot_report;
}
#endif
struct zmk_hid_keyboard_report *report = zmk_hid_get_keyboard_report();
*len = sizeof(*report);
return (uint8_t *)report;
}
static int get_report_cb(const struct device *dev, struct usb_setup_packet *setup, int32_t *len,
uint8_t **data) {
/*
* 7.2.1 of the HID v1.11 spec is unclear about handling requests for reports that do not exist
* For requested reports that aren't input reports, return -ENOTSUP like the Zephyr subsys does
*/
if ((setup->wValue & HID_GET_REPORT_TYPE_MASK) != HID_REPORT_TYPE_INPUT) {
LOG_ERR("Unsupported report type %d requested", (setup->wValue & HID_GET_REPORT_TYPE_MASK)
<< 8);
return -ENOTSUP;
}
switch (setup->wValue & HID_GET_REPORT_ID_MASK) {
case ZMK_HID_REPORT_ID_KEYBOARD: {
*data = get_keyboard_report(len);
break;
}
case ZMK_HID_REPORT_ID_CONSUMER: {
struct zmk_hid_consumer_report *report = zmk_hid_get_consumer_report();
*data = (uint8_t *)report;
*len = sizeof(*report);
break;
}
default:
LOG_ERR("Invalid report ID %d requested", setup->wValue & HID_GET_REPORT_ID_MASK);
return -EINVAL;
}
return 0;
}
static const struct hid_ops ops = { static const struct hid_ops ops = {
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
.protocol_change = set_proto_cb,
#endif
.int_in_ready = in_ready_cb, .int_in_ready = in_ready_cb,
.get_report = get_report_cb,
}; };
int zmk_usb_hid_send_report(const uint8_t *report, size_t len) { static int zmk_usb_hid_send_report(const uint8_t *report, size_t len) {
switch (zmk_usb_get_status()) { switch (zmk_usb_get_status()) {
case USB_DC_SUSPEND: case USB_DC_SUSPEND:
return usb_wakeup_request(); return usb_wakeup_request();
@ -48,6 +112,23 @@ int zmk_usb_hid_send_report(const uint8_t *report, size_t len) {
} }
} }
int zmk_usb_hid_send_keyboard_report() {
size_t len;
uint8_t *report = get_keyboard_report(&len);
return zmk_usb_hid_send_report(report, len);
}
int zmk_usb_hid_send_consumer_report() {
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
if (hid_protocol == HID_PROTOCOL_BOOT) {
return -ENOTSUP;
}
#endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */
struct zmk_hid_consumer_report *report = zmk_hid_get_consumer_report();
return zmk_usb_hid_send_report((uint8_t *)report, sizeof(*report));
}
static int zmk_usb_hid_init(const struct device *_arg) { static int zmk_usb_hid_init(const struct device *_arg) {
hid_dev = device_get_binding("HID_0"); hid_dev = device_get_binding("HID_0");
if (hid_dev == NULL) { if (hid_dev == NULL) {
@ -56,6 +137,11 @@ static int zmk_usb_hid_init(const struct device *_arg) {
} }
usb_hid_register_device(hid_dev, zmk_hid_report_desc, sizeof(zmk_hid_report_desc), &ops); usb_hid_register_device(hid_dev, zmk_hid_report_desc, sizeof(zmk_hid_report_desc), &ops);
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
usb_hid_set_proto_code(hid_dev, HID_BOOT_IFACE_CODE_KEYBOARD);
#endif /* IS_ENABLED(CONFIG_ZMK_USB_BOOT) */
usb_hid_init(hid_dev); usb_hid_init(hid_dev);
return 0; return 0;

View file

@ -0,0 +1,109 @@
---
title: "Community Spotlight Series #1: Keymap Editor"
author: Cem Aksoylar
author_title: Documentation maintainer
author_url: https://github.com/caksoylar
author_image_url: https://avatars.githubusercontent.com/u/7876996
tags: [keyboards, firmware, community]
---
import ThemedImage from '@theme/ThemedImage';
<ThemedImage
alt="Shows a screenshot of the Keymap Editor application featuring a graphical layout of the Corne Keyboard with a keymap loaded from the nickcoutsos/keymap-editor-demo-crkbd GitHub repository."
sources={{
light: require('./assets/2023-11-09-keymap-editor/editor-screenshot-light.png').default,
dark: require('./assets/2023-11-09-keymap-editor/editor-screenshot-dark.png').default,
}}
/>
This blog post is the first in a series of posts where we highlight projects within the ZMK ecosystem that we think are cool and that the users might benefit from knowing about them. We are starting the series with a big one, [Keymap Editor] by [Nick Coutsos](https://github.com/nickcoutsos)!
In the rest of the post we leave it to Nick himself to introduce the project, detail his goals and motivation in developing such a tool, and talk about the future of the project. Stay tuned for future installments in the series!
## What is Keymap Editor?
_[Keymap Editor]_ is a web based graphical editor for ZMK keymaps. It provides a visual way to manage the contents of your keymap and if nothing else offers two critical features:
1. Automatic formatting of the keymap file, so that bindings arrays remain readable
2. Searchable behaviors, keycodes, commands, etc, so you won't have to remember if it's `LCTL` or `LCTRL` (I just had to double check myself and I guessed wrong, apparently)
## What can Keymap Editor do?
- Render [devicetree keymaps](/docs/features/keymaps) using pre-defined, auto-generated, or side-loadable keyboard layouts
- Integrate with a GitHub repo to streamline firmware builds, or FileSystem/Clipboard if you'd still rather build locally
- Edit [combos](/docs/features/combos), [behaviors](/docs/behaviors/key-press), [macros](/docs/behaviors/macros), [conditional layers](/docs/features/conditional-layers) and [rotary encoder bindings](/docs/behaviors/sensor-rotate)
- Manage references: moving a layer or renaming a behavior will look for references throughout your keymap and update them.
But check back regularly, because I update pretty often. A recent significant achievement was enabling [parameterized macros](/docs/behaviors/macros#parameterized-macros) and tying it in with my existing parameter type resolution so, yeah, you can finally create that reusable macro combining bluetooth profile selection with RGB backlight colour. Or use it for an actual useful thing, even. _(See also: [Using Parameterized Macros in Keymap Editor](https://github.com/nickcoutsos/keymap-editor/wiki/Using-Parameterized-Macros-in-Keymap-Editor))_
My goals are, broadly:
- **Treat code as a first-class entity:** as long as ZMK keymaps are described in devicetree code then an editor needs to produce readable devicetree code.
- **Flexibly support ZMK features:** use of any ZMK keymap feature should theoretically be achievable within the app. In some cases this can mean more initial setup _(See also: [my thoughts on implementing "autoshift"](https://github.com/nickcoutsos/keymap-editor/wiki/Autoshift-using-ZMK-behaviors))_ but having that foundation makes its easier to add shortcuts and niceties &mdash; something I do quite often now.
- **Don't get in the way of not-yet-supported features:** If a new ZMK feature is released and the app isn't able to add it natively, you can always edit your keymap file directly. While the app may not _recognize_ the new features, further changes through the app should not break your keymap.
## History of Keymap Editor
When I started writing Keymap Editor I had a handwired Dactyl variant running QMK. Manually editing keymap code was fine, but keeping things readable was important to me, and automating that was the best way to ensure consistency. Programmatically modifying source code was beyond me at the time so the first version persisted keymap data in JSON and spat out formatted versions of both the JSON and C keymaps.
After switching to ZMK I added a few more features, I guess as a pandemic project, and then gradually migrated from generating a templated keymap file to manipulating devicetree syntax directly, and that has made a big difference in adding new ZMK features.
## Why am I doing this?
It started out as a useful tool for me. I shared it with the ZMK community and gained a little traction, and then apparently quite a bit of traction &mdash; turns out it's useful for a lot of people.
I'm a software developer because I enjoy building things. Much of my day-to-day work isn't user facing, so seeing how helpful the keymap editor has been for people in the ZMK community is a big motivator to keep improving it.
## Future plans
### Runtime updates
Streamlining the keymap update process is probably top of mind for most users, but that involves a really big _firmware_ feature, and I'm the wrong person to tackle it.
That said, once there's a protocol I would _absolutely_ be down to integrate it as an additional keymap source. Being able to pull data directly from the keyboard should unlock a lot of possibilities and ease some of the constraints imposed by using devicetree code as a medium.
### Simplifying behavior use
I think a lot of people would like to see the concept of behaviors abstracted away for new users and to prompt them with
- _"When the key is tapped..."_,
- _"When the key is held..."_,
- _"When the key is double-tapped..."_ and so on.
Users who are less familiar with ZMK's behaviors and how they are composed may find these prompts to be more intuitive, and their answers could be mapped to an appropriate combination of behaviors managed internally by an editor.
### Uh, what else?
This has been long enough already, if you're looking for a feature I haven't mentioned don't assume I won't add it. Feel free to make feature requests on the GitHub repo, and I'd be happy to discuss it!
## About Me And My Keebs
I like computers and write software. Many in this field enjoy using mechanical
keyboards for their feel or aesthetics, but what piqued my interest was the
Dactyl keyboard. I think, ergonomics aside, I'm more interested in the DIY/maker
aspect than the collecting of keyboards and switches.
So [I made a Dactyl](https://github.com/nickcoutsos/dactyl-flatpacked/), and
then [I made another Dactyl](https://github.com/nickcoutsos/dactyl-deskmount/)
and I made a third Dactyl that isn't interesting enough to photograph, but now
I'm using ZMK so I left room for 18650 cells.
That last Dactyl (with MX browns and a cheap blank XDA keycap set) serves me
well the eight or so hours a day I'll spend at my desk, but I also spend a good
deal of time computing on my couch where I'll use... my Macbook's built-in
keyboard.
In case that's not surprising enough I'll leave you with this: despite all of
the work and testing I've put into the keymap editor project, I've only updated
an actual keymap once in the last year.
Thank you and good night.
## More information
- [Keymap Editor Wiki](https://github.com/nickcoutsos/keymap-editor/wiki)
- [Keymap Editor Discussions](https://github.com/nickcoutsos/keymap-editor/discussions)
- (YouTube video) [Ben Frain's overview of the Keymap Editor](https://www.youtube.com/watch?v=Vy7IoQAe3oU)
[Keymap Editor]: http://nickcoutsos.github.io/keymap-editor

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View file

@ -11,15 +11,15 @@ This makes flashing ZMK to your keyboard much easier, especially because you don
By default, the `zmk-config` folder should contain two files: By default, the `zmk-config` folder should contain two files:
- `<shield>.conf` - `<keyboard>.conf`
- `<shield>.keymap` - `<keyboard>.keymap`
However, your config folder can also be modified to include a `boards/` directory for keymaps and configurations for multiple boards/shields However, your config folder can also be modified to include a `boards/` directory for keymaps and configurations for multiple boards/shields
outside of the default keyboard setting definitions. outside of the default keyboard setting definitions.
## Configuration Changes ## Configuration Changes
The setup script creates a `config/<shield>.conf` file that allows you to add additional configuration options to The setup script creates a `config/<keyboard>.conf` file that allows you to add additional configuration options to
control what features and options are built into your firmware. Opening that file with your text editor will allow you to see the control what features and options are built into your firmware. Opening that file with your text editor will allow you to see the
various config settings that can be commented/uncommented to modify how your firmware is built. various config settings that can be commented/uncommented to modify how your firmware is built.
@ -27,7 +27,7 @@ Refer to the [Configuration](/docs/config) documentation for more details on thi
## Keymap ## Keymap
Once you have the basic user config completed, you can find the keymap file in `config/<shield>.keymap` and customize from there. Once you have the basic user config completed, you can find the keymap file in `config/<keyboard>.keymap` and customize from there.
Refer to the [Keymap](features/keymaps.md) documentation to learn more. Refer to the [Keymap](features/keymaps.md) documentation to learn more.
## Publishing ## Publishing
@ -39,18 +39,11 @@ GitHub Actions job to build your firmware which you can download once it complet
If you need to, a review of [Learn The Basics Of Git In Under 10 Minutes](https://www.freecodecamp.org/news/learn-the-basics-of-git-in-under-10-minutes-da548267cc91/) will help you get these steps right. If you need to, a review of [Learn The Basics Of Git In Under 10 Minutes](https://www.freecodecamp.org/news/learn-the-basics-of-git-in-under-10-minutes-da548267cc91/) will help you get these steps right.
::: :::
## Building from a local `zmk` fork using `zmk-config` :::note
It is also possible to build firmware locally on your computer by following the [toolchain setup](development/setup.md) and
[As outlined here](development/build-flash.md), firmware comes in the form of .uf2 files, which can be built locally using the command `west build`. Normally, [building instructions](development/build-flash.md), which includes pointers to
`west build` will default to using the in-tree .keymap and .conf files found in your local copy of the `zmk` repository. However, you can append the command, `-DZMK_CONFIG="C:/the/absolute/path/config"` to `west build` in order to use the contents of your `zmk-config` folder instead of the [building using your `zmk-config` folder](development/build-flash.md#building-from-zmk-config-folder).
default keyboard settings. :::
**Notice that this path should point to the folder labelled `config` within your `zmk-config` folder.**
For instance, building kyria firmware from a user `myUser`'s `zmk-config` folder on Windows 10 may look something like this:
```bash
west build -b nice_nano -- -DSHIELD=kyria_left -DZMK_CONFIG="C:/Users/myUser/Documents/Github/zmk-config/config"
```
## Flashing Your Changes ## Flashing Your Changes

View file

@ -65,7 +65,7 @@ west build -b planck_rev6
When building for a new board and/or shield after having built one previously, you may need to enable the pristine build option. This option removes all existing files in the build directory before regenerating them, and can be enabled by adding either --pristine or -p to the command: When building for a new board and/or shield after having built one previously, you may need to enable the pristine build option. This option removes all existing files in the build directory before regenerating them, and can be enabled by adding either --pristine or -p to the command:
```sh ```sh
west build -p -b proton_c -- -DSHIELD=kyria_left west build -p -b nice_nano_v2 -- -DSHIELD=kyria_left
``` ```
### Building For Split Keyboards ### Building For Split Keyboards
@ -77,13 +77,13 @@ For split keyboards, you will have to build and flash each side separately the f
By default, the `build` command outputs a single .uf2 file named `zmk.uf2` so building left and then right immediately after will overwrite your left firmware. In addition, you will need to pristine build each side to ensure the correct files are used. To avoid having to pristine build every time and separate the left and right build files, we recommend setting up separate build directories for each half. You can do this by using the `-d` parameter and first building left into `build/left`: By default, the `build` command outputs a single .uf2 file named `zmk.uf2` so building left and then right immediately after will overwrite your left firmware. In addition, you will need to pristine build each side to ensure the correct files are used. To avoid having to pristine build every time and separate the left and right build files, we recommend setting up separate build directories for each half. You can do this by using the `-d` parameter and first building left into `build/left`:
```sh ```sh
west build -d build/left -b nice_nano -- -DSHIELD=kyria_left west build -d build/left -b nice_nano_v2 -- -DSHIELD=kyria_left
``` ```
and then building right into `build/right`: and then building right into `build/right`:
```sh ```sh
west build -d build/right -b nice_nano -- -DSHIELD=kyria_right west build -d build/right -b nice_nano_v2 -- -DSHIELD=kyria_right
``` ```
This produces `left` and `right` subfolders under the `build` directory and two separate .uf2 files. For future work on a specific half, use the `-d` parameter again to ensure you are building into the correct location. This produces `left` and `right` subfolders under the `build` directory and two separate .uf2 files. For future work on a specific half, use the `-d` parameter again to ensure you are building into the correct location.

View file

@ -493,7 +493,7 @@ Once you've fully created the new keyboard shield definition,
you should be able to test with a build command like: you should be able to test with a build command like:
```sh ```sh
west build --pristine -b proton_c -- -DSHIELD=my_board west build --pristine -b nice_nano_v2 -- -DSHIELD=my_board
``` ```
The above build command generates `build/zephyr/zmk.uf2`. If your board The above build command generates `build/zephyr/zmk.uf2`. If your board

View file

@ -20,7 +20,7 @@ socket or using some sharp tweezers to bend the contacts back together.
## Debounce Configuration ## Debounce Configuration
:::note :::note
Currently only the `zmk,kscan-gpio-matrix` driver supports these options. The other drivers have not yet been updated to use the new debouncing code. Currently the `zmk,kscan-gpio-matrix` and `zmk,kscan-gpio-direct` [drivers](../config/kscan.md) supports these options, while `zmk,kscan-gpio-demux` driver does not.
::: :::
### Global Options ### Global Options

View file

@ -146,6 +146,7 @@ module.exports = {
showReadingTime: true, showReadingTime: true,
// Please change this to your repo. // Please change this to your repo.
editUrl: "https://github.com/zmkfirmware/zmk/edit/main/docs/", editUrl: "https://github.com/zmkfirmware/zmk/edit/main/docs/",
blogSidebarCount: "ALL",
}, },
theme: { theme: {
customCss: [ customCss: [