/* * Copyright (c) 2020 Seagate Technology LLC * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL #include LOG_MODULE_REGISTER(main); #define MAX_BRIGHTNESS 100 #define SLEEP_DELAY_MS 1000 #define FADE_DELAY_MS 10 #define FADE_DELAY K_MSEC(FADE_DELAY_MS) #define SLEEP_DELAY K_MSEC(SLEEP_DELAY_MS) /* * The following colors are shown in the given order. Each row index is sorted * in RGB order. */ static uint8_t colors[][3] = { { 0xFF, 0x00, 0x00 }, /* Red */ { 0x00, 0xFF, 0x00 }, /* Green */ { 0x00, 0x00, 0xFF }, /* Blue */ { 0xFF, 0xFF, 0xFF }, /* White */ { 0xFF, 0xFF, 0x00 }, /* Yellow */ { 0xFF, 0x00, 0xFF }, /* Purple */ { 0x00, 0xFF, 0xFF }, /* Cyan */ { 0xF4, 0x79, 0x20 }, /* Orange */ }; /* * Prepare a color buffer for a single LED using its color mapping and the * desired color index. */ static int prepare_color_buffer(const struct led_info *info, uint8_t *buf, uint8_t color_idx) { uint8_t color; for (color = 0; color < info->num_colors; color++) { switch (info->color_mapping[color]) { case LED_COLOR_ID_RED: buf[color] = colors[color_idx][0]; continue; case LED_COLOR_ID_GREEN: buf[color] = colors[color_idx][1]; continue; case LED_COLOR_ID_BLUE: buf[color] = colors[color_idx][2]; continue; default: LOG_ERR("Invalid color: %d", info->color_mapping[color]); return -EINVAL; } } return 0; } /** * @brief Run tests on a single LED using the LED-based API syscalls. * * @param lp50xx_dev LP50XX LED controller device. * @param led Number of the LED to test. */ static int run_led_test(const struct device *lp50xx_dev, uint8_t led) { const struct led_info *info; uint8_t idx; int err; LOG_INF("Testing LED %d (LED API)", led); err = led_get_info(lp50xx_dev, led, &info); if (err < 0) { LOG_ERR("Failed to get LED %d info", led); return err; } for (idx = 0; idx < ARRAY_SIZE(colors); idx++) { uint16_t level; uint8_t buf[3]; err = prepare_color_buffer(info, buf, idx); if (err < 0) { LOG_ERR("Failed to set color buffer, err=%d", err); return err; } /* Update LED color. */ err = led_set_color(lp50xx_dev, led, 3, buf); if (err < 0) { LOG_ERR("Failed to set LED %d color to " "%02x:%02x:%02x, err=%d", led, buf[0], buf[1], buf[2], err); return err; } k_sleep(SLEEP_DELAY); /* Turn LED on. */ err = led_on(lp50xx_dev, led); if (err < 0) { LOG_ERR("Failed to turn LED %d on, err=%d", led, err); return err; } k_sleep(SLEEP_DELAY); /* Turn LED off. */ err = led_off(lp50xx_dev, led); if (err < 0) { LOG_ERR("Failed to turn LED %d off, err=%d", led, err); return err; } k_sleep(SLEEP_DELAY); /* Set LED brightness gradually to the maximum level. */ for (level = 0; level <= MAX_BRIGHTNESS; level++) { err = led_set_brightness(lp50xx_dev, led, level); if (err < 0) { LOG_ERR("Failed to set LED %d brightness to %d" ", err=%d\n", led, level, err); return err; } k_sleep(FADE_DELAY); } k_sleep(SLEEP_DELAY); /* Turn LED off. */ err = led_off(lp50xx_dev, led); if (err < 0) { LOG_ERR("Failed to turn LED %d off, err=%d", led, err); return err; } k_sleep(SLEEP_DELAY); } return 0; } /** * @brief Run tests on all the LEDs using the channel-based API syscalls. * * @param lp50xx_dev LP50XX LED controller device. */ static int run_channel_test(const struct device *lp50xx_dev, const uint8_t max_leds, const uint8_t bright_chan, const uint8_t color_chan) { uint8_t idx; uint8_t buffer[LP50XX_COLORS_PER_LED * max_leds]; int err; LOG_INF("Testing all LEDs (channel API)"); for (idx = 0; idx < ARRAY_SIZE(colors); idx++) { uint8_t led; uint16_t level; /* Update LEDs colors. */ memset(buffer, 0, sizeof(buffer)); for (led = 0; led < max_leds; led++) { const struct led_info *info; uint8_t *col = &buffer[led * 3]; err = led_get_info(lp50xx_dev, led, &info); if (err < 0) { continue; } col = &buffer[info->index * 3]; err = prepare_color_buffer(info, col, idx); if (err < 0) { LOG_ERR("Failed to set color buffer, err=%d", err); return err; } } err = led_write_channels(lp50xx_dev, color_chan, LP50XX_COLORS_PER_LED * max_leds, buffer); if (err < 0) { LOG_ERR("Failed to write channels, start=%d num=%d" " err=%d\n", color_chan, LP50XX_COLORS_PER_LED * max_leds, err); return err; } k_sleep(SLEEP_DELAY); /* Turn LEDs on. */ memset(buffer, 0, sizeof(buffer)); for (led = 0; led < max_leds; led++) { buffer[led] = MAX_BRIGHTNESS; } err = led_write_channels(lp50xx_dev, bright_chan, max_leds, buffer); if (err < 0) { LOG_ERR("Failed to write channels, start=%d num=%d" " err=%d\n", bright_chan, max_leds, err); return err; } k_sleep(SLEEP_DELAY); /* Turn LEDs off. */ for (led = 0; led < max_leds; led++) { buffer[led] = 0; } err = led_write_channels(lp50xx_dev, bright_chan, max_leds, buffer); if (err < 0) { LOG_ERR("Failed to write channels, start=%d num=%d" " err=%d\n", bright_chan, max_leds, err); return err; } k_sleep(SLEEP_DELAY); /* Set LEDs brightnesses gradually to the maximum level. */ for (level = 0; level <= MAX_BRIGHTNESS; level++) { for (led = 0; led < max_leds; led++) { buffer[led] = level; } err = led_write_channels(lp50xx_dev, bright_chan, max_leds, buffer); if (err < 0) { LOG_ERR("Failed to write channels, start=%d" " num=%d err=%d\n", bright_chan, max_leds, err); return err; } k_sleep(FADE_DELAY); } k_sleep(SLEEP_DELAY); /* Turn LEDs off. */ for (led = 0; led < max_leds; led++) { buffer[led] = 0; } err = led_write_channels(lp50xx_dev, bright_chan, max_leds, buffer); if (err < 0) { LOG_ERR("Failed to write channels, start=%d " "num=%d err=%d\n", bright_chan, max_leds, err); return err; } k_sleep(SLEEP_DELAY); } return 0; } static int run_test(const struct device *const lp50xx_dev, const uint8_t max_leds, const uint8_t bright_chan, const uint8_t color_chan) { int err; uint8_t led; uint8_t num_leds = 0; for (led = 0; led < max_leds; led++) { int col; const struct led_info *info; err = led_get_info(lp50xx_dev, led, &info); if (err < 0) { LOG_DBG("Failed to get information for LED %d (err=%d)", led, err); break; } /* Display LED information. */ printk("Found LED %d", led); if (info->label) { printk(" - %s", info->label); } printk(" - index:%d", info->index); printk(" - %d colors", info->num_colors); if (!info->color_mapping) { continue; } printk(" - %d", info->color_mapping[0]); for (col = 1; col < info->num_colors; col++) { printk(":%d", info->color_mapping[col]); } printk("\n"); } num_leds = led; if (!num_leds) { LOG_ERR("No LEDs found"); return 0; } do { err = run_channel_test(lp50xx_dev, max_leds, bright_chan, color_chan); if (err) { return 0; } for (led = 0; led < num_leds; led++) { err = run_led_test(lp50xx_dev, led); if (err) { return 0; } } } while (true); return 0; } int main(void) { const struct device *lp50xx_dev; bool found = false; lp50xx_dev = DEVICE_DT_GET_ANY(ti_lp5009); if (lp50xx_dev) { LOG_INF("Found LED controller %s", lp50xx_dev->name); found = true; if (device_is_ready(lp50xx_dev)) { run_test(lp50xx_dev, LP5009_MAX_LEDS, LP50XX_LED_BRIGHT_CHAN_BASE, LP5012_LED_COL_CHAN_BASE); } else { LOG_ERR("LED controller %s is not ready", lp50xx_dev->name); } } lp50xx_dev = DEVICE_DT_GET_ANY(ti_lp5012); if (lp50xx_dev) { LOG_INF("Found LED controller %s", lp50xx_dev->name); found = true; if (device_is_ready(lp50xx_dev)) { run_test(lp50xx_dev, LP5012_MAX_LEDS, LP50XX_LED_BRIGHT_CHAN_BASE, LP5012_LED_COL_CHAN_BASE); } else { LOG_ERR("LED controller %s is not ready", lp50xx_dev->name); } } lp50xx_dev = DEVICE_DT_GET_ANY(ti_lp5018); if (lp50xx_dev) { LOG_INF("Found LED controller %s", lp50xx_dev->name); found = true; if (device_is_ready(lp50xx_dev)) { run_test(lp50xx_dev, LP5018_MAX_LEDS, LP50XX_LED_BRIGHT_CHAN_BASE, LP5024_LED_COL_CHAN_BASE); } else { LOG_ERR("LED controller %s is not ready", lp50xx_dev->name); } } lp50xx_dev = DEVICE_DT_GET_ANY(ti_lp5024); if (lp50xx_dev) { LOG_INF("Found LED controller %s", lp50xx_dev->name); found = true; if (device_is_ready(lp50xx_dev)) { run_test(lp50xx_dev, LP5024_MAX_LEDS, LP50XX_LED_BRIGHT_CHAN_BASE, LP5024_LED_COL_CHAN_BASE); } else { LOG_ERR("LED controller %s is not ready", lp50xx_dev->name); } } lp50xx_dev = DEVICE_DT_GET_ANY(ti_lp5030); if (lp50xx_dev) { LOG_INF("Found LED controller %s", lp50xx_dev->name); found = true; if (device_is_ready(lp50xx_dev)) { run_test(lp50xx_dev, LP5030_MAX_LEDS, LP50XX_LED_BRIGHT_CHAN_BASE, LP5036_LED_COL_CHAN_BASE); } else { LOG_ERR("LED controller %s is not ready", lp50xx_dev->name); } } lp50xx_dev = DEVICE_DT_GET_ANY(ti_lp5036); if (lp50xx_dev) { LOG_INF("Found LED controller %s", lp50xx_dev->name); found = true; if (device_is_ready(lp50xx_dev)) { run_test(lp50xx_dev, LP5036_MAX_LEDS, LP50XX_LED_BRIGHT_CHAN_BASE, LP5036_LED_COL_CHAN_BASE); } else { LOG_ERR("LED controller %s is not ready", lp50xx_dev->name); } } if (!found) { LOG_ERR("No LP50XX LED controller found"); } return 0; }