Merge remote-tracking branch 'upstream/main' into corne-ish-zen-v2

This commit is contained in:
Darryldh 2022-10-18 10:52:35 -04:00
commit e45ecab4a4
85 changed files with 1486 additions and 160 deletions

View file

@ -61,7 +61,7 @@ jobs:
set -x
if [ -n "${{ matrix.shield }}" ]
then
EXTRA_CMAKE_ARGS="-DSHIELD=${{ matrix.shield }}"
EXTRA_CMAKE_ARGS="-DSHIELD=\"${{ matrix.shield }}\""
ARTIFACT_NAME="${{ matrix.shield }}-${{ matrix.board }}-zmk"
DISPLAY_NAME="${{ matrix.shield }} - ${{ matrix.board }}"
else

View file

@ -35,11 +35,11 @@ jobs:
tools/
zephyr/
bootloader/
key: 4-${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('app/west.yml') }}
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('app/west.yml') }}
restore-keys: |
4-${{ runner.os }}-build-${{ env.cache-name }}-
4-${{ runner.os }}-build-
4-${{ runner.os }}-
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
timeout-minutes: 2
continue-on-error: true
- name: Initialize workspace (west init)
@ -71,7 +71,7 @@ jobs:
for (const shieldArgs of buildShieldArgs) {
try {
const output = execSync(`west build -s app -p -b ${{ matrix.board }} -- ${shieldArgs.shield ? '-DSHIELD=' + shieldArgs.shield : ''} ${shieldArgs['cmake-args'] || ''}`);
const output = execSync(`west build -s app -p -b ${{ matrix.board }} -- ${shieldArgs.shield ? '-DSHIELD="' + shieldArgs.shield + '"' : ''} ${shieldArgs['cmake-args'] || ''}`);
console.log(`::group::${{ matrix.board}} ${shieldArgs.shield} Build`)
console.log(output.toString());
@ -246,6 +246,9 @@ jobs:
return hm.requires.flatMap(i =>
metadata.interconnects[i].boards.flatMap(b => boardAndShield(b, hm))
);
} else {
console.warn("Unhandled shield without keys");
return [];
}
break;
case "interconnect":

View file

@ -47,11 +47,11 @@ jobs:
tools/
zephyr/
bootloader/
key: 4-${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('app/west.yml') }}
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('app/west.yml') }}
restore-keys: |
4-${{ runner.os }}-build-${{ env.cache-name }}-
4-${{ runner.os }}-build-
4-${{ runner.os }}-
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
timeout-minutes: 2
continue-on-error: true
- name: Initialize workspace (west init)

View file

@ -25,6 +25,18 @@ config USB_DEVICE_PID
config USB_DEVICE_MANUFACTURER
default "ZMK Project"
config BT_DIS_PNP_VID
default 0x1D50
config BT_DIS_PNP_PID
default 0x615E
config BT_DIS_MODEL
default ZMK_KEYBOARD_NAME
config BT_DIS_MANUF
default "ZMK Project"
menu "HID"
choice ZMK_HID_REPORT_TYPE

View file

@ -2,9 +2,9 @@ config BOARD_ENABLE_DCDC
bool "Enable DCDC mode"
select SOC_DCDC_NRF52X
default y
depends on (BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13)
depends on (BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13 || BOARD_NRFMICRO_13_52833)
config BOARD_NRFMICRO_CHARGER
bool "Enable battery charger"
default y
depends on (BOARD_NRFMICRO_13)
depends on (BOARD_NRFMICRO_13 || BOARD_NRFMICRO_13_52833)

View file

@ -14,3 +14,7 @@ config BOARD_NRFMICRO_11_FLIPPED
config BOARD_NRFMICRO_13
bool "nrfmicro_13"
depends on SOC_NRF52840_QIAA
config BOARD_NRFMICRO_13_52833
bool "nrfmicro_13_52833"
depends on SOC_NRF52833_QIAA

View file

@ -3,7 +3,7 @@
# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
if BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13
if BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13 || BOARD_NRFMICRO_13_52833
config BOARD
default "nrfmicro"
@ -27,11 +27,11 @@ config ZMK_USB
config PINMUX
default y
if BOARD_NRFMICRO_13
if BOARD_NRFMICRO_13 || BOARD_NRFMICRO_13_52833
config BOARD_NRFMICRO_CHARGER
default y
endif # BOARD_NRFMICRO_13
endif # BOARD_NRFMICRO_13 || BOARD_NRFMICRO_13_52833
endif # BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13
endif # BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13 || BOARD_NRFMICRO_13_52833

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
/ {
pro_micro: connector {
compatible = "arduino-pro-micro";
#gpio-cells = <2>;
gpio-map-mask = <0xffffffff 0xffffffc0>;
gpio-map-pass-thru = <0 0x3f>;
gpio-map
= <0 0 &gpio0 8 0> /* D0 */
, <1 0 &gpio0 6 0> /* D1 */
, <2 0 &gpio0 15 0> /* D2 */
, <3 0 &gpio0 17 0> /* D3 */
, <4 0 &gpio0 20 0> /* D4/A6 */
, <5 0 &gpio0 13 0> /* D5 */
, <6 0 &gpio0 24 0> /* D6/A7 */
, <7 0 &gpio0 9 0> /* D7 */
, <8 0 &gpio0 10 0> /* D8/A8 */
, <9 0 &gpio1 6 0> /* D9/A9 */
, <10 0 &gpio1 4 0> /* D10/A10 */
, <16 0 &gpio0 28 0> /* D16 */
, <14 0 &gpio0 3 0> /* D14 */
, <15 0 &gpio1 5 0> /* D15 */
, <18 0 &gpio0 2 0> /* D18/A0 */
, <19 0 &gpio0 29 0> /* D19/A1 */
, <20 0 &gpio0 31 0> /* D20/A2 */
, <21 0 &gpio0 30 0> /* D21/A3 */
;
};
pro_micro_a: connector_a {
compatible = "arduino-pro-micro";
#gpio-cells = <2>;
gpio-map-mask = <0xffffffff 0xffffffc0>;
gpio-map-pass-thru = <0 0x3f>;
gpio-map
= <0 0 &gpio0 2 0> /* D18/A0 */
, <1 0 &gpio0 29 0> /* D19/A1 */
, <2 0 &gpio0 31 0> /* D20/A2 */
, <3 0 &gpio0 30 0> /* D21/A3 */
, <6 0 &gpio0 20 0> /* D4/A6 */
, <7 0 &gpio0 24 0> /* D6/A7 */
, <8 0 &gpio0 10 0> /* D8/A8 */
, <9 0 &gpio1 6 0> /* D9/A9 */
, <10 0 &gpio1 11 0> /* D10/A10 */
;
};
};
pro_micro_d: &pro_micro {};
pro_micro_i2c: &i2c0 {};
pro_micro_spi: &spi0 {};
pro_micro_serial: &uart0 {};

View file

@ -0,0 +1,121 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
/dts-v1/;
#include <nordic/nrf52833_qiaa.dtsi>
#include "arduino_pro_micro_pins_52833.dtsi"
/ {
model = "nrfmicro";
compatible = "joric,nrfmicro";
chosen {
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,battery = &vbatt;
};
leds {
compatible = "gpio-leds";
blue_led: led_0 {
gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
label = "Blue LED";
};
};
ext-power {
compatible = "zmk,ext-power-generic";
label = "EXT_POWER";
control-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
};
vbatt: vbatt {
compatible = "zmk,battery-voltage-divider";
label = "BATTERY";
io-channels = <&adc 2>;
output-ohms = <2000000>;
full-ohms = <(2000000 + 820000)>;
};
};
&adc {
status = "okay";
};
&gpiote {
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&i2c0 {
compatible = "nordic,nrf-twi";
sda-pin = <15>;
scl-pin = <17>;
};
&uart0 {
compatible = "nordic,nrf-uarte";
tx-pin = <6>;
rx-pin = <8>;
};
&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 0x00046000>;
};
/*
* The flash starting at 0x0006c000 and ending at
* 0x00073fff is reserved for use by the application.
*/
/*
* Storage partition will be used by FCB/LittleFS/NVS
* if enabled.
*/
storage_partition: partition@6c000 {
label = "storage";
reg = <0x0006c000 0x00008000>;
};
boot_partition: partition@74000 {
label = "adafruit_boot";
reg = <0x00074000 0x0000c000>;
};
};
};

View file

@ -0,0 +1,15 @@
identifier: nrfmicro_13_52833
name: nrfmicro_13_52833
type: mcu
arch: arm
toolchain:
- zephyr
- gnuarmemb
- xtools
supported:
- adc
- usb_device
- ble
- ieee802154
- pwm
- watchdog

