Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Soft Off #1942

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ target_sources(app PRIVATE src/matrix_transform.c)
target_sources(app PRIVATE src/sensors.c)
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/wpm.c)
target_sources(app PRIVATE src/event_manager.c)
target_sources_ifdef(CONFIG_ZMK_GPIO_KEY_BEHAVIOR_TRIGGER app PRIVATE src/gpio_key_behavior_trigger.c)
target_sources_ifdef(CONFIG_ZMK_GPIO_SCANNED_KEY_BEHAVIOR_TRIGGER app PRIVATE src/gpio_scanned_key_behavior_trigger.c)
target_sources_ifdef(CONFIG_ZMK_PM app PRIVATE src/pm.c)
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c)
target_sources_ifdef(CONFIG_ZMK_GPIO_KEY_WAKEUP_TRIGGER app PRIVATE src/gpio_key_wakeup_trigger.c)
target_sources(app PRIVATE src/events/activity_state_changed.c)
target_sources(app PRIVATE src/events/position_state_changed.c)
target_sources(app PRIVATE src/events/sensor_event.c)
Expand All @@ -31,6 +35,7 @@ target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c)
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/events/usb_conn_state_changed.c)
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c)
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SOFT_OFF app PRIVATE src/behaviors/behavior_soft_off.c)
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
target_sources(app PRIVATE src/hid.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse.c)
Expand Down
13 changes: 13 additions & 0 deletions app/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,19 @@ config ZMK_EXT_POWER
bool "Enable support to control external power output"
default y

config ZMK_PM
bool

config ZMK_PM_SOFT_OFF
bool "Soft-off support"
select ZMK_PM
select PM_DEVICE

config ZMK_GPIO_KEY_WAKEUP_TRIGGER
bool "Hardware supported wakeup (GPIO)"
default y
depends on DT_HAS_ZMK_GPIO_KEY_WAKEUP_TRIGGER_ENABLED && ZMK_PM_SOFT_OFF

#Power Management
endmenu

Expand Down
15 changes: 15 additions & 0 deletions app/Kconfig.behaviors
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# Copyright (c) 2023 The ZMK Contributors
# SPDX-License-Identifier: MIT

config ZMK_GPIO_KEY_BEHAVIOR_TRIGGER
bool
default y
depends on DT_HAS_ZMK_GPIO_KEY_BEHAVIOR_TRIGGER_ENABLED

config ZMK_GPIO_SCANNED_KEY_BEHAVIOR_TRIGGER
bool
default y
depends on DT_HAS_ZMK_GPIO_SCANNED_KEY_BEHAVIOR_TRIGGER_ENABLED

config ZMK_BEHAVIOR_KEY_TOGGLE
bool
default y
Expand All @@ -12,6 +22,11 @@ config ZMK_BEHAVIOR_MOUSE_KEY_PRESS
depends on DT_HAS_ZMK_BEHAVIOR_MOUSE_KEY_PRESS_ENABLED
imply ZMK_MOUSE

config ZMK_BEHAVIOR_SOFT_OFF
bool
default y
depends on DT_HAS_ZMK_BEHAVIOR_SOFT_OFF_ENABLED && ZMK_PM_SOFT_OFF

config ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON
bool
default n
Expand Down
3 changes: 3 additions & 0 deletions app/boards/shields/zmk_uno/Kconfig.defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ config ZMK_RGB_UNDERGLOW
select WS2812_STRIP
select SPI

config ZMK_PM_SOFT_OFF
default y if BOARD_NRF52840DK_NRF52840

endif
44 changes: 43 additions & 1 deletion app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@
bias-pull-up;
};
};

qdec_sleep: qdec_sleep {
group1 {
psels = <NRF_PSEL(QDEC_A, 1, 11)>,
<NRF_PSEL(QDEC_B, 1, 10)>;
bias-pull-up;
low-power-enable;
};
};
};

// Set up the QDEC hardware based driver and give it the same label as the deleted node.
Expand All @@ -20,5 +29,38 @@ encoder: &qdec0 {
led-pre = <0>;
steps = <80>;
pinctrl-0 = <&qdec_default>;
pinctrl-names = "default";
pinctrl-1 = <&qdec_sleep>;
pinctrl-names = "default", "sleep";
};

