1 /*
2 * Copyright (c) 2020 Seagate Technology LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <device.h>
8 #include <errno.h>
9 #include <drivers/led.h>
10 #include <drivers/led/lp503x.h>
11 #include <sys/util.h>
12 #include <zephyr.h>
13
14 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
15 #include <logging/log.h>
16 LOG_MODULE_REGISTER(main);
17
18 #define MAX_BRIGHTNESS 100
19
20 #define SLEEP_DELAY_MS 1000
21 #define FADE_DELAY_MS 10
22
23 #define FADE_DELAY K_MSEC(FADE_DELAY_MS)
24 #define SLEEP_DELAY K_MSEC(SLEEP_DELAY_MS)
25
26 /*
27 * The following colors are shown in the given order.
28 */
29 static uint8_t colors[][3] = {
30 { 0xFF, 0x00, 0x00 }, /* Red */
31 { 0x00, 0xFF, 0x00 }, /* Green */
32 { 0x00, 0x00, 0xFF }, /* Blue */
33 { 0xFF, 0xFF, 0xFF }, /* White */
34 { 0xFF, 0xFF, 0x00 }, /* Yellow */
35 { 0xFF, 0x00, 0xFF }, /* Purple */
36 { 0x00, 0xFF, 0xFF }, /* Cyan */
37 { 0xF4, 0x79, 0x20 }, /* Orange */
38 };
39
40 /**
41 * @brief Run tests on a single LED using the LED-based API syscalls.
42 *
43 * @param lp503x_dev LP503X LED controller device.
44 * @param led Number of the LED to test.
45 */
run_led_test(const struct device * lp503x_dev,uint8_t led)46 static int run_led_test(const struct device *lp503x_dev, uint8_t led)
47 {
48 uint8_t idx;
49 int err;
50
51 LOG_INF("Testing LED %d (LED API)", led);
52
53 for (idx = 0; idx < ARRAY_SIZE(colors); idx++) {
54 uint16_t level;
55
56 /* Update LED color. */
57 err = led_set_color(lp503x_dev, led, 3, colors[idx]);
58 if (err < 0) {
59 LOG_ERR("Failed to set LED %d color to "
60 "%02x:%02x:%02x, err=%d", led,
61 colors[idx][0], colors[idx][1],
62 colors[idx][2], err);
63 return err;
64 }
65 k_sleep(SLEEP_DELAY);
66
67 /* Turn LED on. */
68 err = led_on(lp503x_dev, led);
69 if (err < 0) {
70 LOG_ERR("Failed to turn LED %d on, err=%d", led, err);
71 return err;
72 }
73 k_sleep(SLEEP_DELAY);
74
75 /* Turn LED off. */
76 err = led_off(lp503x_dev, led);
77 if (err < 0) {
78 LOG_ERR("Failed to turn LED %d off, err=%d", led, err);
79 return err;
80 }
81 k_sleep(SLEEP_DELAY);
82
83 /* Set LED brightness gradually to the maximum level. */
84 for (level = 0; level <= MAX_BRIGHTNESS; level++) {
85 err = led_set_brightness(lp503x_dev, led, level);
86 if (err < 0) {
87 LOG_ERR("Failed to set LED %d brightness to %d"
88 ", err=%d\n", led, level, err);
89 return err;
90 }
91 k_sleep(FADE_DELAY);
92 }
93 k_sleep(SLEEP_DELAY);
94
95 /* Turn LED off. */
96 err = led_off(lp503x_dev, led);
97 if (err < 0) {
98 LOG_ERR("Failed to turn LED %d off, err=%d", led, err);
99 return err;
100 }
101 k_sleep(SLEEP_DELAY);
102 }
103
104 return 0;
105 }
106
107 /**
108 * @brief Run tests on a all the LEDs using the channel-based API syscalls.
109 *
110 * @param lp503x_dev LP503X LED controller device.
111 */
run_channel_test(const struct device * lp503x_dev)112 static int run_channel_test(const struct device *lp503x_dev)
113 {
114 uint8_t idx;
115 uint8_t buffer[LP503X_COLORS_PER_LED * LP503X_MAX_LEDS];
116 int err;
117
118 LOG_INF("Testing alls LEDs (channel API)");
119
120 for (idx = 0; idx < ARRAY_SIZE(colors); idx++) {
121 uint8_t led;
122 uint16_t level;
123
124 /* Update LEDs colors. */
125 for (led = 0; led < LP503X_MAX_LEDS; led++) {
126 uint8_t *col = &buffer[led * 3];
127
128 col[0] = colors[idx][0];
129 col[1] = colors[idx][1];
130 col[2] = colors[idx][2];
131 }
132 err = led_write_channels(lp503x_dev, LP503X_LED_COL1_CHAN(0),
133 LP503X_COLORS_PER_LED *
134 LP503X_MAX_LEDS,
135 buffer);
136 if (err < 0) {
137 LOG_ERR("Failed to write channels, start=%d num=%d"
138 " err=%d\n", LP503X_LED_COL1_CHAN(0),
139 LP503X_COLORS_PER_LED * LP503X_MAX_LEDS, err);
140 return err;
141 }
142 k_sleep(SLEEP_DELAY);
143
144 /* Turn LEDs on. */
145 for (led = 0; led < LP503X_MAX_LEDS; led++) {
146 buffer[led] = MAX_BRIGHTNESS;
147 }
148 err = led_write_channels(lp503x_dev,
149 LP503X_LED_BRIGHT_CHAN(0),
150 LP503X_MAX_LEDS, buffer);
151 if (err < 0) {
152 LOG_ERR("Failed to write channels, start=%d num=%d"
153 " err=%d\n", LP503X_LED_BRIGHT_CHAN(0),
154 LP503X_MAX_LEDS, err);
155 return err;
156 }
157 k_sleep(SLEEP_DELAY);
158
159 /* Turn LEDs off. */
160 for (led = 0; led < LP503X_MAX_LEDS; led++) {
161 buffer[led] = 0;
162 }
163 err = led_write_channels(lp503x_dev,
164 LP503X_LED_BRIGHT_CHAN(0),
165 LP503X_MAX_LEDS, buffer);
166 if (err < 0) {
167 LOG_ERR("Failed to write channels, start=%d num=%d"
168 " err=%d\n", LP503X_LED_BRIGHT_CHAN(0),
169 LP503X_MAX_LEDS, err);
170 return err;
171 }
172 k_sleep(SLEEP_DELAY);
173
174 /* Set LEDs brightnesses gradually to the maximum level. */
175 for (level = 0; level <= MAX_BRIGHTNESS; level++) {
176 for (led = 0; led < LP503X_MAX_LEDS; led++) {
177 buffer[led] = level;
178 }
179 err = led_write_channels(lp503x_dev,
180 LP503X_LED_BRIGHT_CHAN(0),
181 LP503X_MAX_LEDS, buffer);
182 if (err < 0) {
183 LOG_ERR("Failed to write channels, start=%d"
184 " num=%d err=%d\n",
185 LP503X_LED_BRIGHT_CHAN(0),
186 LP503X_MAX_LEDS, err);
187 return err;
188 }
189 k_sleep(FADE_DELAY);
190 }
191 k_sleep(SLEEP_DELAY);
192
193 /* Turn LED off. */
194 for (led = 0; led < LP503X_MAX_LEDS; led++) {
195 buffer[led] = 0;
196 }
197 err = led_write_channels(lp503x_dev,
198 LP503X_LED_BRIGHT_CHAN(0),
199 LP503X_MAX_LEDS, buffer);
200 if (err < 0) {
201 LOG_ERR("Failed to write channels, start=%d "
202 "num=%d err=%d\n", LP503X_LED_BRIGHT_CHAN(0),
203 LP503X_MAX_LEDS, err);
204 return err;
205 }
206 k_sleep(SLEEP_DELAY);
207 }
208
209 return 0;
210 }
211
main(void)212 void main(void)
213 {
214 const struct device *lp503x_dev = DEVICE_DT_GET_ANY(ti_lp503x);
215
216 int err;
217 uint8_t led;
218 uint8_t num_leds = 0;
219
220 if (!lp503x_dev) {
221 LOG_ERR("No device with compatible ti,lp503x found");
222 return;
223 } else if (!device_is_ready(lp503x_dev)) {
224 LOG_ERR("LED controller %s is not ready", lp503x_dev->name);
225 return;
226 }
227 LOG_INF("Found LED controller %s", lp503x_dev->name);
228
229 for (led = 0; led < LP503X_MAX_LEDS; led++) {
230 int col;
231 const struct led_info *info;
232
233 err = led_get_info(lp503x_dev, led, &info);
234 if (err < 0) {
235 LOG_DBG("Failed to get information for LED %d (err=%d)",
236 led, err);
237 break;
238 }
239
240 /* Display LED information. */
241 printk("Found LED %d", led);
242 if (info->label)
243 printk(" - %s", info->label);
244 printk(" - index:%d", info->index);
245 printk(" - %d colors", info->num_colors);
246 if (!info->color_mapping) {
247 continue;
248 }
249 printk(" - %d", info->color_mapping[0]);
250 for (col = 1; col < info->num_colors; col++)
251 printk(":%d", info->color_mapping[col]);
252 printk("\n");
253 }
254 num_leds = led;
255 if (!num_leds) {
256 LOG_ERR("No LEDs found");
257 return;
258 }
259
260 do {
261 err = run_channel_test(lp503x_dev);
262 if (err) {
263 return;
264 }
265 for (led = 0; led < num_leds; led++) {
266 err = run_led_test(lp503x_dev, led);
267 if (err) {
268 return;
269 }
270 }
271 } while (true);
272 }
273