View file

@ -0,0 +1,10 @@
file_format: "1"
id: nrfmicro_13_52833
name: nRFMicro 1.3/1.4 (nRF52833)
type: board
arch: arm
outputs:
- usb
- ble
url: https://github.com/joric/nrfmicro/
exposes: [pro_micro]

View file

@ -0,0 +1,23 @@
# SPDX-License-Identifier: MIT
CONFIG_SOC_SERIES_NRF52X=y
CONFIG_SOC_NRF52833_QIAA=y
CONFIG_BOARD_NRFMICRO_13_52833=y
# Enable MPU
CONFIG_ARM_MPU=y
# enable GPIO
CONFIG_GPIO=y
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BUILD_OUTPUT_UF2=y
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
CONFIG_CLOCK_CONTROL_NRF=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y

View file

@ -14,7 +14,7 @@
static int pinmux_nrfmicro_init(const struct device *port) {
ARG_UNUSED(port);
#if CONFIG_BOARD_NRFMICRO_13
#if (CONFIG_BOARD_NRFMICRO_13 || CONFIG_BOARD_NRFMICRO_13_52833)
const struct device *p0 = device_get_binding("GPIO_0");
#if CONFIG_BOARD_NRFMICRO_CHARGER
gpio_pin_configure(p0, 5, GPIO_OUTPUT);

View file

@ -1,3 +1,9 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
@ -6,16 +12,34 @@
compatible = "zmk,keymap";
default_layer {
// -----------------------------------------------------------------------------------------
// | TAB | Q | W | E | R | T | Y | U | I | O | P | BSPC |
// | ESC | A | S | D | F | G | H | J | K | L | ; | ' |
// | SHIFT | Z | X | C | V | B | N | M | , | . | / | RET |
// | FN | LGUI | LALT | LCTL | LOWR | SPACE | RAIS | LARW | DARW | UARW | RARW |
// -----------------------------------------------------------------------------------------
// | TAB | Q | W | E | R | T | Y | U | I | O | P | BSPC |
// | ESC | A | S | D | F | G | H | J | K | L | ; | ' |
// | SHIFT | Z | X | C | V | B | N | M | , | . | / | RET |
// | | LCTL | LALT | LGUI | LOWR | SPACE | RAIS | LARW | DARW | UARW | RARW |
bindings = <
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp DEL
&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 LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp BSLH &kp RET
&trans &kp LGUI &kp LALT &kp LCTRL &trans &trans &kp SPACE &trans &kp LEFT &kp DOWN &kp UP &kp RIGHT
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSPC
&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 LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp SLASH &kp RET
&trans &kp LCTL &kp LALT &kp LGUI &mo 1 &trans &kp SPACE &mo 2 &kp LEFT &kp DOWN &kp UP &kp RIGHT
>;
};
lower {
bindings = <
&kp LS(GRAVE) &kp LS(N1) &kp LS(N2) &kp LS(N3) &kp LS(N4) &kp LS(N5) &kp LS(N6) &kp LS(N7) &kp LS(N8) &kp LS(N9) &kp LS(N0) &kp DEL
&kp DEL &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp UNDER &kp PLUS &kp LBRC &kp RBRC &kp PIPE
&trans &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp LS(HASH) &kp LS(BSLH) &kp HOME &kp END &trans
&trans &trans &trans &trans &trans &trans &trans &trans &kp C_NEXT &kp C_VOL_DN &kp C_VOL_UP &kp C_PP
>;
};
raise {
bindings = <
&kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp BSPC
&kp DEL &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp MINUS &kp EQUAL &kp LBKT &kp RBKT &kp BSLH
&trans &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp HASH &kp BSLH &kp PG_UP &kp PG_DN &trans
&reset &bootloader &trans &trans &trans &trans &trans &trans &kp C_NEXT &kp C_VOL_DN &kp C_VOL_UP &kp C_PP
>;
};
};

View file

@ -1 +0,0 @@
A 40% Ortho keyboard made by Polarity Works

View file

