summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-04-08 10:28:29 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-04-10 00:10:07 +0000
commit0abb7a45d973a5d612d901726588db78e4679720 (patch)
tree0f2e1c72f7b8699fafdda85c3068dd39e4283b9d
parentda755350cfddfc0483cb4d95d5899027f70c5436 (diff)
downloadchrome-ec-0abb7a45d973a5d612d901726588db78e4679720.tar.gz
accel: Add host cmd for setting lid angle threshold for disabling keyboard wake
Added a sub-command to the motionsense host command (0x2b) for getting/setting the lid angle at which the keyboard is disabled as a wake source in S3. The value can be anywhere from 0 to 360 degrees, default set to 180. Note, this only takes affect for boards that have CONFIG_LID_ANGLE_KEY_SCAN defined. Modified ectool motionsense command to use new host sub-command. Also modified the lid angle measurement in the EC to be in the range [0, 360], instead of [-180, 180], and changed casting of lid angle as an int to round to nearest. BUG=none BRANCH=rambi TEST=Tested on a glimmer: Using default keyboard disable lid angle of 180, made sure that when lid angle is past 180, key presses do not wake system, and when lid angle is less than 180, key presses do wake up system. Used ectool motionsense kb_wake to set the keyboard disable lid angle to 0. Made sure that keyboard never wakes up the system. Set keyboard disable lid angle to 360 and made sure that the keyboard always wakes up the system. Change-Id: I437164c6e38c29169ef6e20e86c9cf2a1c78f86e Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/193663 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/clapper/board.h12
-rw-r--r--board/glimmer/board.h12
-rw-r--r--common/lid_angle.c92
-rw-r--r--common/motion_sense.c30
-rw-r--r--include/config.h5
-rw-r--r--include/ec_commands.h21
-rw-r--r--include/lid_angle.h8
-rw-r--r--include/motion_sense.h5
-rw-r--r--test/motion_sense.c4
-rw-r--r--util/ectool.c25
10 files changed, 173 insertions, 41 deletions
diff --git a/board/clapper/board.h b/board/clapper/board.h
index a3d9c693f8..8cbde47b90 100644
--- a/board/clapper/board.h
+++ b/board/clapper/board.h
@@ -71,18 +71,6 @@
#define WIRELESS_GPIO_WWAN GPIO_PP3300_LTE_EN
#define WIRELESS_GPIO_WLAN_POWER GPIO_PP3300_WLAN_EN
-/*
- * Macros to be used in suspend to determine the state of key scanning
- * based on measured lid angle. Note that the angle input is bound [-180, 180]
- * where 0 degrees is lid closed/lid fully open. Also note that the key scan
- * enable state will only change if recent readings are all within range,
- * therefore it is recommended to leave a deadband where the lid angle doesn't
- * fit into either range. Also note, if lid is closed, key scanning is
- * automatically disabled.
- */
-#define LID_IN_RANGE_TO_ACCEPT_KEYS(ang) ((ang) >= 15 || (ang) <= -173)
-#define LID_IN_RANGE_TO_IGNORE_KEYS(ang) ((ang) <= 12 && (ang) >= -170)
-
/* GPIO signal definitions. */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/board/glimmer/board.h b/board/glimmer/board.h
index 792e55f851..9ce971e3ea 100644
--- a/board/glimmer/board.h
+++ b/board/glimmer/board.h
@@ -79,18 +79,6 @@
#define WIRELESS_GPIO_WWAN GPIO_PP3300_LTE_EN
#define WIRELESS_GPIO_WLAN_POWER GPIO_PP3300_WLAN_EN
-/*
- * Macros to be used in suspend to determine the state of key scanning
- * based on measured lid angle. Note that the angle input is bound [-180, 180]
- * where 0 degrees is lid closed/lid fully open. Also note that the key scan
- * enable state will only change if recent readings are all within range,
- * therefore it is recommended to leave a deadband where the lid angle doesn't
- * fit into either range. Also note, if lid is closed, key scanning is
- * automatically disabled.
- */
-#define LID_IN_RANGE_TO_ACCEPT_KEYS(ang) ((ang) >= 15 || (ang) <= -173)
-#define LID_IN_RANGE_TO_IGNORE_KEYS(ang) ((ang) <= 12 && (ang) >= -170)
-
/* GPIO signal definitions. */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/common/lid_angle.c b/common/lid_angle.c
index e7a3139ebb..02f72f1991 100644
--- a/common/lid_angle.c
+++ b/common/lid_angle.c
@@ -25,6 +25,94 @@
*/
#define KEY_SCAN_LID_ANGLE_BUFFER_SIZE 4
+/*
+ * Define two variables to determine if keyboard scanning should be enabled
+ * or disabled in S3 based on the current lid angle. Note, the lid angle is
+ * bound to [0, 360]. Here are two angles, defined such that we segregate the
+ * lid angle space into two regions. The first region is the region in which
+ * we enable keyboard scanning in S3 and is when the lid angle CCW of the
+ * small_angle and CW of the large_angle. The second region is the region in
+ * which we disable keyboard scanning in S3 and is when the lid angle is CCW
+ * of the large_angle and CW of the small_angle.
+ *
+ * Note, the most sensical values are small_angle = 0 and large_angle = 180,
+ * but, the angle measurement is not perfect, and we know that if the angle is
+ * near 0 and the lid isn't closed, then the lid must be near 360. So, the
+ * small_angle is set to a small positive value to make sure we don't swap modes
+ * when the lid is open all the way but is measuring a small positive value.
+ */
+static int kb_wake_large_angle = 180;
+static const int kb_wake_small_angle = 13;
+
+/* Define hysteresis value to add stability to the keyboard scanning flag. */
+#define KB_DIS_HYSTERESIS_DEG 2
+
+/* Define max and min values for kb_wake_large_angle. */
+#define KB_DIS_MIN_LARGE_ANGLE 0
+#define KB_DIS_MAX_LARGE_ANGLE 360
+
+/**
+ * Determine if given angle is in region to accept keyboard presses.
+ *
+ * @param ang Some lid angle in degrees [0, 360]
+ *
+ * @return true/false
+ */
+static int lid_in_range_to_accept_keys(float ang)
+{
+ /*
+ * If the keyboard wake large angle is min or max, then this
+ * function should return false or true respectively, independent of
+ * input angle.
+ */
+ if (kb_wake_large_angle == KB_DIS_MIN_LARGE_ANGLE)
+ return 0;
+ else if (kb_wake_large_angle == KB_DIS_MAX_LARGE_ANGLE)
+ return 1;
+
+ return (ang >= (kb_wake_small_angle + KB_DIS_HYSTERESIS_DEG)) &&
+ (ang <= (kb_wake_large_angle - KB_DIS_HYSTERESIS_DEG));
+}
+
+/**
+ * Determine if given angle is in region to ignore keyboard presses.
+ *
+ * @param ang Some lid angle in degrees [0, 360]
+ *
+ * @return true/false
+ */
+static int lid_in_range_to_ignore_keys(float ang)
+{
+ /*
+ * If the keyboard wake large angle is min or max, then this
+ * function should return true or false respectively, independent of
+ * input angle.
+ */
+ if (kb_wake_large_angle == KB_DIS_MIN_LARGE_ANGLE)
+ return 1;
+ else if (kb_wake_large_angle == KB_DIS_MAX_LARGE_ANGLE)
+ return 0;
+
+ return (ang <= (kb_wake_small_angle - KB_DIS_HYSTERESIS_DEG)) ||
+ (ang >= (kb_wake_large_angle + KB_DIS_HYSTERESIS_DEG));
+}
+
+
+int lid_angle_get_kb_wake_angle(void)
+{
+ return kb_wake_large_angle;
+}
+
+void lid_angle_set_kb_wake_angle(int ang)
+{
+ if (ang < KB_DIS_MIN_LARGE_ANGLE)
+ ang = KB_DIS_MIN_LARGE_ANGLE;
+ else if (ang > KB_DIS_MAX_LARGE_ANGLE)
+ ang = KB_DIS_MAX_LARGE_ANGLE;
+
+ kb_wake_large_angle = ang;
+}
+
void lidangle_keyscan_update(float lid_ang)
{
static float lidangle_buffer[KEY_SCAN_LID_ANGLE_BUFFER_SIZE];
@@ -60,9 +148,9 @@ void lidangle_keyscan_update(float lid_ang)
* in range of one of the conditions in order to change
* to the corresponding key scanning state.
*/
- if (!LID_IN_RANGE_TO_ACCEPT_KEYS(lidangle_buffer[i]))
+ if (!lid_in_range_to_accept_keys(lidangle_buffer[i]))
keys_accept = 0;
- if (!LID_IN_RANGE_TO_IGNORE_KEYS(lidangle_buffer[i]))
+ if (!lid_in_range_to_ignore_keys(lidangle_buffer[i]))
keys_ignore = 0;
}
diff --git a/common/motion_sense.c b/common/motion_sense.c
index 1fb158b7c9..d48b578cd1 100644
--- a/common/motion_sense.c
+++ b/common/motion_sense.c
@@ -133,6 +133,10 @@ static int calculate_lid_angle(vector_3_t base, vector_3_t lid,
if (ang_lid_270 > ang_lid_90)
ang_lid_to_base = -ang_lid_to_base;
+ /* Place lid angle between 0 and 360 degrees. */
+ if (ang_lid_to_base < 0)
+ ang_lid_to_base += 360;
+
*lid_angle = ang_lid_to_base;
return reliable;
}
@@ -140,7 +144,11 @@ static int calculate_lid_angle(vector_3_t base, vector_3_t lid,
int motion_get_lid_angle(void)
{
if (lid_angle_is_reliable)
- return (int)lid_angle_deg;
+ /*
+ * Round to nearest int by adding 0.5. Note, only works because
+ * lid angle is known to be positive.
+ */
+ return (int)(lid_angle_deg + 0.5F);
else
return (int)LID_ANGLE_UNRELIABLE;
}
@@ -253,7 +261,11 @@ void motion_sense_task(void)
/*
* Copy sensor data to shared memory. Note that this code
- * assumes little endian, which is what the host expects.
+ * assumes little endian, which is what the host expects. Also,
+ * note that we share the lid angle calculation with host only
+ * for debugging purposes. The EC lid angle is an approximation
+ * with un-calibrated accels. The AP calculates a separate,
+ * more accurate lid angle.
*/
lpc_data[0] = motion_get_lid_angle();
lpc_data[1] = acc_base_host[X];
@@ -467,6 +479,20 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
args->response_size = sizeof(out->sensor_range);
break;
+ case MOTIONSENSE_CMD_KB_WAKE_ANGLE:
+#ifdef CONFIG_LID_ANGLE_KEY_SCAN
+ /* Set new keyboard wake lid angle if data arg has value. */
+ if (in->kb_wake_angle.data != EC_MOTION_SENSE_NO_VALUE)
+ lid_angle_set_kb_wake_angle(in->kb_wake_angle.data);
+
+ out->kb_wake_angle.ret = lid_angle_get_kb_wake_angle();
+#else
+ out->kb_wake_angle.ret = 0;
+#endif
+ args->response_size = sizeof(out->kb_wake_angle);
+
+ break;
+
default:
CPRINTF("[%T MS bad cmd 0x%x]\n", in->cmd);
return EC_RES_INVALID_PARAM;
diff --git a/include/config.h b/include/config.h
index 048033d793..73ca90fc83 100644
--- a/include/config.h
+++ b/include/config.h
@@ -536,11 +536,6 @@
/*
* Allows using the lid angle measurement to determine if key scanning should
* be enabled or disabled when chipset is suspended.
- *
- * Any board that defines this must also define two macros:
- * LID_IN_RANGE_TO_ACCEPT_KEYS(angle), LID_IN_RANGE_TO_IGNORE_KEYS(angle).
- * These macros should return true if the given angle argument is in range
- * to accept or ignore key presses.
*/
#undef CONFIG_LID_ANGLE_KEY_SCAN
diff --git a/include/ec_commands.h b/include/ec_commands.h
index f71848a707..de47135d53 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1190,6 +1190,15 @@ enum motionsense_command {
*/
MOTIONSENSE_CMD_SENSOR_RANGE = 4,
+ /*
+ * Setter/getter command for the keyboard wake angle. When the lid
+ * angle is greater than this value, keyboard wake is disabled in S3,
+ * and when the lid angle goes less than this value, keyboard wake is
+ * enabled. Note, the lid angle measurement is an approximate,
+ * un-calibrated value, hence the wake angle isn't exact.
+ */
+ MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5,
+
/* Number of motionsense sub-commands. */
MOTIONSENSE_NUM_CMDS
};
@@ -1244,11 +1253,14 @@ struct ec_params_motion_sense {
/* no args */
} dump;
- /* Used for MOTIONSENSE_CMD_EC_RATE. */
+ /*
+ * Used for MOTIONSENSE_CMD_EC_RATE and
+ * MOTIONSENSE_CMD_KB_WAKE_ANGLE.
+ */
struct {
/* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */
int16_t data;
- } ec_rate;
+ } ec_rate, kb_wake_angle;
/* Used for MOTIONSENSE_CMD_INFO. */
struct {
@@ -1303,12 +1315,13 @@ struct ec_response_motion_sense {
/*
* Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR,
- * and MOTIONSENSE_CMD_SENSOR_RANGE.
+ * MOTIONSENSE_CMD_SENSOR_RANGE, and
+ * MOTIONSENSE_CMD_KB_WAKE_ANGLE.
*/
struct {
/* Current value of the parameter queried. */
int32_t ret;
- } ec_rate, sensor_odr, sensor_range;
+ } ec_rate, sensor_odr, sensor_range, kb_wake_angle;
};
} __packed;
diff --git a/include/lid_angle.h b/include/lid_angle.h
index bd60b90907..cd13265c93 100644
--- a/include/lid_angle.h
+++ b/include/lid_angle.h
@@ -17,4 +17,12 @@
*/
void lidangle_keyscan_update(float lid_ang);
+/**
+ * Getter and setter methods for the keyboard wake angle. In S3, when the
+ * lid angle is greater than this value, the keyboard is disabled, and when
+ * the lid angle is smaller than this value, the keyboard is enabled.
+ */
+int lid_angle_get_kb_wake_angle(void);
+void lid_angle_set_kb_wake_angle(int ang);
+
#endif /* __CROS_EC_LID_ANGLE_H */
diff --git a/include/motion_sense.h b/include/motion_sense.h
index d0c2774254..3a3b9b5121 100644
--- a/include/motion_sense.h
+++ b/include/motion_sense.h
@@ -53,9 +53,10 @@ struct accel_orientation acc_orient;
/**
- * Get last calculated lid angle.
+ * Get last calculated lid angle. Note, the lid angle calculated by the EC
+ * is un-calibrated and is an approximate angle.
*
- * @return lid angle in degrees in range [-180, 180].
+ * @return lid angle in degrees in range [0, 360].
*/
int motion_get_lid_angle(void);
diff --git a/test/motion_sense.c b/test/motion_sense.c
index ab07a41e96..1ec3d4ad60 100644
--- a/test/motion_sense.c
+++ b/test/motion_sense.c
@@ -86,13 +86,13 @@ static int test_lid_angle(void)
msleep(5);
TEST_ASSERT(motion_get_lid_angle() == 90);
- /* Set lid open to -135. */
+ /* Set lid open to 225. */
mock_x_acc[ACCEL_LID] = 500;
mock_y_acc[ACCEL_LID] = 0;
mock_z_acc[ACCEL_LID] = -500;
task_wake(TASK_ID_MOTIONSENSE);
msleep(5);
- TEST_ASSERT(motion_get_lid_angle() == -135);
+ TEST_ASSERT(motion_get_lid_angle() == 225);
/*
* Align base with hinge and make sure it returns unreliable for angle.
diff --git a/util/ectool.c b/util/ectool.c
index 62f2799453..6636e6eb71 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -1669,6 +1669,7 @@ static const struct {
MS_SIZES(ec_rate),
MS_SIZES(sensor_odr),
MS_SIZES(sensor_range),
+ MS_SIZES(kb_wake_angle),
};
BUILD_ASSERT(ARRAY_SIZE(ms_command_sizes) == MOTIONSENSE_NUM_CMDS);
#undef MS_SIZES
@@ -1682,6 +1683,7 @@ static int ms_help(const char *cmd)
printf(" %s ec_rate [RATE_MS] - set/get sample rate\n", cmd);
printf(" %s odr NUM [ODR [ROUNDUP]] - set/get sensor ODR\n", cmd);
printf(" %s range NUM [RANGE [ROUNDUP]]- set/get sensor range\n", cmd);
+ printf(" %s kb_wake NUM - set/get KB wake ang\n", cmd);
return 0;
}
@@ -1902,6 +1904,29 @@ static int cmd_motionsense(int argc, char **argv)
return 0;
}
+ if (argc < 4 && !strcasecmp(argv[1], "kb_wake")) {
+ param.cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE;
+ param.kb_wake_angle.data = EC_MOTION_SENSE_NO_VALUE;
+
+ if (argc == 3) {
+ param.kb_wake_angle.data = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad %s arg.\n", argv[1]);
+ return -1;
+ }
+ }
+
+ rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 0,
+ &param, ms_command_sizes[param.cmd].insize,
+ &resp, ms_command_sizes[param.cmd].outsize);
+
+ if (rv < 0)
+ return rv;
+
+ printf("%d\n", resp.kb_wake_angle.ret);
+ return 0;
+ }
+
return ms_help(argv[0]);
}