From 5264a3c45c890014dc97ed3698b2c4272d9af2ba Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 2 Jul 2017 15:15:58 +0200 Subject: filter: Add timestamp smoothing support Some devices, specifically some bluetooth touchpads generate quite unreliable timestamps for their events. The problem seems to be that (some of) these touchpads sample at aprox 90 Hz, but the bluetooth stack only communicates about every 30 ms (*) and then sends mutiple HID input reports in one batch. This results in 2-4 packets / SYNs every 30 ms. With timestamps really close together. The finger coordinate deltas in these packets change by aprox. the same amount between each packet when moving a finger at constant speed. But the time deltas are e.g. 28 ms, 1 ms, 1 ms resulting in calculate_tracker_velocity returning vastly different speeds for the 1st and 2nd packet, which in turn results in very "jerky" mouse pointer movement. *) Maybe it is waiting for a transmit time slot or some such. This commit adds support for a real simple timestamp smoothing algorithm, intended *only* for use with touchpads. Since touchpads will send a contineous stream of events at their sample rate when a finger is down, this filter simply assumes that any events which are under event_delta_smooth_threshold us apart are part of a smooth continuous stream of events with each event being event_delta_smooth_value us apart. Theoritically a very still finger may send the exact same coordinates and pressure twice, but even if this happens that is not a problem because a still finger generates coordinates changes below the hyst treshold so we ignore it anyways. Signed-off-by: Hans de Goede --- src/filter.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/filter.c b/src/filter.c index 7c500f8..49d324e 100644 --- a/src/filter.c +++ b/src/filter.c @@ -176,6 +176,10 @@ struct pointer_accelerator { double accel; /* unitless factor */ double incline; /* incline of the function */ + /* For smoothing timestamps from devices with unreliable timing */ + uint64_t event_delta_smooth_threshold; + uint64_t event_delta_smooth_value; + int dpi; }; @@ -227,14 +231,21 @@ tracker_by_offset(struct pointer_accelerator *accel, unsigned int offset) } static double -calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time) +calculate_tracker_velocity(struct pointer_accelerator *accel, + struct pointer_tracker *tracker, uint64_t time) { - double tdelta = time - tracker->time + 1; - return hypot(tracker->delta.x, tracker->delta.y) / tdelta; /* units/us */ + uint64_t tdelta = time - tracker->time + 1; + + if (tdelta < accel->event_delta_smooth_threshold) + tdelta = accel->event_delta_smooth_value; + + return hypot(tracker->delta.x, tracker->delta.y) / + (double)tdelta; /* units/us */ } static inline double -calculate_velocity_after_timeout(struct pointer_tracker *tracker) +calculate_velocity_after_timeout(struct pointer_accelerator *accel, + struct pointer_tracker *tracker) { /* First movement after timeout needs special handling. * @@ -247,7 +258,7 @@ calculate_velocity_after_timeout(struct pointer_tracker *tracker) * for really slow movements but provides much more useful initial * movement in normal use-cases (pause, move, pause, move) */ - return calculate_tracker_velocity(tracker, + return calculate_tracker_velocity(accel, tracker, tracker->time + MOTION_TIMEOUT); } @@ -282,11 +293,11 @@ calculate_velocity(struct pointer_accelerator *accel, uint64_t time) /* Stop if too far away in time */ if (time - tracker->time > MOTION_TIMEOUT) { if (offset == 1) - result = calculate_velocity_after_timeout(tracker); + result = calculate_velocity_after_timeout(accel, tracker); break; } - velocity = calculate_tracker_velocity(tracker, time); + velocity = calculate_tracker_velocity(accel, tracker, time); /* Stop if direction changed */ dir &= tracker->dir; -- cgit v1.2.3