global access to framebuff

This commit is contained in:
2025-07-30 17:44:52 -06:00
parent 6a5ba29df1
commit 078e1f6931
3 changed files with 95 additions and 57 deletions

12
kernel/src/abi.rs Normal file
View File

@@ -0,0 +1,12 @@
use abi::Syscall;
#[unsafe(no_mangle)]
pub extern "C" fn syscall_dispatch(call: *const Syscall) -> usize {
let call = unsafe { &*call };
match call {
Syscall::DrawPixels { x, y, color } => {
draw_pixel(*x, *y, *color);
0
}
}
}

View File

@@ -1,4 +1,4 @@
use core::sync::atomic::Ordering; use core::{cell::RefCell, sync::atomic::Ordering};
use defmt::info; use defmt::info;
use embassy_rp::{ use embassy_rp::{
@@ -6,7 +6,7 @@ use embassy_rp::{
peripherals::{PIN_13, PIN_14, PIN_15, SPI1}, peripherals::{PIN_13, PIN_14, PIN_15, SPI1},
spi::{Async, Spi}, spi::{Async, Spi},
}; };
use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, signal::Signal}; use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, mutex::Mutex, signal::Signal};
use embassy_time::{Delay, Instant, Timer}; use embassy_time::{Delay, Instant, Timer};
use embedded_graphics::{ use embedded_graphics::{
Drawable, Drawable,
@@ -20,19 +20,31 @@ use embedded_graphics::{
use embedded_hal_bus::spi::ExclusiveDevice; use embedded_hal_bus::spi::ExclusiveDevice;
use portable_atomic::AtomicBool; use portable_atomic::AtomicBool;
use st7365p_lcd::{FrameBuffer, ST7365P}; use st7365p_lcd::{FrameBuffer, ST7365P};
use static_cell::StaticCell;
type DISPLAY = ST7365P<
ExclusiveDevice<Spi<'static, SPI1, Async>, Output<'static>, Delay>,
Output<'static>,
Output<'static>,
Delay,
>;
const SCREEN_WIDTH: usize = 320; const SCREEN_WIDTH: usize = 320;
const SCREEN_HEIGHT: usize = 320; const SCREEN_HEIGHT: usize = 320;
pub static DISPLAY_SIGNAL: Signal<ThreadModeRawMutex, ()> = Signal::new(); type FB = FrameBuffer<SCREEN_WIDTH, SCREEN_HEIGHT, { SCREEN_WIDTH * SCREEN_HEIGHT }>;
static FRAMEBUFFER_CELL: StaticCell<FB> = StaticCell::new();
pub static FRAMEBUFFER: Mutex<ThreadModeRawMutex, RefCell<Option<&'static mut FB>>> =
Mutex::new(RefCell::new(None));
pub async fn display_handler( pub async fn init_display(
spi: Spi<'static, SPI1, Async>, spi: Spi<'static, SPI1, Async>,
cs: PIN_13, cs: PIN_13,
data: PIN_14, data: PIN_14,
reset: PIN_15, reset: PIN_15,
) { ) -> DISPLAY {
let spi_device = ExclusiveDevice::new(spi, Output::new(cs, Level::Low), Delay).unwrap(); let spi_device = ExclusiveDevice::new(spi, Output::new(cs, Level::Low), Delay).unwrap();
defmt::info!("spi made");
let mut display = ST7365P::new( let mut display = ST7365P::new(
spi_device, spi_device,
Output::new(data, Level::Low), Output::new(data, Level::Low),
@@ -41,28 +53,31 @@ pub async fn display_handler(
true, true,
Delay, Delay,
); );
let mut framebuffer: FrameBuffer< let framebuffer = FRAMEBUFFER_CELL.init(FrameBuffer::new());
SCREEN_WIDTH,
SCREEN_HEIGHT,
{ SCREEN_WIDTH * SCREEN_HEIGHT },
> = FrameBuffer::new();
display.init().await.unwrap(); display.init().await.unwrap();
display.set_custom_orientation(0x40).await.unwrap(); display.set_custom_orientation(0x40).await.unwrap();
framebuffer.draw(&mut display).await.unwrap(); framebuffer.draw(&mut display).await.unwrap();
display.set_on().await.unwrap(); display.set_on().await.unwrap();
FRAMEBUFFER
.lock()
.await
.swap(&RefCell::new(Some(framebuffer)));
DISPLAY_SIGNAL.signal(()); display
}
pub async fn display_handler(mut display: DISPLAY) {
loop { loop {
DISPLAY_SIGNAL.wait().await; defmt::info!("drawing");
FRAMEBUFFER
// text.draw(&mut framebuffer).unwrap(); .lock()
.await
let start = Instant::now(); .borrow_mut()
framebuffer .as_mut()
.unwrap()
.partial_draw_batched(&mut display) .partial_draw_batched(&mut display)
.await .await
.unwrap(); .unwrap();
info!("Elapsed {}ms", start.elapsed().as_millis()); Timer::after_millis(32).await; // 30 fps
} }
} }

View File

@@ -3,9 +3,19 @@
#![cfg_attr(not(test), no_std)] #![cfg_attr(not(test), no_std)]
#![cfg_attr(not(test), no_main)] #![cfg_attr(not(test), no_main)]
mod display;
mod peripherals;
mod scsi;
mod storage;
mod usb;
mod utils;
use crate::{ use crate::{
display::DISPLAY_SIGNAL, display::{FRAMEBUFFER, display_handler, init_display},
peripherals::keyboard::{KeyCode, KeyState, read_keyboard_fifo}, peripherals::{
conf_peripherals,
keyboard::{KeyCode, KeyState, read_keyboard_fifo},
},
storage::SdCard, storage::SdCard,
usb::usb_handler, usb::usb_handler,
}; };
@@ -14,7 +24,7 @@ use {defmt_rtt as _, panic_probe as _};
use core::cell::RefCell; use core::cell::RefCell;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_futures::join::join; use embassy_futures::join::{join, join3};
use embassy_rp::{ use embassy_rp::{
gpio::{Input, Level, Output, Pull}, gpio::{Input, Level, Output, Pull},
peripherals::{I2C1, USB}, peripherals::{I2C1, USB},
@@ -25,20 +35,18 @@ use embassy_rp::{i2c, i2c::I2c, spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_sync::mutex::Mutex; use embassy_sync::mutex::Mutex;
use embassy_time::{Delay, Timer}; use embassy_time::{Delay, Timer};
use embedded_graphics::primitives::Rectangle; use embedded_graphics::{
Drawable,
mono_font::{MonoTextStyle, ascii::FONT_6X10},
pixelcolor::{BinaryColor, Rgb565},
prelude::{Point, RgbColor},
primitives::Rectangle,
text::{Text, TextStyle},
};
use embedded_hal_bus::spi::ExclusiveDevice; use embedded_hal_bus::spi::ExclusiveDevice;
use embedded_sdmmc::SdCard as SdmmcSdCard; use embedded_sdmmc::SdCard as SdmmcSdCard;
use heapless::String; use heapless::String;
mod peripherals;
use peripherals::conf_peripherals;
mod display;
use display::display_handler;
mod scsi;
mod storage;
mod usb;
mod utils;
embassy_rp::bind_interrupts!(struct Irqs { embassy_rp::bind_interrupts!(struct Irqs {
I2C1_IRQ => i2c::InterruptHandler<I2C1>; I2C1_IRQ => i2c::InterruptHandler<I2C1>;
USBCTRL_IRQ => embassy_rp_usb::InterruptHandler<USB>; USBCTRL_IRQ => embassy_rp_usb::InterruptHandler<USB>;
@@ -54,25 +62,30 @@ async fn main(_spawner: Spawner) {
let i2c1 = I2c::new_async(p.I2C1, p.PIN_7, p.PIN_6, Irqs, config); let i2c1 = I2c::new_async(p.I2C1, p.PIN_7, p.PIN_6, Irqs, config);
conf_peripherals(i2c1).await; conf_peripherals(i2c1).await;
// SPI1 bus display Timer::after_millis(250).await;
let mut config = spi::Config::default();
config.frequency = 16_000_000;
let spi1 = spi::Spi::new(
p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.DMA_CH0, p.DMA_CH1, config,
);
let usb = embassy_rp_usb::Driver::new(p.USB, Irqs); let display_fut = {
let mut config = spi::Config::default();
config.frequency = 16_000_000;
let spi = Spi::new(
p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.DMA_CH0, p.DMA_CH1, config,
);
let cs = p.PIN_13;
let data = p.PIN_14;
let reset = p.PIN_15;
let display = init_display(spi, cs, data, reset).await;
display_handler(display)
};
defmt::info!("ready");
let sdcard = { let sdcard = {
let mut config = spi::Config::default(); let mut config = spi::Config::default();
config.frequency = 400_000; config.frequency = 400_000;
let spi = Spi::new_blocking( let clk = p.PIN_18;
p.SPI0, let mosi = p.PIN_19;
p.PIN_18, // clk let miso = p.PIN_16;
p.PIN_19, // mosi let spi = Spi::new_blocking(p.SPI0, clk, mosi, miso, config.clone());
p.PIN_16, // miso
config.clone(),
);
let cs = Output::new(p.PIN_17, Level::High); let cs = Output::new(p.PIN_17, Level::High);
let det = Input::new(p.PIN_22, Pull::None); let det = Input::new(p.PIN_22, Pull::None);
@@ -84,18 +97,16 @@ async fn main(_spawner: Spawner) {
SdCard::new(sdcard, det) SdCard::new(sdcard, det)
}; };
usb_handler(usb, sdcard).await; let usb = embassy_rp_usb::Driver::new(p.USB, Irqs);
} let usb_fut = usb_handler(usb, sdcard);
use abi::Syscall; Text::new(
"Framebuffer works",
Point::new(100, 100),
MonoTextStyle::new(&FONT_6X10, Rgb565::GREEN),
)
.draw(*FRAMEBUFFER.lock().await.get_mut().as_mut().unwrap())
.unwrap();
#[no_mangle] display_fut.await;
pub extern "C" fn syscall_dispatch(call: *const Syscall) -> usize {
let call = unsafe { &*call };
match call {
Syscall::DrawPixels { x, y, color } => {
draw_pixel(*x, *y, *color);
0
}
}
} }