From 6f364e3c0e1bf858ee19ec978fd4114265b06f5d Mon Sep 17 00:00:00 2001 From: Wimads <50098220+Wimads@users.noreply.github.com> Date: Sun, 18 Feb 2024 22:49:52 +0100 Subject: [PATCH 01/17] Add z variable, and update math --- maccel/maccel.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index 422d5cfc3916..9ca745d2ad18 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -29,6 +29,11 @@ static uint32_t maccel_timer; #ifndef MACCEL_LIMIT # define MACCEL_LIMIT 4.5 // upper limit of accel curve #endif +#ifndef MACCEL_Z //needs a better name; and maccel_steepness is now also confusing... maybe maccel_smoothing_start and maccel_smoothing_end? +# define MACCEL_Z 4 //steepnesss at start of accel curve +#endif + +static float g_maccel_config_z = MACCEL_Z; //@burkfers: turn this into g_maccel_config.z like the other variables maccel_config_t g_maccel_config = { // clang-format off @@ -137,10 +142,7 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { // calculate delta velocity: dv = dpi_correction * sqrt(dx^2 + dy^2)/dt const float velocity = dpi_correction * (sqrtf(mouse_report.x * mouse_report.x + mouse_report.y * mouse_report.y)) / delta_time; // calculate mouse acceleration factor: f(dv) = c - (c - 1) * e^(-(dv - b) * a) - float maccel_factor = g_maccel_config.c - (g_maccel_config.c - 1) * expf(-1 * (velocity - g_maccel_config.b) * g_maccel_config.a); - if (maccel_factor <= 1) { // cut-off acceleration curve below maccel_factor = 1 - maccel_factor = 1; - } + float maccel_factor = g_maccel_config.c - (g_maccel_config.c - 1) / powf(1 + expf(g_maccel_config_z*(velocity - g_maccel_config.b)), g_maccel_config.a / g_maccel_config_z); // calculate accelerated delta X and Y values and clamp: const mouse_xy_report_t x = CONSTRAIN_REPORT(mouse_report.x * maccel_factor); const mouse_xy_report_t y = CONSTRAIN_REPORT(mouse_report.y * maccel_factor); From 6071dd0f595c06361118b4409564bba81d66edf8 Mon Sep 17 00:00:00 2001 From: Wimads <50098220+Wimads@users.noreply.github.com> Date: Mon, 19 Feb 2024 01:55:28 +0100 Subject: [PATCH 02/17] Rename variables more logically for new curve --- maccel/maccel.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index 9ca745d2ad18..f63e3b5211cc 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -20,20 +20,20 @@ static uint32_t maccel_timer; -#ifndef MACCEL_STEEPNESS -# define MACCEL_STEEPNESS 0.4 // steepness of accel curve +#ifndef MACCEL_START_RATE +# define MACCEL_START_RATE 2.0 // higher value = accel curve takes off more abrubtly +#endif +#ifndef MACCEL_GROWTH_RATE +# define MACCEL_GROWTH_RATE 0.25 // higher value = curve reaches its limit faster #endif #ifndef MACCEL_OFFSET -# define MACCEL_OFFSET 1.1 // start offset of accel curve +# define MACCEL_OFFSET 2.2 // higher value = shifts whole curve to the right, so acceleration kicks in later #endif #ifndef MACCEL_LIMIT -# define MACCEL_LIMIT 4.5 // upper limit of accel curve -#endif -#ifndef MACCEL_Z //needs a better name; and maccel_steepness is now also confusing... maybe maccel_smoothing_start and maccel_smoothing_end? -# define MACCEL_Z 4 //steepnesss at start of accel curve +# define MACCEL_LIMIT 6.0 // upper limit of accel curve #endif -static float g_maccel_config_z = MACCEL_Z; //@burkfers: turn this into g_maccel_config.z like the other variables +static float g_maccel_config_z = MACCEL_START_RATE; //@burkfers: turn this into g_maccel_config.z like the other variables maccel_config_t g_maccel_config = { // clang-format off @@ -150,7 +150,7 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { // console output for debugging (enable/disable in config.h) #ifdef MACCEL_DEBUG float accelerated = velocity * maccel_factor; // resulting velocity after acceleration; unneccesary for calculation, but nice for debug console - printf("MACCEL: DPI = %i, Steepn. = %f, Offset = %f, Limit = %f | Factor = %4f, Veloc.in = %4f, Veloc.out = %4f\n", device_cpi, g_maccel_config.a, g_maccel_config.b, g_maccel_config.c, maccel_factor, velocity, accelerated); + printf("MACCEL: DPI = %i, Start = %f, Growth = %f, Offset = %f, Limit = %f | Factor = %4f, Veloc.in = %4f, Veloc.out = %4f\n", device_cpi, g_maccel_config_z, g_maccel_config.a, g_maccel_config.b, g_maccel_config.c, maccel_factor, velocity, accelerated); #endif // MACCEL_DEBUG // report back accelerated values From ce7f2fb24fedcea50262898131eb1dc57f302825 Mon Sep 17 00:00:00 2001 From: Wimads <50098220+Wimads@users.noreply.github.com> Date: Mon, 19 Feb 2024 02:07:56 +0100 Subject: [PATCH 03/17] Clearer comments explaining variables findreplace steepness growth_rate findreplace steepness growthrate findreplace steepness growthrate --- maccel/maccel.c | 32 ++++++++++++++++---------------- maccel/maccel.h | 6 +++--- maccel/maccel_via.c | 8 ++++---- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index f63e3b5211cc..4e96d9fb0cdd 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -21,23 +21,23 @@ static uint32_t maccel_timer; #ifndef MACCEL_START_RATE -# define MACCEL_START_RATE 2.0 // higher value = accel curve takes off more abrubtly +# define MACCEL_START_RATE 2.0 // lower/higher value = curve starts more smoothly/abrubtly #endif #ifndef MACCEL_GROWTH_RATE -# define MACCEL_GROWTH_RATE 0.25 // higher value = curve reaches its limit faster +# define MACCEL_GROWTH_RATE 0.25 // lower/higher value = curve reaches its upper limit slower/faster #endif #ifndef MACCEL_OFFSET -# define MACCEL_OFFSET 2.2 // higher value = shifts whole curve to the right, so acceleration kicks in later +# define MACCEL_OFFSET 2.2 // lower/higher value = acceleration kicks in earlier/later #endif #ifndef MACCEL_LIMIT -# define MACCEL_LIMIT 6.0 // upper limit of accel curve +# define MACCEL_LIMIT 6.0 // upper limit of accel curve (maximum acceleration factor) #endif static float g_maccel_config_z = MACCEL_START_RATE; //@burkfers: turn this into g_maccel_config.z like the other variables maccel_config_t g_maccel_config = { // clang-format off - .a = MACCEL_STEEPNESS, + .a = MACCEL_GROWTH_RATE, .b = MACCEL_OFFSET, .c = MACCEL_LIMIT, .enabled = true @@ -67,8 +67,8 @@ A device specific parameter required to ensure consistent acceleration behaviour #endif #ifdef MACCEL_USE_KEYCODES -# ifndef MACCEL_STEEPNESS_STEP -# define MACCEL_STEEPNESS_STEP 0.01f +# ifndef MACCEL_GROWTH_RATE_STEP +# define MACCEL_GROWTH_RATE_STEP 0.01f # endif # ifndef MACCEL_OFFSET_STEP # define MACCEL_OFFSET_STEP 0.1f @@ -78,7 +78,7 @@ A device specific parameter required to ensure consistent acceleration behaviour # endif #endif -float maccel_get_steepness(void) { +float maccel_get_growthrate(void) { return g_maccel_config.a; } float maccel_get_offset(void) { @@ -87,7 +87,7 @@ float maccel_get_offset(void) { float maccel_get_limit(void) { return g_maccel_config.c; } -void maccel_set_steepness(float val) { +void maccel_set_growthrate(float val) { if (val >= 0) { // value less 0 leads to nonsensical results g_maccel_config.a = val; } @@ -172,28 +172,28 @@ static inline float get_mod_step(float step) { return step; } -bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t steepness, uint16_t offset, uint16_t limit) { +bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t growthrate, uint16_t offset, uint16_t limit) { if (record->event.pressed) { - if (keycode == steepness) { - maccel_set_steepness(maccel_get_steepness() + get_mod_step(MACCEL_STEEPNESS_STEP)); - printf("MACCEL:keycode: STEEPNESS: %f, offset: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + if (keycode == growthrate) { + maccel_set_growthrate(maccel_get_growthrate() + get_mod_step(MACCEL_GROWTH_RATE_STEP)); + printf("MACCEL:keycode: growthrate: %f, offset: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); return false; } if (keycode == offset) { maccel_set_offset(maccel_get_offset() + get_mod_step(MACCEL_OFFSET_STEP)); - printf("MACCEL:keycode: steepness: %f, OFFSET: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:keycode: growthrate: %f, OFFSET: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); return false; } if (keycode == limit) { maccel_set_limit(maccel_get_limit() + get_mod_step(MACCEL_LIMIT_STEP)); - printf("MACCEL:keycode: steepness: %f, offset: %f, LIMIT: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:keycode: growthrate: %f, offset: %f, LIMIT: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); return false; } } return true; } #else -bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t steepness, uint16_t offset, uint16_t limit) { +bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t growthrate, uint16_t offset, uint16_t limit) { // provide a do-nothing keyrecord function so a user doesn't need to unshim when disabling the keycodes return true; } diff --git a/maccel/maccel.h b/maccel/maccel.h index ef0baf5ad10f..74127a9835ea 100644 --- a/maccel/maccel.h +++ b/maccel/maccel.h @@ -21,7 +21,7 @@ #define MACCEL_USE_KEYCODES report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report); -bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t steepness, uint16_t offset, uint16_t limit); +bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t growthrate, uint16_t offset, uint16_t limit); typedef struct _maccel_config_t { float a; @@ -36,10 +36,10 @@ void maccel_enabled(bool enable); bool maccel_get_enabled(void); void maccel_toggle_enabled(void); -float maccel_get_steepness(void); +float maccel_get_growthrate(void); float maccel_get_offset(void); float maccel_get_limit(void); -void maccel_set_steepness(float val); +void maccel_set_growthrate(float val); void maccel_set_offset(float val); void maccel_set_limit(float val); diff --git a/maccel/maccel_via.c b/maccel/maccel_via.c index bd7c1e8a5fce..6bfe56b73459 100644 --- a/maccel/maccel_via.c +++ b/maccel/maccel_via.c @@ -45,10 +45,10 @@ void maccel_config_set_value(uint8_t *data) { case id_maccel_a: { uint16_t a = COMBINE_UINT8(value_data[0], value_data[1]); - // calc uint16 to float: steepness only moves the comma + // calc uint16 to float: growthrate only moves the comma g_maccel_config.a = a / 10000.0f; #ifdef MACCEL_DEBUG - printf("MACCEL:via: STEEPNESS: %f, offset: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:via: GROWTHRATE: %f, offset: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); #endif break; } @@ -58,7 +58,7 @@ void maccel_config_set_value(uint8_t *data) { // calc uint16 to float: offset moves comma and shifts by 3, so that -3..3 fits into 0..60k g_maccel_config.b = (b / 10000.0f) - 3; #ifdef MACCEL_DEBUG - printf("MACCEL:via: steepness: %f, OFFSET: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:via: growthrate: %f, OFFSET: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); #endif break; } @@ -68,7 +68,7 @@ void maccel_config_set_value(uint8_t *data) { // calc uint16 to float: offset moves comma, divides by 2 and shifts by 1, so that 1..14 fits into 0..60k g_maccel_config.c = (c / 5000.0f) + 1; #ifdef MACCEL_DEBUG - printf("MACCEL:via: steepness: %f, offset: %f, LIMIT: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:via: growthrate: %f, offset: %f, LIMIT: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); #endif break; } From 4f054e61ad548ee7c1b04aaac06d7ae9d4bbbbcc Mon Sep 17 00:00:00 2001 From: burkfers Date: Mon, 19 Feb 2024 17:01:08 +0100 Subject: [PATCH 04/17] rename parameters to more speaking names --- maccel/maccel.c | 41 ++++++++++++++++---------------- maccel/maccel.h | 7 +++--- maccel/maccel_via.c | 58 ++++++++++++++++++++++----------------------- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index 4e96d9fb0cdd..08beee0e3c41 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -20,27 +20,26 @@ static uint32_t maccel_timer; -#ifndef MACCEL_START_RATE -# define MACCEL_START_RATE 2.0 // lower/higher value = curve starts more smoothly/abrubtly +#ifndef MACCEL_TAKEOFF +# define MACCEL_TAKEOFF 2.0 // lower/higher value = curve starts more smoothly/abrubtly #endif #ifndef MACCEL_GROWTH_RATE # define MACCEL_GROWTH_RATE 0.25 // lower/higher value = curve reaches its upper limit slower/faster #endif #ifndef MACCEL_OFFSET -# define MACCEL_OFFSET 2.2 // lower/higher value = acceleration kicks in earlier/later +# define MACCEL_OFFSET 2.2 // lower/higher value = acceleration kicks in earlier/later #endif #ifndef MACCEL_LIMIT -# define MACCEL_LIMIT 6.0 // upper limit of accel curve (maximum acceleration factor) +# define MACCEL_LIMIT 6.0 // upper limit of accel curve (maximum acceleration factor) #endif -static float g_maccel_config_z = MACCEL_START_RATE; //@burkfers: turn this into g_maccel_config.z like the other variables - maccel_config_t g_maccel_config = { // clang-format off - .a = MACCEL_GROWTH_RATE, - .b = MACCEL_OFFSET, - .c = MACCEL_LIMIT, - .enabled = true + .growth_rate = MACCEL_GROWTH_RATE, + .offset = MACCEL_OFFSET, + .limit = MACCEL_LIMIT, + .takeoff = MACCEL_TAKEOFF, + .enabled = true // clang-format on }; @@ -79,25 +78,25 @@ A device specific parameter required to ensure consistent acceleration behaviour #endif float maccel_get_growthrate(void) { - return g_maccel_config.a; + return g_maccel_config.growth_rate; } float maccel_get_offset(void) { - return g_maccel_config.b; + return g_maccel_config.limit; } float maccel_get_limit(void) { - return g_maccel_config.c; + return g_maccel_config.limit; } void maccel_set_growthrate(float val) { if (val >= 0) { // value less 0 leads to nonsensical results - g_maccel_config.a = val; + g_maccel_config.growth_rate = val; } } void maccel_set_offset(float val) { - g_maccel_config.b = val; + g_maccel_config.limit = val; } void maccel_set_limit(float val) { if (val >= 1) { // limit less than 1 leads to nonsensical results - g_maccel_config.c = val; + g_maccel_config.limit = val; } } @@ -142,7 +141,7 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { // calculate delta velocity: dv = dpi_correction * sqrt(dx^2 + dy^2)/dt const float velocity = dpi_correction * (sqrtf(mouse_report.x * mouse_report.x + mouse_report.y * mouse_report.y)) / delta_time; // calculate mouse acceleration factor: f(dv) = c - (c - 1) * e^(-(dv - b) * a) - float maccel_factor = g_maccel_config.c - (g_maccel_config.c - 1) / powf(1 + expf(g_maccel_config_z*(velocity - g_maccel_config.b)), g_maccel_config.a / g_maccel_config_z); + float maccel_factor = g_maccel_config.limit - (g_maccel_config.limit - 1) / powf(1 + expf(g_maccel_config.takeoff * (velocity - g_maccel_config.limit)), g_maccel_config.growth_rate / g_maccel_config.takeoff); // calculate accelerated delta X and Y values and clamp: const mouse_xy_report_t x = CONSTRAIN_REPORT(mouse_report.x * maccel_factor); const mouse_xy_report_t y = CONSTRAIN_REPORT(mouse_report.y * maccel_factor); @@ -150,7 +149,7 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { // console output for debugging (enable/disable in config.h) #ifdef MACCEL_DEBUG float accelerated = velocity * maccel_factor; // resulting velocity after acceleration; unneccesary for calculation, but nice for debug console - printf("MACCEL: DPI = %i, Start = %f, Growth = %f, Offset = %f, Limit = %f | Factor = %4f, Veloc.in = %4f, Veloc.out = %4f\n", device_cpi, g_maccel_config_z, g_maccel_config.a, g_maccel_config.b, g_maccel_config.c, maccel_factor, velocity, accelerated); + printf("MACCEL: DPI = %i, Start = %f, Growth = %f, Offset = %f, Limit = %f | Factor = %4f, Veloc.in = %4f, Veloc.out = %4f\n", device_cpi, g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit, maccel_factor, velocity, accelerated); #endif // MACCEL_DEBUG // report back accelerated values @@ -176,17 +175,17 @@ bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t growt if (record->event.pressed) { if (keycode == growthrate) { maccel_set_growthrate(maccel_get_growthrate() + get_mod_step(MACCEL_GROWTH_RATE_STEP)); - printf("MACCEL:keycode: growthrate: %f, offset: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:keycode: growthrate: %f, offset: %f, limit: %f\n", g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); return false; } if (keycode == offset) { maccel_set_offset(maccel_get_offset() + get_mod_step(MACCEL_OFFSET_STEP)); - printf("MACCEL:keycode: growthrate: %f, OFFSET: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:keycode: growthrate: %f, OFFSET: %f, limit: %f\n", g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); return false; } if (keycode == limit) { maccel_set_limit(maccel_get_limit() + get_mod_step(MACCEL_LIMIT_STEP)); - printf("MACCEL:keycode: growthrate: %f, offset: %f, LIMIT: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:keycode: growthrate: %f, offset: %f, LIMIT: %f\n", g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); return false; } } diff --git a/maccel/maccel.h b/maccel/maccel.h index 74127a9835ea..c116813a5797 100644 --- a/maccel/maccel.h +++ b/maccel/maccel.h @@ -24,9 +24,10 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report); bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t growthrate, uint16_t offset, uint16_t limit); typedef struct _maccel_config_t { - float a; - float b; - float c; + float growth_rate; + float offset; + float limit; + float takeoff; bool enabled; } maccel_config_t; diff --git a/maccel/maccel_via.c b/maccel/maccel_via.c index 6bfe56b73459..7941f8ee62b9 100644 --- a/maccel/maccel_via.c +++ b/maccel/maccel_via.c @@ -26,10 +26,10 @@ enum via_maccel_channel { }; enum via_maccel_ids { // clang-format off - id_maccel_a = 1, - id_maccel_b = 2, - id_maccel_c = 3, - id_maccel_enabled = 4 + id_maccel_growth_rate = 1, + id_maccel_offset = 2, + id_maccel_limit = 3, + id_maccel_enabled = 4 // clang-format on }; @@ -42,33 +42,33 @@ void maccel_config_set_value(uint8_t *data) { uint8_t *value_data = &(data[1]); switch (*value_id) { - case id_maccel_a: { - uint16_t a = COMBINE_UINT8(value_data[0], value_data[1]); + case id_maccel_growth_rate: { + uint16_t growth_rate = COMBINE_UINT8(value_data[0], value_data[1]); - // calc uint16 to float: growthrate only moves the comma - g_maccel_config.a = a / 10000.0f; + // calc uint16 to float: growth_rate only moves the comma + g_maccel_config.growth_rate = growth_rate / 10000.0f; #ifdef MACCEL_DEBUG - printf("MACCEL:via: GROWTHRATE: %f, offset: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:via: growth_rate: %f, offset: %f, limit: %f\n", g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); #endif break; } - case id_maccel_b: { - uint16_t b = COMBINE_UINT8(value_data[0], value_data[1]); + case id_maccel_offset: { + uint16_t offset = COMBINE_UINT8(value_data[0], value_data[1]); // calc uint16 to float: offset moves comma and shifts by 3, so that -3..3 fits into 0..60k - g_maccel_config.b = (b / 10000.0f) - 3; + g_maccel_config.offset = (offset / 10000.0f) - 3; #ifdef MACCEL_DEBUG - printf("MACCEL:via: growthrate: %f, OFFSET: %f, limit: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:via: growth_rate: %f, OFFSET: %f, limit: %f\n", g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); #endif break; } - case id_maccel_c: { - uint16_t c = COMBINE_UINT8(value_data[0], value_data[1]); + case id_maccel_limit: { + uint16_t limit = COMBINE_UINT8(value_data[0], value_data[1]); // calc uint16 to float: offset moves comma, divides by 2 and shifts by 1, so that 1..14 fits into 0..60k - g_maccel_config.c = (c / 5000.0f) + 1; + g_maccel_config.limit = (limit / 5000.0f) + 1; #ifdef MACCEL_DEBUG - printf("MACCEL:via: growthrate: %f, offset: %f, LIMIT: %f\n", g_maccel_config.a, g_maccel_config.b, g_maccel_config.c); + printf("MACCEL:via: growth_rate: %f, offset: %f, LIMIT: %f\n", g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); #endif break; } @@ -86,22 +86,22 @@ void maccel_config_get_value(uint8_t *data) { uint8_t *value_data = &(data[1]); switch (*value_id) { - case id_maccel_a: { - uint16_t a = g_maccel_config.a * 10000; - value_data[0] = a >> 8; - value_data[1] = a & 0xFF; + case id_maccel_growth_rate: { + uint16_t growth_rate = g_maccel_config.growth_rate * 10000; + value_data[0] = growth_rate >> 8; + value_data[1] = growth_rate & 0xFF; break; } - case id_maccel_b: { - uint16_t b = (g_maccel_config.b + 3) * 10000; - value_data[0] = b >> 8; - value_data[1] = b & 0xFF; + case id_maccel_offset: { + uint16_t offset = (g_maccel_config.offset + 3) * 10000; + value_data[0] = offset >> 8; + value_data[1] = offset & 0xFF; break; } - case id_maccel_c: { - uint16_t c = (g_maccel_config.c - 1) * 5000; - value_data[0] = c >> 8; - value_data[1] = c & 0xFF; + case id_maccel_limit: { + uint16_t limit = (g_maccel_config.limit - 1) * 5000; + value_data[0] = limit >> 8; + value_data[1] = limit & 0xFF; break; } case id_maccel_enabled: { From e7851beb1f1e57eae4cb915feaef28568c93caf5 Mon Sep 17 00:00:00 2001 From: burkfers Date: Tue, 20 Feb 2024 10:27:03 +0100 Subject: [PATCH 05/17] rework debug prints --- maccel/maccel.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index 08beee0e3c41..64d95c496ea4 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -114,7 +114,7 @@ void maccel_toggle_enabled(void) { } #define _CONSTRAIN(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt))) -#define CONSTRAIN_REPORT(val) _CONSTRAIN(val, XY_REPORT_MIN, XY_REPORT_MAX) +#define CONSTRAIN_REPORT(val) (mouse_xy_report_t) _CONSTRAIN(val, XY_REPORT_MIN, XY_REPORT_MAX) report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { if (mouse_report.x != 0 || mouse_report.y != 0) { @@ -138,8 +138,10 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { } // calculate dpi correction factor (for normalizing velocity range across different user dpi settings) const float dpi_correction = (float)100.0f / (DEVICE_CPI_PARAM * device_cpi); - // calculate delta velocity: dv = dpi_correction * sqrt(dx^2 + dy^2)/dt - const float velocity = dpi_correction * (sqrtf(mouse_report.x * mouse_report.x + mouse_report.y * mouse_report.y)) / delta_time; + // calculate euclidean distance moved (sqrt(x^2 + y^2)) + const float distance = sqrtf(mouse_report.x * mouse_report.x + mouse_report.y * mouse_report.y); + // calculate delta velocity: dv = dpi_correction * distance/dt + const float velocity = dpi_correction * distance / delta_time; // calculate mouse acceleration factor: f(dv) = c - (c - 1) * e^(-(dv - b) * a) float maccel_factor = g_maccel_config.limit - (g_maccel_config.limit - 1) / powf(1 + expf(g_maccel_config.takeoff * (velocity - g_maccel_config.limit)), g_maccel_config.growth_rate / g_maccel_config.takeoff); // calculate accelerated delta X and Y values and clamp: @@ -148,8 +150,8 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { // console output for debugging (enable/disable in config.h) #ifdef MACCEL_DEBUG - float accelerated = velocity * maccel_factor; // resulting velocity after acceleration; unneccesary for calculation, but nice for debug console - printf("MACCEL: DPI = %i, Start = %f, Growth = %f, Offset = %f, Limit = %f | Factor = %4f, Veloc.in = %4f, Veloc.out = %4f\n", device_cpi, g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit, maccel_factor, velocity, accelerated); + const float distance_out = sqrtf(x * x + y * y); + printf("MACCEL: DPI:%4i Sta: %.3f Grw: %.3f Ofs: %.3f Lmt: %.3f | Fct: %.3f Vel:%.3f Dst.in:%3i Dst.out:%3i\n", device_cpi, g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit, maccel_factor, velocity, CONSTRAIN_REPORT(distance), CONSTRAIN_REPORT(distance_out)); #endif // MACCEL_DEBUG // report back accelerated values From 007a14b74f6b257b67d3e4c6466117596124511e Mon Sep 17 00:00:00 2001 From: burkfers Date: Tue, 20 Feb 2024 11:20:31 +0100 Subject: [PATCH 06/17] add via support for takeoff param --- maccel/assets/cnano.json | 23 ++++++++++++++++++----- maccel/assets/dilemma_max.json | 23 ++++++++++++++++++----- maccel/assets/via.json | 23 ++++++++++++++++++----- maccel/maccel_via.c | 31 ++++++++++++++++++++++++------- 4 files changed, 78 insertions(+), 22 deletions(-) diff --git a/maccel/assets/cnano.json b/maccel/assets/cnano.json index d3c4148b686d..a3b61d96b21c 100644 --- a/maccel/assets/cnano.json +++ b/maccel/assets/cnano.json @@ -16,22 +16,35 @@ "content": [ "id_maccel_enabled", 24, - 4 + 5 ] }, { - "label": "Steepness", + "label": "Takeoff", "type": "range", "options": [ 0, 60000 ], "content": [ - "id_maccel_steepness", + "id_maccel_takeoff", 24, 1 ] }, + { + "label": "Growth Rate", + "type": "range", + "options": [ + 0, + 60000 + ], + "content": [ + "id_maccel_growth_rate", + 24, + 2 + ] + }, { "label": "Offset", "type": "range", @@ -42,7 +55,7 @@ "content": [ "id_maccel_offset", 24, - 2 + 3 ] }, { @@ -55,7 +68,7 @@ "content": [ "id_maccel_limit", 24, - 3 + 4 ] } ] diff --git a/maccel/assets/dilemma_max.json b/maccel/assets/dilemma_max.json index 494212b869bd..4b156df6df9a 100644 --- a/maccel/assets/dilemma_max.json +++ b/maccel/assets/dilemma_max.json @@ -20,22 +20,35 @@ "content": [ "id_maccel_enabled", 24, - 4 + 5 ] }, { - "label": "Steepness", + "label": "Takeoff", "type": "range", "options": [ 0, 60000 ], "content": [ - "id_maccel_steepness", + "id_maccel_takeoff", 24, 1 ] }, + { + "label": "Growth Rate", + "type": "range", + "options": [ + 0, + 60000 + ], + "content": [ + "id_maccel_growth_rate", + 24, + 2 + ] + }, { "label": "Offset", "type": "range", @@ -46,7 +59,7 @@ "content": [ "id_maccel_offset", 24, - 2 + 3 ] }, { @@ -59,7 +72,7 @@ "content": [ "id_maccel_limit", 24, - 3 + 4 ] } ] diff --git a/maccel/assets/via.json b/maccel/assets/via.json index 792f1205511b..9536c4da44f1 100644 --- a/maccel/assets/via.json +++ b/maccel/assets/via.json @@ -10,22 +10,35 @@ "content": [ "id_maccel_enabled", 24, - 4 + 5 ] }, { - "label": "Steepness", + "label": "Takeoff", "type": "range", "options": [ 0, 60000 ], "content": [ - "id_maccel_steepness", + "id_maccel_takeoff", 24, 1 ] }, + { + "label": "Growth Rate", + "type": "range", + "options": [ + 0, + 60000 + ], + "content": [ + "id_maccel_growth_rate", + 24, + 2 + ] + }, { "label": "Offset", "type": "range", @@ -36,7 +49,7 @@ "content": [ "id_maccel_offset", 24, - 2 + 3 ] }, { @@ -49,7 +62,7 @@ "content": [ "id_maccel_limit", 24, - 3 + 4 ] } ] diff --git a/maccel/maccel_via.c b/maccel/maccel_via.c index 7941f8ee62b9..6fdcdb4c9576 100644 --- a/maccel/maccel_via.c +++ b/maccel/maccel_via.c @@ -26,10 +26,11 @@ enum via_maccel_channel { }; enum via_maccel_ids { // clang-format off - id_maccel_growth_rate = 1, - id_maccel_offset = 2, - id_maccel_limit = 3, - id_maccel_enabled = 4 + id_maccel_takeoff = 1, + id_maccel_growth_rate = 2, + id_maccel_offset = 3, + id_maccel_limit = 4, + id_maccel_enabled = 5 // clang-format on }; @@ -42,13 +43,23 @@ void maccel_config_set_value(uint8_t *data) { uint8_t *value_data = &(data[1]); switch (*value_id) { + case id_maccel_takeoff: { + uint16_t takeoff = COMBINE_UINT8(value_data[0], value_data[1]); + + // calc uint16 to float: takeoff moves comma and shifts by 0.5, so that 0.5..6.5 fits into 0..60k + g_maccel_config.takeoff = (takeoff / 10000.0f) + 0.5; +#ifdef MACCEL_DEBUG + printf("MACCEL:via: TKO: %.3f grw: %.3f ofs: %.3f lmt: %.3f\n", g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); +#endif + break; + } case id_maccel_growth_rate: { uint16_t growth_rate = COMBINE_UINT8(value_data[0], value_data[1]); // calc uint16 to float: growth_rate only moves the comma g_maccel_config.growth_rate = growth_rate / 10000.0f; #ifdef MACCEL_DEBUG - printf("MACCEL:via: growth_rate: %f, offset: %f, limit: %f\n", g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); + printf("MACCEL:via: tko: %.3f GRW: %.3f ofs: %.3f lmt: %.3f\n", g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); #endif break; } @@ -58,7 +69,7 @@ void maccel_config_set_value(uint8_t *data) { // calc uint16 to float: offset moves comma and shifts by 3, so that -3..3 fits into 0..60k g_maccel_config.offset = (offset / 10000.0f) - 3; #ifdef MACCEL_DEBUG - printf("MACCEL:via: growth_rate: %f, OFFSET: %f, limit: %f\n", g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); + printf("MACCEL:via: tko: %.3f grw: %.3f OFS: %.3f lmt: %.3f\n", g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); #endif break; } @@ -68,7 +79,7 @@ void maccel_config_set_value(uint8_t *data) { // calc uint16 to float: offset moves comma, divides by 2 and shifts by 1, so that 1..14 fits into 0..60k g_maccel_config.limit = (limit / 5000.0f) + 1; #ifdef MACCEL_DEBUG - printf("MACCEL:via: growth_rate: %f, offset: %f, LIMIT: %f\n", g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); + printf("MACCEL:via: tko: %.3f grw: %.3f ofs: %.3f LMT: %.3f\n", g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit); #endif break; } @@ -86,6 +97,12 @@ void maccel_config_get_value(uint8_t *data) { uint8_t *value_data = &(data[1]); switch (*value_id) { + case id_maccel_takeoff: { + uint16_t takeoff = (g_maccel_config.takeoff - 0.5) * 5000; + value_data[0] = takeoff >> 8; + value_data[1] = takeoff & 0xFF; + break; + } case id_maccel_growth_rate: { uint16_t growth_rate = g_maccel_config.growth_rate * 10000; value_data[0] = growth_rate >> 8; From 8a597b0860b47db16a7fc1660654021a4d2215c6 Mon Sep 17 00:00:00 2001 From: burkfers Date: Tue, 20 Feb 2024 11:20:47 +0100 Subject: [PATCH 07/17] cleanup --- maccel/maccel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index 64d95c496ea4..e1a7a82b8bfb 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -142,8 +142,8 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { const float distance = sqrtf(mouse_report.x * mouse_report.x + mouse_report.y * mouse_report.y); // calculate delta velocity: dv = dpi_correction * distance/dt const float velocity = dpi_correction * distance / delta_time; - // calculate mouse acceleration factor: f(dv) = c - (c - 1) * e^(-(dv - b) * a) - float maccel_factor = g_maccel_config.limit - (g_maccel_config.limit - 1) / powf(1 + expf(g_maccel_config.takeoff * (velocity - g_maccel_config.limit)), g_maccel_config.growth_rate / g_maccel_config.takeoff); + // calculate mouse acceleration factor: f(dv) = c - ((c-1) / ((1 + e^(x(x - b)) * a/z))) + const float maccel_factor = g_maccel_config.limit - (g_maccel_config.limit - 1) / powf(1 + expf(g_maccel_config.takeoff * (velocity - g_maccel_config.limit)), g_maccel_config.growth_rate / g_maccel_config.takeoff); // calculate accelerated delta X and Y values and clamp: const mouse_xy_report_t x = CONSTRAIN_REPORT(mouse_report.x * maccel_factor); const mouse_xy_report_t y = CONSTRAIN_REPORT(mouse_report.y * maccel_factor); @@ -151,7 +151,7 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { // console output for debugging (enable/disable in config.h) #ifdef MACCEL_DEBUG const float distance_out = sqrtf(x * x + y * y); - printf("MACCEL: DPI:%4i Sta: %.3f Grw: %.3f Ofs: %.3f Lmt: %.3f | Fct: %.3f Vel:%.3f Dst.in:%3i Dst.out:%3i\n", device_cpi, g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit, maccel_factor, velocity, CONSTRAIN_REPORT(distance), CONSTRAIN_REPORT(distance_out)); + printf("MACCEL: DPI:%4i Tko: %.3f Grw: %.3f Ofs: %.3f Lmt: %.3f | Fct: %.3f Vel:%.3f Dst.in:%3i Dst.out:%3i\n", device_cpi, g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit, maccel_factor, velocity, CONSTRAIN_REPORT(distance), CONSTRAIN_REPORT(distance_out)); #endif // MACCEL_DEBUG // report back accelerated values From 8433f9ec4da40e58c760686a0f5aafc557435565 Mon Sep 17 00:00:00 2001 From: burkfers Date: Tue, 20 Feb 2024 11:56:35 +0100 Subject: [PATCH 08/17] add keycodes for takeoff param --- maccel/maccel.c | 34 +++++++++++++++++++++++++--------- maccel/maccel.h | 8 +++++--- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index e1a7a82b8bfb..886702237197 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -66,6 +66,9 @@ A device specific parameter required to ensure consistent acceleration behaviour #endif #ifdef MACCEL_USE_KEYCODES +# ifndef MACCEL_TAKEOFF_STEP +# define MACCEL_TAKEOFF_STEP 0.01f +# endif # ifndef MACCEL_GROWTH_RATE_STEP # define MACCEL_GROWTH_RATE_STEP 0.01f # endif @@ -77,7 +80,10 @@ A device specific parameter required to ensure consistent acceleration behaviour # endif #endif -float maccel_get_growthrate(void) { +float maccel_get_takeoff(void) { + return g_maccel_config.takeoff; +} +float maccel_get_growth_rate(void) { return g_maccel_config.growth_rate; } float maccel_get_offset(void) { @@ -86,7 +92,12 @@ float maccel_get_offset(void) { float maccel_get_limit(void) { return g_maccel_config.limit; } -void maccel_set_growthrate(float val) { +void maccel_set_takeoff(float val) { + if (val >= 0.5) { // value less than 0.5 leads to nonsensical results + g_maccel_config.takeoff = val; + } +} +void maccel_set_growth_rate(float val) { if (val >= 0) { // value less 0 leads to nonsensical results g_maccel_config.growth_rate = val; } @@ -173,28 +184,33 @@ static inline float get_mod_step(float step) { return step; } -bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t growthrate, uint16_t offset, uint16_t limit) { +bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t takeoff, uint16_t growth_rate, uint16_t offset, uint16_t limit) { if (record->event.pressed) { - if (keycode == growthrate) { - maccel_set_growthrate(maccel_get_growthrate() + get_mod_step(MACCEL_GROWTH_RATE_STEP)); - printf("MACCEL:keycode: growthrate: %f, offset: %f, limit: %f\n", g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); + if (keycode == takeoff) { + maccel_set_takeoff(maccel_get_takeoff() + get_mod_step(MACCEL_TAKEOFF_STEP)); + printf("MACCEL:keycode: TKO: %.3f gro: %.3f ofs: %.3f lmt: %.3f\n", g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); + return false; + } + if (keycode == growth_rate) { + maccel_set_growth_rate(maccel_get_growth_rate() + get_mod_step(MACCEL_GROWTH_RATE_STEP)); + printf("MACCEL:keycode: tko: %.3f GRO: %.3f ofs: %.3f lmt: %.3f\n", g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); return false; } if (keycode == offset) { maccel_set_offset(maccel_get_offset() + get_mod_step(MACCEL_OFFSET_STEP)); - printf("MACCEL:keycode: growthrate: %f, OFFSET: %f, limit: %f\n", g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); + printf("MACCEL:keycode: tko: %.3f gro: %.3f OFS: %.3f lmt: %.3f\n", g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); return false; } if (keycode == limit) { maccel_set_limit(maccel_get_limit() + get_mod_step(MACCEL_LIMIT_STEP)); - printf("MACCEL:keycode: growthrate: %f, offset: %f, LIMIT: %f\n", g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); + printf("MACCEL:keycode: tko: %.3f gro: %.3f ofs: %.3f LMT: %.3f\n", g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.limit, g_maccel_config.limit); return false; } } return true; } #else -bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t growthrate, uint16_t offset, uint16_t limit) { +bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t takeoff, uint16_t growth_rate, uint16_t offset, uint16_t limit) { // provide a do-nothing keyrecord function so a user doesn't need to unshim when disabling the keycodes return true; } diff --git a/maccel/maccel.h b/maccel/maccel.h index c116813a5797..7e6df59bbc1f 100644 --- a/maccel/maccel.h +++ b/maccel/maccel.h @@ -21,7 +21,7 @@ #define MACCEL_USE_KEYCODES report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report); -bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t growthrate, uint16_t offset, uint16_t limit); +bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t takeoff, uint16_t growth_rate, uint16_t offset, uint16_t limit); typedef struct _maccel_config_t { float growth_rate; @@ -37,10 +37,12 @@ void maccel_enabled(bool enable); bool maccel_get_enabled(void); void maccel_toggle_enabled(void); -float maccel_get_growthrate(void); +float maccel_get_takeoff(void); +float maccel_get_growth_rate(void); float maccel_get_offset(void); float maccel_get_limit(void); -void maccel_set_growthrate(float val); +void maccel_set_growth_rate(float val); +void maccel_set_growth_rate(float val); void maccel_set_offset(float val); void maccel_set_limit(float val); From cfa24c81af19a275c0de84734e0402d19f8d6261 Mon Sep 17 00:00:00 2001 From: burkfers Date: Tue, 20 Feb 2024 11:58:48 +0100 Subject: [PATCH 09/17] do not use keycodes by default --- maccel/maccel.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/maccel/maccel.h b/maccel/maccel.h index 7e6df59bbc1f..b50bea56e665 100644 --- a/maccel/maccel.h +++ b/maccel/maccel.h @@ -18,8 +18,6 @@ #include "quantum.h" -#define MACCEL_USE_KEYCODES - report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report); bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t takeoff, uint16_t growth_rate, uint16_t offset, uint16_t limit); From 3e52f16ed82052f2f5106d276f49c4b3d443b86d Mon Sep 17 00:00:00 2001 From: burkfers Date: Tue, 20 Feb 2024 12:39:02 +0100 Subject: [PATCH 10/17] extend debug message with further detail --- maccel/maccel.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index 886702237197..6aeca58c16a2 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -151,8 +151,10 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { const float dpi_correction = (float)100.0f / (DEVICE_CPI_PARAM * device_cpi); // calculate euclidean distance moved (sqrt(x^2 + y^2)) const float distance = sqrtf(mouse_report.x * mouse_report.x + mouse_report.y * mouse_report.y); - // calculate delta velocity: dv = dpi_correction * distance/dt - const float velocity = dpi_correction * distance / delta_time; + // calculate delta velocity: dv = distance/dt + const float velocity_raw = distance / delta_time; + // correct raw velocity for dpi + const float velocity = dpi_correction * velocity_raw; // calculate mouse acceleration factor: f(dv) = c - ((c-1) / ((1 + e^(x(x - b)) * a/z))) const float maccel_factor = g_maccel_config.limit - (g_maccel_config.limit - 1) / powf(1 + expf(g_maccel_config.takeoff * (velocity - g_maccel_config.limit)), g_maccel_config.growth_rate / g_maccel_config.takeoff); // calculate accelerated delta X and Y values and clamp: @@ -162,7 +164,7 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { // console output for debugging (enable/disable in config.h) #ifdef MACCEL_DEBUG const float distance_out = sqrtf(x * x + y * y); - printf("MACCEL: DPI:%4i Tko: %.3f Grw: %.3f Ofs: %.3f Lmt: %.3f | Fct: %.3f Vel:%.3f Dst.in:%3i Dst.out:%3i\n", device_cpi, g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit, maccel_factor, velocity, CONSTRAIN_REPORT(distance), CONSTRAIN_REPORT(distance_out)); + printf("MACCEL: DPI:%4i Tko: %.3f Grw: %.3f Ofs: %.3f Lmt: %.3f | Fct: %.3f v: %.3f vraw: %.3f Dst.in: %3i Dst.out: %3i\n", device_cpi, g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit, maccel_factor, velocity, velocity_raw, CONSTRAIN_REPORT(distance), CONSTRAIN_REPORT(distance_out)); #endif // MACCEL_DEBUG // report back accelerated values From 5e58eff5e2d06b0d8bd1aa857ef94593233a1967 Mon Sep 17 00:00:00 2001 From: Wimads Date: Tue, 20 Feb 2024 15:33:31 +0100 Subject: [PATCH 11/17] Update readme and debug console reports --- maccel/maccel.c | 3 ++- maccel/readme.md | 55 ++++++++++++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index 6aeca58c16a2..ea4c38af2ece 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -164,7 +164,8 @@ report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report) { // console output for debugging (enable/disable in config.h) #ifdef MACCEL_DEBUG const float distance_out = sqrtf(x * x + y * y); - printf("MACCEL: DPI:%4i Tko: %.3f Grw: %.3f Ofs: %.3f Lmt: %.3f | Fct: %.3f v: %.3f vraw: %.3f Dst.in: %3i Dst.out: %3i\n", device_cpi, g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit, maccel_factor, velocity, velocity_raw, CONSTRAIN_REPORT(distance), CONSTRAIN_REPORT(distance_out)); + const float velocity_out = velocity * maccel_factor; + printf("MACCEL: DPI:%4i Tko: %.3f Grw: %.3f Ofs: %.3f Lmt: %.3f | Fct: %.3f v.in: %.3f v.out: %.3f d.in: %3i d.out: %3i\n", device_cpi, g_maccel_config.takeoff, g_maccel_config.growth_rate, g_maccel_config.offset, g_maccel_config.limit, maccel_factor, velocity, velocity_out, CONSTRAIN_REPORT(distance), CONSTRAIN_REPORT(distance_out)); #endif // MACCEL_DEBUG // report back accelerated values diff --git a/maccel/readme.md b/maccel/readme.md index 6ad7a2dfdcda..7d45dda9c822 100644 --- a/maccel/readme.md +++ b/maccel/readme.md @@ -9,13 +9,22 @@ You have 2 options of how to build it. **1. First build option:** - +If you do not maintain a user space (or if you don't know what that is), use this build option. First copy the `maccel.c` and `maccel.h` files into your keymap folder. - +Then in the same folder create a new file named `rules.mk` (or edit it if it already exists) and add the following code: +```c +ifeq ($(strip $(MACCEL_ENABLE)), yes) + SRC += ./maccel.c + ifeq ($(strip $(VIA_ENABLE)), yes) + SRC += ./maccel_via.c + endif + OPT_DEFS += -DMACCEL_ENABLE +endif +``` Then simply add the following code at the top of your keymap.c file: ```c -#include "maccel.c" +#include "maccel.h" report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { return pointing_device_task_maccel(mouse_report); @@ -24,8 +33,6 @@ report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { If you already have a `pointing_device_task_user` in your keymap, then add the `pointing_device_task_maccel` line to that instead. -This is an easy option if you are not maintaining a userspace. - **2. Second build option for those maintaining a user space:** @@ -40,25 +47,17 @@ This will add `maccel.c` to your build process, and additionally include `maccel --- -Next, add the acceleration shim to your `pointing_device_task_user`: +Next, `#include "maccel.h` in your keymap, and add the acceleration shim to your `pointing_device_task_user`: ```c report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { // ... return pointing_device_task_maccel(mouse_report); } ``` -If you have chosen to use the build system, you will also need to `#include "maccel.h`. - You may call it at the beginning if you wish to use the accelerated mouse report for your other code. -If you have not previously implemented a `pointing_device_task_user` (ie. your keymap has no such function), add one to `keymap.c`: -```c -report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { - return pointing_device_task_maccel(mouse_report); -} -``` -** 3. Runtime parameter adjusting with custom keycodes (optional) +**3. Runtime parameter adjusting with custom keycodes (optional)** To use keycodes to adjust the parameters without recompiling, two more steps are required. First, add three keycodes to your keycode enum. You may choose different names, as long as you use the same names in the following step. If you are not yet using custom keycodes, add the following snippet to `keymap.c`: @@ -84,23 +83,28 @@ See the configuration section on how to enable this feature once you have set it ## Configuration -This accel curve works in opposite direction from what you may be used to from other acceleration tools, due to technical limitation in QMK. It scales pointer sensitivity upwards rather than downwards, which means you will likely have to lower your DPI setting from what you'd normally do. +This accel curve works in opposite direction from what you may be used to from other acceleration tools, due to technical limitations in QMK. It scales pointer sensitivity upwards rather than downwards, which means you will have to lower your device DPI setting from what you'd normally do. Several characteristics of the acceleration curve can be tweaked by adding relevant defines to `config.h`: ```c -#define MACCEL_STEEPNESS 0.6 // steepness of accel curve -#define MACCEL_OFFSET 0.8 // start offset of accel curve -#define MACCEL_LIMIT 3.5 // upper limit of accel curve +#define MACCEL_TAKEOFF 2.0 // lower/higher value = curve takes off more smoothly/abrubtly +#define MACCEL_GROWTH 0.25 // lower/higher value = curve reaches its upper limit slower/faster +#define MACCEL_OFFSET 2.2 // lower/higher value = acceleration kicks in earlier/later +#define MACCEL_LIMIT 6.0 // upper limit of accel curve (maximum acceleration factor) ``` [![](assets/accel_curve.png)](https://www.wolframalpha.com/input?i=plot+c-%28c-1%29%28e%5E%28-%28x-b%29*a%29%29+with+a%3D0.6+with+b%3D0.8+with+c%3D3.5+from+x%3D-0.1+to+10+from+y%3D-0.1+to+4.5) +//image to be updated +The graph above shows the acceleration curve. Interpret this graph as follows: the horizontal axis is input velocity (ie. how fast you are physically moving your mouse/trackball/trackpad); the vertical axis is the acceleration factor, which is the factor with which the input speed will be multiplied, resulting in your new output speed on screen. You can also understand this as a DPI scaling factor: at the start of the curve the factor is 1, and your mouse sensitivity will be equal to your default DPI setting. At the end of the curve, the factor approaches a limit which can be set by the LIMIT variable. The limit is 6 in this example and will result in a maximum mouse sensitivity of 6 times your default DPI. + +The TAKEOFF variable controls how smoothly or abrubtly the acceleration curve takes off. A higher value will make it take off more abrubtly, a lower value smoothens out the start of the curve. -Interpret this graph as follows: horizontal axis is input velocity (ie. how fast you are physically moving your mouse/trackball/trackpad); vertical axis is the acceleration factor, which is the factor with which the input speed will be multiplied, resulting in your new output speed on screen. You can also understand this as a DPI scaling factor: at the start of the curve the factor is 1, and your mouse sensitivity will be equal to your default DPI setting. At the end of the curve, the factor approaches a limit which can be set by the LIMIT variable. The limit is 3.5 in this example and will result in a maximum mouse sensitivity of 3.5 times your default DPI. +The GROWTH variable sets the growth rate of the acceleration curve. A lower value will result in a flatter curve which takes longer to reach its LIMIT. A higher value will result in a steeper curve, which will reach its LIMIT faster. -The OFFSET variable moves the start of the curve towards the right, which means acceleration will kick in only after a certain velocity is reached. This is useful for low speed precision movements, in effect what you might normally use SNIPING mode for - and this is intended to entirely replace SNIPING mode. If you do not like this, you can set this variable to 0. +The OFFSET variable moves the entire curve towards left/right. Offsetting the curve to the right means acceleration will kick in later, which is useful for low speed precision - in effect what you would otherwise have used SNIPING mode for. The maccel feature basically eliminates the need for a sniping mode. -The STEEPNESS variable sets the steepness of the acceleration curve. A lower value will result in a flatter curve which takes longer to reach its LIMIT. A higher value will result in a steeper curve, which will reach its LIMIT faster. +The LIMIT variable sets the upper limit for the acceleration curve. This is the maximum acceleration factor the curve will reach. -A good starting point for tweaking your settings, is to set your default DPI to what you'd normally have set your sniping DPI. Then set the LIMIT variable to a factor that results in slightly higher than your usual default DPI. For example, if my usual settings are a default DPI of 1000 and a sniping DPI of 300, I would now set my default DPI to 300, and set my LIMIT variable to 3.5, which will result in an equivalent DPI scaling of 300*3.5=1050 at the upper limit of the acceleration curve. From there you can start playing around with the variables until you arrive at something to your liking. +A good starting point for tweaking your settings, is to set your default DPI to what you'd normally have set your sniping DPI. Then set the LIMIT variable to a factor that results in a bit higher than your usual default DPI. For example, if my usual settings are a default DPI of 1000 and a sniping DPI of 200, I would now set my default DPI to 200, and set my LIMIT variable to 6, which will result in an equivalent DPI scaling of 200*6=1200 at the upper limit of the acceleration curve. From there you can start playing around with the variables until you arrive at something to your liking. To aid in dialing in the settings just right, a debug mode exists to print mathy details to the console. Refer to the QMK documentation on how to enable the console and debugging, then enable mouse acceleration debugging in `config.h`: ```c @@ -112,10 +116,11 @@ To aid in dialing in the settings just right, a debug mode exists to print mathy #define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 1 ``` -The debug console will print your current DPI setting, the acceleration factor, the input velocity, and the accelerated velocity - which will help you understand what is happening at different settings of your variables. +The debug console will print your current DPI setting and variable settings, as well as the acceleration factor, the input and output velocity, and the input and output distance. This will help understand the effect of different variable values. +To help visualize the effect of the values, you can also use this desmos tool which plots the accel curve: https://www.desmos.com/calculator/g6zxh5rt44 ### Runtime adjusting of curve parameters by keycodes - +//VIA README IS STILL OUT OF DATE Once the additional keycodes and shim are added, this feature can be enabled: ``` #define MACCEL_USE_KEYCODES From 1db6e1e73426596523f7e303bfc929c5b9e8a6bb Mon Sep 17 00:00:00 2001 From: Wimads Date: Tue, 20 Feb 2024 15:39:14 +0100 Subject: [PATCH 12/17] Updated accel curve image --- maccel/assets/accel_curve.png | Bin 37843 -> 104240 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/maccel/assets/accel_curve.png b/maccel/assets/accel_curve.png index a7e177477e71d3593d56b670237d8d7a9dc5f30c..3afe60dcff4fbc3913b8616b78800706014bbca9 100644 GIT binary patch literal 104240 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

