summaryrefslogtreecommitdiff
path: root/src/filter.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2015-08-05 13:39:33 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2015-08-11 09:19:55 +1000
commit723dccfd939d151ad460e166c7a73a25ea7c0fc5 (patch)
treeeeb9844aed82b8246b5caced90abc9c44b3e437d /src/filter.c
parent1cbcc641a06e49d676263093e088c5c25c47cb4d (diff)
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>
Diffstat (limited to 'src/filter.c')
-rw-r--r--src/filter.c83
1 files changed, 73 insertions, 10 deletions
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);