Login
1 branch 0 tags
Ben (Desktop/Arch) AGENTS.md b60dcff 29 days ago 82 Commits
moon / esp32 / main / lvgl_port_esp32.c
/**
 * @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"

// Single full-frame draw buffer for RGB565 (160x128 = 40KB)
static uint16_t draw_buf1[SCREEN_WIDTH * SCREEN_HEIGHT];

static lv_display_t* display;

// Flush callback - queue all SPI transactions async (window + pixels)
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);

	st7735_flush_async(x1, y1, x2, y2, (const uint16_t*)px_map, pixel_count);
}

// Wait callback - blocks until all queued DMA completes, then signals LVGL
static void flush_wait_cb(lv_display_t* disp) {
	st7735_flush_wait();
	lv_display_flush_ready(disp);
}

void lvgl_port_init(void) {
	lv_init();

	lvgl_port_set_refr_period(8);

	// 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);

	// Single full-frame buffer for smooth screen transitions
	lv_display_set_buffers(display, draw_buf1, NULL, sizeof(draw_buf1),
	                       LV_DISPLAY_RENDER_MODE_FULL);

	// 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);
	}
}