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