From 723dccfd939d151ad460e166c7a73a25ea7c0fc5 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 5 Aug 2015 13:39:33 +1000 Subject: filter: explain the acceleration function in detail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And switch to a code-flow that's a bit more self-explanatory than the current min/max combinations. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ã…dahl --- src/filter.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 10 deletions(-) (limited to 'src/filter.c') diff --git a/src/filter.c b/src/filter.c index 425bc795..467eb225 100644 --- a/src/filter.c +++ b/src/filter.c @@ -421,19 +421,26 @@ pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; - double f1, f2; /* unitless */ double max_accel = accel_filter->accel; /* unitless factor */ - const double threshold = accel_filter->threshold; /* units/us */ + double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; double factor; /* unitless */ double dpi_factor = accel_filter->dpi_factor; + /* dpi_factor is always < 1.0, increase max_accel, reduce + the threshold so it kicks in earlier */ max_accel /= dpi_factor; + threshold *= dpi_factor; - f1 = min(1, 0.3 + v_us2ms(speed_in) * 10.0); - f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold) * dpi_factor) * incline; + /* see pointer_accel_profile_linear for a long description */ + if (v_us2ms(speed_in) < 0.07) + factor = 10 * v_us2ms(speed_in) + 0.3; + else if (speed_in < threshold) + factor = 1; + else + factor = incline * v_us2ms(speed_in - threshold) + 1; - factor = min(max_accel, f2 > 1 ? f2 : f1); + factor = min(max_accel, factor); return factor; } @@ -446,17 +453,67 @@ pointer_accel_profile_linear(struct motion_filter *filter, { struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; - - double f1, f2; /* unitless */ const double max_accel = accel_filter->accel; /* unitless factor */ const double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; double factor; /* unitless */ - f1 = min(1, 0.3 + v_us2ms(speed_in) * 10); - f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold)) * incline; + /* + Our acceleration function calculates a factor to accelerate input + deltas with. The function is a double incline with a plateau, + with a rough shape like this: + + accel + factor + ^ + | / + | _____/ + | / + |/ + +-------------> speed in + + The two inclines are linear functions in the form + y = ax + b + where y is speed_out + x is speed_in + a is the incline of acceleration + b is minimum acceleration factor + + for speeds up to 0.07 u/ms, we decelerate, down to 30% of input + speed. + hence 1 = a * 0.07 + 0.3 + 0.3 = a * 0.00 + 0.3 => a := 10 + deceleration function is thus: + y = 10x + 0.3 + + Note: + * 0.07u/ms as threshold is a result of trial-and-error and + has no other intrinsic meaning. + * 0.3 is chosen simply because it is above the Nyquist frequency + for subpixel motion within a pixel. + */ + if (v_us2ms(speed_in) < 0.07) { + factor = 10 * v_us2ms(speed_in) + 0.3; + /* up to the threshold, we keep factor 1, i.e. 1:1 movement */ + } else if (speed_in < threshold) { + factor = 1; + + } else { + /* Acceleration function above the threshold: + y = ax' + b + where T is threshold + x is speed_in + x' is speed + and + y(T) == 1 + hence 1 = ax' + 1 + => x' := (x - T) + */ + factor = incline * v_us2ms(speed_in - threshold) + 1; + } - factor = min(max_accel, f2 > 1 ? f2 : f1); + /* Cap at the maximum acceleration factor */ + factor = min(max_accel, factor); return factor; } @@ -509,6 +566,12 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, TP_MAGIC_LOW_RES_FACTOR; /* units/us */ const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR; + /* Note: the magic values in this function are obtained by + * trial-and-error. No other meaning should be interpreted. + * The calculation is a compressed form of + * pointer_accel_profile_linear(), look at the git history of that + * function for an explaination of what the min/max/etc. does. + */ speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; f1 = min(1, v_us2ms(speed_in) * 5); -- cgit v1.2.3