From 1dc5caebe8591945e9aeff62a58d04baf1b3c814 Mon Sep 17 00:00:00 2001 From: Bjonnh Date: Sat, 7 Dec 2024 17:37:21 -0600 Subject: [PATCH 1/2] Support for hall effect mouse keys. You need to set MOUSEKEY_VARIABLE 1 in your keyboard config.h Currently only tested on a Q2 HE. --- .../common/analog_matrix/analog_matrix_scan.c | 17 +++++++ keyboards/keychron/common/keychron_common.c | 46 ++++++++++++++++++- keyboards/keychron/common/keychron_common.h | 13 ++++++ keyboards/keychron/k2_he/ansi_rgb/config.h | 1 + quantum/mousekey.c | 43 ++++++++++++++--- quantum/mousekey.h | 6 +++ 6 files changed, 119 insertions(+), 7 deletions(-) diff --git a/keyboards/keychron/common/analog_matrix/analog_matrix_scan.c b/keyboards/keychron/common/analog_matrix/analog_matrix_scan.c index 2d5edae21e0b..63cbefd51832 100644 --- a/keyboards/keychron/common/analog_matrix/analog_matrix_scan.c +++ b/keyboards/keychron/common/analog_matrix/analog_matrix_scan.c @@ -22,6 +22,8 @@ #include "debounce.h" #include "lpm.h" +#include + #ifndef HC164_DS # define HC164_DS B3 #endif @@ -161,6 +163,21 @@ void matrix_read_rows_on_col(uint8_t current_col, matrix_row_t row_shifter) { if ((analog_raw_matrix[row_index] & row_mask) == 0) changed = true; + if (is_mouse_key(current_col, row_index)) { + uint8_t travel = analog_matrix_get_travel(row_index, current_col)/TRAVEL_SCALE; + uint8_t mouse_speed = ((travel * travel + travel) * 4) / 100; + if (mouse_speed == 0) + mouse_speed = 1; + if (mouse_speed > 200) + mouse_speed = 200; + if (is_vertical_mouse_key(current_col, row_index)) { + mousekey_set_speed_y(mouse_speed); + } else { + mousekey_set_speed_x(mouse_speed); + } + } + + if (debouce_times == ANALOG_DEBOUCE_TIME) { row_value |= (0x01 << row_index); } else { diff --git a/keyboards/keychron/common/keychron_common.c b/keyboards/keychron/common/keychron_common.c index 8957199b1351..b83b7dc8eda4 100644 --- a/keyboards/keychron/common/keychron_common.c +++ b/keyboards/keychron/common/keychron_common.c @@ -48,6 +48,39 @@ static key_combination_t key_comb_list[4] = { {2, {KC_LWIN, KC_C}}, }; +// A struct that stores col and row +typedef struct { + uint8_t col; + uint8_t row; +} key_pos_t; + +// An array for the 4 keys, all set to 255, 255 by default using key_post_t +key_pos_t mouse_keys_pos[4] = { + {255, 255}, + {255, 255}, + {255, 255}, + {255, 255}, +}; + +void set_mouse_key_last_key_pos(uint8_t pos, uint8_t col, uint8_t row) { + if (pos>3) return; + mouse_keys_pos[pos].col = col; + mouse_keys_pos[pos].row = row; +} + +inline bool is_mouse_key(uint8_t col, uint8_t row) { + for (uint8_t i = 0; i < 4; i++) { + if (mouse_keys_pos[i].col == col && mouse_keys_pos[i].row == row) { + return true; + } + } + return false; +} + +inline bool is_vertical_mouse_key(uint8_t col, uint8_t row) { + return (mouse_keys_pos[0].col == col && mouse_keys_pos[0].row == row) || (mouse_keys_pos[1].col == col && mouse_keys_pos[1].row == row); +} + bool process_record_keychron_common(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case KC_MCTRL: @@ -100,7 +133,18 @@ bool process_record_keychron_common(uint16_t keycode, keyrecord_t *record) { } } return false; // Skip all further processing of this key - + case KC_MS_UP: + set_mouse_key_last_key_pos(0, record->event.key.col, record->event.key.row); + break; + case KC_MS_DOWN: + set_mouse_key_last_key_pos(1, record->event.key.col, record->event.key.row); + break; + case KC_MS_LEFT: + set_mouse_key_last_key_pos(2, record->event.key.col, record->event.key.row); + break; + case KC_MS_RIGHT: + set_mouse_key_last_key_pos(3, record->event.key.col, record->event.key.row); + break; default: #ifdef ANANLOG_MATRIX return process_record_profile( keycode, record); diff --git a/keyboards/keychron/common/keychron_common.h b/keyboards/keychron/common/keychron_common.h index d33f1b681bf8..f3f90eb93b8e 100644 --- a/keyboards/keychron/common/keychron_common.h +++ b/keyboards/keychron/common/keychron_common.h @@ -42,6 +42,10 @@ enum { PROF1, PROF2, PROF3, + HE_M_UP, + HE_M_DOWN, + HE_M_LEFT, + HE_M_RIGHT, #endif NEW_SAFE_RANGE, }; @@ -57,6 +61,10 @@ enum { #define PROF1 KC_TRANS #define PROF2 KC_TRANS #define PROF3 KC_TRANS + #define HE_M_UP KC_TRANS + #define HE_M_DOWN KC_TRANS + #define HE_M_LEFT KC_TRANS + #define HE_M_RIGHT KC_TRANS #endif #define KC_TASK KC_TASK_VIEW @@ -79,6 +87,11 @@ typedef struct PACKED { bool process_record_keychron_common(uint16_t keycode, keyrecord_t *record); void keychron_common_task(void); +void set_mouse_vertical_last_key_pos(uint8_t col, uint8_t row); +void set_mouse_horizontal_last_key_pos(uint8_t col, uint8_t row); +void set_mouse_key_last_key_pos(uint8_t pos, uint8_t col, uint8_t row); +bool is_mouse_key(uint8_t col, uint8_t row); +bool is_vertical_mouse_key(uint8_t col, uint8_t row); #ifdef ENCODER_ENABLE void encoder_cb_init(void); diff --git a/keyboards/keychron/k2_he/ansi_rgb/config.h b/keyboards/keychron/k2_he/ansi_rgb/config.h index 5398569cbffa..9dc000a55de6 100644 --- a/keyboards/keychron/k2_he/ansi_rgb/config.h +++ b/keyboards/keychron/k2_he/ansi_rgb/config.h @@ -20,6 +20,7 @@ /* RGB Matrix driver configuration */ # define DRIVER_COUNT 2 # define RGB_MATRIX_LED_COUNT 84 +# define MOUSEKEY_VARIABLE 1 # define SPI_SCK_PIN A5 # define SPI_MISO_PIN A6 diff --git a/quantum/mousekey.c b/quantum/mousekey.c index 39108117524b..13ef868ae3da 100644 --- a/quantum/mousekey.c +++ b/quantum/mousekey.c @@ -42,6 +42,9 @@ static void mousekey_debug(void); static uint8_t mousekey_accel = 0; static uint8_t mousekey_repeat = 0; static uint8_t mousekey_wheel_repeat = 0; +static uint8_t mousekey_variable = MOUSEKEY_VARIABLE; +static uint8_t mousekey_speed_x = 1; +static uint8_t mousekey_speed_y = 1; #ifdef MOUSEKEY_INERTIA static uint8_t mousekey_frame = 0; // track whether gesture is inactive, first frame, or repeating static int8_t mousekey_x_dir = 0; // -1 / 0 / 1 = left / neutral / right @@ -110,6 +113,34 @@ static uint8_t move_unit(void) { return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit)); } +void mousekey_set_speed_x(uint8_t speed) { + mousekey_speed_x = speed; +} + +void mousekey_set_speed_y(uint8_t speed) { + mousekey_speed_y = speed; +} + +static uint8_t move_unit_x(void) { + uint16_t unit; + if (mousekey_variable) { + unit = mousekey_speed_x; + } else { + unit = move_unit(); + } + return unit; +} + +static uint8_t move_unit_y(void) { + uint16_t unit; + if (mousekey_variable) { + unit = mousekey_speed_y; + } else { + unit = move_unit(); + } + return unit; +} + # else // MOUSEKEY_INERTIA mode static int8_t move_unit(uint8_t axis) { @@ -341,8 +372,8 @@ void mousekey_task(void) { if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) { if (mousekey_repeat != UINT8_MAX) mousekey_repeat++; - if (tmpmr.x != 0) mouse_report.x = move_unit() * ((tmpmr.x > 0) ? 1 : -1); - if (tmpmr.y != 0) mouse_report.y = move_unit() * ((tmpmr.y > 0) ? 1 : -1); + if (tmpmr.x != 0) mouse_report.x = move_unit_x() * ((tmpmr.x > 0) ? 1 : -1); + if (tmpmr.y != 0) mouse_report.y = move_unit_y() * ((tmpmr.y > 0) ? 1 : -1); /* diagonal move [1/sqrt(2)] */ if (mouse_report.x && mouse_report.y) { @@ -418,13 +449,13 @@ void mousekey_on(uint8_t code) { # else // no inertia if (code == KC_MS_UP) - mouse_report.y = move_unit() * -1; + mouse_report.y = move_unit_y() * -1; else if (code == KC_MS_DOWN) - mouse_report.y = move_unit(); + mouse_report.y = move_unit_y(); else if (code == KC_MS_LEFT) - mouse_report.x = move_unit() * -1; + mouse_report.x = move_unit_x() * -1; else if (code == KC_MS_RIGHT) - mouse_report.x = move_unit(); + mouse_report.x = move_unit_x(); # endif // inertia or not diff --git a/quantum/mousekey.h b/quantum/mousekey.h index 73380b743a7b..f7b69862141f 100644 --- a/quantum/mousekey.h +++ b/quantum/mousekey.h @@ -120,6 +120,10 @@ along with this program. If not, see . # define MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS 8 # endif +#ifndef MOUSEKEY_VARIABLE +# define MOUSEKEY_VARIABLE 0 +#endif + #else /* #ifndef MK_3_SPEED */ # ifndef MK_C_OFFSET_UNMOD @@ -190,6 +194,8 @@ void mousekey_on(uint8_t code); void mousekey_off(uint8_t code); void mousekey_clear(void); void mousekey_send(void); +void mousekey_set_speed_x(uint8_t); +void mousekey_set_speed_y(uint8_t); report_mouse_t mousekey_get_report(void); bool should_mousekey_report_send(report_mouse_t *mouse_report); From e0f1d2143670909442b51535824de243fb42c634 Mon Sep 17 00:00:00 2001 From: Bjonnh Date: Sat, 7 Dec 2024 21:14:50 -0600 Subject: [PATCH 2/2] Support for hall effect mouse keys: wheel support Also refactors the code a little --- .../common/analog_matrix/analog_matrix_scan.c | 25 +++++-- keyboards/keychron/common/keychron_common.c | 42 +++++++---- keyboards/keychron/common/keychron_common.h | 3 +- quantum/mousekey.c | 69 ++++++++++--------- quantum/mousekey.h | 2 + 5 files changed, 86 insertions(+), 55 deletions(-) diff --git a/keyboards/keychron/common/analog_matrix/analog_matrix_scan.c b/keyboards/keychron/common/analog_matrix/analog_matrix_scan.c index 63cbefd51832..1fe892c6c49e 100644 --- a/keyboards/keychron/common/analog_matrix/analog_matrix_scan.c +++ b/keyboards/keychron/common/analog_matrix/analog_matrix_scan.c @@ -163,21 +163,34 @@ void matrix_read_rows_on_col(uint8_t current_col, matrix_row_t row_shifter) { if ((analog_raw_matrix[row_index] & row_mask) == 0) changed = true; - if (is_mouse_key(current_col, row_index)) { + uint16_t mouse_keycode = is_mouse_key(current_col, row_index); + if (mouse_keycode>0) { uint8_t travel = analog_matrix_get_travel(row_index, current_col)/TRAVEL_SCALE; uint8_t mouse_speed = ((travel * travel + travel) * 4) / 100; if (mouse_speed == 0) mouse_speed = 1; if (mouse_speed > 200) mouse_speed = 200; - if (is_vertical_mouse_key(current_col, row_index)) { - mousekey_set_speed_y(mouse_speed); - } else { - mousekey_set_speed_x(mouse_speed); + switch (mouse_keycode) { + case KC_MS_UP: + case KC_MS_DOWN: + mousekey_set_speed_y(mouse_speed); + break; + case KC_MS_LEFT: + case KC_MS_RIGHT: + mousekey_set_speed_x(mouse_speed); + break; + case KC_MS_WH_UP: + case KC_MS_WH_DOWN: + mousekey_set_speed_v(mouse_speed); + break; + case KC_MS_WH_LEFT: + case KC_MS_WH_RIGHT: + mousekey_set_speed_h(mouse_speed); + break; } } - if (debouce_times == ANALOG_DEBOUCE_TIME) { row_value |= (0x01 << row_index); } else { diff --git a/keyboards/keychron/common/keychron_common.c b/keyboards/keychron/common/keychron_common.c index b83b7dc8eda4..65ae9814777d 100644 --- a/keyboards/keychron/common/keychron_common.c +++ b/keyboards/keychron/common/keychron_common.c @@ -52,33 +52,33 @@ static key_combination_t key_comb_list[4] = { typedef struct { uint8_t col; uint8_t row; + uint16_t keycode; } key_pos_t; -// An array for the 4 keys, all set to 255, 255 by default using key_post_t -key_pos_t mouse_keys_pos[4] = { - {255, 255}, - {255, 255}, - {255, 255}, - {255, 255}, +key_pos_t mouse_keys_pos[8] = { + {255, 255, KC_MS_UP}, + {255, 255, KC_MS_DOWN}, + {255, 255, KC_MS_LEFT}, + {255, 255, KC_MS_RIGHT}, + {255, 255, KC_MS_WH_UP}, + {255, 255, KC_MS_WH_DOWN}, + {255, 255, KC_MS_WH_LEFT}, + {255, 255, KC_MS_WH_RIGHT}, }; void set_mouse_key_last_key_pos(uint8_t pos, uint8_t col, uint8_t row) { - if (pos>3) return; + if (pos>7) return; mouse_keys_pos[pos].col = col; mouse_keys_pos[pos].row = row; } -inline bool is_mouse_key(uint8_t col, uint8_t row) { - for (uint8_t i = 0; i < 4; i++) { +uint16_t is_mouse_key(uint8_t col, uint8_t row) { + for (uint8_t i = 0; i < 8; i++) { if (mouse_keys_pos[i].col == col && mouse_keys_pos[i].row == row) { - return true; + return mouse_keys_pos[i].keycode; } } - return false; -} - -inline bool is_vertical_mouse_key(uint8_t col, uint8_t row) { - return (mouse_keys_pos[0].col == col && mouse_keys_pos[0].row == row) || (mouse_keys_pos[1].col == col && mouse_keys_pos[1].row == row); + return 0; } bool process_record_keychron_common(uint16_t keycode, keyrecord_t *record) { @@ -145,6 +145,18 @@ bool process_record_keychron_common(uint16_t keycode, keyrecord_t *record) { case KC_MS_RIGHT: set_mouse_key_last_key_pos(3, record->event.key.col, record->event.key.row); break; + case KC_MS_WH_UP: + set_mouse_key_last_key_pos(4, record->event.key.col, record->event.key.row); + break; + case KC_MS_WH_DOWN: + set_mouse_key_last_key_pos(5, record->event.key.col, record->event.key.row); + break; + case KC_MS_WH_LEFT: + set_mouse_key_last_key_pos(6, record->event.key.col, record->event.key.row); + break; + case KC_MS_WH_RIGHT: + set_mouse_key_last_key_pos(7, record->event.key.col, record->event.key.row); + break; default: #ifdef ANANLOG_MATRIX return process_record_profile( keycode, record); diff --git a/keyboards/keychron/common/keychron_common.h b/keyboards/keychron/common/keychron_common.h index f3f90eb93b8e..d7681b628c63 100644 --- a/keyboards/keychron/common/keychron_common.h +++ b/keyboards/keychron/common/keychron_common.h @@ -90,8 +90,7 @@ void keychron_common_task(void); void set_mouse_vertical_last_key_pos(uint8_t col, uint8_t row); void set_mouse_horizontal_last_key_pos(uint8_t col, uint8_t row); void set_mouse_key_last_key_pos(uint8_t pos, uint8_t col, uint8_t row); -bool is_mouse_key(uint8_t col, uint8_t row); -bool is_vertical_mouse_key(uint8_t col, uint8_t row); +uint16_t is_mouse_key(uint8_t col, uint8_t row); #ifdef ENCODER_ENABLE void encoder_cb_init(void); diff --git a/quantum/mousekey.c b/quantum/mousekey.c index 13ef868ae3da..267eb171041d 100644 --- a/quantum/mousekey.c +++ b/quantum/mousekey.c @@ -45,6 +45,9 @@ static uint8_t mousekey_wheel_repeat = 0; static uint8_t mousekey_variable = MOUSEKEY_VARIABLE; static uint8_t mousekey_speed_x = 1; static uint8_t mousekey_speed_y = 1; +static uint8_t mousekey_speed_h = 1; +static uint8_t mousekey_speed_v = 1; +# #ifdef MOUSEKEY_INERTIA static uint8_t mousekey_frame = 0; // track whether gesture is inactive, first frame, or repeating static int8_t mousekey_x_dir = 0; // -1 / 0 / 1 = left / neutral / right @@ -95,9 +98,15 @@ uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; /* Default accelerated mode */ -static uint8_t move_unit(void) { +static uint8_t move_unit(uint8_t axis) { uint16_t unit; - if (mousekey_accel & (1 << 0)) { + if (mousekey_variable) { + if (axis) { + unit = mousekey_speed_x; + } else { + unit = mousekey_speed_y; + } + } else if (mousekey_accel & (1 << 0)) { unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4; } else if (mousekey_accel & (1 << 1)) { unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2; @@ -113,6 +122,8 @@ static uint8_t move_unit(void) { return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit)); } +/* Used to set acceleration from other means such as hall effect */ + void mousekey_set_speed_x(uint8_t speed) { mousekey_speed_x = speed; } @@ -121,24 +132,12 @@ void mousekey_set_speed_y(uint8_t speed) { mousekey_speed_y = speed; } -static uint8_t move_unit_x(void) { - uint16_t unit; - if (mousekey_variable) { - unit = mousekey_speed_x; - } else { - unit = move_unit(); - } - return unit; +void mousekey_set_speed_h(uint8_t speed) { + mousekey_speed_h = speed; } -static uint8_t move_unit_y(void) { - uint16_t unit; - if (mousekey_variable) { - unit = mousekey_speed_y; - } else { - unit = move_unit(); - } - return unit; +void mousekey_set_speed_v(uint8_t speed) { + mousekey_speed_v = speed; } # else // MOUSEKEY_INERTIA mode @@ -188,9 +187,15 @@ static int8_t move_unit(uint8_t axis) { # endif // end MOUSEKEY_INERTIA mode -static uint8_t wheel_unit(void) { +static uint8_t wheel_unit(uint8_t axis) { uint16_t unit; - if (mousekey_accel & (1 << 0)) { + if (mousekey_variable) { + if (axis) { + unit = mousekey_speed_h; + } else { + unit = mousekey_speed_v; + } + } else if (mousekey_accel & (1 << 0)) { unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 4; } else if (mousekey_accel & (1 << 1)) { unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2; @@ -372,8 +377,8 @@ void mousekey_task(void) { if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) { if (mousekey_repeat != UINT8_MAX) mousekey_repeat++; - if (tmpmr.x != 0) mouse_report.x = move_unit_x() * ((tmpmr.x > 0) ? 1 : -1); - if (tmpmr.y != 0) mouse_report.y = move_unit_y() * ((tmpmr.y > 0) ? 1 : -1); + if (tmpmr.x != 0) mouse_report.x = move_unit(1) * ((tmpmr.x > 0) ? 1 : -1); + if (tmpmr.y != 0) mouse_report.y = move_unit(0) * ((tmpmr.y > 0) ? 1 : -1); /* diagonal move [1/sqrt(2)] */ if (mouse_report.x && mouse_report.y) { @@ -392,8 +397,8 @@ void mousekey_task(void) { if ((tmpmr.v || tmpmr.h) && timer_elapsed(last_timer_w) > (mousekey_wheel_repeat ? mk_wheel_interval : mk_wheel_delay * 10)) { if (mousekey_wheel_repeat != UINT8_MAX) mousekey_wheel_repeat++; - if (tmpmr.v != 0) mouse_report.v = wheel_unit() * ((tmpmr.v > 0) ? 1 : -1); - if (tmpmr.h != 0) mouse_report.h = wheel_unit() * ((tmpmr.h > 0) ? 1 : -1); + if (tmpmr.v != 0) mouse_report.v = wheel_unit(0) * ((tmpmr.v > 0) ? 1 : -1); + if (tmpmr.h != 0) mouse_report.h = wheel_unit(1) * ((tmpmr.h > 0) ? 1 : -1); /* diagonal move [1/sqrt(2)] */ if (mouse_report.v && mouse_report.h) { @@ -449,24 +454,24 @@ void mousekey_on(uint8_t code) { # else // no inertia if (code == KC_MS_UP) - mouse_report.y = move_unit_y() * -1; + mouse_report.y = move_unit(0) * -1; else if (code == KC_MS_DOWN) - mouse_report.y = move_unit_y(); + mouse_report.y = move_unit(0); else if (code == KC_MS_LEFT) - mouse_report.x = move_unit_x() * -1; + mouse_report.x = move_unit(1) * -1; else if (code == KC_MS_RIGHT) - mouse_report.x = move_unit_x(); + mouse_report.x = move_unit(1); # endif // inertia or not else if (code == KC_MS_WH_UP) - mouse_report.v = wheel_unit(); + mouse_report.v = wheel_unit(0); else if (code == KC_MS_WH_DOWN) - mouse_report.v = wheel_unit() * -1; + mouse_report.v = wheel_unit(0) * -1; else if (code == KC_MS_WH_LEFT) - mouse_report.h = wheel_unit() * -1; + mouse_report.h = wheel_unit(1) * -1; else if (code == KC_MS_WH_RIGHT) - mouse_report.h = wheel_unit(); + mouse_report.h = wheel_unit(1); else if (IS_MOUSEKEY_BUTTON(code)) mouse_report.buttons |= 1 << (code - KC_MS_BTN1); else if (code == KC_MS_ACCEL0) diff --git a/quantum/mousekey.h b/quantum/mousekey.h index f7b69862141f..268b2496c280 100644 --- a/quantum/mousekey.h +++ b/quantum/mousekey.h @@ -196,6 +196,8 @@ void mousekey_clear(void); void mousekey_send(void); void mousekey_set_speed_x(uint8_t); void mousekey_set_speed_y(uint8_t); +void mousekey_set_speed_h(uint8_t); +void mousekey_set_speed_v(uint8_t); report_mouse_t mousekey_get_report(void); bool should_mousekey_report_send(report_mouse_t *mouse_report);