Setting the led color based on the app state
[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 <limits.h>
20 #include <stdlib.h>
21 #include <peripheral_io.h>
22 #include <time.h>
23 #include "log.h"
24 #include "resource/resource_led.h"
25 #include "resource/resource_PCA9685.h"
26 #include "config.h"
27
28 #define DEFAULT_BI_LED_RED 17
29 #define DEFAULT_BI_LED_GREEN 27
30
31 #define CONFIG_KEY_RPI_BI_LED_RED "bi.red"
32 #define CONFIG_KEY_RPI_BI_LED_GREEN "bi.green"
33 #define CONFIG_KEY_RPI_USE_BI_LED "bi.use"
34
35 #define CONFIG_KEY_RPI_RGB_GPIO_R "rgb.gpio.red"
36 #define CONFIG_KEY_RPI_RGB_GPIO_G "rgb.gpio.green"
37 #define CONFIG_KEY_RPI_RGB_GPIO_B "rgb.gpio.blue"
38 #define CONFIG_KEY_RPI_USE_GPIO_RGB "rgb.gpio.use"
39
40 #define CONFIG_KEY_RPI_RGB_L2C_R "rgb.l2c.red"
41 #define CONFIG_KEY_RPI_RGB_L2C_G "rgb.l2c.green"
42 #define CONFIG_KEY_RPI_RGB_L2C_B "rgb.l2c.blue"
43 #define CONFIG_KEY_RPI_USE_L2C_RGB "rgb.l2c.use"
44
45
46 #define DEFAULT_RGB_GPIO_R 23
47 #define DEFAULT_RGB_GPIO_G 24
48 #define DEFAULT_RGB_GPIO_B 25
49
50 #define DEFAULT_RGB_L2C_R 8
51 #define DEFAULT_RGB_L2C_G 9
52 #define DEFAULT_RGB_L2C_B 10
53
54 #define CONFIG_GRP_RPI "Rpi.led"
55
56
57 typedef struct _led_s {
58         peripheral_gpio_h gpio_bi_led[2];
59         peripheral_gpio_h rgb_gpio[3];
60         bi_led_color_e current_color;
61
62
63         bool current_rgb_gpio_color[3];
64         int current_rgb_l2c_color[3];
65
66         int use_bi_led;
67         int use_rgb_gpio;
68         int use_rgb_l2c;
69 } led_s;
70
71 static led_s s_info = {
72         .current_color = LED_COLOR_NONE,
73         .current_rgb_gpio_color = { 0, },
74         .current_rgb_l2c_color = { 0, },
75         0, };
76
77 #define  CHECK_GPIO_ERROR(pin, ret) \
78         if (ret != PERIPHERAL_ERROR_NONE) { \
79                 peripheral_gpio_close(pin); \
80                 _E("GPIO ERROR: %s, %s[%d]", get_error_message(ret), __FILE__, __LINE__); \
81                 return ; \
82         }
83
84 #define RGB_TO_REGISTER(val) ((unsigned)((float)val / 255.0f * 4095u))
85
86 static inline void _led_bi_set(bi_led_color_e color)
87 {
88         int red;
89         int green;
90
91         if (!s_info.use_bi_led) {
92                 _D("Bi led is turned OFF");
93                 return;
94         }
95
96         switch (color) {
97                 case LED_COLOR_RED:
98                         red = 1;
99                         green = 0;
100                         break;
101                 case LED_COLOR_GREEN:
102                         red = 0;
103                         green = 1;
104                         break;
105                 default:
106                         red = 0;
107                         green = 0;
108                         break;
109         }
110
111         int ret = peripheral_gpio_write(s_info.gpio_bi_led[LED_COLOR_RED], red);
112         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
113
114         ret = peripheral_gpio_write(s_info.gpio_bi_led[LED_COLOR_GREEN], green);
115         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
116
117         _D("BI: [%d, %d]", red, green);
118 }
119
120 static inline void _rgb_gpio_set(bool red, bool green, bool blue)
121 {
122         if (!s_info.use_rgb_gpio) {
123                 _D("gpio rgb led is turned OFF");
124                 return;
125         }
126
127         _D("RGB GPIO: [%d, %d, %d]", red, green, blue);
128
129         int ret = peripheral_gpio_write(s_info.rgb_gpio[0], red);
130         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
131
132         ret = peripheral_gpio_write(s_info.rgb_gpio[1], green);
133         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
134
135         ret = peripheral_gpio_write(s_info.rgb_gpio[2], blue);
136         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
137 }
138
139 static inline void _rgb_l2c_set(int red, int green, int blue)
140 {
141         if (!s_info.use_rgb_l2c) {
142                 _D("l2c rgb led is turned OFF");
143                 return;
144         }
145
146         int ret = resource_pca9685_set_value_to_channel(DEFAULT_RGB_L2C_R, 0, RGB_TO_REGISTER(red));
147         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
148
149         ret = resource_pca9685_set_value_to_channel(DEFAULT_RGB_L2C_G, 0, RGB_TO_REGISTER(green));
150         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
151
152         ret = resource_pca9685_set_value_to_channel(DEFAULT_RGB_L2C_B, 0, RGB_TO_REGISTER(blue));
153         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
154
155         _D("RGB L2C: [%d, %d, %d] -> [%d, %d, %d]", red, green, blue, RGB_TO_REGISTER(red), RGB_TO_REGISTER(green), RGB_TO_REGISTER(blue));
156 }
157
158 static gboolean _restore_bi_color_cb(gpointer data)
159 {
160         _led_bi_set(s_info.current_color);
161         return false;
162 }
163
164 static gboolean _restore_rgb_gpio_color_cb(gpointer data)
165 {
166         _rgb_gpio_set(s_info.current_rgb_gpio_color[0], s_info.current_rgb_gpio_color[1], s_info.current_rgb_gpio_color[2]);
167         return false;
168 }
169
170 static gboolean _restore_rgb_l2c_color_cb(gpointer data)
171 {
172         _rgb_l2c_set(s_info.current_rgb_l2c_color[0], s_info.current_rgb_l2c_color[1], s_info.current_rgb_l2c_color[2]);
173         return false;
174 }
175
176 static peripheral_gpio_h _init_gpio(int default_gpio, char *key)
177 {
178         peripheral_gpio_h gpio;
179
180         int pin = 0;
181         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, key, default_gpio, &pin);
182
183         _D("Initializing gpio: %d", pin);
184
185         if (modified) {
186                 config_save();
187         }
188
189         int ret = peripheral_gpio_open(pin, &gpio);
190         retv_error_message(ret != PERIPHERAL_ERROR_NONE, ret, 0);
191
192         ret = peripheral_gpio_set_direction(gpio, PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW);
193         retv_error_message(ret != PERIPHERAL_ERROR_NONE, ret, 0);
194
195         return gpio;
196
197 }
198
199 static void _init_bi_led(void)
200 {
201         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_USE_BI_LED, 1, &s_info.use_bi_led);
202         if (modified) {
203                 config_save();
204         }
205
206         if (s_info.use_bi_led) {
207                 s_info.gpio_bi_led[LED_COLOR_RED] = _init_gpio(DEFAULT_BI_LED_RED, CONFIG_KEY_RPI_BI_LED_RED);
208                 s_info.gpio_bi_led[LED_COLOR_GREEN] = _init_gpio(DEFAULT_BI_LED_GREEN, CONFIG_KEY_RPI_BI_LED_GREEN);
209         } else {
210                 _D("BI-Led is turned OFF");
211         }
212 }
213
214 static void _init_rgb_gpio_led(void)
215 {
216         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_USE_GPIO_RGB, 1, &s_info.use_rgb_gpio);
217         if (modified) {
218                 config_save();
219         }
220
221         if (!s_info.use_rgb_gpio) {
222                 _D("RGB GPIO is turned off");
223                 return;
224         }
225
226         s_info.rgb_gpio[0] = _init_gpio(DEFAULT_RGB_GPIO_R, CONFIG_KEY_RPI_RGB_GPIO_R);
227         s_info.rgb_gpio[1] = _init_gpio(DEFAULT_RGB_GPIO_G, CONFIG_KEY_RPI_RGB_GPIO_G);
228         s_info.rgb_gpio[2] = _init_gpio(DEFAULT_RGB_GPIO_B, CONFIG_KEY_RPI_RGB_GPIO_B);
229 }
230
231 void _init_l2c(int default_channel, char *config_key)
232 {
233         int channel;
234         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, config_key, default_channel, &channel);
235         if (modified) {
236                 config_save();
237         }
238
239         int ret = resource_pca9685_init(channel, 60);
240         ret_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
241 }
242
243 static void _init_rgb_l2c_led(void)
244 {
245         bool modified = config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_USE_L2C_RGB, 1, &s_info.use_rgb_l2c);
246         if (modified) {
247                 config_save();
248         }
249
250         if (!s_info.use_rgb_l2c) {
251                 _D("RGB L2C is turned off");
252                 return;
253         }
254
255         _init_l2c(DEFAULT_RGB_L2C_R, CONFIG_KEY_RPI_RGB_L2C_R);
256         _init_l2c(DEFAULT_RGB_L2C_G, CONFIG_KEY_RPI_RGB_L2C_G);
257         _init_l2c(DEFAULT_RGB_L2C_B, CONFIG_KEY_RPI_RGB_L2C_B);
258 }
259
260 void resource_led_init(void)
261 {
262         _D("Initialize Led");
263         _init_rgb_gpio_led();
264         _init_bi_led();
265         _init_rgb_l2c_led();
266 }
267
268 void resource_led_destroy(void)
269 {
270         peripheral_gpio_close(s_info.gpio_bi_led[LED_COLOR_RED]);
271         peripheral_gpio_close(s_info.gpio_bi_led[LED_COLOR_GREEN]);
272
273         peripheral_gpio_close(s_info.rgb_gpio[0]);
274         peripheral_gpio_close(s_info.rgb_gpio[1]);
275         peripheral_gpio_close(s_info.rgb_gpio[2]);
276
277         resource_rgb_l2c_set(0, 0, 0);
278
279         resource_pca9685_fini(DEFAULT_RGB_L2C_R);
280         resource_pca9685_fini(DEFAULT_RGB_L2C_G);
281         resource_pca9685_fini(DEFAULT_RGB_L2C_B);
282 }
283
284 void resource_bi_led_set(bi_led_color_e color)
285 {
286         _D("Set led to: %d", color);
287         if (color == s_info.current_color) {
288                 return;
289         }
290
291         s_info.current_color = color;
292         _led_bi_set(color);
293 }
294
295 void resource_bi_led_blink(bi_led_color_e color, unsigned timeout)
296 {
297         if (color == s_info.current_color) {
298                 return;
299         }
300
301         _led_bi_set(color);
302         g_timeout_add(timeout, _restore_bi_color_cb, NULL);
303 }
304
305 void resource_rgb_gpio_set(bool red, bool green, bool blue)
306 {
307         if (red == s_info.current_rgb_gpio_color[0] &&
308                         green == s_info.current_rgb_gpio_color[1] &&
309                         blue == s_info.current_rgb_gpio_color[2]) {
310                 return;
311         }
312
313
314         s_info.current_rgb_gpio_color[0] = red;
315         s_info.current_rgb_gpio_color[1] = green;
316         s_info.current_rgb_gpio_color[2] = blue;
317
318         _rgb_gpio_set(red, green, blue);
319 }
320
321 void resource_gpio_rgb_blink(bool red, bool green, bool blue, unsigned timeout)
322 {
323         if (red == s_info.current_rgb_gpio_color[0] &&
324                         green == s_info.current_rgb_gpio_color[1] &&
325                         blue == s_info.current_rgb_gpio_color[2]) {
326                 return;
327         }
328
329         _rgb_gpio_set(red, green, blue);
330         g_timeout_add(timeout, _restore_rgb_gpio_color_cb, NULL);
331 }
332
333 void resource_rgb_l2c_set(int red, int green, int blue)
334 {
335         if (red == s_info.current_rgb_l2c_color[0] &&
336                         green == s_info.current_rgb_l2c_color[1] &&
337                         blue == s_info.current_rgb_l2c_color[2]) {
338                 return;
339         }
340
341         s_info.current_rgb_l2c_color[0] = red;
342         s_info.current_rgb_l2c_color[1] = green;
343         s_info.current_rgb_l2c_color[2] = blue;
344
345         _rgb_l2c_set(red, green, blue);
346 }
347
348 void resource_rgb_l2c_blink(int red, int green, int blue, unsigned timeout)
349 {
350         if (red == s_info.current_rgb_l2c_color[0] &&
351                         green == s_info.current_rgb_l2c_color[1] &&
352                         blue == s_info.current_rgb_l2c_color[2]) {
353                 return;
354         }
355
356         _rgb_l2c_set(red, green, blue);
357         g_timeout_add(timeout, _restore_rgb_l2c_color_cb, NULL);
358 }
359