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 <map> 6 7 #include <gtest/gtest.h> // for FRIEND_TEST 8 9 #include "include/filter_interpreter.h" 10 #include "include/finger_metrics.h" 11 #include "include/gestures.h" 12 #include "include/prop_registry.h" 13 #include "include/tracer.h" 14 15 #ifndef GESTURES_IIR_FILTER_INTERPRETER_H_ 16 #define GESTURES_IIR_FILTER_INTERPRETER_H_ 17 18 namespace gestures { 19 20 // This filter interpreter applies a low-pass infinite impulse response (iir) 21 // filter to each incoming finger. The default filter is a low-pass 2nd order 22 // Butterworth IIR filter with a normalized cutoff frequency of 0.2. It can be 23 // configured via properties to use other formulae or 24 // different coefficients for the Butterworth filter. 25 26 class IirFilterInterpreter : public FilterInterpreter, public PropertyDelegate { 27 FRIEND_TEST(IirFilterInterpreterTest, DisableIIRTest); 28 public: 29 // We'll maintain one IOHistory record per active finger 30 class IoHistory { 31 public: IoHistory()32 IoHistory() : in_head(0), out_head(0) {} IoHistory(const FingerState & fs)33 explicit IoHistory(const FingerState& fs) : in_head(0), out_head(0) { 34 for (size_t i = 0; i < kInSize; i++) 35 in[i] = fs; 36 for (size_t i = 0; i < kOutSize; i++) 37 out[i] = fs; 38 } 39 // Note: NextOut() and the oldest PrevOut() point to the same object. NextOut()40 FingerState* NextOut() { return &out[NextOutHead()]; } PrevOut(size_t idx)41 FingerState* PrevOut(size_t idx) { 42 return &out[(out_head + idx) % kOutSize]; 43 } 44 // Note: NextIn() and the oldest PrevIn() point to the same object. NextIn()45 FingerState* NextIn() { return &in[NextInHead()]; } PrevIn(size_t idx)46 FingerState* PrevIn(size_t idx) { return &in[(in_head + idx) % kInSize]; } 47 void Increment(); 48 49 bool operator==(const IoHistory& that) const; 50 bool operator!=(const IoHistory& that) const { return !(*this == that); } 51 52 void WarpBy(float dx, float dy); 53 54 private: NextOutHead()55 size_t NextOutHead() const { 56 return (out_head + kOutSize - 1) % kOutSize; 57 } NextInHead()58 size_t NextInHead() const { 59 return (in_head + kInSize - 1) % kInSize; 60 } 61 62 static const size_t kInSize = 3; 63 static const size_t kOutSize = 2; 64 FingerState in[kInSize]; // previous input values 65 size_t in_head; 66 FingerState out[kOutSize]; // previous output values 67 size_t out_head; 68 }; 69 70 // Takes ownership of |next|: 71 IirFilterInterpreter(PropRegistry* prop_reg, Interpreter* next, 72 Tracer* tracer); ~IirFilterInterpreter()73 virtual ~IirFilterInterpreter() {} 74 75 protected: 76 virtual void SyncInterpretImpl(HardwareState* hwstate, stime_t* timeout); 77 78 public: 79 virtual void DoubleWasWritten(DoubleProperty* prop); 80 81 private: 82 // Whether IIR filter should be used. Put as a member variable for 83 // unittest purpose. 84 bool using_iir_; 85 86 // Sync state history information 87 std::map<short, IoHistory> histories_; 88 89 // y[0] = b[0]*x[0] + b[1]*x[1] + b[2]*x[2] + b[3]*x[3] 90 // - (a[1]*y[1] + a[2]*y[2]) 91 DoubleProperty b0_, b1_, b2_, b3_, a1_, a2_; 92 93 // If position change between 2 frames is less than iir_dist_thresh_, 94 // IIR filter is applied, otherwise rolling average is applied. 95 DoubleProperty iir_dist_thresh_; 96 // Whether to adjust the IIR history when finger WARP is detected. 97 BoolProperty adjust_iir_on_warp_; 98 }; 99 100 } // namespace gestures 101 102 #endif // GESTURES_IIR_FILTER_INTERPRETER_H_ 103