From f3c67beb00eee1cf8dd0a3cd01b439b0e87f08bf Mon Sep 17 00:00:00 2001 From: sawyer bristol Date: Wed, 27 Aug 2025 17:12:51 -0600 Subject: [PATCH] userlib now implements embedded_graphics::DrawTarget --- Cargo.lock | 12 ++++- abi/Cargo.toml | 1 + abi/src/lib.rs | 90 ++++++++++++++++++++++++-------- abi_sys/Cargo.toml | 8 +++ abi_sys/src/lib.rs | 28 ++++++++++ kernel/Cargo.toml | 2 +- kernel/src/abi.rs | 2 +- user-apps/calculator/Cargo.toml | 1 + user-apps/calculator/src/main.rs | 39 +++++++------- 9 files changed, 141 insertions(+), 42 deletions(-) create mode 100644 abi_sys/Cargo.toml create mode 100644 abi_sys/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index da46856..0f917d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,15 @@ dependencies = [ [[package]] name = "abi" version = "0.1.0" +dependencies = [ + "abi_sys", + "embedded-graphics", + "shared", +] + +[[package]] +name = "abi_sys" +version = "0.1.0" dependencies = [ "embedded-graphics", "shared", @@ -208,6 +217,7 @@ name = "calculator" version = "0.1.0" dependencies = [ "abi", + "embedded-graphics", ] [[package]] @@ -1163,7 +1173,7 @@ dependencies = [ name = "kernel" version = "0.1.0" dependencies = [ - "abi", + "abi_sys", "bitflags 2.9.1", "bt-hci", "cortex-m", diff --git a/abi/Cargo.toml b/abi/Cargo.toml index e7aaf0e..d20ffeb 100644 --- a/abi/Cargo.toml +++ b/abi/Cargo.toml @@ -6,3 +6,4 @@ edition = "2024" [dependencies] embedded-graphics = "0.8.1" shared = { path = "../shared" } +abi_sys = { path = "../abi_sys" } diff --git a/abi/src/lib.rs b/abi/src/lib.rs index 2ed0f97..c387b4a 100644 --- a/abi/src/lib.rs +++ b/abi/src/lib.rs @@ -1,28 +1,76 @@ #![no_std] -pub use embedded_graphics::{ - Pixel, - geometry::Point, - pixelcolor::{Rgb565, RgbColor}, -}; +use abi_sys::{Syscall, call_abi}; use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers}; -// Instead of extern, declare a static pointer in a dedicated section -#[unsafe(no_mangle)] -#[unsafe(link_section = ".user_reloc")] -#[allow(non_upper_case_globals)] -pub static mut call_abi_ptr: usize = 0; +pub mod display { + use crate::{Syscall, call_abi}; + use embedded_graphics::{ + Pixel, + geometry::{Dimensions, Point}, + pixelcolor::{Rgb565, RgbColor}, + prelude::{DrawTarget, Size}, + primitives::Rectangle, + }; -// Helper to call it -pub unsafe fn call_abi(call: *const Syscall) { - let f: extern "C" fn(*const Syscall) = unsafe { core::mem::transmute(call_abi_ptr) }; - f(call); -} + pub const SCREEN_WIDTH: usize = 320; + pub const SCREEN_HEIGHT: usize = 320; -#[repr(C)] -pub enum Syscall { - DrawIter { - pixels: *const Pixel, - len: usize, - }, + pub type Pixel565 = Pixel; + + pub struct Display; + + impl Display { + fn syscall_draw(&self, pixels: &[Pixel565]) { + let syscall = Syscall::DrawIter { + pixels: pixels.as_ptr(), + len: pixels.len(), + }; + unsafe { + call_abi(&syscall); + } + } + } + + impl Dimensions for Display { + fn bounding_box(&self) -> Rectangle { + Rectangle { + top_left: Point { x: 0, y: 0 }, + size: Size { + width: SCREEN_WIDTH as u32, + height: SCREEN_HEIGHT as u32, + }, + } + } + } + + impl DrawTarget for Display { + type Color = Rgb565; + type Error = (); + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + const BUF_SIZE: usize = 1024; // tune this for performance + let mut buf: [Pixel565; BUF_SIZE] = [Pixel(Point::new(0, 0), Rgb565::BLACK); BUF_SIZE]; + + let mut count = 0; + for p in pixels { + buf[count] = p; + count += 1; + + if count == BUF_SIZE { + self.syscall_draw(&buf[..count]); + count = 0; + } + } + + if count > 0 { + self.syscall_draw(&buf[..count]); + } + + Ok(()) + } + } } diff --git a/abi_sys/Cargo.toml b/abi_sys/Cargo.toml new file mode 100644 index 0000000..e460dea --- /dev/null +++ b/abi_sys/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "abi_sys" +version = "0.1.0" +edition = "2024" + +[dependencies] +embedded-graphics = "0.8.1" +shared = { path = "../shared" } diff --git a/abi_sys/src/lib.rs b/abi_sys/src/lib.rs new file mode 100644 index 0000000..2ed0f97 --- /dev/null +++ b/abi_sys/src/lib.rs @@ -0,0 +1,28 @@ +#![no_std] + +pub use embedded_graphics::{ + Pixel, + geometry::Point, + pixelcolor::{Rgb565, RgbColor}, +}; +use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers}; + +// Instead of extern, declare a static pointer in a dedicated section +#[unsafe(no_mangle)] +#[unsafe(link_section = ".user_reloc")] +#[allow(non_upper_case_globals)] +pub static mut call_abi_ptr: usize = 0; + +// Helper to call it +pub unsafe fn call_abi(call: *const Syscall) { + let f: extern "C" fn(*const Syscall) = unsafe { core::mem::transmute(call_abi_ptr) }; + f(call); +} + +#[repr(C)] +pub enum Syscall { + DrawIter { + pixels: *const Pixel, + len: usize, + }, +} diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 2891c66..417f175 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -87,4 +87,4 @@ talc = "4.4.3" spin = "0.10.0" shared = { path = "../shared" } -abi = { path = "../abi" } +abi_sys = { path = "../abi_sys" } diff --git a/kernel/src/abi.rs b/kernel/src/abi.rs index dcc1bed..34c2fb5 100644 --- a/kernel/src/abi.rs +++ b/kernel/src/abi.rs @@ -1,4 +1,4 @@ -use abi::Syscall; +use abi_sys::Syscall; use defmt::info; use embassy_futures::block_on; use embedded_graphics::{ diff --git a/user-apps/calculator/Cargo.toml b/user-apps/calculator/Cargo.toml index 8b3311f..bcb1288 100644 --- a/user-apps/calculator/Cargo.toml +++ b/user-apps/calculator/Cargo.toml @@ -5,3 +5,4 @@ edition = "2024" [dependencies] abi = { path = "../../abi" } +embedded-graphics = "0.8.1" diff --git a/user-apps/calculator/src/main.rs b/user-apps/calculator/src/main.rs index 3a174be..aa5efc7 100644 --- a/user-apps/calculator/src/main.rs +++ b/user-apps/calculator/src/main.rs @@ -1,8 +1,16 @@ #![no_std] #![no_main] -use abi::{Pixel, Point, Rgb565, RgbColor, Syscall, call_abi}; +use abi::display::Display; use core::panic::PanicInfo; +use embedded_graphics::{ + Drawable, + geometry::{Dimensions, Point}, + mono_font::{MonoTextStyle, ascii::FONT_6X10}, + pixelcolor::Rgb565, + prelude::RgbColor, + text::{Alignment, Text}, +}; #[panic_handler] fn panic(_info: &PanicInfo) -> ! { @@ -11,23 +19,18 @@ fn panic(_info: &PanicInfo) -> ! { #[unsafe(no_mangle)] pub extern "C" fn _start() { - // Local pixel buffer - let mut pixels = [Pixel(Point { x: 50, y: 50 }, Rgb565::RED); 300]; - for (i, p) in pixels.iter_mut().enumerate() { - *p = Pixel( - Point { - x: i as i32, - y: i as i32, - }, - Rgb565::RED, - ) - } + let mut display = Display; - // Construct syscall with raw pointer + length - let call = Syscall::DrawIter { - pixels: pixels.as_ptr(), // raw pointer - len: pixels.len(), // number of elements - }; + let character_style = MonoTextStyle::new(&FONT_6X10, Rgb565::RED); - unsafe { call_abi(&call) }; + // Draw centered text. + let text = "embedded-graphics"; + Text::with_alignment( + text, + display.bounding_box().center() + Point::new(0, 15), + character_style, + Alignment::Center, + ) + .draw(&mut display) + .unwrap(); }