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