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