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
BUG=chrome-os-partner:44400
TEST=check in a dark room (30~40 lux) there is no flickering.
Add unit test.

Change-Id: I4018e2c2ed764abf9c9ed28e2d50a3e94a7d5f75
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/308205
This commit is contained in:
Gwendal Grignou
2015-10-22 14:13:35 -07:00
committed by chrome-bot
parent 3fc374b7fd
commit 81d269dc00
6 changed files with 96 additions and 23 deletions

View File

@@ -456,10 +456,11 @@ struct motion_sensor_t motion_sensors[] = {
};
const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors);
struct lb_brightness_def lb_brightness_levels[] = {
const struct lb_brightness_def lb_brightness_levels[] = {
{
/* regular brightness */
.lux = 40,
.lux_up = 60,
.lux_down = 40,
.color = {
{0x74, 0x58, 0xb4}, /* Segment0: Google blue */
{0xd6, 0x40, 0x20}, /* Segment1: Google red */
@@ -469,7 +470,8 @@ struct lb_brightness_def lb_brightness_levels[] = {
},
{
/* 25 - 50% brightness */
.lux = 20,
.lux_up = 40,
.lux_down = 20,
.color = {
{0x51, 0x38, 0x7d},
{0x99, 0x28, 0x15},
@@ -479,7 +481,8 @@ struct lb_brightness_def lb_brightness_levels[] = {
},
{
/* 0 .. 25% brightness */
.lux = 0,
.lux_up = 0,
.lux_down = 0,
.color = {
{0x3d, 0x28, 0x5c},
{0x71, 0x28, 0x10},

View File

@@ -204,7 +204,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;
@@ -219,18 +219,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;
return i;
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;
if (i < google_color_id) {
google_color_id = i;
return 1;
}
return 0;
}
#endif
@@ -239,9 +258,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;
@@ -289,12 +305,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
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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();
}

View File

@@ -109,6 +109,7 @@ int ncp15wb_calculate_temp(uint16_t adc);
#ifdef TEST_LIGHTBAR
#define CONFIG_I2C
#define I2C_PORT_LIGHTBAR 0
#define CONFIG_ALS_LIGHTBAR_DIMMING 0
#endif
#ifdef TEST_USB_PD