refactor(sensors): Sensor event channel data, resolution tweaks.
* Refactor sensor events to include channel data, necessary for prop split encoders, and avoiding duplicate calls, to fetch channel data twice, etc. * More consistent behavior driver API. * Allow setting triggers per resolution at the behavior level optionally.
This commit is contained in:
parent
dcf5e75fa6
commit
2244bd3d81
12 changed files with 258 additions and 83 deletions
20
app/Kconfig
20
app/Kconfig
|
@ -194,6 +194,18 @@ rsource "src/split/Kconfig"
|
||||||
#Basic Keyboard Setup
|
#Basic Keyboard Setup
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
menu "Encoders"
|
||||||
|
|
||||||
|
config ZMK_ENCODERS_DEFAULT_TRIGGERS_PER_ROTATION
|
||||||
|
int "Default behavior triggers per rotation"
|
||||||
|
help
|
||||||
|
Unless overridden for a specific behavior in the keymap/devicetree, this value
|
||||||
|
determines how many times to trigger the bound behavior per full rotation.
|
||||||
|
For tactile encoders with detents, this usually should match the number of
|
||||||
|
detents per rotation of the encoder.
|
||||||
|
default 30
|
||||||
|
|
||||||
|
endmenu
|
||||||
menu "Display/LED Options"
|
menu "Display/LED Options"
|
||||||
|
|
||||||
rsource "src/display/Kconfig"
|
rsource "src/display/Kconfig"
|
||||||
|
@ -523,6 +535,14 @@ config ZMK_WPM
|
||||||
config SENSOR
|
config SENSOR
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
if ZMK_KEYMAP_SENSORS
|
||||||
|
|
||||||
|
config ZMK_KEYMAP_SENSORS_DEFAULT_TRIGGERS_PER_ROTATION
|
||||||
|
int "Default triggers per rotation"
|
||||||
|
default 20
|
||||||
|
|
||||||
|
endif # ZMK_KEYMAP_SENSORS
|
||||||
|
|
||||||
choice CBPRINTF_IMPLEMENTATION
|
choice CBPRINTF_IMPLEMENTATION
|
||||||
default CBPRINTF_NANO
|
default CBPRINTF_NANO
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,14 @@ compatible: "zmk,keymap-sensors"
|
||||||
properties:
|
properties:
|
||||||
sensors:
|
sensors:
|
||||||
type: phandles
|
type: phandles
|
||||||
required: true
|
required: false
|
||||||
|
triggers-per-rotation:
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
|
|
||||||
|
child-binding:
|
||||||
|
description: Per-sensor configuration settings
|
||||||
|
properties:
|
||||||
|
triggers-per-rotation:
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <zephyr/device.h>
|
#include <zephyr/device.h>
|
||||||
#include <zmk/keys.h>
|
#include <zmk/keys.h>
|
||||||
|
#include <zmk/sensors.h>
|
||||||
#include <zmk/behavior.h>
|
#include <zmk/behavior.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,9 +25,10 @@
|
||||||
|
|
||||||
typedef int (*behavior_keymap_binding_callback_t)(struct zmk_behavior_binding *binding,
|
typedef int (*behavior_keymap_binding_callback_t)(struct zmk_behavior_binding *binding,
|
||||||
struct zmk_behavior_binding_event event);
|
struct zmk_behavior_binding_event event);
|
||||||
typedef int (*behavior_sensor_keymap_binding_callback_t)(struct zmk_behavior_binding *binding,
|
typedef int (*behavior_sensor_keymap_binding_callback_t)(
|
||||||
const struct device *sensor,
|
struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event,
|
||||||
struct zmk_behavior_binding_event event);
|
const struct zmk_sensor_config *sensor_config, size_t channel_data_size,
|
||||||
|
const struct zmk_sensor_channel_data channel_data[channel_data_size]);
|
||||||
|
|
||||||
enum behavior_locality {
|
enum behavior_locality {
|
||||||
BEHAVIOR_LOCALITY_CENTRAL,
|
BEHAVIOR_LOCALITY_CENTRAL,
|
||||||
|
@ -158,14 +160,15 @@ static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_bi
|
||||||
* @retval 0 If successful.
|
* @retval 0 If successful.
|
||||||
* @retval Negative errno code if failure.
|
* @retval Negative errno code if failure.
|
||||||
*/
|
*/
|
||||||
__syscall int behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *binding,
|
__syscall int behavior_sensor_keymap_binding_triggered(
|
||||||
const struct device *sensor,
|
struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event,
|
||||||
struct zmk_behavior_binding_event event);
|
const struct zmk_sensor_config *sensor_config, size_t channel_data_size,
|
||||||
|
const struct zmk_sensor_channel_data *channel_data);
|
||||||
|
|
||||||
static inline int
|
static inline int z_impl_behavior_sensor_keymap_binding_triggered(
|
||||||
z_impl_behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *binding,
|
struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event,
|
||||||
const struct device *sensor,
|
const struct zmk_sensor_config *sensor_config, size_t channel_data_size,
|
||||||
struct zmk_behavior_binding_event event) {
|
const struct zmk_sensor_channel_data *channel_data) {
|
||||||
const struct device *dev = device_get_binding(binding->behavior_dev);
|
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||||
|
|
||||||
if (dev == NULL) {
|
if (dev == NULL) {
|
||||||
|
@ -178,7 +181,8 @@ z_impl_behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *bin
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return api->sensor_binding_triggered(binding, sensor, event);
|
return api->sensor_binding_triggered(binding, event, sensor_config, channel_data_size,
|
||||||
|
channel_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,12 +6,21 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <zephyr/kernel.h>
|
|
||||||
|
#include <zephyr/drivers/sensor.h>
|
||||||
#include <zmk/event_manager.h>
|
#include <zmk/event_manager.h>
|
||||||
#include <zephyr/device.h>
|
#include <zmk/sensors.h>
|
||||||
|
#include <device.h>
|
||||||
|
|
||||||
|
// TODO: Move to Kconfig when we need more than one channel
|
||||||
|
#define ZMK_SENSOR_EVENT_MAX_CHANNELS 1
|
||||||
|
|
||||||
struct zmk_sensor_event {
|
struct zmk_sensor_event {
|
||||||
uint8_t sensor_number;
|
uint8_t sensor_position;
|
||||||
const struct device *sensor;
|
|
||||||
|
size_t channel_data_size;
|
||||||
|
struct zmk_sensor_channel_data channel_data[ZMK_SENSOR_EVENT_MAX_CHANNELS];
|
||||||
|
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <drivers/sensor.h>
|
||||||
|
|
||||||
|
#define _SENSOR_CHILD_LEN(node) 1 +
|
||||||
#define ZMK_KEYMAP_SENSORS_NODE DT_INST(0, zmk_keymap_sensors)
|
#define ZMK_KEYMAP_SENSORS_NODE DT_INST(0, zmk_keymap_sensors)
|
||||||
#define ZMK_KEYMAP_HAS_SENSORS DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_NODE, okay)
|
#define ZMK_KEYMAP_HAS_SENSORS DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_NODE, okay)
|
||||||
#define ZMK_KEYMAP_SENSORS_BY_IDX(idx) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_SENSORS_NODE, sensors, idx)
|
#define ZMK_KEYMAP_SENSORS_BY_IDX(idx) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_SENSORS_NODE, sensors, idx)
|
||||||
|
@ -15,3 +18,14 @@
|
||||||
#else
|
#else
|
||||||
#define ZMK_KEYMAP_SENSORS_LEN 0
|
#define ZMK_KEYMAP_SENSORS_LEN 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const struct zmk_sensor_config *zmk_sensors_get_config_at_position(uint8_t sensor_position);
|
||||||
|
|
||||||
|
struct zmk_sensor_config {
|
||||||
|
uint16_t triggers_per_rotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zmk_sensor_channel_data {
|
||||||
|
enum sensor_channel channel;
|
||||||
|
struct sensor_value value;
|
||||||
|
};
|
||||||
|
|
|
@ -14,6 +14,11 @@
|
||||||
*/
|
*/
|
||||||
#define ZMK_VIRTUAL_KEY_POSITION_SENSOR(index) (ZMK_KEYMAP_LEN + (index))
|
#define ZMK_VIRTUAL_KEY_POSITION_SENSOR(index) (ZMK_KEYMAP_LEN + (index))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the sensor number from the virtual key position.
|
||||||
|
*/
|
||||||
|
#define ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(vkp) ((vkp)-ZMK_KEYMAP_LEN)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the virtual key position to use for the combo with the given index.
|
* Gets the virtual key position to use for the combo with the given index.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -33,8 +33,10 @@ static int behavior_sensor_rotate_init(const struct device *dev) { return 0; };
|
||||||
.tap_ms = DT_INST_PROP_OR(n, tap_ms, 5), \
|
.tap_ms = DT_INST_PROP_OR(n, tap_ms, 5), \
|
||||||
.override_params = false, \
|
.override_params = false, \
|
||||||
}; \
|
}; \
|
||||||
DEVICE_DT_INST_DEFINE( \
|
static struct behavior_sensor_rotate_data behavior_sensor_rotate_data_##n = {}; \
|
||||||
n, behavior_sensor_rotate_init, NULL, NULL, &behavior_sensor_rotate_config_##n, \
|
DEVICE_DT_INST_DEFINE(n, behavior_sensor_rotate_init, NULL, &behavior_sensor_rotate_data_##n, \
|
||||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_driver_api);
|
&behavior_sensor_rotate_config_##n, APPLICATION, \
|
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||||
|
&behavior_sensor_rotate_driver_api);
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(SENSOR_ROTATE_INST)
|
DT_INST_FOREACH_STATUS_OKAY(SENSOR_ROTATE_INST)
|
||||||
|
|
|
@ -5,48 +5,75 @@
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
#include <zmk/behavior_queue.h>
|
#include <zmk/behavior_queue.h>
|
||||||
|
#include <zmk/virtual_key_position.h>
|
||||||
|
|
||||||
#include "behavior_sensor_rotate_common.h"
|
#include "behavior_sensor_rotate_common.h"
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding,
|
int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding,
|
||||||
const struct device *sensor,
|
struct zmk_behavior_binding_event event,
|
||||||
struct zmk_behavior_binding_event event) {
|
const struct zmk_sensor_config *sensor_config,
|
||||||
|
size_t channel_data_size,
|
||||||
|
const struct zmk_sensor_channel_data *channel_data) {
|
||||||
const struct device *dev = device_get_binding(binding->behavior_dev);
|
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||||
const struct behavior_sensor_rotate_config *cfg = dev->config;
|
const struct behavior_sensor_rotate_config *cfg = dev->config;
|
||||||
|
struct behavior_sensor_rotate_data *data = dev->data;
|
||||||
|
|
||||||
struct sensor_value value;
|
const struct sensor_value value = channel_data[0].value;
|
||||||
|
int triggers;
|
||||||
|
int sensor_position = ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(event.position);
|
||||||
|
|
||||||
const int err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value);
|
// Some funky special casing for "old encoder behavior" where ticks where reported in val2 only,
|
||||||
|
// instead of rotational degrees in val1.
|
||||||
|
// REMOVE ME: Remove after a grace period of old ec11 sensor behavior
|
||||||
|
if (value.val1 == 0) {
|
||||||
|
triggers = value.val2;
|
||||||
|
} else {
|
||||||
|
struct sensor_value remainder = data->remainder[sensor_position];
|
||||||
|
|
||||||
if (err < 0) {
|
remainder.val1 += value.val1;
|
||||||
LOG_WRN("Failed to get sensor rotation value: %d", err);
|
remainder.val2 += value.val2;
|
||||||
return err;
|
|
||||||
|
if (remainder.val2 >= 1000000 || remainder.val2 <= 1000000) {
|
||||||
|
remainder.val1 += remainder.val2 / 1000000;
|
||||||
|
remainder.val2 %= 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
int trigger_degrees = 360 / sensor_config->triggers_per_rotation;
|
||||||
|
triggers = remainder.val1 / trigger_degrees;
|
||||||
|
remainder.val1 %= trigger_degrees;
|
||||||
|
|
||||||
|
data->remainder[sensor_position] = remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_DBG(
|
||||||
|
"val1: %d, val2: %d, remainder: %d/%d triggers: %d inc keycode 0x%02X dec keycode 0x%02X",
|
||||||
|
value.val1, value.val2, data->remainder[sensor_position].val1,
|
||||||
|
data->remainder[sensor_position].val2, triggers, binding->param1, binding->param2);
|
||||||
|
|
||||||
struct zmk_behavior_binding triggered_binding;
|
struct zmk_behavior_binding triggered_binding;
|
||||||
switch (value.val1) {
|
if (triggers > 0) {
|
||||||
case 1:
|
|
||||||
triggered_binding = cfg->cw_binding;
|
triggered_binding = cfg->cw_binding;
|
||||||
if (cfg->override_params) {
|
if (cfg->override_params) {
|
||||||
triggered_binding.param1 = binding->param1;
|
triggered_binding.param1 = binding->param1;
|
||||||
}
|
}
|
||||||
break;
|
} else if (triggers < 0) {
|
||||||
case -1:
|
triggers = -triggers;
|
||||||
triggered_binding = cfg->ccw_binding;
|
triggered_binding = cfg->ccw_binding;
|
||||||
if (cfg->override_params) {
|
if (cfg->override_params) {
|
||||||
triggered_binding.param1 = binding->param2;
|
triggered_binding.param1 = binding->param2;
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
default:
|
return 0;
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("Sensor binding: %s", binding->behavior_dev);
|
LOG_DBG("Sensor binding: %s", binding->behavior_dev);
|
||||||
|
|
||||||
zmk_behavior_queue_add(event.position, triggered_binding, true, cfg->tap_ms);
|
for (int i = 0; i < triggers; i++) {
|
||||||
zmk_behavior_queue_add(event.position, triggered_binding, false, 0);
|
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;
|
return ZMK_BEHAVIOR_OPAQUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
#include <zmk/behavior.h>
|
#include <zmk/behavior.h>
|
||||||
|
#include <zmk/sensors.h>
|
||||||
|
|
||||||
struct behavior_sensor_rotate_config {
|
struct behavior_sensor_rotate_config {
|
||||||
struct zmk_behavior_binding cw_binding;
|
struct zmk_behavior_binding cw_binding;
|
||||||
|
@ -8,6 +14,12 @@ struct behavior_sensor_rotate_config {
|
||||||
bool override_params;
|
bool override_params;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct behavior_sensor_rotate_data {
|
||||||
|
struct sensor_value remainder[ZMK_KEYMAP_SENSORS_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding,
|
int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding,
|
||||||
const struct device *sensor,
|
struct zmk_behavior_binding_event event,
|
||||||
struct zmk_behavior_binding_event event);
|
const struct zmk_sensor_config *sensor_config,
|
||||||
|
size_t channel_data_size,
|
||||||
|
const struct zmk_sensor_channel_data *channel_data);
|
|
@ -24,8 +24,10 @@ static int behavior_sensor_rotate_var_init(const struct device *dev) { return 0;
|
||||||
.tap_ms = DT_INST_PROP(n, tap_ms), \
|
.tap_ms = DT_INST_PROP(n, tap_ms), \
|
||||||
.override_params = true, \
|
.override_params = true, \
|
||||||
}; \
|
}; \
|
||||||
|
static struct behavior_sensor_rotate_data behavior_sensor_rotate_var_data_##n = {}; \
|
||||||
DEVICE_DT_INST_DEFINE( \
|
DEVICE_DT_INST_DEFINE( \
|
||||||
n, behavior_sensor_rotate_var_init, NULL, NULL, &behavior_sensor_rotate_var_config_##n, \
|
n, behavior_sensor_rotate_var_init, NULL, &behavior_sensor_rotate_var_data_##n, \
|
||||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_var_driver_api);
|
&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)
|
DT_INST_FOREACH_STATUS_OKAY(SENSOR_ROTATE_VAR_INST)
|
||||||
|
|
|
@ -252,27 +252,34 @@ int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pr
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sensor,
|
int zmk_keymap_sensor_triggered(
|
||||||
int64_t timestamp) {
|
uint8_t sensor_position, size_t channel_data_size,
|
||||||
|
const struct zmk_sensor_channel_data channel_data[channel_data_size], int64_t timestamp) {
|
||||||
for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) {
|
for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) {
|
||||||
if (zmk_keymap_layer_active(layer)) {
|
if (zmk_keymap_layer_active(layer)) {
|
||||||
struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_number];
|
struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_position];
|
||||||
const struct device *behavior;
|
const struct device *behavior;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
LOG_DBG("layer: %d sensor_number: %d, binding name: %s", layer, sensor_number,
|
LOG_DBG("layer: %d sensor_position: %d, binding name: %s", layer, sensor_position,
|
||||||
binding->behavior_dev);
|
binding->behavior_dev);
|
||||||
|
|
||||||
behavior = device_get_binding(binding->behavior_dev);
|
behavior = device_get_binding(binding->behavior_dev);
|
||||||
|
|
||||||
if (!behavior) {
|
if (!behavior) {
|
||||||
LOG_DBG("No behavior assigned to %d on layer %d", sensor_number, layer);
|
LOG_DBG("No behavior assigned to %d on layer %d", sensor_position, layer);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct zmk_behavior_binding_event event = {
|
struct zmk_behavior_binding_event event = {
|
||||||
.position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_number), .timestamp = timestamp};
|
.layer = layer,
|
||||||
ret = behavior_sensor_keymap_binding_triggered(binding, sensor, event);
|
.position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_position),
|
||||||
|
.timestamp = timestamp,
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = behavior_sensor_keymap_binding_triggered(
|
||||||
|
binding, event, zmk_sensors_get_config_at_position(sensor_position),
|
||||||
|
channel_data_size, channel_data);
|
||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
LOG_DBG("behavior processing to continue to next layer");
|
LOG_DBG("behavior processing to continue to next layer");
|
||||||
|
@ -301,8 +308,8 @@ int keymap_listener(const zmk_event_t *eh) {
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
const struct zmk_sensor_event *sensor_ev;
|
const struct zmk_sensor_event *sensor_ev;
|
||||||
if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) {
|
if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) {
|
||||||
return zmk_keymap_sensor_triggered(sensor_ev->sensor_number, sensor_ev->sensor,
|
return zmk_keymap_sensor_triggered(sensor_ev->sensor_position, sensor_ev->channel_data_size,
|
||||||
sensor_ev->timestamp);
|
sensor_ev->channel_data, sensor_ev->timestamp);
|
||||||
}
|
}
|
||||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||||
|
|
||||||
|
|
|
@ -18,65 +18,128 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
|
|
||||||
struct sensors_data_item {
|
struct sensors_item_cfg {
|
||||||
uint8_t sensor_number;
|
uint8_t sensor_position;
|
||||||
|
const struct zmk_sensor_config *config;
|
||||||
const struct device *dev;
|
const struct device *dev;
|
||||||
struct sensor_trigger trigger;
|
struct sensor_trigger trigger;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define _SENSOR_ITEM(node) \
|
#define _SENSOR_ITEM(idx, node) \
|
||||||
{ \
|
{ \
|
||||||
.dev = NULL, .trigger = {.type = SENSOR_TRIG_DELTA, .chan = SENSOR_CHAN_ROTATION } \
|
.dev = DEVICE_DT_GET_OR_NULL(node), \
|
||||||
|
.trigger = {.type = SENSOR_TRIG_DATA_READY, .chan = SENSOR_CHAN_ROTATION}, \
|
||||||
|
.config = &configs[idx] \
|
||||||
|
}
|
||||||
|
#define SENSOR_ITEM(idx, _i) _SENSOR_ITEM(idx, ZMK_KEYMAP_SENSORS_BY_IDX(idx))
|
||||||
|
|
||||||
|
#define PLUS_ONE(n) +1
|
||||||
|
#define ZMK_KEYMAP_SENSORS_CHILD_COUNT (0 DT_FOREACH_CHILD(ZMK_KEYMAP_SENSORS_NODE, PLUS_ONE))
|
||||||
|
#define SENSOR_CHILD_ITEM(node) \
|
||||||
|
{ \
|
||||||
|
.triggers_per_rotation = \
|
||||||
|
DT_PROP_OR(node, triggers_per_rotation, \
|
||||||
|
DT_PROP_OR(ZMK_KEYMAP_SENSORS_NODE, triggers_per_rotation, \
|
||||||
|
CONFIG_ZMK_KEYMAP_SENSORS_DEFAULT_TRIGGERS_PER_ROTATION)) \
|
||||||
|
}
|
||||||
|
#define SENSOR_CHILD_DEFAULTS(idx, arg) \
|
||||||
|
{ .triggers_per_rotation = DT_PROP_OR(ZMK_KEYMAP_SENSORS_NODE, triggers_per_rotation, 20) }
|
||||||
|
|
||||||
|
static struct zmk_sensor_config configs[] = {
|
||||||
|
#if ZMK_KEYMAP_SENSORS_CHILD_COUNT > 0
|
||||||
|
DT_FOREACH_CHILD_SEP(ZMK_KEYMAP_SENSORS_NODE, SENSOR_CHILD_ITEM, (, ))
|
||||||
|
#else
|
||||||
|
LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_CHILD_DEFAULTS, (, ), 0)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sensors_item_cfg sensors[] = {LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_ITEM, (, ), 0)};
|
||||||
|
|
||||||
|
static ATOMIC_DEFINE(pending_sensors, ZMK_KEYMAP_SENSORS_LEN);
|
||||||
|
|
||||||
|
const struct zmk_sensor_config *zmk_sensors_get_config_at_position(uint8_t sensor_position) {
|
||||||
|
if (sensor_position > ARRAY_SIZE(configs)) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SENSOR_ITEM(idx, _node) \
|
return &configs[sensor_position];
|
||||||
COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx), okay), \
|
}
|
||||||
(_SENSOR_ITEM(ZMK_KEYMAP_SENSORS_BY_IDX(idx))), ({}))
|
|
||||||
|
|
||||||
static struct sensors_data_item sensors[] = {LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_ITEM, (, ), 0)};
|
static void trigger_sensor_data_for_position(uint32_t sensor_position) {
|
||||||
|
|
||||||
static void zmk_sensors_trigger_handler(const struct device *dev,
|
|
||||||
const struct sensor_trigger *trigger) {
|
|
||||||
int err;
|
int err;
|
||||||
const struct sensors_data_item *item = CONTAINER_OF(trigger, struct sensors_data_item, trigger);
|
const struct sensors_item_cfg *item = &sensors[sensor_position];
|
||||||
|
|
||||||
LOG_DBG("sensor %d", item->sensor_number);
|
err = sensor_sample_fetch(item->dev);
|
||||||
|
|
||||||
err = sensor_sample_fetch(dev);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_WRN("Failed to fetch sample from device %d", err);
|
LOG_WRN("Failed to fetch sample from device %d", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMK_EVENT_RAISE(new_zmk_sensor_event((struct zmk_sensor_event){
|
struct sensor_value value;
|
||||||
.sensor_number = item->sensor_number, .sensor = dev, .timestamp = k_uptime_get()}));
|
err = sensor_channel_get(item->dev, item->trigger.chan, &value);
|
||||||
}
|
|
||||||
|
|
||||||
static void zmk_sensors_init_item(const char *node, uint8_t i, uint8_t abs_i) {
|
if (err) {
|
||||||
LOG_DBG("Init %s at index %d with sensor_number %d", node, i, abs_i);
|
LOG_WRN("Failed to get channel data from device %d", err);
|
||||||
|
|
||||||
sensors[i].dev = device_get_binding(node);
|
|
||||||
sensors[i].sensor_number = abs_i;
|
|
||||||
|
|
||||||
if (!sensors[i].dev) {
|
|
||||||
LOG_WRN("Failed to find device for %s", node);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor_trigger_set(sensors[i].dev, &sensors[i].trigger, zmk_sensors_trigger_handler);
|
ZMK_EVENT_RAISE(new_zmk_sensor_event(
|
||||||
|
(struct zmk_sensor_event){.sensor_position = item->sensor_position,
|
||||||
|
.channel_data = {(struct zmk_sensor_channel_data){
|
||||||
|
.value = value, .channel = item->trigger.chan}},
|
||||||
|
.timestamp = k_uptime_get()}));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _SENSOR_INIT(node) \
|
static void run_sensors_data_trigger(struct k_work *work) {
|
||||||
zmk_sensors_init_item(DT_PROP(node, label), local_index++, absolute_index++);
|
for (int i = 0; i < ARRAY_SIZE(sensors); i++) {
|
||||||
#define SENSOR_INIT(idx, _i) \
|
if (atomic_test_and_clear_bit(pending_sensors, i)) {
|
||||||
COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx), okay), \
|
trigger_sensor_data_for_position(i);
|
||||||
(_SENSOR_INIT(ZMK_KEYMAP_SENSORS_BY_IDX(idx))), (absolute_index++;))
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
K_WORK_DEFINE(sensor_data_work, run_sensors_data_trigger);
|
||||||
|
|
||||||
|
static void zmk_sensors_trigger_handler(const struct device *dev,
|
||||||
|
const struct sensor_trigger *trigger) {
|
||||||
|
const struct sensors_item_cfg *test_item =
|
||||||
|
CONTAINER_OF(trigger, struct sensors_item_cfg, trigger);
|
||||||
|
int sensor_index = test_item - sensors;
|
||||||
|
|
||||||
|
if (sensor_index < 0 || sensor_index >= ARRAY_SIZE(sensors)) {
|
||||||
|
LOG_ERR("Invalid sensor item triggered our callback");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k_is_in_isr()) {
|
||||||
|
atomic_set_bit(pending_sensors, sensor_index);
|
||||||
|
k_work_submit(&sensor_data_work);
|
||||||
|
} else {
|
||||||
|
trigger_sensor_data_for_position(sensor_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zmk_sensors_init_item(uint8_t i) {
|
||||||
|
LOG_DBG("Init sensor at index %d", i);
|
||||||
|
|
||||||
|
sensors[i].sensor_position = i;
|
||||||
|
|
||||||
|
if (!sensors[i].dev) {
|
||||||
|
LOG_DBG("No local device for %d", i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = sensor_trigger_set(sensors[i].dev, &sensors[i].trigger, zmk_sensors_trigger_handler);
|
||||||
|
if (err) {
|
||||||
|
LOG_WRN("Failed to set sensor trigger (%d)", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SENSOR_INIT(idx, _t) zmk_sensors_init_item(idx);
|
||||||
|
|
||||||
static int zmk_sensors_init(const struct device *_arg) {
|
static int zmk_sensors_init(const struct device *_arg) {
|
||||||
int local_index = 0;
|
|
||||||
int absolute_index = 0;
|
|
||||||
|
|
||||||
LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_INIT, (), 0)
|
LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_INIT, (), 0)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue