This commit is contained in:
Jack Hartstein 2021-04-03 09:04:03 -07:00
commit 1c9bfaf104
112 changed files with 2177 additions and 405 deletions

View file

@ -1,12 +1,12 @@
fail_fast: false
repos:
- repo: https://github.com/pocc/pre-commit-hooks
rev: master
rev: v1.1.1
hooks:
- id: clang-format
args:
- -i
- repo: https://github.com/prettier/prettier
rev: master
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.2.1
hooks:
- id: prettier

View file

@ -419,6 +419,9 @@ config ZMK_WPM
bool "Calculate WPM"
default n
config SENSOR
default y
module = ZMK
module-str = zmk
source "subsys/logging/Kconfig.template.log_config"

View file

@ -42,7 +42,7 @@
, <7 0 &gpio0 24 0> /* D6/A7 D7*/
, <8 0 &gpio0 10 0> /* D8/A8 B4*/
, <9 0 &gpio1 6 0> /* D9/A9 B5*/
, <10 0 &gpio1 13 0> /* D10/A10 B6*/
, <10 0 &gpio1 11 0> /* D10/A10 B6*/
;
};
};

View file

@ -9,7 +9,6 @@ config ZMK_KEYBOARD_NAME
config ZMK_USB
default y
endif
if ZMK_DISPLAY
@ -46,3 +45,5 @@ choice LVGL_COLOR_DEPTH
endchoice
endif # LVGL
endif

View file

@ -1 +0,0 @@
CONFIG_SENSOR=y

View file

@ -18,7 +18,7 @@
compatible = "zmk,behavior-hold-tap";
label = "homerow mods";
#binding-cells = <2>;
tapping_term_ms = <225>;
tapping-term-ms = <225>;
flavor = "tap-preferred";
bindings = <&kp>, <&kp>;
};

View file

@ -14,7 +14,7 @@
compatible = "zmk,behavior-hold-tap";
label = "Hold Tap";
#binding-cells = <2>;
tapping_term_ms = <200>;
tapping-term-ms = <200>;
flavor = "tap-preferred";
bindings = <&kp>, <&kp>;
};

View file

@ -6,7 +6,6 @@ if SHIELD_TIDBIT
config ZMK_KEYBOARD_NAME
default "tidbit"
endif
if ZMK_DISPLAY
@ -43,3 +42,5 @@ choice LVGL_COLOR_DEPTH
endchoice
endif # LVGL
endif

View file

@ -1 +0,0 @@
CONFIG_SENSOR=y

View file

@ -2,7 +2,7 @@
# SPDX-License-Identifier: MIT
config ZMK_KSCAN_GPIO_DRIVER
bool "Enable GPIO kscan driver to simulate key presses"
bool "Enable GPIO kscan driver to detect key presses"
default y
select GPIO

View file

@ -83,7 +83,7 @@ static int kscan_gpio_config_interrupts(const struct device *dev, gpio_flags_t f
int err = gpio_pin_interrupt_configure(dev, cfg->pin, flags);
if (err) {
LOG_ERR("Unable to enable matrix GPIO interrupt");
LOG_ERR("Unable to enable direct GPIO interrupt");
return err;
}
}

View file

@ -93,7 +93,7 @@ static int bvd_sample_fetch(const struct device *dev, enum sensor_channel chan)
&val);
uint16_t millivolts = val * (uint64_t)drv_cfg->full_ohm / drv_cfg->output_ohm;
LOG_DBG("ADC raw %d ~ %d mV => %d mV\n", drv_data->adc_raw, val, millivolts);
LOG_DBG("ADC raw %d ~ %d mV => %d mV", drv_data->adc_raw, val, millivolts);
uint8_t percent = lithium_ion_mv_to_pct(millivolts);
LOG_DBG("Percent: %d", percent);

View file

@ -11,7 +11,7 @@
label = "LAYER_TAP";
#binding-cells = <2>;
flavor = "tap-preferred";
tapping_term_ms = <200>;
tapping-term-ms = <200>;
bindings = <&mo>, <&kp>;
};
};

View file

@ -11,7 +11,7 @@
label = "MOD_TAP";
#binding-cells = <2>;
flavor = "hold-preferred";
tapping_term_ms = <200>;
tapping-term-ms = <200>;
bindings = <&kp>, <&kp>;
};
};

View file

@ -11,11 +11,15 @@ properties:
bindings:
type: phandles
required: true
tapping_term_ms:
tapping-term-ms:
type: int
quick_tap_ms:
tapping_term_ms: # deprecated
type: int
quick-tap-ms:
type: int
default: -1
quick_tap_ms: # deprecated
type: int
flavor:
type: string
required: false
@ -24,3 +28,5 @@ properties:
- "hold-preferred"
- "balanced"
- "tap-preferred"
retro-tap:
type: boolean

View file

@ -15,3 +15,7 @@ properties:
label:
type: string
required: true
init-delay-ms:
type: int
description: Number of milliseconds to delay after initializing driver
required: false

View file

