aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorPete Johanson <[email protected]>2023-12-29 16:28:22 -0800
committerPete Johanson <[email protected]>2024-03-27 20:59:26 -0700
commit933fdcd36400ea9d2f73284ff5936e0c6cefe879 (patch)
treef342ab728b2d870bd75a398de675b9b90df11cf8
parent5ebe924e941ba00e81d1c66ad2333e6a73826754 (diff)
downloadzmk-933fdcd36400ea9d2f73284ff5936e0c6cefe879.tar.gz
zmk-933fdcd36400ea9d2f73284ff5936e0c6cefe879.zip
refactor(pm): Remove scanned behavior trigger.
* Remove the painful scanned behavior trigger for now, future enhancement will restore this high level functionality using kscan directly.
-rw-r--r--app/CMakeLists.txt1
-rw-r--r--app/Kconfig.behaviors5
-rw-r--r--app/dts/bindings/zmk,gpio-scanned-key-behavior-trigger.yaml31
-rw-r--r--app/src/gpio_scanned_key_behavior_trigger.c184
-rw-r--r--docs/docs/features/soft-off.md17
5 files changed, 2 insertions, 236 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index a56a63b369..4ee9135d23 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -30,7 +30,6 @@ 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)
diff --git a/app/Kconfig.behaviors b/app/Kconfig.behaviors
index ecd06ffbff..6abdbddd77 100644
--- a/app/Kconfig.behaviors
+++ b/app/Kconfig.behaviors
@@ -6,11 +6,6 @@ config ZMK_GPIO_KEY_BEHAVIOR_TRIGGER
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
diff --git a/app/dts/bindings/zmk,gpio-scanned-key-behavior-trigger.yaml b/app/dts/bindings/zmk,gpio-scanned-key-behavior-trigger.yaml
deleted file mode 100644
index 860155dda7..0000000000
--- a/app/dts/bindings/zmk,gpio-scanned-key-behavior-trigger.yaml
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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.
diff --git a/app/src/gpio_scanned_key_behavior_trigger.c b/app/src/gpio_scanned_key_behavior_trigger.c
deleted file mode 100644
index d27b162b19..0000000000
--- a/app/src/gpio_scanned_key_behavior_trigger.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2023 The ZMK Contributors
- *
- * SPDX-License-Identifier: MIT
- */
-
-#define DT_DRV_COMPAT zmk_gpio_scanned_key_behavior_trigger
-
-#include <zephyr/device.h>
-#include <drivers/behavior.h>
-#include <zephyr/drivers/gpio.h>
-#include <zephyr/logging/log.h>
-#include <zephyr/pm/device.h>
-
-#include <zmk/event_manager.h>
-#include <zmk/behavior.h>
-#include <zmk/debounce.h>
-#include <zmk/keymap.h>
-
-LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-
-struct gskbt_config {
- struct zmk_debounce_config debounce_config;
- int32_t debounce_scan_period_ms;
- struct gpio_dt_spec key;
-};
-
-struct gskbt_data {
- struct zmk_behavior_binding binding;
- struct zmk_debounce_state debounce_state;
- struct gpio_callback key_callback;
- const struct device *dev;
- struct k_work_delayable update_work;
- struct k_work gpio_trigger_work;
- uint32_t read_time;
- uint32_t trigger_time;
- bool pin_active;
- bool active_scan_detected;
-};
-
-static void gskbt_enable_interrupt(const struct device *dev, bool active_scanning) {
- const struct gskbt_config *config = dev->config;
-
- gpio_pin_interrupt_configure_dt(&config->key, active_scanning ? GPIO_INT_EDGE_TO_ACTIVE
- : GPIO_INT_LEVEL_ACTIVE);
-}
-
-static void gskbt_disable_interrupt(const struct device *dev) {
- const struct gskbt_config *config = dev->config;
-
- gpio_pin_interrupt_configure_dt(&config->key, GPIO_INT_DISABLE);
-}
-
-static void gskbt_read(const struct device *dev) {
- const struct gskbt_config *config = dev->config;
- struct gskbt_data *data = dev->data;
-
- zmk_debounce_update(&data->debounce_state, data->active_scan_detected,
- config->debounce_scan_period_ms, &config->debounce_config);
-
- if (zmk_debounce_get_changed(&data->debounce_state)) {
- const bool pressed = zmk_debounce_is_pressed(&data->debounce_state);
-
- struct zmk_behavior_binding_event event = {.position = INT32_MAX,
- .timestamp = k_uptime_get()};
-
- if (pressed) {
- behavior_keymap_binding_pressed(&data->binding, event);
- } else {
- behavior_keymap_binding_released(&data->binding, event);
- }
- }
-
- if (zmk_debounce_is_active(&data->debounce_state)) {
- data->active_scan_detected = false;
- data->read_time += config->debounce_scan_period_ms;
-
- k_work_schedule(&data->update_work, K_TIMEOUT_ABS_MS(data->read_time));
- } else {
- gskbt_enable_interrupt(dev, false);
- }
-}
-
-static void gskbt_update_work(struct k_work *work) {
- struct k_work_delayable *dwork = CONTAINER_OF(work, struct k_work_delayable, work);
- struct gskbt_data *data = CONTAINER_OF(dwork, struct gskbt_data, update_work);
- gskbt_read(data->dev);
-}
-
-static void gskbt_gpio_interrupt_work(struct k_work *work) {
- struct gskbt_data *data = CONTAINER_OF(work, struct gskbt_data, gpio_trigger_work);
-
- const struct gskbt_config *config = data->dev->config;
-
- if (!zmk_debounce_is_active(&data->debounce_state)) {
- // When we get that very first interrupt, we need to schedule the update checks right before
- // the next real scan, so we can do our checks for state *after* each scan has
- // occurred.
- data->read_time = data->trigger_time;
- k_work_reschedule(&data->update_work,
- K_TIMEOUT_ABS_MS(data->read_time + config->debounce_scan_period_ms - 1));
- }
-}
-
-static void gskbt_gpio_irq_callback(const struct device *port, struct gpio_callback *cb,
- const gpio_port_pins_t pin) {
- struct gskbt_data *data = CONTAINER_OF(cb, struct gskbt_data, key_callback);
-
- // LOG_DBG("IRQ");
- data->active_scan_detected = true;
- data->trigger_time = k_uptime_get();
- gskbt_enable_interrupt(data->dev, true);
- k_work_submit(&data->gpio_trigger_work);
-}
-
-static int gskbt_init(const struct device *dev) {
- const struct gskbt_config *config = dev->config;
- struct gskbt_data *data = dev->data;
-
- if (!device_is_ready(config->key.port)) {
- LOG_ERR("GPIO port is not ready");
- return -ENODEV;
- }
-
- k_work_init_delayable(&data->update_work, gskbt_update_work);
- k_work_init(&data->gpio_trigger_work, gskbt_gpio_interrupt_work);
-
- data->dev = dev;
-
- gpio_pin_configure_dt(&config->key, GPIO_INPUT);
- gpio_init_callback(&data->key_callback, gskbt_gpio_irq_callback, BIT(config->key.pin));
- gpio_add_callback(config->key.port, &data->key_callback);
-
- while (gpio_pin_get_dt(&config->key)) {
- k_sleep(K_MSEC(100));
- }
-
- gskbt_enable_interrupt(dev, false);
-
- return 0;
-}
-
-static int gskbt_pm_action(const struct device *dev, enum pm_device_action action) {
- const struct gskbt_config *config = dev->config;
- struct gskbt_data *data = dev->data;
-
- int ret;
-
- switch (action) {
- case PM_DEVICE_ACTION_SUSPEND:
- gskbt_disable_interrupt(dev);
- ret = gpio_remove_callback(config->key.port, &data->key_callback);
- break;
- case PM_DEVICE_ACTION_RESUME:
- ret = gpio_add_callback(config->key.port, &data->key_callback);
- gskbt_enable_interrupt(dev, false);
- break;
- default:
- ret = -ENOTSUP;
- break;
- }
-
- return ret;
-}
-
-#define GSKBT_INST(n) \
- const struct gskbt_config gskbt_config_##n = { \
- .key = GPIO_DT_SPEC_GET(DT_INST_PHANDLE(n, key), gpios), \
- .debounce_config = \
- { \
- .debounce_press_ms = DT_INST_PROP(n, debounce_press_ms), \
- .debounce_release_ms = DT_INST_PROP(n, debounce_release_ms), \
- }, \
- .debounce_scan_period_ms = DT_INST_PROP(n, debounce_scan_period_ms), \
- }; \
- struct gskbt_data gskbt_data_##n = { \
- .binding = ZMK_KEYMAP_EXTRACT_BINDING(0, DT_DRV_INST(n)), \
- }; \
- PM_DEVICE_DT_INST_DEFINE(n, gskbt_pm_action); \
- DEVICE_DT_INST_DEFINE(n, gskbt_init, PM_DEVICE_DT_INST_GET(n), &gskbt_data_##n, \
- &gskbt_config_##n, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
- NULL);
-
-DT_INST_FOREACH_STATUS_OKAY(GSKBT_INST)
diff --git a/docs/docs/features/soft-off.md b/docs/docs/features/soft-off.md
index 6b6b5cf4b3..370a388076 100644
--- a/docs/docs/features/soft-off.md
+++ b/docs/docs/features/soft-off.md
@@ -37,7 +37,7 @@ The simplest way to achieve this is with a push button between a GPIO pin and gr
#### Matrix-Integrated Hardware Combo
-Another, more complicated option is to tie two of the switch outputs in the matrix together through an AND gate and connect that to the dedicated GPIO pin. This way you can use a key combination in your existing keyboard matrix to trigger soft on/off. To make this work best, the two switches used should both be driven by the same matrix input pin so that both will be active simultaneously on the AND gate inputs. The alternative is to use a combination of diodes and capacitors to ensure both pins are active/high at the same time even if scanning sets them high at different times.
+Another, more complicated option is to tie two of the switch outputs in the matrix together through an AND gate and connect that to the dedicated GPIO pin. This way you can use a key combination in your existing keyboard matrix to trigger soft on/off. To make this work best, the two switches used should both be driven by the same matrix input pin so that both will be active simultaneously on the AND gate inputs. The alternative is to use a combination of diodes and capacitors to ensure both pins are active/high at the same time even if scanning sets them high at different times. Support for this mode will be coming soon.
### Firmware Changes
@@ -92,20 +92,7 @@ Here are the properties for the behavior key node:
- The `bindings` property is a phandle to the soft off behavior defined above.
- The `key` property is a phandle to the GPIO key defined earlier.
-If you have set up your on/off to be controlled by a matrix-integrated combo, the behavior key needs use a different driver that will handle detecting the pressed state when the pin is toggled by the other matrix kscan driver:
-
-```
-/ {
- soft_off_behavior_key {
- compatible = "zmk,gpio-scanned-key-behavior-trigger";
- status = "okay";
- bindings = <&hw_soft_off>;
- key = <&wakeup_key>;
- };
-};
-```
-
-Note that the only difference from the `soft_off_behavior_key` definition for GPIO keys above is the `compatible` value of `zmk,gpio-scanned-key-behavior-trigger`.
+If you have set up your on/off to be controlled by a matrix-integrated combo, the behavior key will need to be integrated into your existing kscan setup. Full details to come when this is supported.
#### Wakeup Sources