Use smoothed version of sensor array data to calculate movement and add weight
to prior values when calculating average. This gives more granular and more
predictable movement.

Signed-off-by: Clinton Sprain <[email protected]>
---
 drivers/input/mouse/appletouch.c |   72 ++++++++++++++++++++++++++++----------
 1 file changed, 53 insertions(+), 19 deletions(-)

diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index 2745832..0252bab 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -332,7 +332,11 @@ static void atp_reinit(struct work_struct *work)
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
                             int *z, int *fingers)
 {
-       int i;
+       int i, k;
+       int smooth[nb_sensors + 8];
+       int smooth_tmp[nb_sensors + 8];
+       int scale = 12;
+
        /* values to calculate mean */
        int pcum = 0, psum = 0;
        int is_increasing = 0;
@@ -344,9 +348,6 @@ static int atp_calculate_abs(int *xy_sensors, int 
nb_sensors, int fact,
                        if (is_increasing)
                                is_increasing = 0;
 
-                       continue;
-               }
-
                /*
                 * Makes the finger detection more versatile.  For example,
                 * two fingers with no gap will be detected.  Also, my
@@ -361,27 +362,60 @@ static int atp_calculate_abs(int *xy_sensors, int 
nb_sensors, int fact,
                 *
                 * - Jason Parekh <[email protected]>
                 */
-               if (i < 1 ||
+
+               } else if (i < 1 ||
                    (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
                        (*fingers)++;
                        is_increasing = 1;
                } else if (i > 0 && (xy_sensors[i - 1] - xy_sensors[i] > 
threshold)) {
                        is_increasing = 0;
                }
+       }
 
-               /*
-                * Subtracts threshold so a high sensor that just passes the
-                * threshold won't skew the calculated absolute coordinate.
-                * Fixes an issue where slowly moving the mouse would
-                * occasionally jump a number of pixels (slowly moving the
-                * finger makes this issue most apparent.)
-                */
-               pcum += (xy_sensors[i] - threshold) * i;
-               psum += (xy_sensors[i] - threshold);
+       /*
+        * Use a smoothed version of sensor data for movement calculations, to
+        * combat noise without needing to rely so heavily on a threshold.
+        * This improves tracking.
+        *
+        * The smoothed array is bigger than the original so that the smoothing
+        * doesn't result in edge values being truncated.
+        */
+
+       for (i = 0; i < 4; i++)
+               smooth[i] = 0;
+       for (i = nb_sensors + 4; i < nb_sensors + 8; i++)
+               smooth[i] = 0;
+
+       /* Pull base values, scaled up to help avoid truncation errors. */
+
+       for (i = 0; i < nb_sensors; i++)
+               smooth[i + 4] = xy_sensors[i] << scale;
+
+       for (k = 0; k < 4; k++) {
+
+               /* Handle edge. */
+               smooth_tmp[0] = (smooth[0] * 1 + smooth[1]) >> 1;
+
+               /* Average values with neighbors. */
+               for (i = 1; i < nb_sensors + 7; i++)
+                       smooth_tmp[i] = (smooth[i - 1] + smooth[i] * 2 + 
smooth[i + 1]) >> 2;
+
+               /* Handle other edge. */
+               smooth_tmp[nb_sensors + 7] = (smooth[nb_sensors + 7] + 
smooth[nb_sensors + 6]) >> 1;
+
+               for (i = 0; i < nb_sensors + 7; i++)
+                       smooth[i] = smooth_tmp[i];
+       }
+
+       for (i = 0; i < nb_sensors + 8; i++) {
+               if ((smooth[i] >> scale) > 0) {  /* Skip individual values if */
+                       pcum += (smooth[i]) * i; /* they are small enough to  */
+                       psum += (smooth[i]);     /* be truncated to 0 by our  */
+               }                                /* scale; mostly just noise. */
        }
 
        if (psum > 0) {
-               *z = psum;
+               *z = psum >> scale;            /* Scale down pressure output. */
                return pcum * fact / psum;
        }
 
@@ -559,8 +593,8 @@ static void atp_complete_geyser_1_2(struct urb *urb)
 
        if (x && y) {
                if (dev->x_old != -1) {
-                       x = (dev->x_old * 3 + x) >> 2;
-                       y = (dev->y_old * 3 + y) >> 2;
+                       x = (dev->x_old * 7 + x) >> 3;
+                       y = (dev->y_old * 7 + y) >> 3;
                        dev->x_old = x;
                        dev->y_old = y;
 
@@ -671,8 +705,8 @@ static void atp_complete_geyser_3_4(struct urb *urb)
 
        if (x && y) {
                if (dev->x_old != -1) {
-                       x = (dev->x_old * 3 + x) >> 2;
-                       y = (dev->y_old * 3 + y) >> 2;
+                       x = (dev->x_old * 7 + x) >> 3;
+                       y = (dev->y_old * 7 + y) >> 3;
                        dev->x_old = x;
                        dev->y_old = y;
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to