1 /*
2  * Copyright (c) 2018 Workaround GmbH
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/device.h>
8 #include <errno.h>
9 #include <zephyr/drivers/led.h>
10 #include <zephyr/sys/util.h>
11 #include <zephyr/kernel.h>
12 
13 #define LOG_LEVEL 4
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(main);
16 
17 #define NUM_LEDS 4
18 #define BLINK_DELAY_ON 500
19 #define BLINK_DELAY_OFF 500
20 #define DELAY_TIME 2000
21 #define COLORS_TO_SHOW 8
22 #define VALUES_PER_COLOR 3
23 
24 /*
25  * We assume that the colors are connected the way it is described in the driver
26  * datasheet.
27  */
28 #define LED_R 2
29 #define LED_G 1
30 #define LED_B 0
31 
32 /*
33  * The following colors are shown in the given order.
34  */
35 static uint8_t colors[COLORS_TO_SHOW][VALUES_PER_COLOR] = {
36 	{ 0xFF, 0x00, 0x00 }, /*< Red    */
37 	{ 0x00, 0xFF, 0x00 }, /*< Green  */
38 	{ 0x00, 0x00, 0xFF }, /*< Blue   */
39 	{ 0xFF, 0xFF, 0xFF }, /*< White  */
40 	{ 0xFF, 0xFF, 0x00 }, /*< Yellow */
41 	{ 0xFF, 0x00, 0xFF }, /*< Purple */
42 	{ 0x00, 0xFF, 0xFF }, /*< Cyan   */
43 	{ 0xF4, 0x79, 0x20 }, /*< Orange */
44 };
45 
46 /*
47  * @brief scale hex values [0x00..0xFF] to percent [0..100].
48  *
49  * @param hex Hex value.
50  *
51  * @return Hex value scaled to percent.
52  */
scale_color_to_percent(uint8_t hex)53 static inline uint8_t scale_color_to_percent(uint8_t hex)
54 {
55 	return (hex * 100U) / 0xFF;
56 }
57 
58 /*
59  * @brief Set a color using the three RGB LEDs.
60  *
61  * @param dev LED device.
62  * @param r Red value in hex [0x00..0xFF].
63  * @param g Green value in hex [0x00..0xFF].
64  * @param b Blue value in hex [0x00..0xFF].
65  *
66  * @return 0 if successful, -ERRNO otherwise.
67  */
set_static_color(const struct device * dev,uint8_t r,uint8_t g,uint8_t b)68 static int set_static_color(const struct device *dev, uint8_t r, uint8_t g,
69 			    uint8_t b)
70 {
71 	int ret;
72 
73 	r = scale_color_to_percent(r);
74 	g = scale_color_to_percent(g);
75 	b = scale_color_to_percent(b);
76 
77 	ret = led_set_brightness(dev, LED_R, r);
78 	if (ret) {
79 		LOG_ERR("Failed to set color.");
80 		return ret;
81 	}
82 
83 	ret = led_set_brightness(dev, LED_G, g);
84 	if (ret) {
85 		LOG_ERR("Failed to set color.");
86 		return ret;
87 	}
88 
89 	ret = led_set_brightness(dev, LED_B, b);
90 	if (ret) {
91 		LOG_ERR("Failed to set color.");
92 		return ret;
93 	}
94 
95 	return 0;
96 }
97 
98 /*
99  * @brief Blink the LED in the given color.
100  *
101  * Currently it is only possible to create colors by turning the three LEDs
102  * completely on or off. Proper mixing is not supported by the underlying API.
103  *
104  * @param dev LED device.
105  * @param r Blink the red LED.
106  * @param g Blink the green LED.
107  * @param b Blink the blue LED.
108  * @param delay_on Time in ms the LEDs stay on.
109  * @param delay_off Time in ms the LEDs stay off.
110  *
111  * @return 0 if successful, -ERRNO otherwise.
112  */
blink_color(const struct device * dev,bool r,bool g,bool b,uint32_t delay_on,uint32_t delay_off)113 static int blink_color(const struct device *dev, bool r, bool g, bool b,
114 		       uint32_t delay_on, uint32_t delay_off)
115 {
116 	int ret;
117 
118 	if (r) {
119 		ret = led_blink(dev, LED_R, delay_on, delay_off);
120 		if (ret) {
121 			LOG_ERR("Failed to set color.");
122 			return ret;
123 		}
124 	}
125 
126 	if (g) {
127 		ret = led_blink(dev, LED_G, delay_on, delay_off);
128 		if (ret) {
129 			LOG_ERR("Failed to set color.");
130 			return ret;
131 		}
132 	}
133 
134 	if (b) {
135 		ret = led_blink(dev, LED_B, delay_on, delay_off);
136 		if (ret) {
137 			LOG_ERR("Failed to set color.");
138 			return ret;
139 		}
140 	}
141 
142 	return 0;
143 }
144 
145 /*
146  * @brief Helper function to turn off all LEDs connected to the driver.
147  *
148  * @param dev LED driver device.
149  *
150  * @return 0 if successful, -ERRNO otherwise.
151  */
turn_off_all_leds(const struct device * dev)152 static int turn_off_all_leds(const struct device *dev)
153 {
154 	for (int i = 0; i < NUM_LEDS; i++) {
155 		int ret = led_off(dev, i);
156 
157 		if (ret) {
158 			return ret;
159 		}
160 	}
161 
162 	return 0;
163 }
164 
main(void)165 int main(void)
166 {
167 	const struct device *const dev = DEVICE_DT_GET_ANY(ti_lp5562);
168 	int i, ret;
169 
170 	if (!dev) {
171 		LOG_ERR("No \"ti,lp5562\" device found");
172 		return 0;
173 	} else if (!device_is_ready(dev)) {
174 		LOG_ERR("LED device %s is not ready", dev->name);
175 		return 0;
176 	} else {
177 		LOG_INF("Found LED device %s", dev->name);
178 	}
179 
180 	LOG_INF("Testing leds");
181 
182 	while (1) {
183 
184 		for (i = 0; i < COLORS_TO_SHOW; i++) {
185 			ret = set_static_color(dev,
186 					colors[i][0],
187 					colors[i][1],
188 					colors[i][2]);
189 			if (ret) {
190 				return 0;
191 			}
192 
193 			k_msleep(DELAY_TIME);
194 		}
195 
196 		ret = turn_off_all_leds(dev);
197 		if (ret < 0) {
198 			return 0;
199 		}
200 
201 		/* Blink white. */
202 		ret = blink_color(dev, true, true, true, BLINK_DELAY_ON,
203 				BLINK_DELAY_OFF);
204 		if (ret) {
205 			return 0;
206 		}
207 
208 		/* Wait a few blinking before turning off the LEDs */
209 		k_msleep(DELAY_TIME * 2);
210 
211 		/* Change the color of the LEDs while keeping blinking. */
212 		for (i = 0; i < COLORS_TO_SHOW; i++) {
213 			ret = set_static_color(dev,
214 					colors[i][0],
215 					colors[i][1],
216 					colors[i][2]);
217 			if (ret) {
218 				return 0;
219 			}
220 
221 			k_msleep(DELAY_TIME * 2);
222 		}
223 
224 		ret = turn_off_all_leds(dev);
225 		if (ret < 0) {
226 			return 0;
227 		}
228 
229 		k_msleep(DELAY_TIME);
230 	}
231 	return 0;
232 }
233