@ -13,16 +13,16 @@
compatible = "zmk,keymap";
default_layer {
// -----------------------------------------------------------------------------------------
// | TAB | Q | W | E | R | T | Y | U | I | O | P | BSPC |
// | ESC | A | S | D | F | G | H | J | K | L | ; | ' |
// | SHIFT | Z | X | C | V | B | N | M | , | . | / | RET |
// | FN | LGUI | LALT | LCTL | LOWR | SPACE | RAIS | LARW | DARW | UARW | RARW |
// -----------------------------------------------------------------------------------------
// | TAB | Q | W | E | R | T | Y | U | I | O | P | BSPC |
// | ESC | A | S | D | F | G | H | J | K | L | ; | ' |
// | SHIFT | Z | X | C | V | B | N | M | , | . | / | RET |
// | | LCTL | LALT | LGUI | LOWR | SPACE | RAIS | LARW | DARW | UARW | RARW |
bindings = <
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSPC
&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 LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp BSLH &kp RET
&trans &kp LGUI &kp LALT &kp LCTRL &mo 1 &kp SPACE &trans &mo 2 &kp LEFT &kp DOWN &kp UP &kp RIGHT
&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp SLASH &kp RET
&trans &kp LCTL &kp LALT &kp LGUI &mo 1 &kp SPACE &trans &mo 2 &kp LEFT &kp DOWN &kp UP &kp RIGHT
>;
sensor-bindings = <&inc_dec_kp PG_UP PG_DN>;
@ -31,7 +31,7 @@
lower {
bindings = <
&kp LS(GRAVE) &kp LS(N1) &kp LS(N2) &kp LS(N3) &kp LS(N4) &kp LS(N5) &kp LS(N6) &kp LS(N7) &kp LS(N8) &kp LS(N9) &kp LS(N0) &kp DEL
&kp DEL &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp UNDER &kp PLUS &kp LT &kp GT &kp PIPE
&kp DEL &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp UNDER &kp PLUS &kp LBRC &kp RBRC &kp PIPE
&trans &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp LS(HASH) &kp LS(BSLH) &kp HOME &kp END &trans
&trans &trans &trans &trans &trans &trans &trans &mo 3 &kp C_NEXT &kp C_VOL_DN &kp C_VOL_UP &kp C_PP
>;
@ -46,12 +46,14 @@
&trans &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp HASH &kp BSLH &kp PG_UP &kp PG_DN &trans
&trans &trans &trans &trans &mo 3 &trans &trans &trans &kp C_NEXT &kp C_VOL_DN &kp C_VOL_UP &kp C_PP
>;
sensor-bindings = <&inc_dec_kp PG_UP PG_DN>;
};
control {
bindings = <
&reset &bootloader &bt BT_CLR &bt BT_PRV &bt BT_NXT &trans &trans &trans &trans &trans &trans &trans
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
&bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &trans &trans &trans &trans &trans &trans &trans &trans &trans
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
>;

View file

@ -0,0 +1,22 @@
# Copyright (c) 2022 The ZMK Contributors
# SPDX-License-Identifier: MIT
if SHIELD_NICE_VIEW
config ZMK_DISPLAY
select LVGL_FONT_MONTSERRAT_26
if ZMK_DISPLAY
config SPI
default y
config LS0XX
default y
config ZMK_WIDGET_WPM_STATUS
default y if !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL
endif # ZMK_DISPLAY
endif

View file

@ -0,0 +1,5 @@
# Copyright (c) 2022 The ZMK Contributors
# SPDX-License-Identifier: MIT
config SHIELD_NICE_VIEW
def_bool $(shields_list_contains,nice_view)

View file

@ -0,0 +1,5 @@
# nice!view
The nice!view is a low power, high refresh rate display meant to replace I2C OLEDs traditionally used.
This shield requires that an `&nice_view_spi` labelled SPI bus is provided with *at least* MOSI, SCK, and CS pins defined.

View file

@ -0,0 +1,5 @@
# Enable nice!view
CONFIG_ZMK_DISPLAY=y
CONFIG_LVGL_THEME_DEFAULT_FONT_SMALL_MONTSERRAT_26=y
CONFIG_LVGL_THEME_DEFAULT_FONT_NORMAL_MONTSERRAT_26=y
CONFIG_ZMK_DISPLAY_BLANK_ON_IDLE=n

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
&nice_view_spi {
status = "okay";
nice_view: ls0xx@0 {
compatible = "sharp,ls0xx";
label = "DISPLAY";
spi-max-frequency = <1000000>;
reg = <0>;
width = <160>;
height = <68>;
};
};
/ {
chosen {
zephyr,display = &nice_view;
};
};

View file

@ -0,0 +1,8 @@
file_format: "1"
id: nice_view
name: nice!view
type: shield
url: https://nicekeyboards.com/nice-view
requires: [nice_view_header]
features:
- display

View file

@ -0,0 +1,2 @@
# Copyright (c) 2022 The ZMK Contributors
# SPDX-License-Identifier: MIT

View file

@ -0,0 +1,5 @@
# Copyright (c) 2022 The ZMK Contributors
# SPDX-License-Identifier: MIT
config SHIELD_NICE_VIEW_ADAPTER
def_bool $(shields_list_contains,nice_view_adapter)

View file

@ -0,0 +1,11 @@
# nice!view Adapter
This shield is used as an adapter between the nice!view and existing shields/boards that expose an I2C OLED header.
To use this shield, you should add this shield to your list of shields *before* `nice_view`.
The nice!view will use the SDA/SCL pins of the OLED, and then the adapter expects a final pin to be "bodged" from your microcontroller to the nice!view CS pin. This adapter assumes that the CS pin bodged is the `&pro_micro 1` pin or "D1", which is the top left pin when looking at the front of the board. If you can't use this pin, you'll need to override the `cs-gpios` for the `&nice_view_spi` bus (in your `zmk-config` keymap for example) or you will want to define your own `&nice_view_spi` bus without using this adapter.
```
west build -b nice_nano_v2 -- -DSHIELD="lily58_left nice_view_adapter nice_view"
```

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
nice_view_spi: &spi0 {
compatible = "nordic,nrf-spim";
sck-pin = <17>;
mosi-pin = <15>;
miso-pin = <25>;
cs-gpios = <&pro_micro 1 GPIO_ACTIVE_HIGH>;
};
&pro_micro_i2c {
status = "disabled";
};

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
nice_view_spi: &spi0 {
compatible = "nordic,nrf-spim";
sck-pin = <20>;
mosi-pin = <17>;
miso-pin = <5>;
cs-gpios = <&pro_micro 1 GPIO_ACTIVE_HIGH>;
};
&pro_micro_i2c {
status = "disabled";
};

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
nice_view_spi: &spi0 {
compatible = "nordic,nrf-spim";
sck-pin = <20>;
mosi-pin = <17>;
miso-pin = <25>;
cs-gpios = <&pro_micro 1 GPIO_ACTIVE_HIGH>;
};
&pro_micro_i2c {
status = "disabled";
};

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
nice_view_spi: &spi0 {
compatible = "nordic,nrf-spim";
sck-pin = <20>;
mosi-pin = <17>;
miso-pin = <25>;
cs-gpios = <&pro_micro 1 GPIO_ACTIVE_HIGH>;
};
&pro_micro_i2c {
status = "disabled";
};

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
nice_view_spi: &spi0 {
compatible = "nordic,nrf-spim";
sck-pin = <17>;
mosi-pin = <15>;
miso-pin = <25>;
cs-gpios = <&pro_micro 1 GPIO_ACTIVE_HIGH>;
};
&pro_micro_i2c {
status = "disabled";
};

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
nice_view_spi: &spi0 {
compatible = "nordic,nrf-spim";
sck-pin = <31>;
mosi-pin = <30>;
miso-pin = <25>;
cs-gpios = <&pro_micro 1 GPIO_ACTIVE_HIGH>;
};
&pro_micro_i2c {
status = "disabled";
};

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
nice_view_spi: &spi0 {
compatible = "nordic,nrf-spim";
sck-pin = <17>;
mosi-pin = <15>;
miso-pin = <25>;
cs-gpios = <&pro_micro 1 GPIO_ACTIVE_HIGH>;
};
&pro_micro_i2c {
status = "disabled";
};

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
nice_view_spi: &spi0 {
compatible = "nordic,nrf-spim";
sck-pin = <17>;
mosi-pin = <15>;
miso-pin = <25>;
cs-gpios = <&pro_micro 1 GPIO_ACTIVE_HIGH>;
};
&pro_micro_i2c {
status = "disabled";
};

View file

@ -0,0 +1,2 @@
# Disable OLED
CONFIG_SSD1306=n

View file

@ -0,0 +1,5 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

View file

@ -0,0 +1,7 @@
file_format: "1"
id: nice_view_adapter
name: nice!view adapter
type: shield
url: https://nicekeyboards.com/nice-view
requires: [i2c_oled]
exposes: [nice_view_header]

View file

@ -30,3 +30,6 @@ include:
shield: romac_plus
cmake-args: "-DCONFIG_ZMK_RGB_UNDERGLOW=y -DCONFIG_WS2812_STRIP=y"
nickname: "underglow"
- board: nice_nano_v2
shield: lily58_left nice_view_adapter nice_view
nickname: "niceview"

View file

@ -1,4 +1,4 @@
# Copyright (c) 2020 The ZMK Contributors
# Copyright (c) 2022 The ZMK Contributors
# SPDX-License-Identifier: MIT
zephyr_library_named(zmk__drivers__gpio)
@ -6,3 +6,4 @@ zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include)
zephyr_library_sources_ifdef(CONFIG_GPIO_595 gpio_595.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_MCP23017 gpio_mcp23017.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_MAX7318 gpio_max7318.c)

View file

@ -2,4 +2,5 @@ menuconfig ZMK_DRIVERS_GPIO
bool "GPIO"
rsource "Kconfig.mcp23017"
rsource "Kconfig.595"
rsource "Kconfig.max7318"
rsource "Kconfig.595"

View file

@ -0,0 +1,25 @@
# MAX7318 GPIO configuration options
# Copyright (c) 2022 The ZMK Contributors
# SPDX-License-Identifier: MIT
DT_COMPAT_MAXIM_MAX7318 := maxim,max7318
menuconfig GPIO_MAX7318
bool "MAX7318 I2C-based GPIO chip"
default $(dt_compat_enabled,$(DT_COMPAT_MAXIM_MAX7318))
depends on I2C
select HAS_DTS_GPIO
select ZMK_DRIVERS_GPIO
help
Enable driver for MAX7318 I2C-based GPIO chip.
if GPIO_MAX7318
config GPIO_MAX7318_INIT_PRIORITY
int "Init priority"
default 75
help
Device driver initialization priority.
endif #GPIO_MAX7318

View file

@ -0,0 +1,336 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#define DT_DRV_COMPAT maxim_max7318
/**
* @file Driver for MAX7318 I2C-based GPIO driver.
*/
#include <errno.h>
#include <kernel.h>
#include <device.h>
#include <init.h>
#include <sys/byteorder.h>
#include <drivers/gpio.h>
#include <drivers/i2c.h>
#include <drivers/ext_power.h>
#define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(gpio_max7318);
// Register definitions
#define REG_INPUT_PORTA 0x00
#define REG_INPUT_PORTB 0x01
#define REG_OUTPUT_PORTA 0x02
#define REG_OUTPUT_PORTB 0x03
#define REG_IPOL_PORTA 0x04
#define REG_IPOL_PORTB 0x05
#define REG_CONFIG_PORTA 0x06
#define REG_CONFIG_PORTB 0x07
// Configuration data
struct max7318_config {
struct gpio_driver_config common;
struct i2c_dt_spec i2c_bus;
uint8_t ngpios;
};
// Runtime driver data
struct max7318_drv_data {
// gpio_driver_data needs to be first
struct gpio_driver_config data;
struct k_sem lock;
struct {
uint16_t ipol;
uint16_t config;
uint16_t output;
} reg_cache;
};
/**
* @brief Read the value of two consecutive registers
*
* Read two consecutive bytes from the register at address `reg` and `reg + 1`,
* typically reading from registers for port 0 and 1 simultaneously.
*
* @param dev The max7318 device.
* @param reg Register to read (the PORT0 of the pair of registers).
* @param buf Buffer to read data into.
*
* @return 0 if successful, failed otherwise.
*/
static int read_registers(const struct device *dev, uint8_t reg, uint16_t *buf) {
const struct max7318_config *config = dev->config;
uint16_t data = 0;
int ret = i2c_burst_read_dt(&config->i2c_bus, reg, (uint8_t *)&data, sizeof(data));
if (ret) {
LOG_DBG("i2c_write_read FAIL %d\n", ret);
return ret;
}
*buf = sys_le16_to_cpu(data);
LOG_DBG("max7318: read: reg[0x%X] = 0x%X, reg[0x%X] = 0x%X", reg, (*buf & 0xFF), (reg + 1),
(*buf >> 8));
return 0;
}
/**
* @brief Write the value of two consecutive registers
*
* Write two consecutive bytes from the register at address `reg` and `reg + 1`,
* typically to registers for port 0 and 1 simultaneously.
*
* @param dev The max7318 device.
* @param reg Register to write (usually the register for PORT0).
* @param value The value to write
*
* @return 0 if successful, failed otherwise.
*/
static int write_registers(const struct device *dev, uint8_t reg, uint16_t value) {
const struct max7318_config *config = dev->config;
LOG_DBG("max7318: write: reg[0x%X] = 0x%X, reg[0x%X] = 0x%X", reg, (value & 0xFF), (reg + 1),
(value >> 8));
uint16_t data = sys_cpu_to_le16(value);
return i2c_burst_write_dt(&config->i2c_bus, reg, (uint8_t *)&data, sizeof(data));
}
/**
* @brief Setup the pin direction (input or output)
*
* @param dev The max7318 device.
* @param pin The pin number.
* @param flags Flags of pin or port.
*
* @return 0 if successful, failed otherwise
*/
static int set_pin_direction(const struct device *dev, uint32_t pin, int flags) {
struct max7318_drv_data *const drv_data = (struct max7318_drv_data *const)dev->data;
uint16_t *dir = &drv_data->reg_cache.config;
uint16_t *output = &drv_data->reg_cache.output;
/*
The output register is 1=high, 0=low; the direction (config) register
is 1=input, 0=output.
*/
if ((flags & GPIO_OUTPUT) != 0U) {
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
*output |= BIT(pin);
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
*output &= ~BIT(pin);
}
*dir &= ~BIT(pin);
} else {
*dir |= BIT(pin);
}
int ret = write_registers(dev, REG_OUTPUT_PORTA, *output);
if (ret != 0) {
return ret;
}
return write_registers(dev, REG_CONFIG_PORTA, *dir);
}
/**
* @brief Setup the pin pull up/pull down status. This function doesn't actually set any
* registers, since the max7318 only supports a pullup, and it can't be controlled.
*
* @param dev The max7318 device.
* @param pin The pin number
* @param flags Flags of pin or port
*
* @return 0 if successful, failed otherwise
*/
static int set_pin_pull_direction(const struct device *dev, uint32_t pin, int flags) {
// actually, this chip only supports pull-up, and it can't be disabled.
// so, if we try to set anything else, return enotsup; we don't actually
// need to set any registers.
if ((flags & GPIO_PULL_DOWN) != 0U) {
return -ENOTSUP;
}
return 0;
}
static int max7318_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) {
struct max7318_drv_data *const drv_data = (struct max7318_drv_data *const)dev->data;
/* Can't do I2C bus operations from an ISR */
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
k_sem_take(&drv_data->lock, K_FOREVER);
int ret = 0;
if ((flags & GPIO_OPEN_DRAIN) != 0U) {
ret = -ENOTSUP;
goto done;
};
ret = set_pin_direction(dev, pin, flags);
if (ret != 0) {
LOG_ERR("error setting pin direction (%d)", ret);
goto done;
}
ret = set_pin_pull_direction(dev, pin, flags);
if (ret != 0) {
LOG_ERR("error setting pin pull up/down (%d)", ret);
goto done;
}
done:
k_sem_give(&drv_data->lock);
return ret;
}
static int max7318_port_get_raw(const struct device *dev, uint32_t *value) {
struct max7318_drv_data *const drv_data = (struct max7318_drv_data *const)dev->data;
/* Can't do I2C bus operations from an ISR */
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
k_sem_take(&drv_data->lock, K_FOREVER);
uint16_t buf = 0;
int ret = read_registers(dev, REG_INPUT_PORTA, &buf);
if (ret != 0) {
goto done;
}
*value = buf;
done:
k_sem_give(&drv_data->lock);
return ret;
}
static int max7318_port_set_masked_raw(const struct device *dev, uint32_t mask, uint32_t value) {
struct max7318_drv_data *const drv_data = (struct max7318_drv_data *const)dev->data;
/* Can't do I2C bus operations from an ISR */
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
k_sem_take(&drv_data->lock, K_FOREVER);
uint16_t buf = drv_data->reg_cache.output;
buf = (buf & ~mask) | (mask & value);
int ret = write_registers(dev, REG_OUTPUT_PORTA, buf);
if (ret == 0) {
drv_data->reg_cache.output = buf;
}
k_sem_give(&drv_data->lock);
return ret;
}
static int max7318_port_set_bits_raw(const struct device *dev, uint32_t mask) {
return max7318_port_set_masked_raw(dev, mask, mask);
}
static int max7318_port_clear_bits_raw(const struct device *dev, uint32_t mask) {
return max7318_port_set_masked_raw(dev, mask, 0);
}
static int max7318_port_toggle_bits(const struct device *dev, uint32_t mask) {
struct max7318_drv_data *const drv_data = (struct max7318_drv_data *const)dev->data;
/* Can't do I2C bus operations from an ISR */
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
k_sem_take(&drv_data->lock, K_FOREVER);
uint16_t buf = drv_data->reg_cache.output;
buf ^= mask;
int ret = write_registers(dev, REG_OUTPUT_PORTA, buf);
if (ret == 0) {
drv_data->reg_cache.output = buf;
}
k_sem_give(&drv_data->lock);
return ret;
}
static int max7318_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
enum gpio_int_mode mode, enum gpio_int_trig trig) {
return -ENOTSUP;
}
static const struct gpio_driver_api api_table = {
.pin_configure = max7318_config,
.port_get_raw = max7318_port_get_raw,
.port_set_masked_raw = max7318_port_set_masked_raw,
.port_set_bits_raw = max7318_port_set_bits_raw,
.port_clear_bits_raw = max7318_port_clear_bits_raw,
.port_toggle_bits = max7318_port_toggle_bits,
.pin_interrupt_configure = max7318_pin_interrupt_configure,
};
/**
* @brief Initialisation function of MAX7318
*
* @param dev Device struct
* @return 0 if successful, failed otherwise.
*/
static int max7318_init(const struct device *dev) {
const struct max7318_config *const config = dev->config;
struct max7318_drv_data *const drv_data = (struct max7318_drv_data *const)dev->data;
if (!device_is_ready(config->i2c_bus.bus)) {
LOG_WRN("i2c bus not ready!");
return -EINVAL;
}
LOG_INF("device initialised at 0x%x", config->i2c_bus.addr);
k_sem_init(&drv_data->lock, 1, 1);
return 0;
}
#define GPIO_PORT_PIN_MASK_FROM_NGPIOS(ngpios) ((gpio_port_pins_t)(((uint64_t)1 << (ngpios)) - 1U))
#define GPIO_PORT_PIN_MASK_FROM_DT_INST(inst) \
GPIO_PORT_PIN_MASK_FROM_NGPIOS(DT_INST_PROP(inst, ngpios))
#define MAX7318_INIT(inst) \
static struct max7318_config max7318_##inst##_config = { \
.common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst)}, \
.i2c_bus = I2C_DT_SPEC_INST_GET(inst)}; \
\
static struct max7318_drv_data max7318_##inst##_drvdata = { \
/* Default for registers according to datasheet */ \
.reg_cache.ipol = 0x0, \
.reg_cache.config = 0xFFFF, \
.reg_cache.output = 0xFFFF, \
}; \
\
DEVICE_DT_INST_DEFINE(inst, max7318_init, NULL, &max7318_##inst##_drvdata, \
&max7318_##inst##_config, POST_KERNEL, \
CONFIG_GPIO_MAX7318_INIT_PRIORITY, &api_table);
DT_INST_FOREACH_STATUS_OKAY(MAX7318_INIT)

