feat(boards): Add Glove80 to boards

* Add board definition for MoErgo Glove80
This commit is contained in:
Chris Andreae 2023-11-14 16:08:58 +09:00 committed by GitHub
parent afe65ead9c
commit 2a1904e184
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 927 additions and 0 deletions

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;
}