1 /**
2  * @file lv_led.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_led_private.h"
10 #include "../../core/lv_obj_private.h"
11 #include "../../core/lv_obj_class_private.h"
12 
13 #if LV_USE_LED
14 
15 #include "../../misc/lv_assert.h"
16 #include "../../themes/lv_theme.h"
17 #include "../../misc/lv_color.h"
18 
19 /*********************
20  *      DEFINES
21  *********************/
22 #define MY_CLASS (&lv_led_class)
23 
24 /**********************
25  *      TYPEDEFS
26  **********************/
27 
28 /**********************
29  *  STATIC PROTOTYPES
30  **********************/
31 static void lv_led_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
32 static void lv_led_event(const lv_obj_class_t * class_p, lv_event_t * e);
33 
34 /**********************
35  *  STATIC VARIABLES
36  **********************/
37 
38 const lv_obj_class_t lv_led_class  = {
39     .base_class = &lv_obj_class,
40     .constructor_cb = lv_led_constructor,
41     .width_def = LV_DPI_DEF / 5,
42     .height_def = LV_DPI_DEF / 5,
43     .event_cb = lv_led_event,
44     .instance_size = sizeof(lv_led_t),
45     .name = "led",
46 };
47 
48 /**********************
49  *      MACROS
50  **********************/
51 
52 /**********************
53  *   GLOBAL FUNCTIONS
54  **********************/
55 
lv_led_create(lv_obj_t * parent)56 lv_obj_t * lv_led_create(lv_obj_t * parent)
57 {
58     LV_LOG_INFO("begin");
59     lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
60     lv_obj_class_init_obj(obj);
61     return obj;
62 }
63 
64 /*=====================
65  * Setter functions
66  *====================*/
67 
lv_led_set_color(lv_obj_t * obj,lv_color_t color)68 void lv_led_set_color(lv_obj_t * obj, lv_color_t color)
69 {
70     LV_ASSERT_OBJ(obj, MY_CLASS);
71 
72     lv_led_t * led = (lv_led_t *)obj;
73     led->color = color;
74     lv_obj_invalidate(obj);
75 }
76 
lv_led_set_brightness(lv_obj_t * obj,uint8_t bright)77 void lv_led_set_brightness(lv_obj_t * obj, uint8_t bright)
78 {
79     LV_ASSERT_OBJ(obj, MY_CLASS);
80 
81     lv_led_t * led = (lv_led_t *)obj;
82     if(led->bright == bright) return;
83 
84     led->bright = LV_CLAMP(LV_LED_BRIGHT_MIN, bright, LV_LED_BRIGHT_MAX);
85 
86     /*Invalidate the object there fore it will be redrawn*/
87     lv_obj_invalidate(obj);
88 }
89 
lv_led_on(lv_obj_t * led)90 void lv_led_on(lv_obj_t * led)
91 {
92     lv_led_set_brightness(led, LV_LED_BRIGHT_MAX);
93 }
94 
lv_led_off(lv_obj_t * led)95 void lv_led_off(lv_obj_t * led)
96 {
97     lv_led_set_brightness(led, LV_LED_BRIGHT_MIN);
98 }
99 
lv_led_toggle(lv_obj_t * obj)100 void lv_led_toggle(lv_obj_t * obj)
101 {
102     uint8_t bright = lv_led_get_brightness(obj);
103     if(bright > (LV_LED_BRIGHT_MIN + LV_LED_BRIGHT_MAX) >> 1)
104         lv_led_off(obj);
105     else
106         lv_led_on(obj);
107 }
108 
109 /*=====================
110  * Getter functions
111  *====================*/
112 
lv_led_get_brightness(const lv_obj_t * obj)113 uint8_t lv_led_get_brightness(const lv_obj_t * obj)
114 {
115     LV_ASSERT_OBJ(obj, MY_CLASS);
116 
117     lv_led_t * led = (lv_led_t *)obj;
118     return led->bright;
119 }
120 
121 /**********************
122  *   STATIC FUNCTIONS
123  **********************/
124 
lv_led_constructor(const lv_obj_class_t * class_p,lv_obj_t * obj)125 static void lv_led_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
126 {
127     LV_UNUSED(class_p);
128     lv_led_t * led = (lv_led_t *)obj;
129     led->color = lv_theme_get_color_primary(obj);
130     led->bright = LV_LED_BRIGHT_MAX;
131 }
132 
lv_led_event(const lv_obj_class_t * class_p,lv_event_t * e)133 static void lv_led_event(const lv_obj_class_t * class_p, lv_event_t * e)
134 {
135     LV_UNUSED(class_p);
136 
137     lv_result_t res;
138 
139     /* Call the ancestor's event handler */
140     lv_event_code_t code = lv_event_get_code(e);
141     if(code != LV_EVENT_DRAW_MAIN && code != LV_EVENT_DRAW_MAIN_END) {
142         res = lv_obj_event_base(MY_CLASS, e);
143         if(res != LV_RESULT_OK) return;
144     }
145 
146     lv_obj_t * obj = lv_event_get_current_target(e);
147     if(code == LV_EVENT_DRAW_MAIN) {
148         /*Make darker colors in a temporary style according to the brightness*/
149         lv_led_t * led = (lv_led_t *)obj;
150         lv_layer_t * layer = lv_event_get_layer(e);
151 
152         lv_draw_rect_dsc_t rect_dsc;
153         lv_draw_rect_dsc_init(&rect_dsc);
154         rect_dsc.base.layer = layer;
155         lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &rect_dsc);
156 
157         /*Use the original colors brightness to modify color->led*/
158         rect_dsc.bg_color = lv_color_mix(led->color, lv_color_black(), lv_color_brightness(rect_dsc.bg_color));
159         rect_dsc.bg_grad.stops[0].color = lv_color_mix(led->color, lv_color_black(),
160                                                        lv_color_brightness(rect_dsc.bg_grad.stops[0].color));
161         rect_dsc.bg_grad.stops[1].color = lv_color_mix(led->color, lv_color_black(),
162                                                        lv_color_brightness(rect_dsc.bg_grad.stops[1].color));
163         rect_dsc.shadow_color = lv_color_mix(led->color, lv_color_black(), lv_color_brightness(rect_dsc.shadow_color));
164         rect_dsc.border_color = lv_color_mix(led->color, lv_color_black(), lv_color_brightness(rect_dsc.border_color));
165         rect_dsc.outline_color = lv_color_mix(led->color, lv_color_black(), lv_color_brightness(rect_dsc.outline_color));
166 
167         /*Mix. the color with black proportionally with brightness*/
168         rect_dsc.bg_color = lv_color_mix(rect_dsc.bg_color, lv_color_black(), led->bright);
169         rect_dsc.bg_grad.stops[0].color   = lv_color_mix(rect_dsc.bg_grad.stops[0].color, lv_color_black(), led->bright);
170         rect_dsc.bg_grad.stops[1].color   = lv_color_mix(rect_dsc.bg_grad.stops[1].color, lv_color_black(), led->bright);
171         rect_dsc.border_color = lv_color_mix(rect_dsc.border_color, lv_color_black(), led->bright);
172         rect_dsc.shadow_color = lv_color_mix(rect_dsc.shadow_color, lv_color_black(), led->bright);
173         rect_dsc.outline_color = lv_color_mix(rect_dsc.outline_color, lv_color_black(), led->bright);
174 
175         /*Set the current shadow width according to brightness proportionally between LV_LED_BRIGHT_OFF
176          * and LV_LED_BRIGHT_ON*/
177         rect_dsc.shadow_width = ((led->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_width) /
178                                 (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN);
179         rect_dsc.shadow_spread = ((led->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_spread) /
180                                  (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN);
181 
182         lv_draw_rect(layer, &rect_dsc, &obj->coords);
183     }
184 }
185 
186 #endif
187