summaryrefslogtreecommitdiff
path: root/common/gesture.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/gesture.c')
-rw-r--r--common/gesture.c335
1 files changed, 0 insertions, 335 deletions
diff --git a/common/gesture.c b/common/gesture.c
deleted file mode 100644
index 88d79448a5..0000000000
--- a/common/gesture.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/* Copyright 2014 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.
- */
-
-/* Board specific gesture recognition */
-
-#include "accelgyro.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "gesture.h"
-#include "lid_switch.h"
-#include "lightbar.h"
-#include "motion_sense.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_GESTURE, outstr)
-#define CPRINTS(format, args...) cprints(CC_GESTURE, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_GESTURE, format, ## args)
-
-
-/*
- * Double tap detection parameters
- * Double tap works by looking for two isolated Z-axis accelerometer impulses
- * preceded and followed by relatively calm periods of accelerometer motion.
- *
- * Define an outer and inner window. The inner window specifies how
- * long the tap impulse is expected to last. The outer window specifies the
- * period before the initial tap impluse and after the final tap impulse for
- * which to check for relatively calm periods. In between the two impulses
- * there is a minimum and maximum interstice time allowed.
- */
-#define OUTER_WINDOW \
- (CONFIG_GESTURE_TAP_OUTER_WINDOW_T / \
- CONFIG_GESTURE_SAMPLING_INTERVAL_MS)
-#define INNER_WINDOW \
- (CONFIG_GESTURE_TAP_INNER_WINDOW_T / \
- CONFIG_GESTURE_SAMPLING_INTERVAL_MS)
-#define MIN_INTERSTICE \
- (CONFIG_GESTURE_TAP_MIN_INTERSTICE_T / \
- CONFIG_GESTURE_SAMPLING_INTERVAL_MS)
-#define MAX_INTERSTICE \
- (CONFIG_GESTURE_TAP_MAX_INTERSTICE_T / \
- CONFIG_GESTURE_SAMPLING_INTERVAL_MS)
-#define MAX_WINDOW OUTER_WINDOW
-
-/* State machine states for detecting double tap */
-enum tap_states {
- /* Look for calm before the storm */
- TAP_IDLE,
- /* Record first Z impulse */
- TAP_IMPULSE_1,
-
- /* Eye of the storm, expect Z motion to drop and then suddenly spike */
- TAP_INTERSTICE_DROP,
- TAP_INTERSTICE_RISE,
-
- /* Record second Z impulse */
- TAP_IMPULSE_2,
- /* Should be quiet after the storm */
- TAP_AFTER_EVENT
-};
-
-/* Tap sensor to use */
-static struct motion_sensor_t *sensor =
-&motion_sensors[CONFIG_GESTURE_TAP_SENSOR];
-
-/* Tap state information */
-static int history_z[MAX_WINDOW]; /* Changes in Z */
-static int history_xy[MAX_WINDOW]; /* Changes in X and Y */
-static int state, history_idx;
-static int history_initialized, history_init_index;
-static int tap_debug;
-
-/* Tap detection flag */
-static int tap_detection;
-
-/*
- * TODO(crosbug.com/p/33102): Cleanup this function: break into multiple
- * functions and generalize so it can be used for other boards.
- */
-static int gesture_tap_for_battery(void)
-{
- /* Current and previous accel x,y,z */
- int x, y, z;
- static int x_p, y_p, z_p;
-
- /* Number of iterations in this state */
- static int state_cnt;
-
- /*
- * Running sums of data diffs for inner and outer windows.
- * Z data kept separate from X and Y data
- */
- static int sum_z_inner, sum_z_outer, sum_xy_inner, sum_xy_outer;
-
- /* Total variation in each signal, normalized for window size */
- int delta_z_outer, delta_z_inner, delta_xy_outer, delta_xy_inner;
-
- /* Max variation seen during tap event and state cnts since max */
- static int delta_z_inner_max;
- static int cnts_since_max;
-
- /* Interstice Z motion thresholds */
- static int z_drop_thresh, z_rise_thresh;
-
- int history_idx_inner, state_p;
- int ret = 0;
-
- /* Get data */
- x = sensor->xyz[0];
- y = sensor->xyz[1];
- z = sensor->xyz[2];
-
- /*
- * Calculate history of change in Z sensor and keeping
- * running sums for the past.
- */
- history_idx_inner = history_idx - INNER_WINDOW;
- if (history_idx_inner < 0)
- history_idx_inner += MAX_WINDOW;
- sum_z_inner -= history_z[history_idx_inner];
- sum_z_outer -= history_z[history_idx];
- history_z[history_idx] = ABS(z - z_p);
- sum_z_inner += history_z[history_idx];
- sum_z_outer += history_z[history_idx];
-
- /*
- * Calculate history of change in X and Y sensors combined
- * and keep a running sum of the change over the past.
- */
- sum_xy_inner -= history_xy[history_idx_inner];
- sum_xy_outer -= history_xy[history_idx];
- history_xy[history_idx] = ABS(x - x_p) + ABS(y - y_p);
- sum_xy_inner += history_xy[history_idx];
- sum_xy_outer += history_xy[history_idx];
-
- /* Increment history index */
- history_idx = (history_idx == MAX_WINDOW - 1) ? 0 : (history_idx + 1);
-
- /* Store previous X, Y, Z data */
- x_p = x;
- y_p = y;
- z_p = z;
-
- /*
- * Ignore data until we fill history buffer and wrap around. If
- * detection is paused, history_init_index will store the index
- * when paused, so that when re-started, we will wait until we
- * wrap around again.
- */
- if (history_idx == history_init_index)
- history_initialized = 1;
- if (!history_initialized)
- return 0;
-
- /*
- * Normalize data based on window size and isolate outer and inner
- * window data.
- */
- delta_z_outer = (sum_z_outer - sum_z_inner) * 1000 /
- (OUTER_WINDOW - INNER_WINDOW);
- delta_z_inner = sum_z_inner * 1000 / INNER_WINDOW;
- delta_xy_outer = (sum_xy_outer - sum_xy_inner) * 1000 /
- (OUTER_WINDOW - INNER_WINDOW);
- delta_xy_inner = sum_xy_inner * 1000 / INNER_WINDOW;
-
- state_cnt++;
- state_p = state;
-
- switch (state) {
- case TAP_IDLE:
- /* Look for a sudden increase in Z movement */
- if (delta_z_inner > 30000 &&
- delta_z_inner > 13 * delta_z_outer &&
- delta_z_inner > 1 * delta_xy_inner) {
- delta_z_inner_max = delta_z_inner;
- state_cnt = 0;
- state = TAP_IMPULSE_1;
- }
- break;
-
- case TAP_IMPULSE_1:
- /* Find the peak inner window of Z movement */
- if (delta_z_inner > delta_z_inner_max) {
- delta_z_inner_max = delta_z_inner;
- cnts_since_max = state_cnt;
- }
-
- /* After inner window has passed, move to next state */
- if (state_cnt >= INNER_WINDOW) {
- state = TAP_INTERSTICE_DROP;
- z_drop_thresh = delta_z_inner_max / 12;
- z_rise_thresh = delta_z_inner_max / 3;
- state_cnt += INNER_WINDOW - cnts_since_max;
- }
- break;
-
- case TAP_INTERSTICE_DROP:
- /* Check for z motion to go back down first */
- if (delta_z_inner < z_drop_thresh)
- state = TAP_INTERSTICE_RISE;
-
- if (state_cnt > MAX_INTERSTICE)
- state = TAP_IDLE;
-
- break;
-
- case TAP_INTERSTICE_RISE:
- /* Then, check for z motion to go back up */
- if (delta_z_inner > z_rise_thresh) {
- if (state_cnt < MIN_INTERSTICE) {
- state = TAP_IDLE;
- } else {
- delta_z_inner_max = delta_z_inner;
- state_cnt = 0;
- state = TAP_IMPULSE_2;
- }
- }
-
- if (state_cnt > MAX_INTERSTICE)
- state = TAP_IDLE;
- break;
-
- case TAP_IMPULSE_2:
- /* Find the peak inner window of Z movement */
- if (delta_z_inner > delta_z_inner_max) {
- delta_z_inner_max = delta_z_inner;
- cnts_since_max = state_cnt;
- }
-
- /* After inner window has passed, move to next state */
- if (state_cnt >= INNER_WINDOW) {
- state = TAP_AFTER_EVENT;
- state_cnt += INNER_WINDOW - cnts_since_max;
- }
-
- case TAP_AFTER_EVENT:
- /* Check for small Z movement after the event */
- if (state_cnt < OUTER_WINDOW)
- break;
-
- if (2 * delta_z_inner_max > 3 * delta_z_outer &&
- delta_z_outer > 1 * delta_xy_outer)
- ret = 1;
-
- state = TAP_IDLE;
- break;
- }
-
- /* On state transitions, print debug info */
- if (tap_debug &&
- (state != state_p ||
- (state_cnt % 10000 == 9999))) {
- /* make sure we don't divide by 0 */
- if (delta_z_outer == 0 || delta_xy_inner == 0)
- CPRINTS("tap st %d->%d, error div by 0",
- state_p, state);
- else
- CPRINTS("tap st %d->%d, st_cnt %-3d "
- "Z_in:Z_out %-3d, Z_in:XY_in %-3d "
- "dZ_in %-8.3d, dZ_in_max %-8.3d, "
- "dZ_out %-8.3d",
- state_p, state, state_cnt,
- delta_z_inner / delta_z_outer,
- delta_z_inner / delta_xy_inner,
- delta_z_inner,
- delta_z_inner_max,
- delta_z_outer);
- }
-
- return ret;
-}
-
-static void gesture_chipset_resume(void)
-{
- /* disable tap detection */
- tap_detection = 0;
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, gesture_chipset_resume,
- GESTURE_HOOK_PRIO);
-
-static void gesture_chipset_suspend(void)
-{
- /*
- * Clear tap init and history initialized so that we have to
- * record a whole new set of data, and enable tap detection
- */
- history_initialized = 0;
- history_init_index = history_idx;
- state = TAP_IDLE;
- tap_detection = 1;
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, gesture_chipset_suspend,
- GESTURE_HOOK_PRIO);
-
-void gesture_calc(uint32_t *event)
-{
- /* Only check for gesture if lid is closed and tap detection is on */
- if (!tap_detection || lid_is_open())
- return;
-
- if (gesture_tap_for_battery())
- *event |= TASK_EVENT_MOTION_ACTIVITY_INTERRUPT(
- MOTIONSENSE_ACTIVITY_DOUBLE_TAP);
-}
-
-/*****************************************************************************/
-/* Console commands */
-static int command_tap_info(int argc, char **argv)
-{
- int val;
-
- ccprintf("tap: %s\n", (tap_detection && !lid_is_open()) ?
- "on" : "off");
-
- if (argc > 1) {
- if (!parse_bool(argv[1], &val))
- return EC_ERROR_PARAM1;
- tap_debug = val;
- }
-
- ccprintf("debug: %s\n", tap_debug ? "on" : "off");
- ccprintf("odr: %d\n", sensor->drv->get_data_rate(sensor));
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(tapinfo, command_tap_info,
- "debug on/off",
- "Print tap information");
-