View file

@ -32,6 +32,16 @@ config ZMK_KSCAN_GPIO_MATRIX
if ZMK_KSCAN_GPIO_MATRIX
config ZMK_KSCAN_MATRIX_WAIT_BEFORE_INPUTS
int "Ticks to wait before reading inputs after an output set active"
default 0
help
When iterating over each output to drive it active, read inputs, then set
inactive again, some boards may take time for output to propagate to the
inputs. In that scenario, set this value to a positive value to configure
the number of ticks to wait after setting an output active before reading
the inputs for their active state.
config ZMK_KSCAN_MATRIX_WAIT_BETWEEN_OUTPUTS
int "Ticks to wait between each output when scanning"
default 0
@ -40,7 +50,7 @@ config ZMK_KSCAN_MATRIX_WAIT_BETWEEN_OUTPUTS
inactive again, some boards may take time for the previous output to
"settle" before reading inputs for the next active output column. In that
scenario, set this value to a positive value to configure the number of
usecs to wait after reading each column of keys.
ticks to wait after reading each column of keys.
endif # ZMK_KSCAN_GPIO_MATRIX

View file

@ -235,6 +235,10 @@ static int kscan_matrix_read(const struct device *dev) {
return err;
}
#if CONFIG_ZMK_KSCAN_MATRIX_WAIT_BEFORE_INPUTS > 0
k_busy_wait(CONFIG_ZMK_KSCAN_MATRIX_WAIT_BEFORE_INPUTS);
#endif
for (int i = 0; i < config->inputs.len; i++) {
const struct gpio_dt_spec *in_gpio = &config->inputs.gpios[i];

View file

@ -0,0 +1,29 @@
#
# Copyright (c) 2022 The ZMK Contributors
#
# SPDX-License-Identifier: MIT
#
description: >
This is a representation of the Maxim MAX7318 I2C Gpio Expander.
compatible: "maxim,max7318"
include: [gpio-controller.yaml, i2c-device.yaml]
properties:
label:
required: true
"#gpio-cells":
const: 2
ngpios:
type: int
required: true
const: 16
description: Number of gpios supported
gpio-cells:
- pin
- flags

View file

@ -14,3 +14,6 @@ properties:
mods:
type: int
required: true
keep-mods:
type: int
required: false

View file

@ -263,6 +263,7 @@
/* Keyboard Non-US # and ~ (Non-US Hash/Number and Tilde) */
#define NON_US_HASH (ZMK_HID_USAGE(HID_USAGE_KEY, HID_USAGE_KEY_KEYBOARD_NON_US_HASH_AND_TILDE))
#define NUHS (NON_US_HASH)
/* Keyboard ~ (Tilde) */
#define TILDE2 (LS(ZMK_HID_USAGE(HID_USAGE_KEY, HID_USAGE_KEY_KEYBOARD_NON_US_HASH_AND_TILDE)))
@ -499,6 +500,7 @@
#define NON_US_BACKSLASH \
(ZMK_HID_USAGE(HID_USAGE_KEY, HID_USAGE_KEY_KEYBOARD_NON_US_BACKSLASH_AND_PIPE))
#define NON_US_BSLH (NON_US_BACKSLASH)
#define NUBS (NON_US_BACKSLASH)
/* Keyboard Pipe */
#define PIPE2 (LS(ZMK_HID_USAGE(HID_USAGE_KEY, HID_USAGE_KEY_KEYBOARD_NON_US_BACKSLASH_AND_PIPE)))

View file

@ -135,6 +135,8 @@ int zmk_hid_register_mods(zmk_mod_flags_t explicit_modifiers);
int zmk_hid_unregister_mods(zmk_mod_flags_t explicit_modifiers);
int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t implicit_modifiers);
int zmk_hid_implicit_modifiers_release();
int zmk_hid_masked_modifiers_set(zmk_mod_flags_t masked_modifiers);
int zmk_hid_masked_modifiers_clear();
int zmk_hid_keyboard_press(zmk_key_t key);
int zmk_hid_keyboard_release(zmk_key_t key);

View file

@ -75,7 +75,7 @@ static void backlight_save_work_handler(struct k_work *work) {
settings_save_one("backlight/state", &state, sizeof(state));
}
static K_DELAYED_WORK_DEFINE(backlight_save_work, backlight_save_work_handler);
static struct k_work_delayable backlight_save_work;
#endif
static int zmk_backlight_init(const struct device *_arg) {
@ -90,6 +90,7 @@ static int zmk_backlight_init(const struct device *_arg) {
if (rc != 0) {
LOG_ERR("Failed to load backlight settings: %d", rc);
}
k_work_init_delayable(&backlight_save_work, backlight_save_work_handler);
#endif
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
state.on = zmk_usb_is_powered();
@ -104,8 +105,8 @@ static int zmk_backlight_update_and_save() {
}
#if IS_ENABLED(CONFIG_SETTINGS)
k_delayed_work_cancel(&backlight_save_work);
return k_delayed_work_submit(&backlight_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE));
int ret = k_work_reschedule(&backlight_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE));
return MIN(ret, 0);
#else
return 0;
#endif

View file

@ -27,6 +27,7 @@ struct behavior_mod_morph_config {
struct zmk_behavior_binding normal_binding;
struct zmk_behavior_binding morph_binding;
zmk_mod_flags_t mods;
zmk_mod_flags_t masked_mods;
};
struct behavior_mod_morph_data {
@ -45,6 +46,7 @@ static int on_mod_morph_binding_pressed(struct zmk_behavior_binding *binding,
}
if (zmk_hid_get_explicit_mods() & cfg->mods) {
zmk_hid_masked_modifiers_set(cfg->masked_mods);
data->pressed_binding = (struct zmk_behavior_binding *)&cfg->morph_binding;
} else {
data->pressed_binding = (struct zmk_behavior_binding *)&cfg->normal_binding;
@ -64,7 +66,10 @@ static int on_mod_morph_binding_released(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding *pressed_binding = data->pressed_binding;
data->pressed_binding = NULL;
return behavior_keymap_binding_released(pressed_binding, event);
int err;
err = behavior_keymap_binding_released(pressed_binding, event);
zmk_hid_masked_modifiers_clear();
return err;
}
static const struct behavior_driver_api behavior_mod_morph_driver_api = {
@ -88,6 +93,8 @@ static int behavior_mod_morph_init(const struct device *dev) { return 0; }
.normal_binding = _TRANSFORM_ENTRY(0, n), \
.morph_binding = _TRANSFORM_ENTRY(1, n), \
.mods = DT_INST_PROP(n, mods), \
.masked_mods = COND_CODE_0(DT_INST_NODE_HAS_PROP(n, keep_mods), (DT_INST_PROP(n, mods)), \
(DT_INST_PROP(n, mods) & ~DT_INST_PROP(n, keep_mods))), \
}; \
static struct behavior_mod_morph_data behavior_mod_morph_data_##n = {}; \
DEVICE_DT_INST_DEFINE(n, behavior_mod_morph_init, NULL, &behavior_mod_morph_data_##n, \

View file

@ -20,10 +20,12 @@ static struct zmk_hid_consumer_report consumer_report = {.report_id = 2, .body =
// Only release the modifier if the count is 0.
static int explicit_modifier_counts[8] = {0, 0, 0, 0, 0, 0, 0, 0};
static zmk_mod_flags_t explicit_modifiers = 0;
static zmk_mod_flags_t implicit_modifiers = 0;
static zmk_mod_flags_t masked_modifiers = 0;
#define SET_MODIFIERS(mods) \
{ \
keyboard_report.body.modifiers = mods; \
keyboard_report.body.modifiers = (mods & ~masked_modifiers) | implicit_modifiers; \
LOG_DBG("Modifiers set to 0x%02X", keyboard_report.body.modifiers); \
}
@ -158,13 +160,29 @@ static inline int check_keyboard_usage(zmk_key_t usage) {
} \
}
int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t implicit_modifiers) {
int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t new_implicit_modifiers) {
implicit_modifiers = new_implicit_modifiers;
zmk_mod_flags_t current = GET_MODIFIERS;
SET_MODIFIERS(explicit_modifiers | implicit_modifiers);
SET_MODIFIERS(explicit_modifiers);
return current == GET_MODIFIERS ? 0 : 1;
}
int zmk_hid_implicit_modifiers_release() {
implicit_modifiers = 0;
zmk_mod_flags_t current = GET_MODIFIERS;
SET_MODIFIERS(explicit_modifiers);
return current == GET_MODIFIERS ? 0 : 1;
}
int zmk_hid_masked_modifiers_set(zmk_mod_flags_t new_masked_modifiers) {
masked_modifiers = new_masked_modifiers;
zmk_mod_flags_t current = GET_MODIFIERS;
SET_MODIFIERS(explicit_modifiers);
return current == GET_MODIFIERS ? 0 : 1;
}
int zmk_hid_masked_modifiers_clear() {
masked_modifiers = 0;
zmk_mod_flags_t current = GET_MODIFIERS;
SET_MODIFIERS(explicit_modifiers);
return current == GET_MODIFIERS ? 0 : 1;

View file

@ -33,6 +33,7 @@ enum zmk_usb_conn_state zmk_usb_get_conn_state() {
switch (usb_status) {
case USB_DC_SUSPEND:
case USB_DC_CONFIGURED:
case USB_DC_RESUME:
return ZMK_USB_CONN_HID;
case USB_DC_DISCONNECTED:

View file

@ -0,0 +1,8 @@
s/.*hid_listener_keycode_pressed.*keycode/pressed: keycode/p
s/.*hid_listener_keycode_released.*keycode/released: keycode/p
s/.*hid_register_mod.*Modifiers set to /reg explicit: Modifiers set to /p
s/.*hid_unregister_mod.*Modifiers set to /unreg explicit: Modifiers set to /p
s/.*hid_implicit_modifiers_press.*Modifiers set to /reg implicit: Modifiers set to /p
s/.*hid_implicit_modifiers_release.*Modifiers set to /unreg implicit: Modifiers set to /p
s/.*hid_masked_modifiers_set.*Modifiers set to /mask mods: Modifiers set to /p
s/.*hid_masked_modifiers_clear.*Modifiers set to /unmask mods: Modifiers set to /p

View file

@ -0,0 +1,5 @@
pressed: keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
reg implicit: Modifiers set to 0x00
released: keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
unreg implicit: Modifiers set to 0x00
unmask mods: Modifiers set to 0x00

View file

@ -0,0 +1,11 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan_mock.h>
#include "../behavior_keymap.dtsi"
&kscan {
events = <
ZMK_MOCK_PRESS(0,1,10)
ZMK_MOCK_RELEASE(0,1,10)
>;
};

View file

@ -0,0 +1,8 @@
s/.*hid_listener_keycode_pressed.*keycode/pressed: keycode/p
s/.*hid_listener_keycode_released.*keycode/released: keycode/p
s/.*hid_register_mod.*Modifiers set to /reg explicit: Modifiers set to /p
s/.*hid_unregister_mod.*Modifiers set to /unreg explicit: Modifiers set to /p
s/.*hid_implicit_modifiers_press.*Modifiers set to /reg implicit: Modifiers set to /p
s/.*hid_implicit_modifiers_release.*Modifiers set to /unreg implicit: Modifiers set to /p
s/.*hid_masked_modifiers_set.*Modifiers set to /mask mods: Modifiers set to /p
s/.*hid_masked_modifiers_clear.*Modifiers set to /unmask mods: Modifiers set to /p

View file

@ -0,0 +1,12 @@
pressed: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
reg explicit: Modifiers set to 0x02
reg implicit: Modifiers set to 0x02
mask mods: Modifiers set to 0x00
pressed: keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
reg implicit: Modifiers set to 0x00
released: keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
unreg implicit: Modifiers set to 0x00
unmask mods: Modifiers set to 0x02
released: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
unreg explicit: Modifiers set to 0x00
unreg implicit: Modifiers set to 0x00

View file

@ -0,0 +1,13 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan_mock.h>
#include "../behavior_keymap.dtsi"
&kscan {
events = <
ZMK_MOCK_PRESS(1,0,10)
ZMK_MOCK_PRESS(0,1,10)
ZMK_MOCK_RELEASE(0,1,10)
ZMK_MOCK_RELEASE(1,0,10)
>;
};

View file

@ -0,0 +1,8 @@
s/.*hid_listener_keycode_pressed.*keycode/pressed: keycode/p
s/.*hid_listener_keycode_released.*keycode/released: keycode/p
s/.*hid_register_mod.*Modifiers set to /reg explicit: Modifiers set to /p
s/.*hid_unregister_mod.*Modifiers set to /unreg explicit: Modifiers set to /p
s/.*hid_implicit_modifiers_press.*Modifiers set to /reg implicit: Modifiers set to /p
s/.*hid_implicit_modifiers_release.*Modifiers set to /unreg implicit: Modifiers set to /p
s/.*hid_masked_modifiers_set.*Modifiers set to /mask mods: Modifiers set to /p
s/.*hid_masked_modifiers_clear.*Modifiers set to /unmask mods: Modifiers set to /p

View file

@ -0,0 +1,12 @@
pressed: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
reg explicit: Modifiers set to 0x02
reg implicit: Modifiers set to 0x02
mask mods: Modifiers set to 0x00
pressed: keycode 0x05 implicit_mods 0x02 explicit_mods 0x00
reg implicit: Modifiers set to 0x02
released: keycode 0x05 implicit_mods 0x02 explicit_mods 0x00
unreg implicit: Modifiers set to 0x00
unmask mods: Modifiers set to 0x02
released: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
unreg explicit: Modifiers set to 0x00
unreg implicit: Modifiers set to 0x00

View file

@ -0,0 +1,37 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan_mock.h>
/ {
behaviors {
mod_morph: mod_morph {
compatible = "zmk,behavior-mod-morph";
label = "MOD_MORPH_TEST";
#binding-cells = <0>;
bindings = <&kp A>, <&kp LS(B)>; // implict mod overwrite
mods = <(MOD_LSFT|MOD_RSFT)>;
};
};
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&kp LEFT_ALT &mod_morph
&kp LEFT_SHIFT &kp RIGHT_SHIFT
>;
};
};
};
&kscan {
events = <
ZMK_MOCK_PRESS(1,0,10)
ZMK_MOCK_PRESS(0,1,10)
ZMK_MOCK_RELEASE(0,1,10)
ZMK_MOCK_RELEASE(1,0,10)
>;
};

View file

@ -0,0 +1,8 @@
s/.*hid_listener_keycode_pressed.*keycode/pressed: keycode/p
s/.*hid_listener_keycode_released.*keycode/released: keycode/p
s/.*hid_register_mod.*Modifiers set to /reg explicit: Modifiers set to /p
s/.*hid_unregister_mod.*Modifiers set to /unreg explicit: Modifiers set to /p
s/.*hid_implicit_modifiers_press.*Modifiers set to /reg implicit: Modifiers set to /p
s/.*hid_implicit_modifiers_release.*Modifiers set to /unreg implicit: Modifiers set to /p
s/.*hid_masked_modifiers_set.*Modifiers set to /mask mods: Modifiers set to /p
s/.*hid_masked_modifiers_clear.*Modifiers set to /unmask mods: Modifiers set to /p

View file

@ -0,0 +1,18 @@
pressed: keycode 0xE2 implicit_mods 0x00 explicit_mods 0x00
reg explicit: Modifiers set to 0x04
reg implicit: Modifiers set to 0x04
pressed: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
reg explicit: Modifiers set to 0x06
reg implicit: Modifiers set to 0x06
mask mods: Modifiers set to 0x04
pressed: keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
reg implicit: Modifiers set to 0x04
released: keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
unreg implicit: Modifiers set to 0x04
unmask mods: Modifiers set to 0x06
released: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
unreg explicit: Modifiers set to 0x04
unreg implicit: Modifiers set to 0x04
released: keycode 0xE2 implicit_mods 0x00 explicit_mods 0x00
unreg explicit: Modifiers set to 0x00
unreg implicit: Modifiers set to 0x00

View file

@ -0,0 +1,15 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan_mock.h>
#include "../behavior_keymap.dtsi"
&kscan {
events = <
ZMK_MOCK_PRESS(0,0,10)
ZMK_MOCK_PRESS(1,0,10)
ZMK_MOCK_PRESS(0,1,10)
ZMK_MOCK_RELEASE(0,1,10)
ZMK_MOCK_RELEASE(1,0,10)
ZMK_MOCK_RELEASE(0,0,10)
>;
};

View file

@ -0,0 +1,8 @@
s/.*hid_listener_keycode_pressed.*keycode/pressed: keycode/p
s/.*hid_listener_keycode_released.*keycode/released: keycode/p
s/.*hid_register_mod.*Modifiers set to /reg explicit: Modifiers set to /p
s/.*hid_unregister_mod.*Modifiers set to /unreg explicit: Modifiers set to /p
s/.*hid_implicit_modifiers_press.*Modifiers set to /reg implicit: Modifiers set to /p
s/.*hid_implicit_modifiers_release.*Modifiers set to /unreg implicit: Modifiers set to /p
s/.*hid_masked_modifiers_set.*Modifiers set to /mask mods: Modifiers set to /p
s/.*hid_masked_modifiers_clear.*Modifiers set to /unmask mods: Modifiers set to /p

View file

@ -0,0 +1,12 @@
pressed: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
reg explicit: Modifiers set to 0x02
reg implicit: Modifiers set to 0x02
mask mods: Modifiers set to 0x00
pressed: keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
reg implicit: Modifiers set to 0x00
released: keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
unreg implicit: Modifiers set to 0x00
unmask mods: Modifiers set to 0x02
released: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
unreg explicit: Modifiers set to 0x00
unreg implicit: Modifiers set to 0x00

View file

@ -0,0 +1,45 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan_mock.h>
&kscan {
events = <
/* Shift + tap &mod_morph --> expect B (but get Shift + B) */
ZMK_MOCK_PRESS(0,0,10)
ZMK_MOCK_PRESS(0,1,10)
ZMK_MOCK_RELEASE(0,1,10)
ZMK_MOCK_RELEASE(0,0,10)
>;
};
/ {
behaviors {
mod_morph: mod_morph {
compatible = "zmk,behavior-mod-morph";
label = "MOD_MORPH_TEST";
#binding-cells = <0>;
bindings = <&kp A>, <&lt 1 B>;
mods = <(MOD_LSFT|MOD_RSFT)>;
};
};
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&kp LEFT_SHIFT &mod_morph
&kp C &none
>;
};
second_layer {
bindings = <
&trans &trans
&kp D &trans
>;
};
};
};

View file

@ -0,0 +1,8 @@
s/.*hid_listener_keycode_pressed.*keycode/pressed: keycode/p
s/.*hid_listener_keycode_released.*keycode/released: keycode/p
s/.*hid_register_mod.*Modifiers set to /reg explicit: Modifiers set to /p
s/.*hid_unregister_mod.*Modifiers set to /unreg explicit: Modifiers set to /p
s/.*hid_implicit_modifiers_press.*Modifiers set to /reg implicit: Modifiers set to /p
s/.*hid_implicit_modifiers_release.*Modifiers set to /unreg implicit: Modifiers set to /p
s/.*hid_masked_modifiers_set.*Modifiers set to /mask mods: Modifiers set to /p
s/.*hid_masked_modifiers_clear.*Modifiers set to /unmask mods: Modifiers set to /p

View file

@ -0,0 +1,12 @@
pressed: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
reg explicit: Modifiers set to 0x02
reg implicit: Modifiers set to 0x02
mask mods: Modifiers set to 0x00
pressed: keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
reg implicit: Modifiers set to 0x00
released: keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
unreg implicit: Modifiers set to 0x00
unmask mods: Modifiers set to 0x02
released: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
unreg explicit: Modifiers set to 0x00
unreg implicit: Modifiers set to 0x00

View file

@ -0,0 +1,47 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan_mock.h>
&kscan {
events = <
/* Shift + hold &mod_morph --> expect and get D (no shift) */
ZMK_MOCK_PRESS(0,0,10)
ZMK_MOCK_PRESS(0,1,200)
ZMK_MOCK_PRESS(1,0,10)
ZMK_MOCK_RELEASE(1,0,10)
ZMK_MOCK_RELEASE(0,1,10)
ZMK_MOCK_RELEASE(0,0,10)
>;
};
/ {
behaviors {
mod_morph: mod_morph {
compatible = "zmk,behavior-mod-morph";
label = "MOD_MORPH_TEST";
#binding-cells = <0>;
bindings = <&kp A>, <&lt 1 B>;
mods = <(MOD_LSFT|MOD_RSFT)>;
};
};
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&kp LEFT_SHIFT &mod_morph
&kp C &none
>;
};
second_layer {
bindings = <
&trans &trans
&kp D &trans
>;
};
};
};

