double framebuffer

This commit is contained in:
2025-10-27 19:46:09 -06:00
parent 4c58f66c94
commit 10c9457953
5 changed files with 46 additions and 15 deletions

View File

@@ -65,8 +65,9 @@ pub mod display {
abi_sys::lock_display(lock); abi_sys::lock_display(lock);
} }
const BUF_SIZE: usize = 250 * 1024; // tune this for performance // const BUF_SIZE: usize = 15 * 1024; // tune this for performance
// static mut BUF: [CPixel; BUF_SIZE] = [CPixel::new(); BUF_SIZE]; // static mut BUF: [CPixel; BUF_SIZE] = [CPixel::new(); BUF_SIZE];
const BUF_SIZE: usize = 250 * 1024; // tune this for performance
static mut BUF: Lazy<Vec<CPixel>> = Lazy::new(|| vec![const { CPixel::new() }; BUF_SIZE]); static mut BUF: Lazy<Vec<CPixel>> = Lazy::new(|| vec![const { CPixel::new() }; BUF_SIZE]);
pub struct Display; pub struct Display;

View File

@@ -2,7 +2,7 @@ MEMORY {
FLASH : ORIGIN = 0x10000000, LENGTH = 16M - 4K FLASH : ORIGIN = 0x10000000, LENGTH = 16M - 4K
RAM : ORIGIN = 0x20000000, LENGTH = 512K RAM : ORIGIN = 0x20000000, LENGTH = 512K
SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K # SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K
SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K
} }

View File

@@ -1,6 +1,6 @@
use crate::framebuffer::{self, AtomicFrameBuffer};
use alloc::vec;
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use crate::framebuffer::AtomicFrameBuffer;
use embassy_rp::{ use embassy_rp::{
Peri, Peri,
gpio::{Level, Output}, gpio::{Level, Output},
@@ -44,6 +44,10 @@ pub async fn init_display(
unsafe { FRAMEBUFFER.draw(&mut display).await.unwrap() } unsafe { FRAMEBUFFER.draw(&mut display).await.unwrap() }
display.set_on().await.unwrap(); display.set_on().await.unwrap();
// create double buffer if board has psram
#[cfg(feature = "pimoroni2w")]
framebuffer::init_double_buffer();
display display
} }
@@ -59,6 +63,13 @@ pub async fn display_handler(mut display: DISPLAY) {
} }
} }
Timer::after_millis(10).await; // Only do swap if feature enabled
#[cfg(feature = "pimoroni2w")]
{
framebuffer::swap_buffers();
}
// small yield to allow other tasks to run
Timer::after_nanos(100).await;
} }
} }

View File

@@ -26,6 +26,24 @@ const SIZE: usize = SCREEN_HEIGHT * SCREEN_WIDTH;
static mut BUFFER: [u16; SIZE] = [0; SIZE]; static mut BUFFER: [u16; SIZE] = [0; SIZE];
#[cfg(feature = "pimoroni2w")]
static mut DOUBLE_BUFFER: Option<alloc::vec::Vec<u16>> = None;
#[cfg(feature = "pimoroni2w")]
pub fn init_double_buffer() {
unsafe { DOUBLE_BUFFER = Some(alloc::vec![0_u16; SIZE]) };
}
#[cfg(feature = "pimoroni2w")]
pub fn swap_buffers() {
unsafe {
core::mem::swap(
&mut BUFFER[..].as_mut_ptr(),
&mut DOUBLE_BUFFER.as_mut().unwrap().as_mut_slice().as_mut_ptr(),
);
}
}
static mut DIRTY_TILES: LazyLock<heapless::Vec<AtomicBool, TILE_COUNT>> = LazyLock::new(|| { static mut DIRTY_TILES: LazyLock<heapless::Vec<AtomicBool, TILE_COUNT>> = LazyLock::new(|| {
let mut tiles = Vec::new(); let mut tiles = Vec::new();
for _ in 0..TILE_COUNT { for _ in 0..TILE_COUNT {

View File

@@ -37,7 +37,7 @@ pub fn main() {
let gif = Gif::<Rgb565>::from_slice(&buf).unwrap(); let gif = Gif::<Rgb565>::from_slice(&buf).unwrap();
let mut frame_num = 0; // let mut frame_num = 0;
loop { loop {
for frame in gif.frames() { for frame in gif.frames() {
let start = get_ms(); let start = get_ms();
@@ -46,18 +46,19 @@ pub fn main() {
frame.draw(&mut display).unwrap(); frame.draw(&mut display).unwrap();
lock_display(false); lock_display(false);
frame_num += 1; // frame_num += 1;
print!("drew {}", frame_num);
sleep(((frame.delay_centis as u64) * 10).saturating_sub(start)); sleep(((frame.delay_centis as u64) * 10).saturating_sub(start));
let event = get_key(); // if frame_num % 100 == 0 {
if event.state != KeyState::Idle { // let event = get_key();
match event.key { // if event.state != KeyState::Idle {
KeyCode::Esc => return, // match event.key {
_ => (), // KeyCode::Esc => return,
}; // _ => (),
}; // };
// };
// }
} }
} }
} }