#include <lvgl.h>
#include <LovyanGFX.hpp>

// LovyanGFX display class for ILI9341
class MyDisplay : public lgfx::LGFX_Device {
public:
    MyDisplay() {
        auto cfg = bus_cfg();
        cfg.spi_host = HSPI_HOST;       // Use HSPI
        cfg.spi_mosi = 23;             // MOSI pin
        cfg.spi_miso = -1;             // MISO pin (not used for ILI9341)
        cfg.spi_sclk = 18;             // SCLK pin
        cfg.spi_cs   = 5;              // CS pin
        bus_spi.setBusConfig(cfg);

        auto panel_cfg = panel_cfg();
        panel_cfg.pin_cs   = 5;        // Chip select pin
        panel_cfg.pin_rst  = 4;        // Reset pin
        panel_cfg.pin_busy = -1;       // Busy pin (not used)
        panel_cfg.memory_width  = 240; // ILI9341 width
        panel_cfg.memory_height = 320; // ILI9341 height
        panel_cfg.offset_x      = 0;   // Horizontal offset
        panel_cfg.offset_y      = 0;   // Vertical offset
        panel_cfg.bus_shared = false;  // SPI is not shared
        setPanel(panel_cfg);
    }
};

MyDisplay tft;

void my_lv_tick_handler() {
    lv_tick_inc(1); // Inform LVGL about 1ms time elapsed
}

void setup() {
    Serial.begin(115200);

    // Initialize display
    tft.init();

    // Initialize LVGL
    lv_init();

    // Create a buffer for LVGL
    static lv_color_t buf[LV_HOR_RES_MAX * 10];
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);

    // Register the display in LVGL
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = 240; // Set horizontal resolution
    disp_drv.ver_res = 320; // Set vertical resolution
    disp_drv.flush_cb = [](lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
        tft.startWrite();
        tft.setAddrWindow(area->x1, area->y1, area->x2 - area->x1 + 1, area->y2 - area->y1 + 1);
        tft.pushColors((uint16_t *)&color_p->full, (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1), true);
        tft.endWrite();
        lv_disp_flush_ready(disp); // Inform LVGL that flushing is done
    };
    disp_drv.draw_buf = &disp_buf;
    lv_disp_drv_register(&disp_drv);

    // Add a tick handler for LVGL
    lv_tick_set_cb(my_lv_tick_handler);

    // Create a simple LVGL label
    lv_obj_t *label = lv_label_create(lv_scr_act());
    lv_label_set_text(label, "Hello, ILI9341 with LVGL!");
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
}

void loop() {
    lv_timer_handler(); // Call LVGL's task handler
    delay(5);           // Small delay to allow LVGL to run smoothly
}
esp:0
esp:2
esp:4
esp:5
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:21
esp:22
esp:23
esp:25
esp:26
esp:27
esp:32
esp:33
esp:34
esp:35
esp:3V3
esp:EN
esp:VP
esp:VN
esp:GND.1
esp:D2
esp:D3
esp:CMD
esp:5V
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:D1
esp:D0
esp:CLK
lcd1:VCC
lcd1:GND
lcd1:CS
lcd1:RST
lcd1:D/C
lcd1:MOSI
lcd1:SCK
lcd1:LED
lcd1:MISO
lcd1:SCL
lcd1:SDA