View file

@ -0,0 +1,8 @@
s/.*hid_listener_keycode_pressed.*keycode/pressed: keycode/p
s/.*hid_listener_keycode_released.*keycode/released: keycode/p
s/.*hid_register_mod.*Modifiers set to /reg explicit: Modifiers set to /p
s/.*hid_unregister_mod.*Modifiers set to /unreg explicit: Modifiers set to /p
s/.*hid_implicit_modifiers_press.*Modifiers set to /reg implicit: Modifiers set to /p
s/.*hid_implicit_modifiers_release.*Modifiers set to /unreg implicit: Modifiers set to /p
s/.*hid_masked_modifiers_set.*Modifiers set to /mask mods: Modifiers set to /p
s/.*hid_masked_modifiers_clear.*Modifiers set to /unmask mods: Modifiers set to /p

View file

@ -0,0 +1,12 @@
pressed: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
reg explicit: Modifiers set to 0x02
reg implicit: Modifiers set to 0x02
mask mods: Modifiers set to 0x02
pressed: keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
reg implicit: Modifiers set to 0x02
released: keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
unreg implicit: Modifiers set to 0x02
unmask mods: Modifiers set to 0x02
released: keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
unreg explicit: Modifiers set to 0x00
unreg implicit: Modifiers set to 0x00

