Merge branch 'zmkfirmware:main' into main

This commit is contained in:
DonPavlov 2021-08-25 20:24:47 +02:00 committed by GitHub
commit 30030f4ef9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
105 changed files with 11170 additions and 6539 deletions

View file

@ -1,4 +1,4 @@
FROM zmkfirmware/zmk-dev-arm:2.4
FROM zmkfirmware/zmk-dev-arm:2.5
COPY .bashrc tmp
RUN mv /tmp/.bashrc ~/.bashrc

View file

@ -14,12 +14,13 @@ jobs:
build:
runs-on: ubuntu-latest
container:
image: zmkfirmware/zmk-build-arm:2.4
image: zmkfirmware/zmk-build-arm:2.5
strategy:
matrix:
board:
- bluemicro840_v1
- nice_nano
- nice_nano_v2
- nrfmicro_13
- proton_c
shield:
@ -70,11 +71,11 @@ jobs:
- board: planck_rev6
- board: proton_c
shield: clueboard_california
- board: nice_nano
- board: nice_nano_v2
shield: kyria_left
cmake-args: -DCONFIG_ZMK_DISPLAY=y
skip-archive: true
- board: nice_nano
- board: nice_nano_v2
shield: kyria_right
cmake-args: -DCONFIG_ZMK_DISPLAY=y
skip-archive: true

View file

@ -16,7 +16,7 @@ jobs:
integration_test:
runs-on: ubuntu-latest
container:
image: zmkfirmware/zmk-build-arm:2.4
image: zmkfirmware/zmk-build-arm:2.5
steps:
- name: Checkout
uses: actions/checkout@v2

View file

@ -91,7 +91,7 @@ You can setup git to run prettier automatically when you commit by installing th
### Development Setup
To get your development environment setup going, start at the
[basic setup](https://zmk.dev/docs/dev-setup) docs, and make sure you can build and flash
[basic setup](https://zmk.dev/docs/development/setup/) docs, and make sure you can build and flash
your own locally built firmware.
### Formatting

View file

@ -36,6 +36,7 @@ target_sources(app PRIVATE src/events/position_state_changed.c)
target_sources(app PRIVATE src/events/layer_state_changed.c)
target_sources(app PRIVATE src/events/keycode_state_changed.c)
target_sources(app PRIVATE src/events/modifiers_state_changed.c)
target_sources(app PRIVATE src/events/endpoint_selection_changed.c)
target_sources(app PRIVATE src/events/sensor_event.c)
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c)

View file

@ -263,14 +263,11 @@ config ZMK_SLEEP
if ZMK_SLEEP
config SYS_POWER_DEEP_SLEEP_STATES
default y
choice SYS_PM_POLICY
default SYS_PM_POLICY_APP
default PM_POLICY_APP
endchoice
config DEVICE_POWER_MANAGEMENT
config PM_DEVICE
default y
config ZMK_IDLE_SLEEP_TIMEOUT
@ -422,6 +419,11 @@ config ZMK_WPM
config SENSOR
default y
choice CBPRINTF_IMPLEMENTATION
default CBPRINTF_NANO
endchoice
module = ZMK
module-str = zmk
source "subsys/logging/Kconfig.template.log_config"

View file

@ -11,6 +11,9 @@ CONFIG_FPU=y
# enable GPIO
CONFIG_GPIO=y
# Enable pinmux
CONFIG_PINMUX=y
# Needed to reduce this to size that will fit on F072
CONFIG_HEAP_MEM_POOL_SIZE=1024

View file

@ -4,4 +4,4 @@ config BOARD_ENABLE_DCDC
bool "Enable DCDC mode"
select SOC_DCDC_NRF52X
default y
depends on BOARD_NICE_NANO
depends on (BOARD_NICE_NANO || BOARD_NICE_NANO_V2)

View file

@ -7,3 +7,7 @@ config BOARD_NICE_NANO
bool "nice!nano"
depends on SOC_NRF52840_QIAA
config BOARD_NICE_NANO_V2
bool "nice!nano v2"
depends on SOC_NRF52840_QIAA

View file

@ -1,7 +1,7 @@
# Copyright (c) 2020 Pete Johanson
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
if BOARD_NICE_NANO
if BOARD_NICE_NANO || BOARD_NICE_NANO_V2
config BOARD
default "nice_nano"
@ -25,7 +25,18 @@ config ZMK_BLE
config ZMK_USB
default y
endif # BOARD_NICE_NANO || BOARD_NICE_NANO_V2
if BOARD_NICE_NANO
config ZMK_BATTERY_VOLTAGE_DIVIDER
default y
endif # BOARD_NICE_NANO
if BOARD_NICE_NANO_V2
config ZMK_BATTERY_NRF_VDDH
default y
endif # BOARD_NICE_NANO_V2

View file

@ -1,31 +1,13 @@
/*
* Copyright (c) 2020 Pete Johanson
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
/dts-v1/;
#include <nordic/nrf52840_qiaa.dtsi>
#include "arduino_pro_micro_pins.dtsi"
#include "nice_nano.dtsi"
/ {
model = "nice!nano";
compatible = "nice,nano";
chosen {
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
};
leds {
compatible = "gpio-leds";
blue_led: led_0 {
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
label = "Blue LED";
};
};
ext-power {
compatible = "zmk,ext-power-generic";
label = "EXT_POWER";
@ -40,76 +22,3 @@
full-ohms = <(2000000 + 806000)>;
};
};
&adc {
status = "okay";
};
&gpiote {
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&i2c0 {
compatible = "nordic,nrf-twi";
sda-pin = <17>;
scl-pin = <20>;
};
&uart0 {
compatible = "nordic,nrf-uarte";
tx-pin = <6>;
rx-pin = <8>;
};
&usbd {
status = "okay";
};
&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,100 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <nordic/nrf52840_qiaa.dtsi>
#include "arduino_pro_micro_pins.dtsi"
/ {
model = "nice!nano";
compatible = "nice,nano";
chosen {
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
};
leds {
compatible = "gpio-leds";
blue_led: led_0 {
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
label = "Blue LED";
};
};
};
&adc {
status = "okay";
};
&gpiote {
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&i2c0 {
compatible = "nordic,nrf-twi";
sda-pin = <17>;
scl-pin = <20>;
};
&uart0 {
compatible = "nordic,nrf-uarte";
tx-pin = <6>;
rx-pin = <8>;
};
&usbd {
status = "okay";
};
&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,22 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
/dts-v1/;
#include "nice_nano.dtsi"
/ {
ext-power {
compatible = "zmk,ext-power-generic";
label = "EXT_POWER";
control-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
init-delay-ms = <10>;
};
vbatt {
compatible = "zmk,battery-nrf-vddh";
label = "BATTERY";
};
};

View file

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

View file

@ -0,0 +1,20 @@
# SPDX-License-Identifier: MIT
CONFIG_SOC_SERIES_NRF52X=y
CONFIG_SOC_NRF52840_QIAA=y
CONFIG_BOARD_NICE_NANO_V2=y
# Enable MPU
CONFIG_ARM_MPU=y
# enable GPIO
CONFIG_GPIO=y
CONFIG_USE_DT_CODE_PARTITION=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

View file

@ -6,6 +6,7 @@
/dts-v1/;
#include <st/f3/stm32f303Xc.dtsi>
#include <dt-bindings/zmk/matrix_transform.h>
/ {
model = "Plack PCD, rev6";
@ -15,11 +16,13 @@
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zmk,kscan = &kscan0;
zmk,matrix_transform = &layout_grid_transform;
};
kscan0: kscan {
compatible = "zmk,kscan-gpio-matrix";
label = "KSCAN";
diode-direction = "col2row";
row-gpios
= <&gpioa 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&gpioa 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
@ -40,6 +43,42 @@
;
};
layout_grid_transform:
keymap_transform_0 {
compatible = "zmk,matrix-transform";
columns = <6>;
rows = <8>;
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5)
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(5,0) RC(5,1) RC(5,2) RC(5,3) RC(5,4) RC(5,5)
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(6,0) RC(6,1) RC(6,2) RC(6,3) RC(6,4) RC(6,5)
RC(3,0) RC(3,1) RC(3,2) RC(7,3) RC(7,4) RC(7,5) RC(7,0) RC(7,1) RC(7,2) RC(3,3) RC(3,4) RC(3,5)
>;
};
layout_mit_transform:
keymap_transform_1 {
compatible = "zmk,matrix-transform";
columns = <6>;
rows = <8>;
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5)
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(5,0) RC(5,1) RC(5,2) RC(5,3) RC(5,4) RC(5,5)
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(6,0) RC(6,1) RC(6,2) RC(6,3) RC(6,4) RC(6,5)
RC(3,0) RC(3,1) RC(3,2) RC(7,3) RC(7,4) RC(7,0) RC(7,1) RC(7,2) RC(3,3) RC(3,4) RC(3,5)
>;
};
layout_2x2u_transform:
keymap_transform_2 {
compatible = "zmk,matrix-transform";
columns = <6>;
rows = <8>;
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5)
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(5,0) RC(5,1) RC(5,2) RC(5,3) RC(5,4) RC(5,5)
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(6,0) RC(6,1) RC(6,2) RC(6,3) RC(6,4) RC(6,5)
RC(3,0) RC(3,1) RC(3,2) RC(7,3) RC(7,5) RC(7,1) RC(7,2) RC(3,3) RC(3,4) RC(3,5)
>;
};
};
&usb {

View file

@ -1,7 +0,0 @@
# SPDX-License-Identifier: MIT
if(CONFIG_PINMUX)
zephyr_library()
zephyr_library_sources(pinmux.c)
zephyr_library_include_directories(${ZEPHYR_BASE}/drivers)
endif()

View file

@ -48,5 +48,5 @@
};
pro_micro_i2c: &i2c1 {};
pro_micro_spi: &spi1 {};
pro_micro_spi: &spi2 {};
pro_micro_serial: &usart1 {};

View file

@ -1,67 +0,0 @@
/*
* Copyright (c) 2017 I-SENSE group of ICCS
*
* SPDX-License-Identifier: MIT
*/
#include <kernel.h>
#include <device.h>
#include <init.h>
#include <drivers/pinmux.h>
#include <sys/sys_io.h>
#include <pinmux/stm32/pinmux_stm32.h>
/* pin assignments for STM32F3DISCOVERY board */
static const struct pin_config pinconf[] = {
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay) && CONFIG_SERIAL
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay) && CONFIG_SERIAL
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) && CONFIG_I2C
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay) && CONFIG_I2C
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI
#ifdef CONFIG_SPI_STM32_USE_HW_SS
{STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay) && CONFIG_SPI
#ifdef CONFIG_SPI_STM32_USE_HW_SS
{STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
#endif
#ifdef CONFIG_USB_DC_STM32
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
#endif /* CONFIG_USB_DC_STM32 */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) && CONFIG_CAN
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
#endif
};
static int pinmux_stm32_init(const struct device *port) {
ARG_UNUSED(port);
stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
return 0;
}
SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);

View file

@ -6,6 +6,7 @@
/dts-v1/;
#include <st/f3/stm32f303Xc.dtsi>
#include <st/f3/stm32f303c(b-c)tx-pinctrl.dtsi>
#include "arduino_pro_micro_pins.dtsi"
/ {
@ -26,6 +27,18 @@
};
};
&usart1 {
pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>;
};
&spi2 {
pinctrl-0 = <&spi2_sck_pb13 &spi2_miso_pb14 &spi2_mosi_pb15>;
};
&i2c1 {
pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pb7>;
};
&usb {
status = "okay";
};

View file

@ -16,40 +16,40 @@
// -----------------------------------------------------------------------------------------
// | TAB | Q | W | E | R | T | | Y | U | I | O | P | BKSP |
// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' |
// | SHFT | Z | X | C | V | B | | N | M | , | . | / | SHFT |
// | SHFT | Z | X | C | V | B | | N | M | , | . | / | ESC |
// | GUI | LWR | SPC | | ENT | RSE | ALT |
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 LCTRL &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 FSLH &kp RSHFT
&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp ESC
&kp LGUI &mo 1 &kp SPACE &kp RET &mo 2 &kp RALT
>;
};
lower_layer {
// -----------------------------------------------------------------------------------------
// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | BKSP |
// | TAB | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | BKSP |
// | BTCLR| BT1 | BT2 | BT3 | BT4 | BT5 | | LFT | DWN | UP | RGT | | |
// | SHFT | | | | | | | | | | | | |
// | GUI | | SPC | | ENT | | ALT |
bindings = <
&kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp BSPC
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &kp LEFT &kp DOWN &kp UP &kp RIGHT &trans &trans
&kp LSHFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
&kp LGUI &trans &kp SPACE &kp RET &trans &kp RALT
&kp TAB &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp BSPC
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &kp LEFT &kp DOWN &kp UP &kp RIGHT &trans &trans
&kp LSHFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
&kp LGUI &trans &kp SPACE &kp RET &trans &kp RALT
>;
};
raise_layer {
// -----------------------------------------------------------------------------------------
// | ESC | ! | @ | # | $ | % | | ^ | & | * | ( | ) | BKSP |
// | CTRL | | | | | | | - | = | { | } | "|" | ` |
// | SHFT | | | | | | | _ | + | [ | ] | \ | ~ | // TODO: Fix this row when &mkp is committed
// | TAB | ! | @ | # | $ | % | | ^ | & | * | ( | ) | BKSP |
// | CTRL | | | | | | | - | = | [ | ] | \ | ` |
// | SHFT | | | | | | | _ | + | { | } | "|" | ~ |
// | GUI | | SPC | | ENT | | ALT |
bindings = <
&kp ESC &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp KP_MULTIPLY &kp LPAR &kp RPAR &kp BSPC
&kp LCTRL &trans &trans &trans &trans &trans &kp MINUS &kp EQUAL &kp LBKT &kp RBKT &kp PIPE &kp GRAVE
&kp LSHFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &kp BSLH &kp TILDE
&kp LGUI &trans &kp SPACE &kp RET &trans &kp RALT
&kp TAB &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp KP_MULTIPLY &kp LPAR &kp RPAR &kp BSPC
&kp LCTRL &trans &trans &trans &trans &trans &kp MINUS &kp EQUAL &kp LBKT &kp RBKT &kp BSLH &kp GRAVE
&kp LSHFT &trans &trans &trans &trans &trans &kp UNDER &kp PLUS &kp LBRC &kp RBRC &kp PIPE &kp TILDE
&kp LGUI &trans &kp SPACE &kp RET &trans &kp RALT
>;
};
};

