use core::ffi::c_void;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
use oxivgl_sys::{
lv_display_create, lv_display_set_buffers, lv_display_set_color_format,
lv_color_format_t_LV_COLOR_FORMAT_RGB565_SWAPPED,
lv_display_render_mode_t_LV_DISPLAY_RENDER_MODE_PARTIAL,
};
#[cfg(feature = "esp-hal")]
use oxivgl_sys::{lv_display_set_flush_cb, lv_display_set_flush_wait_cb};
pub const COLOR_BUF_LINES: usize = 40;
#[repr(align(16))]
pub struct LvglBuf<const BYTES: usize>(pub [u8; BYTES]);
impl<const BYTES: usize> core::fmt::Debug for LvglBuf<BYTES> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LvglBuf").finish_non_exhaustive()
}
}
impl<const BYTES: usize> LvglBuf<BYTES> {
pub const fn new() -> Self { Self([0; BYTES]) }
}
pub struct LvglBuffers<const BYTES: usize> {
pub buf1: LvglBuf<BYTES>,
pub buf2: LvglBuf<BYTES>,
}
impl<const BYTES: usize> core::fmt::Debug for LvglBuffers<BYTES> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LvglBuffers").finish_non_exhaustive()
}
}
impl<const BYTES: usize> LvglBuffers<BYTES> {
pub const fn new() -> Self { Self { buf1: LvglBuf::new(), buf2: LvglBuf::new() } }
}
pub static DISPLAY_READY: Signal<CriticalSectionRawMutex, ()> = Signal::new();
pub unsafe fn lvgl_disp_init<const BYTES: usize>(
w: i32,
h: i32,
bufs: &'static mut LvglBuffers<BYTES>,
) {
unsafe {
let buf1_ptr = core::ptr::addr_of_mut!(bufs.buf1) as *mut c_void;
let buf2_ptr = core::ptr::addr_of_mut!(bufs.buf2) as *mut c_void;
assert_eq!(buf1_ptr as usize % 4, 0, "DMA buffer must be 4-byte aligned");
let disp = lv_display_create(w, h);
assert!(!disp.is_null(), "lv_display_create returned NULL");
lv_display_set_color_format(disp, lv_color_format_t_LV_COLOR_FORMAT_RGB565_SWAPPED);
lv_display_set_buffers(
disp,
buf1_ptr,
buf2_ptr,
BYTES as u32,
lv_display_render_mode_t_LV_DISPLAY_RENDER_MODE_PARTIAL,
);
#[cfg(feature = "esp-hal")]
{
use crate::flush_pipeline::{flush_callback, wait_callback};
lv_display_set_flush_cb(disp, Some(flush_callback));
lv_display_set_flush_wait_cb(disp, Some(wait_callback));
}
#[cfg(not(feature = "esp-hal"))]
DISPLAY_READY.signal(());
}
}