acid/firmware/acid-firmware/src/ui/dpi.rs

121 lines
3.5 KiB
Rust
Raw Normal View History

2026-02-15 02:33:42 +01:00
use core::{
alloc::Layout,
cell::UnsafeCell,
ops::{Deref, DerefMut},
2026-02-24 23:07:51 +01:00
sync::atomic::{self, AtomicBool},
2026-02-15 02:33:42 +01:00
};
2026-02-14 20:03:32 +01:00
use alloc::{
alloc::{Allocator, Global},
boxed::Box,
sync::Arc,
2026-02-14 20:03:32 +01:00
vec,
};
use bytemuck::{AnyBitPattern, NoUninit};
2026-02-14 20:03:32 +01:00
use esp_hal::{
Blocking,
dma::{
2026-02-24 23:07:51 +01:00
self, BurstConfig, DmaDescriptor, DmaTxBuffer, Mem2Mem, SimpleMem2Mem,
SimpleMem2MemTransfer,
2026-02-14 20:03:32 +01:00
},
2026-02-24 23:07:51 +01:00
handler,
2026-02-15 02:33:42 +01:00
interrupt::{self, Priority},
lcd_cam::lcd::dpi::{Dpi, DpiTransfer},
2026-02-24 23:07:51 +01:00
peripherals::{DMA, DMA_CH0, Interrupt},
2026-02-14 20:03:32 +01:00
ram,
spi::master::AnySpi,
};
use esp_hal_bounce_buffers::{DmaBounce, Swapchain, SwapchainWriter, allocate_dma_buffer_in};
2026-02-24 23:07:51 +01:00
use log::error;
use ouroboros::self_referencing;
2026-02-14 20:03:32 +01:00
2026-02-24 23:07:51 +01:00
use crate::PSRAM_ALLOCATOR;
2026-02-14 20:03:32 +01:00
2026-02-15 02:33:42 +01:00
/// THIS IS TAKEN FROM https://github.com/esp-rs/esp-hal/blob/main/esp-hal/src/soc/esp32s3/mod.rs
/// Write back a specific range of data in the cache.
#[doc(hidden)]
#[unsafe(link_section = ".rwtext")]
pub unsafe fn cache_writeback_addr(addr: u32, size: u32) {
unsafe extern "C" {
fn rom_Cache_WriteBack_Addr(addr: u32, size: u32);
fn Cache_Suspend_DCache_Autoload() -> u32;
fn Cache_Resume_DCache_Autoload(value: u32);
}
// suspend autoload, avoid load cachelines being written back
unsafe {
let autoload = Cache_Suspend_DCache_Autoload();
rom_Cache_WriteBack_Addr(addr, size);
Cache_Resume_DCache_Autoload(autoload);
}
}
/// THIS IS TAKEN FROM https://github.com/esp-rs/esp-hal/blob/main/esp-hal/src/soc/esp32s3/mod.rs
/// Invalidate a specific range of addresses in the cache.
#[doc(hidden)]
#[unsafe(link_section = ".rwtext")]
pub unsafe fn cache_invalidate_addr(addr: u32, size: u32) {
unsafe extern "C" {
fn Cache_Invalidate_Addr(addr: u32, size: u32);
}
unsafe {
Cache_Invalidate_Addr(addr, size);
}
}
// TODO: Rename or get rid of.
2026-02-22 00:59:01 +01:00
pub struct Framebuffer {
pub width: u32,
pub height: u32,
pub swapchain: Option<SwapchainWriter>,
pub bounce_buffers: Option<DmaBounce>,
2026-02-22 00:59:01 +01:00
}
2026-02-14 20:03:32 +01:00
impl Framebuffer {
2026-02-22 00:59:01 +01:00
pub fn new(
channel: DMA_CH0<'static>,
peripheral_src: AnySpi<'static>,
peripheral_dst: Dpi<'static, Blocking>,
burst_config: BurstConfig,
front_porch_pixels: u32,
width_pixels: u32,
height_pixels: u32,
2026-02-22 00:59:01 +01:00
rows_per_window: usize,
cyclic: bool,
) -> Self {
const BYTES_PER_PIXEL: usize = core::mem::size_of::<u16>();
let buffer_size = width_pixels as usize * height_pixels as usize * BYTES_PER_PIXEL;
let framebuffers = [
Box::leak(allocate_dma_buffer_in(
buffer_size,
burst_config,
&PSRAM_ALLOCATOR,
)),
Box::leak(allocate_dma_buffer_in(
buffer_size,
burst_config,
&PSRAM_ALLOCATOR,
)),
];
let (swapchain_reader, swapchain_writer) = Swapchain { framebuffers }.into_reader_writer();
2026-02-22 00:59:01 +01:00
let bounce_buffers = DmaBounce::new(
Global,
channel,
peripheral_src,
peripheral_dst,
swapchain_reader,
front_porch_pixels as usize * BYTES_PER_PIXEL,
width_pixels as usize * BYTES_PER_PIXEL,
rows_per_window,
2026-02-22 00:59:01 +01:00
burst_config,
cyclic,
2026-02-14 20:03:32 +01:00
);
Self {
width: width_pixels,
height: height_pixels,
swapchain: Some(swapchain_writer),
bounce_buffers: Some(bounce_buffers),
2026-02-14 20:03:32 +01:00
}
}
}