@ -27,6 +27,7 @@ typedef int (*behavior_sensor_keymap_binding_callback_t)(struct zmk_behavior_bin
int64_t timestamp);
__subsystem struct behavior_driver_api {
behavior_keymap_binding_callback_t binding_convert_central_state_dependent_params;
behavior_keymap_binding_callback_t binding_pressed;
behavior_keymap_binding_callback_t binding_released;
behavior_sensor_keymap_binding_callback_t sensor_binding_triggered;
@ -35,6 +36,30 @@ __subsystem struct behavior_driver_api {
* @endcond
*/
/**
* @brief Handle the keymap binding which needs to be converted from relative "toggle" to absolute
* "turn on"
* @param binding Pointer to the details so of the binding
* @param event The event that triggered use of the binding
*
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
__syscall int behavior_keymap_binding_convert_central_state_dependent_params(
struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event);
static inline int z_impl_behavior_keymap_binding_convert_central_state_dependent_params(
struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) {
const struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api;
if (api->binding_convert_central_state_dependent_params == NULL) {
return 0;
}
return api->binding_convert_central_state_dependent_params(binding, event);
}
/**
* @brief Handle the keymap binding being pressed
* @param dev Pointer to the device structure for the driver instance.

View file

@ -5,19 +5,23 @@
*/
#define RGB_TOG_CMD 0
#define RGB_HUI_CMD 1
#define RGB_HUD_CMD 2
#define RGB_SAI_CMD 3
#define RGB_SAD_CMD 4
#define RGB_BRI_CMD 5
#define RGB_BRD_CMD 6
#define RGB_SPI_CMD 7
#define RGB_SPD_CMD 8
#define RGB_EFF_CMD 9
#define RGB_EFR_CMD 10
#define RGB_COLOR_HSB_CMD 11
#define RGB_ON_CMD 1
#define RGB_OFF_CMD 2
#define RGB_HUI_CMD 3
#define RGB_HUD_CMD 4
#define RGB_SAI_CMD 5
#define RGB_SAD_CMD 6
#define RGB_BRI_CMD 7
#define RGB_BRD_CMD 8
#define RGB_SPI_CMD 9
#define RGB_SPD_CMD 10
#define RGB_EFF_CMD 11
#define RGB_EFR_CMD 12
#define RGB_COLOR_HSB_CMD 13
#define RGB_TOG RGB_TOG_CMD 0
#define RGB_ON RGB_ON_CMD 0
#define RGB_OFF RGB_OFF_CMD 0
#define RGB_HUI RGB_HUI_CMD 0
#define RGB_HUD RGB_HUD_CMD 0
#define RGB_SAI RGB_SAI_CMD 0
@ -28,5 +32,6 @@
#define RGB_SPD RGB_SPD_CMD 0
#define RGB_EFF RGB_EFF_CMD 0
#define RGB_EFR RGB_EFR_CMD 0
#define RGB_COLOR_HSB(h, s, v) RGB_COLOR_HSB_CMD(((h) << 16) + ((s) << 8) + (v))
#define RGB_COLOR_HSB_VAL(h, s, v) (((h) << 16) + ((s) << 8) + (v))
#define RGB_COLOR_HSB(h, s, v) RGB_COLOR_HSB_CMD##(RGB_COLOR_HSB_VAL(h, s, v))
#define RGB_COLOR_HSV RGB_COLOR_HSB

View file

@ -0,0 +1,9 @@
/*
* Copyright (c) 2021 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
uint8_t zmk_battery_state_of_charge();

View file

@ -6,10 +6,22 @@
#pragma once
struct zmk_led_hsb {
uint16_t h;
uint8_t s;
uint8_t b;
};
int zmk_rgb_underglow_toggle();
int zmk_rgb_underglow_get_state(bool *state);
int zmk_rgb_underglow_on();
int zmk_rgb_underglow_off();
int zmk_rgb_underglow_cycle_effect(int direction);
struct zmk_led_hsb zmk_rgb_underglow_calc_hue(int direction);
struct zmk_led_hsb zmk_rgb_underglow_calc_sat(int direction);
struct zmk_led_hsb zmk_rgb_underglow_calc_brt(int direction);
int zmk_rgb_underglow_change_hue(int direction);
int zmk_rgb_underglow_change_sat(int direction);
int zmk_rgb_underglow_change_brt(int direction);
int zmk_rgb_underglow_change_spd(int direction);
int zmk_rgb_underglow_set_hsb(uint16_t hue, uint8_t saturation, uint8_t brightness);
int zmk_rgb_underglow_set_hsb(struct zmk_led_hsb color);

View file

@ -15,10 +15,15 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/event_manager.h>
#include <zmk/battery.h>
#include <zmk/events/battery_state_changed.h>
const struct device *battery;
static uint8_t last_state_of_charge = 0;
uint8_t zmk_battery_state_of_charge() { return last_state_of_charge; }
static int zmk_battery_update(const struct device *battery) {
struct sensor_value state_of_charge;
@ -36,17 +41,23 @@ static int zmk_battery_update(const struct device *battery) {
return rc;
}
LOG_DBG("Setting BAS GATT battery level to %d.", state_of_charge.val1);
if (last_state_of_charge != state_of_charge.val1) {
last_state_of_charge = state_of_charge.val1;
rc = bt_bas_set_battery_level(state_of_charge.val1);
LOG_DBG("Setting BAS GATT battery level to %d.", last_state_of_charge);
if (rc != 0) {
LOG_WRN("Failed to set BAS GATT battery level (err %d)", rc);
return rc;
rc = bt_bas_set_battery_level(last_state_of_charge);
if (rc != 0) {
LOG_WRN("Failed to set BAS GATT battery level (err %d)", rc);
return rc;
}
rc = ZMK_EVENT_RAISE(new_zmk_battery_state_changed(
(struct zmk_battery_state_changed){.state_of_charge = last_state_of_charge}));
}
return ZMK_EVENT_RAISE(new_zmk_battery_state_changed(
(struct zmk_battery_state_changed){.state_of_charge = state_of_charge.val1}));
return rc;
}
static void zmk_battery_work(struct k_work *work) {

View file

@ -18,6 +18,22 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
static int
on_keymap_binding_convert_central_state_dependent_params(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
const struct device *ext_power = device_get_binding("EXT_POWER");
if (ext_power == NULL) {
LOG_ERR("Unable to retrieve ext_power device: %d", binding->param1);
return -EIO;
}
if (binding->param1 == EXT_POWER_TOGGLE_CMD) {
binding->param1 = ext_power_get(ext_power) > 0 ? EXT_POWER_OFF_CMD : EXT_POWER_ON_CMD;
}
return 0;
}
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
const struct device *ext_power = device_get_binding("EXT_POWER");
@ -51,6 +67,8 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
static int behavior_ext_power_init(const struct device *dev) { return 0; };
static const struct behavior_driver_api behavior_ext_power_driver_api = {
.binding_convert_central_state_dependent_params =
on_keymap_binding_convert_central_state_dependent_params,
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
};

View file

@ -31,9 +31,24 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define ZMK_BHV_HOLD_TAP_POSITION_NOT_USED 9999
enum flavor {
ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED = 0,
ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED = 1,
ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2,
FLAVOR_HOLD_PREFERRED,
FLAVOR_BALANCED,
FLAVOR_TAP_PREFERRED,
};
enum status {
STATUS_UNDECIDED,
STATUS_TAP,
STATUS_HOLD_INTERRUPT,
STATUS_HOLD_TIMER,
};
enum decision_moment {
HT_KEY_UP,
HT_OTHER_KEY_DOWN,
HT_OTHER_KEY_UP,
HT_TIMER_EVENT,
HT_QUICK_TAP,
};
struct behavior_hold_tap_config {
@ -42,17 +57,16 @@ struct behavior_hold_tap_config {
char *tap_behavior_dev;
int quick_tap_ms;
enum flavor flavor;
bool retro_tap;
};
// this data is specific for each hold-tap
struct active_hold_tap {
int32_t position;
// todo: move these params into the config->behaviors->tap and
uint32_t param_hold;
uint32_t param_tap;
int64_t timestamp;
bool is_decided;
bool is_hold;
enum status status;
const struct behavior_hold_tap_config *config;
struct k_delayed_work work;
bool work_is_cancelled;
@ -187,8 +201,7 @@ static struct active_hold_tap *store_hold_tap(uint32_t position, uint32_t param_
continue;
}
active_hold_taps[i].position = position;
active_hold_taps[i].is_decided = false;
active_hold_taps[i].is_hold = false;
active_hold_taps[i].status = STATUS_UNDECIDED;
active_hold_taps[i].config = config;
active_hold_taps[i].param_hold = param_hold;
active_hold_taps[i].param_tap = param_tap;
@ -200,34 +213,24 @@ static struct active_hold_tap *store_hold_tap(uint32_t position, uint32_t param_
static void clear_hold_tap(struct active_hold_tap *hold_tap) {
hold_tap->position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
hold_tap->is_decided = false;
hold_tap->is_hold = false;
hold_tap->status = STATUS_UNDECIDED;
hold_tap->work_is_cancelled = false;
}
enum decision_moment {
HT_KEY_UP = 0,
HT_OTHER_KEY_DOWN = 1,
HT_OTHER_KEY_UP = 2,
HT_TIMER_EVENT = 3,
HT_QUICK_TAP = 4,
};
static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_moment event) {
switch (event) {
case HT_KEY_UP:
hold_tap->is_hold = 0;
hold_tap->is_decided = true;
break;
hold_tap->status = STATUS_TAP;
return;
case HT_OTHER_KEY_UP:
hold_tap->status = STATUS_HOLD_INTERRUPT;
return;
case HT_TIMER_EVENT:
hold_tap->is_hold = 1;
hold_tap->is_decided = true;
break;
hold_tap->status = STATUS_HOLD_TIMER;
return;
case HT_QUICK_TAP:
hold_tap->is_hold = 0;
hold_tap->is_decided = true;
break;
hold_tap->status = STATUS_TAP;
return;
default:
return;
}
@ -236,17 +239,14 @@ static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_mome
static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) {
switch (event) {
case HT_KEY_UP:
hold_tap->is_hold = 0;
hold_tap->is_decided = true;
break;
hold_tap->status = STATUS_TAP;
return;
case HT_TIMER_EVENT:
hold_tap->is_hold = 1;
hold_tap->is_decided = true;
break;
hold_tap->status = STATUS_HOLD_TIMER;
return;
case HT_QUICK_TAP:
hold_tap->is_hold = 0;
hold_tap->is_decided = true;
break;
hold_tap->status = STATUS_TAP;
return;
default:
return;
}
@ -255,37 +255,113 @@ static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision
static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) {
switch (event) {
case HT_KEY_UP:
hold_tap->is_hold = 0;
hold_tap->is_decided = true;
break;
hold_tap->status = STATUS_TAP;
return;
case HT_OTHER_KEY_DOWN:
hold_tap->status = STATUS_HOLD_INTERRUPT;
return;
case HT_TIMER_EVENT:
hold_tap->is_hold = 1;
hold_tap->is_decided = true;
break;
hold_tap->status = STATUS_HOLD_TIMER;
return;
case HT_QUICK_TAP:
hold_tap->is_hold = 0;
hold_tap->is_decided = true;
break;
hold_tap->status = STATUS_TAP;
return;
default:
return;
}
}
static inline char *flavor_str(enum flavor flavor) {
static inline const char *flavor_str(enum flavor flavor) {
switch (flavor) {
case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
case FLAVOR_HOLD_PREFERRED:
return "hold-preferred";
case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
case FLAVOR_BALANCED:
return "balanced";
case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
case FLAVOR_TAP_PREFERRED:
return "tap-preferred";
default:
return "UNKNOWN FLAVOR";
}
return "UNKNOWN FLAVOR";
}
static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event_type) {
if (hold_tap->is_decided) {
static inline const char *status_str(enum status status) {
switch (status) {
case STATUS_UNDECIDED:
return "undecided";
case STATUS_HOLD_TIMER:
return "hold-timer";
case STATUS_HOLD_INTERRUPT:
return "hold-interrupt";
case STATUS_TAP:
return "tap";
default:
return "UNKNOWN STATUS";
}
}
static inline const char *decision_moment_str(enum decision_moment decision_moment) {
switch (decision_moment) {
case HT_KEY_UP:
return "key-up";
case HT_OTHER_KEY_DOWN:
return "other-key-down";
case HT_OTHER_KEY_UP:
return "other-key-up";
case HT_QUICK_TAP:
return "quick-tap";
case HT_TIMER_EVENT:
return "timer";
default:
return "UNKNOWN STATUS";
}
}
static int press_binding(struct active_hold_tap *hold_tap) {
if (hold_tap->config->retro_tap && hold_tap->status == STATUS_HOLD_TIMER) {
return 0;
}
struct zmk_behavior_binding_event event = {
.position = hold_tap->position,
.timestamp = hold_tap->timestamp,
};
struct zmk_behavior_binding binding = {0};
if (hold_tap->status == STATUS_HOLD_TIMER || hold_tap->status == STATUS_HOLD_INTERRUPT) {
binding.behavior_dev = hold_tap->config->hold_behavior_dev;
binding.param1 = hold_tap->param_hold;
} else {
binding.behavior_dev = hold_tap->config->tap_behavior_dev;
binding.param1 = hold_tap->param_tap;
store_last_tapped(hold_tap);
}
return behavior_keymap_binding_pressed(&binding, event);
}
static int release_binding(struct active_hold_tap *hold_tap) {
if (hold_tap->config->retro_tap && hold_tap->status == STATUS_HOLD_TIMER) {
return 0;
}
struct zmk_behavior_binding_event event = {
.position = hold_tap->position,
.timestamp = hold_tap->timestamp,
};
struct zmk_behavior_binding binding = {0};
if (hold_tap->status == STATUS_HOLD_TIMER || hold_tap->status == STATUS_HOLD_INTERRUPT) {
binding.behavior_dev = hold_tap->config->hold_behavior_dev;
binding.param1 = hold_tap->param_hold;
} else {
binding.behavior_dev = hold_tap->config->tap_behavior_dev;
binding.param1 = hold_tap->param_tap;
}
return behavior_keymap_binding_released(&binding, event);
}
static void decide_hold_tap(struct active_hold_tap *hold_tap,
enum decision_moment decision_moment) {
if (hold_tap->status != STATUS_UNDECIDED) {
return;
}
@ -295,42 +371,55 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome
}
switch (hold_tap->config->flavor) {
case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
decide_hold_preferred(hold_tap, event_type);
case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
decide_balanced(hold_tap, event_type);
case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
decide_tap_preferred(hold_tap, event_type);
case FLAVOR_HOLD_PREFERRED:
decide_hold_preferred(hold_tap, decision_moment);
case FLAVOR_BALANCED:
decide_balanced(hold_tap, decision_moment);
case FLAVOR_TAP_PREFERRED:
decide_tap_preferred(hold_tap, decision_moment);
}
if (!hold_tap->is_decided) {
if (hold_tap->status == STATUS_UNDECIDED) {
return;
}
LOG_DBG("%d decided %s (%s event %d)", hold_tap->position, hold_tap->is_hold ? "hold" : "tap",
flavor_str(hold_tap->config->flavor), event_type);
LOG_DBG("%d decided %s (%s decision moment %s)", hold_tap->position,
status_str(hold_tap->status), flavor_str(hold_tap->config->flavor),
decision_moment_str(decision_moment));
undecided_hold_tap = NULL;
struct zmk_behavior_binding_event event = {
.position = hold_tap->position,
.timestamp = hold_tap->timestamp,
};
struct zmk_behavior_binding binding;
if (hold_tap->is_hold) {
binding.behavior_dev = hold_tap->config->hold_behavior_dev;
binding.param1 = hold_tap->param_hold;
binding.param2 = 0;
} else {
binding.behavior_dev = hold_tap->config->tap_behavior_dev;
binding.param1 = hold_tap->param_tap;
binding.param2 = 0;
store_last_tapped(hold_tap);
}
behavior_keymap_binding_pressed(&binding, event);
press_binding(hold_tap);
release_captured_events();
}
static void decide_retro_tap(struct active_hold_tap *hold_tap) {
if (!hold_tap->config->retro_tap) {
return;
}
if (hold_tap->status == STATUS_HOLD_TIMER) {
release_binding(hold_tap);
LOG_DBG("%d retro tap", hold_tap->position);
hold_tap->status = STATUS_TAP;
press_binding(hold_tap);
return;
}
}
static void update_hold_status_for_retro_tap(uint32_t ignore_position) {
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
struct active_hold_tap *hold_tap = &active_hold_taps[i];
if (hold_tap->position == ignore_position ||
hold_tap->position == ZMK_BHV_HOLD_TAP_POSITION_NOT_USED ||
hold_tap->config->retro_tap == false) {
continue;
}
if (hold_tap->status == STATUS_HOLD_TIMER) {
LOG_DBG("Update hold tap %d status to hold-interrupt", hold_tap->position);
hold_tap->status = STATUS_HOLD_INTERRUPT;
press_binding(hold_tap);
}
}
}
static int on_hold_tap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
const struct device *dev = device_get_binding(binding->behavior_dev);
@ -362,6 +451,8 @@ static int on_hold_tap_binding_pressed(struct zmk_behavior_binding *binding,
int32_t tapping_term_ms_left = (hold_tap->timestamp + cfg->tapping_term_ms) - k_uptime_get();
if (tapping_term_ms_left > 0) {
k_delayed_work_submit(&hold_tap->work, K_MSEC(tapping_term_ms_left));
} else {
decide_hold_tap(hold_tap, HT_TIMER_EVENT);
}
return ZMK_BEHAVIOR_OPAQUE;
@ -383,25 +474,8 @@ static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding,
}
decide_hold_tap(hold_tap, HT_KEY_UP);
// todo: set up the binding and data items inside of the
// active_hhold_tap->config->behaviors->tap.behavior_dev;old_tap struct
struct zmk_behavior_binding_event sub_behavior_data = {
.position = hold_tap->position,
.timestamp = hold_tap->timestamp,
};
struct zmk_behavior_binding sub_behavior_binding;
if (hold_tap->is_hold) {
sub_behavior_binding.behavior_dev = hold_tap->config->hold_behavior_dev;
sub_behavior_binding.param1 = hold_tap->param_hold;
sub_behavior_binding.param2 = 0;
} else {
sub_behavior_binding.behavior_dev = hold_tap->config->tap_behavior_dev;
sub_behavior_binding.param1 = hold_tap->param_tap;
sub_behavior_binding.param2 = 0;
}
behavior_keymap_binding_released(&sub_behavior_binding, sub_behavior_data);
decide_retro_tap(hold_tap);
release_binding(hold_tap);
if (work_cancel_result == -EINPROGRESS) {
// let the timer handler clean up
@ -424,6 +498,8 @@ static const struct behavior_driver_api behavior_hold_tap_driver_api = {
static int position_state_changed_listener(const zmk_event_t *eh) {
struct zmk_position_state_changed *ev = as_zmk_position_state_changed(eh);
update_hold_status_for_retro_tap(ev->position);
if (undecided_hold_tap == NULL) {
LOG_DBG("%d bubble (no undecided hold_tap active)", ev->position);
return ZMK_EV_EVENT_BUBBLE;
@ -531,6 +607,7 @@ static struct behavior_hold_tap_data behavior_hold_tap_data;
.tap_behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(n, bindings, 1)), \
.quick_tap_ms = DT_INST_PROP(n, quick_tap_ms), \
.flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \
.retro_tap = DT_INST_PROP(n, retro_tap), \
}; \
DEVICE_AND_API_INIT(behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \
&behavior_hold_tap_data, &behavior_hold_tap_config_##n, APPLICATION, \

View file

@ -20,11 +20,81 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
static int behavior_rgb_underglow_init(const struct device *dev) { return 0; }
static int
on_keymap_binding_convert_central_state_dependent_params(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
switch (binding->param1) {
case RGB_TOG_CMD: {
bool state;
int err = zmk_rgb_underglow_get_state(&state);
if (err) {
LOG_ERR("Failed to get RGB underglow state (err %d)", err);
return err;
}
binding->param1 = state ? RGB_OFF_CMD : RGB_ON_CMD;
break;
}
case RGB_BRI_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_brt(1);
binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_BRD_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_brt(-1);
binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_HUI_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_hue(1);
binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_HUD_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_hue(-1);
binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_SAI_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_sat(1);
binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
case RGB_SAD_CMD: {
struct zmk_led_hsb color = zmk_rgb_underglow_calc_sat(-1);
binding->param1 = RGB_COLOR_HSB_CMD;
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
break;
}
default:
return 0;
}
LOG_DBG("RGB relative convert to absolute (%d/%d)", binding->param1, binding->param2);
return 0;
};
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
switch (binding->param1) {
case RGB_TOG_CMD:
return zmk_rgb_underglow_toggle();
case RGB_ON_CMD:
return zmk_rgb_underglow_on();
case RGB_OFF_CMD:
return zmk_rgb_underglow_off();
case RGB_HUI_CMD:
return zmk_rgb_underglow_change_hue(1);
case RGB_HUD_CMD:
@ -46,8 +116,9 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
case RGB_EFR_CMD:
return zmk_rgb_underglow_cycle_effect(-1);
case RGB_COLOR_HSB_CMD:
return zmk_rgb_underglow_set_hsb((binding->param2 >> 16) & 0xFFFF,
(binding->param2 >> 8) & 0xFF, binding->param2 & 0xFF);
return zmk_rgb_underglow_set_hsb((struct zmk_led_hsb){.h = (binding->param2 >> 16) & 0xFFFF,
.s = (binding->param2 >> 8) & 0xFF,
.b = binding->param2 & 0xFF});
}
return -ENOTSUP;
@ -59,6 +130,8 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
}
static const struct behavior_driver_api behavior_rgb_underglow_driver_api = {
.binding_convert_central_state_dependent_params =
on_keymap_binding_convert_central_state_dependent_params,
.binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released,
};

View file

@ -192,7 +192,7 @@ static inline bool candidate_is_completely_pressed(struct combo_cfg *candidate)
return pressed_keys[candidate->key_position_len - 1] != NULL;
}
static void cleanup();
static int cleanup();
static int filter_timed_out_candidates(int64_t timestamp) {
int num_candidates = 0;
@ -224,7 +224,7 @@ static int clear_candidates() {
}
static int capture_pressed_key(const zmk_event_t *ev) {
for (int i = 0; i < CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY; i++) {
for (int i = 0; i < CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO; i++) {
if (pressed_keys[i] != NULL) {
continue;
}
@ -236,23 +236,25 @@ static int capture_pressed_key(const zmk_event_t *ev) {
const struct zmk_listener zmk_listener_combo;
static void release_pressed_keys() {
// release the first key that was pressed
if (pressed_keys[0] == NULL) {
return;
}
ZMK_EVENT_RELEASE(pressed_keys[0])
pressed_keys[0] = NULL;
// reprocess events (see tests/combo/fully-overlapping-combos-3 for why this is needed)
for (int i = 1; i < CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY; i++) {
if (pressed_keys[i] == NULL) {
return;
}
static int release_pressed_keys() {
for (int i = 0; i < CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO; i++) {
const zmk_event_t *captured_event = pressed_keys[i];
if (pressed_keys[i] == NULL) {
return i;
}
pressed_keys[i] = NULL;
ZMK_EVENT_RAISE(captured_event);
if (i == 0) {
LOG_DBG("combo: releasing position event %d",
as_zmk_position_state_changed(captured_event)->position);
ZMK_EVENT_RELEASE(captured_event)
} else {
// reprocess events (see tests/combo/fully-overlapping-combos-3 for why this is needed)
LOG_DBG("combo: reraising position event %d",
as_zmk_position_state_changed(captured_event)->position);
ZMK_EVENT_RAISE(captured_event);
}
}
return CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO;
}
static inline int press_combo_behavior(struct combo_cfg *combo, int32_t timestamp) {
@ -360,14 +362,14 @@ static bool release_combo_key(int32_t position, int64_t timestamp) {
return false;
}
static void cleanup() {
static int cleanup() {
k_delayed_work_cancel(&timeout_task);
clear_candidates();
if (fully_pressed_combo != NULL) {
activate_combo(fully_pressed_combo);
fully_pressed_combo = NULL;
}
release_pressed_keys();
return release_pressed_keys();
}
static void update_timeout_task() {
@ -399,6 +401,7 @@ static int position_state_down(const zmk_event_t *ev, struct zmk_position_state_
update_timeout_task();
struct combo_cfg *candidate_combo = candidates[0].combo;
LOG_DBG("combo: capturing position event %d", data->position);
int ret = capture_pressed_key(ev);
switch (num_candidates) {
case 0:
@ -418,13 +421,18 @@ static int position_state_down(const zmk_event_t *ev, struct zmk_position_state_
}
}
static int position_state_up(struct zmk_position_state_changed *ev) {
cleanup();
if (release_combo_key(ev->position, ev->timestamp)) {
static int position_state_up(const zmk_event_t *ev, struct zmk_position_state_changed *data) {
int released_keys = cleanup();
if (release_combo_key(data->position, data->timestamp)) {
return ZMK_EV_EVENT_HANDLED;
} else {
return 0;
}
if (released_keys > 1) {
// The second and further key down events are re-raised. To preserve
// correct order for e.g. hold-taps, reraise the key up event too.
ZMK_EVENT_RAISE(ev);
return ZMK_EV_EVENT_CAPTURED;
}
return 0;
}
static void combo_timeout_handler(struct k_work *item) {
@ -447,7 +455,7 @@ static int position_state_changed_listener(const zmk_event_t *ev) {
if (data->state) { // keydown
return position_state_down(ev, data);
} else { // keyup
return position_state_up(data);
return position_state_up(ev, data);
}
}

View file

@ -38,12 +38,20 @@ void display_timer_cb() { k_work_submit(&display_tick_work); }
K_TIMER_DEFINE(display_timer, display_timer_cb, NULL);
static void start_display_updates() {
if (display == NULL) {
return;
}
display_blanking_off(display);
k_timer_start(&display_timer, K_MSEC(10), K_MSEC(10));
}
static void stop_display_updates() {
if (display == NULL) {
return;
}
display_blanking_on(display);
k_timer_stop(&display_timer);

View file

@ -22,24 +22,25 @@ int zmk_event_manager_handle_from(zmk_event_t *event, uint8_t start_index) {
uint8_t len = __event_subscriptions_end - __event_subscriptions_start;
for (int i = start_index; i < len; i++) {
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
if (ev_sub->event_type == event->event) {
ret = ev_sub->listener->callback(event);
if (ret < 0) {
LOG_DBG("Listener returned an error: %d", ret);
goto release;
} else if (ret > 0) {
switch (ret) {
case ZMK_EV_EVENT_HANDLED:
LOG_DBG("Listener handled the event");
ret = 0;
goto release;
case ZMK_EV_EVENT_CAPTURED:
LOG_DBG("Listener captured the event");
event->last_listener_index = i;
// Listeners are expected to free events they capture
return 0;
}
}
if (ev_sub->event_type != event->event) {
continue;
}
ret = ev_sub->listener->callback(event);
switch (ret) {
case ZMK_EV_EVENT_BUBBLE:
continue;
case ZMK_EV_EVENT_HANDLED:
LOG_DBG("Listener handled the event");
ret = 0;
goto release;
case ZMK_EV_EVENT_CAPTURED:
LOG_DBG("Listener captured the event");
event->last_listener_index = i;
// Listeners are expected to free events they capture
return 0;
default:
LOG_DBG("Listener returned an error: %d", ret);
goto release;
}
}

View file

@ -23,6 +23,7 @@ struct ext_power_generic_config {
const char *label;
const uint8_t pin;
const uint8_t flags;
const uint16_t init_delay_ms;
};
struct ext_power_generic_data {
@ -171,6 +172,10 @@ static int ext_power_generic_init(const struct device *dev) {
ext_power_enable(dev);
#endif
if (config->init_delay_ms) {
k_msleep(config->init_delay_ms);
}
return 0;
}
@ -210,7 +215,8 @@ static int ext_power_generic_pm_control(const struct device *dev, uint32_t ctrl_
static const struct ext_power_generic_config config = {
.label = DT_INST_GPIO_LABEL(0, control_gpios),
.pin = DT_INST_GPIO_PIN(0, control_gpios),
.flags = DT_INST_GPIO_FLAGS(0, control_gpios)};
.flags = DT_INST_GPIO_FLAGS(0, control_gpios),
.init_delay_ms = DT_INST_PROP_OR(0, init_delay_ms, 0)};
static struct ext_power_generic_data data = {
.status = false,
@ -223,13 +229,15 @@ static const struct ext_power_api api = {.enable = ext_power_generic_enable,
.disable = ext_power_generic_disable,
.get = ext_power_generic_get};
#define ZMK_EXT_POWER_INIT_PRIORITY 81
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
DEVICE_DEFINE(ext_power_generic, DT_INST_LABEL(0), ext_power_generic_init,
&ext_power_generic_pm_control, &data, &config, APPLICATION,
CONFIG_APPLICATION_INIT_PRIORITY, &api);
&ext_power_generic_pm_control, &data, &config, POST_KERNEL,
ZMK_EXT_POWER_INIT_PRIORITY, &api);
#else
DEVICE_AND_API_INIT(ext_power_generic, DT_INST_LABEL(0), ext_power_generic_init, &data, &config,
APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, &api);
POST_KERNEL, ZMK_EXT_POWER_INIT_PRIORITY, &api);
#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View file

@ -153,7 +153,9 @@ const char *zmk_keymap_layer_label(uint8_t layer) {
}
int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed, int64_t timestamp) {
struct zmk_behavior_binding *binding = &zmk_keymap[layer][position];
// We want to make a copy of this, since it may be converted from
// relative to absolute before being invoked
struct zmk_behavior_binding binding = zmk_keymap[layer][position];
const struct device *behavior;
struct zmk_behavior_binding_event event = {
.layer = layer,
@ -162,19 +164,25 @@ int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed,
};
LOG_DBG("layer: %d position: %d, binding name: %s", layer, position,
log_strdup(binding->behavior_dev));
log_strdup(binding.behavior_dev));
behavior = device_get_binding(binding->behavior_dev);
behavior = device_get_binding(binding.behavior_dev);
if (!behavior) {
LOG_DBG("No behavior assigned to %d on layer %d", position, layer);
return 1;
}
int err = behavior_keymap_binding_convert_central_state_dependent_params(&binding, event);
if (err) {
LOG_ERR("Failed to convert relative to absolute behavior binding (err %d)", err);
return err;
}
if (pressed) {
return behavior_keymap_binding_pressed(binding, event);
return behavior_keymap_binding_pressed(&binding, event);
} else {
return behavior_keymap_binding_released(binding, event);
return behavior_keymap_binding_released(&binding, event);
}
}

View file

@ -47,7 +47,7 @@ void zmk_kscan_process_msgq(struct k_work *item) {
while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0) {
bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
uint32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column);
LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s\n", ev.row, ev.column, position,
LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s", ev.row, ev.column, position,
(pressed ? "true" : "false"));
ZMK_EVENT_RAISE(new_zmk_position_state_changed((struct zmk_position_state_changed){
.state = pressed, .position = position, .timestamp = k_uptime_get()}));

View file

@ -17,11 +17,17 @@
#include <drivers/led_strip.h>
#include <drivers/ext_power.h>
#include <zmk/rgb_underglow.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define STRIP_LABEL DT_LABEL(DT_CHOSEN(zmk_underglow))
#define STRIP_NUM_PIXELS DT_PROP(DT_CHOSEN(zmk_underglow), chain_length)
#define HUE_MAX 360
#define SAT_MAX 100
#define BRT_MAX 100
enum rgb_underglow_effect {
UNDERGLOW_EFFECT_SOLID,
UNDERGLOW_EFFECT_BREATHE,
@ -30,16 +36,8 @@ enum rgb_underglow_effect {
UNDERGLOW_EFFECT_NUMBER // Used to track number of underglow effects
};
struct led_hsb {
uint16_t h;
uint8_t s;
uint8_t b;
};
struct rgb_underglow_state {
uint16_t hue;
uint8_t saturation;
uint8_t brightness;
struct zmk_led_hsb color;
uint8_t animation_speed;
uint8_t current_effect;
uint16_t animation_step;
@ -56,13 +54,13 @@ static struct rgb_underglow_state state;
static const struct device *ext_power;
#endif
static struct led_rgb hsb_to_rgb(struct led_hsb hsb) {
static struct led_rgb hsb_to_rgb(struct zmk_led_hsb hsb) {
double r, g, b;
uint8_t i = hsb.h / 60;
double v = hsb.b / 100.0;
double s = hsb.s / 100.0;
double f = hsb.h / 360.0 * 6 - i;
double v = hsb.b / ((float)BRT_MAX);
double s = hsb.s / ((float)SAT_MAX);
double f = hsb.h / ((float)HUE_MAX) * 6 - i;
double p = v * (1 - s);
double q = v * (1 - f * s);
double t = v * (1 - (1 - f) * s);
@ -105,33 +103,16 @@ static struct led_rgb hsb_to_rgb(struct led_hsb hsb) {
return rgb;
}
static void zmk_rgb_underglow_off() {
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0};
}
led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS);
}
static void zmk_rgb_underglow_effect_solid() {
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
int hue = state.hue;
int sat = state.saturation;
int brt = state.brightness;
struct led_hsb hsb = {hue, sat, brt};
pixels[i] = hsb_to_rgb(hsb);
pixels[i] = hsb_to_rgb(state.color);
}
}
static void zmk_rgb_underglow_effect_breathe() {
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
int hue = state.hue;
int sat = state.saturation;
int brt = abs(state.animation_step - 1200) / 12;
struct led_hsb hsb = {hue, sat, brt};
struct zmk_led_hsb hsb = state.color;
hsb.b = abs(state.animation_step - 1200) / 12;
pixels[i] = hsb_to_rgb(hsb);
}
@ -145,32 +126,26 @@ static void zmk_rgb_underglow_effect_breathe() {
static void zmk_rgb_underglow_effect_spectrum() {
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
int hue = state.animation_step;
int sat = state.saturation;
int brt = state.brightness;
struct led_hsb hsb = {hue, sat, brt};
struct zmk_led_hsb hsb = state.color;
hsb.h = state.animation_step;
pixels[i] = hsb_to_rgb(hsb);
}
state.animation_step += state.animation_speed;
state.animation_step = state.animation_step % 360;
state.animation_step = state.animation_step % HUE_MAX;
}
static void zmk_rgb_underglow_effect_swirl() {
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
int hue = (360 / STRIP_NUM_PIXELS * i + state.animation_step) % 360;
int sat = state.saturation;
int brt = state.brightness;
struct led_hsb hsb = {hue, sat, brt};
struct zmk_led_hsb hsb = state.color;
hsb.h = (HUE_MAX / STRIP_NUM_PIXELS * i + state.animation_step) % HUE_MAX;
pixels[i] = hsb_to_rgb(hsb);
}
state.animation_step += state.animation_speed * 2;
state.animation_step = state.animation_step % 360;
state.animation_step = state.animation_step % HUE_MAX;
}
static void zmk_rgb_underglow_tick(struct k_work *work) {
@ -196,10 +171,6 @@ K_WORK_DEFINE(underglow_work, zmk_rgb_underglow_tick);
static void zmk_rgb_underglow_tick_handler(struct k_timer *timer) {
if (!state.on) {
zmk_rgb_underglow_off();
k_timer_stop(timer);
return;
}
@ -255,9 +226,11 @@ static int zmk_rgb_underglow_init(const struct device *_arg) {
#endif
state = (struct rgb_underglow_state){
hue : CONFIG_ZMK_RGB_UNDERGLOW_HUE_START,
saturation : CONFIG_ZMK_RGB_UNDERGLOW_SAT_START,
brightness : CONFIG_ZMK_RGB_UNDERGLOW_BRT_START,
color : {
h : CONFIG_ZMK_RGB_UNDERGLOW_HUE_START,
s : CONFIG_ZMK_RGB_UNDERGLOW_SAT_START,
b : CONFIG_ZMK_RGB_UNDERGLOW_BRT_START,
},
animation_speed : CONFIG_ZMK_RGB_UNDERGLOW_SPD_START,
current_effect : CONFIG_ZMK_RGB_UNDERGLOW_EFF_START,
animation_step : 0,
@ -292,20 +265,65 @@ int zmk_rgb_underglow_save_state() {
#endif
}
int zmk_rgb_underglow_get_state(bool *on_off) {
if (!led_strip)
return -ENODEV;
*on_off = state.on;
return 0;
}
int zmk_rgb_underglow_on() {
if (!led_strip)
return -ENODEV;
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER)
if (ext_power != NULL) {
int rc = ext_power_enable(ext_power);
if (rc != 0) {
LOG_ERR("Unable to enable EXT_POWER: %d", rc);
}
}
#endif
state.on = true;
state.animation_step = 0;
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
return zmk_rgb_underglow_save_state();
}
int zmk_rgb_underglow_off() {
if (!led_strip)
return -ENODEV;
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER)
if (ext_power != NULL) {
int rc = ext_power_disable(ext_power);
if (rc != 0) {
LOG_ERR("Unable to disable EXT_POWER: %d", rc);
}
}
#endif
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0};
}
led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS);
k_timer_stop(&underglow_tick);
state.on = false;
return zmk_rgb_underglow_save_state();
}
int zmk_rgb_underglow_cycle_effect(int direction) {
if (!led_strip)
return -ENODEV;
if (state.current_effect == 0 && direction < 0) {
state.current_effect = UNDERGLOW_EFFECT_NUMBER - 1;
return 0;
}
state.current_effect += direction;
if (state.current_effect >= UNDERGLOW_EFFECT_NUMBER) {
state.current_effect = 0;
}
state.current_effect += UNDERGLOW_EFFECT_NUMBER + direction;
state.current_effect %= UNDERGLOW_EFFECT_NUMBER;
state.animation_step = 0;
@ -313,63 +331,61 @@ int zmk_rgb_underglow_cycle_effect(int direction) {
}
int zmk_rgb_underglow_toggle() {
if (!led_strip)
return -ENODEV;
state.on = !state.on;
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER)
if (ext_power != NULL) {
int rc;
if (state.on) {
rc = ext_power_enable(ext_power);
} else {
rc = ext_power_disable(ext_power);
}
if (rc != 0) {
LOG_ERR("Unable to toggle EXT_POWER: %d", rc);
}
}
#endif
if (state.on) {
state.animation_step = 0;
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
} else {
zmk_rgb_underglow_off();
k_timer_stop(&underglow_tick);
}
return zmk_rgb_underglow_save_state();
return state.on ? zmk_rgb_underglow_off() : zmk_rgb_underglow_on();
}
int zmk_rgb_underglow_set_hsb(uint16_t hue, uint8_t saturation, uint8_t brightness) {
if (hue > 360 || saturation > 100 || brightness > 100) {
int zmk_rgb_underglow_set_hsb(struct zmk_led_hsb color) {
if (color.h > HUE_MAX || color.s > SAT_MAX || color.b > BRT_MAX) {
return -ENOTSUP;
}
state.hue = hue;
state.saturation = saturation;
state.brightness = brightness;
state.color = color;
return 0;
}
struct zmk_led_hsb zmk_rgb_underglow_calc_hue(int direction) {
struct zmk_led_hsb color = state.color;
color.h += HUE_MAX + (direction * CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP);
color.h %= HUE_MAX;
return color;
}
struct zmk_led_hsb zmk_rgb_underglow_calc_sat(int direction) {
struct zmk_led_hsb color = state.color;
int s = color.s + (direction * CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP);
if (s < 0) {
s = 0;
} else if (s > SAT_MAX) {
s = SAT_MAX;
}
color.s = s;
return color;
}
struct zmk_led_hsb zmk_rgb_underglow_calc_brt(int direction) {
struct zmk_led_hsb color = state.color;
int b = color.b + (direction * CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP);
if (b < 0) {
b = 0;
} else if (b > BRT_MAX) {
b = BRT_MAX;
}
color.b = b;
return color;
}
int zmk_rgb_underglow_change_hue(int direction) {
if (!led_strip)
return -ENODEV;
if (state.hue == 0 && direction < 0) {
state.hue = 360 - CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP;
return 0;
}
state.hue += direction * CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP;
state.hue = state.hue % 360;
state.color = zmk_rgb_underglow_calc_hue(direction);
return zmk_rgb_underglow_save_state();
}
@ -378,15 +394,7 @@ int zmk_rgb_underglow_change_sat(int direction) {
if (!led_strip)
return -ENODEV;
if (state.saturation == 0 && direction < 0) {
return 0;
}
state.saturation += direction * CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP;
if (state.saturation > 100) {
state.saturation = 100;
}
state.color = zmk_rgb_underglow_calc_sat(direction);
return zmk_rgb_underglow_save_state();
}
@ -395,15 +403,7 @@ int zmk_rgb_underglow_change_brt(int direction) {
if (!led_strip)
return -ENODEV;
if (state.brightness == 0 && direction < 0) {
return 0;
}
state.brightness += direction * CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP;
if (state.brightness > 100) {
state.brightness = 100;
}
state.color = zmk_rgb_underglow_calc_brt(direction);
return zmk_rgb_underglow_save_state();
}

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo//p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo//p
s/.*hid_listener_keycode_//p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo//p
s/.*hid_listener_keycode_//p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo//p
s/.*hid_listener_keycode_//p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo//p
s/.*hid_listener_keycode_//p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo//p
s/.*hid_listener_keycode_//p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo//p
s/.*hid_listener_keycode_//p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo//p
s/.*hid_listener_keycode_//p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo//p
s/.*hid_listener_keycode_//p

View file

@ -0,0 +1 @@
s/.*hid_listener_keycode_//p

View file

@ -0,0 +1,4 @@
pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -0,0 +1,35 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan-mock.h>
/ {
combos {
compatible = "zmk,combos";
combo_one {
timeout-ms = <80>;
key-positions = <0 1 2 3>;
bindings = <&kp Z>;
};
};
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&kp A &kp B
&kp C &kp D
>;
};
};
};
&kscan {
events = <
ZMK_MOCK_PRESS(1,1,10)
ZMK_MOCK_PRESS(0,1,10)
ZMK_MOCK_RELEASE(0,1,100)
ZMK_MOCK_RELEASE(1,1,100)
>;
};

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo/combo/p
s/.*hid_listener_keycode_//p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo/combo/p

View file

@ -1,2 +1 @@
s/.*hid_listener_keycode_//p
s/.*combo/combo/p
s/.*hid_listener_keycode_//p

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (balanced event 0)
ht_decide: 0 decided tap (balanced decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 3)
ht_decide: 0 decided hold-timer (balanced decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,6 +1,6 @@
kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (balanced event 0)
ht_decide: 0 decided tap (balanced decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,6 +1,6 @@
kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 3)
ht_decide: 0 decided hold-timer (balanced decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_decide: 0 decided tap (balanced event 0)
ht_decide: 0 decided tap (balanced decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_decide: 0 decided hold (balanced event 3)
ht_decide: 0 decided hold-timer (balanced decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,8 +1,8 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 3)
ht_decide: 0 decided hold-timer (balanced decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 1 new undecided hold_tap
ht_decide: 1 decided tap (balanced event 0)
ht_decide: 1 decided tap (balanced decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 1 cleaning up hold-tap

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 3)
ht_decide: 0 decided hold-timer (balanced decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 2)
ht_decide: 0 decided hold-interrupt (balanced decision moment other-key-up)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 2)
ht_decide: 0 decided hold-interrupt (balanced decision moment other-key-up)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (balanced event 0)
ht_decide: 0 decided tap (balanced decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,10 +1,10 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (balanced event 0)
ht_decide: 0 decided tap (balanced decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (balanced event 4)
ht_decide: 0 decided tap (balanced decision moment quick-tap)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -0,0 +1,6 @@
s/.*hid_listener_keycode/kp/p
s/.*mo_keymap_binding/mo/p
s/.*on_hold_tap_binding/ht_binding/p
s/.*decide_hold_tap/ht_decide/p
s/.*update_hold_status_for_retro_tap/update_hold_status_for_retro_tap/p
s/.*decide_retro_tap/decide_retro_tap/p

View file

@ -0,0 +1,19 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (balanced decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold-timer (balanced decision moment timer)
decide_retro_tap: 0 retro tap
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold-timer (balanced decision moment timer)
update_hold_status_for_retro_tap: Update hold tap 0 status to hold-interrupt
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -0,0 +1,45 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan_mock.h>
/ {
behaviors {
ht_bal: behavior_balanced {
compatible = "zmk,behavior-hold-tap";
label = "MOD_TAP";
#binding-cells = <2>;
flavor = "balanced";
tapping_term_ms = <300>;
bindings = <&kp>, <&kp>;
retro-tap;
};
};
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&ht_bal LEFT_SHIFT F &none
&kp D &none>;
};
};
};
&kscan {
events = <
/* tap */
ZMK_MOCK_PRESS(0,0,10)
ZMK_MOCK_RELEASE(0,0,10)
/* retro tap */
ZMK_MOCK_PRESS(0,0,400)
ZMK_MOCK_RELEASE(0,0,10)
/* hold */
ZMK_MOCK_PRESS(0,0,400)
ZMK_MOCK_PRESS(1,0,10)
ZMK_MOCK_RELEASE(1,0,10)
ZMK_MOCK_RELEASE(0,0,10)
>;
};

View file

@ -9,8 +9,8 @@
label = "HOLD_TAP_BALANCED";
#binding-cells = <2>;
flavor = "balanced";
tapping_term_ms = <300>;
quick_tap_ms = <200>;
tapping-term-ms = <300>;
quick-tap-ms = <200>;
bindings = <&kp>, <&kp>;
};
};