yjjZKom+^us0j%G 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 T^wtVgg84Ifb-79z)8PLDaCO#` literal 37843 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 From 8befa2c216d67aec592991dbc3a709552e715dfa Mon Sep 17 00:00:00 2001 From: Wimads Date: Tue, 20 Feb 2024 15:58:31 +0100 Subject: [PATCH 13/17] more readme updates --- maccel/readme.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/maccel/readme.md b/maccel/readme.md index 7d45dda9c822..d07936ff7201 100644 --- a/maccel/readme.md +++ b/maccel/readme.md @@ -14,6 +14,8 @@ If you do not maintain a user space (or if you don't know what that is), use thi First copy the `maccel.c` and `maccel.h` files into your keymap folder. Then in the same folder create a new file named `rules.mk` (or edit it if it already exists) and add the following code: ```c +MACCEL_ENABLE = yes +VIA_ENABLE = no //enable this if you use via ifeq ($(strip $(MACCEL_ENABLE)), yes) SRC += ./maccel.c ifeq ($(strip $(VIA_ENABLE)), yes) @@ -33,6 +35,7 @@ report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { If you already have a `pointing_device_task_user` in your keymap, then add the `pointing_device_task_maccel` line to that instead. +Lastly, if you use via, also add the `maccel_via.c` file to your keymap folder, and set `VIA_ENABLE = yes` in your `rules.mk`. **2. Second build option for those maintaining a user space:** @@ -42,8 +45,7 @@ Next, include `rules.mk` in your `rules.mk`: ```make -include $(USER_PATH)/features/maccel/rules.mk ``` - -This will add `maccel.c` to your build process, and additionally include `maccel_via.c` if you have via enabled. +This will add `maccel.c` to your build process; additionally include `maccel_via.c` if you have via enabled. --- @@ -92,9 +94,11 @@ Several characteristics of the acceleration curve can be tweaked by adding relev #define MACCEL_OFFSET 2.2 // lower/higher value = acceleration kicks in earlier/later #define MACCEL_LIMIT 6.0 // upper limit of accel curve (maximum acceleration factor) ``` -[![](assets/accel_curve.png)](https://www.wolframalpha.com/input?i=plot+c-%28c-1%29%28e%5E%28-%28x-b%29*a%29%29+with+a%3D0.6+with+b%3D0.8+with+c%3D3.5+from+x%3D-0.1+to+10+from+y%3D-0.1+to+4.5) -//image to be updated -The graph above shows the acceleration curve. Interpret this graph as follows: the horizontal axis is input velocity (ie. how fast you are physically moving your mouse/trackball/trackpad); the vertical axis is the acceleration factor, which is the factor with which the input speed will be multiplied, resulting in your new output speed on screen. You can also understand this as a DPI scaling factor: at the start of the curve the factor is 1, and your mouse sensitivity will be equal to your default DPI setting. At the end of the curve, the factor approaches a limit which can be set by the LIMIT variable. The limit is 6 in this example and will result in a maximum mouse sensitivity of 6 times your default DPI. +[![](assets/accel_curve.png)](https://www.desmos.com/calculator/g6zxh5rt44) + +The graph above shows the acceleration curve. You can interpret this graph as follows: the horizontal axis is input velocity (ie. how fast you are physically moving your mouse/trackball/trackpad); the vertical axis is the acceleration factor, which is the factor with which the input speed will be multiplied, resulting in your new output speed on screen. You can also understand this as a DPI scaling factor: at the start of the curve the factor is 1, and your mouse sensitivity will be equal to your default DPI setting. At the end of the curve, the factor approaches a limit which can be set by the LIMIT variable. The limit is 6 in this example and will result in a maximum mouse sensitivity of 6 times your default DPI. + +If you click on the image of the curve, you will be linked to desmos, where you can play around with the variables to understand how each of them affect the shape of the curve. But in short: The TAKEOFF variable controls how smoothly or abrubtly the acceleration curve takes off. A higher value will make it take off more abrubtly, a lower value smoothens out the start of the curve. @@ -106,7 +110,7 @@ The LIMIT variable sets the upper limit for the acceleration curve. This is the A good starting point for tweaking your settings, is to set your default DPI to what you'd normally have set your sniping DPI. Then set the LIMIT variable to a factor that results in a bit higher than your usual default DPI. For example, if my usual settings are a default DPI of 1000 and a sniping DPI of 200, I would now set my default DPI to 200, and set my LIMIT variable to 6, which will result in an equivalent DPI scaling of 200*6=1200 at the upper limit of the acceleration curve. From there you can start playing around with the variables until you arrive at something to your liking. -To aid in dialing in the settings just right, a debug mode exists to print mathy details to the console. Refer to the QMK documentation on how to enable the console and debugging, then enable mouse acceleration debugging in `config.h`: +To aid in dialing in your settings just right, a debug mode exists to print mathy details to the console. Refer to the QMK documentation on how to enable the console and debugging, then enable mouse acceleration debugging in `config.h`: ```c #define MACCEL_DEBUG /* @@ -116,11 +120,12 @@ To aid in dialing in the settings just right, a debug mode exists to print mathy #define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 1 ``` -The debug console will print your current DPI setting and variable settings, as well as the acceleration factor, the input and output velocity, and the input and output distance. This will help understand the effect of different variable values. -To help visualize the effect of the values, you can also use this desmos tool which plots the accel curve: https://www.desmos.com/calculator/g6zxh5rt44 +The debug console will print your current DPI setting and variable settings, as well as the acceleration factor, the input and output velocity, and the input and output distance. ### Runtime adjusting of curve parameters by keycodes -//VIA README IS STILL OUT OF DATE + +//THIS PART TO BE UPDATED BY @finrod09 + Once the additional keycodes and shim are added, this feature can be enabled: ``` #define MACCEL_USE_KEYCODES From 3c4db94798e92c70d1f5657fd8e4eef718a13838 Mon Sep 17 00:00:00 2001 From: Wimads Date: Tue, 20 Feb 2024 16:01:44 +0100 Subject: [PATCH 14/17] Formatting readme --- maccel/readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/maccel/readme.md b/maccel/readme.md index d07936ff7201..b9c5d3bf450a 100644 --- a/maccel/readme.md +++ b/maccel/readme.md @@ -37,6 +37,8 @@ If you already have a `pointing_device_task_user` in your keymap, then add the ` Lastly, if you use via, also add the `maccel_via.c` file to your keymap folder, and set `VIA_ENABLE = yes` in your `rules.mk`. +--- + **2. Second build option for those maintaining a user space:** First, place the `maccel/` directory in `users/YOUR_USERNAME/features/` (you may omit the readme and assets). @@ -47,7 +49,6 @@ Next, include `rules.mk` in your `rules.mk`: ``` This will add `maccel.c` to your build process; additionally include `maccel_via.c` if you have via enabled. ---- Next, `#include "maccel.h` in your keymap, and add the acceleration shim to your `pointing_device_task_user`: ```c @@ -58,6 +59,7 @@ report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { ``` You may call it at the beginning if you wish to use the accelerated mouse report for your other code. +--- **3. Runtime parameter adjusting with custom keycodes (optional)** From f72a97fb6775f8a96ffe3cad95af7378409b47ab Mon Sep 17 00:00:00 2001 From: Wimads Date: Tue, 20 Feb 2024 16:08:46 +0100 Subject: [PATCH 15/17] Moved build process of keycodes to relevant header nittigritty nittigritty --- maccel/readme.md | 55 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/maccel/readme.md b/maccel/readme.md index b9c5d3bf450a..05a7e0040f69 100644 --- a/maccel/readme.md +++ b/maccel/readme.md @@ -59,32 +59,6 @@ report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { ``` You may call it at the beginning if you wish to use the accelerated mouse report for your other code. ---- - -**3. Runtime parameter adjusting with custom keycodes (optional)** - -To use keycodes to adjust the parameters without recompiling, two more steps are required. -First, add three keycodes to your keycode enum. You may choose different names, as long as you use the same names in the following step. If you are not yet using custom keycodes, add the following snippet to `keymap.c`: -```c -enum my_keycodes { - MA_STEEPNESS = QK_USER, // mouse acceleration curve steepness step key - MA_OFFSET, // mouse acceleration curve offset step key - MA_LIMIT, // mouse acceleration curve limit step key -}; -``` -Next, add another shim, this time to `process_record_user`. If you have not previously implemented this function, simply place the following snippet in your `keymap.c`: -```c -bool process_record_user(uint16_t keycode, keyrecord_t *record) { - if (!process_record_maccel(keycode, record, MA_STEEPNESS, MA_OFFSET, MA_LIMIT)) { - return false; - } - return true; -} -``` -Take care to use the same names that you used in the previous step. - -See the configuration section on how to enable this feature once you have set it up. - ## Configuration This accel curve works in opposite direction from what you may be used to from other acceleration tools, due to technical limitations in QMK. It scales pointer sensitivity upwards rather than downwards, which means you will have to lower your device DPI setting from what you'd normally do. @@ -124,15 +98,42 @@ To aid in dialing in your settings just right, a debug mode exists to print math The debug console will print your current DPI setting and variable settings, as well as the acceleration factor, the input and output velocity, and the input and output distance. -### Runtime adjusting of curve parameters by keycodes +## Runtime adjusting of curve parameters by keycodes (optional) //THIS PART TO BE UPDATED BY @finrod09 +**Build process for maccel keycodes** + +To use keycodes to adjust the parameters without recompiling, two more build steps are required. +First, add three keycodes to your keycode enum. You may choose different names, as long as you use the same names in the following step. If you are not yet using custom keycodes, add the following snippet to `keymap.c`: +```c +enum my_keycodes { + MA_STEEPNESS = QK_USER, // mouse acceleration curve steepness step key + MA_OFFSET, // mouse acceleration curve offset step key + MA_LIMIT, // mouse acceleration curve limit step key +}; +``` +Next, add another shim, this time to `process_record_user`. If you have not previously implemented this function, simply place the following snippet in your `keymap.c`: +```c +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + if (!process_record_maccel(keycode, record, MA_STEEPNESS, MA_OFFSET, MA_LIMIT)) { + return false; + } + return true; +} +``` +Take care to use the same names that you used in the previous step. + +See the configuration section on how to enable this feature once you have set it up. + Once the additional keycodes and shim are added, this feature can be enabled: ``` #define MACCEL_USE_KEYCODES ``` +--- +**Using maccel keycodes** + The three keycodes can be used to adjust the curve parameters. This is currently *not* persisted - Adjusted values are printed to the console to aid in finding the right settings for `config.h`. The step keys will adjust the parameters by the following amounts, which can optionally be adjusted: From e53d9654335e7d8ce5a3553187aee394d7dd91b2 Mon Sep 17 00:00:00 2001 From: burkfers Date: Fri, 23 Feb 2024 10:55:28 +0100 Subject: [PATCH 16/17] includes cleanup --- maccel/maccel.c | 5 +++-- maccel/maccel.h | 3 ++- maccel/maccel_via.c | 5 ++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/maccel/maccel.c b/maccel/maccel.c index ea4c38af2ece..db8367bc29b5 100644 --- a/maccel/maccel.c +++ b/maccel/maccel.c @@ -14,9 +14,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "quantum.h" -#include "math.h" + +#include "quantum.h" // IWYU pragma: keep #include "maccel.h" +#include "math.h" static uint32_t maccel_timer; diff --git a/maccel/maccel.h b/maccel/maccel.h index b50bea56e665..f16c26fd5491 100644 --- a/maccel/maccel.h +++ b/maccel/maccel.h @@ -16,7 +16,8 @@ */ #pragma once -#include "quantum.h" +#include "action.h" +#include "report.h" report_mouse_t pointing_device_task_maccel(report_mouse_t mouse_report); bool process_record_maccel(uint16_t keycode, keyrecord_t *record, uint16_t takeoff, uint16_t growth_rate, uint16_t offset, uint16_t limit); diff --git a/maccel/maccel_via.c b/maccel/maccel_via.c index 6fdcdb4c9576..7e09ae030fdf 100644 --- a/maccel/maccel_via.c +++ b/maccel/maccel_via.c @@ -13,9 +13,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "quantum.h" + #include "maccel.h" #include "via.h" +#ifdef MACCEL_DEBUG +# include "debug.h" // IWYU pragma: keep +#endif _Static_assert(sizeof(maccel_config_t) == EECONFIG_USER_DATA_SIZE, "Mismatch in keyboard EECONFIG stored data"); From 9f319a3ede7399cde0062ee53a9b901d47fc818a Mon Sep 17 00:00:00 2001 From: burkfers Date: Fri, 23 Feb 2024 11:37:33 +0100 Subject: [PATCH 17/17] improve documentation --- maccel/readme.md | 117 +++++++++++++++++++++++++++-------------------- maccel/rules.mk | 4 +- 2 files changed, 70 insertions(+), 51 deletions(-) diff --git a/maccel/readme.md b/maccel/readme.md index 05a7e0040f69..f68b38cd8576 100644 --- a/maccel/readme.md +++ b/maccel/readme.md @@ -4,60 +4,71 @@ This feature was born from the frustration of not having a tweakable acceleratio ## Installation -You have 2 options of how to build it. +### Installation (keymap) +Choose this route if you do not maintain a userspace. -**1. First build option:** +Place the `maccel` directory in your keymap directory. For example, if you were using the `via` keymap on a BastardKB Dilemma Max, you'd place it to be `keyboards/bastardkb/dilemma/4x6_4/keymaps/via/maccel/`. -If you do not maintain a user space (or if you don't know what that is), use this build option. - -First copy the `maccel.c` and `maccel.h` files into your keymap folder. -Then in the same folder create a new file named `rules.mk` (or edit it if it already exists) and add the following code: -```c -MACCEL_ENABLE = yes -VIA_ENABLE = no //enable this if you use via -ifeq ($(strip $(MACCEL_ENABLE)), yes) - SRC += ./maccel.c - ifeq ($(strip $(VIA_ENABLE)), yes) - SRC += ./maccel_via.c +Add to `rules.mk` (Create it if it does not exist): +```make +# MACCEL +SRC += ./maccel/maccel.c +ifeq ($(strip $(VIA_ENABLE)), yes) + ifeq ($(strip $(MACCEL_VIA_ENABLE)), yes) + SRC += ./maccel/maccel_via.c endif - OPT_DEFS += -DMACCEL_ENABLE endif +OPT_DEFS += -DMACCEL_ENABLE ``` -Then simply add the following code at the top of your keymap.c file: -```c -#include "maccel.h" -report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { - return pointing_device_task_maccel(mouse_report); -} +Add to your `keymap.c`, near the top: +```c +#ifdef MACCEL_ENABLE + #include "maccel/maccel.h" +#endif ``` -If you already have a `pointing_device_task_user` in your keymap, then add the `pointing_device_task_maccel` line to that instead. +Continue with "Installation (common)", below. -Lastly, if you use via, also add the `maccel_via.c` file to your keymap folder, and set `VIA_ENABLE = yes` in your `rules.mk`. +### Installation (userspace) ---- +Choose this route if you maintain a userspace. -**2. Second build option for those maintaining a user space:** +Place the `maccel` directory within `features/` in your userspace. For example, if your username was burkfers, you'd place it to be `users/burkfers/features/maccel/`. -First, place the `maccel/` directory in `users/YOUR_USERNAME/features/` (you may omit the readme and assets). +Add to `rules.mk` in the top level of your userspace (Create it if not present): -Next, include `rules.mk` in your `rules.mk`: ```make --include $(USER_PATH)/features/maccel/rules.mk +MACCEL_ENABLE = yes + +include $(USER_PATH)/features/maccel/rules.mk +``` + +You may instead place `MACCEL_ENABLE = yes` in your keymap's `rules.mk` if you wish to only enable maccel for some boards. + +Add to your userspace source file, near the top: +```c +#ifdef MACCEL_ENABLE + #include "features/maccel/maccel.h" +#endif ``` -This will add `maccel.c` to your build process; additionally include `maccel_via.c` if you have via enabled. +Continue with "Installation (common)", below. + +### Installation (common) -Next, `#include "maccel.h` in your keymap, and add the acceleration shim to your `pointing_device_task_user`: +Add to `pointing_device_task_user` in `keymap.c` or your userspace source file (paste the whole function if it did not exist): ```c report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { // ... +#ifdef MACCEL_ENABLE return pointing_device_task_maccel(mouse_report); +#endif } ``` -You may call it at the beginning if you wish to use the accelerated mouse report for your other code. + +See the section on runtime adjusting by keycodes and on via support for installation steps for these optional features. ## Configuration @@ -86,7 +97,7 @@ The LIMIT variable sets the upper limit for the acceleration curve. This is the A good starting point for tweaking your settings, is to set your default DPI to what you'd normally have set your sniping DPI. Then set the LIMIT variable to a factor that results in a bit higher than your usual default DPI. For example, if my usual settings are a default DPI of 1000 and a sniping DPI of 200, I would now set my default DPI to 200, and set my LIMIT variable to 6, which will result in an equivalent DPI scaling of 200*6=1200 at the upper limit of the acceleration curve. From there you can start playing around with the variables until you arrive at something to your liking. -To aid in dialing in your settings just right, a debug mode exists to print mathy details to the console. Refer to the QMK documentation on how to enable the console and debugging, then enable mouse acceleration debugging in `config.h`: +To aid in dialing in your settings just right, a debug mode exists to print mathy details to the console. Refer to the QMK documentation on how to *enable the console and debugging*, then enable mouse acceleration debugging in `config.h`: ```c #define MACCEL_DEBUG /* @@ -100,15 +111,14 @@ The debug console will print your current DPI setting and variable settings, as ## Runtime adjusting of curve parameters by keycodes (optional) -//THIS PART TO BE UPDATED BY @finrod09 - -**Build process for maccel keycodes** +### Additional required installation steps To use keycodes to adjust the parameters without recompiling, two more build steps are required. -First, add three keycodes to your keycode enum. You may choose different names, as long as you use the same names in the following step. If you are not yet using custom keycodes, add the following snippet to `keymap.c`: +First, add four keycodes to your keycode enum. You may choose different names, as long as you use the same names in the following step. If you are not yet using custom keycodes, add the following snippet to `keymap.c`: ```c enum my_keycodes { - MA_STEEPNESS = QK_USER, // mouse acceleration curve steepness step key + MA_TAKEOFF = QK_USER, // mouse acceleration curve takeoff (initial acceleration) step key + MA_GROWTH_RATE, // mouse acceleration curve growth rate step key MA_OFFSET, // mouse acceleration curve offset step key MA_LIMIT, // mouse acceleration curve limit step key }; @@ -116,7 +126,7 @@ enum my_keycodes { Next, add another shim, this time to `process_record_user`. If you have not previously implemented this function, simply place the following snippet in your `keymap.c`: ```c bool process_record_user(uint16_t keycode, keyrecord_t *record) { - if (!process_record_maccel(keycode, record, MA_STEEPNESS, MA_OFFSET, MA_LIMIT)) { + if (!process_record_maccel(keycode, record, MA_TAKEOFF, MA_GROWTH_RATE, MA_OFFSET, MA_LIMIT)) { return false; } return true; @@ -126,22 +136,23 @@ Take care to use the same names that you used in the previous step. See the configuration section on how to enable this feature once you have set it up. -Once the additional keycodes and shim are added, this feature can be enabled: +Once the additional keycodes and shim are added, this feature can be enabled in `config.h`: ``` #define MACCEL_USE_KEYCODES ``` --- -**Using maccel keycodes** +### Acceleration keycode usage -The three keycodes can be used to adjust the curve parameters. This is currently *not* persisted - Adjusted values are printed to the console to aid in finding the right settings for `config.h`. +The four keycodes can be used to adjust the curve parameters. This is *not* persisted unless you also enabled the via option - Adjusted values are printed to the console to aid in finding the right settings for `config.h`. The step keys will adjust the parameters by the following amounts, which can optionally be adjusted: -| Parameter | Default step value | Define name | -| --- | --- | --- | -| Steepness | `+0.01` | `MACCEL_STEEPNESS_STEP` | -| Offset | `+0.1` | `MACCEL_OFFSET_STEP` | -| Limit | `+0.1` | `MACCEL_LIMIT_STEP` | +| Parameter | Default step value | Define name | +| --- | --- | --- | +| Takeoff | `+0.01` | `MACCEL_TAKEOFF_STEP` | +| Growth rate | `+0.01` | `MACCEL_GROWTH_RATE_STEP` | +| Offset | `+0.1` | `MACCEL_OFFSET_STEP` | +| Limit | `+0.1` | `MACCEL_LIMIT_STEP` | The modifier keys can be used to alter the step effect: @@ -160,9 +171,12 @@ With every adjustment, an informational message is printed to the console. Mouse acceleration can now be configured though via. If your keyboard is not already supported by via, you must first [create a via definition](https://www.caniusevia.com/docs/specification). -To begin, ensure `maccel_via.c` is included in your build process. The provided `rules.mk` will do this for you if via is enabled on your board. +Add to `rules.mk`, *before* the include added previously: +```make +VIA_MACCEL_ENABLE = yes +`````` -Next, shim `keyboard_post_init_user`: +Add a shim to `keyboard_post_init_user`: ```c void keyboard_post_init_user(void) { keyboard_post_init_maccel(); @@ -173,7 +187,7 @@ Add the entire function to your keymap if not already present, or insert the cal You must also configure the size of the EEPROM user block by placing the following define in `config.h`: ```c -#define EECONFIG_USER_DATA_SIZE 16 +#define EECONFIG_USER_DATA_SIZE 20 ``` Please be aware of the following caveats: @@ -194,9 +208,10 @@ Finally, after flashing the firmware to your board, load the custom via definiti - Add configuration defines for parameters and optionally debugging - Optional: Config keycodes: - Enable keycode support by define - - Create three keycodes in the keycode enum + - Create four keycodes in the keycode enum - Shim `process_record_user` - Optional: VIA support: + - Enable in `rules.mk` - Shim `keyboard_post_init_user` - Set user eeprom data block size - Create custom via json and sideload it in the web app @@ -211,13 +226,15 @@ With an unfavorable combination of `POINTING_DEVICE_THROTTLE_MS` and higher DPI, The maccel feature has so far only been properly tested with PMW3360 sensor. However, it should work fine with all other QMK compatible sensors and devices as well, but the behaviour may not be 100% consistent across different DPI settings. Hence it might be a bit harder to dial in your variable preferences for those devices. This is due to a device-specific parameter in the calculations, that hasn't yet been determined for other devices than the PMW3360 sensor. ## Release history +- 2024 February 23 - New four-parameter acceleration curve and improved documentation - 2024 February 07 - Experimental new DPI correction to achieve consistent acceleration behavior across different user DPI settings. - 2024 February 06 - First release candidate. Feedback welcome! ## Credits Thanks to everyone who helped! -Including: +Including, but not limited to: - Wimads (@wimads) and burkfers (@burkfers) wrote most of the code - Quentin (@balanstik) for insightful commentary on the math, and testing - ouglop (@ouglop) for insightful commentary on the math - Drashna Jael're (@drashna) for coding tips and their invaluable bag of magic C tricks +- ankostis (@ankostis) for catalysing discussion about improving the acceleration curve diff --git a/maccel/rules.mk b/maccel/rules.mk index 4207ba5e011b..9ef6fc3f673b 100644 --- a/maccel/rules.mk +++ b/maccel/rules.mk @@ -1,7 +1,9 @@ ifeq ($(strip $(MACCEL_ENABLE)), yes) SRC += $(USER_PATH)/features/maccel/maccel.c ifeq ($(strip $(VIA_ENABLE)), yes) - SRC += $(USER_PATH)/features/maccel/maccel_via.c + ifeq ($(strip $(MACCEL_VIA_ENABLE)), yes) + SRC += $(USER_PATH)/features/maccel/maccel_via.c + endif endif OPT_DEFS += -DMACCEL_ENABLE endif