blob: e41e019eaab35f729425c478e015deb0b8e58d50 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <gtest/gtest.h> // for FRIEND_TEST
#include "gestures/include/filter_interpreter.h"
#include "gestures/include/gestures.h"
#include "gestures/include/prop_registry.h"
#include "gestures/include/tracer.h"
#ifndef GESTURES_NON_LINEARITY_FILTER_INTERPRETER_H_
#define GESTURES_NON_LINEARITY_FILTER_INTERPRETER_H_
namespace gestures {
// This filters the incoming hardware state to try and correct for nonlinearity
// in the sensor's output. What we found to be happening was that even when a
// finger moved perfectly straight across the touchpad, "wiggles" were reported
// back to the computer. This nonlinearities turned out to be quite consistent
// so this can filter them out.
//
// There is a data file specifying a large grid of observed errors, sampled
// across the space of inputs (x, y, and pressure). Then as the hardware
// states come in, this module, looks at the finger positions and interpolates
// over the three axes to estimate the error in x and y for that reading, and
// compensates accordingly.
//
// The data file consists of three "range" arrays which define which points
// the error was sampled at, followed by a 3 dimensional array of those errors.
// The error matrix will have an entry for each value in the cross product of
// the three range arrays.
//
// File format:
// X Range Array
// Y Range Array
// P Range Array
// Error Matrix
//
// Range Array Format:
// 4 bytes: Integer length of array
// 8 bytes x length: Double values for each point in the array
//
// Error Matrix Format:
// Three dimensional matrix of error entries stored in x, y, p order.
// The number of entries is determined by the range arrays.
// Each error entry is of the form:
// 8 bytes: Double x error
// 8 bytes: Double y error
//
// Currently, this only handles the situation where exactly 1 finger is on the
// touchpad at a time. There may be interactions between multiple contacts
// that this doesn't take into consideration, so it simply skips hwstates with
// more than 1 finger.
class NonLinearityFilterInterpreter : public FilterInterpreter {
FRIEND_TEST(NonLinearityFilterInterpreterTest, DisablingTest);
FRIEND_TEST(NonLinearityFilterInterpreterTest, HWstateModificationTest);
FRIEND_TEST(NonLinearityFilterInterpreterTest, HWstateNoChangesNeededTest);
public:
NonLinearityFilterInterpreter(PropRegistry* prop_reg, Interpreter* next,
Tracer* tracer);
protected:
virtual void SyncInterpretImpl(HardwareState* hwstate, stime_t* timeout);
private:
struct Error {
double x_error;
double y_error;
};
struct Bounds {
ssize_t lo;
ssize_t hi;
};
// The error readings are stored in a flattened matrix, this finds the 1d
// index corresponding to the point (x_index, y_index, p_index)
unsigned int ErrorIndex(size_t x_index, size_t y_index, size_t p_index) const;
// Find the two values in the range on either side of "value" to interpolate
Bounds FindBounds(float value, const std::unique_ptr<double[]>& range,
size_t len) const;
// Given a point (x, y, p) calculate the non-linearity error that needs to be
// compensated for at that point.
Error GetError(float finger_x, float finger_y, float finger_p) const;
// Interpolate linearly between p1 and p2, according to percent_p1
Error LinearInterpolate(const Error& p1, const Error& p2,
float percent_p1) const;
// Load nonlinearity data from disk and parse it
void LoadData();
// Parse only a range array from the binary data
bool LoadRange(std::unique_ptr<double[]>& arr, size_t& len, FILE* fd);
int ReadObject(void* buf, size_t object_size, FILE* fd);
BoolProperty enabled_;
StringProperty data_location_;
// These three arrays define the points where the error was sampled.
// There is a reading in err_ for each point formed by the cross product
// of these arrays.
std::unique_ptr<double[]> x_range_, y_range_, p_range_;
size_t x_range_len_, y_range_len_, p_range_len_;
// A flattened 3-d array holding the actual sampled error values
std::unique_ptr<Error[]> err_;
};
} // namespace gestures
#endif // GESTURES_NON_LINEARITY_FILTER_INTERPRETER_H_