View file

@ -1,16 +1,16 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (balanced event 3)
ht_decide: 0 decided hold-timer (balanced decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 1 new undecided hold_tap
ht_decide: 1 decided hold (balanced event 3)
ht_decide: 1 decided hold-timer (balanced decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 2 new undecided hold_tap
ht_binding_released: 0 cleaning up hold-tap
ht_decide: 2 decided hold (balanced event 3)
ht_decide: 2 decided hold-timer (balanced decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 3 new undecided hold_tap
ht_binding_released: 1 cleaning up hold-tap
ht_decide: 3 decided hold (balanced event 3)
ht_decide: 3 decided hold-timer (balanced decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe2 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00

View file

@ -9,7 +9,7 @@
label = "HOLD_TAP_BALANCED";
#binding-cells = <2>;
flavor = "balanced";
tapping_term_ms = <300>;
tapping-term-ms = <300>;
bindings = <&kp>, <&kp>;
};
};

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (hold-preferred event 0)
ht_decide: 0 decided tap (hold-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (hold-preferred event 3)
ht_decide: 0 decided hold-timer (hold-preferred decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,6 +1,6 @@
kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (hold-preferred event 0)
ht_decide: 0 decided tap (hold-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,6 +1,6 @@
kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (hold-preferred event 3)
ht_decide: 0 decided hold-timer (hold-preferred decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_decide: 0 decided tap (hold-preferred event 0)
ht_decide: 0 decided tap (hold-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_decide: 0 decided hold (hold-preferred event 3)
ht_decide: 0 decided hold-timer (hold-preferred decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,8 +1,8 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (hold-preferred event 1)
ht_decide: 0 decided hold-interrupt (hold-preferred decision moment other-key-down)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 1 new undecided hold_tap
ht_decide: 1 decided tap (hold-preferred event 0)
ht_decide: 1 decided tap (hold-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 1 cleaning up hold-tap

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (hold-preferred event 1)
ht_decide: 0 decided hold-interrupt (hold-preferred decision moment other-key-down)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (hold-preferred event 1)
ht_decide: 0 decided hold-interrupt (hold-preferred decision moment other-key-down)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (hold-preferred event 1)
ht_decide: 0 decided hold-interrupt (hold-preferred decision moment other-key-down)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (hold-preferred event 1)
ht_decide: 0 decided hold-interrupt (hold-preferred decision moment other-key-down)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,10 +1,10 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (hold-preferred event 0)
ht_decide: 0 decided tap (hold-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (hold-preferred event 4)
ht_decide: 0 decided tap (hold-preferred decision moment quick-tap)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -0,0 +1,6 @@
s/.*hid_listener_keycode/kp/p
s/.*mo_keymap_binding/mo/p
s/.*on_hold_tap_binding/ht_binding/p
s/.*decide_hold_tap/ht_decide/p
s/.*update_hold_status_for_retro_tap/update_hold_status_for_retro_tap/p
s/.*decide_retro_tap/decide_retro_tap/p

View file

@ -0,0 +1,19 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (hold-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold-timer (hold-preferred decision moment timer)
decide_retro_tap: 0 retro tap
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold-timer (hold-preferred decision moment timer)
update_hold_status_for_retro_tap: Update hold tap 0 status to hold-interrupt
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -0,0 +1,45 @@
#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
#include <dt-bindings/zmk/kscan_mock.h>
/ {
behaviors {
hp: behavior_hold_preferred {
compatible = "zmk,behavior-hold-tap";
label = "MOD_TAP";
#binding-cells = <2>;
flavor = "hold-preferred";
tapping_term_ms = <300>;
bindings = <&kp>, <&kp>;
retro-tap;
};
};
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&hp LEFT_SHIFT F &none
&kp D &none>;
};
};
};
&kscan {
events = <
/* tap */
ZMK_MOCK_PRESS(0,0,10)
ZMK_MOCK_RELEASE(0,0,10)
/* retro tap */
ZMK_MOCK_PRESS(0,0,400)
ZMK_MOCK_RELEASE(0,0,10)
/* hold */
ZMK_MOCK_PRESS(0,0,400)
ZMK_MOCK_PRESS(1,0,10)
ZMK_MOCK_RELEASE(1,0,10)
ZMK_MOCK_RELEASE(0,0,10)
>;
};

View file

@ -11,8 +11,8 @@
label = "hold_hold_tap";
#binding-cells = <2>;
flavor = "hold-preferred";
tapping_term_ms = <300>;
quick_tap_ms = <200>;
tapping-term-ms = <300>;
quick-tap-ms = <200>;
bindings = <&kp>, <&kp>;
};
};

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (tap-preferred event 0)
ht_decide: 0 decided tap (tap-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (tap-preferred event 3)
ht_decide: 0 decided hold-timer (tap-preferred decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,6 +1,6 @@
kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (tap-preferred event 0)
ht_decide: 0 decided tap (tap-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,6 +1,6 @@
kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (tap-preferred event 3)
ht_decide: 0 decided hold-timer (tap-preferred decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_decide: 0 decided tap (tap-preferred event 0)
ht_decide: 0 decided tap (tap-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,7 +1,7 @@
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 0 new undecided hold_tap
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
ht_decide: 0 decided hold (tap-preferred event 3)
ht_decide: 0 decided hold-timer (tap-preferred decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -1,8 +1,8 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (tap-preferred event 3)
ht_decide: 0 decided hold-timer (tap-preferred decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
ht_binding_pressed: 1 new undecided hold_tap
ht_decide: 1 decided tap (tap-preferred event 0)
ht_decide: 1 decided tap (tap-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 1 cleaning up hold-tap

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (tap-preferred event 3)
ht_decide: 0 decided hold-timer (tap-preferred decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided hold (tap-preferred event 3)
ht_decide: 0 decided hold-timer (tap-preferred decision moment timer)
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (tap-preferred event 0)
ht_decide: 0 decided tap (tap-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,5 +1,5 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (tap-preferred event 0)
ht_decide: 0 decided tap (tap-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00

View file

@ -1,10 +1,10 @@
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (tap-preferred event 0)
ht_decide: 0 decided tap (tap-preferred decision moment key-up)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap
ht_binding_pressed: 0 new undecided hold_tap
ht_decide: 0 decided tap (tap-preferred event 4)
ht_decide: 0 decided tap (tap-preferred decision moment quick-tap)
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
ht_binding_released: 0 cleaning up hold-tap

View file

@ -9,8 +9,8 @@
label = "MOD_TAP";
#binding-cells = <2>;
flavor = "tap-preferred";
tapping_term_ms = <300>;
quick_tap_ms = <200>;
tapping-term-ms = <300>;
quick-tap-ms = <200>;
bindings = <&kp>, <&kp>;
};
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View file

@ -23,9 +23,9 @@ We call this the 'hold-preferred' flavor of hold-taps. While this flavor may wor
#### Flavors
- The 'hold-preferred' flavor triggers the hold behavior when the `tapping_term_ms` has expired or another key is pressed.
- The 'balanced' flavor will trigger the hold behavior when the `tapping_term_ms` has expired or another key is pressed and released.
- The 'tap-preferred' flavor triggers the hold behavior when the `tapping_term_ms` has expired. It triggers the tap behavior when another key is pressed.
- The 'hold-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired or another key is pressed.
- The 'balanced' flavor will trigger the hold behavior when the `tapping-term-ms` has expired or another key is pressed and released.
- The 'tap-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired. It triggers the tap behavior when another key is pressed.
When the hold-tap key is released and the hold behavior has not been triggered, the tap behavior will trigger.
@ -37,7 +37,7 @@ For basic usage, please see [mod-tap](./mod-tap.md) and [layer-tap](./layers.md)
### Advanced Configuration
#### `tapping_term_ms`
#### `tapping-term-ms`
Defines how long a key must be pressed to trigger Hold behavior.
@ -47,6 +47,18 @@ If you press a tapped hold-tap again within `quick_tap_ms` milliseconds, it will
In QMK, unlike ZMK, this functionality is enabled by default, and you turn it off using `TAPPING_FORCE_HOLD`.
#### `retro-tap`
If retro tap is enabled, the tap behavior is triggered when releasing the hold-tap key if no other key was pressed in the meantime.
For example, if you press `&mt LEFT_SHIFT A` and then release it without pressing another key, it will output `a`.
```
&mt {
retro-tap;
}
```
#### Home row mods
This example configures a hold-tap that works well for homerow mods:
@ -61,7 +73,7 @@ This example configures a hold-tap that works well for homerow mods:
compatible = "zmk,behavior-hold-tap";
label = "HOMEROW_MODS";
#binding-cells = <2>;
tapping_term_ms = <150>;
tapping-term-ms = <150>;
quick_tap_ms = <0>;
flavor = "tap-preferred";
bindings = <&kp>, <&kp>;
@ -81,7 +93,7 @@ This example configures a hold-tap that works well for homerow mods:
```
If this config does not work for you, try the flavor "balanced" with a medium `tapping_term_ms` such as 200ms.
If this config does not work for you, try the flavor "balanced" with a medium `tapping-term-ms` such as 200ms.
#### Comparison to QMK

View file

@ -34,7 +34,7 @@ You can configure a different tapping term in your keymap:
```
&mt {
tapping_term_ms = <400>;
tapping-term-ms = <400>;
};
/ {
@ -46,4 +46,4 @@ You can configure a different tapping term in your keymap:
### Additional information
The mod-tap is a [hold-tap](./hold-tap.md) under the hood with the "balanced" flavor and tapping_term_ms 200.
The mod-tap is a [hold-tap](./hold-tap.md) under the hood with the "balanced" flavor and tapping-term-ms 200.

View file

@ -0,0 +1,159 @@
---
title: IDE Integration
sidebar_label: IDE Integration
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
export const OsTabs = (props) => (<Tabs
groupId="operating-systems"
defaultValue="debian"
values={[
{label: 'Debian/Ubuntu', value: 'debian'},
{label: 'Windows', value: 'win'},
{label: 'macOS', value: 'mac'},
{label: 'Raspberry OS', value: 'raspberryos'},
{label: 'Fedora', value: 'fedora'},
{label: 'VS Code & Docker', value: 'docker'},
]
}>{props.children}</Tabs>);
## Visual Studio Code
Visual Studio Code needs to know some things about the project such as include
paths and compiler paths before features such as code completion, go to definition,
and graying out disabled code blocks will work. Fortunately, CMake can generate
that configuration for us automatically.
### Create a Compilation Database
To configure `west` to tell CMake to generate a compilation database, open a
terminal to the ZMK repository and run the following command:
```sh
west config build.cmake-args -- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
```
Every [build](build-flash#building) will now update the database. You will
need to build once to create the database before code completion will work.
We'll tell Visual Studio Code where to find the database in the next step.
:::note
If you have set any other CMake arguments such as the path to your zmk-config, the
above command will overwrite them. You should instead provide the flag to export
compile commands and all other arguments surrounded by quotes. For example:
```sh
west config build.cmake-args -- "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DZMK_CONFIG=/path/to/zmk-config/config"
```
:::
### Create a C/C++ Configuration
Install the [C/C++ extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools),
then run **F1 > C/C++: Edit Configurations (UI)**. It should automatically create
a new configuration for you, but if the text box under **Configuration name** is empty,
click **Add Configuration**, enter a name, and click **OK**.
Change these options:
| Option | Value |
| ------------------------------------- | ---------------------------------------------------- |
| Compiler path | Path to your toolchain's GCC binary (see below) |
| IntelliSense mode | gcc-arm |
| Advanced Settings > Compiler commands | `${workspaceFolder}/app/build/compile_commands.json` |
#### Compiler Path
<OsTabs>
<TabItem value="debian">
Open VS Code's integrated terminal and run the following commands. It will print
your compiler path.
```sh
source zephyr/zephyr-env.sh
echo ${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc
```
:::note
You will need to update this path any time you switch to a new version of the Zephyr SDK.
:::
</TabItem>
<TabItem value="win">
Your compiler path is
```
${env:GNUARMEMB_TOOLCHAIN_PATH}/bin/arm-none-eabi-gcc.exe
```
This assumes `GNUARMEMB_TOOLCHAIN_PATH` is set in your system or user environment variables.
If not, you will need to list the full path instead of using the `${env}` placeholder.
</TabItem>
<TabItem value="mac">
Open VS Code's integrated terminal and run the following command. It will print
your compiler path.
```sh
echo ${GNUARMEMB_TOOLCHAIN_PATH}/bin/arm-none-eabi-gcc
```
</TabItem>
<TabItem value="raspberryos">
Your compiler path is
```
/usr/bin/arm-none-eabi-gcc
```
</TabItem>
<TabItem value="fedora">
Open VS Code's integrated terminal and run the following commands. It will print
your compiler path.
```sh
source zephyr/zephyr-env.sh
echo ${ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc
```
:::note
You will need to update this path any time you switch to a new version of the Zephyr SDK.
:::
</TabItem>
<TabItem value="docker">
Your compiler path is
```
${env:ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc
```
</TabItem>
</OsTabs>
#### Compiler Commands Path
When building with all default options, the path to the compilation database file
is `${workspaceFolder}/app/build/compile_commands.json` as shown in the table above,
however some arguments to `west build` can change this path.
The `-d` or `--build-dir` option lets you change the build directory to something
other than `build`. Replace `build` in the above path with what you set this to.
For example, if you build with `-d build/my_shield`, the path is
`${workspaceFolder}/app/build/my_shield/compile_commands.json`. If you use this
to keep builds for multiple keyboards separate, you may want to create a separate
C/C++ configuration for each one in VS Code.
You can also build from the root folder of the project instead of the `app`
folder by adding `-S app` to your CMake arguments. In this case, simply remove
`app` from the path to `compile_commands.json`, for example,
`${workspaceFolder}/build/compile_commands.json`.

View file

@ -0,0 +1,100 @@
---
title: Beta Testing
sidebar_label: Beta Testing
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
You may find that ZMK does not support a feature or keyboard that you are interesting in using. You may find that someone
has already taken the time to submit the feature you need as a [Pull Request](https://github.com/zmkfirmware/zmk/pulls). If you find the feature you need as a pull request,
this page is for you!
## Developer Repositories and Branches
For a developer to submit a pull request to ZMK, they must first clone the original ZMK repository. After they have a copy
of the source code, they may create a feature branch to work within. When they have finished, they will publish the feature
branch and create the pull request.
### Finding the Repository Page from the Pull Request
![PR Repository](../assets/features/beta-testing/pr-repo-branch.png)
### Finding the Repository URL
![Repository URL](../assets/features/beta-testing/repo-url.png)
### Finding the Repository Branch
![Repository URL](../assets/features/beta-testing/repo-branch.png)
## Testing features
Testing features will require you to modify the `west.yml` file. You will need to add a new remote for the pull request you
would like to test, and change the selected remote and revision (or branch) for the `zmk` project.
### Examples
<Tabs
defaultValue="zmk"
values={[
{label: 'Default', value: 'zmk'},
{label: 'PR685: Macros', value: 'macros'},
{label: 'PR649: Add &sleep behavior', value: 'sleep'},
]}>
<TabItem value="zmk">
```
manifest:
remotes:
- name: zmkfirmware
url-base: https://github.com/zmkfirmware
projects:
- name: zmk
remote: zmkfirmware
revision: main
import: app/west.yml
self:
path: config
```
</TabItem>
<TabItem value="macros">
```
manifest:
remotes:
- name: zmkfirmware
url-base: https://github.com/zmkfirmware
- name: okke-formsma
url-base: https://github.com/okke-formsma
projects:
- name: zmk
remote: okke-formsma
revision: macros
import: app/west.yml
self:
path: config
```
</TabItem>
<TabItem value="sleep">
```
manifest:
remotes:
- name: zmkfirmware
url-base: https://github.com/zmkfirmware
- name: mcrosson
url-base: https://github.com/mcrosson
projects:
- name: zmk
remote: mcrosson
revision: feat-behavior-sleep
import: app/west.yml
self:
path: config
```
</TabItem>
</Tabs>

Some files were not shown because too many files have changed in this diff Show more