Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Arduino.h>
- #define LV_COLOR_16_SWAP 0
- #include <lvgl.h>
- #include <TFT_eSPI.h>
- TFT_eSPI tft = TFT_eSPI();
- static lv_disp_draw_buf_t draw_buf;
- static lv_color_t buf[LV_HOR_RES_MAX * 10];
- #define NUM_TABS 3
- #define NUM_GAUGES 6
- LV_FONT_DECLARE(lv_font_montserrat_14);
- LV_FONT_DECLARE(lv_font_montserrat_28);
- void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
- uint16_t w = area->x2 - area->x1 + 1;
- uint16_t h = area->y2 - area->y1 + 1;
- tft.startWrite();
- tft.setAddrWindow(area->x1, area->y1, w, h);
- tft.pushColors((uint16_t *)&color_p->full, w * h, true);
- tft.endWrite();
- lv_disp_flush_ready(disp);
- }
- typedef struct {
- lv_obj_t *label;
- lv_obj_t *widget;
- } gauge_t;
- gauge_t gauges[NUM_TABS][NUM_GAUGES];
- const char *gauge_titles[NUM_TABS][NUM_GAUGES] = {
- {"RPM", "Speed", "AFR", "CLT", "TPS", "Battery"},
- {"Oil Temp", "Oil Press", "Boost", "IAT", "Load", "MAP"},
- {"Gear", "Lambda", "Ign Adv", "Fuel Trim", "Duty", "Knock"}
- };
- typedef enum {
- GAUGE_ARC,
- GAUGE_BAR,
- GAUGE_LABEL
- } gauge_type_t;
- gauge_type_t gauge_types[NUM_TABS][NUM_GAUGES] = {
- {GAUGE_ARC, GAUGE_ARC, GAUGE_BAR, GAUGE_BAR, GAUGE_BAR, GAUGE_BAR},
- {GAUGE_BAR, GAUGE_BAR, GAUGE_ARC, GAUGE_BAR, GAUGE_BAR, GAUGE_BAR},
- {GAUGE_LABEL, GAUGE_BAR, GAUGE_BAR, GAUGE_BAR, GAUGE_BAR, GAUGE_BAR}
- };
- lv_obj_t *create_gauge(lv_obj_t *parent, const char *title, gauge_type_t type, gauge_t *g);
- lv_obj_t *create_gauge(lv_obj_t *parent, const char *title, gauge_type_t type, gauge_t *g) {
- lv_obj_t *cont = lv_obj_create(parent);
- lv_obj_set_style_bg_color(cont, lv_color_black(), 0);
- lv_obj_set_style_radius(cont, 8, 0);
- lv_obj_set_style_pad_all(cont, 6, 0);
- lv_obj_set_style_border_width(cont, 0, 0);
- lv_obj_set_size(cont, lv_pct(45), lv_pct(30)); // 2x3 layout
- lv_obj_t *label = lv_label_create(cont);
- lv_label_set_text(label, title);
- lv_obj_set_style_text_color(label, lv_color_white(), 0);
- lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 0);
- lv_obj_t *widget = NULL;
- switch (type) {
- case GAUGE_ARC:
- widget = lv_arc_create(cont);
- lv_arc_set_range(widget, 0, 8000); // e.g., RPM
- lv_arc_set_value(widget, 0);
- lv_obj_set_size(widget, 60, 60);
- lv_obj_align(widget, LV_ALIGN_CENTER, 0, 10);
- lv_arc_set_bg_angles(widget, 135, 45);
- lv_arc_set_rotation(widget, 270);
- break;
- case GAUGE_BAR:
- widget = lv_bar_create(cont);
- lv_bar_set_range(widget, 0, 100);
- lv_bar_set_value(widget, 0, LV_ANIM_OFF);
- lv_obj_set_size(widget, lv_pct(80), 10);
- lv_obj_align(widget, LV_ALIGN_CENTER, 0, 10);
- break;
- case GAUGE_LABEL:
- widget = lv_label_create(cont);
- lv_label_set_text(widget, "--");
- lv_obj_set_style_text_color(widget, lv_color_white(), 0);
- lv_obj_align(widget, LV_ALIGN_CENTER, 0, 10);
- break;
- }
- g->label = label;
- g->widget = widget;
- return cont;
- }
- void create_ui() {
- lv_obj_t *tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 30);
- lv_obj_set_style_bg_color(tabview, lv_color_black(), 0);
- for (int t = 0; t < NUM_TABS; t++) {
- lv_obj_t *tab = lv_tabview_add_tab(tabview, ("Tab " + String(t + 1)).c_str());
- lv_obj_set_style_bg_color(tab, lv_color_black(), 0);
- lv_obj_t *grid = lv_obj_create(tab);
- lv_obj_set_size(grid, lv_pct(100), lv_pct(100));
- lv_obj_center(grid);
- lv_obj_set_layout(grid, LV_LAYOUT_FLEX);
- lv_obj_set_flex_flow(grid, LV_FLEX_FLOW_ROW_WRAP);
- lv_obj_set_style_pad_row(grid, 6, 0);
- lv_obj_set_style_pad_column(grid, 6, 0);
- lv_obj_set_scrollbar_mode(grid, LV_SCROLLBAR_MODE_OFF);
- lv_obj_set_style_bg_color(grid, lv_color_black(), 0);
- lv_obj_set_style_border_width(grid, 0, 0);
- for (int g = 0; g < NUM_GAUGES; g++) {
- create_gauge(grid, gauge_titles[t][g], gauge_types[t][g], &gauges[t][g]);
- }
- }
- }
- void update_gauges() {
- static int rpm = 0;
- rpm = (rpm + 200) % 8000;
- char buf[16];
- // Tab 0, RPM
- lv_arc_set_value(gauges[0][0].widget, rpm);
- snprintf(buf, sizeof(buf), "%d", rpm);
- lv_label_set_text(gauges[0][0].label, buf);
- // Tab 0, Speed
- int speed = (rpm / 30) % 240;
- lv_arc_set_value(gauges[0][1].widget, speed);
- snprintf(buf, sizeof(buf), "%d", speed);
- lv_label_set_text(gauges[0][1].label, buf);
- // Tab 0, AFR
- float afr = 14.0 + (rpm % 30) / 10.0;
- lv_bar_set_value(gauges[0][2].widget, afr, LV_ANIM_OFF);
- snprintf(buf, sizeof(buf), "%.1f", afr);
- lv_label_set_text(gauges[0][2].label, buf);
- // Tab 2, Gear
- int gear = 1 + ((rpm / 1000) % 6);
- snprintf(buf, sizeof(buf), "G%d", gear);
- lv_label_set_text(gauges[2][0].widget, buf);
- }
- unsigned long last_update = 0;
- void setup() {
- tft.init();
- uint16_t darkGray = ((30 & 0xF8) << 8) | ((30 & 0xFC) << 3) | (30 >> 3);
- tft.fillScreen(darkGray);
- tft.setRotation(1);
- Serial.begin(1000000);
- // Initialize LVGL
- lv_init();
- lv_refr_now(NULL);
- lv_disp_draw_buf_init(&draw_buf, buf, NULL, LV_HOR_RES_MAX * 10);
- // Setup LVGL Display Driver
- static lv_disp_drv_t disp_drv;
- lv_disp_drv_init(&disp_drv);
- disp_drv.hor_res = 320;
- disp_drv.ver_res = 240;
- disp_drv.flush_cb = my_disp_flush;
- disp_drv.draw_buf = &draw_buf;
- lv_disp_drv_register(&disp_drv);
- create_ui();
- }
- void loop() {
- lv_timer_handler(); // Must call often
- delay(5); // Avoid watchdog
- unsigned long now = millis();
- if (now - last_update > 200) { // update every 200 ms
- last_update = now;
- update_gauges();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment