diff options
author | Nick Conway <[email protected]> | 2022-05-23 16:33:08 -0400 |
---|---|---|
committer | Pete Johanson <[email protected]> | 2023-04-21 21:13:31 -0700 |
commit | 3db163aa2cf7db2bd710ba93b57f3eb804b086c7 (patch) | |
tree | 3154e3d3cbb63235af8f37a9ccab76af0c78d78f /app/src | |
parent | 9a73650041da7008fa2df7bd8bbb02ecc8efd9b4 (diff) | |
download | zmk-3db163aa2cf7db2bd710ba93b57f3eb804b086c7.tar.gz zmk-3db163aa2cf7db2bd710ba93b57f3eb804b086c7.zip |
feat(behaviors): Add reusable sensor behaviors.
* Add new sensor behaviors that either take full bindings
add definition, or accept parameters when bound in the
keymap.
* Remove existing hard-coded key press sensor behavior
and instead leverage new generic sensor behaviors to
achieve the same functionality.
Co-authored-by: [email protected]
Diffstat (limited to 'app/src')
-rw-r--r-- | app/src/behaviors/behavior_sensor_rotate.c | 40 | ||||
-rw-r--r-- | app/src/behaviors/behavior_sensor_rotate_common.c | 52 | ||||
-rw-r--r-- | app/src/behaviors/behavior_sensor_rotate_common.h | 13 | ||||
-rw-r--r-- | app/src/behaviors/behavior_sensor_rotate_key_press.c | 69 | ||||
-rw-r--r-- | app/src/behaviors/behavior_sensor_rotate_var.c | 31 | ||||
-rw-r--r-- | app/src/keymap.c | 5 |
6 files changed, 139 insertions, 71 deletions
diff --git a/app/src/behaviors/behavior_sensor_rotate.c b/app/src/behaviors/behavior_sensor_rotate.c new file mode 100644 index 0000000000..e12278bba1 --- /dev/null +++ b/app/src/behaviors/behavior_sensor_rotate.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_behavior_sensor_rotate + +#include <zephyr/device.h> + +#include <drivers/behavior.h> + +#include "behavior_sensor_rotate_common.h" + +static const struct behavior_driver_api behavior_sensor_rotate_driver_api = { + .sensor_binding_triggered = zmk_behavior_sensor_rotate_common_trigger}; + +static int behavior_sensor_rotate_init(const struct device *dev) { return 0; }; + +#define _TRANSFORM_ENTRY(idx, node) \ + { \ + .behavior_dev = DT_PROP(DT_INST_PHANDLE_BY_IDX(node, bindings, idx), label), \ + .param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), \ + (DT_INST_PHA_BY_IDX(node, bindings, idx, param1))), \ + .param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param2), (0), \ + (DT_INST_PHA_BY_IDX(node, bindings, idx, param2))), \ + } + +#define SENSOR_ROTATE_INST(n) \ + static struct behavior_sensor_rotate_config behavior_sensor_rotate_config_##n = { \ + .cw_binding = _TRANSFORM_ENTRY(0, n), \ + .ccw_binding = _TRANSFORM_ENTRY(1, n), \ + .tap_ms = DT_INST_PROP_OR(n, tap_ms, 5), \ + .override_params = false, \ + }; \ + DEVICE_DT_INST_DEFINE( \ + n, behavior_sensor_rotate_init, NULL, NULL, &behavior_sensor_rotate_config_##n, \ + APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SENSOR_ROTATE_INST) diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c new file mode 100644 index 0000000000..bd31170eda --- /dev/null +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -0,0 +1,52 @@ + +#include <zephyr/device.h> +#include <zephyr/drivers/sensor.h> +#include <zephyr/logging/log.h> +#include <zephyr/kernel.h> + +#include <zmk/behavior_queue.h> + +#include "behavior_sensor_rotate_common.h" + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding, + const struct device *sensor, + struct zmk_behavior_binding_event event) { + const struct device *dev = device_get_binding(binding->behavior_dev); + const struct behavior_sensor_rotate_config *cfg = dev->config; + + struct sensor_value value; + + const int err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value); + + if (err < 0) { + LOG_WRN("Failed to get sensor rotation value: %d", err); + return err; + } + + struct zmk_behavior_binding triggered_binding; + switch (value.val1) { + case 1: + triggered_binding = cfg->cw_binding; + if (cfg->override_params) { + triggered_binding.param1 = binding->param1; + } + break; + case -1: + triggered_binding = cfg->ccw_binding; + if (cfg->override_params) { + triggered_binding.param1 = binding->param2; + } + break; + default: + return -ENOTSUP; + } + + LOG_DBG("Sensor binding: %s", binding->behavior_dev); + + zmk_behavior_queue_add(event.position, triggered_binding, true, cfg->tap_ms); + zmk_behavior_queue_add(event.position, triggered_binding, false, 0); + + return ZMK_BEHAVIOR_OPAQUE; +} diff --git a/app/src/behaviors/behavior_sensor_rotate_common.h b/app/src/behaviors/behavior_sensor_rotate_common.h new file mode 100644 index 0000000000..2d58218d8a --- /dev/null +++ b/app/src/behaviors/behavior_sensor_rotate_common.h @@ -0,0 +1,13 @@ + +#include <zmk/behavior.h> + +struct behavior_sensor_rotate_config { + struct zmk_behavior_binding cw_binding; + struct zmk_behavior_binding ccw_binding; + int tap_ms; + bool override_params; +}; + +int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding, + const struct device *sensor, + struct zmk_behavior_binding_event event);
\ No newline at end of file diff --git a/app/src/behaviors/behavior_sensor_rotate_key_press.c b/app/src/behaviors/behavior_sensor_rotate_key_press.c deleted file mode 100644 index 72e33ea46b..0000000000 --- a/app/src/behaviors/behavior_sensor_rotate_key_press.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2020 The ZMK Contributors - * - * SPDX-License-Identifier: MIT - */ - -#define DT_DRV_COMPAT zmk_behavior_sensor_rotate_key_press - -#include <zephyr/device.h> -#include <zephyr/drivers/sensor.h> -#include <zephyr/logging/log.h> - -#include <drivers/behavior.h> -#include <zmk/event_manager.h> -#include <zmk/events/keycode_state_changed.h> - -LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); - -#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) - -static int behavior_sensor_rotate_key_press_init(const struct device *dev) { return 0; }; - -static int on_sensor_binding_triggered(struct zmk_behavior_binding *binding, - const struct device *sensor, uint32_t virtual_key_position, - int64_t timestamp) { - struct sensor_value value; - int err; - uint32_t keycode; - LOG_DBG("inc keycode 0x%02X dec keycode 0x%02X", binding->param1, binding->param2); - - err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value); - - if (err) { - LOG_WRN("Failed to ge sensor rotation value: %d", err); - return err; - } - - switch (value.val1) { - case 1: - keycode = binding->param1; - break; - case -1: - keycode = binding->param2; - break; - default: - return -ENOTSUP; - } - - LOG_DBG("SEND %d", keycode); - - ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, true, timestamp)); - - // TODO: Better way to do this? - k_msleep(5); - - return ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, false, timestamp)); -} - -static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = { - .sensor_binding_triggered = on_sensor_binding_triggered}; - -#define KP_INST(n) \ - DEVICE_DT_INST_DEFINE(n, behavior_sensor_rotate_key_press_init, NULL, NULL, NULL, APPLICATION, \ - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ - &behavior_sensor_rotate_key_press_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(KP_INST) - -#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ diff --git a/app/src/behaviors/behavior_sensor_rotate_var.c b/app/src/behaviors/behavior_sensor_rotate_var.c new file mode 100644 index 0000000000..a82267a55e --- /dev/null +++ b/app/src/behaviors/behavior_sensor_rotate_var.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_behavior_sensor_rotate_var + +#include <zephyr/device.h> + +#include <drivers/behavior.h> + +#include "behavior_sensor_rotate_common.h" + +static const struct behavior_driver_api behavior_sensor_rotate_var_driver_api = { + .sensor_binding_triggered = zmk_behavior_sensor_rotate_common_trigger}; + +static int behavior_sensor_rotate_var_init(const struct device *dev) { return 0; }; + +#define SENSOR_ROTATE_VAR_INST(n) \ + static struct behavior_sensor_rotate_config behavior_sensor_rotate_var_config_##n = { \ + .cw_binding = {.behavior_dev = DT_PROP(DT_INST_PHANDLE_BY_IDX(n, bindings, 0), label)}, \ + .ccw_binding = {.behavior_dev = DT_PROP(DT_INST_PHANDLE_BY_IDX(n, bindings, 1), label)}, \ + .tap_ms = DT_INST_PROP(n, tap_ms), \ + .override_params = true, \ + }; \ + DEVICE_DT_INST_DEFINE( \ + n, behavior_sensor_rotate_var_init, NULL, NULL, &behavior_sensor_rotate_var_config_##n, \ + APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_var_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SENSOR_ROTATE_VAR_INST) diff --git a/app/src/keymap.c b/app/src/keymap.c index 1f55ad03d3..909fd20de8 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -270,8 +270,9 @@ int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sens continue; } - const uint32_t position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_number); - ret = behavior_sensor_keymap_binding_triggered(binding, sensor, position, timestamp); + struct zmk_behavior_binding_event event = { + .position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_number), .timestamp = timestamp}; + ret = behavior_sensor_keymap_binding_triggered(binding, sensor, event); if (ret > 0) { LOG_DBG("behavior processing to continue to next layer"); |