1 /**
2 * @file lv_led.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_led.h"
10 #if LV_USE_LED != 0
11
12 #include "../lv_misc/lv_debug.h"
13 #include "../lv_themes/lv_theme.h"
14 #include "../lv_draw/lv_draw.h"
15
16 /*********************
17 * DEFINES
18 *********************/
19 #define LV_OBJX_NAME "lv_led"
20
21 #define LV_LED_WIDTH_DEF (LV_DPI / 3)
22 #define LV_LED_HEIGHT_DEF (LV_DPI / 3)
23
24 /**********************
25 * TYPEDEFS
26 **********************/
27
28 /**********************
29 * STATIC PROTOTYPES
30 **********************/
31 static lv_design_res_t lv_led_design(lv_obj_t * led, const lv_area_t * clip_area, lv_design_mode_t mode);
32 static lv_res_t lv_led_signal(lv_obj_t * led, lv_signal_t sign, void * param);
33
34 /**********************
35 * STATIC VARIABLES
36 **********************/
37 static lv_design_cb_t ancestor_design;
38 static lv_signal_cb_t ancestor_signal;
39
40 /**********************
41 * MACROS
42 **********************/
43
44 /**********************
45 * GLOBAL FUNCTIONS
46 **********************/
47
48 /**
49 * Create a led objects
50 * @param par pointer to an object, it will be the parent of the new led
51 * @param copy pointer to a led object, if not NULL then the new object will be copied from it
52 * @return pointer to the created led
53 */
lv_led_create(lv_obj_t * par,const lv_obj_t * copy)54 lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy)
55 {
56 LV_LOG_TRACE("led create started");
57
58 /*Create the ancestor basic object*/
59 lv_obj_t * led = lv_obj_create(par, copy);
60 LV_ASSERT_MEM(led);
61 if(led == NULL) return NULL;
62
63 if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(led);
64 if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(led);
65
66 /*Allocate the object type specific extended data*/
67 lv_led_ext_t * ext = lv_obj_allocate_ext_attr(led, sizeof(lv_led_ext_t));
68 LV_ASSERT_MEM(ext);
69 if(ext == NULL) {
70 lv_obj_del(led);
71 return NULL;
72 }
73
74 ext->bright = LV_LED_BRIGHT_MAX;
75
76 lv_obj_set_signal_cb(led, lv_led_signal);
77 lv_obj_set_design_cb(led, lv_led_design);
78
79 /*Init the new led object*/
80 if(copy == NULL) {
81 lv_obj_set_size(led, LV_LED_WIDTH_DEF, LV_LED_HEIGHT_DEF);
82
83 lv_theme_apply(led, LV_THEME_LED);
84 }
85 /*Copy an existing object*/
86 else {
87 lv_led_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
88 ext->bright = copy_ext->bright;
89
90 /*Refresh the style with new signal function*/
91 lv_obj_refresh_style(led, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
92 }
93
94 LV_LOG_INFO("led created");
95
96 return led;
97 }
98
99 /*=====================
100 * Setter functions
101 *====================*/
102
103 /**
104 * Set the brightness of a LED object
105 * @param led pointer to a LED object
106 * @param bright LV_LED_BRIGHT_MIN (max. dark) ... LV_LED_BRIGHT_MAX (max. light)
107 */
lv_led_set_bright(lv_obj_t * led,uint8_t bright)108 void lv_led_set_bright(lv_obj_t * led, uint8_t bright)
109 {
110 LV_ASSERT_OBJ(led, LV_OBJX_NAME);
111
112 /*Set the brightness*/
113 lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
114 if(ext->bright == bright) return;
115
116 if(bright <= LV_LED_BRIGHT_MIN) bright = LV_LED_BRIGHT_MIN;
117 if(bright >= LV_LED_BRIGHT_MAX) bright = LV_LED_BRIGHT_MAX;
118
119 ext->bright = bright;
120
121 /*Invalidate the object there fore it will be redrawn*/
122 lv_obj_invalidate(led);
123 }
124
125 /**
126 * Light on a LED
127 * @param led pointer to a LED object
128 */
lv_led_on(lv_obj_t * led)129 void lv_led_on(lv_obj_t * led)
130 {
131 LV_ASSERT_OBJ(led, LV_OBJX_NAME);
132
133 lv_led_set_bright(led, LV_LED_BRIGHT_MAX);
134 }
135
136 /**
137 * Light off a LED
138 * @param led pointer to a LED object
139 */
lv_led_off(lv_obj_t * led)140 void lv_led_off(lv_obj_t * led)
141 {
142 LV_ASSERT_OBJ(led, LV_OBJX_NAME);
143
144 lv_led_set_bright(led, LV_LED_BRIGHT_MIN);
145 }
146
147 /**
148 * Toggle the state of a LED
149 * @param led pointer to a LED object
150 */
lv_led_toggle(lv_obj_t * led)151 void lv_led_toggle(lv_obj_t * led)
152 {
153 LV_ASSERT_OBJ(led, LV_OBJX_NAME);
154
155 uint8_t bright = lv_led_get_bright(led);
156 if(bright > (LV_LED_BRIGHT_MIN + LV_LED_BRIGHT_MAX) >> 1)
157 lv_led_off(led);
158 else
159 lv_led_on(led);
160 }
161
162 /*=====================
163 * Getter functions
164 *====================*/
165
166 /**
167 * Get the brightness of a LEd object
168 * @param led pointer to LED object
169 * @return bright 0 (max. dark) ... 255 (max. light)
170 */
lv_led_get_bright(const lv_obj_t * led)171 uint8_t lv_led_get_bright(const lv_obj_t * led)
172 {
173 LV_ASSERT_OBJ(led, LV_OBJX_NAME);
174
175 lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
176 return ext->bright;
177 }
178
179 /**********************
180 * STATIC FUNCTIONS
181 **********************/
182
183 /**
184 * Handle the drawing related tasks of the leds
185 * @param led pointer to an object
186 * @param clip_area the object will be drawn only in this area
187 * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
188 * (return 'true' if yes)
189 * LV_DESIGN_DRAW: draw the object (always return 'true')
190 * LV_DESIGN_DRAW_POST: drawing after every children are drawn
191 * @param return an element of `lv_design_res_t`
192 */
lv_led_design(lv_obj_t * led,const lv_area_t * clip_area,lv_design_mode_t mode)193 static lv_design_res_t lv_led_design(lv_obj_t * led, const lv_area_t * clip_area, lv_design_mode_t mode)
194 {
195 if(mode == LV_DESIGN_COVER_CHK) {
196 /*Return false if the object is not covers the clip_area area*/
197 return ancestor_design(led, clip_area, mode);
198 }
199 else if(mode == LV_DESIGN_DRAW_MAIN) {
200 /*Make darker colors in a temporary style according to the brightness*/
201 lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
202
203 lv_draw_rect_dsc_t rect_dsc;
204 lv_draw_rect_dsc_init(&rect_dsc);
205 lv_obj_init_draw_rect_dsc(led, LV_LED_PART_MAIN, &rect_dsc);
206
207 /*Mix. the color with black proportionally with brightness*/
208 rect_dsc.bg_color = lv_color_mix(rect_dsc.bg_color, LV_COLOR_BLACK, ext->bright);
209 rect_dsc.bg_grad_color = lv_color_mix(rect_dsc.bg_grad_color, LV_COLOR_BLACK, ext->bright);
210 rect_dsc.border_color = lv_color_mix(rect_dsc.border_color, LV_COLOR_BLACK, ext->bright);
211 rect_dsc.shadow_color = lv_color_mix(rect_dsc.shadow_color, LV_COLOR_BLACK, ext->bright);
212
213 /*Set the current shadow width according to brightness proportionally between LV_LED_BRIGHT_OFF
214 * and LV_LED_BRIGHT_ON*/
215 rect_dsc.shadow_width = ((ext->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_width) /
216 (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN);
217 rect_dsc.shadow_spread = ((ext->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_spread) /
218 (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN);
219
220 lv_draw_rect(&led->coords, clip_area, &rect_dsc);
221 }
222 return LV_DESIGN_RES_OK;
223 }
224
225 /**
226 * Signal function of the led
227 * @param led pointer to a led object
228 * @param sign a signal type from lv_signal_t enum
229 * @param param pointer to a signal specific variable
230 * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
231 */
lv_led_signal(lv_obj_t * led,lv_signal_t sign,void * param)232 static lv_res_t lv_led_signal(lv_obj_t * led, lv_signal_t sign, void * param)
233 {
234 lv_res_t res;
235
236 /* Include the ancient signal function */
237 res = ancestor_signal(led, sign, param);
238 if(res != LV_RES_OK) return res;
239
240 if(sign == LV_SIGNAL_GET_TYPE) {
241 lv_obj_type_t * buf = param;
242 uint8_t i;
243 for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
244 if(buf->type[i] == NULL) break;
245 }
246 buf->type[i] = "lv_led";
247 }
248
249 return res;
250 }
251 #endif
252