filter: explain the acceleration function in detail

And switch to a code-flow that's a bit more self-explanatory than the current
min/max combinations.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
This commit is contained in:
Peter Hutterer 2015-08-05 13:39:33 +10:00
parent 1cbcc641a0
commit 723dccfd93

View file

@ -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:
factor = min(max_accel, f2 > 1 ? f2 : f1);
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;
}
/* 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);