summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
8 files changed, 173 insertions, 17 deletions
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 e89be9ca53..5a18ea4dee 100644
--- a/include/config.h
+++ b/include/config.h
@@ -576,11 +576,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 439e871d77..eac00da6b3 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1200,6 +1200,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
};
@@ -1254,11 +1263,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 {
@@ -1313,12 +1325,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 f8c1b13339..4d827f52af 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -1702,6 +1702,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
@@ -1715,6 +1716,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;
}
@@ -1935,6 +1937,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]);
}