/*******************************************************************************
* Example 5: GPIO Dashboard
*
* Combined widgets: LED, Switch, Button, Container
* Platform: PSoC Edge E84 + LVGL v9.2.0
******************************************************************************/
#define EX5_NUM_GPIOS 4
/* Data structure สำหรับแต่ละ GPIO channel */
typedef struct {
lv_obj_t *led;
lv_obj_t *sw;
lv_obj_t *label;
const char *name;
bool state;
} gpio_item_t;
/* Global array เก็บทุก channel */
static gpio_item_t ex5_gpios[EX5_NUM_GPIOS];
/* [Callback] เมื่อ switch ถูก toggle */
static void ex5_switch_cb(lv_event_t * e)
{
gpio_item_t * gpio = (gpio_item_t *)lv_event_get_user_data(e);
lv_obj_t * sw = lv_event_get_target(e);
gpio->state = lv_obj_has_state(sw, LV_STATE_CHECKED);
if(gpio->state) {
lv_led_on(gpio->led);
printf("%s: ON\r\n", gpio->name);
} else {
lv_led_off(gpio->led);
printf("%s: OFF\r\n", gpio->name);
}
}
/* [Callback] All ON button */
static void ex5_all_on_cb(lv_event_t * e)
{
(void)e;
for(int i = 0; i < EX5_NUM_GPIOS; i++) {
ex5_gpios[i].state = true;
lv_led_on(ex5_gpios[i].led);
lv_obj_add_state(ex5_gpios[i].sw, LV_STATE_CHECKED);
lv_obj_invalidate(ex5_gpios[i].sw);
lv_obj_invalidate(ex5_gpios[i].led);
}
printf("All LEDs: ON\r\n");
}
/* [Callback] All OFF button */
static void ex5_all_off_cb(lv_event_t * e)
{
(void)e;
for(int i = 0; i < EX5_NUM_GPIOS; i++) {
ex5_gpios[i].state = false;
lv_led_off(ex5_gpios[i].led);
lv_obj_clear_state(ex5_gpios[i].sw, LV_STATE_CHECKED);
lv_obj_invalidate(ex5_gpios[i].sw);
lv_obj_invalidate(ex5_gpios[i].led);
}
printf("All LEDs: OFF\r\n");
}
void part1_ex5_gpio_dashboard(void)
{
const char *gpio_names[] = {"LED1", "LED2", "LED3", "LED4"};
lv_color_t gpio_colors[] = {
lv_palette_main(LV_PALETTE_RED),
lv_palette_main(LV_PALETTE_GREEN),
lv_palette_main(LV_PALETTE_BLUE),
lv_palette_main(LV_PALETTE_YELLOW)
};
/* [1] Background + ปิด scroll หน้าจอหลัก */
lv_obj_set_style_bg_color(lv_screen_active(),
lv_color_hex(0x1a1a2e), LV_PART_MAIN);
lv_obj_clear_flag(lv_screen_active(), LV_OBJ_FLAG_SCROLLABLE);
/* [2] Title */
lv_obj_t * title = lv_label_create(lv_screen_active());
lv_label_set_text(title, "Part 1 - Example 5: GPIO Dashboard");
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 10);
/* [3] Container - กรอบจัดกลุ่ม widget */
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont, 420, 200);
lv_obj_align(cont, LV_ALIGN_CENTER, 0, 10);
lv_obj_set_style_bg_color(cont, lv_color_hex(0x0f0f23), 0);
lv_obj_set_style_border_width(cont, 2, 0);
lv_obj_set_style_border_color(cont, lv_color_hex(0x444444), 0);
lv_obj_clear_flag(cont, LV_OBJ_FLAG_SCROLLABLE);
/* [4] สร้าง GPIO items ใน 2x2 grid */
for(int i = 0; i < EX5_NUM_GPIOS; i++) {
ex5_gpios[i].name = gpio_names[i];
ex5_gpios[i].state = false;
/* คำนวณ grid position */
int x_pos = (i % 2) * 200 + 20; /* Column: 20 หรือ 220 */
int y_pos = (i / 2) * 80 + 20; /* Row: 20 หรือ 100 */
/* LED */
ex5_gpios[i].led = lv_led_create(cont);
lv_obj_set_size(ex5_gpios[i].led, 40, 40);
lv_obj_set_pos(ex5_gpios[i].led, x_pos, y_pos);
lv_led_set_color(ex5_gpios[i].led, gpio_colors[i]);
lv_led_off(ex5_gpios[i].led);
/* Label - จัดอยู่ขวาของ LED */
ex5_gpios[i].label = lv_label_create(cont);
lv_label_set_text(ex5_gpios[i].label, gpio_names[i]);
lv_obj_set_style_text_color(ex5_gpios[i].label,
lv_color_hex(0xFFFFFF), 0);
lv_obj_align_to(ex5_gpios[i].label, ex5_gpios[i].led,
LV_ALIGN_OUT_RIGHT_MID, 10, 0);
/* Switch - จัดอยู่ขวาของ Label */
ex5_gpios[i].sw = lv_switch_create(cont);
lv_obj_set_size(ex5_gpios[i].sw, 60, 30);
lv_obj_align_to(ex5_gpios[i].sw, ex5_gpios[i].label,
LV_ALIGN_OUT_RIGHT_MID, 15, 0);
lv_obj_add_event_cb(ex5_gpios[i].sw, ex5_switch_cb,
LV_EVENT_VALUE_CHANGED, &ex5_gpios[i]);
}
/* [5] All ON button */
lv_obj_t * btn_all_on = lv_button_create(lv_screen_active());
lv_obj_add_event_cb(btn_all_on, ex5_all_on_cb, LV_EVENT_CLICKED, NULL);
lv_obj_align(btn_all_on, LV_ALIGN_BOTTOM_LEFT, 40, -50);
lv_obj_set_style_bg_color(btn_all_on,
lv_palette_main(LV_PALETTE_GREEN), 0);
lv_obj_set_style_pad_hor(btn_all_on, 30, 0);
lv_obj_set_style_pad_ver(btn_all_on, 15, 0);
lv_obj_t * label_on = lv_label_create(btn_all_on);
lv_label_set_text(label_on, "All ON");
lv_obj_center(label_on);
/* [6] All OFF button */
lv_obj_t * btn_all_off = lv_button_create(lv_screen_active());
lv_obj_add_event_cb(btn_all_off, ex5_all_off_cb, LV_EVENT_CLICKED, NULL);
lv_obj_align(btn_all_off, LV_ALIGN_BOTTOM_RIGHT, -40, -50);
lv_obj_set_style_bg_color(btn_all_off,
lv_palette_main(LV_PALETTE_RED), 0);
lv_obj_set_style_pad_hor(btn_all_off, 30, 0);
lv_obj_set_style_pad_ver(btn_all_off, 15, 0);
lv_obj_t * label_off = lv_label_create(btn_all_off);
lv_label_set_text(label_off, "All OFF");
lv_obj_center(label_off);
}