/ {
behaviors {
soft_off: soft_off {
compatible = "zmk,behavior-soft-off";
#binding-cells = <0>;
status = "okay";
};
};

wakeup_source: wakeup_source {
compatible = "zmk,gpio-key-wakeup-trigger";
status = "okay";

trigger = <&button0>;
wakeup-source;
};

soft_off_wakers {
compatible = "zmk,soft-off-wakeup-sources";
status = "okay";

wakeup-sources = <&wakeup_source>;
};

soft_off_behavior_key {
compatible = "zmk,gpio-key-behavior-trigger";
status = "okay";
bindings = <&soft_off>;
key = <&button0>;
};
};
2 changes: 2 additions & 0 deletions app/boards/shields/zmk_uno/zmk_uno.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ nice_view_spi: &arduino_spi {

kscan_matrix: kscan_matrix {
compatible = "zmk,kscan-gpio-matrix";
wakeup-source;

diode-direction = "col2row";

Expand All @@ -141,6 +142,7 @@ nice_view_spi: &arduino_spi {

kscan_direct: kscan_direct {
compatible = "zmk,kscan-gpio-direct";
wakeup-source;
status = "disabled";

input-gpios
Expand Down
1 change: 1 addition & 0 deletions app/dts/behaviors.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
#include <behaviors/backlight.dtsi>
#include <behaviors/macros.dtsi>
#include <behaviors/mouse_key_press.dtsi>
#include <behaviors/soft_off.dtsi>
14 changes: 14 additions & 0 deletions app/dts/behaviors/soft_off.dtsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) 2023 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

/ {
behaviors {
/omit-if-no-ref/ soft_off: soft_off {
compatible = "zmk,behavior-soft-off";
#binding-cells = <0>;
};
};
};
14 changes: 14 additions & 0 deletions app/dts/bindings/behaviors/zmk,behavior-soft-off.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2023 The ZMK Contributors
# SPDX-License-Identifier: MIT

description: Soft-Off Behavior

compatible: "zmk,behavior-soft-off"

include: zero_param.yaml

properties:
hold-time-ms:
type: int
required: false
description: Number of milliseconds the behavior must be held before releasing will actually trigger a soft-off.
31 changes: 31 additions & 0 deletions app/dts/bindings/zmk,gpio-key-behavior-trigger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright (c) 2023 The ZMK Contributors
# SPDX-License-Identifier: MIT

description: |
Driver for a dedicated key for invoking a connected behavior.

compatible: "zmk,gpio-key-behavior-trigger"

include: base.yaml

properties:
key:
type: phandle
required: true
description: The GPIO key that triggers wake via interrupt
bindings:
type: phandle
required: true
description: The behavior to invoke when the GPIO key is pressed
debounce-press-ms:
type: int
default: 5
description: Debounce time for key press in milliseconds. Use 0 for eager debouncing.
debounce-release-ms:
type: int
default: 5
description: Debounce time for key release in milliseconds.
debounce-scan-period-ms:
type: int
default: 1
description: Time between reads in milliseconds when any key is pressed.
18 changes: 18 additions & 0 deletions app/dts/bindings/zmk,gpio-key-wakeup-trigger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (c) 2023 The ZMK Contributors
# SPDX-License-Identifier: MIT

description: |
Driver for a dedicated key for waking the device from sleep

compatible: "zmk,gpio-key-wakeup-trigger"

include: base.yaml

properties:
trigger:
type: phandle
required: true
description: The GPIO key that triggers wake via interrupt
extra-gpios:
type: phandle-array
description: Optional set of pins that should be set active before sleeping.
31 changes: 31 additions & 0 deletions app/dts/bindings/zmk,gpio-scanned-key-behavior-trigger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright (c) 2023 The ZMK Contributors
# SPDX-License-Identifier: MIT

description: |
Driver for a dedicated key triggered by matrix scanning for invoking a connected behavior.

compatible: "zmk,gpio-scanned-key-behavior-trigger"

include: base.yaml

properties:
key:
type: phandle
required: true
description: The GPIO key that triggers wake via interrupt
bindings:
type: phandle
required: true
description: The behavior to invoke when the GPIO key is pressed
debounce-press-ms:
type: int
default: 5
description: Debounce time for key press in milliseconds. Use 0 for eager debouncing.
debounce-release-ms:
type: int
default: 5
description: Debounce time for key release in milliseconds.
debounce-scan-period-ms:
type: int
default: 1
description: Time between reads in milliseconds when any key is pressed.
14 changes: 14 additions & 0 deletions app/dts/bindings/zmk,soft-off-wakeup-sources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2023 The ZMK Contributors
# SPDX-License-Identifier: MIT

description: |
Description of all possible wakeup-sources from a forced
soft-off state.

compatible: "zmk,soft-off-wakeup-sources"

properties:
wakeup-sources:
type: phandles
required: true
description: List of wakeup-sources that should be enabled to wake the system from forced soft-off state.
2 changes: 2 additions & 0 deletions app/include/zmk/endpoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,5 @@ int zmk_endpoints_send_report(uint16_t usage_page);
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
int zmk_endpoints_send_mouse_report();
#endif // IS_ENABLE(CONFIG_ZMK_MOUSE)

void zmk_endpoints_clear_current(void);
9 changes: 9 additions & 0 deletions app/include/zmk/pm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright (c) 2023 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

#pragma once

int zmk_pm_soft_off(void);
22 changes: 21 additions & 1 deletion app/module/drivers/kscan/kscan_gpio_direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <zephyr/drivers/kscan.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include <zephyr/sys/util.h>

#include <zmk/debounce.h>
Expand Down Expand Up @@ -318,6 +319,23 @@ static int kscan_direct_init(const struct device *dev) {
return 0;
}

#if IS_ENABLED(CONFIG_PM_DEVICE)

static int kscan_direct_pm_action(const struct device *dev, enum pm_device_action action) {
switch (action) {
case PM_DEVICE_ACTION_SUSPEND:
kscan_direct_disable(dev);
break;
case PM_DEVICE_ACTION_RESUME:
kscan_direct_enable(dev);
break;
default:
return -ENOTSUP;
}
}

#endif // IS_ENABLED(CONFIG_PM_DEVICE)

static const struct kscan_driver_api kscan_direct_api = {
.config = kscan_direct_configure,
.enable_callback = kscan_direct_enable,
Expand Down Expand Up @@ -354,7 +372,9 @@ static const struct kscan_driver_api kscan_direct_api = {
.toggle_mode = DT_INST_PROP(n, toggle_mode), \
}; \
\
DEVICE_DT_INST_DEFINE(n, &kscan_direct_init, NULL, &kscan_direct_data_##n, \
PM_DEVICE_DT_INST_DEFINE(n, kscan_direct_pm_action); \
\
DEVICE_DT_INST_DEFINE(n, &kscan_direct_init, PM_DEVICE_DT_INST_GET(n), &kscan_direct_data_##n, \
&kscan_direct_config_##n, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \
&kscan_direct_api);

Expand Down
20 changes: 19 additions & 1 deletion app/module/drivers/kscan/kscan_gpio_matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/kscan.h>
#include <zephyr/pm/device.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/__assert.h>
Expand Down Expand Up @@ -421,6 +422,21 @@ static int kscan_matrix_init(const struct device *dev) {
return 0;
}

#if IS_ENABLED(CONFIG_PM_DEVICE)

static int kscan_matrix_pm_action(const struct device *dev, enum pm_device_action action) {
petejohanson marked this conversation as resolved.
Show resolved Hide resolved
switch (action) {
case PM_DEVICE_ACTION_SUSPEND:
return kscan_matrix_disable(dev);
case PM_DEVICE_ACTION_RESUME:
return kscan_matrix_enable(dev);
default:
return -ENOTSUP;
}
}

#endif // IS_ENABLED(CONFIG_PM_DEVICE)

static const struct kscan_driver_api kscan_matrix_api = {
.config = kscan_matrix_configure,
.enable_callback = kscan_matrix_enable,
Expand Down Expand Up @@ -465,7 +481,9 @@ static const struct kscan_driver_api kscan_matrix_api = {
.diode_direction = INST_DIODE_DIR(n), \
}; \
\
DEVICE_DT_INST_DEFINE(n, &kscan_matrix_init, NULL, &kscan_matrix_data_##n, \
PM_DEVICE_DT_INST_DEFINE(n, kscan_matrix_pm_action); \
\
DEVICE_DT_INST_DEFINE(n, &kscan_matrix_init, PM_DEVICE_DT_INST_GET(n), &kscan_matrix_data_##n, \
&kscan_matrix_config_##n, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \
&kscan_matrix_api);

Expand Down
Loading
Loading