summaryrefslogtreecommitdiff
path: root/common/rgb_keyboard.c
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2021-12-04 13:08:04 -0800
committerCommit Bot <commit-bot@chromium.org>2022-03-01 19:41:59 +0000
commit14b34644fe16349af348d21f20d3897707132896 (patch)
tree1439a332e77c942d809b2ebfc128d690d72fe8e8 /common/rgb_keyboard.c
parent10a7a0a72017fe15633fa563977b748e88ec8726 (diff)
downloadchrome-ec-14b34644fe16349af348d21f20d3897707132896.tar.gz
RGBKBD: Add RGB Keyboard task
This patch introduces a RGB keyboard task and a IS31FL3743B driver. BUG=b:203664745, b:213921985, b:199995751 BRANCH=None TEST=Vell and unit test. Change-Id: Iefc1714efca9a4dc70db5a024d1ab020ec7b69b6 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3342506 Reviewed-by: Jack Rosenthal <jrosenth@chromium.org> Reviewed-by: Aaron Massey <aaronmassey@google.com>
Diffstat (limited to 'common/rgb_keyboard.c')
-rw-r--r--common/rgb_keyboard.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/common/rgb_keyboard.c b/common/rgb_keyboard.c
new file mode 100644
index 0000000000..2a2e05b43a
--- /dev/null
+++ b/common/rgb_keyboard.c
@@ -0,0 +1,315 @@
+/* Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <stdbool.h>
+
+#include "atomic.h"
+#include "common.h"
+#include "console.h"
+#include "ec_commands.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "registers.h"
+#include "rgb_keyboard.h"
+#include "task.h"
+#include "timer.h"
+#include "util.h"
+
+/* Console output macros */
+#define CPUTS(outstr) cputs(CC_RGBKBD, outstr)
+#define CPRINTF(fmt, args...) cprintf(CC_RGBKBD, "RGBKBD: " fmt, ##args)
+#define CPRINTS(fmt, args...) cprints(CC_RGBKBD, "RGBKBD: " fmt, ##args)
+
+test_export_static enum rgbkbd_demo demo =
+#if defined(CONFIG_RGBKBD_DEMO_FLOW)
+ RGBKBD_DEMO_FLOW
+#elif defined(CONFIG_RGBKBD_DEMO_DOT)
+ RGBKBD_DEMO_DOT
+#else
+ RGBKBD_DEMO_OFF
+#endif
+ ;
+
+static int set_color_single(struct rgb_s color, int x, int y)
+{
+ struct rgbkbd *ctx = &rgbkbds[0];
+ uint8_t gid;
+ uint8_t col = 0;
+ uint8_t offset;
+
+ if (rgbkbd_hsize <= x || rgbkbd_vsize <= y) {
+ return EC_ERROR_OVERFLOW;
+ }
+
+ /* Search the grid where x belongs to. */
+ for (gid = 0; gid < rgbkbd_count; gid++, ctx++) {
+ if (x < col + ctx->cfg->col_len)
+ break;
+ col += ctx->cfg->col_len;
+ }
+
+ offset = ctx->cfg->row_len * (x - col) + y;
+ ctx->buf[offset] = color;
+
+ CPRINTS("Set [%d,%d] to color=[%d,%d,%d] (gid=%u offset=%u)",
+ x, y, color.r, color.g, color.b, gid, offset);
+ return ctx->cfg->drv->set_color(ctx, offset, &ctx->buf[offset], 1);
+}
+
+test_export_static uint8_t get_grid_size(const struct rgbkbd *ctx)
+{
+ return ctx->cfg->col_len * ctx->cfg->row_len;
+}
+
+static void sync_grids(void)
+{
+ struct rgbkbd *ctx;
+ uint8_t len;
+ int i;
+
+ for (i = 0; i < rgbkbd_count; i++) {
+ ctx = &rgbkbds[i];
+ len = get_grid_size(ctx);
+ ctx->cfg->drv->set_color(ctx, 0, ctx->buf, len);
+ }
+}
+
+test_export_static struct rgb_s rotate_color(struct rgb_s color, int step)
+{
+ color.r += step;
+ if (color.r == 0) {
+ color.g += step;
+ if (color.g == 0) {
+ color.b += step;
+ }
+ }
+
+ return color;
+}
+
+static void rgbkbd_reset_color(struct rgb_s color)
+{
+ struct rgbkbd *ctx;
+ int i, j;
+
+ for (i = 0; i < rgbkbd_count; i++) {
+ ctx = &rgbkbds[i];
+ for (j = 0; j < get_grid_size(ctx); j++)
+ ctx->buf[j] = color;
+ }
+
+ sync_grids();
+}
+
+static void rgbkbd_demo_flow(void)
+{
+ struct rgbkbd *ctx = &rgbkbds[0];
+ static struct rgb_s color;
+ uint8_t len;
+ int i, g;
+
+ for (g = rgbkbd_count - 1; g >= 0; g--) {
+ ctx = &rgbkbds[g];
+ len = get_grid_size(ctx);
+ for (i = len - 1; i > 0; i--)
+ ctx->buf[i] = ctx->buf[i - 1];
+ if (g > 0) {
+ /* Copy the last dot of the g-1 grid to the 1st. */
+ len = get_grid_size(&rgbkbds[g - 1]);
+ ctx->buf[0] = rgbkbds[g - 1].buf[len - 1];
+ }
+ }
+
+ /* Create a new color by shifting R by <step>. */
+ color = rotate_color(color, 32);
+
+ /* Finally, insert a new color to (0, 0). */
+ ctx->buf[0] = color;
+
+ sync_grids();
+
+#ifdef TEST_BUILD
+ task_wake(TASK_ID_TEST_RUNNER);
+#else
+ msleep(250);
+#endif
+}
+
+static void rgbkbd_demo_dot(void)
+{
+ static struct rgb_s color = { 0x80, 0, 0 };
+ const struct rgb_s off = { 0, 0, 0 };
+ static uint8_t x, y;
+
+ /* Turn off previous dot. */
+ set_color_single(off, x, y);
+
+ /* Move position. */
+ y++;
+ if (y >= rgbkbd_vsize) {
+ y = 0;
+ x++;
+ if (x >= rgbkbd_hsize) {
+ x = 0;
+ color = rotate_color(color, 0x80);
+ }
+ }
+
+ /* Turn on next dot. */
+ set_color_single(color, x, y);
+
+#ifdef TEST_BUILD
+ task_wake(TASK_ID_TEST_RUNNER);
+#else
+ msleep(250);
+#endif
+}
+
+static void rgbkbd_demo(enum rgbkbd_demo id)
+{
+ switch (id) {
+ case RGBKBD_DEMO_FLOW:
+ rgbkbd_demo_flow();
+ break;
+ case RGBKBD_DEMO_DOT:
+ rgbkbd_demo_dot();
+ break;
+ case RGBKBD_DEMO_OFF:
+ default:
+ break;
+ }
+}
+
+__overridable void board_enable_rgb_keyboard(bool enable) {}
+
+void rgbkbd_task(void *u)
+{
+ uint32_t event;
+ int i, rv;
+
+ board_enable_rgb_keyboard(true);
+
+ for (i = 0; i < rgbkbd_count; i++) {
+ struct rgbkbd *ctx = &rgbkbds[i];
+ rv = ctx->cfg->drv->init(ctx);
+ if (rv)
+ CPRINTS("Failed to init GRID%d (%d)", i, rv);
+ rv = ctx->cfg->drv->set_gcc(ctx, 0x80);
+ rv |= ctx->cfg->drv->set_scale(ctx, 0, 0x80,
+ get_grid_size(ctx));
+ if (rv)
+ CPRINTS("Failed to set GCC or scale (%d)", rv);
+ }
+
+ while (1) {
+ event = task_wait_event(100 * MSEC);
+ if (IS_ENABLED(CONFIG_RGB_KEYBOARD_DEBUG))
+ CPRINTS("event=0x%08x", event);
+ if (demo)
+ rgbkbd_demo(demo);
+ }
+}
+
+test_export_static int cc_rgbk(int argc, char **argv)
+{
+ struct rgbkbd *ctx;
+ char *end, *comma;
+ struct rgb_s color;
+ int gcc, x, y, val;
+ int i, rv = EC_SUCCESS;
+
+ if (argc < 2 || 5 < argc) {
+ return EC_ERROR_PARAM_COUNT;
+ }
+
+ comma = strstr(argv[1], ",");
+ if (comma && strlen(comma) > 1) {
+ /* Usage 2 */
+ /* Found ',' and more string after that. Split it into two. */
+ *comma = '\0';
+ x = strtoi(argv[1], &end, 0);
+ if (*end || x >= rgbkbd_hsize)
+ return EC_ERROR_PARAM1;
+ y = strtoi(comma + 1, &end, 0);
+ if (*end || y >= rgbkbd_vsize)
+ return EC_ERROR_PARAM1;
+ } else if (!strcasecmp(argv[1], "all")) {
+ /* Usage 3 */
+ x = -1;
+ y = -1;
+ } else if (!strcasecmp(argv[1], "demo")) {
+ /* Usage 4 */
+ val = strtoi(argv[2], &end, 0);
+ if (*end || val >= RGBKBD_DEMO_COUNT)
+ return EC_ERROR_PARAM1;
+ demo = val;
+ rgbkbd_reset_color((struct rgb_s){.r = 0, .g = 0, .b = 0});
+ ccprintf("Demo set to %d\n", demo);
+ return EC_SUCCESS;
+ } else {
+ /* Usage 1 */
+ if (argc != 2)
+ return EC_ERROR_PARAM_COUNT;
+ gcc = strtoi(argv[1], &end, 0);
+ if (*end || gcc < 0 || gcc > UINT8_MAX)
+ return EC_ERROR_PARAM1;
+ demo = RGBKBD_DEMO_OFF;
+ for (i = 0; i < rgbkbd_count; i++) {
+ ctx = &rgbkbds[i];
+ ctx->cfg->drv->set_gcc(ctx, gcc);
+ }
+ return EC_SUCCESS;
+ }
+
+ if (argc != 5)
+ return EC_ERROR_PARAM_COUNT;
+
+ val = strtoi(argv[2], &end, 0);
+ if (*end || val < 0 || val > UINT8_MAX)
+ return EC_ERROR_PARAM2;
+ color.r = val;
+ val = strtoi(argv[3], &end, 0);
+ if (*end || val < 0 || val > UINT8_MAX)
+ return EC_ERROR_PARAM3;
+ color.g = val;
+ val = strtoi(argv[4], &end, 0);
+ if (*end || val < 0 || val > UINT8_MAX)
+ return EC_ERROR_PARAM4;
+ color.b = val;
+
+ demo = RGBKBD_DEMO_OFF;
+ if (y < 0 && x < 0) {
+ /* Usage 3 */
+ rgbkbd_reset_color(color);
+ } else if (y < 0) {
+ /* Usage 2: Set all LEDs on column x. */
+ ccprintf("Set column %d to 0x%02x%02x%02x\n",
+ x, color.r, color.g, color.b);
+ for (i = 0; i < rgbkbd_vsize; i++)
+ rv = set_color_single(color, x, i);
+ } else if (x < 0) {
+ /* Usage 2: Set all LEDs on row y. */
+ ccprintf("Set row %d to 0x%02x%02x%02x\n",
+ y, color.r, color.g, color.b);
+ for (i = 0; i < rgbkbd_hsize; i++)
+ rv = set_color_single(color, i, y);
+ } else {
+ /* Usage 2 */
+ ccprintf("Set (%d,%d) to 0x%02x%02x%02x\n",
+ x, y, color.r, color.g, color.b);
+ rv = set_color_single(color, x, y);
+ }
+
+ return rv;
+}
+#ifndef TEST_BUILD
+DECLARE_CONSOLE_COMMAND(rgbk, cc_rgbk,
+ "\n"
+ "1. rgbk <global-brightness>\n"
+ "2. rgbk <col,row> <r-bright> <g-bright> <b-bright>\n"
+ "3. rgbk all <r-bright> <g-bright> <b-bright>\n"
+ "4. rgbk demo <id>\n",
+ "Set color of RGB keyboard"
+ );
+#endif