summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-04-22 14:56:51 +0800
committerChromeBot <chrome-bot@google.com>2013-04-23 23:06:14 -0700
commitcb5407d8e70b9a261a76d4a841973984916a9617 (patch)
treeb25e55bfce2f9f52a208c110d513442596034118
parent7c06069001d32cba3ce0f5d041646d468dd69051 (diff)
downloadchrome-ec-cb5407d8e70b9a261a76d4a841973984916a9617.tar.gz
spring: Improve battery LED stability
Previously, we sometimes saw battery LED went off when going into or out of battery assist mode. This CL adds a state machine to stabilize battery LED. By controlling the state of lighting engine, the tranisition from/to battery assist mode is seamless now. BUG=chrome-os-partner:18844 TEST=On spring, check: 1. LED doesn't go off when going into battery assist mode. 2. LED doesn't suddenly change brightness when coming out of battery assist mode. 3. LED goes red after few seconds when battery is not present. 4. LED goes green when battery is charged. BRANCH=spring Change-Id: Ia640300d50beed49cd409dee60888db7ed08bebd Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/49011 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/spring/board.c188
1 files changed, 139 insertions, 49 deletions
diff --git a/board/spring/board.c b/board/spring/board.c
index 69efeee81f..69133c00ba 100644
--- a/board/spring/board.c
+++ b/board/spring/board.c
@@ -36,6 +36,19 @@
#define LED_COLOR_YELLOW LP5562_COLOR_BLUE
#define LED_COLOR_RED LP5562_COLOR_RED
+/* LED states */
+enum led_state_t {
+ LED_STATE_SOLID_RED,
+ LED_STATE_SOLID_GREEN,
+ LED_STATE_SOLID_YELLOW,
+ LED_STATE_TRANSITION_ON, /* Solid yellow -> breathing */
+ LED_STATE_TRANSITION_OFF, /* Breathing -> solid yellow */
+ LED_STATE_BREATHING,
+
+ /* Not an actual state */
+ LED_STATE_OFF,
+};
+
/* LED breathing program */
uint8_t breathing_prog[] = {0x41, 0xff, /* 0x80 -> 0x0 */
0x41, 0x7f, /* 0x0 -> 0x80 */
@@ -43,7 +56,10 @@ uint8_t breathing_prog[] = {0x41, 0xff, /* 0x80 -> 0x0 */
0x7f, 0x00,
0x7f, 0x00,
0x7f, 0x00,
- 0x00, 0x00}; /* Repeat */
+ 0x00, 0x00, /* Go to start */
+ 0x40, 0x80, /* Set PWM = 0x80 */
+ 0x00, 0x00}; /* Go to start */
+#define BREATHING_PROG_ENTRY 7
/* GPIO interrupt handlers prototypes */
#ifndef CONFIG_TASK_GAIAPOWER
@@ -315,43 +331,127 @@ int board_get_ac(void)
return vbus_good;
}
-int board_led_breathing(int enabled)
+static int stop_led_engine(void)
+{
+ int pc;
+ if (lp5562_get_engine_state(LP5562_ENG_SEL_1) == LP5562_ENG_STEP)
+ return 0; /* Not stopped */
+ pc = lp5562_get_pc(LP5562_ENG_SEL_1);
+ if (pc == 1) {
+ /* LED currently off. Ramp up. */
+ lp5562_engine_control(LP5562_ENG_STEP,
+ LP5562_ENG_HOLD,
+ LP5562_ENG_HOLD);
+ return 0;
+ }
+
+ lp5562_set_engine(LP5562_ENG_SEL_NONE,
+ LP5562_ENG_SEL_NONE,
+ LP5562_ENG_SEL_NONE);
+ lp5562_set_color(LED_COLOR_YELLOW);
+ return 1;
+}
+
+static int set_led_color(enum led_state_t state)
{
- int ret = 0;
-
- if (enabled) {
- ret |= lp5562_engine_load(LP5562_ENG_SEL_1,
- breathing_prog,
- sizeof(breathing_prog));
- ret |= lp5562_engine_control(LP5562_ENG_RUN,
- LP5562_ENG_HOLD,
- LP5562_ENG_HOLD);
- ret |= lp5562_set_engine(LP5562_ENG_SEL_NONE,
- LP5562_ENG_SEL_NONE,
- LP5562_ENG_SEL_1);
- } else {
- ret |= lp5562_engine_control(LP5562_ENG_HOLD,
- LP5562_ENG_HOLD,
- LP5562_ENG_HOLD);
- ret |= lp5562_set_engine(LP5562_ENG_SEL_NONE,
- LP5562_ENG_SEL_NONE,
- LP5562_ENG_SEL_NONE);
+ ASSERT(state != LED_STATE_TRANSITION_ON &&
+ state != LED_STATE_TRANSITION_OFF);
+
+ switch (state) {
+ case LED_STATE_SOLID_RED:
+ return lp5562_set_color(LED_COLOR_RED);
+ case LED_STATE_SOLID_GREEN:
+ return lp5562_set_color(LED_COLOR_GREEN);
+ case LED_STATE_SOLID_YELLOW:
+ case LED_STATE_BREATHING:
+ return lp5562_set_color(LED_COLOR_YELLOW);
+ default:
+ return EC_ERROR_UNKNOWN;
+ }
+}
+
+static void board_stablize_led(enum led_state_t desired_state)
+{
+ static enum led_state_t current_state = LED_STATE_OFF;
+ enum led_state_t next_state = LED_STATE_OFF;
+
+ /* TRANSITIONs are internal states */
+ ASSERT(desired_state != LED_STATE_TRANSITION_ON &&
+ desired_state != LED_STATE_TRANSITION_OFF);
+
+ if (desired_state == LED_STATE_OFF) {
+ current_state = LED_STATE_OFF;
+ return;
+ }
+
+ /* Determine next state */
+ switch (current_state) {
+ case LED_STATE_OFF:
+ case LED_STATE_SOLID_RED:
+ case LED_STATE_SOLID_GREEN:
+ if (desired_state == LED_STATE_BREATHING)
+ next_state = LED_STATE_SOLID_YELLOW;
+ else
+ next_state = desired_state;
+ set_led_color(next_state);
+ break;
+ case LED_STATE_SOLID_YELLOW:
+ if (desired_state == LED_STATE_BREATHING) {
+ next_state = LED_STATE_TRANSITION_ON;
+ lp5562_set_pc(LP5562_ENG_SEL_1, BREATHING_PROG_ENTRY);
+ lp5562_engine_control(LP5562_ENG_STEP,
+ LP5562_ENG_HOLD,
+ LP5562_ENG_HOLD);
+ } else {
+ next_state = desired_state;
+ set_led_color(next_state);
+ }
+ break;
+ case LED_STATE_BREATHING:
+ if (desired_state != LED_STATE_BREATHING) {
+ next_state = LED_STATE_TRANSITION_OFF;
+ lp5562_engine_control(LP5562_ENG_STEP,
+ LP5562_ENG_HOLD,
+ LP5562_ENG_HOLD);
+ } else {
+ next_state = LED_STATE_BREATHING;
+ }
+ break;
+ case LED_STATE_TRANSITION_ON:
+ if (desired_state == LED_STATE_BREATHING) {
+ next_state = LED_STATE_BREATHING;
+ lp5562_set_engine(LP5562_ENG_SEL_NONE,
+ LP5562_ENG_SEL_NONE,
+ LP5562_ENG_SEL_1);
+ lp5562_engine_control(LP5562_ENG_RUN,
+ LP5562_ENG_HOLD,
+ LP5562_ENG_HOLD);
+ } else {
+ next_state = LED_STATE_SOLID_YELLOW;
+ lp5562_engine_control(LP5562_ENG_HOLD,
+ LP5562_ENG_HOLD,
+ LP5562_ENG_HOLD);
+ }
+ break;
+ case LED_STATE_TRANSITION_OFF:
+ if (stop_led_engine())
+ next_state = LED_STATE_SOLID_YELLOW;
+ else
+ next_state = LED_STATE_TRANSITION_OFF;
+ break;
}
- return ret;
+ current_state = next_state;
}
static void board_battery_led_update(void)
{
int current;
int desired_current;
+ enum led_state_t state = LED_STATE_OFF;
/* Current states and next states */
- static uint32_t color = LED_COLOR_RED;
- static int breathing;
static int led_power = -1;
- int new_color = LED_COLOR_RED;
- int new_breathing = 0;
int new_led_power;
/* Determine LED power */
@@ -360,13 +460,12 @@ static void board_battery_led_update(void)
led_power = new_led_power;
if (new_led_power) {
lp5562_poweron();
+ lp5562_engine_load(LP5562_ENG_SEL_1,
+ breathing_prog,
+ sizeof(breathing_prog));
} else {
- color = LED_COLOR_NONE;
- if (breathing) {
- board_led_breathing(0);
- breathing = 0;
- }
lp5562_poweroff();
+ board_stablize_led(LED_STATE_OFF);
}
}
if (!new_led_power)
@@ -378,48 +477,39 @@ static void board_battery_led_update(void)
*/
switch (charge_get_state()) {
case ST_IDLE:
- new_color = LED_COLOR_GREEN;
+ state = LED_STATE_SOLID_GREEN;
break;
case ST_DISCHARGING:
/* Discharging with AC, must be battery assist */
- new_color = LED_COLOR_YELLOW;
- new_breathing = 1;
+ state = LED_STATE_BREATHING;
break;
case ST_PRE_CHARGING:
- new_color = LED_COLOR_YELLOW;
+ state = LED_STATE_SOLID_YELLOW;
break;
case ST_CHARGING:
if (battery_current(&current) ||
battery_desired_current(&desired_current)) {
/* Cannot talk to the battery. Set LED to red. */
- new_color = LED_COLOR_RED;
+ state = LED_STATE_SOLID_RED;
break;
}
if (current < 0 && desired_current > 0) { /* Battery assist */
- new_breathing = 1;
- new_color = LED_COLOR_YELLOW;
+ state = LED_STATE_BREATHING;
break;
}
if (current && desired_current)
- new_color = LED_COLOR_YELLOW;
+ state = LED_STATE_SOLID_YELLOW;
else
- new_color = LED_COLOR_GREEN;
+ state = LED_STATE_SOLID_GREEN;
break;
case ST_CHARGING_ERROR:
- new_color = LED_COLOR_RED;
+ state = LED_STATE_SOLID_RED;
break;
}
- if (new_color != color) {
- lp5562_set_color(new_color);
- color = new_color;
- }
- if (new_breathing != breathing) {
- board_led_breathing(new_breathing);
- breathing = new_breathing;
- }
+ board_stablize_led(state);
}
DECLARE_HOOK(HOOK_SECOND, board_battery_led_update, HOOK_PRIO_DEFAULT);