View file

@ -2,4 +2,5 @@
# SPDX-License-Identifier: MIT
add_subdirectory(kscan)
add_subdirectory(sensor)
add_subdirectory(sensor)
add_subdirectory(display)

View file

@ -2,4 +2,5 @@
# SPDX-License-Identifier: MIT
rsource "kscan/Kconfig"
rsource "sensor/Kconfig"
rsource "sensor/Kconfig"
rsource "display/Kconfig"

View file

@ -0,0 +1,4 @@
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
zephyr_sources_ifdef(CONFIG_IL0323 il0323.c)

View file

@ -0,0 +1,4 @@
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
rsource "Kconfig.il0323"

View file

@ -0,0 +1,11 @@
# Copyright (c) 2020 Phytec Messtechnik GmbH, Peter Johanson
# SPDX-License-Identifier: Apache-2.0
# IL0323 display controller configuration options
config IL0323
bool "IL0323 compatible display controller driver"
depends on SPI
depends on HEAP_MEM_POOL_SIZE != 0
help
Enable driver for IL0323 compatible controller.

View file

@ -0,0 +1,432 @@
/*
* Copyright (c) 2020 PHYTEC Messtechnik GmbHH, Peter Johanson
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT gooddisplay_il0323
#include <string.h>
#include <device.h>
#include <init.h>
#include <drivers/display.h>
#include <drivers/gpio.h>
#include <drivers/spi.h>
#include <sys/byteorder.h>
#include "il0323_regs.h"
#include <logging/log.h>
LOG_MODULE_REGISTER(il0323, CONFIG_DISPLAY_LOG_LEVEL);
/**
* IL0323 compatible EPD controller driver.
*
*/
#define IL0323_SPI_FREQ DT_INST_PROP(0, spi_max_frequency)
#define IL0323_BUS_NAME DT_INST_BUS_LABEL(0)
#define IL0323_DC_PIN DT_INST_GPIO_PIN(0, dc_gpios)
#define IL0323_DC_FLAGS DT_INST_GPIO_FLAGS(0, dc_gpios)
#define IL0323_DC_CNTRL DT_INST_GPIO_LABEL(0, dc_gpios)
#define IL0323_CS_PIN DT_INST_SPI_DEV_CS_GPIOS_PIN(0)
#define IL0323_CS_FLAGS DT_INST_SPI_DEV_CS_GPIOS_FLAGS(0)
#if DT_INST_SPI_DEV_HAS_CS_GPIOS(0)
#define IL0323_CS_CNTRL DT_INST_SPI_DEV_CS_GPIOS_LABEL(0)
#endif
#define IL0323_BUSY_PIN DT_INST_GPIO_PIN(0, busy_gpios)
#define IL0323_BUSY_CNTRL DT_INST_GPIO_LABEL(0, busy_gpios)
#define IL0323_BUSY_FLAGS DT_INST_GPIO_FLAGS(0, busy_gpios)
#define IL0323_RESET_PIN DT_INST_GPIO_PIN(0, reset_gpios)
#define IL0323_RESET_CNTRL DT_INST_GPIO_LABEL(0, reset_gpios)
#define IL0323_RESET_FLAGS DT_INST_GPIO_FLAGS(0, reset_gpios)
#define EPD_PANEL_WIDTH DT_INST_PROP(0, width)
#define EPD_PANEL_HEIGHT DT_INST_PROP(0, height)
#define IL0323_PIXELS_PER_BYTE 8U
/* Horizontally aligned page! */
#define IL0323_NUMOF_PAGES (EPD_PANEL_WIDTH / IL0323_PIXELS_PER_BYTE)
#define IL0323_PANEL_FIRST_GATE 0U
#define IL0323_PANEL_LAST_GATE (EPD_PANEL_HEIGHT - 1)
#define IL0323_PANEL_FIRST_PAGE 0U
#define IL0323_PANEL_LAST_PAGE (IL0323_NUMOF_PAGES - 1)
#define IL0323_BUFFER_SIZE 1280
struct il0323_data {
const struct device *reset;
const struct device *dc;
const struct device *busy;
const struct device *spi_dev;
struct spi_config spi_config;
#if defined(IL0323_CS_CNTRL)
struct spi_cs_control cs_ctrl;
#endif
};
static uint8_t il0323_pwr[] = DT_INST_PROP(0, pwr);
static uint8_t last_buffer[IL0323_BUFFER_SIZE];
static bool blanking_on = true;
static inline int il0323_write_cmd(struct il0323_data *driver, uint8_t cmd, uint8_t *data,
size_t len) {
struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)};
struct spi_buf_set buf_set = {.buffers = &buf, .count = 1};
gpio_pin_set(driver->dc, IL0323_DC_PIN, 1);
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
return -EIO;
}
if (data != NULL) {
buf.buf = data;
buf.len = len;
gpio_pin_set(driver->dc, IL0323_DC_PIN, 0);
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
return -EIO;
}
}
return 0;
}
static inline void il0323_busy_wait(struct il0323_data *driver) {
int pin = gpio_pin_get(driver->busy, IL0323_BUSY_PIN);
while (pin > 0) {
__ASSERT(pin >= 0, "Failed to get pin level");
// LOG_DBG("wait %u", pin);
k_msleep(IL0323_BUSY_DELAY);
pin = gpio_pin_get(driver->busy, IL0323_BUSY_PIN);
}
}
static int il0323_update_display(const struct device *dev) {
struct il0323_data *driver = dev->data;
LOG_DBG("Trigger update sequence");
if (il0323_write_cmd(driver, IL0323_CMD_DRF, NULL, 0)) {
return -EIO;
}
k_msleep(IL0323_BUSY_DELAY);
return 0;
}
static int il0323_blanking_off(const struct device *dev) {
struct il0323_data *driver = dev->data;
if (blanking_on) {
/* Update EPD pannel in normal mode */
il0323_busy_wait(driver);
if (il0323_update_display(dev)) {
return -EIO;
}
}
blanking_on = false;
return 0;
}
static int il0323_blanking_on(const struct device *dev) {
blanking_on = true;
return 0;
}
static int il0323_write(const struct device *dev, const uint16_t x, const uint16_t y,
const struct display_buffer_descriptor *desc, const void *buf) {
struct il0323_data *driver = dev->data;
uint16_t x_end_idx = x + desc->width - 1;
uint16_t y_end_idx = y + desc->height - 1;
uint8_t ptl[IL0323_PTL_REG_LENGTH] = {0};
size_t buf_len;
LOG_DBG("x %u, y %u, height %u, width %u, pitch %u", x, y, desc->height, desc->width,
desc->pitch);
buf_len = MIN(desc->buf_size, desc->height * desc->width / IL0323_PIXELS_PER_BYTE);
__ASSERT(desc->width <= desc->pitch, "Pitch is smaller then width");
__ASSERT(buf != NULL, "Buffer is not available");
__ASSERT(buf_len != 0U, "Buffer of length zero");
__ASSERT(!(desc->width % IL0323_PIXELS_PER_BYTE), "Buffer width not multiple of %d",
IL0323_PIXELS_PER_BYTE);
LOG_DBG("buf_len %d", buf_len);
if ((y_end_idx > (EPD_PANEL_HEIGHT - 1)) || (x_end_idx > (EPD_PANEL_WIDTH - 1))) {
LOG_ERR("Position out of bounds");
return -EINVAL;
}
/* Setup Partial Window and enable Partial Mode */
ptl[IL0323_PTL_HRST_IDX] = x;
ptl[IL0323_PTL_HRED_IDX] = x_end_idx;
ptl[IL0323_PTL_VRST_IDX] = y;
ptl[IL0323_PTL_VRED_IDX] = y_end_idx;
ptl[sizeof(ptl) - 1] = IL0323_PTL_PT_SCAN;
LOG_HEXDUMP_DBG(ptl, sizeof(ptl), "ptl");
il0323_busy_wait(driver);
if (il0323_write_cmd(driver, IL0323_CMD_PIN, NULL, 0)) {
return -EIO;
}
if (il0323_write_cmd(driver, IL0323_CMD_PTL, ptl, sizeof(ptl))) {
return -EIO;
}
if (il0323_write_cmd(driver, IL0323_CMD_DTM1, last_buffer, IL0323_BUFFER_SIZE)) {
return -EIO;
}
if (il0323_write_cmd(driver, IL0323_CMD_DTM2, (uint8_t *)buf, buf_len)) {
return -EIO;
}
memcpy(last_buffer, (uint8_t *)buf, IL0323_BUFFER_SIZE);
/* Update partial window and disable Partial Mode */
if (blanking_on == false) {
if (il0323_update_display(dev)) {
return -EIO;
}
}
if (il0323_write_cmd(driver, IL0323_CMD_POUT, NULL, 0)) {
return -EIO;
}
return 0;
}
static int il0323_read(const struct device *dev, const uint16_t x, const uint16_t y,
const struct display_buffer_descriptor *desc, void *buf) {
LOG_ERR("not supported");
return -ENOTSUP;
}
static void *il0323_get_framebuffer(const struct device *dev) {
LOG_ERR("not supported");
return NULL;
}
static int il0323_set_brightness(const struct device *dev, const uint8_t brightness) {
LOG_WRN("not supported");
return -ENOTSUP;
}
static int il0323_set_contrast(const struct device *dev, uint8_t contrast) {
LOG_WRN("not supported");
return -ENOTSUP;
}
static void il0323_get_capabilities(const struct device *dev, struct display_capabilities *caps) {
memset(caps, 0, sizeof(struct display_capabilities));
caps->x_resolution = EPD_PANEL_WIDTH;
caps->y_resolution = EPD_PANEL_HEIGHT;
caps->supported_pixel_formats = PIXEL_FORMAT_MONO10;
caps->current_pixel_format = PIXEL_FORMAT_MONO10;
caps->screen_info = SCREEN_INFO_MONO_MSB_FIRST | SCREEN_INFO_EPD;
}
static int il0323_set_orientation(const struct device *dev,
const enum display_orientation orientation) {
LOG_ERR("Unsupported");
return -ENOTSUP;
}
static int il0323_set_pixel_format(const struct device *dev, const enum display_pixel_format pf) {
if (pf == PIXEL_FORMAT_MONO10) {
return 0;
}
LOG_ERR("not supported");
return -ENOTSUP;
}
static int il0323_clear_and_write_buffer(const struct device *dev, uint8_t pattern, bool update) {
struct display_buffer_descriptor desc = {
.buf_size = IL0323_NUMOF_PAGES,
.width = EPD_PANEL_WIDTH,
.height = 1,
.pitch = EPD_PANEL_WIDTH,
};
uint8_t *line;
line = k_malloc(IL0323_NUMOF_PAGES);
if (line == NULL) {
return -ENOMEM;
}
memset(line, pattern, IL0323_NUMOF_PAGES);
for (int i = 0; i < EPD_PANEL_HEIGHT; i++) {
il0323_write(dev, 0, i, &desc, line);
}
k_free(line);
if (update == true) {
if (il0323_update_display(dev)) {
return -EIO;
}
}
return 0;
}
static int il0323_controller_init(const struct device *dev) {
struct il0323_data *driver = dev->data;
uint8_t tmp[IL0323_TRES_REG_LENGTH];
LOG_DBG("");
gpio_pin_set(driver->reset, IL0323_RESET_PIN, 1);
k_msleep(IL0323_RESET_DELAY);
gpio_pin_set(driver->reset, IL0323_RESET_PIN, 0);
k_msleep(IL0323_RESET_DELAY);
il0323_busy_wait(driver);
LOG_DBG("Initialize IL0323 controller");
if (il0323_write_cmd(driver, IL0323_CMD_PWR, il0323_pwr, sizeof(il0323_pwr))) {
return -EIO;
}
/* Turn on: booster, controller, regulators, and sensor. */
if (il0323_write_cmd(driver, IL0323_CMD_PON, NULL, 0)) {
return -EIO;
}
k_msleep(IL0323_PON_DELAY);
il0323_busy_wait(driver);
/* Pannel settings, KW mode */
tmp[0] = IL0323_PSR_UD | IL0323_PSR_SHL | IL0323_PSR_SHD | IL0323_PSR_RST;
#if EPD_PANEL_WIDTH == 80
#if EPD_PANEL_HEIGHT == 128
tmp[0] |= IL0323_PSR_RES_HEIGHT;
#endif /* panel height */
#else
tmp[0] |= IL0323_PSR_RES_WIDTH;
#if EPD_PANEL_HEIGHT == 96
tmp[0] |= IL0323_PSR_RES_HEIGHT;
#else
#endif /* panel height */
#endif /* panel width */
LOG_HEXDUMP_DBG(tmp, 1, "PSR");
if (il0323_write_cmd(driver, IL0323_CMD_PSR, tmp, 1)) {
return -EIO;
}
/* Set panel resolution */
tmp[IL0323_TRES_HRES_IDX] = EPD_PANEL_WIDTH;
tmp[IL0323_TRES_VRES_IDX] = EPD_PANEL_HEIGHT;
LOG_HEXDUMP_DBG(tmp, IL0323_TRES_REG_LENGTH, "TRES");
if (il0323_write_cmd(driver, IL0323_CMD_TRES, tmp, IL0323_TRES_REG_LENGTH)) {
return -EIO;
}
tmp[IL0323_CDI_CDI_IDX] = DT_INST_PROP(0, cdi);
LOG_HEXDUMP_DBG(tmp, IL0323_CDI_REG_LENGTH, "CDI");
if (il0323_write_cmd(driver, IL0323_CMD_CDI, tmp, IL0323_CDI_REG_LENGTH)) {
return -EIO;
}
tmp[0] = DT_INST_PROP(0, tcon);
if (il0323_write_cmd(driver, IL0323_CMD_TCON, tmp, 1)) {
return -EIO;
}
/* Enable Auto Sequence */
tmp[0] = IL0323_AUTO_PON_DRF_POF;
if (il0323_write_cmd(driver, IL0323_CMD_AUTO, tmp, 1)) {
return -EIO;
}
if (il0323_clear_and_write_buffer(dev, 0xff, false)) {
return -1;
}
return 0;
}
static int il0323_init(const struct device *dev) {
struct il0323_data *driver = dev->data;
LOG_DBG("");
driver->spi_dev = device_get_binding(IL0323_BUS_NAME);
if (driver->spi_dev == NULL) {
LOG_ERR("Could not get SPI device for IL0323");
return -EIO;
}
driver->spi_config.frequency = IL0323_SPI_FREQ;
driver->spi_config.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8);
driver->spi_config.slave = DT_INST_REG_ADDR(0);
driver->spi_config.cs = NULL;
driver->reset = device_get_binding(IL0323_RESET_CNTRL);
if (driver->reset == NULL) {
LOG_ERR("Could not get GPIO port for IL0323 reset");
return -EIO;
}
gpio_pin_configure(driver->reset, IL0323_RESET_PIN, GPIO_OUTPUT_INACTIVE | IL0323_RESET_FLAGS);
driver->dc = device_get_binding(IL0323_DC_CNTRL);
if (driver->dc == NULL) {
LOG_ERR("Could not get GPIO port for IL0323 DC signal");
return -EIO;
}
gpio_pin_configure(driver->dc, IL0323_DC_PIN, GPIO_OUTPUT_INACTIVE | IL0323_DC_FLAGS);
driver->busy = device_get_binding(IL0323_BUSY_CNTRL);
if (driver->busy == NULL) {
LOG_ERR("Could not get GPIO port for IL0323 busy signal");
return -EIO;
}
gpio_pin_configure(driver->busy, IL0323_BUSY_PIN, GPIO_INPUT | IL0323_BUSY_FLAGS);
#if defined(IL0323_CS_CNTRL)
driver->cs_ctrl.gpio_dev = device_get_binding(IL0323_CS_CNTRL);
if (!driver->cs_ctrl.gpio_dev) {
LOG_ERR("Unable to get SPI GPIO CS device");
return -EIO;
}
driver->cs_ctrl.gpio_pin = IL0323_CS_PIN;
driver->cs_ctrl.gpio_dt_flags = IL0323_CS_FLAGS;
driver->cs_ctrl.delay = 0U;
driver->spi_config.cs = &driver->cs_ctrl;
#endif
return il0323_controller_init(dev);
}
static struct il0323_data il0323_driver;
static struct display_driver_api il0323_driver_api = {
.blanking_on = il0323_blanking_on,
.blanking_off = il0323_blanking_off,
.write = il0323_write,
.read = il0323_read,
.get_framebuffer = il0323_get_framebuffer,
.set_brightness = il0323_set_brightness,
.set_contrast = il0323_set_contrast,
.get_capabilities = il0323_get_capabilities,
.set_pixel_format = il0323_set_pixel_format,
.set_orientation = il0323_set_orientation,
};
DEVICE_DT_INST_DEFINE(0, il0323_init, device_pm_control_nop, &il0323_driver, NULL, POST_KERNEL,
CONFIG_APPLICATION_INIT_PRIORITY, &il0323_driver_api);

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2020 PHYTEC Messtechnik GmbH, Peter Johanson
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_DRIVERS_DISPLAY_IL0323_REGS_H_
#define ZEPHYR_DRIVERS_DISPLAY_IL0323_REGS_H_
#define IL0323_CMD_PSR 0x00
#define IL0323_CMD_PWR 0x01
#define IL0323_CMD_POF 0x02
#define IL0323_CMD_PFS 0x03
#define IL0323_CMD_PON 0x04
#define IL0323_CMD_PMES 0x05
#define IL0323_CMD_CPSET 0x06
#define IL0323_CMD_DSLP 0x07
#define IL0323_CMD_DTM1 0x10
#define IL0323_CMD_DSP 0x11
#define IL0323_CMD_DRF 0x12
#define IL0323_CMD_DTM2 0x13
#define IL0323_CMD_AUTO 0x17
#define IL0323_CMD_LUTOPT 0x2A
#define IL0323_CMD_PLL 0x30
#define IL0323_CMD_TSC 0x40
#define IL0323_CMD_TSE 0x41
#define IL0323_CMD_PBC 0x44
#define IL0323_CMD_CDI 0x50
#define IL0323_CMD_LPD 0x51
#define IL0323_CMD_TCON 0x60
#define IL0323_CMD_TRES 0x61
#define IL0323_CMD_GSST 0x65
#define IL0323_CMD_REV 0x70
#define IL0323_CMD_FLG 0x71
#define IL0323_CMD_CRC 0x72
#define IL0323_CMD_AMV 0x80
#define IL0323_CMD_VV 0x81
#define IL0323_CMD_VDCS 0x82
#define IL0323_CMD_PTL 0x90
#define IL0323_CMD_PIN 0x91
#define IL0323_CMD_POUT 0x92
#define IL0323_CMD_PGM 0xA0
#define IL0323_CMD_APG 0xA1
#define IL0323_CMD_ROTP 0xA2
#define IL0323_CMD_CCSET 0xE0
#define IL0323_CMD_PWS 0xE3
#define IL0323_CMD_LVSEL 0xE4
#define IL0323_CMD_TSSET 0xE5
#define IL0323_PSR_RES_WIDTH BIT(7)
#define IL0323_PSR_RES_HEIGHT BIT(6)
#define IL0323_PSR_LUT_REG BIT(5)
#define IL0323_PSR_LUT_OTP BIT(4)
#define IL0323_PSR_UD BIT(3)
#define IL0323_PSR_SHL BIT(2)
#define IL0323_PSR_SHD BIT(1)
#define IL0323_PSR_RST BIT(0)
#define IL0323_AUTO_PON_DRF_POF 0xA5
#define IL0323_AUTO_PON_DRF_POF_DSLP 0xA7
#define IL0323_CDI_REG_LENGTH 1U
#define IL0323_CDI_CDI_IDX 0
#define IL0323_TRES_REG_LENGTH 2U
#define IL0323_TRES_HRES_IDX 0
#define IL0323_TRES_VRES_IDX 1
#define IL0323_PTL_REG_LENGTH 5U
#define IL0323_PTL_HRST_IDX 0
#define IL0323_PTL_HRED_IDX 1
#define IL0323_PTL_VRST_IDX 2
#define IL0323_PTL_VRED_IDX 3
#define IL0323_PTL_PT_SCAN BIT(0)
/* Time constants in ms */
#define IL0323_RESET_DELAY 10U
#define IL0323_PON_DELAY 100U
#define IL0323_BUSY_DELAY 1U
#endif /* ZEPHYR_DRIVERS_DISPLAY_IL0323_REGS_H_ */

