text/plain
•
1.98 KB
•
71 lines
/**
* @file lvgl_port_esp32.c
* LVGL display driver for ESP32-S3 with ST7735
* RGB565 double-buffered with async SPI DMA
*/
#include "lvgl_port.h"
#include "moon.h"
#include "st7735.h"
// Double draw buffers for RGB565 partial refresh (32 lines at 160px)
#define DRAW_BUF_LINES 32
static uint16_t draw_buf1[SCREEN_WIDTH * DRAW_BUF_LINES];
static uint16_t draw_buf2[SCREEN_WIDTH * DRAW_BUF_LINES];
// SPI transaction for async transfers
static spi_transaction_t spi_trans;
static lv_display_t* display;
// Flush callback - queue async SPI transfer (RGB565_SWAPPED = ST7735 byte order)
static void flush_cb(lv_display_t* disp,
const lv_area_t* area,
uint8_t* px_map) {
(void)disp;
int x1 = area->x1;
int y1 = area->y1;
int x2 = area->x2;
int y2 = area->y2;
int pixel_count = (x2 - x1 + 1) * (y2 - y1 + 1);
// Set window and queue async DMA transfer
st7735_set_window(x1, y1, x2, y2);
st7735_write_pixels_async((const uint16_t*)px_map, pixel_count, &spi_trans);
// Do NOT call lv_display_flush_ready() here — flush_wait_cb handles it
}
// Wait callback - blocks until previous DMA completes, then signals LVGL
static void flush_wait_cb(lv_display_t* disp) {
st7735_wait_async();
lv_display_flush_ready(disp);
}
void lvgl_port_init(void) {
lv_init();
// Create display with RGB565 color format
display = lv_display_create(SCREEN_WIDTH, SCREEN_HEIGHT);
lv_display_set_color_format(display, LV_COLOR_FORMAT_RGB565_SWAPPED);
// Set double draw buffers
lv_display_set_buffers(display, draw_buf1, draw_buf2, sizeof(draw_buf1),
LV_DISPLAY_RENDER_MODE_PARTIAL);
// Set flush and flush-wait callbacks
lv_display_set_flush_cb(display, flush_cb);
lv_display_set_flush_wait_cb(display, flush_wait_cb);
}
lv_display_t* lvgl_port_get_display(void) {
return display;
}
void lvgl_port_set_refr_period(uint32_t period_ms) {
lv_timer_t* timer = lv_display_get_refr_timer(display);
if (timer) {
lv_timer_set_period(timer, period_ms);
}
}