Blit dirty data to the screen instead of everything

This commit is contained in:
Savanni D'Gerinel 2025-03-09 11:31:28 -04:00
parent f951518b57
commit ca0bc90e85
3 changed files with 132 additions and 39 deletions

View File

@ -8,6 +8,8 @@
// e c
// d d d
use alloc::vec::Vec;
use crate::font::{Font, Glyph};
pub struct RGB {
@ -18,6 +20,11 @@ pub struct RGB {
pub trait Canvas {
fn set_pixel(&mut self, x: usize, y: usize, color: &RGB);
fn buf(&self) -> &[u8];
fn partial(&self, x1: usize, y1: usize, x2: usize, y2: usize) -> impl Iterator<Item = &[u8]>;
fn clean(&mut self);
fn dirty(&self) -> Option<(usize, usize, usize, usize)>;
fn width(&self) -> usize;
fn fill(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: &RGB) {
for x in x1..x2 {

View File

@ -3,7 +3,10 @@
extern crate alloc;
use alloc::fmt::format;
use alloc::{
fmt::format,
vec::{self, Vec},
};
use embedded_alloc::LlffHeap as Heap;
use embedded_hal::{delay::DelayNs, digital::OutputPin};
use fugit::RateExtU32;
@ -48,6 +51,7 @@ static mut BUF: [u8; 163200] = [0; 163200];
pub struct FrameBuf {
pub buf: &'static mut [u8; 163200],
pub dirty: Option<(usize, usize, usize, usize)>,
pub width: usize,
}
@ -55,6 +59,7 @@ impl FrameBuf {
pub fn new() -> Self {
Self {
buf: unsafe { &mut BUF },
dirty: None,
width: 170,
}
}
@ -62,9 +67,51 @@ impl FrameBuf {
impl Canvas for FrameBuf {
fn set_pixel(&mut self, x: usize, y: usize, color: &RGB) {
self.buf[(y * self.width + x) * 3 + 0] = color.r << 2;
self.buf[(y * self.width + x) * 3 + 1] = color.g << 2;
self.buf[(y * self.width + x) * 3 + 2] = color.b << 2;
let addr = y * self.width + x;
self.buf[addr * 3 + 0] = color.r << 2;
self.buf[addr * 3 + 1] = color.g << 2;
self.buf[addr * 3 + 2] = color.b << 2;
if let Some((ref mut x1, ref mut y1, ref mut x2, ref mut y2)) = self.dirty {
if x < *x1 {
*x1 = x
}
if y < *y1 {
*y1 = y
}
if x > *x2 {
*x2 = x
}
if y > *y2 {
*y2 = y
}
} else {
self.dirty = Some((x, y, x, y));
}
}
fn buf(&self) -> &[u8] {
self.buf
}
fn partial(&self, x1: usize, y1: usize, x2: usize, y2: usize) -> impl Iterator<Item = &[u8]> {
(y1..y2 + 1).map(move |y| {
let start = (y * self.width + x1) * 3;
let end = (y * self.width + x2) * 3;
&self.buf[start..end]
})
}
fn clean(&mut self) {
self.dirty = None;
}
fn dirty(&self) -> Option<(usize, usize, usize, usize)> {
self.dirty
}
fn width(&self) -> usize {
self.width
}
}
@ -186,8 +233,8 @@ unsafe fn main() -> ! {
Ok(v) if v == 0 => print(
&mut canvas,
&font_bitmap,
1,
1,
0,
0,
&format(format_args!("POWER_DOWN")),
&RGB {
r: 63,
@ -199,8 +246,8 @@ unsafe fn main() -> ! {
Err(err) => print(
&mut canvas,
&font_bitmap,
1,
1,
0,
0,
&format(format_args!("ERROR: {:?}", err)),
&RGB {
r: 63,
@ -210,23 +257,34 @@ unsafe fn main() -> ! {
),
}
{
let display = display.acquire();
display.blit_frame(&canvas);
}
loop {
canvas.fill(0, 0, 170, 320, &RGB{ r: 0, g: 0, b: 0 });
print(&mut canvas, &font_bitmap, 1, 1, "A", &RGB{ r: 63, g: 63, b: 63 });
{
let display = display.acquire();
let _ = led.set_high();
timer.delay_ms(100);
display.send_buf(canvas.buf);
let _ = led.set_low();
canvas.fill(0, 0, 170, 60, &RGB { r: 0, g: 0, b: 0 });
if let Some((x1, y1, x2, y2)) = canvas.dirty() {
print(
&mut canvas,
&font_bitmap,
0,
0,
&format(format_args!("{} {} {} {}", x1, y1, x2, y2)),
&RGB {
r: 63,
g: 63,
b: 63,
},
);
}
match light_sensor.read_full_spectrum() {
Ok(full) => print(
&mut canvas,
&font_bitmap,
1,
10,
0,
20,
&format(format_args!("FULL: {}", full)),
&RGB {
r: 63,
@ -237,8 +295,8 @@ unsafe fn main() -> ! {
Err(err) => print(
&mut canvas,
&font_bitmap,
1,
10,
0,
20,
&format(format_args!("FULL: {:?}", err)),
&RGB {
r: 63,
@ -247,21 +305,12 @@ unsafe fn main() -> ! {
},
),
}
print(&mut canvas, &font_bitmap, 10, 1, "B", &RGB{ r: 63, g: 63, b: 63 });
{
let display = display.acquire();
let _ = led.set_high();
timer.delay_ms(100);
display.send_buf(canvas.buf);
let _ = led.set_low();
}
match light_sensor.read_ir() {
Ok(ir) => print(
&mut canvas,
&font_bitmap,
1,
20,
0,
40,
&format(format_args!("IR: {}", ir)),
&RGB {
r: 63,
@ -272,8 +321,8 @@ unsafe fn main() -> ! {
Err(err) => print(
&mut canvas,
&font_bitmap,
1,
20,
0,
40,
&format(format_args!("IR: {:?}", err)),
&RGB {
r: 63,
@ -283,13 +332,10 @@ unsafe fn main() -> ! {
),
}
print(&mut canvas, &font_bitmap, 20, 1, "C", &RGB{ r: 63, g: 63, b: 63 });
{
let display = display.acquire();
let _ = led.set_high();
timer.delay_ms(100);
display.send_buf(canvas.buf);
display.blit_dirty(&canvas);
let _ = led.set_low();
}

View File

@ -5,6 +5,8 @@ use rp_pico::hal::{
Spi, Timer,
};
use crate::canvas::Canvas;
pub struct Step {
param_cnt: usize,
command: u8,
@ -185,14 +187,52 @@ impl<BoardSelectId: PinId, DataCommandId: PinId, D: SpiDevice, Pinout: ValidSpiP
}
}
pub fn send_buf(&mut self, frame: &[u8]) {
pub fn blit_frame(&mut self, frame: &impl Canvas) {
// let _ = DISPOFF.send_command(&mut self.spi, &mut self.data_command);
let _ = self.data_command.set_low();
let _ = self.spi.write(&[RAMWR]);
let _ = self.data_command.set_high();
let _ = self.spi.write(&frame);
let _ = self.spi.write(frame.buf());
// let _ = DISPON.send_command(&mut self.spi, &mut self.data_command);
}
pub fn blit_dirty(&mut self, frame: &impl Canvas) {
if let Some((start_x, start_y, end_x, end_y)) = frame.dirty() {
let end_y = end_y + 60;
Step {
param_cnt: 4,
command: 0x30,
params: [
(start_y >> 8 & 0xff) as u8,
(start_y & 0xff) as u8,
(end_y >> 8 & 0xff) as u8,
(end_y & 0xff) as u8,
],
delay: None,
}
.send_command(&mut self.spi, &mut self.data_command);
Step {
param_cnt: 0,
command: 0x12,
params: [0, 0, 0, 0],
delay: None,
}
.send_command(&mut self.spi, &mut self.data_command);
let _ = self.data_command.set_low();
let _ = self.spi.write(&[RAMWR]);
let _ = self.data_command.set_high();
for row in frame.partial(0, start_y, frame.width(), end_y) {
let _ = self.spi.write(row);
}
Step {
param_cnt: 0,
command: 0x13,
params: [0, 0, 0, 0],
delay: None,
}
.send_command(&mut self.spi, &mut self.data_command);
}
}
}
impl<BoardSelectId: PinId, DataCommandId: PinId, D: SpiDevice, Pinout: ValidSpiPinout<D>> Drop