#include "ui.h" #include "lamp.h" #include "pins.h" #include #include #include static constexpr uint32_t COL_BG = 0x0A1016; static constexpr uint32_t COL_INK = 0xEAF0F6; static constexpr uint32_t COL_MUTED = 0x7A8B9C; static constexpr uint32_t COL_BTN = 0x243140; static constexpr uint32_t COL_ON = 0x1B5E4A; static constexpr uint32_t COL_R = 0xE85D4C; static constexpr uint32_t COL_G = 0x3DDC97; static constexpr uint32_t COL_B = 0x4FC3F7; static lv_obj_t *lbl_state; static lv_obj_t *lbl_bright; static lv_obj_t *slider; static lv_obj_t *btn_r; static lv_obj_t *btn_g; static lv_obj_t *btn_b; static lv_obj_t *lbl_r; static lv_obj_t *lbl_g; static lv_obj_t *lbl_b; static lv_obj_t *btn_light; static lv_obj_t *lbl_light; static void style_btn(lv_obj_t *btn, uint32_t bg) { lv_obj_set_style_radius(btn, 10, 0); lv_obj_set_style_bg_color(btn, lv_color_hex(bg), 0); lv_obj_set_style_bg_opa(btn, LV_OPA_COVER, 0); lv_obj_set_style_shadow_width(btn, 0, 0); lv_obj_set_style_border_width(btn, 0, 0); lv_obj_set_style_pad_all(btn, 0, 0); } static uint32_t accent_for(lamp_color_t c) { if (c == LAMP_COLOR_R) { return COL_R; } if (c == LAMP_COLOR_G) { return COL_G; } return COL_B; } void ui_refresh_lamp() { const bool on = lamp_is_on(); const lamp_color_t c = lamp_color(); const uint8_t pct = lamp_brightness(); const uint32_t accent = accent_for(c); if (lbl_state) { static const char *names[] = {"RED", "GREEN", "BLUE"}; lv_label_set_text_fmt(lbl_state, "%s %s", names[c], on ? "ON" : "OFF"); lv_obj_set_style_text_color(lbl_state, lv_color_hex(on ? accent : 0xE85D4C), 0); } if (lbl_bright) { lv_label_set_text_fmt(lbl_bright, "Brightness %u%%", (unsigned)pct); } if (slider) { lv_slider_set_value(slider, pct, LV_ANIM_OFF); lv_obj_set_style_bg_color(slider, lv_color_hex(accent), LV_PART_INDICATOR); lv_obj_set_style_bg_opa(slider, on ? LV_OPA_COVER : LV_OPA_50, LV_PART_MAIN); } style_btn(btn_r, c == LAMP_COLOR_R ? COL_R : COL_BTN); style_btn(btn_g, c == LAMP_COLOR_G ? COL_G : COL_BTN); style_btn(btn_b, c == LAMP_COLOR_B ? COL_B : COL_BTN); if (lbl_light) { lv_label_set_text(lbl_light, on ? "Turn OFF" : "Turn ON"); } if (btn_light) { style_btn(btn_light, on ? COL_ON : COL_BTN); } } static void on_light(lv_event_t *e) { if (lv_event_get_code(e) != LV_EVENT_CLICKED) { return; } lamp_set_on(!lamp_is_on()); ui_refresh_lamp(); } static void on_color(lv_event_t *e) { if (lv_event_get_code(e) != LV_EVENT_CLICKED) { return; } const lamp_color_t c = (lamp_color_t)(uintptr_t)lv_event_get_user_data(e); lamp_set_color(c); if (!lamp_is_on()) { lamp_set_on(true); } ui_refresh_lamp(); } static void on_slider(lv_event_t *e) { const lv_event_code_t code = lv_event_get_code(e); if (code != LV_EVENT_VALUE_CHANGED && code != LV_EVENT_RELEASED) { return; } lv_obj_t *obj = (lv_obj_t *)lv_event_get_target(e); const int32_t v = lv_slider_get_value(obj); lamp_set_brightness((uint8_t)v); if (!lamp_is_on() && v > 0) { lamp_set_on(true); } ui_refresh_lamp(); } static lv_obj_t *make_color_btn(lv_obj_t *scr, const char *txt, int x, lamp_color_t c, lv_obj_t **out_lbl) { lv_obj_t *btn = lv_button_create(scr); lv_obj_set_size(btn, UW(88), UH(40)); lv_obj_align(btn, LV_ALIGN_TOP_LEFT, UX(x), UY(72)); style_btn(btn, COL_BTN); lv_obj_add_event_cb(btn, on_color, LV_EVENT_CLICKED, (void *)(uintptr_t)c); lv_obj_t *lbl = lv_label_create(btn); lv_label_set_text(lbl, txt); lv_obj_set_style_text_color(lbl, lv_color_hex(COL_INK), 0); lv_obj_set_style_text_font(lbl, &lv_font_montserrat_18, 0); lv_obj_center(lbl); if (out_lbl) { *out_lbl = lbl; } return btn; } void ui_create() { lv_obj_t *scr = lv_screen_active(); lv_obj_set_style_bg_color(scr, lv_color_hex(COL_BG), 0); lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); lv_obj_t *lbl_title = lv_label_create(scr); lv_label_set_text(lbl_title, "KY-009"); lv_obj_set_style_text_color(lbl_title, lv_color_hex(COL_INK), 0); lv_obj_set_style_text_font(lbl_title, &lv_font_montserrat_20, 0); lv_obj_align(lbl_title, LV_ALIGN_TOP_MID, UX(0), UY(4)); lv_obj_t *lbl_pin = lv_label_create(scr); lv_label_set_text_fmt(lbl_pin, "R%d G%d B%d", KY009_R_PIN, KY009_G_PIN, KY009_B_PIN); lv_obj_set_style_text_color(lbl_pin, lv_color_hex(COL_MUTED), 0); lv_obj_set_style_text_font(lbl_pin, &lv_font_montserrat_14, 0); lv_obj_align(lbl_pin, LV_ALIGN_TOP_MID, UX(0), UY(28)); lbl_state = lv_label_create(scr); lv_label_set_text(lbl_state, "RED ON"); lv_obj_set_style_text_color(lbl_state, lv_color_hex(COL_R), 0); lv_obj_set_style_text_font(lbl_state, &lv_font_montserrat_16, 0); lv_obj_align(lbl_state, LV_ALIGN_TOP_MID, UX(0), UY(48)); btn_r = make_color_btn(scr, "R", 24, LAMP_COLOR_R, &lbl_r); btn_g = make_color_btn(scr, "G", 116, LAMP_COLOR_G, &lbl_g); btn_b = make_color_btn(scr, "B", 208, LAMP_COLOR_B, &lbl_b); lbl_bright = lv_label_create(scr); lv_label_set_text(lbl_bright, "Brightness 60%"); lv_obj_set_style_text_color(lbl_bright, lv_color_hex(COL_INK), 0); lv_obj_set_style_text_font(lbl_bright, &lv_font_montserrat_16, 0); lv_obj_align(lbl_bright, LV_ALIGN_TOP_MID, UX(0), UY(124)); slider = lv_slider_create(scr); lv_obj_set_size(slider, UI_HOR_RES - UW(48), UH(28)); lv_slider_set_range(slider, 0, 100); lv_slider_set_value(slider, 60, LV_ANIM_OFF); lv_obj_align(slider, LV_ALIGN_TOP_MID, UX(0), UY(150)); lv_obj_set_style_bg_color(slider, lv_color_hex(COL_BTN), LV_PART_MAIN); lv_obj_set_style_bg_color(slider, lv_color_hex(COL_R), LV_PART_INDICATOR); lv_obj_set_style_bg_color(slider, lv_color_hex(COL_INK), LV_PART_KNOB); lv_obj_set_ext_click_area(slider, 12); lv_obj_add_event_cb(slider, on_slider, LV_EVENT_VALUE_CHANGED, nullptr); lv_obj_add_event_cb(slider, on_slider, LV_EVENT_RELEASED, nullptr); btn_light = lv_button_create(scr); lv_obj_set_size(btn_light, UI_HOR_RES - UW(48), UH(44)); lv_obj_align(btn_light, LV_ALIGN_TOP_MID, UX(0), UY(190)); style_btn(btn_light, COL_ON); lv_obj_add_event_cb(btn_light, on_light, LV_EVENT_CLICKED, nullptr); lbl_light = lv_label_create(btn_light); lv_label_set_text(lbl_light, "Turn OFF"); lv_obj_set_style_text_color(lbl_light, lv_color_hex(COL_INK), 0); lv_obj_set_style_text_font(lbl_light, &lv_font_montserrat_18, 0); lv_obj_center(lbl_light); ui_refresh_lamp(); }