Merge branch 'splitkb-aurora-lily58-with-double-encoders-infused-kim' of https://github.com/narze/zmk into splitkb-aurora-lily58-with-double-encoders-infused-kim

This commit is contained in:
Nikola Ravic 2023-02-28 00:28:05 +01:00
commit f9506033f0
13 changed files with 233 additions and 39 deletions

2
Makefile Normal file
View file

@ -0,0 +1,2 @@
build: build.sh
bash ./build.sh

View file

@ -11,3 +11,7 @@ Check out the website to learn more: https://zmk.dev/
You can also come join our [ZMK Discord Server](https://zmk.dev/community/discord/invite)
To review features, check out the [feature overview](https://zmk.dev/docs/). ZMK is under active development, and new features are listed with the [enhancement label](https://github.com/zmkfirmware/zmk/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) in GitHub. Please feel free to add 👍 to the issue description of any requests to upvote the feature.
## My build command
For Aurora Lily58 in https://github.com/narze/zmk-config, run `make` in Devcontainer

View file

@ -6,6 +6,7 @@
#pragma once
#include <drivers/sensor.h>
#include <zephyr/types.h>
#include <stddef.h>
#include <sys/util.h>
@ -25,7 +26,7 @@
typedef int (*behavior_keymap_binding_callback_t)(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event);
typedef int (*behavior_sensor_keymap_binding_callback_t)(struct zmk_behavior_binding *binding,
const struct device *sensor,
const struct sensor_value value,
int64_t timestamp);
enum behavior_locality {
@ -159,12 +160,11 @@ static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_bi
* @retval Negative errno code if failure.
*/
__syscall int behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *binding,
const struct device *sensor,
const struct sensor_value value,
int64_t timestamp);
static inline int
z_impl_behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *binding,
const struct device *sensor, int64_t timestamp) {
static inline int z_impl_behavior_sensor_keymap_binding_triggered(
struct zmk_behavior_binding *binding, const struct sensor_value value, int64_t timestamp) {
const struct device *dev = device_get_binding(binding->behavior_dev);
if (dev == NULL) {
@ -177,7 +177,7 @@ z_impl_behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *bin
return -ENOTSUP;
}
return api->sensor_binding_triggered(binding, sensor, timestamp);
return api->sensor_binding_triggered(binding, value, timestamp);
}
/**

View file

@ -6,12 +6,13 @@
#pragma once
#include <drivers/sensor.h>
#include <zephyr.h>
#include <zmk/event_manager.h>
#include <device.h>
struct zmk_sensor_event {
uint8_t sensor_number;
const struct device *sensor;
struct sensor_value value;
int64_t timestamp;
};

View file

@ -6,6 +6,8 @@
#pragma once
#include <drivers/sensor.h>
#define ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN 9
struct zmk_split_run_behavior_data {
@ -21,4 +23,5 @@ struct zmk_split_run_behavior_payload {
} __packed;
int zmk_split_bt_position_pressed(uint8_t position);
int zmk_split_bt_position_released(uint8_t position);
int zmk_split_bt_position_released(uint8_t position);
int zmk_split_bt_sensor_triggered(uint8_t sensor_number, struct sensor_value value);

View file

@ -16,3 +16,4 @@
#define ZMK_SPLIT_BT_SERVICE_UUID ZMK_BT_SPLIT_UUID(0x00000000)
#define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001)
#define ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID ZMK_BT_SPLIT_UUID(0x00000002)
#define ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000002)

View file

@ -21,19 +21,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
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, int64_t timestamp) {
struct sensor_value value;
int err;
const struct sensor_value value, int64_t timestamp) {
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;

View file

@ -251,7 +251,7 @@ int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pr
}
#if ZMK_KEYMAP_HAS_SENSORS
int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sensor,
int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct sensor_value value,
int64_t timestamp) {
for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) {
if (zmk_keymap_layer_active(layer) && zmk_sensor_keymap[layer] != NULL) {
@ -269,7 +269,7 @@ int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sens
continue;
}
ret = behavior_sensor_keymap_binding_triggered(binding, sensor, timestamp);
ret = behavior_sensor_keymap_binding_triggered(binding, value, timestamp);
if (ret > 0) {
LOG_DBG("behavior processing to continue to next layer");
@ -298,7 +298,7 @@ int keymap_listener(const zmk_event_t *eh) {
#if ZMK_KEYMAP_HAS_SENSORS
const struct zmk_sensor_event *sensor_ev;
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_number, sensor_ev->value,
sensor_ev->timestamp);
}
#endif /* ZMK_KEYMAP_HAS_SENSORS */

View file

@ -44,8 +44,15 @@ static void zmk_sensors_trigger_handler(const struct device *dev, struct sensor_
return;
}
struct sensor_value value;
err = sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &value);
if (err) {
LOG_WRN("Failed to get sensor rotation value: %d", err);
return;
}
ZMK_EVENT_RAISE(new_zmk_sensor_event((struct zmk_sensor_event){
.sensor_number = item->sensor_number, .sensor = dev, .timestamp = k_uptime_get()}));
.sensor_number = item->sensor_number, .value = value, .timestamp = k_uptime_get()}));
}
static void zmk_sensors_init_item(const char *node, uint8_t i, uint8_t abs_i) {

View file

@ -20,10 +20,12 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/stdlib.h>
#include <zmk/ble.h>
#include <zmk/behavior.h>
#include <zmk/sensors.h>
#include <zmk/split/bluetooth/uuid.h>
#include <zmk/split/bluetooth/service.h>
#include <zmk/event_manager.h>
#include <zmk/events/position_state_changed.h>
#include <zmk/events/sensor_event.h>
#include <init.h>
static int start_scan(void);
@ -162,6 +164,50 @@ int confirm_peripheral_slot_conn(struct bt_conn *conn) {
return 0;
}
#if ZMK_KEYMAP_HAS_SENSORS
K_MSGQ_DEFINE(peripheral_sensor_event_msgq, sizeof(struct zmk_sensor_event),
CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4);
void peripheral_sensor_event_work_callback(struct k_work *work) {
struct zmk_sensor_event ev;
while (k_msgq_get(&peripheral_sensor_event_msgq, &ev, K_NO_WAIT) == 0) {
LOG_DBG("Trigger sensor change for %d", ev.sensor_number);
ZMK_EVENT_RAISE(new_zmk_sensor_event(ev));
}
}
K_WORK_DEFINE(peripheral_sensor_event_work, peripheral_sensor_event_work_callback);
struct sensor_event {
uint8_t sensor_number;
struct sensor_value value;
};
static uint8_t split_central_sensor_notify_func(struct bt_conn *conn,
struct bt_gatt_subscribe_params *params,
const void *data, uint16_t length) {
const struct sensor_event *sensor_event = data;
if (!data) {
LOG_DBG("[UNSUBSCRIBED]");
params->value_handle = 0U;
return BT_GATT_ITER_STOP;
}
LOG_DBG("[SENSOR NOTIFICATION] data %p length %u", data, length);
struct zmk_sensor_event ev = {
.sensor_number = sensor_event->sensor_number,
.value = {.val1 = (sensor_event->value).val1, .val2 = (sensor_event->value).val2},
.timestamp = k_uptime_get()};
k_msgq_put(&peripheral_sensor_event_msgq, &ev, K_NO_WAIT);
k_work_submit(&peripheral_sensor_event_work);
return BT_GATT_ITER_CONTINUE;
}
#endif /* ZMK_KEYMAP_HAS_SENSORS */
static uint8_t split_central_notify_func(struct bt_conn *conn,
struct bt_gatt_subscribe_params *params, const void *data,
uint16_t length) {
@ -206,14 +252,8 @@ static uint8_t split_central_notify_func(struct bt_conn *conn,
return BT_GATT_ITER_CONTINUE;
}
static void split_central_subscribe(struct bt_conn *conn) {
struct peripheral_slot *slot = peripheral_slot_for_conn(conn);
if (slot == NULL) {
LOG_ERR("No peripheral state found for connection");
return;
}
int err = bt_gatt_subscribe(conn, &slot->subscribe_params);
static void split_central_subscribe(struct bt_conn *conn, struct bt_gatt_subscribe_params *params) {
int err = bt_gatt_subscribe(conn, params);
switch (err) {
case -EALREADY:
LOG_DBG("[ALREADY SUBSCRIBED]");
@ -227,6 +267,39 @@ static void split_central_subscribe(struct bt_conn *conn) {
}
}
#if ZMK_KEYMAP_HAS_SENSORS
static struct bt_uuid_128 sensor_uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID);
static struct bt_gatt_discover_params sensor_discover_params;
static struct bt_gatt_subscribe_params sensor_subscribe_params;
static uint8_t split_central_sensor_desc_discovery_func(struct bt_conn *conn,
const struct bt_gatt_attr *attr,
struct bt_gatt_discover_params *params) {
int err;
if (!bt_uuid_cmp(sensor_discover_params.uuid,
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID))) {
memcpy(&sensor_uuid, BT_UUID_GATT_CCC, sizeof(sensor_uuid));
sensor_discover_params.uuid = &sensor_uuid.uuid;
sensor_discover_params.start_handle = attr->handle;
sensor_discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
sensor_subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
err = bt_gatt_discover(conn, &sensor_discover_params);
if (err) {
LOG_ERR("Discover failed (err %d)", err);
}
} else {
sensor_subscribe_params.notify = split_central_sensor_notify_func;
sensor_subscribe_params.value = BT_GATT_CCC_NOTIFY;
sensor_subscribe_params.ccc_handle = attr->handle;
split_central_subscribe(conn, &sensor_subscribe_params);
}
return BT_GATT_ITER_STOP;
}
#endif /* ZMK_KEYMAP_HAS_SENSORS */
static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
const struct bt_gatt_attr *attr,
struct bt_gatt_discover_params *params) {
@ -260,7 +333,7 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
slot->subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
slot->subscribe_params.notify = split_central_notify_func;
slot->subscribe_params.value = BT_GATT_CCC_NOTIFY;
split_central_subscribe(conn);
split_central_subscribe(conn, &slot->subscribe_params);
} else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID))) {
LOG_DBG("Found run behavior handle");
@ -304,6 +377,22 @@ static uint8_t split_central_service_discovery_func(struct bt_conn *conn,
if (err) {
LOG_ERR("Failed to start discovering split service characteristics (err %d)", err);
}
#if ZMK_KEYMAP_HAS_SENSORS
memcpy(&sensor_uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID),
sizeof(sensor_uuid));
sensor_discover_params.uuid = &sensor_uuid.uuid;
sensor_discover_params.start_handle = attr->handle;
sensor_discover_params.end_handle = 0xffff;
sensor_discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
sensor_discover_params.func = split_central_sensor_desc_discovery_func;
err = bt_gatt_discover(conn, &sensor_discover_params);
if (err) {
LOG_ERR("Discover failed (err %d)", err);
}
#endif /* ZMK_KEYMAP_HAS_SENSORS */
return BT_GATT_ITER_STOP;
}

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: MIT
*/
#include <drivers/sensor.h>
#include <zephyr/types.h>
#include <sys/util.h>
#include <init.h>
@ -20,6 +21,23 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/matrix.h>
#include <zmk/split/bluetooth/uuid.h>
#include <zmk/split/bluetooth/service.h>
#include <zmk/sensors.h>
#if ZMK_KEYMAP_HAS_SENSORS
struct sensor_event {
uint8_t sensor_number;
struct sensor_value value;
} sensor_event;
static ssize_t split_svc_sensor_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
void *buf, uint16_t len, uint16_t offset) {
return bt_gatt_attr_read(conn, attrs, buf, len, offset, &sensor_event, sizeof(sensor_event));
}
static void split_svc_sensor_state_ccc(const struct bt_gatt_attr *attr, uint16_t value) {
LOG_DBG("value %d", value);
}
#endif /* ZMK_KEYMAP_HAS_SENSORS */
#define POS_STATE_LEN 16
@ -98,7 +116,14 @@ BT_GATT_SERVICE_DEFINE(
BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL,
split_svc_run_behavior, &behavior_run_payload),
BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL,
&num_of_positions), );
&num_of_positions),
#if ZMK_KEYMAP_HAS_SENSORS
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID),
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT,
split_svc_sensor_state, NULL, &sensor_event),
BT_GATT_CCC(split_svc_sensor_state_ccc, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
#endif /* ZMK_KEYMAP_HAS_SENSORS */
);
K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE);
@ -151,6 +176,51 @@ int zmk_split_bt_position_released(uint8_t position) {
return send_position_state();
}
#if ZMK_KEYMAP_HAS_SENSORS
K_MSGQ_DEFINE(sensor_state_msgq, sizeof(sensor_event),
CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE, 4);
void send_sensor_state_callback(struct k_work *work) {
struct sensor_event ev;
while (k_msgq_get(&sensor_state_msgq, &ev, K_NO_WAIT) == 0) {
int err = bt_gatt_notify(NULL, &split_svc.attrs[5], &ev, sizeof(ev));
if (err) {
LOG_DBG("Error notifying %d", err);
}
}
};
K_WORK_DEFINE(service_sensor_notify_work, send_sensor_state_callback);
int send_sensor_state() {
int err = k_msgq_put(&sensor_state_msgq, &sensor_event, K_MSEC(100));
if (err) {
// retry...
switch (err) {
case -EAGAIN: {
LOG_WRN("Sensor state message queue full, popping first message and queueing again");
struct sensor_event discarded_state;
k_msgq_get(&sensor_state_msgq, &discarded_state, K_NO_WAIT);
return send_sensor_state();
}
default:
LOG_WRN("Failed to queue sensor state to send (%d)", err);
return err;
}
}
k_work_submit_to_queue(&service_work_q, &service_sensor_notify_work);
return 0;
}
int zmk_split_bt_sensor_triggered(uint8_t sensor_number, struct sensor_value value) {
sensor_event.sensor_number = sensor_number;
sensor_event.value = value;
return send_sensor_state();
}
#endif /* ZMK_KEYMAP_HAS_SENSORS */
int service_init(const struct device *_arg) {
static const struct k_work_queue_config queue_config = {
.name = "Split Peripheral Notification Queue"};

View file

@ -5,6 +5,7 @@
*/
#include <device.h>
#include <drivers/sensor.h>
#include <logging/log.h>
#include <zmk/split/bluetooth/service.h>
@ -13,21 +14,38 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/event_manager.h>
#include <zmk/events/position_state_changed.h>
#include <zmk/events/sensor_event.h>
#include <zmk/hid.h>
#include <zmk/sensors.h>
#include <zmk/endpoints.h>
int split_listener(const zmk_event_t *eh) {
LOG_DBG("");
const struct zmk_position_state_changed *ev = as_zmk_position_state_changed(eh);
if (ev != NULL) {
if (ev->state) {
return zmk_split_bt_position_pressed(ev->position);
} else {
return zmk_split_bt_position_released(ev->position);
const struct zmk_position_state_changed *pos_ev;
if ((pos_ev = as_zmk_position_state_changed(eh)) != NULL) {
if (pos_ev != NULL) {
if (pos_ev->state) {
return zmk_split_bt_position_pressed(pos_ev->position);
} else {
return zmk_split_bt_position_released(pos_ev->position);
}
}
}
#if ZMK_KEYMAP_HAS_SENSORS
const struct zmk_sensor_event *sensor_ev;
if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) {
if (sensor_ev != NULL) {
return zmk_split_bt_sensor_triggered(sensor_ev->sensor_number, sensor_ev->value);
}
}
#endif /* ZMK_KEYMAP_HAS_SENSORS */
return ZMK_EV_EVENT_BUBBLE;
}
ZMK_LISTENER(split_listener, split_listener);
ZMK_SUBSCRIPTION(split_listener, zmk_position_state_changed);
ZMK_SUBSCRIPTION(split_listener, zmk_position_state_changed);
#if ZMK_KEYMAP_HAS_SENSORS
ZMK_SUBSCRIPTION(split_listener, zmk_sensor_event);
#endif /* ZMK_KEYMAP_HAS_SENSORS */

8
build.sh Executable file
View file

@ -0,0 +1,8 @@
#!/bin/bash
SIDES=(left right)
for side in ${SIDES[@]}
do
west build -b nice_nano_v2 -s /workspaces/zmk/app -d /workspaces/zmk-config/build/aurora_lily58_$side.build -- -DSHIELD="splitkb_aurora_lily58_$side nice_view_adapter nice_view" -DZMK_CONFIG="/workspaces/zmk-config/config"
cp /workspaces/zmk-config/build/aurora_lily58_$side.build/zephyr/zmk.uf2 /workspaces/zmk-config/build/aurora_lily58_$side.uf2
done