From f5aa0bf3f05a3461172c488c7a16701fa68063f6 Mon Sep 17 00:00:00 2001 From: Mark Stosberg Date: Tue, 3 Jun 2025 17:54:52 -0400 Subject: [PATCH] keyboard:aki27/cocot46plus smooth trackball scrolling From upstream, which updated their mouse handling: https://github.com/aki27kbd/qmk_firmware/blob/master/keyboards/aki27/cocot46plus/cocot46plus.c#L71 --- keyboards/aki27/cocot46plus/cocot46plus.c | 103 ++++++++++++++-------- 1 file changed, 64 insertions(+), 39 deletions(-) diff --git a/keyboards/aki27/cocot46plus/cocot46plus.c b/keyboards/aki27/cocot46plus/cocot46plus.c index 12772830864..dad0e164a11 100644 --- a/keyboards/aki27/cocot46plus/cocot46plus.c +++ b/keyboards/aki27/cocot46plus/cocot46plus.c @@ -62,11 +62,6 @@ int8_t angle_array[] = COCOT_ROTATION_ANGLE; bool BurstState = false; // init burst state for Trackball module uint16_t MotionStart = 0; // Timer for accel, 0 is resting state -// Scroll Accumulation -static int16_t h_acm = 0; -static int16_t v_acm = 0; - - void pointing_device_init_kb(void) { // set the CPI. pointing_device_set_cpi(cpi_array[cocot_config.cpi_idx]); @@ -75,52 +70,82 @@ void pointing_device_init_kb(void) { } report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) { + static float x_accumulator = 0.0; + static float y_accumulator = 0.0; + static float prev_x = 0.0, prev_y = 0.0; + float sensitivity = 0.5; // Movement sensitivity + float smoothing_factor = 0.7; // Smoothing factor + float sensitivity_multiplier = 1.5; // Sensitivity adjustment multiplier + + // Apply rotation angle adjustment double rad = (double)angle_array[cocot_config.rotation_angle] * (M_PI / 180) * -1; - int8_t x_rev = + mouse_report.x * cos(rad) - mouse_report.y * sin(rad); - int8_t y_rev = + mouse_report.x * sin(rad) + mouse_report.y * cos(rad); + float rotated_x = mouse_report.x * cos(rad) - mouse_report.y * sin(rad); + float rotated_y = mouse_report.x * sin(rad) + mouse_report.y * cos(rad); + // Apply smoothing to the rotated values + float smoothed_x = prev_x * smoothing_factor + rotated_x * (1.0 - smoothing_factor); + float smoothed_y = prev_y * smoothing_factor + rotated_y * (1.0 - smoothing_factor); + prev_x = smoothed_x; + prev_y = smoothed_y; + + // Apply sensitivity multiplier + smoothed_x *= sensitivity_multiplier; + smoothed_y *= sensitivity_multiplier; + + // Scroll mode handling if (cocot_get_scroll_mode()) { - // rock scroll direction - if (abs(x_rev) > abs(y_rev)) { - y_rev = 0; + static int h_acm = 0, v_acm = 0; + + // Determine scroll direction + if (abs((int)smoothed_x) > abs((int)smoothed_y)) { + smoothed_y = 0; // Horizontal scroll } else { - x_rev = 0; + smoothed_x = 0; // Vertical scroll } - // accumulate scroll - h_acm += x_rev * cocot_config.scrl_inv; - v_acm += y_rev * cocot_config.scrl_inv * -1; - - int8_t h_rev = h_acm >> scrl_div_array[cocot_config.scrl_div]; - int8_t v_rev = v_acm >> scrl_div_array[cocot_config.scrl_div]; - - // clear accumulated scroll on assignment - - if (h_rev != 0) { - if (mouse_report.h + h_rev > 127) { - h_rev = 127 - mouse_report.h; - } else if (mouse_report.h + h_rev < -127) { - h_rev = -127 - mouse_report.h; - } - mouse_report.h += h_rev; - h_acm -= h_rev << scrl_div_array[cocot_config.scrl_div]; - } - if (v_rev != 0) { - if (mouse_report.v + v_rev > 127) { - v_rev = 127 - mouse_report.v; - } else if (mouse_report.v + v_rev < -127) { - v_rev = -127 - mouse_report.v; - } - mouse_report.v += v_rev; - v_acm -= v_rev << scrl_div_array[cocot_config.scrl_div]; + // Accumulate scroll values + if (cocot_config.scrl_inv > 0) { + h_acm += smoothed_x; + v_acm -= smoothed_y; + } else { + h_acm -= smoothed_x; + v_acm += smoothed_y; } + // Calculate scroll values with division factor + int8_t h_scroll = h_acm >> scrl_div_array[cocot_config.scrl_div]; + int8_t v_scroll = v_acm >> scrl_div_array[cocot_config.scrl_div]; + + // Apply scroll to mouse report + if (h_scroll != 0) { + mouse_report.h += h_scroll; + h_acm -= h_scroll << scrl_div_array[cocot_config.scrl_div]; + } + if (v_scroll != 0) { + mouse_report.v += v_scroll; + v_acm -= v_scroll << scrl_div_array[cocot_config.scrl_div]; + } + + // Reset X/Y movement in scroll mode mouse_report.x = 0; mouse_report.y = 0; } else { - mouse_report.x = x_rev; - mouse_report.y = y_rev; + // Movement smoothing and accumulation for normal mode + x_accumulator += smoothed_x * sensitivity; + y_accumulator += smoothed_y * sensitivity; + if (fabs(x_accumulator) >= 1.0) { + mouse_report.x = (int8_t)x_accumulator; + x_accumulator -= mouse_report.x; + } else { + mouse_report.x = 0; + } + if (fabs(y_accumulator) >= 1.0) { + mouse_report.y = (int8_t)y_accumulator; + y_accumulator -= mouse_report.y; + } else { + mouse_report.y = 0; + } } return pointing_device_task_user(mouse_report);