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