From 4deef677cdad11b1d6ffff035574ba7fdb9dd4ea Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Thu, 22 Oct 2015 14:13:35 -0700 Subject: BACKPORT: common: lightbar: Add histeresis to prevent flickering When ALS is enabled, if light is around one threshold (say 40 lux), the lightbar will flicker between readings. Add a histeresis to prevent the flickering. The current setting is: setting ^ (dim) 2 | ------+---->---+ 1 | +----<---+--->---+ (bright) 0 | +---<---+--------- +-------+--------+-------+--------> lux 20 40 60 BRANCH=smaug, cyan BUG=chrome-os-partner:44400, b:27849483 TEST=check in a dark room (30~40 lux) there is no flickering. Add unit test. Change-Id: I4018e2c2ed764abf9c9ed28e2d50a3e94a7d5f75 Signed-off-by: Gwendal Grignou Reviewed-on: https://chromium-review.googlesource.com/308205 (cherry picked from commit 81d269dc004b6c7334e4e8eafbb2872e5b6fdcf1) Signed-off-by: Gwendal Grignou Reviewed-on: https://chromium-review.googlesource.com/359392 --- common/lightbar.c | 45 +++++++++++++++++++++++++++++---------------- include/lightbar.h | 8 +++++--- include/motion_sense.h | 5 +++++ test/lightbar.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ test/test_config.h | 4 +++- 5 files changed, 91 insertions(+), 20 deletions(-) diff --git a/common/lightbar.c b/common/lightbar.c index 3a1e005c9e..94e79fa43d 100644 --- a/common/lightbar.c +++ b/common/lightbar.c @@ -195,7 +195,7 @@ static void lightbar_restore_state(void) static int last_backlight_level; #endif #ifdef CONFIG_ALS_LIGHTBAR_DIMMING -static int last_google_color = -1; +test_export_static int google_color_id; #endif static int demo_mode = DEMO_MODE_DEFAULT; @@ -210,18 +210,37 @@ static int quantize_battery_level(int pct) } #ifdef CONFIG_ALS_LIGHTBAR_DIMMING -static int lux_level_to_google_color(int lux) +test_export_static int lux_level_to_google_color(const int lux) { int i; - if (!lid_is_open()) + if (!lid_is_open()) { /* The lid shades the light sensor, use full brightness. */ - return 0; + if (google_color_id != 0) { + google_color_id = 0; + return 1; + } else { + return 0; + } + } - for (i = 0; i < lb_brightness_levels_count ; i++) - if (lux >= lb_brightness_levels[i].lux) + /* See if we need to decrease brightness */ + for (i = google_color_id; i < lb_brightness_levels_count ; i++) + if (lux >= lb_brightness_levels[i].lux_down) + break; + if (i > google_color_id) { + google_color_id = i; + return 1; + } + /* See if we need to increase brightness */ + for (i = google_color_id; i > 0; i--) + if (lux < lb_brightness_levels[i - 1].lux_up) break; - return i; + if (i < google_color_id) { + google_color_id = i; + return 1; + } + return 0; } #endif @@ -230,9 +249,6 @@ static void get_battery_level(void) { int pct = 0; int bl; -#ifdef CONFIG_ALS_LIGHTBAR_DIMMING - int color_id; -#endif if (demo_mode) return; @@ -282,12 +298,9 @@ static void get_battery_level(void) #ifdef CONFIG_ALS_LIGHTBAR_DIMMING /* Read last value (in lux) collected by the motion sensor. */ /* Convert lux into brightness percentage */ - color_id = lux_level_to_google_color(MOTION_SENSE_LUX); - - if (color_id != last_google_color) { - last_google_color = pct; - memcpy(st.p.color, lb_brightness_levels[color_id].color, - sizeof(lb_brightness_levels[color_id].color)); + if (lux_level_to_google_color(MOTION_SENSE_LUX)) { + memcpy(st.p.color, lb_brightness_levels[google_color_id].color, + sizeof(lb_brightness_levels[google_color_id].color)); } #endif } diff --git a/include/lightbar.h b/include/lightbar.h index 8648e3f3bd..61ee5a2a9d 100644 --- a/include/lightbar.h +++ b/include/lightbar.h @@ -38,17 +38,19 @@ enum lb_control { /* * For dimming the lightbar in the dark, we define an array to * describe the expected colors: - * if luminosity is more than 'lux', the color defined will be used. + * if luminosity is more than 'lux_up', the color defined will be used. + * if luminosity is more than 'lux_down', we will look at the next band. * The last entry must have lux == 0. * Defining brightness is not enough to prevent washed color in low * lux setting. */ struct lb_brightness_def { - uint16_t lux; + uint16_t lux_up; + uint16_t lux_down; struct rgb_s color[4]; }; -extern struct lb_brightness_def lb_brightness_levels[]; +extern const struct lb_brightness_def lb_brightness_levels[]; extern const unsigned lb_brightness_levels_count; #endif diff --git a/include/motion_sense.h b/include/motion_sense.h index ed24f232fd..aa4170b722 100644 --- a/include/motion_sense.h +++ b/include/motion_sense.h @@ -187,6 +187,11 @@ void motion_sense_fifo_add_unit(struct ec_response_motion_sensor_data *data, #endif #ifdef CONFIG_ALS_LIGHTBAR_DIMMING +#ifdef TEST_BUILD +#define MOTION_SENSE_LUX 0 +#else #define MOTION_SENSE_LUX motion_sensors[CONFIG_ALS_LIGHTBAR_DIMMING].raw_xyz[0] #endif +#endif + #endif /* __CROS_EC_MOTION_SENSE_H */ diff --git a/test/lightbar.c b/test/lightbar.c index 3aae1e71f3..8a21c1fc62 100644 --- a/test/lightbar.c +++ b/test/lightbar.c @@ -11,6 +11,7 @@ #include "timer.h" #include "util.h" + static int get_seq(void) { int rv; @@ -272,6 +273,53 @@ static int test_stable_states(void) return EC_SUCCESS; } +const struct lb_brightness_def lb_brightness_levels[] = { + { + /* regular brightness */ + .lux_up = 60, + .lux_down = 40, + }, + { + /* 25 - 50% brightness */ + .lux_up = 40, + .lux_down = 20, + }, + { + /* 0 .. 25% brightness */ + .lux_up = 0, + .lux_down = 0, + }, +}; +const unsigned int lb_brightness_levels_count = + ARRAY_SIZE(lb_brightness_levels); + +int lux_level_to_google_color(const int lux); +extern int google_color_id; + +int lid_is_open(void) +{ + return 1; +} + +static int test_als_lightbar(void) +{ + int lux_data[] = { 500, 100, 35, 15, 30, 35, 55, 70, 55, 100 }; + int exp_gcid[] = { 0, 0, 1, 2, 2, 2, 1, 0, 0, 0 }; + int exp_chg[] = { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0 }; + int i; + + BUILD_ASSERT(ARRAY_SIZE(lux_data) == ARRAY_SIZE(exp_gcid)); + BUILD_ASSERT(ARRAY_SIZE(lux_data) == ARRAY_SIZE(exp_chg)); + + google_color_id = 0; + for (i = 0; i < ARRAY_SIZE(lux_data); i++) { + TEST_ASSERT(exp_chg[i] == + lux_level_to_google_color(lux_data[i])); + TEST_ASSERT(exp_gcid[i] == google_color_id); + } + return EC_SUCCESS; +} + void run_test(void) { RUN_TEST(test_stable_states); @@ -280,5 +328,6 @@ void run_test(void) RUN_TEST(test_stop_timeout); RUN_TEST(test_oneshots_norm_msg); RUN_TEST(test_double_oneshots); + RUN_TEST(test_als_lightbar); test_print_result(); } diff --git a/test/test_config.h b/test/test_config.h index 8cdb12d1d8..0b1608001d 100644 --- a/test/test_config.h +++ b/test/test_config.h @@ -103,7 +103,9 @@ int bd99992gw_get_temp(uint16_t adc); #endif #ifdef TEST_LIGHTBAR -#define I2C_PORT_LIGHTBAR 1 +#define CONFIG_I2C +#define I2C_PORT_LIGHTBAR 0 +#define CONFIG_ALS_LIGHTBAR_DIMMING 0 #endif #ifdef TEST_USB_PD -- cgit v1.2.1