2026-02-15 02:33:42 +01:00
|
|
|
use core::{
|
|
|
|
|
alloc::Layout,
|
2026-02-23 23:08:27 +01:00
|
|
|
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,
|
2026-02-23 23:08:27 +01:00
|
|
|
sync::Arc,
|
2026-02-14 20:03:32 +01:00
|
|
|
vec,
|
|
|
|
|
};
|
2026-02-23 23:08:27 +01:00
|
|
|
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,
|
|
|
|
|
};
|
2026-02-26 02:02:25 +01:00
|
|
|
use esp_hal_bounce_buffers::{DmaBounce, Swapchain, SwapchainWriter, allocate_dma_buffer_in};
|
2026-02-24 23:07:51 +01:00
|
|
|
use log::error;
|
2026-02-23 23:08:27 +01:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-23 23:08:27 +01:00
|
|
|
// TODO: Rename or get rid of.
|
2026-02-22 00:59:01 +01:00
|
|
|
pub struct Framebuffer {
|
|
|
|
|
pub width: u32,
|
|
|
|
|
pub height: u32,
|
2026-02-23 23:08:27 +01:00
|
|
|
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>,
|
2026-02-22 17:19:02 +01:00
|
|
|
burst_config: BurstConfig,
|
2026-02-22 16:09:20 +01:00
|
|
|
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 {
|
2026-02-22 16:09:20 +01:00
|
|
|
const BYTES_PER_PIXEL: usize = core::mem::size_of::<u16>();
|
|
|
|
|
let buffer_size = width_pixels as usize * height_pixels as usize * BYTES_PER_PIXEL;
|
2026-02-23 23:08:27 +01:00
|
|
|
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,
|
2026-02-23 23:08:27 +01:00
|
|
|
swapchain_reader,
|
2026-02-22 16:09:20 +01:00
|
|
|
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 {
|
2026-02-22 16:09:20 +01:00
|
|
|
width: width_pixels,
|
|
|
|
|
height: height_pixels,
|
2026-02-23 23:08:27 +01:00
|
|
|
swapchain: Some(swapchain_writer),
|
|
|
|
|
bounce_buffers: Some(bounce_buffers),
|
2026-02-14 20:03:32 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|