/** * Calculate the velocity based on the tracker data. Velocity is averaged * across multiple historical values, provided those values aren't "too * different" to our current one. That includes either being too far in the * past, moving into a different direction or having too much of a velocity * change between events. */ static double calculate_velocity(struct pointer_accelerator *accel, uint64_t time) { struct pointer_tracker *tracker; double velocity; double result = 0.0; double initial_velocity = 0.0; double velocity_diff; unsigned int offset; unsigned int dir = tracker_by_offset(accel, 0)->dir; /* Find least recent vector within a timelimit, maximum velocity diff * and direction threshold. */ for (offset = 1; offset < NUM_POINTER_TRACKERS; offset++) { tracker = tracker_by_offset(accel, offset); /* Bug: time running backwards */ if (tracker->time > time) break; /* Stop if too far away in time */ if (time - tracker->time > MOTION_TIMEOUT) { if (offset == 1) result = calculate_velocity_after_timeout(accel, tracker); break; } velocity = calculate_tracker_velocity(accel, tracker, time); /* Stop if direction changed */ dir &= tracker->dir; if (dir == 0) { /* First movement after dirchange - velocity is that * of the last movement */ if (offset == 1) result = velocity; break; } if (initial_velocity == 0.0) { result = initial_velocity = velocity; } else { /* Stop if velocity differs too much from initial */ velocity_diff = fabs(initial_velocity - velocity); if (velocity_diff > MAX_VELOCITY_DIFF) break; result = velocity; } } return result; /* units/us */ }
static double calculate_velocity(struct pointer_accelerator *accel, uint32_t time) { struct pointer_tracker *tracker; double velocity; double result = 0.0; double initial_velocity; double velocity_diff; unsigned int offset; unsigned int dir = tracker_by_offset(accel, 0)->dir; /* Find first velocity */ for (offset = 1; offset < NUM_POINTER_TRACKERS; offset++) { tracker = tracker_by_offset(accel, offset); if (time <= tracker->time) continue; result = initial_velocity = calculate_tracker_velocity(tracker, time); if (initial_velocity > 0.0) break; } /* Find least recent vector within a timelimit, maximum velocity diff * and direction threshold. */ for (; offset < NUM_POINTER_TRACKERS; offset++) { tracker = tracker_by_offset(accel, offset); /* Stop if too far away in time */ if (time - tracker->time > MOTION_TIMEOUT || tracker->time > time) break; /* Stop if direction changed */ dir &= tracker->dir; if (dir == 0) break; velocity = calculate_tracker_velocity(tracker, time); /* Stop if velocity differs too much from initial */ velocity_diff = fabs(initial_velocity - velocity); if (velocity_diff > MAX_VELOCITY_DIFF) break; result = velocity; } return result; }
static void accelerator_restart(struct motion_filter *filter, void *data, uint64_t time) { struct pointer_accelerator *accel = (struct pointer_accelerator *) filter; unsigned int offset; struct pointer_tracker *tracker; for (offset = 1; offset < NUM_POINTER_TRACKERS; offset++) { tracker = tracker_by_offset(accel, offset); tracker->time = 0; tracker->dir = 0; tracker->delta.x = 0; tracker->delta.y = 0; } tracker = tracker_by_offset(accel, 0); tracker->time = time; tracker->dir = UNDEFINED_DIRECTION; }