xref: /aosp_15_r20/external/libchrome-gestures/include/non_linearity_filter_interpreter.h (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
1 // Copyright 2012 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <gtest/gtest.h>  // for FRIEND_TEST
6 
7 #include "include/filter_interpreter.h"
8 #include "include/gestures.h"
9 #include "include/prop_registry.h"
10 #include "include/tracer.h"
11 
12 #ifndef GESTURES_NON_LINEARITY_FILTER_INTERPRETER_H_
13 #define GESTURES_NON_LINEARITY_FILTER_INTERPRETER_H_
14 
15 namespace gestures {
16 // This filters the incoming hardware state to try and correct for nonlinearity
17 // in the sensor's output.  What we found to be happening was that even when a
18 // finger moved perfectly straight across the touchpad, "wiggles" were reported
19 // back to the computer.  This nonlinearities turned out to be quite consistent
20 // so this can filter them out.
21 //
22 // There is a data file specifying a large grid of observed errors, sampled
23 // across the space of inputs (x, y, and pressure).  Then as the hardware
24 // states come in, this module, looks at the finger positions and interpolates
25 // over the three axes to estimate the error in x and y for that reading, and
26 // compensates accordingly.
27 //
28 // The data file consists of three "range" arrays which define which points
29 // the error was sampled at, followed by a 3 dimensional array of those errors.
30 // The error matrix will have an entry for each value in the cross product of
31 // the three range arrays.
32 //
33 // File format:
34 //      X Range Array
35 //      Y Range Array
36 //      P Range Array
37 //      Error Matrix
38 //
39 // Range Array Format:
40 //      4 bytes: Integer length of array
41 //      8 bytes x length: Double values for each point in the array
42 //
43 // Error Matrix Format:
44 //      Three dimensional matrix of error entries stored in x, y, p order.
45 //      The number of entries is determined by the range arrays.
46 //      Each error entry is of the form:
47 //          8 bytes: Double x error
48 //          8 bytes: Double y error
49 //
50 // Currently, this only handles the situation where exactly 1 finger is on the
51 // touchpad at a time.  There may be interactions between multiple contacts
52 // that this doesn't take into consideration, so it simply skips hwstates with
53 // more than 1 finger.
54 
55 class NonLinearityFilterInterpreter : public FilterInterpreter {
56   FRIEND_TEST(NonLinearityFilterInterpreterTest, DisablingTest);
57   FRIEND_TEST(NonLinearityFilterInterpreterTest, HWstateModificationTest);
58   FRIEND_TEST(NonLinearityFilterInterpreterTest, HWstateNoChangesNeededTest);
59  public:
60   NonLinearityFilterInterpreter(PropRegistry* prop_reg, Interpreter* next,
61                            Tracer* tracer);
62 
63  protected:
64   virtual void SyncInterpretImpl(HardwareState& hwstate, stime_t* timeout);
65 
66  private:
67   struct Error {
68     double x_error;
69     double y_error;
70   };
71   struct Bounds {
72     ssize_t lo;
73     ssize_t hi;
74   };
75 
76   // The error readings are stored in a flattened matrix, this finds the 1d
77   // index corresponding to the point (x_index, y_index, p_index)
78   unsigned int ErrorIndex(size_t x_index, size_t y_index, size_t p_index) const;
79   // Find the two values in the range on either side of "value" to interpolate
80   Bounds FindBounds(float value, const std::unique_ptr<double[]>& range,
81                            size_t len) const;
82   // Given a point (x, y, p) calculate the non-linearity error that needs to be
83   // compensated for at that point.
84   Error GetError(float finger_x, float finger_y, float finger_p) const;
85   // Interpolate linearly between p1 and p2, according to percent_p1
86   Error LinearInterpolate(const Error& p1, const Error& p2,
87                           float percent_p1) const;
88   // Load nonlinearity data from disk and parse it
89   void LoadData();
90   // Parse only a range array from the binary data
91   bool LoadRange(std::unique_ptr<double[]>& arr, size_t& len, FILE* fd);
92   int ReadObject(void* buf, size_t object_size, FILE* fd);
93 
94   // These three arrays define the points where the error was sampled.
95   // There is a reading in err_ for each point formed by the cross product
96   // of these arrays.
97   std::unique_ptr<double[]> x_range_, y_range_, p_range_;
98   size_t x_range_len_, y_range_len_, p_range_len_;
99   // A flattened 3-d array holding the actual sampled error values
100   std::unique_ptr<Error[]> err_;
101 
102   BoolProperty enabled_;
103   StringProperty data_location_;
104 };
105 
106 }  // namespace gestures
107 
108 #endif  // GESTURES_NON_LINEARITY_FILTER_INTERPRETER_H_
109