View file

@ -108,6 +108,6 @@ static const struct kscan_composite_config kscan_composite_config = {};
static struct kscan_composite_data kscan_composite_data;
DEVICE_AND_API_INIT(kscan_composite, DT_INST_LABEL(0), kscan_composite_init, &kscan_composite_data,
&kscan_composite_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&mock_driver_api);
DEVICE_DT_INST_DEFINE(0, kscan_composite_init, device_pm_control_nop, &kscan_composite_data,
&kscan_composite_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&mock_driver_api);

View file

@ -248,9 +248,9 @@ struct kscan_gpio_item_config {
.cols = {UTIL_LISTIFY(INST_DEMUX_GPIOS(n), _KSCAN_GPIO_OUTPUT_CFG_INIT, n)}, \
}; \
\
DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
&kscan_gpio_data_##n, &kscan_gpio_config_##n, APPLICATION, \
CONFIG_APPLICATION_INIT_PRIORITY, &gpio_driver_api_##n);
DEVICE_DT_INST_DEFINE(n, kscan_gpio_init_##n, device_pm_control_nop, &kscan_gpio_data_##n, \
&kscan_gpio_config_##n, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, \
&gpio_driver_api_##n);
DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT)

View file

@ -238,9 +238,9 @@ static const struct kscan_driver_api gpio_driver_api = {
.inputs = {UTIL_LISTIFY(INST_INPUT_LEN(n), KSCAN_DIRECT_INPUT_ITEM, n)}, \
.num_of_inputs = INST_INPUT_LEN(n), \
.debounce_period = DT_INST_PROP(n, debounce_period)}; \
DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
&kscan_gpio_data_##n, &kscan_gpio_config_##n, POST_KERNEL, \
CONFIG_ZMK_KSCAN_INIT_PRIORITY, &gpio_driver_api);
DEVICE_DT_INST_DEFINE(n, kscan_gpio_init_##n, device_pm_control_nop, &kscan_gpio_data_##n, \
&kscan_gpio_config_##n, POST_KERNEL, CONFIG_ZMK_KSCAN_INIT_PRIORITY, \
&gpio_driver_api);
DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT)

View file

@ -298,9 +298,9 @@ static int kscan_gpio_config_interrupts(const struct device **devices,
.rows = {UTIL_LISTIFY(INST_MATRIX_ROWS(n), _KSCAN_GPIO_ROW_CFG_INIT, n)}, \
.cols = {UTIL_LISTIFY(INST_MATRIX_COLS(n), _KSCAN_GPIO_COL_CFG_INIT, n)}, \
}; \
DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
&kscan_gpio_data_##n, &kscan_gpio_config_##n, APPLICATION, \
CONFIG_APPLICATION_INIT_PRIORITY, &gpio_driver_api_##n);
DEVICE_DT_INST_DEFINE(n, kscan_gpio_init_##n, device_pm_control_nop, &kscan_gpio_data_##n, \
&kscan_gpio_config_##n, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, \
&gpio_driver_api_##n);
DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT)

View file

@ -88,8 +88,8 @@ static int kscan_mock_configure(const struct device *dev, kscan_callback_t callb
static struct kscan_mock_data kscan_mock_data_##n; \
static const struct kscan_mock_config_##n kscan_mock_config_##n = { \
.events = DT_INST_PROP(n, events), .exit_after = DT_INST_PROP(n, exit_after)}; \
DEVICE_AND_API_INIT(kscan_mock_##n, DT_INST_LABEL(n), kscan_mock_init_##n, \
&kscan_mock_data_##n, &kscan_mock_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &mock_driver_api_##n);
DEVICE_DT_INST_DEFINE(n, kscan_mock_init_##n, device_pm_control_nop, &kscan_mock_data_##n, \
&kscan_mock_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &mock_driver_api_##n);
DT_INST_FOREACH_STATUS_OKAY(MOCK_INST_INIT)

View file

@ -1,5 +1,5 @@
# Copyright (c) 2020 The ZMK Contributors
# Copyright (c) 2020-2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
add_subdirectory_ifdef(CONFIG_ZMK_BATTERY_VOLTAGE_DIVIDER battery_voltage_divider)
add_subdirectory_ifdef(CONFIG_ZMK_BATTERY battery)
add_subdirectory_ifdef(CONFIG_EC11 ec11)

View file

@ -1,5 +1,5 @@
# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
rsource "battery_voltage_divider/Kconfig"
rsource "battery/Kconfig"
rsource "ec11/Kconfig"

View file

@ -0,0 +1,10 @@
# Copyright (c) 2020-2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
zephyr_include_directories(.)
zephyr_library()
zephyr_library_sources(battery_common.c)
zephyr_library_sources_ifdef(CONFIG_ZMK_BATTERY_NRF_VDDH battery_nrf_vddh.c)
zephyr_library_sources_ifdef(CONFIG_ZMK_BATTERY_VOLTAGE_DIVIDER battery_voltage_divider.c)

View file

@ -0,0 +1,21 @@
# Copyright (c) 2020-2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
config ZMK_BATTERY
bool "ZMK battery monitoring"
help
Enable battery monitoring
config ZMK_BATTERY_NRF_VDDH
bool "ZMK nRF VDDH battery monitoring"
select ADC
select ZMK_BATTERY
help
Enable ZMK nRF VDDH voltage driver for battery monitoring.
config ZMK_BATTERY_VOLTAGE_DIVIDER
bool "ZMK battery voltage divider"
select ADC
select ZMK_BATTERY
help
Enable ZMK battery voltage divider driver for battery monitoring.

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <errno.h>
#include <drivers/sensor.h>
#include "battery_common.h"
int battery_channel_get(const struct battery_value *value, enum sensor_channel chan,
struct sensor_value *val_out) {
switch (chan) {
case SENSOR_CHAN_GAUGE_VOLTAGE:
val_out->val1 = value->millivolts / 1000;
val_out->val2 = (value->millivolts % 1000) * 1000U;
break;
case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE:
val_out->val1 = value->state_of_charge;
val_out->val2 = 0;
break;
default:
return -ENOTSUP;
}
return 0;
}
uint8_t lithium_ion_mv_to_pct(int16_t bat_mv) {
// Simple linear approximation of a battery based off adafruit's discharge graph:
// https://learn.adafruit.com/li-ion-and-lipoly-batteries/voltages
if (bat_mv >= 4200) {
return 100;
} else if (bat_mv <= 3450) {
return 0;
}
return bat_mv * 2 / 15 - 459;
}

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <drivers/sensor.h>
#include <stdint.h>
struct battery_value {
uint16_t adc_raw;
uint16_t millivolts;
uint8_t state_of_charge;
};
int battery_channel_get(const struct battery_value *value, enum sensor_channel chan,
struct sensor_value *val_out);
uint8_t lithium_ion_mv_to_pct(int16_t bat_mv);

View file

@ -0,0 +1,116 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*
* This is a simplified version of battery_voltage_divider.c which always reads
* the VDDHDIV5 channel of the &adc node and multiplies it by 5.
*/
#define DT_DRV_COMPAT zmk_battery_nrf_vddh
#include <device.h>
#include <devicetree.h>
#include <drivers/adc.h>
#include <drivers/sensor.h>
#include <logging/log.h>
#include "battery_common.h"
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define VDDHDIV (5)
static const struct device *adc = DEVICE_DT_GET(DT_NODELABEL(adc));
struct vddh_data {
struct adc_channel_cfg acc;
struct adc_sequence as;
struct battery_value value;
};
static int vddh_sample_fetch(const struct device *dev, enum sensor_channel chan) {
// Make sure selected channel is supported
if (chan != SENSOR_CHAN_GAUGE_VOLTAGE && chan != SENSOR_CHAN_GAUGE_STATE_OF_CHARGE &&
chan != SENSOR_CHAN_ALL) {
LOG_DBG("Selected channel is not supported: %d.", chan);
return -ENOTSUP;
}
struct vddh_data *drv_data = dev->data;
struct adc_sequence *as = &drv_data->as;
int rc = adc_read(adc, as);
as->calibrate = false;
if (rc != 0) {
LOG_ERR("Failed to read ADC: %d", rc);
return rc;
}
int32_t val = drv_data->value.adc_raw;
rc = adc_raw_to_millivolts(adc_ref_internal(adc), drv_data->acc.gain, as->resolution, &val);
if (rc != 0) {
LOG_ERR("Failed to convert raw ADC to mV: %d", rc);
return rc;
}
drv_data->value.millivolts = val * VDDHDIV;
drv_data->value.state_of_charge = lithium_ion_mv_to_pct(drv_data->value.millivolts);
LOG_DBG("ADC raw %d ~ %d mV => %d%%", drv_data->value.adc_raw, drv_data->value.millivolts,
drv_data->value.state_of_charge);
return rc;
}
static int vddh_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val) {
struct vddh_data const *drv_data = dev->data;
return battery_channel_get(&drv_data->value, chan, val);
}
static const struct sensor_driver_api vddh_api = {
.sample_fetch = vddh_sample_fetch,
.channel_get = vddh_channel_get,
};
static int vddh_init(const struct device *dev) {
struct vddh_data *drv_data = dev->data;
if (!device_is_ready(adc)) {
LOG_ERR("ADC device is not ready %s", adc->name);
return -ENODEV;
}
drv_data->as = (struct adc_sequence){
.channels = BIT(0),
.buffer = &drv_data->value.adc_raw,
.buffer_size = sizeof(drv_data->value.adc_raw),
.oversampling = 4,
.calibrate = true,
};
#ifdef CONFIG_ADC_NRFX_SAADC
drv_data->acc = (struct adc_channel_cfg){
.gain = ADC_GAIN_1_5,
.reference = ADC_REF_INTERNAL,
.acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40),
.input_positive = SAADC_CH_PSELN_PSELN_VDDHDIV5,
};
drv_data->as.resolution = 12;
#else
#error Unsupported ADC
#endif
const int rc = adc_channel_setup(adc, &drv_data->acc);
LOG_DBG("VDDHDIV5 setup returned %d", rc);
return rc;
}
static struct vddh_data vddh_data;
DEVICE_DT_INST_DEFINE(0, &vddh_init, device_pm_control_nop, &vddh_data, NULL, POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY, &vddh_api);

