diff options
-rw-r--r-- | board/clapper/board.h | 12 | ||||
-rw-r--r-- | board/glimmer/board.h | 12 | ||||
-rw-r--r-- | common/lid_angle.c | 92 | ||||
-rw-r--r-- | common/motion_sense.c | 30 | ||||
-rw-r--r-- | include/config.h | 5 | ||||
-rw-r--r-- | include/ec_commands.h | 21 | ||||
-rw-r--r-- | include/lid_angle.h | 8 | ||||
-rw-r--r-- | include/motion_sense.h | 5 | ||||
-rw-r--r-- | test/motion_sense.c | 4 | ||||
-rw-r--r-- | util/ectool.c | 25 |
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, + ¶m, 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]); } |