View file

@ -0,0 +1,37 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan_mock.h>
/ {
behaviors {
mod_morph: mod_morph {
compatible = "zmk,behavior-mod-morph";
label = "MOD_MORPH_TEST";
#binding-cells = <0>;
bindings = <&kp A>, <&kp B>;
mods = <(MOD_LSFT|MOD_RSFT)>;
keep-mods = <(MOD_LSFT|MOD_RSFT)>; // no masking
};
};
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&kp LEFT_ALT &mod_morph
&kp LEFT_SHIFT &kp RIGHT_SHIFT
>;
};
};
};
&kscan {
events = <
ZMK_MOCK_PRESS(1,0,10)
ZMK_MOCK_PRESS(0,1,10)
ZMK_MOCK_RELEASE(0,1,10)
ZMK_MOCK_RELEASE(1,0,10)
>;
};

View file

@ -0,0 +1,23 @@
/ {
behaviors {
mod_morph: mod_morph {
compatible = "zmk,behavior-mod-morph";
label = "MOD_MORPH_TEST";
#binding-cells = <0>;
bindings = <&kp A>, <&kp B>;
mods = <(MOD_LSFT|MOD_RSFT)>;
};
};
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&kp LEFT_ALT &mod_morph
&kp LEFT_SHIFT &kp RIGHT_SHIFT
>;
};
};
};

View file

@ -7,7 +7,7 @@ mods: Modifiers set to 0x03
released: usage_page 0x07 keycode 0xE0 implicit_mods 0x00 explicit_mods 0x00
unreg: Modifier 0 count: 0
unreg: Modifier 0 released
unreg: Modifiers set to 0x00
unreg: Modifiers set to 0x02
mods: Modifiers set to 0x00
released: usage_page 0x07 keycode 0x05 implicit_mods 0x02 explicit_mods 0x00
mods: Modifiers set to 0x00

View file

