Add LCD1602A I2C test with SoftSPI touch and LVGL.
PCF8574 backpack on SDA=GPIO22/SCL=GPIO27, demo/hello/clear/backlight UI, and flashable firmware/cyd package. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
184
src/ui.cpp
Normal file
184
src/ui.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
#include "ui.h"
|
||||
#include "lcd.h"
|
||||
#include "pins.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <lvgl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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_ACCENT = 0x7CDBFF;
|
||||
static constexpr uint32_t COL_DIM = 0x3A4656;
|
||||
static constexpr uint32_t COL_ERR = 0xC62828;
|
||||
|
||||
static lv_obj_t *lbl_title;
|
||||
static lv_obj_t *lbl_pin;
|
||||
static lv_obj_t *lbl_status;
|
||||
static lv_obj_t *lbl_line0;
|
||||
static lv_obj_t *lbl_line1;
|
||||
static lv_obj_t *btn_demo;
|
||||
static lv_obj_t *lbl_demo;
|
||||
static lv_obj_t *btn_hello;
|
||||
static lv_obj_t *btn_clear;
|
||||
static lv_obj_t *btn_bl;
|
||||
static lv_obj_t *lbl_bl;
|
||||
|
||||
static uint8_t g_demo_idx = 0;
|
||||
|
||||
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 lv_obj_t *make_btn(lv_obj_t *parent, const char *txt, int16_t x,
|
||||
int16_t y, int16_t w, int16_t h, lv_event_cb_t cb,
|
||||
lv_obj_t **out_lbl) {
|
||||
lv_obj_t *btn = lv_button_create(parent);
|
||||
lv_obj_set_size(btn, w, h);
|
||||
lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x, y);
|
||||
style_btn(btn, COL_BTN);
|
||||
lv_obj_add_event_cb(btn, cb, LV_EVENT_CLICKED, nullptr);
|
||||
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_16, 0);
|
||||
lv_obj_center(lbl);
|
||||
if (out_lbl) {
|
||||
*out_lbl = lbl;
|
||||
}
|
||||
return btn;
|
||||
}
|
||||
|
||||
void ui_refresh_lcd() {
|
||||
char l0[LCD_COLS + 1];
|
||||
char l1[LCD_COLS + 1];
|
||||
lcd_get_line(0, l0, sizeof(l0));
|
||||
lcd_get_line(1, l1, sizeof(l1));
|
||||
|
||||
if (lbl_line0) {
|
||||
lv_label_set_text_fmt(lbl_line0, "[%s]", l0);
|
||||
}
|
||||
if (lbl_line1) {
|
||||
lv_label_set_text_fmt(lbl_line1, "[%s]", l1);
|
||||
}
|
||||
|
||||
if (lbl_status) {
|
||||
if (lcd_ok()) {
|
||||
lv_label_set_text_fmt(lbl_status, "OK addr 0x%02X", lcd_addr());
|
||||
lv_obj_set_style_text_color(lbl_status, lv_color_hex(COL_ON), 0);
|
||||
} else {
|
||||
lv_label_set_text(lbl_status, "FAIL no PCF8574");
|
||||
lv_obj_set_style_text_color(lbl_status, lv_color_hex(COL_ERR), 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (lbl_bl) {
|
||||
lv_label_set_text(lbl_bl, lcd_backlight() ? "BL OFF" : "BL ON");
|
||||
}
|
||||
if (btn_bl) {
|
||||
style_btn(btn_bl, lcd_backlight() ? COL_ON : COL_DIM);
|
||||
}
|
||||
if (lbl_demo) {
|
||||
lv_label_set_text_fmt(lbl_demo, "Demo %u/%u",
|
||||
(unsigned)(g_demo_idx % lcd_demo_count() + 1),
|
||||
(unsigned)lcd_demo_count());
|
||||
}
|
||||
}
|
||||
|
||||
static void on_demo(lv_event_t *e) {
|
||||
if (lv_event_get_code(e) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
lcd_demo(g_demo_idx);
|
||||
g_demo_idx = (uint8_t)((g_demo_idx + 1) % lcd_demo_count());
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
|
||||
static void on_hello(lv_event_t *e) {
|
||||
if (lv_event_get_code(e) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
lcd_set_backlight(true);
|
||||
lcd_set_line(0, "Hello World!");
|
||||
lcd_set_line(1, "LCD1602A");
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
|
||||
static void on_clear(lv_event_t *e) {
|
||||
if (lv_event_get_code(e) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
lcd_clear();
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
|
||||
static void on_bl(lv_event_t *e) {
|
||||
if (lv_event_get_code(e) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
lcd_set_backlight(!lcd_backlight());
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
lbl_title = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_title, "LCD1602A");
|
||||
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_28, 0);
|
||||
lv_obj_align(lbl_title, LV_ALIGN_TOP_MID, 0, 4);
|
||||
|
||||
lbl_pin = lv_label_create(scr);
|
||||
lv_label_set_text_fmt(lbl_pin, "I2C SDA%d SCL%d PCF8574", LCD_I2C_SDA_PIN,
|
||||
LCD_I2C_SCL_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, 0, 36);
|
||||
|
||||
lbl_status = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_status, "...");
|
||||
lv_obj_set_style_text_font(lbl_status, &lv_font_montserrat_14, 0);
|
||||
lv_obj_align(lbl_status, LV_ALIGN_TOP_MID, 0, 54);
|
||||
|
||||
lbl_line0 = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_line0, "[ ]");
|
||||
lv_obj_set_style_text_color(lbl_line0, lv_color_hex(COL_ACCENT), 0);
|
||||
lv_obj_set_style_text_font(lbl_line0, &lv_font_montserrat_18, 0);
|
||||
lv_obj_align(lbl_line0, LV_ALIGN_TOP_MID, 0, 78);
|
||||
|
||||
lbl_line1 = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_line1, "[ ]");
|
||||
lv_obj_set_style_text_color(lbl_line1, lv_color_hex(COL_ACCENT), 0);
|
||||
lv_obj_set_style_text_font(lbl_line1, &lv_font_montserrat_18, 0);
|
||||
lv_obj_align(lbl_line1, LV_ALIGN_TOP_MID, 0, 104);
|
||||
|
||||
const int16_t gap = 8;
|
||||
const int16_t bw = (UI_HOR_RES - 48 - gap) / 2;
|
||||
const int16_t bx0 = 24;
|
||||
const int16_t row0 = 140;
|
||||
const int16_t row1 = 188;
|
||||
|
||||
btn_demo = make_btn(scr, "Demo", bx0, row0, bw, 40, on_demo, &lbl_demo);
|
||||
btn_hello = make_btn(scr, "Hello", bx0 + bw + gap, row0, bw, 40, on_hello,
|
||||
nullptr);
|
||||
btn_clear =
|
||||
make_btn(scr, "Clear", bx0, row1, bw, 40, on_clear, nullptr);
|
||||
btn_bl = make_btn(scr, "BL OFF", bx0 + bw + gap, row1, bw, 40, on_bl, &lbl_bl);
|
||||
|
||||
(void)btn_demo;
|
||||
(void)btn_hello;
|
||||
(void)btn_clear;
|
||||
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
Reference in New Issue
Block a user