View file

@ -7,11 +7,14 @@
#define DT_DRV_COMPAT zmk_battery_voltage_divider
#include <device.h>
#include <devicetree.h>
#include <drivers/gpio.h>
#include <drivers/adc.h>
#include <drivers/sensor.h>
#include <logging/log.h>
#include "battery_common.h"
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct io_channel_config {
@ -37,24 +40,9 @@ struct bvd_data {
const struct device *gpio;
struct adc_channel_cfg acc;
struct adc_sequence as;
uint16_t adc_raw;
uint16_t voltage;
uint8_t state_of_charge;
struct battery_value value;
};
static uint8_t lithium_ion_mv_to_pct(int16_t bat_mv) {
// Simple linear approximation of a battery based off adafruit's discharge graph:
// https://learn.adafruit.com/li-ion-and-lipoly-batteries/voltages
if (bat_mv >= 4200) {
return 100;
} else if (bat_mv <= 3450) {
return 0;
}
return bat_mv * 2 / 15 - 459;
}
static int bvd_sample_fetch(const struct device *dev, enum sensor_channel chan) {
struct bvd_data *drv_data = dev->data;
const struct bvd_config *drv_cfg = dev->config;
@ -87,18 +75,18 @@ static int bvd_sample_fetch(const struct device *dev, enum sensor_channel chan)
as->calibrate = false;
if (rc == 0) {
int32_t val = drv_data->adc_raw;
int32_t val = drv_data->value.adc_raw;
adc_raw_to_millivolts(adc_ref_internal(drv_data->adc), drv_data->acc.gain, as->resolution,
&val);
uint16_t millivolts = val * (uint64_t)drv_cfg->full_ohm / drv_cfg->output_ohm;
LOG_DBG("ADC raw %d ~ %d mV => %d mV", drv_data->adc_raw, val, millivolts);
LOG_DBG("ADC raw %d ~ %d mV => %d mV", drv_data->value.adc_raw, val, millivolts);
uint8_t percent = lithium_ion_mv_to_pct(millivolts);
LOG_DBG("Percent: %d", percent);
drv_data->voltage = millivolts;
drv_data->state_of_charge = percent;
drv_data->value.millivolts = millivolts;
drv_data->value.state_of_charge = percent;
} else {
LOG_DBG("Failed to read ADC: %d", rc);
}
@ -119,23 +107,7 @@ static int bvd_sample_fetch(const struct device *dev, enum sensor_channel chan)
static int bvd_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val) {
struct bvd_data *drv_data = dev->data;
switch (chan) {
case SENSOR_CHAN_GAUGE_VOLTAGE:
val->val1 = drv_data->voltage / 1000;
val->val2 = (drv_data->voltage % 1000) * 1000U;
break;
case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE:
val->val1 = drv_data->state_of_charge;
val->val2 = 0;
break;
default:
return -ENOTSUP;
}
return 0;
return battery_channel_get(&drv_data->value, chan, val);
}
static const struct sensor_driver_api bvd_api = {
@ -173,8 +145,8 @@ static int bvd_init(const struct device *dev) {
drv_data->as = (struct adc_sequence){
.channels = BIT(0),
.buffer = &drv_data->adc_raw,
.buffer_size = sizeof(drv_data->adc_raw),
.buffer = &drv_data->value.adc_raw,
.buffer_size = sizeof(drv_data->value.adc_raw),
.oversampling = 4,
.calibrate = true,
};
@ -217,5 +189,5 @@ static const struct bvd_config bvd_cfg = {
.full_ohm = DT_INST_PROP(0, full_ohms),
};
DEVICE_AND_API_INIT(bvd_dev, DT_INST_LABEL(0), &bvd_init, &bvd_data, &bvd_cfg, POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY, &bvd_api);
DEVICE_DT_INST_DEFINE(0, &bvd_init, device_pm_control_nop, &bvd_data, &bvd_cfg, POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY, &bvd_api);

View file

@ -1,6 +0,0 @@
# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
zephyr_library()
zephyr_library_sources(battery_voltage_divider.c)

View file

@ -1,8 +0,0 @@
# Copyright (c) 2020 The ZMK Contributors
# SPDX-License-Identifier: MIT
config ZMK_BATTERY_VOLTAGE_DIVIDER
bool "ZMK battery voltage divider"
select ADC
help
Enable ZMK battery voltage divider driver for battery monitoring.

View file

@ -142,7 +142,7 @@ int ec11_init(const struct device *dev) {
.b_flags = DT_INST_GPIO_FLAGS(n, b_gpios), \
COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))), \
}; \
DEVICE_AND_API_INIT(ec11_##n, DT_INST_LABEL(n), ec11_init, &ec11_data_##n, &ec11_cfg_##n, \
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ec11_driver_api);
DEVICE_DT_INST_DEFINE(n, ec11_init, device_pm_control_nop, &ec11_data_##n, &ec11_cfg_##n, \
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ec11_driver_api);
DT_INST_FOREACH_STATUS_OKAY(EC11_INST)
DT_INST_FOREACH_STATUS_OKAY(EC11_INST)

View file

@ -0,0 +1,11 @@
# Copyright (c) 2021 The ZMK Contributors
# SPDX-License-Identifier: MIT
description: Battery SoC monitoring using nRF VDDH
compatible: "zmk,battery-nrf-vddh"
properties:
label:
required: true
type: string

View file

@ -0,0 +1,61 @@
# Copyright (c) 2020, Phytec Messtechnik GmbH, Peter Johanson
# SPDX-License-Identifier: Apache-2.0
description: IL0323 EPD display controller
compatible: "gooddisplay,il0323"
include: spi-device.yaml
properties:
height:
type: int
required: true
description: Height in pixel of the panel driven by the controller
width:
type: int
required: true
description: Width in pixel of the panel driven by the controller
reset-gpios:
type: phandle-array
required: true
description: RESET pin.
The RESET pin of GD7965 is active low.
If connected directly the MCU pin should be configured
as active low.
dc-gpios:
type: phandle-array
required: true
description: DC pin.
The DC pin of GD7965 is active low (transmission command byte).
If connected directly the MCU pin should be configured
as active low.
busy-gpios:
type: phandle-array
required: true
description: BUSY pin.
The BUSY pin of GD7965 is active low.
If connected directly the MCU pin should be configured
as active low.
pwr:
type: uint8-array
required: true
description: Power Setting (PWR) values
cdi:
type: int
required: true
description: VCOM and data interval value
tcon:
type: int
required: true
description: TCON setting value

View file

@ -6,13 +6,7 @@
#pragma once
#include <zmk/keys.h>
#include <zmk/hid.h>
enum zmk_endpoint {
ZMK_ENDPOINT_USB,
ZMK_ENDPOINT_BLE,
};
#include <zmk/endpoints_types.h>
int zmk_endpoints_select(enum zmk_endpoint endpoint);
int zmk_endpoints_toggle();

View file

@ -0,0 +1,12 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
enum zmk_endpoint {
ZMK_ENDPOINT_USB,
ZMK_ENDPOINT_BLE,
};

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <zephyr.h>
#include <zmk/endpoints_types.h>
#include <zmk/event_manager.h>
struct zmk_endpoint_selection_changed {
enum zmk_endpoint endpoint;
};
ZMK_EVENT_DECLARE(zmk_endpoint_selection_changed);

View file

