mirror of
https://github.com/LegitCamper/picocalc-os-rs.git
synced 2025-12-27 07:45:28 +00:00
alloc user to access kernel backed heap (psram, if equiped)
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -20,8 +20,6 @@ dependencies = [
|
|||||||
"embedded-graphics",
|
"embedded-graphics",
|
||||||
"embedded-sdmmc",
|
"embedded-sdmmc",
|
||||||
"rand_core 0.9.3",
|
"rand_core 0.9.3",
|
||||||
"spin 0.10.0",
|
|
||||||
"talc",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1039,6 +1037,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-snake"
|
name = "embedded-snake"
|
||||||
version = "0.0.3"
|
version = "0.0.3"
|
||||||
|
source = "git+https://github.com/LegitCamper/embedded-snake-rs#3986819c55819283dc5c1e89717d2a2f52e9b161"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embedded-graphics",
|
"embedded-graphics",
|
||||||
"rand_core 0.9.3",
|
"rand_core 0.9.3",
|
||||||
|
|||||||
@@ -7,6 +7,4 @@ edition = "2024"
|
|||||||
embedded-sdmmc = { version = "0.9.0", default-features = false }
|
embedded-sdmmc = { version = "0.9.0", default-features = false }
|
||||||
embedded-graphics = "0.8.1"
|
embedded-graphics = "0.8.1"
|
||||||
abi_sys = { path = "../abi_sys" }
|
abi_sys = { path = "../abi_sys" }
|
||||||
talc = "4.4.3"
|
|
||||||
spin = "0.10.0"
|
|
||||||
rand_core = "0.9.3"
|
rand_core = "0.9.3"
|
||||||
|
|||||||
@@ -1,18 +1,26 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub use abi_sys::keyboard;
|
|
||||||
use abi_sys::{RngRequest, keyboard::KeyEvent};
|
|
||||||
use rand_core::RngCore;
|
|
||||||
use talc::*;
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
static mut ARENA: [u8; 10000] = [0; 10000];
|
pub use abi_sys::keyboard;
|
||||||
|
use abi_sys::{RngRequest, alloc, dealloc, keyboard::KeyEvent};
|
||||||
|
use core::alloc::{GlobalAlloc, Layout};
|
||||||
|
use rand_core::RngCore;
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static ALLOCATOR: Talck<spin::Mutex<()>, ClaimOnOom> =
|
static ALLOC: Alloc = Alloc;
|
||||||
Talc::new(unsafe { ClaimOnOom::new(Span::from_array(core::ptr::addr_of!(ARENA).cast_mut())) })
|
|
||||||
.lock();
|
struct Alloc;
|
||||||
|
|
||||||
|
unsafe impl GlobalAlloc for Alloc {
|
||||||
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
|
alloc(layout.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
|
dealloc(ptr, layout.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print(msg: &str) {
|
pub fn print(msg: &str) {
|
||||||
abi_sys::print(msg.as_ptr(), msg.len());
|
abi_sys::print(msg.as_ptr(), msg.len());
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["alloc"]
|
||||||
|
alloc = []
|
||||||
defmt = ["dep:defmt"]
|
defmt = ["dep:defmt"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -1,42 +1,89 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
use core::alloc::Layout;
|
||||||
|
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
Pixel,
|
Pixel,
|
||||||
pixelcolor::{Rgb565, raw::RawU16},
|
pixelcolor::{Rgb565, raw::RawU16},
|
||||||
prelude::{IntoStorage, Point},
|
prelude::{IntoStorage, Point},
|
||||||
};
|
};
|
||||||
use embedded_sdmmc::DirEntry;
|
use embedded_sdmmc::DirEntry;
|
||||||
use strum::EnumIter;
|
use strum::{EnumCount, EnumIter};
|
||||||
|
|
||||||
pub const ABI_CALL_TABLE_COUNT: usize = 10;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, EnumIter)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum CallAbiTable {
|
|
||||||
PrintString = 0,
|
|
||||||
SleepMs = 1,
|
|
||||||
GetMs = 2,
|
|
||||||
LockDisplay = 3,
|
|
||||||
DrawIter = 4,
|
|
||||||
GetKey = 5,
|
|
||||||
GenRand = 6,
|
|
||||||
ListDir = 7,
|
|
||||||
ReadFile = 8,
|
|
||||||
FileLen = 9,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type EntryFn = fn();
|
pub type EntryFn = fn();
|
||||||
|
|
||||||
|
pub const ABI_CALL_TABLE_COUNT: usize = 12;
|
||||||
|
const _: () = assert!(ABI_CALL_TABLE_COUNT == CallTable::COUNT);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, EnumIter, EnumCount)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum CallTable {
|
||||||
|
Alloc = 0,
|
||||||
|
Dealloc = 1,
|
||||||
|
PrintString = 2,
|
||||||
|
SleepMs = 3,
|
||||||
|
GetMs = 4,
|
||||||
|
LockDisplay = 5,
|
||||||
|
DrawIter = 6,
|
||||||
|
GetKey = 7,
|
||||||
|
GenRand = 8,
|
||||||
|
ListDir = 9,
|
||||||
|
ReadFile = 10,
|
||||||
|
FileLen = 11,
|
||||||
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
#[unsafe(link_section = ".syscall_table")]
|
#[unsafe(link_section = ".syscall_table")]
|
||||||
pub static mut CALL_ABI_TABLE: [usize; ABI_CALL_TABLE_COUNT] = [0; ABI_CALL_TABLE_COUNT];
|
pub static mut CALL_ABI_TABLE: [usize; ABI_CALL_TABLE_COUNT] = [0; ABI_CALL_TABLE_COUNT];
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CLayout {
|
||||||
|
size: usize,
|
||||||
|
alignment: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl Into<Layout> for CLayout {
|
||||||
|
fn into(self) -> Layout {
|
||||||
|
unsafe { Layout::from_size_align_unchecked(self.size, self.alignment) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl From<Layout> for CLayout {
|
||||||
|
fn from(value: Layout) -> Self {
|
||||||
|
Self {
|
||||||
|
size: value.size(),
|
||||||
|
alignment: value.align(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type AllocAbi = extern "C" fn(layout: CLayout) -> *mut u8;
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn alloc(layout: CLayout) -> *mut u8 {
|
||||||
|
let f: AllocAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::Alloc as usize]) };
|
||||||
|
f(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type DeallocAbi = extern "C" fn(ptr: *mut u8, layout: CLayout);
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn dealloc(ptr: *mut u8, layout: CLayout) {
|
||||||
|
let f: DeallocAbi =
|
||||||
|
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::Dealloc as usize]) };
|
||||||
|
f(ptr, layout)
|
||||||
|
}
|
||||||
|
|
||||||
pub type PrintAbi = extern "C" fn(ptr: *const u8, len: usize);
|
pub type PrintAbi = extern "C" fn(ptr: *const u8, len: usize);
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn print(ptr: *const u8, len: usize) {
|
pub extern "C" fn print(ptr: *const u8, len: usize) {
|
||||||
let f: PrintAbi =
|
let f: PrintAbi =
|
||||||
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::PrintString as usize]) };
|
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::PrintString as usize]) };
|
||||||
f(ptr, len);
|
f(ptr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +92,7 @@ pub type SleepMsAbi = extern "C" fn(ms: u64);
|
|||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn sleep(ms: u64) {
|
pub extern "C" fn sleep(ms: u64) {
|
||||||
let f: SleepMsAbi =
|
let f: SleepMsAbi =
|
||||||
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::SleepMs as usize]) };
|
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::SleepMs as usize]) };
|
||||||
f(ms);
|
f(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +100,7 @@ pub type GetMsAbi = extern "C" fn() -> u64;
|
|||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn get_ms() -> u64 {
|
pub extern "C" fn get_ms() -> u64 {
|
||||||
let f: GetMsAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::GetMs as usize]) };
|
let f: GetMsAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::GetMs as usize]) };
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +109,7 @@ pub type LockDisplay = extern "C" fn(lock: bool);
|
|||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn lock_display(lock: bool) {
|
pub extern "C" fn lock_display(lock: bool) {
|
||||||
let f: LockDisplay =
|
let f: LockDisplay =
|
||||||
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::LockDisplay as usize]) };
|
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::LockDisplay as usize]) };
|
||||||
f(lock);
|
f(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,12 +152,12 @@ pub type DrawIterAbi = extern "C" fn(ptr: *const CPixel, len: usize);
|
|||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn draw_iter(ptr: *const CPixel, len: usize) {
|
pub extern "C" fn draw_iter(ptr: *const CPixel, len: usize) {
|
||||||
let f: DrawIterAbi =
|
let f: DrawIterAbi =
|
||||||
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::DrawIter as usize]) };
|
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::DrawIter as usize]) };
|
||||||
f(ptr, len);
|
f(ptr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod keyboard {
|
pub mod keyboard {
|
||||||
use crate::{CALL_ABI_TABLE, CallAbiTable};
|
use crate::{CALL_ABI_TABLE, CallTable};
|
||||||
|
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
@@ -333,7 +380,7 @@ pub mod keyboard {
|
|||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn get_key() -> KeyEventC {
|
pub extern "C" fn get_key() -> KeyEventC {
|
||||||
let f: GetKeyAbi =
|
let f: GetKeyAbi =
|
||||||
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::GetKey as usize]) };
|
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::GetKey as usize]) };
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,7 +397,7 @@ pub type GenRand = extern "C" fn(req: &mut RngRequest);
|
|||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn gen_rand(req: &mut RngRequest) {
|
pub extern "C" fn gen_rand(req: &mut RngRequest) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = CALL_ABI_TABLE[CallAbiTable::GenRand as usize];
|
let ptr = CALL_ABI_TABLE[CallTable::GenRand as usize];
|
||||||
let f: GenRand = core::mem::transmute(ptr);
|
let f: GenRand = core::mem::transmute(ptr);
|
||||||
f(req)
|
f(req)
|
||||||
}
|
}
|
||||||
@@ -371,7 +418,7 @@ pub extern "C" fn list_dir(
|
|||||||
file_len: usize,
|
file_len: usize,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = CALL_ABI_TABLE[CallAbiTable::ListDir as usize];
|
let ptr = CALL_ABI_TABLE[CallTable::ListDir as usize];
|
||||||
let f: ListDir = core::mem::transmute(ptr);
|
let f: ListDir = core::mem::transmute(ptr);
|
||||||
f(str, len, files, file_len)
|
f(str, len, files, file_len)
|
||||||
}
|
}
|
||||||
@@ -394,7 +441,7 @@ pub extern "C" fn read_file(
|
|||||||
buf_len: usize,
|
buf_len: usize,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = CALL_ABI_TABLE[CallAbiTable::ReadFile as usize];
|
let ptr = CALL_ABI_TABLE[CallTable::ReadFile as usize];
|
||||||
let f: ReadFile = core::mem::transmute(ptr);
|
let f: ReadFile = core::mem::transmute(ptr);
|
||||||
f(str, len, read_from, buf, buf_len)
|
f(str, len, read_from, buf, buf_len)
|
||||||
}
|
}
|
||||||
@@ -405,7 +452,7 @@ pub type FileLen = extern "C" fn(str: *const u8, len: usize) -> usize;
|
|||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn file_len(str: *const u8, len: usize) -> usize {
|
pub extern "C" fn file_len(str: *const u8, len: usize) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = CALL_ABI_TABLE[CallAbiTable::FileLen as usize];
|
let ptr = CALL_ABI_TABLE[CallTable::FileLen as usize];
|
||||||
let f: FileLen = core::mem::transmute(ptr);
|
let f: FileLen = core::mem::transmute(ptr);
|
||||||
f(str, len)
|
f(str, len)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use abi_sys::{
|
use abi_sys::{
|
||||||
CPixel, DrawIterAbi, FileLen, GenRand, GetMsAbi, ListDir, LockDisplay, PrintAbi, ReadFile,
|
AllocAbi, CLayout, CPixel, DeallocAbi, DrawIterAbi, FileLen, GenRand, GetMsAbi, ListDir,
|
||||||
RngRequest, SleepMsAbi, keyboard::*,
|
LockDisplay, PrintAbi, ReadFile, RngRequest, SleepMsAbi, keyboard::*,
|
||||||
};
|
};
|
||||||
use alloc::{string::ToString, vec::Vec};
|
use alloc::{string::ToString, vec::Vec};
|
||||||
use core::sync::atomic::Ordering;
|
use core::sync::atomic::Ordering;
|
||||||
@@ -15,6 +15,18 @@ use crate::{
|
|||||||
storage::{Dir, File, SDCARD},
|
storage::{Dir, File, SDCARD},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const _: AllocAbi = alloc;
|
||||||
|
pub extern "C" fn alloc(layout: CLayout) -> *mut u8 {
|
||||||
|
// SAFETY: caller guarantees layout is valid
|
||||||
|
unsafe { alloc::alloc::alloc(layout.into()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
const _: DeallocAbi = dealloc;
|
||||||
|
pub extern "C" fn dealloc(ptr: *mut u8, layout: CLayout) {
|
||||||
|
// SAFETY: caller guarantees ptr and layout are valid
|
||||||
|
unsafe { alloc::alloc::dealloc(ptr, layout.into()) };
|
||||||
|
}
|
||||||
|
|
||||||
const _: PrintAbi = print;
|
const _: PrintAbi = print;
|
||||||
pub extern "C" fn print(ptr: *const u8, len: usize) {
|
pub extern "C" fn print(ptr: *const u8, len: usize) {
|
||||||
// SAFETY: caller guarantees `ptr` is valid for `len` bytes
|
// SAFETY: caller guarantees `ptr` is valid for `len` bytes
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type DISPLAY = ST7365P<
|
|||||||
pub const SCREEN_WIDTH: usize = 320;
|
pub const SCREEN_WIDTH: usize = 320;
|
||||||
pub const SCREEN_HEIGHT: usize = 320;
|
pub const SCREEN_HEIGHT: usize = 320;
|
||||||
|
|
||||||
pub static mut FRAMEBUFFER: AtomicFrameBuffer = AtomicFrameBuffer::new();
|
pub static mut FRAMEBUFFER: AtomicFrameBuffer = AtomicFrameBuffer;
|
||||||
pub static FB_PAUSED: AtomicBool = AtomicBool::new(false);
|
pub static FB_PAUSED: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
pub async fn init_display(
|
pub async fn init_display(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use crate::{
|
|||||||
abi,
|
abi,
|
||||||
storage::{File, SDCARD},
|
storage::{File, SDCARD},
|
||||||
};
|
};
|
||||||
use abi_sys::CallAbiTable;
|
use abi_sys::CallTable;
|
||||||
use abi_sys::EntryFn;
|
use abi_sys::EntryFn;
|
||||||
use alloc::{vec, vec::Vec};
|
use alloc::{vec, vec::Vec};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
@@ -194,18 +194,20 @@ fn patch_abi(
|
|||||||
unsafe { base.add((sym.st_value as usize) - min_vaddr as usize) }
|
unsafe { base.add((sym.st_value as usize) - min_vaddr as usize) }
|
||||||
as *mut usize;
|
as *mut usize;
|
||||||
|
|
||||||
for (idx, call) in CallAbiTable::iter().enumerate() {
|
for (idx, call) in CallTable::iter().enumerate() {
|
||||||
let ptr = match call {
|
let ptr = match call {
|
||||||
CallAbiTable::PrintString => abi::print as usize,
|
CallTable::Alloc => abi::alloc as usize,
|
||||||
CallAbiTable::SleepMs => abi::sleep as usize,
|
CallTable::Dealloc => abi::dealloc as usize,
|
||||||
CallAbiTable::GetMs => abi::get_ms as usize,
|
CallTable::PrintString => abi::print as usize,
|
||||||
CallAbiTable::LockDisplay => abi::lock_display as usize,
|
CallTable::SleepMs => abi::sleep as usize,
|
||||||
CallAbiTable::DrawIter => abi::draw_iter as usize,
|
CallTable::GetMs => abi::get_ms as usize,
|
||||||
CallAbiTable::GetKey => abi::get_key as usize,
|
CallTable::LockDisplay => abi::lock_display as usize,
|
||||||
CallAbiTable::GenRand => abi::gen_rand as usize,
|
CallTable::DrawIter => abi::draw_iter as usize,
|
||||||
CallAbiTable::ListDir => abi::list_dir as usize,
|
CallTable::GetKey => abi::get_key as usize,
|
||||||
CallAbiTable::ReadFile => abi::read_file as usize,
|
CallTable::GenRand => abi::gen_rand as usize,
|
||||||
CallAbiTable::FileLen => abi::file_len as usize,
|
CallTable::ListDir => abi::list_dir as usize,
|
||||||
|
CallTable::ReadFile => abi::read_file as usize,
|
||||||
|
CallTable::FileLen => abi::file_len as usize,
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
table_base.add(idx as usize).write(ptr);
|
table_base.add(idx as usize).write(ptr);
|
||||||
|
|||||||
@@ -241,19 +241,21 @@ async fn setup_display(display: Display, spawner: Spawner) {
|
|||||||
spawner.spawn(display_handler(display)).unwrap();
|
spawner.spawn(display_handler(display)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// psram is kind of useless on the pico calc
|
||||||
|
// ive opted to use the pimoroni with on onboard xip psram instead
|
||||||
async fn setup_psram(psram: Psram) {
|
async fn setup_psram(psram: Psram) {
|
||||||
let psram = init_psram(
|
// let psram = init_psram(
|
||||||
psram.pio, psram.sclk, psram.mosi, psram.miso, psram.cs, psram.dma1, psram.dma2,
|
// psram.pio, psram.sclk, psram.mosi, psram.miso, psram.cs, psram.dma1, psram.dma2,
|
||||||
)
|
// )
|
||||||
.await;
|
// .await;
|
||||||
|
|
||||||
#[cfg(feature = "defmt")]
|
// #[cfg(feature = "defmt")]
|
||||||
defmt::info!("psram size: {}", psram.size);
|
// defmt::info!("psram size: {}", psram.size);
|
||||||
|
|
||||||
if psram.size == 0 {
|
// if psram.size == 0 {
|
||||||
#[cfg(feature = "defmt")]
|
// #[cfg(feature = "defmt")]
|
||||||
defmt::info!("\u{1b}[1mExternal PSRAM was NOT found!\u{1b}[0m");
|
// defmt::info!("\u{1b}[1mExternal PSRAM was NOT found!\u{1b}[0m");
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[cfg(feature = "pimoroni2w")]
|
#[cfg(feature = "pimoroni2w")]
|
||||||
{
|
{
|
||||||
@@ -291,6 +293,7 @@ async fn kernel_task(
|
|||||||
setup_mcu(mcu).await;
|
setup_mcu(mcu).await;
|
||||||
Timer::after_millis(250).await;
|
Timer::after_millis(250).await;
|
||||||
setup_display(display, spawner).await;
|
setup_display(display, spawner).await;
|
||||||
|
#[cfg(feature = "pimoroni2w")]
|
||||||
setup_psram(psram).await;
|
setup_psram(psram).await;
|
||||||
setup_sd(sd).await;
|
setup_sd(sd).await;
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,15 @@
|
|||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use abi::{
|
use abi::{
|
||||||
display::{Display, lock_display},
|
display::{Display, lock_display},
|
||||||
fs::read_file,
|
fs::{file_len, read_file},
|
||||||
get_key, get_ms,
|
get_key, get_ms,
|
||||||
keyboard::{KeyCode, KeyState},
|
keyboard::{KeyCode, KeyState},
|
||||||
print, sleep,
|
print, sleep,
|
||||||
};
|
};
|
||||||
use alloc::format;
|
use alloc::{format, vec::Vec};
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use embedded_graphics::{image::ImageDrawable, pixelcolor::Rgb565};
|
use embedded_graphics::{image::ImageDrawable, pixelcolor::Rgb565};
|
||||||
use tinygif::{Gif, Header};
|
use tinygif::Gif;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
fn panic(info: &PanicInfo) -> ! {
|
||||||
@@ -33,19 +33,20 @@ pub fn main() {
|
|||||||
print("Starting Gif app");
|
print("Starting Gif app");
|
||||||
let mut display = Display;
|
let mut display = Display;
|
||||||
|
|
||||||
static mut BUF: [u8; 256] = [0_u8; 256];
|
let size = file_len("/gifs/bad_apple.gif");
|
||||||
|
let mut buf = Vec::with_capacity(size);
|
||||||
|
let read = read_file("/gifs/bad_apple.gif", 0, &mut buf);
|
||||||
|
assert!(read == size);
|
||||||
|
|
||||||
read_file("/gif/bad_apple.gif", 0, unsafe { &mut BUF[0..6] });
|
let gif = Gif::<Rgb565>::from_slice(&buf).unwrap();
|
||||||
|
|
||||||
let gif_header = Header::parse(unsafe { &BUF[0..6] });
|
|
||||||
|
|
||||||
let image = Gif::<Rgb565>::from_slice().unwrap();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
for frame in image.frames() {
|
for frame in gif.frames() {
|
||||||
let start = get_ms();
|
let start = get_ms();
|
||||||
|
|
||||||
|
lock_display(true);
|
||||||
frame.draw(&mut display).unwrap();
|
frame.draw(&mut display).unwrap();
|
||||||
|
lock_display(false);
|
||||||
|
|
||||||
sleep(((frame.delay_centis as u64) * 10).saturating_sub(start));
|
sleep(((frame.delay_centis as u64) * 10).saturating_sub(start));
|
||||||
|
|
||||||
@@ -56,9 +57,6 @@ pub fn main() {
|
|||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
lock_display(true);
|
|
||||||
lock_display(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
abi = { path = "../../abi" }
|
abi = { path = "../../abi" }
|
||||||
embedded-graphics = "0.8.1"
|
embedded-graphics = "0.8.1"
|
||||||
embedded-snake = { path = "../../../embedded-snake-rs" }
|
embedded-snake = { git = "https://github.com/LegitCamper/embedded-snake-rs" }
|
||||||
rand = { version = "0.9.0", default-features = false }
|
rand = { version = "0.9.0", default-features = false }
|
||||||
|
|||||||
Reference in New Issue
Block a user