• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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