summaryrefslogtreecommitdiff
path: root/common/lightbar.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/lightbar.c')
-rw-r--r--common/lightbar.c302
1 files changed, 231 insertions, 71 deletions
diff --git a/common/lightbar.c b/common/lightbar.c
index 965c4f8261..f2e95e3a74 100644
--- a/common/lightbar.c
+++ b/common/lightbar.c
@@ -53,7 +53,7 @@ static inline uint8_t controller_read(int ctrl_num, uint8_t reg)
#define MAX_GREEN 0x38
#define MAX_BLUE 0x67
-/* How many LEDs do we have? Right now, only four. */
+/* How many LEDs do we have? */
#define NUM_LEDS 4
/* How we'd like to see the driver chips initialized. The controllers have some
@@ -119,6 +119,22 @@ static inline uint8_t scale(int val, int max)
return scale_abs((val * brightness)/255, max);
}
+
+/* Helper function. */
+static void setrgb(int led, int red, int green, int blue)
+{
+ int ctrl, bank;
+ current[led][0] = red;
+ current[led][1] = green;
+ current[led][2] = blue;
+ ctrl = led_to_ctrl[led];
+ bank = led_to_isc[led];
+ controller_write(ctrl, bank, scale(blue, MAX_BLUE));
+ controller_write(ctrl, bank+1, scale(red, MAX_RED));
+ controller_write(ctrl, bank+2, scale(green, MAX_GREEN));
+}
+
+
/******************************************************************************/
/* Basic LED control functions. */
/******************************************************************************/
@@ -139,18 +155,17 @@ static void lightbar_on(void)
controller_write(1, 0x01, 0x20);
}
-/* LEDs are numbered 0-3, RGB values should be in 0-255. */
-static void lightbar_setcolor(int led, int red, int green, int blue)
+
+/* LEDs are numbered 0-3, RGB values should be in 0-255.
+ * If you specify too large an LED, it sets them all. */
+static void lightbar_setrgb(int led, int red, int green, int blue)
{
- int ctrl, bank;
- current[led][0] = red;
- current[led][1] = green;
- current[led][2] = blue;
- ctrl = led_to_ctrl[led];
- bank = led_to_isc[led];
- controller_write(ctrl, bank, scale(blue, MAX_BLUE));
- controller_write(ctrl, bank+1, scale(red, MAX_RED));
- controller_write(ctrl, bank+2, scale(green, MAX_GREEN));
+ int i;
+ if (led >= NUM_LEDS)
+ for (i = 0; i < NUM_LEDS; i++)
+ setrgb(i, red, green, blue);
+ else
+ setrgb(led, red, green, blue);
}
static inline void lightbar_brightness(int newval)
@@ -159,7 +174,7 @@ static inline void lightbar_brightness(int newval)
uart_printf("%s[(%d)]\n", __func__, newval);
brightness = newval;
for (i = 0; i < NUM_LEDS; i++)
- lightbar_setcolor(i, current[i][0],
+ lightbar_setrgb(i, current[i][0],
current[i][1], current[i][2]);
}
@@ -198,7 +213,7 @@ static uint32_t sequence_s5(void)
/* For now, do something to indicate S5. We might see it. */
lightbar_on();
for (i = 0; i < NUM_LEDS; i++)
- lightbar_setcolor(i, 255, 0, 0);
+ lightbar_setrgb(i, 255, 0, 0);
/* The lightbar loses power in S5, so just wait forever. */
WAIT_OR_RET(-1);
@@ -221,7 +236,7 @@ static uint32_t sequence_s5s3(void)
* We might see it. */
lightbar_on();
for (i = 0; i < NUM_LEDS; i++)
- lightbar_setcolor(i, 255, 255, 255);
+ lightbar_setrgb(i, 255, 255, 255);
WAIT_OR_RET(500000);
return 0;
@@ -240,9 +255,9 @@ static uint32_t sequence_s0(void)
l = l % NUM_LEDS;
n = n % 5;
if (n == 4)
- lightbar_setcolor(l, 0, 0, 0);
+ lightbar_setrgb(l, 0, 0, 0);
else
- lightbar_setcolor(l, testy[n].r,
+ lightbar_setrgb(l, testy[n].r,
testy[n].g, testy[n].b);
l++;
n++;
@@ -257,18 +272,18 @@ static uint32_t sequence_s0s3(void)
{
uart_printf("[%s()]\n", __func__);
lightbar_on();
- lightbar_setcolor(0, 0, 0, 255);
- lightbar_setcolor(1, 255, 0, 0);
- lightbar_setcolor(2, 255, 255, 0);
- lightbar_setcolor(3, 0, 255, 0);
+ lightbar_setrgb(0, 0, 0, 255);
+ lightbar_setrgb(1, 255, 0, 0);
+ lightbar_setrgb(2, 255, 255, 0);
+ lightbar_setrgb(3, 0, 255, 0);
WAIT_OR_RET(200000);
- lightbar_setcolor(0, 0, 0, 0);
+ lightbar_setrgb(0, 0, 0, 0);
WAIT_OR_RET(200000);
- lightbar_setcolor(1, 0, 0, 0);
+ lightbar_setrgb(1, 0, 0, 0);
WAIT_OR_RET(200000);
- lightbar_setcolor(2, 0, 0, 0);
+ lightbar_setrgb(2, 0, 0, 0);
WAIT_OR_RET(200000);
- lightbar_setcolor(3, 0, 0, 0);
+ lightbar_setrgb(3, 0, 0, 0);
return 0;
}
@@ -279,18 +294,18 @@ static uint32_t sequence_s3(void)
uart_printf("[%s()]\n", __func__);
lightbar_off();
lightbar_init_vals();
- lightbar_setcolor(0, 0, 0, 0);
- lightbar_setcolor(1, 0, 0, 0);
- lightbar_setcolor(2, 0, 0, 0);
- lightbar_setcolor(3, 0, 0, 0);
+ lightbar_setrgb(0, 0, 0, 0);
+ lightbar_setrgb(1, 0, 0, 0);
+ lightbar_setrgb(2, 0, 0, 0);
+ lightbar_setrgb(3, 0, 0, 0);
while (1) {
WAIT_OR_RET(3000000);
lightbar_on();
i = i % NUM_LEDS;
/* FIXME: indicate battery level? */
- lightbar_setcolor(i, testy[i].r, testy[i].g, testy[i].b);
+ lightbar_setrgb(i, testy[i].r, testy[i].g, testy[i].b);
WAIT_OR_RET(100000);
- lightbar_setcolor(i, 0, 0, 0);
+ lightbar_setrgb(i, 0, 0, 0);
i++;
lightbar_off();
}
@@ -304,13 +319,13 @@ static uint32_t sequence_s3s0(void)
uart_printf("[%s()]\n", __func__);
lightbar_init_vals();
lightbar_on();
- lightbar_setcolor(0, 0, 0, 255);
+ lightbar_setrgb(0, 0, 0, 255);
WAIT_OR_RET(200000);
- lightbar_setcolor(1, 255, 0, 0);
+ lightbar_setrgb(1, 255, 0, 0);
WAIT_OR_RET(200000);
- lightbar_setcolor(2, 255, 255, 0);
+ lightbar_setrgb(2, 255, 255, 0);
WAIT_OR_RET(200000);
- lightbar_setcolor(3, 0, 255, 0);
+ lightbar_setrgb(3, 0, 255, 0);
WAIT_OR_RET(200000);
return 0;
}
@@ -326,7 +341,7 @@ static uint32_t sequence_s3s5(void)
* We might see it. */
lightbar_on();
for (i = 0; i < NUM_LEDS; i++)
- lightbar_setcolor(i, 0, 0, 255);
+ lightbar_setrgb(i, 0, 0, 255);
WAIT_OR_RET(500000);
return 0;
@@ -349,7 +364,7 @@ static uint32_t sequence_test(void)
r = testy[i].r ? k : 0;
g = testy[i].g ? k : 0;
b = testy[i].b ? k : 0;
- lightbar_setcolor(j, r, g, b);
+ lightbar_setrgb(j, r, g, b);
}
WAIT_OR_RET(10000);
}
@@ -358,7 +373,7 @@ static uint32_t sequence_test(void)
r = testy[i].r ? k : 0;
g = testy[i].g ? k : 0;
b = testy[i].b ? k : 0;
- lightbar_setcolor(j, r, g, b);
+ lightbar_setrgb(j, r, g, b);
}
WAIT_OR_RET(10000);
}
@@ -373,38 +388,28 @@ static uint32_t sequence_test(void)
static uint32_t sequence_pulse(void)
{
uint32_t msg;
- int r, g, b;
+ int r = scale(255, MAX_RED);
+ int g = scale(255, MAX_BLUE);
+ int b = scale(255, MAX_GREEN);
+ struct initdata_s pulse_vals[] = {
+ {0x11, 0xce},
+ {0x12, 0x67},
+ {0x13, 0xef},
+ {0x15, b},
+ {0x16, r},
+ {0x17, g},
+ {0x18, b},
+ {0x19, r},
+ {0x1a, g},
+ };
uart_printf("[%s()]\n", __func__);
- r = scale(255, MAX_RED);
- g = scale(255, MAX_BLUE);
- b = scale(255, MAX_GREEN);
-
lightbar_init_vals();
lightbar_on();
- controller_write(0, 0x11, 0xce);
- controller_write(0, 0x12, 0x67);
- controller_write(0, 0x13, 0xef);
-
- controller_write(0, 0x15, b);
- controller_write(0, 0x16, r);
- controller_write(0, 0x17, g);
- controller_write(0, 0x18, b);
- controller_write(0, 0x19, r);
- controller_write(0, 0x1a, g);
-
- controller_write(1, 0x11, 0xce);
- controller_write(1, 0x12, 0x67);
- controller_write(1, 0x13, 0xcd);
-
- controller_write(1, 0x15, b);
- controller_write(1, 0x16, r);
- controller_write(1, 0x17, g);
- controller_write(1, 0x18, b);
- controller_write(1, 0x19, r);
- controller_write(1, 0x1a, g);
+ set_from_array(pulse_vals, ARRAY_SIZE(pulse_vals));
+ controller_write(1, 0x13, 0xcd); /* this one's different */
/* Not using WAIT_OR_RET() here, because we want to clean up when we're
* done. The only way out is to get a message. */
@@ -413,13 +418,155 @@ static uint32_t sequence_pulse(void)
return TASK_EVENT_CUSTOM(msg);
}
+
+
+/* The host CPU (or someone) is going to poke at the lightbar directly, so we
+ * don't want the EC messing with it. We'll just sit here and ignore all
+ * other messages until we're told to continue. */
+static uint32_t sequence_ec_stop(void)
+{
+ uint32_t msg;
+
+ uart_printf("[%s()]\n", __func__);
+
+ do {
+ msg = TASK_EVENT_CUSTOM(task_wait_event(-1));
+ uart_printf("[%s - got msg %x]\n", __func__, msg);
+ } while (msg != LIGHTBAR_EC_RUN);
+ /* FIXME: What should we do if the host shuts down? */
+
+ uart_printf("[%s() - leaving]\n", __func__);
+
+ return 0;
+}
+
+/* We shouldn't come here, but if we do it shouldn't hurt anything */
+static uint32_t sequence_error(void)
+{
+ uart_printf("[%s()]\n", __func__);
+
+ lightbar_init_vals();
+ lightbar_on();
+
+ lightbar_setrgb(0, 255, 255, 255);
+ lightbar_setrgb(1, 255, 0, 255);
+ lightbar_setrgb(2, 0, 255, 255);
+ lightbar_setrgb(3, 255, 255, 255);
+
+ WAIT_OR_RET(10000000);
+
+ return 0;
+}
+
+
+static const struct {
+ uint8_t led;
+ uint8_t r, g, b;
+ unsigned int delay;
+} konami[] = {
+
+ {1, 0xff, 0xff, 0x00, 0},
+ {2, 0xff, 0xff, 0x00, 100000},
+ {1, 0x00, 0x00, 0x00, 0},
+ {2, 0x00, 0x00, 0x00, 100000},
+
+ {1, 0xff, 0xff, 0x00, 0},
+ {2, 0xff, 0xff, 0x00, 100000},
+ {1, 0x00, 0x00, 0x00, 0},
+ {2, 0x00, 0x00, 0x00, 100000},
+
+ {0, 0x00, 0x00, 0xff, 0},
+ {3, 0x00, 0x00, 0xff, 100000},
+ {0, 0x00, 0x00, 0x00, 0},
+ {3, 0x00, 0x00, 0x00, 100000},
+
+ {0, 0x00, 0x00, 0xff, 0},
+ {3, 0x00, 0x00, 0xff, 100000},
+ {0, 0x00, 0x00, 0x00, 0},
+ {3, 0x00, 0x00, 0x00, 100000},
+
+ {0, 0xff, 0x00, 0x00, 0},
+ {1, 0xff, 0x00, 0x00, 100000},
+ {0, 0x00, 0x00, 0x00, 0},
+ {1, 0x00, 0x00, 0x00, 100000},
+
+ {2, 0x00, 0xff, 0x00, 0},
+ {3, 0x00, 0xff, 0x00, 100000},
+ {2, 0x00, 0x00, 0x00, 0},
+ {3, 0x00, 0x00, 0x00, 100000},
+
+ {0, 0xff, 0x00, 0x00, 0},
+ {1, 0xff, 0x00, 0x00, 100000},
+ {0, 0x00, 0x00, 0x00, 0},
+ {1, 0x00, 0x00, 0x00, 100000},
+
+ {2, 0x00, 0xff, 0x00, 0},
+ {3, 0x00, 0xff, 0x00, 100000},
+ {2, 0x00, 0x00, 0x00, 0},
+ {3, 0x00, 0x00, 0x00, 100000},
+
+ {0, 0x00, 0xff, 0xff, 0},
+ {2, 0x00, 0xff, 0xff, 100000},
+ {0, 0x00, 0x00, 0x00, 0},
+ {2, 0x00, 0x00, 0x00, 150000},
+
+ {1, 0xff, 0x00, 0xff, 0},
+ {3, 0xff, 0x00, 0xff, 100000},
+ {1, 0x00, 0x00, 0x00, 0},
+ {3, 0x00, 0x00, 0x00, 250000},
+
+ {4, 0xff, 0xff, 0xff, 100000},
+ {4, 0x00, 0x00, 0x00, 100000},
+
+ {4, 0xff, 0xff, 0xff, 100000},
+ {4, 0x00, 0x00, 0x00, 100000},
+
+ {4, 0xff, 0xff, 0xff, 100000},
+ {4, 0x00, 0x00, 0x00, 100000},
+
+ {4, 0xff, 0xff, 0xff, 100000},
+ {4, 0x00, 0x00, 0x00, 100000},
+
+ {4, 0xff, 0xff, 0xff, 100000},
+ {4, 0x00, 0x00, 0x00, 100000},
+
+ {4, 0xff, 0xff, 0xff, 100000},
+ {4, 0x00, 0x00, 0x00, 100000},
+
+};
+
+static uint32_t sequence_konami(void)
+{
+ int i;
+ int tmp;
+
+ uart_printf("[%s()]\n", __func__);
+ lightbar_init_vals();
+ lightbar_on();
+
+ tmp = brightness;
+ brightness = 255;
+
+ for (i = 0; i < ARRAY_SIZE(konami); i++) {
+ lightbar_setrgb(konami[i].led,
+ konami[i].r, konami[i].g, konami[i].b);
+ if (konami[i].delay)
+ usleep(konami[i].delay);
+ }
+
+ brightness = tmp;
+
+ return 0;
+}
+
/****************************************************************************/
-/* Lightbar task. It just cycles between various pretty patterns. */
+/* The main lightbar task. It just cycles between various pretty patterns. */
/****************************************************************************/
-/* IMPORTANT: The order here must match the enum lightbar_sequence values. */
+/* IMPORTANT: The order here must match the enum lightbar_sequence order.
+ * FIXME: Use some preprocessor tricks to ensure that's always true. */
static uint32_t (*sequence[])(void) = {
- 0,
+ sequence_error, /* idle - not used */
sequence_s5,
sequence_s3,
sequence_s0,
@@ -427,8 +574,11 @@ static uint32_t (*sequence[])(void) = {
sequence_s3s0,
sequence_s0s3,
sequence_s3s5,
- sequence_test,
+ sequence_ec_stop,
+ sequence_error, /* unexpected ec run */
sequence_pulse,
+ sequence_test,
+ sequence_konami,
};
void lightbar_task(void)
@@ -469,6 +619,10 @@ void lightbar_task(void)
state = LIGHTBAR_S5;
break;
case LIGHTBAR_TEST:
+ case LIGHTBAR_EC_STOP:
+ case LIGHTBAR_EC_RUN:
+ case LIGHTBAR_NULL:
+ case LIGHTBAR_KONAMI:
state = previous_state;
default:
break;
@@ -478,7 +632,7 @@ void lightbar_task(void)
}
-/* Request a preset sequence from the lightbar task. */
+/* Function to request a preset sequence from the lightbar task. */
void lightbar_sequence(enum lightbar_sequence num)
{
uart_printf("[%s(%d)]\n", __func__, num);
@@ -516,8 +670,8 @@ DECLARE_HOST_COMMAND(EC_LPC_COMMAND_LIGHTBAR_TEST, lpc_cmd_test);
static int help(const char *cmd)
{
uart_printf("Usage: %s\n", cmd);
- uart_printf(" %s reset\n", cmd);
uart_printf(" %s off\n", cmd);
+ uart_printf(" %s init\n", cmd);
uart_printf(" %s on\n", cmd);
uart_printf(" %s msg NUM\n", cmd);
uart_printf(" %s brightness NUM\n", cmd);
@@ -543,6 +697,8 @@ static void dump_regs(void)
static int command_lightbar(int argc, char **argv)
{
+ int i;
+
if (1 == argc) { /* no args = dump 'em all */
dump_regs();
return EC_SUCCESS;
@@ -592,7 +748,11 @@ static int command_lightbar(int argc, char **argv)
int red = strtoi(argv[2], &e, 16);
int green = strtoi(argv[3], &e, 16);
int blue = strtoi(argv[4], &e, 16);
- lightbar_setcolor(led, red, green, blue);
+ if (led >= NUM_LEDS)
+ for (i = 0; i < NUM_LEDS; i++)
+ lightbar_setrgb(i, red, green, blue);
+ else
+ lightbar_setrgb(led, red, green, blue);
return EC_SUCCESS;
}