@ -28,7 +28,7 @@ We call this the 'hold-preferred' flavor of hold-taps. While this flavor may wor
- The 'hold-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired or another key is pressed.
- The 'balanced' flavor will trigger the hold behavior when the `tapping-term-ms` has expired or another key is pressed and released.
- The 'tap-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired. It triggers the tap behavior when another key is pressed.
- The 'tap-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired. Pressing another key within `tapping-term-ms` does not affect the decision.
- The 'tap-unless-interrupted' flavor triggers a hold behavior only when another key is pressed before `tapping-term-ms` has expired. It triggers the tap behavior in all other situations.
When the hold-tap key is released and the hold behavior has not been triggered, the tap behavior will trigger.
@ -139,7 +139,7 @@ defaultValue="homerow_mods"
values={[
{label: 'Homerow Mods', value: 'homerow_mods'},
{label: 'Autoshift', value: 'autoshift'},
{label: 'Toggle-on-Tap, Momentary-on-Hold Layers', value: 'tog_mo'},
{label: 'Toggle-on-Tap, Momentary-on-Hold Layers', value: 'mo_tog'},
]}>
<TabItem value="homerow_mods">
@ -276,25 +276,25 @@ A popular method of implementing Autoshift in ZMK involves a C-preprocessor macr
</TabItem>
<TabItem value="tog_mo">
<TabItem value="mo_tog">
This hold-tap example implements a [toggle-layer](layers.md/#toggle-layer) when the keybind is tapped and a [momentary-layer](layers.md/#momentary-layer) when it is held. Similarly to the Autoshift and Sticky Hold use-cases, a `TOG_MO(layer)` macro is defined such that the `&tog` and `&mo` behaviors can target a single layer.
This hold-tap example implements a [momentary-layer](layers.md/#momentary-layer) when the keybind is held and a [toggle-layer](layers.md/#toggle-layer) when it is tapped. Similar to the Autoshift and Sticky Hold use-cases, a `MO_TOG(layer)` macro is defined such that the `&mo` and `&tog` behaviors can target a single layer.
```dtsi title="Hold-Tap Example: Toggle layer on Tap, Momentary layer on Hold"
```dtsi title="Hold-Tap Example: Momentary layer on Hold, Toggle layer on Tap"
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#define TOG_MO(layer) &tog_mo layer layer // Macro to apply toggle-layer-on-tap/momentary-layer-on-hold to a specific layer
#define MO_TOG(layer) &mo_tog layer layer // Macro to apply momentary-layer-on-hold/toggle-layer-on-tap to a specific layer
/ {
behaviors {
tog_mo: behavior_mo_tog {
mo_tog: behavior_mo_tog {
compatible = "zmk,behavior-hold-tap";
label = "mo_tog";
#binding-cells = <2>;
flavor = "hold-preferred";
tapping-term-ms = <200>;
bindings = <&tog>, <&mo>;
bindings = <&mo>, <&tog>;
};
};
@ -302,8 +302,8 @@ This hold-tap example implements a [toggle-layer](layers.md/#toggle-layer) when
compatible = "zmk,keymap";
default_layer {
bindings = <
&tog_mo 2 1 // &mo 2 on hold, &tog 1 on tap
TOG_MO(3) // &mo 3 on hold, &tog 3 on tap
&mo_tog 2 1 // &mo 2 on hold, &tog 1 on tap
MO_TOG(3) // &mo 3 on hold, &tog 3 on tap
>;
};
};

View file

@ -14,8 +14,6 @@ The Mod-Morph behavior sends a different keypress, depending on whether a specif
The Mod-Morph behavior acts as one of two keycodes, depending on if the required modifier is being held during the keypress.
When the modifier is being held it is sent along with the morphed keycode. This can cause problems when the morphed keycode and modifier have an existing relationship (such as `shift-delete` or `ctrl-v` on many operating systems).
### Configuration
An example of how to implement the mod-morph "Grave Escape":
@ -31,10 +29,6 @@ An example of how to implement the mod-morph "Grave Escape":
mods = <(MOD_LGUI|MOD_LSFT|MOD_RGUI|MOD_RSFT)>;
};
};
keymap {
...
};
};
```
@ -71,3 +65,26 @@ Example:
```
mods = <(MOD_LGUI|MOD_LSFT|MOD_RGUI|MOD_RSFT)>;
```
### Advanced configuration
`keep-mods`
When a modifier specified in `mods` is being held, it won't be sent along with the morphed keycode unless it is also specified in `keep-mods`. By default `keep-mods` equals `0`, which means no modifier specified in `mods` will be sent along with the morphed keycode.
For example, the following configuration morphs `LEFT_SHIFT` + `BACKSPACE` into `DELETE`, and morphs `RIGHT_SHIFT` + `BACKSPACE` into `RIGHT_SHIFT` + `DELETE`.
```
/ {
behaviors {
bspc_del: backspace_delete {
compatible = "zmk,behavior-mod-morph";
label = "BACKSPACE_DELETE";
#binding-cells = <0>;
bindings = <&kp BACKSPACE>, <&kp DELETE>;
mods = <(MOD_LSFT|MOD_RSFT)>;
keep-mods = <(MOD_RSFT)>;
};
};
};
```

View file

@ -5,6 +5,7 @@ hide_title: true
slug: ./
---
import SpellingCaution from "@site/src/components/codes/SpellingCaution";
import OsLegend from "@site/src/components/codes/OsLegend";
import ToastyContainer from "@site/src/components/codes/ToastyContainer";
import Key, { toc as keyToc } from "./_keyboard-keypad.mdx";
@ -23,6 +24,7 @@ export const toc = [
...powerToc,
];
<SpellingCaution />
<OsLegend />
<ToastyContainer />
<Key />

View file

@ -93,9 +93,11 @@ Keyboard scan driver where keys are arranged on a matrix with one GPIO per row a
Definition file: [zmk/app/drivers/kscan/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/kscan/Kconfig)
| Config | Type | Description | Default |
| --------------------------------- | ---- | ------------------------------------------------ | ------- |
| `CONFIG_ZMK_KSCAN_MATRIX_POLLING` | bool | Poll for key presses instead of using interrupts | n |
| Config | Type | Description | Default |
| ---------------------------------------------- | ----------- | ------------------------------------------------------------------------- | ------- |
| `CONFIG_ZMK_KSCAN_MATRIX_POLLING` | bool | Poll for key presses instead of using interrupts | n |
| `CONFIG_ZMK_KSCAN_MATRIX_WAIT_BEFORE_INPUTS` | int (ticks) | How long to wait before reading input pins after setting output active | 0 |
| `CONFIG_ZMK_KSCAN_MATRIX_WAIT_BETWEEN_OUTPUTS` | int (ticks) | How long to wait between each output to allow previous output to "settle" | 0 |
### Devicetree

View file

@ -21,13 +21,13 @@ export const toc = [
id: "composite",
level: 2,
},
...Object.values(groupedMetadata(Metadata).interconnects).map(
({ interconnect }) => ({
...Object.values(groupedMetadata(Metadata).interconnects)
.filter((ic) => ic.interconnect !== undefined)
.map(({ interconnect }) => ({
value: `${interconnect.name} Interconnect`,
id: interconnect.id,
level: 3,
})
),
})),
{
value: "Other Hardware",
id: "other-hardware",

102
docs/package-lock.json generated
View file

@ -3323,6 +3323,15 @@
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
"integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.11",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz",
@ -8413,36 +8422,6 @@
"node": ">= 12"
}
},
"node_modules/html-minifier-terser/node_modules/source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
"engines": {
"node": ">= 8"
}
},
"node_modules/html-minifier-terser/node_modules/terser": {
"version": "5.12.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz",
"integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==",
"dependencies": {
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map": "~0.7.2",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
"node": ">=10"
}
},
"node_modules/html-minifier-terser/node_modules/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"node_modules/html-tags": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz",
@ -13561,12 +13540,13 @@
}
},
"node_modules/terser": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz",
"integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==",
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map": "~0.7.2",
"source-map-support": "~0.5.20"
},
"bin": {
@ -13614,14 +13594,6 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"node_modules/terser/node_modules/source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
"engines": {
"node": ">= 8"
}
},
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@ -17436,6 +17408,15 @@
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz",
"integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ=="
},
"@jridgewell/source-map": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
"integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
"requires": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"@jridgewell/sourcemap-codec": {
"version": "1.4.11",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz",
@ -21282,29 +21263,6 @@
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
},
"source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
},
"terser": {
"version": "5.12.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz",
"integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==",
"requires": {
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map": "~0.7.2",
"source-map-support": "~0.5.20"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
}
}
}
}
},
@ -25015,12 +24973,13 @@
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="
},
"terser": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz",
"integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==",
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"requires": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map": "~0.7.2",
"source-map-support": "~0.5.20"
},
"dependencies": {
@ -25028,11 +24987,6 @@
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
}
}
},

View file

@ -0,0 +1,22 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: CC-BY-NC-SA-4.0
*/
import React from "react";
import Admonition from "@theme/Admonition";
export default function SpellingCaution() {
return (
<Admonition type="caution">
<p>
Take extra notice of the spelling of the keycodes, especially the
shorthand spelling. Otherwise, it will result in an elusive parsing
error!
</p>
</Admonition>
);
}
SpellingCaution.propTypes = {};

View file

@ -41,7 +41,11 @@ function groupedShield(agg: GroupedMetadata, shield: Shield) {
ic.shields.push(shield);
agg.interconnects[id] = ic;
});
shield.exposes?.forEach((id) => {
let ic = agg.interconnects[id] ?? { boards: [], shields: [] };
ic.shields.push(shield);
agg.interconnects[id] = ic;
});
return agg;
}

View file

@ -1356,7 +1356,7 @@ export default [
footnotes: {},
},
{
names: ["NON_US_HASH"],
names: ["NON_US_HASH", "NUHS"],
description: "Non-US # [Hash/Pound] and ~ [Tilde]",
context: "Keyboard",
clarify: false,
@ -2606,7 +2606,7 @@ export default [
footnotes: {},
},
{
names: ["NON_US_BACKSLASH", "NON_US_BSLH"],
names: ["NON_US_BACKSLASH", "NON_US_BSLH", "NUBS"],
description: "Non-US \\ [Backslash] and | [Pipe]",
context: "Keyboard",
clarify: false,
@ -2732,7 +2732,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2753,7 +2753,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2774,7 +2774,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2795,7 +2795,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2816,7 +2816,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2837,7 +2837,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2858,7 +2858,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2879,7 +2879,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2900,7 +2900,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2921,7 +2921,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2942,7 +2942,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,
@ -2963,7 +2963,7 @@ export default [
],
documentation: "https://usb.org/sites/default/files/hut1_2.pdf#page=86",
os: {
windows: null,
windows: true,
linux: true,
android: false,
macos: true,

View file

@ -96,4 +96,10 @@ export const displayPower = {
active: 10000, // Estimated power draw when about half the pixels are on
sleep: 7, // Deep sleep power draw (display off)
},
// Based on the nice!view using Sharp's LS011B7DH01
NICEVIEW: {
activePercent: 0.01, // Estimated two refreshes per second taking five milliseconds each
active: 1425, // Power draw during refresh (225uA display + 1200uA SPIM)
sleep: 1, // Idle power draw of the display
},
};

View file

@ -308,6 +308,7 @@ function PowerProfiler() {
</option>
<option value="EPAPER">ePaper</option>
<option value="OLED">OLED</option>
<option value="NICEVIEW">nice!view</option>
</select>
</div>
)}