From 775117d590f701094722c1df8df0ab970c114b2b Mon Sep 17 00:00:00 2001 From: krikun98 Date: Thu, 2 Sep 2021 04:09:07 +0300 Subject: [PATCH] Cleanup and acceleration fixes --- app/dts/behaviors/mouse_move.dtsi | 6 +- app/dts/behaviors/mouse_scroll.dtsi | 2 +- app/include/zmk/events/mouse_tick.h | 5 +- app/include/zmk/mouse.h | 2 +- app/src/behaviors/behavior_mouse_key_press.c | 6 +- app/src/behaviors/behavior_mouse_move.c | 8 +-- app/src/behaviors/behavior_mouse_scroll.c | 8 +-- app/src/endpoints.c | 1 - app/src/main.c | 4 ++ app/src/mouse/key_listener.c | 35 ++++++++++-- app/src/mouse/main.c | 21 +++---- app/src/mouse/tick_listener.c | 58 +++++++------------- 12 files changed, 80 insertions(+), 76 deletions(-) diff --git a/app/dts/behaviors/mouse_move.dtsi b/app/dts/behaviors/mouse_move.dtsi index 858c5617..d34329c8 100644 --- a/app/dts/behaviors/mouse_move.dtsi +++ b/app/dts/behaviors/mouse_move.dtsi @@ -4,9 +4,9 @@ compatible = "zmk,behavior-mouse-move"; label = "MOUSE_MOVE"; #binding-cells = <1>; - delay-ms = <100>; - time-to-max-speed-ms = <1000>; - acceleration-exponent = <2000>; + delay-ms = <0>; + time-to-max-speed-ms = <300>; + acceleration-exponent = <1>; }; }; }; diff --git a/app/dts/behaviors/mouse_scroll.dtsi b/app/dts/behaviors/mouse_scroll.dtsi index 931124ce..fb54886d 100644 --- a/app/dts/behaviors/mouse_scroll.dtsi +++ b/app/dts/behaviors/mouse_scroll.dtsi @@ -5,7 +5,7 @@ label = "MOUSE_SCROLL"; #binding-cells = <1>; delay-ms = <0>; - time-to-max-speed-ms = <1000>; + time-to-max-speed-ms = <300>; acceleration-exponent = <0>; }; }; diff --git a/app/include/zmk/events/mouse_tick.h b/app/include/zmk/events/mouse_tick.h index 6307b5eb..1c78dc8c 100644 --- a/app/include/zmk/events/mouse_tick.h +++ b/app/include/zmk/events/mouse_tick.h @@ -17,6 +17,7 @@ struct zmk_mouse_tick { struct vector2d max_scroll; struct mouse_config move_config; struct mouse_config scroll_config; + int64_t* start_time; int64_t timestamp; }; @@ -25,12 +26,14 @@ ZMK_EVENT_DECLARE(zmk_mouse_tick); static inline struct zmk_mouse_tick_event *zmk_mouse_tick(struct vector2d max_move, struct vector2d max_scroll, struct mouse_config move_config, - struct mouse_config scroll_config) { + struct mouse_config scroll_config, + int64_t* movement_start) { return new_zmk_mouse_tick((struct zmk_mouse_tick){ .max_move = max_move, .max_scroll = max_scroll, .move_config = move_config, .scroll_config = scroll_config, + .start_time = movement_start, .timestamp = k_uptime_get(), }); } diff --git a/app/include/zmk/mouse.h b/app/include/zmk/mouse.h index 1e974f4b..f8f85744 100644 --- a/app/include/zmk/mouse.h +++ b/app/include/zmk/mouse.h @@ -18,7 +18,7 @@ struct mouse_config { // acceleration exponent 0: uniform speed // acceleration exponent 1: uniform acceleration // acceleration exponent 2: uniform jerk - float acceleration_exponent; + int acceleration_exponent; }; struct vector2d { diff --git a/app/src/behaviors/behavior_mouse_key_press.c b/app/src/behaviors/behavior_mouse_key_press.c index 6da2a8c4..e5f2709c 100644 --- a/app/src/behaviors/behavior_mouse_key_press.c +++ b/app/src/behaviors/behavior_mouse_key_press.c @@ -39,9 +39,9 @@ static const struct behavior_driver_api behavior_mouse_key_press_driver_api = { .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released}; #define KP_INST(n) \ - DEVICE_AND_API_INIT( \ - behavior_mouse_key_press_##n, DT_INST_LABEL(n), behavior_mouse_key_press_init, NULL, NULL, \ - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mouse_key_press_driver_api); + DEVICE_DT_INST_DEFINE(n, behavior_mouse_key_press_init, device_pm_control_nop, NULL, NULL, \ + APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ + &behavior_mouse_key_press_driver_api); DT_INST_FOREACH_STATUS_OKAY(KP_INST) diff --git a/app/src/behaviors/behavior_mouse_move.c b/app/src/behaviors/behavior_mouse_move.c index 92ea3d86..5977a039 100644 --- a/app/src/behaviors/behavior_mouse_move.c +++ b/app/src/behaviors/behavior_mouse_move.c @@ -46,11 +46,11 @@ static const struct behavior_driver_api behavior_mouse_move_driver_api = { static struct mouse_config behavior_mouse_move_config_##n = { \ .delay_ms = DT_INST_PROP(n, delay_ms), \ .time_to_max_speed_ms = DT_INST_PROP(n, time_to_max_speed_ms), \ - .acceleration_exponent = (float)DT_INST_PROP(n, acceleration_exponent) / 1000.0f, \ + .acceleration_exponent = DT_INST_PROP(n, acceleration_exponent), \ }; \ - DEVICE_AND_API_INIT(behavior_mouse_move_##n, DT_INST_LABEL(n), behavior_mouse_move_init, NULL, \ - &behavior_mouse_move_config_##n, APPLICATION, \ - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mouse_move_driver_api); + DEVICE_DT_INST_DEFINE(n, behavior_mouse_move_init, device_pm_control_nop, NULL, \ + &behavior_mouse_move_config_##n, APPLICATION, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mouse_move_driver_api); DT_INST_FOREACH_STATUS_OKAY(KP_INST) diff --git a/app/src/behaviors/behavior_mouse_scroll.c b/app/src/behaviors/behavior_mouse_scroll.c index e347d8af..64162352 100644 --- a/app/src/behaviors/behavior_mouse_scroll.c +++ b/app/src/behaviors/behavior_mouse_scroll.c @@ -47,11 +47,11 @@ static const struct behavior_driver_api behavior_mouse_scroll_driver_api = { static struct mouse_config behavior_mouse_scroll_config_##n = { \ .delay_ms = DT_INST_PROP(n, delay_ms), \ .time_to_max_speed_ms = DT_INST_PROP(n, time_to_max_speed_ms), \ - .acceleration_exponent = (float)DT_INST_PROP(n, acceleration_exponent) / 1000.0f, \ + .acceleration_exponent = DT_INST_PROP(n, acceleration_exponent), \ }; \ - DEVICE_AND_API_INIT(behavior_mouse_scroll_##n, DT_INST_LABEL(n), behavior_mouse_scroll_init, \ - NULL, &behavior_mouse_scroll_config_##n, APPLICATION, \ - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mouse_scroll_driver_api); + DEVICE_DT_INST_DEFINE(n, behavior_mouse_scroll_init, device_pm_control_nop, NULL, \ + &behavior_mouse_scroll_config_##n, APPLICATION, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mouse_scroll_driver_api); DT_INST_FOREACH_STATUS_OKAY(KP_INST) diff --git a/app/src/endpoints.c b/app/src/endpoints.c index d40396c8..3e025291 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -146,7 +146,6 @@ int zmk_endpoints_send_report(uint16_t usage_page) { } int zmk_endpoints_send_mouse_report() { - LOG_DBG("SENDING MOUSE REPORT"); struct zmk_hid_mouse_report *mouse_report = zmk_hid_get_mouse_report(); switch (current_endpoint) { diff --git a/app/src/main.c b/app/src/main.c index 62c71437..d3b3e578 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -17,6 +17,10 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include +#ifdef CONFIG_ZMK_MOUSE +#include +#endif /* CONFIG_ZMK_MOUSE */ + #define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID) void main(void) { diff --git a/app/src/mouse/key_listener.c b/app/src/mouse/key_listener.c index 37fb3551..56a84b45 100644 --- a/app/src/mouse/key_listener.c +++ b/app/src/mouse/key_listener.c @@ -20,18 +20,36 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); static struct vector2d move_speed = {0}; static struct vector2d scroll_speed = {0}; -static struct mouse_config move_config = {0}; -static struct mouse_config scroll_config = {0}; +static struct mouse_config move_config = (struct mouse_config){0}; +static struct mouse_config scroll_config = (struct mouse_config){0}; +static int64_t start_time = 0; -static void clear_mouse_state() { +bool equals(const struct mouse_config *one, const struct mouse_config *other) { + return one->delay_ms == other->delay_ms && + one->time_to_max_speed_ms == other->time_to_max_speed_ms && + one->acceleration_exponent == other->acceleration_exponent; +} + +static void clear_mouse_state(struct k_work *work) { move_speed = (struct vector2d){0}; scroll_speed = (struct vector2d){0}; + start_time = 0; + zmk_hid_mouse_movement_set(0, 0); + zmk_hid_mouse_scroll_set(0, 0); + LOG_DBG("Clearing state"); +} + +K_WORK_DEFINE(mouse_clear, &clear_mouse_state); + +void mouse_clear_cb(struct k_timer *dummy) { + k_work_submit_to_queue(zmk_mouse_work_q(), &mouse_clear); } static void mouse_tick_timer_handler(struct k_work *work) { zmk_hid_mouse_movement_set(0, 0); zmk_hid_mouse_scroll_set(0, 0); - ZMK_EVENT_RAISE(zmk_mouse_tick(move_speed, scroll_speed, move_config, scroll_config)); + LOG_DBG("Raising mouse tick event"); + ZMK_EVENT_RAISE(zmk_mouse_tick(move_speed, scroll_speed, move_config, scroll_config, &start_time)); zmk_endpoints_send_mouse_report(); } @@ -41,12 +59,13 @@ void mouse_timer_cb(struct k_timer *dummy) { k_work_submit_to_queue(zmk_mouse_work_q(), &mouse_tick); } -K_TIMER_DEFINE(mouse_timer, mouse_timer_cb, NULL); +K_TIMER_DEFINE(mouse_timer, mouse_timer_cb, mouse_clear_cb); static int mouse_timer_ref_count = 0; void mouse_timer_ref() { if (mouse_timer_ref_count == 0) { + start_time = k_uptime_get(); k_timer_start(&mouse_timer, K_NO_WAIT, K_MSEC(CONFIG_ZMK_MOUSE_TICK_DURATION)); } mouse_timer_ref_count += 1; @@ -58,7 +77,6 @@ void mouse_timer_unref() { } if (mouse_timer_ref_count == 0) { k_timer_stop(&mouse_timer); - clear_mouse_state(); } } @@ -101,6 +119,9 @@ static void listener_mouse_button_released(const struct zmk_mouse_button_state_c int mouse_listener(const zmk_event_t *eh) { const struct zmk_mouse_move_state_changed *mmv_ev = as_zmk_mouse_move_state_changed(eh); if (mmv_ev) { + if (!equals(&move_config, &(mmv_ev->config))) + move_config = mmv_ev->config; + if (mmv_ev->state) { listener_mouse_move_pressed(mmv_ev); } else { @@ -110,6 +131,8 @@ int mouse_listener(const zmk_event_t *eh) { } const struct zmk_mouse_scroll_state_changed *msc_ev = as_zmk_mouse_scroll_state_changed(eh); if (msc_ev) { + if (!equals(&scroll_config, &(msc_ev->config))) + scroll_config = msc_ev->config; if (msc_ev->state) { listener_mouse_scroll_pressed(msc_ev); } else { diff --git a/app/src/mouse/main.c b/app/src/mouse/main.c index 271417c1..49208a76 100644 --- a/app/src/mouse/main.c +++ b/app/src/mouse/main.c @@ -8,23 +8,18 @@ #include #if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED) - K_THREAD_STACK_DEFINE(mouse_work_stack_area, CONFIG_ZMK_MOUSE_DEDICATED_THREAD_STACK_SIZE); - static struct k_work_q mouse_work_q; - -struct k_work_q *zmk_mouse_work_q() { - return &mouse_work_q; -} - -#else - -struct k_work_q *zmk_mouse_work_q() { - return &k_sys_work_q; -} - #endif +struct k_work_q *zmk_mouse_work_q() { +#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED) + return &mouse_work_q; +#else + return &k_sys_work_q; +#endif +} + int zmk_mouse_init() { #if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED) k_work_q_start(&mouse_work_q, mouse_work_stack_area, diff --git a/app/src/mouse/tick_listener.c b/app/src/mouse/tick_listener.c index 4aec26f4..a1459384 100644 --- a/app/src/mouse/tick_listener.c +++ b/app/src/mouse/tick_listener.c @@ -13,17 +13,13 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include -#include - -// CLAMP will be provided by sys/util.h from zephyr 2.6 onward -#define CLAMP(x, min, max) MIN(MAX(x, min), max) +#include // CLAMP #if CONFIG_MINIMAL_LIBC static float powf(float base, float exponent) { // poor man's power implementation rounds the exponent down to the nearest integer. - LOG_DBG("falling back to integer exponent %d instead of %f", (int)exponent, exponent); float power = 1.0f; - for (; exponent < 1.0f; exponent--) { + for (; exponent >= 1.0f; exponent--) { power = power * base; } return power; @@ -32,27 +28,11 @@ static float powf(float base, float exponent) { #include #endif -struct movement_state { - int64_t start; - struct vector2d fractional_remainder; -}; +struct vector2d move_remainder = {0}; +struct vector2d scroll_remainder = {0}; -struct movement_state move_state = {0}; -static struct mouse_config move_config = (struct mouse_config){ - .delay_ms = 0, - .time_to_max_speed_ms = 300, - .acceleration_exponent = 2.0, -}; - -struct movement_state scroll_state = {0}; -static struct mouse_config scroll_config = (struct mouse_config){ - .delay_ms = 0, - .time_to_max_speed_ms = 300, - .acceleration_exponent = 2.0, -}; - -static int64_t ms_since_start(int64_t start, int64_t now) { - int64_t move_duration = now - start; +static int64_t ms_since_start(int64_t start, int64_t now, int64_t delay) { + int64_t move_duration = now - (start + delay); // start can be in the future if there's a delay if (move_duration < 0) { move_duration = 0; @@ -60,10 +40,12 @@ static int64_t ms_since_start(int64_t start, int64_t now) { return move_duration; } -static float speed(struct mouse_config *config, float max_speed, int64_t duration_ms) { +static float speed(const struct mouse_config *config, float max_speed, int64_t duration_ms) { // Calculate the speed based on MouseKeysAccel // See https://en.wikipedia.org/wiki/Mouse_keys - if (duration_ms > config->time_to_max_speed_ms) { + if (duration_ms > config->time_to_max_speed_ms + || config->time_to_max_speed_ms == 0 + || config->acceleration_exponent == 0) { return max_speed; } float time_fraction = (float)duration_ms / config->time_to_max_speed_ms; @@ -76,36 +58,34 @@ static void track_remainder(float *move, float *remainder) { *move = (int)new_move; } -static struct vector2d update_movement(struct movement_state *state, struct mouse_config *config, - struct vector2d max_speed, int64_t now) { +static struct vector2d update_movement(struct vector2d *remainder, + const struct mouse_config *config, struct vector2d max_speed, + int64_t now, int64_t *start_time) { struct vector2d move = {0}; if (max_speed.x == 0 && max_speed.y == 0) { - *state = (struct movement_state){0}; + *remainder = (struct vector2d){0}; return move; } - if (state->start == 0) { - state->start = now + config->delay_ms; - } - int64_t move_duration = ms_since_start(state->start, now); + int64_t move_duration = ms_since_start(*start_time, now, config->delay_ms); move = (struct vector2d){ .x = speed(config, max_speed.x, move_duration) * CONFIG_ZMK_MOUSE_TICK_DURATION / 1000, .y = speed(config, max_speed.y, move_duration) * CONFIG_ZMK_MOUSE_TICK_DURATION / 1000, }; - track_remainder(&(move.x), &state->fractional_remainder.x); - track_remainder(&(move.y), &state->fractional_remainder.y); + track_remainder(&(move.x), &(remainder->x)); + track_remainder(&(move.y), &(remainder->y)); return move; } static void mouse_tick_handler(const struct zmk_mouse_tick *tick) { struct vector2d move = - update_movement(&move_state, &move_config, tick->max_move, tick->timestamp); + update_movement(&move_remainder, &(tick->move_config), tick->max_move, tick->timestamp, tick->start_time); zmk_hid_mouse_movement_update((int16_t)CLAMP(move.x, INT16_MIN, INT16_MAX), (int16_t)CLAMP(move.y, INT16_MIN, INT16_MAX)); struct vector2d scroll = - update_movement(&scroll_state, &scroll_config, tick->max_scroll, tick->timestamp); + update_movement(&scroll_remainder, &(tick->scroll_config), tick->max_scroll, tick->timestamp, tick->start_time); zmk_hid_mouse_scroll_update((int8_t)CLAMP(scroll.x, INT8_MIN, INT8_MAX), (int8_t)CLAMP(scroll.y, INT8_MIN, INT8_MAX)); }