@ -7,6 +7,7 @@
#include <device.h>
#include <init.h>
#include <kernel.h>
#include <power/power.h>
#include <logging/log.h>
@ -55,6 +56,8 @@ void activity_work_handler(struct k_work *work) {
int32_t inactive_time = current - activity_last_uptime;
#if IS_ENABLED(CONFIG_ZMK_SLEEP)
if (inactive_time > MAX_SLEEP_MS) {
// Put devices in low power mode before sleeping
pm_power_state_force((struct pm_state_info){PM_STATE_STANDBY, 0, 0});
set_state(ZMK_ACTIVITY_SLEEP);
} else
#endif /* IS_ENABLED(CONFIG_ZMK_SLEEP) */

View file

@ -49,7 +49,7 @@ static const struct behavior_driver_api behavior_bt_driver_api = {
.binding_released = on_keymap_binding_released,
};
DEVICE_AND_API_INIT(behavior_bt, DT_INST_LABEL(0), behavior_bt_init, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_bt_driver_api);
DEVICE_DT_INST_DEFINE(0, behavior_bt_init, device_pm_control_nop, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_bt_driver_api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -73,7 +73,7 @@ static const struct behavior_driver_api behavior_ext_power_driver_api = {
.binding_released = on_keymap_binding_released,
};
DEVICE_AND_API_INIT(behavior_ext_power, DT_INST_LABEL(0), behavior_ext_power_init, NULL, NULL,
APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, &behavior_ext_power_driver_api);
DEVICE_DT_INST_DEFINE(0, behavior_ext_power_init, device_pm_control_nop, NULL, NULL, APPLICATION,
CONFIG_APPLICATION_INIT_PRIORITY, &behavior_ext_power_driver_api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -605,10 +605,10 @@ static struct behavior_hold_tap_data behavior_hold_tap_data;
.flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \
.retro_tap = DT_INST_PROP(n, retro_tap), \
}; \
DEVICE_AND_API_INIT(behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \
&behavior_hold_tap_data, &behavior_hold_tap_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_hold_tap_driver_api);
DEVICE_DT_INST_DEFINE(n, behavior_hold_tap_init, device_pm_control_nop, \
&behavior_hold_tap_data, &behavior_hold_tap_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_hold_tap_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -36,8 +36,8 @@ static const struct behavior_driver_api behavior_key_press_driver_api = {
.binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
#define KP_INST(n) \
DEVICE_AND_API_INIT(behavior_key_press_##n, DT_INST_LABEL(n), behavior_key_press_init, NULL, \
NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&behavior_key_press_driver_api);
DEVICE_DT_INST_DEFINE(n, behavior_key_press_init, device_pm_control_nop, NULL, NULL, \
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&behavior_key_press_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST)

View file

@ -90,10 +90,11 @@ static int behavior_mod_morph_init(const struct device *dev) { return 0; }
.mods = DT_INST_PROP(n, mods), \
}; \
static struct behavior_mod_morph_data behavior_mod_morph_data_##n = {}; \
DEVICE_AND_API_INIT(behavior_mod_morph_##n, DT_INST_LABEL(n), behavior_mod_morph_init, \
&behavior_mod_morph_data_##n, &behavior_mod_morph_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mod_morph_driver_api);
DEVICE_DT_INST_DEFINE(n, behavior_mod_morph_init, device_pm_control_nop, \
&behavior_mod_morph_data_##n, &behavior_mod_morph_config_##n, \
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&behavior_mod_morph_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
#endif
#endif

View file

@ -39,6 +39,6 @@ static const struct behavior_mo_config behavior_mo_config = {};
static struct behavior_mo_data behavior_mo_data;
DEVICE_AND_API_INIT(behavior_mo, DT_INST_LABEL(0), behavior_mo_init, &behavior_mo_data,
&behavior_mo_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_mo_driver_api);
DEVICE_DT_INST_DEFINE(0, behavior_mo_init, device_pm_control_nop, &behavior_mo_data,
&behavior_mo_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_mo_driver_api);

View file

@ -34,7 +34,7 @@ static const struct behavior_driver_api behavior_none_driver_api = {
.binding_released = on_keymap_binding_released,
};
DEVICE_AND_API_INIT(behavior_none, DT_INST_LABEL(0), behavior_none_init, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_none_driver_api);
DEVICE_DT_INST_DEFINE(0, behavior_none_init, device_pm_control_nop, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_none_driver_api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -42,7 +42,7 @@ static const struct behavior_driver_api behavior_outputs_driver_api = {
.binding_pressed = on_keymap_binding_pressed,
};
DEVICE_AND_API_INIT(behavior_out, DT_INST_LABEL(0), behavior_out_init, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_outputs_driver_api);
DEVICE_DT_INST_DEFINE(0, behavior_out_init, device_pm_control_nop, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_outputs_driver_api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -41,9 +41,9 @@ static const struct behavior_driver_api behavior_reset_driver_api = {
#define RST_INST(n) \
static const struct behavior_reset_config behavior_reset_config_##n = { \
.type = DT_INST_PROP(n, type)}; \
DEVICE_AND_API_INIT(behavior_reset_##n, DT_INST_LABEL(n), behavior_reset_init, NULL, \
&behavior_reset_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_reset_driver_api);
DEVICE_DT_INST_DEFINE(n, behavior_reset_init, device_pm_control_nop, NULL, \
&behavior_reset_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_reset_driver_api);
DT_INST_FOREACH_STATUS_OKAY(RST_INST)

View file

@ -136,8 +136,8 @@ static const struct behavior_driver_api behavior_rgb_underglow_driver_api = {
.binding_released = on_keymap_binding_released,
};
DEVICE_AND_API_INIT(behavior_rgb_underglow, DT_INST_LABEL(0), behavior_rgb_underglow_init, NULL,
NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_rgb_underglow_driver_api);
DEVICE_DT_INST_DEFINE(0, behavior_rgb_underglow_init, device_pm_control_nop, NULL, NULL,
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_rgb_underglow_driver_api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -59,10 +59,9 @@ static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_
.sensor_binding_triggered = on_sensor_binding_triggered};
#define KP_INST(n) \
DEVICE_AND_API_INIT(behavior_sensor_rotate_key_press_##n, DT_INST_LABEL(n), \
behavior_sensor_rotate_key_press_init, NULL, NULL, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&behavior_sensor_rotate_key_press_driver_api);
DEVICE_DT_INST_DEFINE(n, behavior_sensor_rotate_key_press_init, device_pm_control_nop, NULL, \
NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&behavior_sensor_rotate_key_press_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST)

View file

@ -272,9 +272,9 @@ static struct behavior_sticky_key_data behavior_sticky_key_data;
.release_after_ms = DT_INST_PROP(n, release_after_ms), \
.quick_release = DT_INST_PROP(n, quick_release), \
}; \
DEVICE_AND_API_INIT(behavior_sticky_key_##n, DT_INST_LABEL(n), behavior_sticky_key_init, \
&behavior_sticky_key_data, &behavior_sticky_key_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sticky_key_driver_api);
DEVICE_DT_INST_DEFINE(n, behavior_sticky_key_init, device_pm_control_nop, \
&behavior_sticky_key_data, &behavior_sticky_key_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sticky_key_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST)

View file

@ -37,7 +37,7 @@ static const struct behavior_driver_api behavior_to_driver_api = {
.binding_released = to_keymap_binding_released,
};
DEVICE_AND_API_INIT(behavior_to, DT_INST_LABEL(0), behavior_to_init, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_to_driver_api);
DEVICE_DT_INST_DEFINE(0, behavior_to_init, device_pm_control_nop, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_to_driver_api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -43,8 +43,8 @@ static const struct behavior_tog_config behavior_tog_config = {};
static struct behavior_tog_data behavior_tog_data;
DEVICE_AND_API_INIT(behavior_tog, DT_INST_LABEL(0), behavior_tog_init, &behavior_tog_data,
&behavior_tog_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_tog_driver_api);
DEVICE_DT_INST_DEFINE(0, behavior_tog_init, device_pm_control_nop, &behavior_tog_data,
&behavior_tog_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_tog_driver_api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -34,8 +34,7 @@ static const struct behavior_driver_api behavior_transparent_driver_api = {
.binding_released = on_keymap_binding_released,
};
DEVICE_AND_API_INIT(behavior_transparent, DT_INST_LABEL(0), behavior_transparent_init, NULL, NULL,
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_transparent_driver_api);
DEVICE_DT_INST_DEFINE(0, behavior_transparent_init, device_pm_control_nop, NULL, NULL, APPLICATION,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_transparent_driver_api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -26,14 +26,16 @@ static lv_obj_t *screen;
__attribute__((weak)) lv_obj_t *zmk_display_status_screen() { return NULL; }
void display_tick_cb(struct k_work *work) {
lv_tick_inc(10);
lv_task_handler();
}
void display_tick_cb(struct k_work *work) { lv_task_handler(); }
#define TICK_MS 10
K_WORK_DEFINE(display_tick_work, display_tick_cb);
void display_timer_cb() { k_work_submit(&display_tick_work); }
void display_timer_cb() {
lv_tick_inc(TICK_MS);
k_work_submit(&display_tick_work);
}
K_TIMER_DEFINE(display_timer, display_timer_cb, NULL);
@ -44,7 +46,7 @@ static void start_display_updates() {
display_blanking_off(display);
k_timer_start(&display_timer, K_MSEC(10), K_MSEC(10));
k_timer_start(&display_timer, K_MSEC(TICK_MS), K_MSEC(TICK_MS));
}
static void stop_display_updates() {
@ -75,8 +77,6 @@ int zmk_display_init() {
lv_scr_load(screen);
lv_task_handler();
start_display_updates();
LOG_DBG("");

View file

@ -13,6 +13,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/event_manager.h>
#include <zmk/events/usb_conn_state_changed.h>
#include <zmk/events/ble_active_profile_changed.h>
#include <zmk/events/endpoint_selection_changed.h>
#include <zmk/usb.h>
#include <zmk/ble.h>
#include <zmk/endpoints.h>
@ -86,6 +87,8 @@ int output_status_listener(const zmk_event_t *eh) {
}
ZMK_LISTENER(widget_output_status, output_status_listener)
ZMK_SUBSCRIPTION(widget_output_status, zmk_endpoint_selection_changed);
#if defined(CONFIG_USB)
ZMK_SUBSCRIPTION(widget_output_status, zmk_usb_conn_state_changed);
#endif

View file

@ -16,6 +16,7 @@
#include <zmk/event_manager.h>
#include <zmk/events/ble_active_profile_changed.h>
#include <zmk/events/usb_conn_state_changed.h>
#include <zmk/events/endpoint_selection_changed.h>
#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
@ -242,6 +243,9 @@ static void update_current_endpoint() {
current_endpoint = new_endpoint;
LOG_INF("Endpoint changed: %d", current_endpoint);
ZMK_EVENT_RAISE(new_zmk_endpoint_selection_changed(
(struct zmk_endpoint_selection_changed){.endpoint = current_endpoint}));
}
}

View file

@ -0,0 +1,10 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <kernel.h>
#include <zmk/events/endpoint_selection_changed.h>
ZMK_EVENT_IMPL(zmk_endpoint_selection_changed);

View file

@ -32,7 +32,7 @@ struct ext_power_generic_data {
#if IS_ENABLED(CONFIG_SETTINGS)
bool settings_init;
#endif
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
#ifdef CONFIG_PM_DEVICE
uint32_t pm_state;
#endif
};
@ -143,7 +143,7 @@ static int ext_power_generic_init(const struct device *dev) {
return -EIO;
}
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
#ifdef CONFIG_PM_DEVICE
data->pm_state = DEVICE_PM_ACTIVE_STATE;
#endif
@ -179,7 +179,7 @@ static int ext_power_generic_init(const struct device *dev) {
return 0;
}
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
#ifdef CONFIG_PM_DEVICE
static int ext_power_generic_pm_control(const struct device *dev, uint32_t ctrl_command,
void *context, device_pm_cb cb, void *arg) {
int rc;
@ -210,7 +210,7 @@ static int ext_power_generic_pm_control(const struct device *dev, uint32_t ctrl_
return rc;
}
#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */
#endif /* CONFIG_PM_DEVICE */
static const struct ext_power_generic_config config = {
.label = DT_INST_GPIO_LABEL(0, control_gpios),
@ -231,13 +231,7 @@ static const struct ext_power_api api = {.enable = ext_power_generic_enable,
#define ZMK_EXT_POWER_INIT_PRIORITY 81
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
DEVICE_DEFINE(ext_power_generic, DT_INST_LABEL(0), ext_power_generic_init,
&ext_power_generic_pm_control, &data, &config, POST_KERNEL,
ZMK_EXT_POWER_INIT_PRIORITY, &api);
#else
DEVICE_AND_API_INIT(ext_power_generic, DT_INST_LABEL(0), ext_power_generic_init, &data, &config,
POST_KERNEL, ZMK_EXT_POWER_INIT_PRIORITY, &api);
#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */
DEVICE_DT_INST_DEFINE(0, ext_power_generic_init, &ext_power_generic_pm_control, &data, &config,
POST_KERNEL, ZMK_EXT_POWER_INIT_PRIORITY, &api);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -23,18 +23,12 @@ bool is_usb_power_present() {
#endif /* CONFIG_USB */
}
enum power_states sys_pm_policy_next_state(int32_t ticks) {
#ifdef CONFIG_SYS_POWER_DEEP_SLEEP_STATES
#ifdef CONFIG_HAS_SYS_POWER_STATE_DEEP_SLEEP_1
struct pm_state_info pm_policy_next_state(int32_t ticks) {
if (zmk_activity_get_state() == ZMK_ACTIVITY_SLEEP && !is_usb_power_present()) {
return SYS_POWER_STATE_DEEP_SLEEP_1;
return (struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0};
}
#endif /* CONFIG_HAS_SYS_POWER_STATE_DEEP_SLEEP_1 */
#endif /* CONFIG_SYS_POWER_DEEP_SLEEP_STATES */
return SYS_POWER_STATE_ACTIVE;
return (struct pm_state_info){PM_STATE_ACTIVE, 0, 0};
}
bool sys_pm_policy_low_power_devices(enum power_states pm_state) {
return sys_pm_is_sleep_state(pm_state);
}
__weak bool pm_policy_low_power_devices(enum pm_state state) { return pm_is_sleep_state(state); }

View file

@ -19,6 +19,13 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN;
static void raise_usb_status_changed_event(struct k_work *_work) {
ZMK_EVENT_RAISE(new_zmk_usb_conn_state_changed(
(struct zmk_usb_conn_state_changed){.conn_state = zmk_usb_get_conn_state()}));
}
K_WORK_DEFINE(usb_status_notifier_work, raise_usb_status_changed_event);
#ifdef CONFIG_ZMK_USB
static const struct device *hid_dev;
@ -54,14 +61,10 @@ int zmk_usb_hid_send_report(const uint8_t *report, size_t len) {
#endif /* CONFIG_ZMK_USB */
static void raise_usb_status_changed_event() {
ZMK_EVENT_RAISE(new_zmk_usb_conn_state_changed(
(struct zmk_usb_conn_state_changed){.conn_state = zmk_usb_get_conn_state()}));
}
enum usb_dc_status_code zmk_usb_get_status() { return usb_status; }
enum zmk_usb_conn_state zmk_usb_get_conn_state() {
LOG_DBG("state: %d", usb_status);
switch (usb_status) {
case USB_DC_DISCONNECTED:
case USB_DC_UNKNOWN:
@ -78,7 +81,7 @@ enum zmk_usb_conn_state zmk_usb_get_conn_state() {
void usb_status_cb(enum usb_dc_status_code status, const uint8_t *params) {
usb_status = status;
raise_usb_status_changed_event();
k_work_submit(&usb_status_notifier_work);
};
static int zmk_usb_init(const struct device *_arg) {

View file

@ -9,7 +9,7 @@ manifest:
projects:
- name: zephyr
remote: zmkfirmware
revision: v2.4.0+zmk-fixes
revision: v2.5.0+zmk-fixes
clone-depth: 1
import:
# TODO: Rename once upstream offers option like `exclude` or `denylist`

View file

@ -0,0 +1,75 @@
---
title: "Zephyr 2.5 Update"
author: Pete Johanson
author_title: Project Creator
author_url: https://gitlab.com/petejohanson
author_image_url: https://www.gravatar.com/avatar/2001ceff7e9dc753cf96fcb2e6f41110
tags: [firmware, zephyr, core]
---
I'm happy to announce that we have completed the [work](https://github.com/zmkfirmware/zmk/pull/736/) to upgrade ZMK to [Zephyr 2.5](https://docs.zephyrproject.org/2.5.0/releases/release-notes-2.5.html)!
A big part of this work was some _major_ refactors and improvements by [innovaker] to our [zmk-docker](https://github.com/zmkfirmware/zmk-docker/) Docker image and GH Actions automation.
- Faster build times with improved caching.
- Integration tests which automatically verify new images.
- PRs to the repo now build properly and run the tests as well.
- Build images for multiple target architectures, e.g. `zmk-build-riscv64`, all in parallel.
- Nightly builds to be sure we're pulling in the latest OS/package updates, to ensure we keep our images up to date, address any reported vulnerabilities, etc.
- Faster upgrade paths for future Zephyr SDK and Zephyr versions.
In addition, [petejohanson] did the upgrade work to adjust ZMK for the Zephyr changes.
- Updated to newer devicetree/driver Zephyr API
- Adjustment for Zephyr pinmux changes
- Fixes for power management, LVGL, and formatter changes
## Getting The Changes
Use the following steps to update to the latest tooling in order to properly use the new ZMK changes:
### User Config Repositories Using GitHub Actions
Existing user config repositories using Github Actions to build will pull down Zephyr 2.5 automatically,
and should work, fine as is. However, to upgrade to the newer Docker image, you should:
- Open `.github/workflows/build.yml` in your editor/IDE
- Change `zmkfirmware/zmk-build-arm:2.4` to `zmkfirmware/zmk-build-arm:2.5` wherever it is found
:::note
If you created your user config repository a while ago, you may find that your `build.yml` file instead references
a `zephyr-west-action-arm` custom GitHub Action instead. In this case, the upgrade is not as direct. We suggest that
instead you [re-create your config repository](/docs/user-setup) to get an updated setup using the new automation
approach.
:::
### VS Code & Docker (Dev Container)
If you build locally using VS Code & Docker then:
- pull the latest ZMK `main` with `git pull` for your ZMK checkout
- reload the project
- if you are prompted to rebuild the remote container, click `Rebuild`
- otherwise, press `F1` and run `Remote Containers: Rebuild Container`
- Once the container has rebuilt and reloaded, run `west update` to pull the updated Zephyr version and its dependencies.
Once the container has rebuilt, VS Code will be running the 2.5 Docker image.
### Local Host Development
The following steps will get you building ZMK locally against Zephyr 2.5:
- Run the updated [toolchain installation](/docs/development/setup#toolchain-installation) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- pull the latest ZMK `main` with `git pull` for your ZMK checkout
- run `west update` to pull the updated Zephyr version and its dependencies
From there, you should be ready to build as normal!
## Thanks!
Thanks again to [innovaker] for all the hard work, and to all the testers who have helped verify ZMK functionality on the newer Zephyr version.
[petejohanson]: https://github.com/petejohanson
[innovaker]: https://github.com/innovaker

View file

@ -84,5 +84,5 @@ ZMK support bluetooth “profiles” which allows connection to multiple devices
The bluetooth MAC address and negotiated keys during pairing are stored in the permanent storage on your chip and can be reused even after reflashing the firmware. If for some reason you want to delete the stored information, you can bind the `BT_CLR` behavior described above to a key and use it to clear the _current_ profile.
:::note
If you clear bond of a paired profile, make sure you do the same thing on the peer device as well (typically achieved by _removing_ or _forgetting_ the bluetooth connection). Otherwise the peer will try to connect to your keyboard whenever it discovers it. But while the MAC address of both devices could remain the same, the security key no longer match: the peer device still possess the old key negotiated in the previous pairing procedure, but our keyboard firmware has deleted that key. So the connection will fail. If you [enabled USB logging](../development/usb-logging), you might see a lot of failed connection attempts due to the reason of “Security failed”.
If you clear bond of a paired profile, make sure you do the same thing on the peer device as well (typically achieved by _removing_ or _forgetting_ the bluetooth connection). Otherwise the peer will try to connect to your keyboard whenever it discovers it. But while the MAC address of both devices could remain the same, the security key no longer match: the peer device still possess the old key negotiated in the previous pairing procedure, but our keyboard firmware has deleted that key. So the connection will fail. If you [enabled USB logging](../development/usb-logging.md), you might see a lot of failed connection attempts due to the reason of “Security failed”.
:::

View file

@ -33,7 +33,7 @@ When the hold-tap key is released and the hold behavior has not been triggered,
### Basic usage
For basic usage, please see [mod-tap](./mod-tap.md) and [layer-tap](./layers.md) pages.
For basic usage, please see [mod-tap](mod-tap.md) and [layer-tap](layers.md) pages.
### Advanced Configuration

View file

@ -10,14 +10,14 @@ a certain key.
The categories of supported codes are:
- [Keyboard & Keypad](../codes/keyboard-keypad)
- [Editing](../codes/editing)
- [Media](../codes/media)
- [Applications](../codes/applications)
- [Input Assist](../codes/input-assist)
- [Power](../codes/power)
- [Keyboard & Keypad](../codes/keyboard-keypad.mdx)
- [Editing](../codes/editing.mdx)
- [Media](../codes/media.mdx)
- [Applications](../codes/applications.mdx)
- [Input Assist](../codes/input-assist.mdx)
- [Power](../codes/power.mdx)
Please visit the [codes](../codes) section for a comprehensive list.
Please visit the [codes](../codes/index.mdx) section for a comprehensive list.
For advanced users, user-defined HID usages are also supported but must be encoded, please see [`dt-bindings/zmk/keys.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/keys.h) for further insight.
@ -36,7 +36,7 @@ Doing so makes a set of defines such as `A`, `N1`, etc. available for use with t
### Improperly defined keymap - `dtlib.DTError: <board>.dts.pre.tmp:<line number>`
When compiling firmware from a keymap, it may be common to encounter an error in the form of a`dtlib.DTError: <board>.dts.pre.tmp:<line number>`.
For instructions to resolve such an error, click [here](../troubleshooting###Improperly-defined-keymap)
For instructions to resolve such an error, click [here](../troubleshooting.md###Improperly-defined-keymap)
## Key Press

View file

@ -43,7 +43,7 @@ Example:
## Layer-tap
The "layer-tap" behavior enables a layer when a key is held, and output another key when the key is only tapped for a short time. For more information on the inner workings of layer-tap, see [hold-tap](./hold-tap.md).
The "layer-tap" behavior enables a layer when a key is held, and output another key when the key is only tapped for a short time. For more information on the inner workings of layer-tap, see [hold-tap](hold-tap.md).
### Behavior Binding

View file

@ -46,4 +46,4 @@ You can configure a different tapping term in your keymap:
### Additional information
The mod-tap is a [hold-tap](./hold-tap.md) under the hood with the "balanced" flavor and tapping-term-ms 200.
The mod-tap is a [hold-tap](hold-tap.md) under the hood with the "balanced" flavor and tapping-term-ms 200.

View file

@ -24,7 +24,7 @@ import Table from "@site/src/components/codes/Table";
### Modifiers
The [Modifiers](./modifiers) page includes further information.
The [Modifiers](modifiers.mdx) page includes further information.
<Table group="keyboard-modifiers" />

View file

@ -4,7 +4,7 @@ sidebar_label: Customizing ZMK
---
After verifying you can successfully flash the default firmware, you will probably want to begin customizing your keymap and other keyboard options.
[In the initial setup tutorial](user-setup), you created a Github repository called `zmk-config`. This repository is a discrete filesystem which works
[In the initial setup tutorial](user-setup.md), you created a Github repository called `zmk-config`. This repository is a discrete filesystem which works
with the main `zmk` firmware repository to build your desired firmware. The main advantage of a discrete configuration folder is ensuring that the
working components of ZMK are kept separate from your personal keyboard settings, reducing the amount of file manipulation in the configuration process.
This makes flashing ZMK to your keyboard much easier, especially because you don't need to keep an up-to-date copy of zmk on your computer at all times.
@ -26,7 +26,7 @@ various config settings that can be commented/uncommented to modify how your fir
## Keymap
Once you have the basic user config completed, you can find the keymap file in `config/<shield>.keymap` and customize from there.
Refer to the [Keymap](/docs/features/keymaps) documentation to learn more.
Refer to the [Keymap](features/keymaps.md) documentation to learn more.
## Publishing
@ -39,7 +39,7 @@ If you need to, a review of [Learn The Basics Of Git In Under 10 Minutes](https:
## Building from a local `zmk` fork using `zmk-config`
[As outlined here](development/build-flash), firmware comes in the form of .uf2 files, which can be built locally using the command `west build`. Normally,
[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,
`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
default keyboard settings.
**Notice that this path should point to the folder labelled `config` within your `zmk-config` folder.**
@ -55,4 +55,4 @@ west build -b nice_nano -- -DSHIELD=kyria_left -DZMK_CONFIG="C:/Users/myUser/Doc
For normal keyboards, follow the same flashing instructions as before to flash your updated firmware.
For split keyboards, only the central (left) side will need to be reflashed if you are just updating your keymap.
More troubleshooting information for split keyboards can be found [here](troubleshooting#split-keyboard-halves-unable-to-pair).
More troubleshooting information for split keyboards can be found [here](troubleshooting.md#split-keyboard-halves-unable-to-pair).

View file

@ -6,12 +6,12 @@ title: Boards, Shields, and Keymaps
The foundational elements needed to get a specific keyboard working with ZMK can be broken down into:
- A [KSCAN driver](https://docs.zephyrproject.org/2.3.0/reference/peripherals/kscan.html), which uses `compatible="zmk,kscan-gpio-matrix"` for GPIO matrix based keyboards, or uses `compatible="zmk,kscan-gpio-direct"` for small direct wires.
- A [KSCAN driver](https://docs.zephyrproject.org/2.5.0/reference/peripherals/kscan.html), which uses `compatible="zmk,kscan-gpio-matrix"` for GPIO matrix based keyboards, or uses `compatible="zmk,kscan-gpio-direct"` for small direct wires.
- An optional matrix transform, which defines how the KSCAN row/column events are translated into logical "key positions". This is required for non-rectangular keyboards/matrices, where the key positions don't naturally follow the row/columns from the GPIO matrix.
- A keymap, which binds each key position to a behavior, e.g. key press, mod-tap, momentary layer, in a set of layers.
These three core architectural elements are defined per-keyboard, and _where_ they are defined depends on the specifics of how that
keyboard works. For an overview on the general concepts of boards and shields, please see the [FAQs on boards and shields](/docs/faq#why-boards-and-shields--why-not-just-keyboard).
keyboard works. For an overview on the general concepts of boards and shields, please see the [FAQs on boards and shields](../faq.md#why-boards-and-shields--why-not-just-keyboard).
## Self-Contained Keyboard
@ -27,8 +27,8 @@ in the `app/boards/${arch}/${board_name}` directory, e.g. `app/boards/arm/planck
- A `${board_name}_defconfig` file that forces specific Kconfig settings that are specific to this hardware configuration. Mostly this is SoC settings around the specific hardware configuration.
- `${board_name}.dts` which contains all the devicetree definitions, including:
- An `#include` line that pulls in the specific microprocessor that is used, e.g. `#include <st/f3/stm32f303Xc.dtsi>`.
- A [chosen](https://docs.zephyrproject.org/2.3.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,kscan` which references the configured KSCAN driver (usually a GPIO matrix)
- (Optional) A [chosen](https://docs.zephyrproject.org/2.3.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,matrix_transform` that defines the mapping from KSCAN row/column values to the logical key position for the keyboard.
- A [chosen](https://docs.zephyrproject.org/2.5.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,kscan` which references the configured KSCAN driver (usually a GPIO matrix)
- (Optional) A [chosen](https://docs.zephyrproject.org/2.5.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,matrix_transform` that defines the mapping from KSCAN row/column values to the logical key position for the keyboard.
- A `board.cmake` file with CMake directives for how to flash to the device.
- A `keymap/keymap.overlay` file that includes the default keymap for that keyboard. Users will be able to override this keymap in their user configs.
@ -47,6 +47,6 @@ in the `app/boards/shields/${board_name}` directory, e.g. `app/boards/shields/cl
- A `Kconfig.shield` that defines the toplevel Kconfig value for the shield, which uses a supplied utility to function to default the value based on the shield list, e.g. `def_bool $(shields_list_contains,clueboard_california)`.
- A `Kconfig.defconfig` file to set default values for things like `ZMK_KEYBOARD_NAME`
- A `${shield_name}.overlay` file, which is a devicetree overlay file, that includes:
- A [chosen](https://docs.zephyrproject.org/2.3.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,kscan` which references the configured KSCAN driver (usually a GPIO matrix). For these keyboards, to be compatible with any Pro Micro compatible boards, the KSCAN configuration should reference the [nexus node](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html#gpio-nexus-nodes) that ZMK has standardized on. In particular, the `&pro_micro_a` and `&pro_micro_d` aliases can be used to reference the standard `A#` and `D#` pins in shields.
- (Optional) A [chosen](https://docs.zephyrproject.org/2.3.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,matrix_transform` that defines the mapping from KSCAN row/column values to the logical key position for the keyboard.
- A [chosen](https://docs.zephyrproject.org/2.5.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,kscan` which references the configured KSCAN driver (usually a GPIO matrix). For these keyboards, to be compatible with any Pro Micro compatible boards, the KSCAN configuration should reference the [nexus node](https://docs.zephyrproject.org/2.5.0/guides/porting/shields.html#gpio-nexus-nodes) that ZMK has standardized on. In particular, the `&pro_micro_a` and `&pro_micro_d` aliases can be used to reference the standard `A#` and `D#` pins in shields.
- (Optional) A [chosen](https://docs.zephyrproject.org/2.5.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,matrix_transform` that defines the mapping from KSCAN row/column values to the logical key position for the keyboard.
- A `keymap/keymap.overlay` file that includes the default keymap for that keyboard. Users will be able to override this keymap in their user configs.

View file

@ -31,7 +31,7 @@ an onboard MCU, or one that uses an MCU board addon.
### Keyboard (Shield) + MCU Board
ZMK treats keyboards that take an MCU addon board as [shields](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html), and treats the smaller MCU board as the true [board](https://docs.zephyrproject.org/2.3.0/guides/porting/board_porting.html)
ZMK treats keyboards that take an MCU addon board as [shields](https://docs.zephyrproject.org/2.5.0/guides/porting/shields.html), and treats the smaller MCU board as the true [board](https://docs.zephyrproject.org/2.5.0/guides/porting/board_porting.html)
Given the following:
@ -47,7 +47,7 @@ west build -b proton_c -- -DSHIELD=kyria_left
### Keyboard With Onboard MCU
Keyboards with onboard MCU chips are simply treated as the [board](https://docs.zephyrproject.org/2.3.0/guides/porting/board_porting.html) as far as Zephyr™ is concerned.
Keyboards with onboard MCU chips are simply treated as the [board](https://docs.zephyrproject.org/2.5.0/guides/porting/board_porting.html) as far as Zephyr™ is concerned.
Given the following:
@ -90,7 +90,7 @@ This produces `left` and `right` subfolders under the `build` directory and two
### Building from `zmk-config` Folder
Instead of building .uf2 files using the default keymap and config files, you can build directly from your [`zmk-config` folder](../user-setup#github-repo) by adding
Instead of building .uf2 files using the default keymap and config files, you can build directly from your [`zmk-config` folder](../user-setup.md#github-repo) by adding
`-DZMK_CONFIG="C:/the/absolute/path/config"` to your `west build` command. **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:
@ -107,7 +107,7 @@ volume automatically -- we need to delete the default volume before binding it t
1. Remove all the containers that are not running via the command `docker container prune`. We need to remove the ZMK container before we can delete the default `zmk-config` volume referenced by it. If you do not want to delete all the containers that are not running, you can find the id of the ZMK container and use `docker rm` to delete that one only.
1. Remove the default volume via the command `docker volume rm zmk-config`.
Then you can bind the `zmk-config` volume to the correct path pointing to your local [zmk-config](./customization.md) folder:
Then you can bind the `zmk-config` volume to the correct path pointing to your local [zmk-config](customization.md) folder:
```
docker volume create --driver local -o o=bind -o type=none -o \

View file

@ -35,7 +35,7 @@ terminal to the ZMK repository and run the following command:
west config build.cmake-args -- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
```
Every [build](build-flash#building) will now update the database. You will
Every [build](build-flash.md#building) will now update the database. You will
need to build once to create the database before code completion will work.
We'll tell Visual Studio Code where to find the database in the next step.

View file

@ -19,7 +19,7 @@ The high level steps are:
- Add support for features such as encoders, OLED displays, or RGB underglow.
- Update build.yml
It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing.
It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/2.5.0/guides/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing.
:::note
ZMK support for split keyboards requires a few more files than single boards to ensure proper connectivity between the central and peripheral units. Check the following guides thoroughly to ensure that all the files are in place.
@ -30,7 +30,7 @@ ZMK support for split keyboards requires a few more files than single boards to
:::note
This guide describes how to add shield to the ZMK main repository. If you are building firmware for your
own prototype or handwired keyboard, it is recommended to use your own user config repository. Follow the
[user setup guide](./user-setup.md) to create your user config repository first. When following the rest
[user setup guide](user-setup.md) to create your user config repository first. When following the rest
of this guide, replace the `app/` directory in the ZMK main repository with the `config/` directory in your
user config repository. For example, `app/boards/shields/<keyboard_name>` should now be
`config/boards/shields/<keyboard_name>`.
@ -449,7 +449,7 @@ Add the following line to your keymap file to add default encoder behavior bindi
sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>;
```
Add additional bindings as necessary to match the default number of encoders on your board. See the [Encoders](/docs/features/encoders) and [Keymap](/docs/features/keymaps) feature documentation for more details.
Add additional bindings as necessary to match the default number of encoders on your board. See the [Encoders](../features/encoders.md) and [Keymap](../features/keymaps.md) feature documentation for more details.
</TabItem>
</Tabs>
@ -477,11 +477,11 @@ west flash
```
Please have a look at documentation specific to
[building and flashing](build-flash) for additional information.
[building and flashing](build-flash.md) for additional information.
:::note
Further testing your keyboard shield without altering the root keymap file can be done with the use of `-DZMK_CONFIG` in your `west build` command,
shown [here](build-flash#building-from-zmk-config-folder)
shown [here](build-flash.md#building-from-zmk-config-folder)
:::
## Updating `build.yml`

View file

@ -188,7 +188,7 @@ brew install cmake ninja python3 ccache dtc git wget dfu-util
</TabItem>
<TabItem value="docker">
This setup leverages the same [image which is used by the GitHub action](https://github.com/zmkfirmware/zephyr-west-action) for local development. Beyond the benefits of [dev/prod parity](https://12factor.net/dev-prod-parity), this approach is also the easiest to set up. No toolchain or dependencies are necessary when using Docker; the container image you'll be using already has the toolchain installed and set up to use.
This setup leverages the same [image which is used by the GitHub action](https://github.com/zmkfirmware/zmk-docker) for local development. Beyond the benefits of [dev/prod parity](https://12factor.net/dev-prod-parity), this approach is also the easiest to set up. No toolchain or dependencies are necessary when using Docker; the container image you'll be using already has the toolchain installed and set up to use.
1. Install [Docker Desktop](https://www.docker.com/products/docker-desktop) for your operating system.
2. Install [VS Code](https://code.visualstudio.com/)
@ -205,9 +205,9 @@ The docker container includes `west` and the compilation toolchain. If you're us
### West Installation
`west` is the [Zephyr™ meta-tool](https://docs.zephyrproject.org/2.3.0/guides/west/index.html) used to configure and build Zephyr™ applications.
`west` is the [Zephyr™ meta-tool](https://docs.zephyrproject.org/2.5.0/guides/west/index.html) used to configure and build Zephyr™ applications.
West can be installed by using the `pip` python package manager. The [Zephyr™ instructions](https://docs.zephyrproject.org/latest/guides/west/install.html#installing-west) are summarized here:
West can be installed by using the `pip` python package manager. The [Zephyr™ instructions](https://docs.zephyrproject.org/2.5.0/guides/west/install.html#installing-west) are summarized here:
<Tabs
defaultValue="linux"
@ -280,10 +280,10 @@ platform.
To build firmwares for the ARM architecture (all supported MCUs/keyboards at this point), you'll need to install the Zephyr™ ARM SDK to your system:
```
export ZSDK_VERSION=0.11.4
wget -q "https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZSDK_VERSION}/zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run" && \
sh "zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run" --quiet -- -d ~/.local/zephyr-sdk-${ZSDK_VERSION} && \
rm "zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run"
export ZSDK_VERSION=0.12.4
wget -q "https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZSDK_VERSION}/zephyr-toolchain-arm-${ZSDK_VERSION}-x86_64-linux-setup.run" && \
sh "zephyr-toolchain-arm-${ZSDK_VERSION}-x86_64-linux-setup.run" --quiet -- -d ~/.local/zephyr-sdk-${ZSDK_VERSION} && \
rm "zephyr-toolchain-arm-${ZSDK_VERSION}-x86_64-linux-setup.run"
```
The installation will prompt with several questions about installation location, and creating a default `~/.zephyrrc` for you with various variables. The defaults should normally work as expected.
@ -292,7 +292,7 @@ The installation will prompt with several questions about installation location,
<TabItem value="raspberryos">
Because Raspberry OS (Raspbian) runs on the same architecture (but different ABI) as the keyboard MCUs,
the operating system's installed [cross compilers](https://docs.zephyrproject.org/2.3.0/getting_started/toolchain_other_x_compilers.html) can be used to target the different ABI.
the operating system's installed [cross compilers](https://docs.zephyrproject.org/2.5.0/getting_started/toolchain_other_x_compilers.html) can be used to target the different ABI.
First, the cross compiler should be installed:
@ -315,10 +315,10 @@ export CROSS_COMPILE=/usr/bin/arm-none-eabi-
To build firmwares for the ARM architecture (all supported MCUs/keyboards at this point), you'll need to install the Zephyr™ ARM SDK to your system:
```
export ZSDK_VERSION=0.11.4
wget -q "https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZSDK_VERSION}/zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run" && \
sh "zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run" --quiet -- -d ~/.local/zephyr-sdk-${ZSDK_VERSION} && \
rm "zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run"
export ZSDK_VERSION=0.12.4
wget -q "https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZSDK_VERSION}/zephyr-toolchain-arm-${ZSDK_VERSION}-x86_64-linux-setup.run" && \
sh "zephyr-toolchain-arm-${ZSDK_VERSION}-x86_64-linux-setup.run" --quiet -- -d ~/.local/zephyr-sdk-${ZSDK_VERSION} && \
rm "zephyr-toolchain-arm-${ZSDK_VERSION}-x86_64-linux-setup.run"
```
The installation will prompt with several questions about installation location, and creating a default `~/.zephyrrc` for you with various variables. The defaults should normally work as expected.
@ -328,14 +328,14 @@ The installation will prompt with several questions about installation location,
#### GNU ARM Embedded
Since the Zephyr™ SDK is not available for Windows, we recommending following the [Zephyr documentation](https://docs.zephyrproject.org/2.3.0/getting_started/toolchain_3rd_party_x_compilers.html#gnu-arm-embedded) to install a GNU ARM Embedded build. Note the warnings regarding installing the toolchain into a path with spaces, and make sure to follow the steps to add the environment variables which are also summarized with screenshots in the [Environment Variables](#environment-variables) section below.
Since the Zephyr™ SDK is not available for Windows, we recommending following the [Zephyr documentation](https://docs.zephyrproject.org/2.5.0/getting_started/toolchain_3rd_party_x_compilers.html#gnu-arm-embedded) to install a GNU ARM Embedded build. Note the warnings regarding installing the toolchain into a path with spaces, and make sure to follow the steps to add the environment variables which are also summarized with screenshots in the [Environment Variables](#environment-variables) section below.
</TabItem>
<TabItem value="mac">
#### GNU ARM Embedded
Since the Zephyr™ SDK is not available for macOS, we recommending following the steps to install the [GNU ARM Embedded](https://docs.zephyrproject.org/2.3.0/getting_started/toolchain_3rd_party_x_compilers.html#gnu-arm-embedded).
Since the Zephyr™ SDK is not available for macOS, we recommending following the steps to install the [GNU ARM Embedded](https://docs.zephyrproject.org/2.5.0/getting_started/toolchain_3rd_party_x_compilers.html#gnu-arm-embedded).
The install command is:
@ -345,7 +345,7 @@ brew install --cask gcc-arm-embedded
:::warning Security Controls Workaround
Please be sure to read the [additional setup instructions](https://docs.zephyrproject.org/2.3.0/getting_started/installation_mac.html#mac-gatekeeper) needed to address security controls found in macOS 10.15 Catalina and newer
Please be sure to read the [additional setup instructions](https://docs.zephyrproject.org/2.5.0/getting_started/installation_mac.html#mac-gatekeeper) needed to address security controls found in macOS 10.15 Catalina and newer
:::
@ -456,7 +456,7 @@ This step pulls down quite a bit of tooling. Go grab a cup of coffee, it can tak
:::info
If you're using Docker, you're done with setup! You must restart the container at this point. The easiest way to do so is to close the VS Code window, verify that the container has stopped in Docker Dashboard, and reopen the container with VS Code.
Once your container is restarted, proceed to [Building and Flashing](./development/build-flash.md).
Once your container is restarted, proceed to [Building and Flashing](development/build-flash.md).
:::
#### Export Zephyr™ Core
@ -514,7 +514,7 @@ On Windows, only two environment variables need to be set for ZMK to build prope
#### For Zephyr
By default, the Zephyr™ SDK will create a file named `~/.zephyrrc` with the correct environment variables to build ZMK.
We suggest two main [options](https://docs.zephyrproject.org/2.3.0/guides/env_vars.html?highlight=zephyrrc) for how to load those settings.
We suggest two main [options](https://docs.zephyrproject.org/2.5.0/guides/env_vars.html#option-3-using-zephyrrc-files) for how to load those settings.
##### Per Shell

View file

@ -3,7 +3,7 @@ title: Tests
sidebar_label: Tests
---
Running tests requires [native posix support](posix-board). Any folder under `/app/tests`
Running tests requires [native posix support](posix-board.md). Any folder under `/app/tests`
containing `native_posix.keymap` will be selected when running `west test`.
Run a single test with `west test <testname>`, like `west test tests/toggle-layer/normal`.

View file

@ -24,7 +24,7 @@ The `CONFIG_ZMK_USB_LOGGING` KConfig value needs to be set, either by copy and p
`west build -t menuconfig` and manually enabling the setting in that UI at `ZMK -> Advanced -> USB Logging`.
:::note
If you are debugging your own keyboard in your [user config repository](./user-setup.md), use
If you are debugging your own keyboard in your [user config repository](user-setup.md), use
`config/boards/shields/<your_keyboard>/<your_keyboard>.conf` instead of `app/prj.conf`. In Github
Actions, you can search the `Kconfig file` build log to verify the options above have been enabled
for you successfully.

View file

@ -5,6 +5,10 @@ sidebar_label: Encoders
Existing support for encoders in ZMK is focused around the five pin EC11 rotary encoder with push button design used in the majority of current keyboard and macropad designs.
:::note
Encoders are currently only support on the left/central sides of splits. For progress on this, see [#728](https://github.com/zmkfirmware/zmk/pull/728).
:::
## Enabling EC11 Encoders
To enable encoders for boards that have existing encoder support, uncomment the `EC11_CONFIG=y` and `CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y` lines in your board's .conf file in your `zmk-config/config` folder. Save and push your changes, then download and flash the new firmware.
@ -25,7 +29,7 @@ Rotation is handled separately as a type of sensor. The behavior for this is set
sensor-bindings = <BINDING CW_KEY CCW_KEY>;
```
- `BINDING`, for now, has only one behavior available; `&inc_dec_kp` for key presses (see [Key Press](/docs/behaviors/key-press) for details on available keycodes).
- `BINDING`, for now, has only one behavior available; `&inc_dec_kp` for key presses (see [Key Press](../behaviors/key-press.md) for details on available keycodes).
- `CW_KEY` is the keycode activated by a clockwise turn.
- `CCW_KEY` is the keycode activated by a counter-clockwise turn.
@ -41,4 +45,4 @@ Here, the left encoder is configured to control volume up and down while the rig
## Adding Encoder Support
See the [New Keyboard Shield](/docs/development/new-shield#encoders) documentation for how to add or modify additional encoders to your shield.
See the [New Keyboard Shield](../development/new-shield.md#encoders) documentation for how to add or modify additional encoders to your shield.

View file

@ -33,7 +33,7 @@ For example, the simplest behavior in ZMK is the "key press" behavior, which res
(a certain spot on the keyboard), and when that position is pressed, send a keycode to the host, and
when the key position is released, updates the host to notify of the keycode being released.
For the full set of possible behaviors, start at the [Key Press](/docs/behaviors/key-press) behavior.
For the full set of possible behaviors, start at the [Key Press](../behaviors/key-press.md) behavior.
## Layers
@ -98,7 +98,7 @@ The second include brings in the defines for all the keycodes (e.g. `A`, `N1`, `
### Root devicetree Node
ALl the remaining keymap nodes will be nested inside of the root devicetree node, like so:
All the remaining keymap nodes will be nested inside of the root devicetree node, like so:
```devicetree
/ {
@ -131,7 +131,7 @@ Each layer should have:
1. A `bindings` property this will be a list of behaviour bindings, one for each key position for the keyboard.
1. (Optional) A `sensor-bindings` property that will be a list of behavior bindings for each sensor on the keyboard. (Currently, only encoders are supported as sensor hardware, but in the future devices like trackpoints would be supported the same way)
For the full set of possible behaviors, start at the [Key Press](/docs/behaviors/key-press) behavior.
For the full set of possible behaviors, start at the [Key Press](../behaviors/key-press.md) behavior.
### Complete Example

View file

@ -11,11 +11,11 @@ have had their hardware details codified in boards/shields for ZMK.
:::
With the solid technical foundation of Zephyr™ RTOS, ZMK can support a wide diversity of hardware targets.
That being said, there are currently only a few specific [boards](/docs/faq#what-is-a-board)/[shields](/docs/faq#what-is-a-shield) that have been written and tested by the ZMK contributors.
That being said, there are currently only a few specific [boards](faq.md#what-is-a-board)/[shields](faq.md#what-is-a-shield) that have been written and tested by the ZMK contributors.
## Boards
- [nice!nano](https://nicekeyboards.com/products/nice-nano-v1-0) (`nice_nano`)
- [nice!nano](https://nicekeyboards.com/nice-nano) (`nice_nano`, `nice_nano_v2`)
- [nrfMicro](https://github.com/joric/nrfmicro) (`nrfmicro_13`, `nrfmicro_11`, `nrfmicro_11_flipped`)
- [BlueMicro840](https://store.jpconstantineau.com/#/group/bluemicro) (`bluemicro840_v1`)
- [QMK Proton-C](https://qmk.fm/proton-c/) (`proton_c`)
@ -54,4 +54,4 @@ Until detailed documentation is available, feel free to ask questions about how
## Contributing
If you'd like to add support for a new keyboard shield, head over to the [New Keyboard Shield](development/new-shield) documentation.
If you'd like to add support for a new keyboard shield, head over to the [New Keyboard Shield](development/new-shield.md) documentation.

View file

@ -14,32 +14,32 @@ ZMK is currently missing some features found in other popular firmware. This tab
| Legend: | ✅ Supported | 🚧 Under Development | 💡 Planned |
| :------ | :----------- | :------------------- | :--------- |
| **Feature** | ZMK | BlueMicro | QMK |
| ------------------------------------------------------------------------------------------------------------------------- | :-: | :-------: | :-: |
| Low Latency BLE Support | ✅ | ✅ | |
| Multi-Device BLE Support | ✅ | | |
| [USB Connectivity](behaviors/outputs) | ✅ | ✅ | ✅ |
| User Configuration Repositories | ✅ | | |
| Split Keyboard Support | ✅ | ✅ | ✅ |
| [Keymaps and Layers](behaviors/layers) | ✅ | ✅ | ✅ |
| [Hold-Tap](behaviors/hold-tap) (which includes [Mod-Tap](behaviors/mod-tap) and [Layer-Tap](behaviors/layers/#layer-tap)) | ✅ | ✅ | ✅ |
| [Keyboard Codes](codes/#keyboard) | ✅ | ✅ | ✅ |
| [Media](codes/#media-controls) & [Consumer](codes/#consumer-controls) Codes | ✅ | ✅ | ✅ |
| [Encoders](features/encoders)[^1] | ✅ | ✅ | ✅ |
| [Display Support](features/displays)[^2] | 🚧 | 🚧 | ✅ |
| [RGB Underglow](features/underglow) | ✅ | ✅ | ✅ |
| One Shot Keys | ✅ | ✅ | ✅ |
| [Combo Keys](features/combos) | ✅ | | ✅ |
| Macros | 🚧 | ✅ | ✅ |
| Mouse Keys | 💡 | ✅ | ✅ |
| Low Active Power Usage | ✅ | | |
| Low Power Sleep States | ✅ | ✅ | |
| [Low Power Mode (VCC Shutoff)](behaviors/power) | ✅ | ✅ | |
| Battery Reporting | ✅ | ✅ | |
| Shell over BLE | 💡 | | |
| Realtime Keymap Updating | 💡 | | ✅ |
| AVR/8 Bit | | | ✅ |
| [Wide Range of ARM Chips Supported](https://docs.zephyrproject.org/latest/boards/index.html) | ✅ | | |
| **Feature** | ZMK | BlueMicro | QMK |
| ---------------------------------------------------------------------------------------------------------------------------------- | :-: | :-------: | :-: |
| Low Latency BLE Support | ✅ | ✅ | |
| Multi-Device BLE Support | ✅ | | |
| [USB Connectivity](behaviors/outputs.md) | ✅ | ✅ | ✅ |
| User Configuration Repositories | ✅ | | |
| Split Keyboard Support | ✅ | ✅ | ✅ |
| [Keymaps and Layers](behaviors/layers.md) | ✅ | ✅ | ✅ |
| [Hold-Tap](behaviors/hold-tap.md) (which includes [Mod-Tap](behaviors/mod-tap.md) and [Layer-Tap](behaviors/layers.md/#layer-tap)) | ✅ | ✅ | ✅ |
| [Keyboard Codes](codes/index.mdx#keyboard) | ✅ | ✅ | ✅ |
| [Media](codes/index.mdx#media-controls) & [Consumer](codes/index.mdx#consumer-controls) Codes | ✅ | ✅ | ✅ |
| [Encoders](features/encoders.md)[^1] | ✅ | ✅ | ✅ |
| [Display Support](features/displays.md)[^2] | 🚧 | 🚧 | ✅ |
| [RGB Underglow](features/underglow.md) | ✅ | ✅ | ✅ |
| One Shot Keys | ✅ | ✅ | ✅ |
| [Combo Keys](features/combos.md) | ✅ | | ✅ |
| Macros | 🚧 | ✅ | ✅ |
| Mouse Keys | 💡 | ✅ | ✅ |
| Low Active Power Usage | ✅ | | |
| Low Power Sleep States | ✅ | ✅ | |
| [Low Power Mode (VCC Shutoff)](behaviors/power.md) | ✅ | ✅ | |
| Battery Reporting | ✅ | ✅ | |
| Shell over BLE | 💡 | | |
| Realtime Keymap Updating | 💡 | | ✅ |
| AVR/8 Bit | | | ✅ |
| [Wide Range of ARM Chips Supported](https://docs.zephyrproject.org/latest/boards/index.html) | ✅ | | |
[^2]: Encoders are not currently supported on peripheral side splits.
[^1]: OLEDs are currently proof of concept in ZMK.

View file

@ -14,7 +14,7 @@
// | GUI | DEL | RETURN | SPACE | ESCAPE | | RETURN | SPACE | TAB | BSPC | R ALT |
bindings = <
&kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
&kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp QUOTE
&kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT
&kp LSHIFT &kp Z &kp X &kp C &kp V &kp B &kp LC(A) &kp LC(C) &kp LC(V) &kp LC(X) &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RCTRL
&kp LGUI &kp DEL &kp RET &kp SPACE &kp ESC &kp RET &kp SPACE &kp TAB &kp BSPC &kp RALT
>;

View file

@ -10,7 +10,7 @@
// | GUI | DEL | RETURN | SPACE | ESCAPE | | RETURN | SPACE | TAB | BSPC | R ALT |
bindings = <
&kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
&kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp QUOTE
&kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT
&kp LSHIFT &kp Z &kp X &kp C &kp V &kp B &kp LC(A) &kp LC(C) &kp LC(V) &kp LC(X) &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RCTRL
&kp LGUI &kp DEL &kp RET &kp SPACE &kp ESC &kp RET &kp SPACE &kp TAB &kp BSPC &kp RALT
>;

View file

@ -26,7 +26,7 @@ Variations of the warnings shown below occur when flashing the `<firmware>.uf2`
### CMake Error
An error along the lines of `CMake Error at (zmk directory)/zephyr/cmake/generic_toolchain.cmake:64 (include): include could not find load file:` during firmware compilation indicates that the Zephyr Environment Variables are not properly defined.
For more information, click [here](../docs/development/setup#environment-variables).
For more information, click [here](../docs/development/setup.md#environment-variables).
### dtlib.DTError

View file

@ -105,7 +105,7 @@ Pick an MCU board:
:::note
If you are building firmware for a new keyboard shield that is not included in the built-in
list of shields, you can choose any shield from the list that is similar to yours to generate the repository,
and edit / add necessary files according to the [guide for adding new keyboard shield](./development/new-shield).
and edit / add necessary files according to the [guide for adding new keyboard shield](development/new-shield.md).
:::
When prompted, enter the number for the corresponding keyboard shield you would like to target:
@ -189,13 +189,13 @@ To flash the firmware, first put your board into bootloader mode by double click
or the one that is part of your keyboard). The controller should appear in your OS as a new USB storage device.
Once this happens, copy the correct UF2 file (e.g. left or right if working on a split), and paste it onto the root of that USB mass
storage device. Once the flash is complete, the controller should automatically restart, and load your newfly flashed firmware.
storage device. Once the flash is complete, the controller should automatically restart, and load your newly flashed firmware.
## Wirelessly Connecting Your Keyboard
ZMK will automatically advertise itself as connectable if it is not currently connected to a device. You should be able to see your keyboard from the bluetooth scanning view of your laptop or phone / tablet. It is reported by some users that the connections with Android / iOS devices are generally smoother than with laptops, so if you have trouble connecting, you could try to connect from your phone or tablet first to eliminate any potential hardware issues.
ZMK support multiple BLE “profiles”, which allows you to connect to and switch among multiple devices. Please refer to the [Bluetooth behavior](behaviors/bluetooth) section for detailed explanations of how to use them.
ZMK support multiple BLE “profiles”, which allows you to connect to and switch among multiple devices. Please refer to the [Bluetooth behavior](behaviors/bluetooth.md) section for detailed explanations of how to use them.
### Connecting Split Keyboard Halves

15777
docs/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -14,8 +14,8 @@
"prettier:format": "prettier --write ."
},
"dependencies": {
"@docusaurus/core": "^2.0.0-beta.1",
"@docusaurus/preset-classic": "^2.0.0-beta.1",
"@docusaurus/core": "^2.0.0-beta.3",
"@docusaurus/preset-classic": "^2.0.0-beta.3",
"@fortawesome/fontawesome-svg-core": "^1.2.32",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "^0.1.14",
@ -25,7 +25,7 @@
"react-copy-to-clipboard": "^5.0.3",
"react-dom": "^17.0.2",
"react-toastify": "^7.0.4",
"web-tree-sitter": "^0.17.1"
"web-tree-sitter": "^0.19.4"
},
"browserslist": {
"production": [
@ -40,12 +40,12 @@
]
},
"devDependencies": {
"eslint": "^7.29.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-mdx": "^1.13.0",
"eslint-plugin-react": "^7.23.2",
"null-loader": "^4.0.0",
"prettier": "2.3.1",
"string-replace-loader": "^3.0.0"
"string-replace-loader": "^3.0.3"
}
}

View file

@ -37,7 +37,7 @@ export const zmkBase = {
*/
export const zmkBoards = {
"nice!nano": {
name: "nice!nano",
name: "nice!nano v1",
powerSupply: {
type: "LDO",
outputVoltage: 3.3,
@ -45,6 +45,15 @@ export const zmkBoards = {
},
otherQuiescentMicroA: 4,
},
"nice!nano v2": {
name: "nice!nano v2",
powerSupply: {
type: "LDO",
outputVoltage: 3.3,
quiescentMicroA: 15,
},
otherQuiescentMicroA: 3,
},
"nice!60": {
powerSupply: {
type: "SWITCHING",

View file

@ -11,17 +11,33 @@ module.exports = function () {
loader: "null-loader",
});
} else {
// web-tree-sitter has a hard-coded path to tree-sitter.wasm,
// The way web-tree-sitter loads tree-sitter.wasm isn't something that
// Docusaurus/Webpack identify as an asset. There is currently no way to
// set location of the file other than patching web-tree-sitter.
// (see https://github.com/tree-sitter/tree-sitter/issues/559)
// which some browsers treat as absolute and others as relative.
// This breaks everything. Rewrite it to always use an absolute path.
rules.push({
test: /tree-sitter\.js$/,
loader: "string-replace-loader",
options: {
search: '"tree-sitter.wasm"',
replace: '"/tree-sitter.wasm"',
strict: true,
multiple: [
// Replace the path to tree-sitter.wasm with a "new URL()" to clue
// Webpack in that it is an asset.
{
search: '"tree-sitter.wasm"',
replace: '(new URL("tree-sitter.wasm", import.meta.url)).href',
strict: true,
},
// Webpack replaces "new URL()" with the full URL to the asset, but
// web-tree-sitter will still add a prefix to it unless there is a
// Module.locateFile() function.
{
search: "var Module=void 0!==Module?Module:{};",
replace: `var Module = {
locateFile: (path, prefix) => path.startsWith('http') ? path : prefix + path,
};`,
strict: true,
},
],
},
});
}

Some files were not shown because too many files have changed in this diff Show more