Config for different led colors displaying the car states
[apps/native/gear-racing-car.git] / src / resource / resource_led.c
1 /*
2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3 *
4 * Licensed under the Flora License, Version 1.1 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://floralicense.org/license/
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <glib.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <limits.h>
21 #include <stdlib.h>
22 #include <peripheral_io.h>
23 #include <time.h>
24 #include "log.h"
25 #include "resource/resource_led.h"
26 #include "resource/resource_PCA9685.h"
27 #include "config.h"
28
29 #define DEFAULT_BI_LED_RED 17
30 #define DEFAULT_BI_LED_GREEN 27
31
32 #define CONFIG_KEY_RPI_BI_LED_RED "bi.red"
33 #define CONFIG_KEY_RPI_BI_LED_GREEN "bi.green"
34 #define CONFIG_KEY_RPI_USE_BI_LED "bi.use"
35
36 #define CONFIG_KEY_RPI_RGB_GPIO_R "rgb.gpio.red"
37 #define CONFIG_KEY_RPI_RGB_GPIO_G "rgb.gpio.green"
38 #define CONFIG_KEY_RPI_RGB_GPIO_B "rgb.gpio.blue"
39 #define CONFIG_KEY_RPI_USE_GPIO_RGB "rgb.gpio.use"
40
41 #define CONFIG_KEY_RPI_RGB_L2C_R "rgb.l2c.red"
42 #define CONFIG_KEY_RPI_RGB_L2C_G "rgb.l2c.green"
43 #define CONFIG_KEY_RPI_RGB_L2C_B "rgb.l2c.blue"
44 #define CONFIG_KEY_RPI_USE_L2C_RGB "rgb.l2c.use"
45
46
47 #define DEFAULT_RGB_GPIO_R 23
48 #define DEFAULT_RGB_GPIO_G 24
49 #define DEFAULT_RGB_GPIO_B 25
50
51 #define DEFAULT_RGB_L2C_R 8
52 #define DEFAULT_RGB_L2C_G 9
53 #define DEFAULT_RGB_L2C_B 10
54
55 #define CONFIG_GRP_RPI "Rpi.led"
56
57
58 typedef struct _led_s {
59         peripheral_gpio_h gpio_bi_led[2];
60         peripheral_gpio_h rgb_gpio[3];
61         bi_led_color_e current_color;
62
63
64         bool current_rgb_gpio_color[3];
65         int current_rgb_l2c_color[3];
66
67         int use_bi_led;
68         int use_rgb_gpio;
69         int use_rgb_l2c;
70 } led_s;
71
72 static led_s s_info = {
73         .current_color = LED_COLOR_NONE,
74         .current_rgb_gpio_color = { 0, },
75         .current_rgb_l2c_color = { 0, },
76         0, };
77
78 #define  CHECK_GPIO_ERROR(pin, ret) \
79         if (ret != PERIPHERAL_ERROR_NONE) { \
80                 peripheral_gpio_close(pin); \
81                 _E("GPIO ERROR: %s, %s[%d]", get_error_message(ret), __FILE__, __LINE__); \
82                 return ; \
83         }
84
85 #define RGB_TO_REGISTER(val) ((unsigned)((float)val / 255.0f * 4095u))
86
87 static inline void _led_bi_set(bi_led_color_e color)
88 {
89         int red;
90         int green;
91
92         if (!s_info.use_bi_led) {
93                 _D("Bi led is turned OFF");
94                 return;
95         }
96
97         switch (color) {
98                 case LED_COLOR_RED:
99                         red = 1;
100                         green = 0;
101                         break;
102                 case LED_COLOR_GREEN:
103                         red = 0;
104                         green = 1;
105                         break;
106                 default:
107                         red = 0;
108                         green = 0;
109                         break;
110         }
111
112         int ret = peripheral_gpio_write(s_info.gpio_bi_led[LED_COLOR_RED], red);
113         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
114
115         ret = peripheral_gpio_write(s_info.gpio_bi_led[LED_COLOR_GREEN], green);
116         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
117
118         _D("BI: [%d, %d]", red, green);
119 }
120
121 static inline void _rgb_gpio_set(bool red, bool green, bool blue)
122 {
123         if (!s_info.use_rgb_gpio) {
124                 _D("gpio rgb led is turned OFF");
125                 return;
126         }
127
128         _D("RGB GPIO: [%d, %d, %d]", red, green, blue);
129
130         int ret = peripheral_gpio_write(s_info.rgb_gpio[0], red);
131         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
132
133         ret = peripheral_gpio_write(s_info.rgb_gpio[1], green);
134         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
135
136         ret = peripheral_gpio_write(s_info.rgb_gpio[2], blue);
137         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
138 }
139
140 static inline void _rgb_l2c_set(int red, int green, int blue)
141 {
142         if (!s_info.use_rgb_l2c) {
143                 _D("l2c rgb led is turned OFF");
144                 return;
145         }
146
147         int ret = resource_pca9685_set_value_to_channel(DEFAULT_RGB_L2C_R, 0, RGB_TO_REGISTER(red));
148         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
149
150         ret = resource_pca9685_set_value_to_channel(DEFAULT_RGB_L2C_G, 0, RGB_TO_REGISTER(green));
151         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
152
153         ret = resource_pca9685_set_value_to_channel(DEFAULT_RGB_L2C_B, 0, RGB_TO_REGISTER(blue));
154         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
155
156         _D("RGB L2C: [%d, %d, %d] -> [%d, %d, %d]", red, green, blue, RGB_TO_REGISTER(red), RGB_TO_REGISTER(green), RGB_TO_REGISTER(blue));
157 }
158
159 static gboolean _restore_bi_color_cb(gpointer data)
160 {
161         _led_bi_set(s_info.current_color);
162         return false;
163 }
164
165 static gboolean _restore_rgb_gpio_color_cb(gpointer data)
166 {
167         _rgb_gpio_set(s_info.current_rgb_gpio_color[0], s_info.current_rgb_gpio_color[1], s_info.current_rgb_gpio_color[2]);
168         return false;
169 }
170
171 static gboolean _restore_rgb_l2c_color_cb(gpointer data)
172 {
173         _rgb_l2c_set(s_info.current_rgb_l2c_color[0], s_info.current_rgb_l2c_color[1], s_info.current_rgb_l2c_color[2]);
174         return false;
175 }
176
177 static gboolean _restore_rgb_color_cb(gpointer data)
178 {
179         _restore_bi_color_cb(data);
180         _restore_rgb_gpio_color_cb(data);
181         _restore_rgb_l2c_color_cb(data);
182
183         return false;
184 }
185
186 static peripheral_gpio_h _init_gpio(int default_gpio, char *key)
187 {
188         peripheral_gpio_h gpio;
189
190         int pin = 0;
191         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, key, default_gpio, &pin);
192
193         _D("Initializing gpio: %d", pin);
194
195         if (modified) {
196                 config_save();
197         }
198
199         int ret = peripheral_gpio_open(pin, &gpio);
200         retv_error_message(ret != PERIPHERAL_ERROR_NONE, ret, 0);
201
202         ret = peripheral_gpio_set_direction(gpio, PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW);
203         retv_error_message(ret != PERIPHERAL_ERROR_NONE, ret, 0);
204
205         return gpio;
206
207 }
208
209 static void _init_bi_led(void)
210 {
211         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_USE_BI_LED, 1, &s_info.use_bi_led);
212         if (modified) {
213                 config_save();
214         }
215
216         if (s_info.use_bi_led) {
217                 s_info.gpio_bi_led[LED_COLOR_RED] = _init_gpio(DEFAULT_BI_LED_RED, CONFIG_KEY_RPI_BI_LED_RED);
218                 s_info.gpio_bi_led[LED_COLOR_GREEN] = _init_gpio(DEFAULT_BI_LED_GREEN, CONFIG_KEY_RPI_BI_LED_GREEN);
219         } else {
220                 _D("BI-Led is turned OFF");
221         }
222 }
223
224 static void _init_rgb_gpio_led(void)
225 {
226         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_USE_GPIO_RGB, 1, &s_info.use_rgb_gpio);
227         if (modified) {
228                 config_save();
229         }
230
231         if (!s_info.use_rgb_gpio) {
232                 _D("RGB GPIO is turned off");
233                 return;
234         }
235
236         s_info.rgb_gpio[0] = _init_gpio(DEFAULT_RGB_GPIO_R, CONFIG_KEY_RPI_RGB_GPIO_R);
237         s_info.rgb_gpio[1] = _init_gpio(DEFAULT_RGB_GPIO_G, CONFIG_KEY_RPI_RGB_GPIO_G);
238         s_info.rgb_gpio[2] = _init_gpio(DEFAULT_RGB_GPIO_B, CONFIG_KEY_RPI_RGB_GPIO_B);
239 }
240
241 void _init_l2c(int default_channel, char *config_key)
242 {
243         int channel;
244         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, config_key, default_channel, &channel);
245         if (modified) {
246                 config_save();
247         }
248
249         int ret = resource_pca9685_init(channel, 60);
250         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
251 }
252
253 static void _init_rgb_l2c_led(void)
254 {
255         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_USE_L2C_RGB, 1, &s_info.use_rgb_l2c);
256         if (modified) {
257                 config_save();
258         }
259
260         if (!s_info.use_rgb_l2c) {
261                 _D("RGB L2C is turned off");
262                 return;
263         }
264
265         _init_l2c(DEFAULT_RGB_L2C_R, CONFIG_KEY_RPI_RGB_L2C_R);
266         _init_l2c(DEFAULT_RGB_L2C_G, CONFIG_KEY_RPI_RGB_L2C_G);
267         _init_l2c(DEFAULT_RGB_L2C_B, CONFIG_KEY_RPI_RGB_L2C_B);
268 }
269
270 void resource_led_init(void)
271 {
272         _D("Initialize Led");
273         _init_rgb_gpio_led();
274         _init_bi_led();
275         _init_rgb_l2c_led();
276 }
277
278 void resource_led_destroy(void)
279 {
280         peripheral_gpio_close(s_info.gpio_bi_led[LED_COLOR_RED]);
281         peripheral_gpio_close(s_info.gpio_bi_led[LED_COLOR_GREEN]);
282
283         peripheral_gpio_close(s_info.rgb_gpio[0]);
284         peripheral_gpio_close(s_info.rgb_gpio[1]);
285         peripheral_gpio_close(s_info.rgb_gpio[2]);
286
287         resource_led_rgb_l2c_set(0, 0, 0);
288
289         resource_pca9685_fini(DEFAULT_RGB_L2C_R);
290         resource_pca9685_fini(DEFAULT_RGB_L2C_G);
291         resource_pca9685_fini(DEFAULT_RGB_L2C_B);
292 }
293
294 void resource_led_bi_set(bi_led_color_e color)
295 {
296         _D("Set led to: %d", color);
297         if (color == s_info.current_color) {
298                 return;
299         }
300
301         s_info.current_color = color;
302         _led_bi_set(color);
303 }
304
305 void resource_led_bi_blink(bi_led_color_e color, unsigned timeout)
306 {
307         if (color == s_info.current_color) {
308                 return;
309         }
310
311         _led_bi_set(color);
312         g_timeout_add(timeout, _restore_bi_color_cb, NULL);
313 }
314
315 void resource_led_rgb_gpio_set(bool red, bool green, bool blue)
316 {
317         if (red == s_info.current_rgb_gpio_color[0] &&
318                         green == s_info.current_rgb_gpio_color[1] &&
319                         blue == s_info.current_rgb_gpio_color[2]) {
320                 return;
321         }
322
323
324         s_info.current_rgb_gpio_color[0] = red;
325         s_info.current_rgb_gpio_color[1] = green;
326         s_info.current_rgb_gpio_color[2] = blue;
327
328         _rgb_gpio_set(red, green, blue);
329 }
330
331 void resource_led_gpio_rgb_blink(bool red, bool green, bool blue, unsigned timeout)
332 {
333         if (red == s_info.current_rgb_gpio_color[0] &&
334                         green == s_info.current_rgb_gpio_color[1] &&
335                         blue == s_info.current_rgb_gpio_color[2]) {
336                 return;
337         }
338
339         _rgb_gpio_set(red, green, blue);
340         g_timeout_add(timeout, _restore_rgb_gpio_color_cb, NULL);
341 }
342
343 void resource_led_rgb_l2c_set(int red, int green, int blue)
344 {
345         if (red == s_info.current_rgb_l2c_color[0] &&
346                         green == s_info.current_rgb_l2c_color[1] &&
347                         blue == s_info.current_rgb_l2c_color[2]) {
348                 return;
349         }
350
351         s_info.current_rgb_l2c_color[0] = red;
352         s_info.current_rgb_l2c_color[1] = green;
353         s_info.current_rgb_l2c_color[2] = blue;
354
355         _rgb_l2c_set(red, green, blue);
356 }
357
358 void resource_led_rgb_l2c_blink(int red, int green, int blue, unsigned timeout)
359 {
360         if (red == s_info.current_rgb_l2c_color[0] &&
361                         green == s_info.current_rgb_l2c_color[1] &&
362                         blue == s_info.current_rgb_l2c_color[2]) {
363                 return;
364         }
365
366         _rgb_l2c_set(red, green, blue);
367         g_timeout_add(timeout, _restore_rgb_l2c_color_cb, NULL);
368 }
369
370 void resource_led_set_rgb_colors(char *key,
371                 int def_r_3bit, int def_g_3bit, int def_b_3bit,
372                 int def_r_24bit, int def_g_24bit, int def_b_24bit,
373                 bi_led_color_e bi_led)
374 {
375         int red, green, blue;
376         char final_key[PATH_MAX];
377
378         snprintf(final_key, PATH_MAX, "3bit.%s", key);
379         bool modified = config_get_rgb_with_default("Rpi.led", final_key, def_r_3bit, def_g_3bit, def_b_3bit, &red, &green, &blue);
380         resource_led_rgb_gpio_set(red, green, blue);
381
382         _D("%s: 3bit color: [%d, %d, %d]", final_key, red, green, blue);
383
384         snprintf(final_key, PATH_MAX, "24bit.%s", key);
385         modified |= config_get_rgb_with_default("Rpi.led", final_key, def_r_24bit, def_g_24bit, def_b_24bit, &red, &green, &blue);
386         resource_led_rgb_l2c_set(red, green, blue);
387
388         _D("%s: 24bit color: [%d, %d, %d]", final_key, red, green, blue);
389
390         int value;
391         snprintf(final_key, PATH_MAX, "bicolor.%s", key);
392         modified |= config_get_int_with_default("Rpi.led", final_key, bi_led, &value);
393         resource_led_bi_set(value);
394
395         if (modified) {
396                 config_save();
397         }
398         _D("%s: bicolor: [%d]", final_key, value);
399 }
400
401 void resource_led_blink_rgb_colors(char *key,
402                 int def_r_3bit, int def_g_3bit, int def_b_3bit,
403                 int def_r_24bit, int def_g_24bit, int def_b_24bit,
404                 bi_led_color_e bi_led, int timeout)
405 {
406         resource_led_set_rgb_colors(key, def_r_3bit, def_g_3bit, def_b_3bit, def_r_24bit, def_g_24bit, def_b_24bit, bi_led);
407
408         g_timeout_add(timeout, _restore_rgb_color_cb, NULL);
409 }