Add touch buttons for speaker toggle and music playback.
Enable SoftSPI touch, replace auto beeps with Speaker ON/OFF and Play Music controls, and document usage. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
186
src/ui.cpp
186
src/ui.cpp
@@ -1,4 +1,5 @@
|
||||
#include "ui.h"
|
||||
#include "audio_test.h"
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
@@ -6,13 +7,12 @@ static lv_obj_t *lbl_status;
|
||||
static lv_obj_t *lbl_type;
|
||||
static lv_obj_t *lbl_fs;
|
||||
static lv_obj_t *lbl_capacity;
|
||||
static lv_obj_t *lbl_total;
|
||||
static lv_obj_t *lbl_used;
|
||||
static lv_obj_t *lbl_free;
|
||||
static lv_obj_t *lbl_files;
|
||||
static lv_obj_t *bar_usage;
|
||||
static lv_obj_t *lbl_hint;
|
||||
static lv_obj_t *lbl_audio;
|
||||
static lv_obj_t *bar_usage;
|
||||
static lv_obj_t *btn_speaker;
|
||||
static lv_obj_t *btn_play;
|
||||
static lv_obj_t *lbl_speaker;
|
||||
static lv_obj_t *lbl_play;
|
||||
|
||||
static lv_obj_t *make_row(lv_obj_t *parent, const char *title, lv_obj_t **value_out) {
|
||||
lv_obj_t *row = lv_obj_create(parent);
|
||||
@@ -20,7 +20,7 @@ static lv_obj_t *make_row(lv_obj_t *parent, const char *title, lv_obj_t **value_
|
||||
lv_obj_set_height(row, LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_bg_opa(row, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(row, 0, 0);
|
||||
lv_obj_set_style_pad_all(row, 2, 0);
|
||||
lv_obj_set_style_pad_all(row, 1, 0);
|
||||
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(row, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER,
|
||||
LV_FLEX_ALIGN_CENTER);
|
||||
@@ -34,11 +34,51 @@ static lv_obj_t *make_row(lv_obj_t *parent, const char *title, lv_obj_t **value_
|
||||
lv_obj_t *v = lv_label_create(row);
|
||||
lv_label_set_text(v, "—");
|
||||
lv_obj_set_style_text_color(v, lv_color_hex(0xECEFF1), 0);
|
||||
lv_obj_set_style_text_font(v, &lv_font_montserrat_16, 0);
|
||||
lv_obj_set_style_text_font(v, &lv_font_montserrat_14, 0);
|
||||
*value_out = v;
|
||||
return row;
|
||||
}
|
||||
|
||||
static void on_speaker_clicked(lv_event_t *e) {
|
||||
LV_UNUSED(e);
|
||||
audio_set_enabled(!audio_is_enabled());
|
||||
ui_refresh_audio_buttons();
|
||||
}
|
||||
|
||||
static void on_play_clicked(lv_event_t *e) {
|
||||
LV_UNUSED(e);
|
||||
if (audio_is_playing()) {
|
||||
audio_stop();
|
||||
} else {
|
||||
audio_play_music();
|
||||
}
|
||||
ui_refresh_audio_buttons();
|
||||
}
|
||||
|
||||
void ui_refresh_audio_buttons() {
|
||||
if (lbl_speaker) {
|
||||
lv_label_set_text(lbl_speaker, audio_is_enabled() ? "Speaker ON" : "Speaker OFF");
|
||||
}
|
||||
if (btn_speaker) {
|
||||
lv_obj_set_style_bg_color(
|
||||
btn_speaker,
|
||||
audio_is_enabled() ? lv_color_hex(0x2E7D32) : lv_color_hex(0x455A64), 0);
|
||||
}
|
||||
|
||||
if (lbl_play) {
|
||||
lv_label_set_text(lbl_play, audio_is_playing() ? "Stop" : "Play Music");
|
||||
}
|
||||
if (btn_play) {
|
||||
lv_obj_set_style_bg_color(
|
||||
btn_play,
|
||||
audio_is_playing() ? lv_color_hex(0xC62828) : lv_color_hex(0x1565C0), 0);
|
||||
}
|
||||
|
||||
if (lbl_audio) {
|
||||
lv_label_set_text(lbl_audio, audio_last_status());
|
||||
}
|
||||
}
|
||||
|
||||
void ui_create() {
|
||||
lv_obj_t *scr = lv_screen_active();
|
||||
lv_obj_set_style_bg_color(scr, lv_color_hex(0x0D1B2A), 0);
|
||||
@@ -48,59 +88,66 @@ void ui_create() {
|
||||
lv_obj_set_size(col, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_set_style_bg_opa(col, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(col, 0, 0);
|
||||
lv_obj_set_style_pad_left(col, 12, 0);
|
||||
lv_obj_set_style_pad_right(col, 12, 0);
|
||||
lv_obj_set_style_pad_top(col, 10, 0);
|
||||
lv_obj_set_style_pad_bottom(col, 8, 0);
|
||||
lv_obj_set_style_pad_left(col, 10, 0);
|
||||
lv_obj_set_style_pad_right(col, 10, 0);
|
||||
lv_obj_set_style_pad_top(col, 6, 0);
|
||||
lv_obj_set_style_pad_bottom(col, 6, 0);
|
||||
lv_obj_set_flex_flow(col, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(col, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER,
|
||||
LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_set_style_pad_row(col, 4, 0);
|
||||
lv_obj_set_style_pad_row(col, 2, 0);
|
||||
lv_obj_clear_flag(col, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t *title = lv_label_create(col);
|
||||
lv_label_set_text(title, "TF Card");
|
||||
lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
|
||||
lv_label_set_text(title, "TF + Speaker");
|
||||
lv_obj_set_style_text_font(title, &lv_font_montserrat_18, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(0x4FC3F7), 0);
|
||||
|
||||
lv_obj_t *subtitle = lv_label_create(col);
|
||||
lv_label_set_text(subtitle, "CYD ESP32 Storage Info");
|
||||
lv_obj_set_style_text_font(subtitle, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(subtitle, lv_color_hex(0x607D8B), 0);
|
||||
|
||||
lv_obj_t *sep = lv_obj_create(col);
|
||||
lv_obj_set_size(sep, LV_PCT(100), 1);
|
||||
lv_obj_set_style_bg_color(sep, lv_color_hex(0x37474F), 0);
|
||||
lv_obj_set_style_bg_opa(sep, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(sep, 0, 0);
|
||||
lv_obj_set_style_pad_all(sep, 0, 0);
|
||||
|
||||
make_row(col, "Status", &lbl_status);
|
||||
make_row(col, "Type", &lbl_type);
|
||||
make_row(col, "Format", &lbl_fs);
|
||||
make_row(col, "Capacity", &lbl_capacity);
|
||||
make_row(col, "Partition", &lbl_total);
|
||||
make_row(col, "Used", &lbl_used);
|
||||
make_row(col, "Free", &lbl_free);
|
||||
make_row(col, "Root files", &lbl_files);
|
||||
make_row(col, "Speaker", &lbl_audio);
|
||||
lv_label_set_text(lbl_audio, "GPIO26");
|
||||
make_row(col, "Audio", &lbl_audio);
|
||||
|
||||
bar_usage = lv_bar_create(col);
|
||||
lv_obj_set_width(bar_usage, LV_PCT(100));
|
||||
lv_obj_set_height(bar_usage, 14);
|
||||
lv_obj_set_height(bar_usage, 10);
|
||||
lv_bar_set_range(bar_usage, 0, 100);
|
||||
lv_bar_set_value(bar_usage, 0, LV_ANIM_OFF);
|
||||
lv_obj_set_style_bg_color(bar_usage, lv_color_hex(0x263238), 0);
|
||||
lv_obj_set_style_bg_opa(bar_usage, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_bg_color(bar_usage, lv_color_hex(0x29B6F6), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_radius(bar_usage, 4, 0);
|
||||
lv_obj_set_style_radius(bar_usage, 4, LV_PART_INDICATOR);
|
||||
|
||||
lbl_hint = lv_label_create(col);
|
||||
lv_label_set_text(lbl_hint, "Refreshing every 3s");
|
||||
lv_obj_set_style_text_font(lbl_hint, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(lbl_hint, lv_color_hex(0x546E7A), 0);
|
||||
// 底部两个触控按钮
|
||||
lv_obj_t *row_btns = lv_obj_create(col);
|
||||
lv_obj_set_width(row_btns, LV_PCT(100));
|
||||
lv_obj_set_height(row_btns, 52);
|
||||
lv_obj_set_style_bg_opa(row_btns, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(row_btns, 0, 0);
|
||||
lv_obj_set_style_pad_all(row_btns, 0, 0);
|
||||
lv_obj_set_flex_flow(row_btns, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(row_btns, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER,
|
||||
LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_clear_flag(row_btns, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
btn_speaker = lv_button_create(row_btns);
|
||||
lv_obj_set_size(btn_speaker, 145, 46);
|
||||
lv_obj_set_style_radius(btn_speaker, 8, 0);
|
||||
lv_obj_add_event_cb(btn_speaker, on_speaker_clicked, LV_EVENT_CLICKED, nullptr);
|
||||
lbl_speaker = lv_label_create(btn_speaker);
|
||||
lv_label_set_text(lbl_speaker, "Speaker OFF");
|
||||
lv_obj_set_style_text_font(lbl_speaker, &lv_font_montserrat_14, 0);
|
||||
lv_obj_center(lbl_speaker);
|
||||
|
||||
btn_play = lv_button_create(row_btns);
|
||||
lv_obj_set_size(btn_play, 145, 46);
|
||||
lv_obj_set_style_radius(btn_play, 8, 0);
|
||||
lv_obj_add_event_cb(btn_play, on_play_clicked, LV_EVENT_CLICKED, nullptr);
|
||||
lbl_play = lv_label_create(btn_play);
|
||||
lv_label_set_text(lbl_play, "Play Music");
|
||||
lv_obj_set_style_text_font(lbl_play, &lv_font_montserrat_14, 0);
|
||||
lv_obj_center(lbl_play);
|
||||
|
||||
ui_refresh_audio_buttons();
|
||||
}
|
||||
|
||||
void ui_update(const SdCardInfo &info) {
|
||||
@@ -110,51 +157,24 @@ void ui_update(const SdCardInfo &info) {
|
||||
lv_label_set_text(lbl_type, info.type);
|
||||
lv_label_set_text(lbl_fs, "—");
|
||||
lv_label_set_text(lbl_capacity, "—");
|
||||
lv_label_set_text(lbl_total, "—");
|
||||
lv_label_set_text(lbl_used, "—");
|
||||
lv_label_set_text(lbl_free, "—");
|
||||
lv_label_set_text(lbl_files, "—");
|
||||
lv_bar_set_value(bar_usage, 0, LV_ANIM_OFF);
|
||||
lv_label_set_text(lbl_hint, "Insert TF and wait...");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
lv_label_set_text(lbl_status, "Mounted OK");
|
||||
lv_obj_set_style_text_color(lbl_status, lv_color_hex(0x66BB6A), 0);
|
||||
lv_label_set_text(lbl_type, info.type);
|
||||
lv_label_set_text(lbl_fs, info.filesystem);
|
||||
String cap = format_bytes(info.card_bytes);
|
||||
lv_label_set_text(lbl_capacity, cap.c_str());
|
||||
|
||||
lv_label_set_text(lbl_status, "Mounted OK");
|
||||
lv_obj_set_style_text_color(lbl_status, lv_color_hex(0x66BB6A), 0);
|
||||
lv_label_set_text(lbl_type, info.type);
|
||||
lv_label_set_text(lbl_fs, info.filesystem);
|
||||
|
||||
String cap = format_bytes(info.card_bytes);
|
||||
String tot = format_bytes(info.total_bytes);
|
||||
String used = format_bytes(info.used_bytes);
|
||||
String freeb = format_bytes(info.free_bytes);
|
||||
|
||||
lv_label_set_text(lbl_capacity, cap.c_str());
|
||||
lv_label_set_text(lbl_total, tot.c_str());
|
||||
lv_label_set_text(lbl_used, used.c_str());
|
||||
lv_label_set_text(lbl_free, freeb.c_str());
|
||||
|
||||
char files_buf[16];
|
||||
snprintf(files_buf, sizeof(files_buf), "%lu", static_cast<unsigned long>(info.root_files));
|
||||
lv_label_set_text(lbl_files, files_buf);
|
||||
|
||||
int pct = 0;
|
||||
if (info.total_bytes > 0) {
|
||||
pct = static_cast<int>((info.used_bytes * 100ULL) / info.total_bytes);
|
||||
if (pct > 100) {
|
||||
pct = 100;
|
||||
int pct = 0;
|
||||
if (info.total_bytes > 0) {
|
||||
pct = static_cast<int>((info.used_bytes * 100ULL) / info.total_bytes);
|
||||
if (pct > 100) {
|
||||
pct = 100;
|
||||
}
|
||||
}
|
||||
lv_bar_set_value(bar_usage, pct, LV_ANIM_ON);
|
||||
}
|
||||
lv_bar_set_value(bar_usage, pct, LV_ANIM_ON);
|
||||
|
||||
char hint[48];
|
||||
snprintf(hint, sizeof(hint), "Used %d%% | SD+Audio", pct);
|
||||
lv_label_set_text(lbl_hint, hint);
|
||||
}
|
||||
|
||||
void ui_set_audio_status(const char *text) {
|
||||
if (lbl_audio == nullptr || text == nullptr) {
|
||||
return;
|
||||
}
|
||||
lv_label_set_text(lbl_audio, text);
|
||||
ui_refresh_audio_buttons();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user