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