Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions luma_core/src/allocate.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
use alloc::alloc::{alloc, Layout};
use alloc::boxed::Box;
use core::pin::Pin;
use core::slice;

const CACHELINE: usize = 32;

/// Allocate a slice aligned to a cacheline, and return it pinned.
pub fn alloc_aligned(size: usize) -> Pin<Box<[u8]>> {
let layout = Layout::from_size_align(size, CACHELINE).unwrap();
let ptr = unsafe { alloc(layout) };
let boxed = unsafe { Box::from_raw(ptr) };
let slice = Box::into_boxed_slice(boxed);
Pin::from(slice)
pub fn alloc_aligned<T: Copy>(size: usize) -> Pin<Box<[T]>> {
let layout = Layout::array::<T>(size)
.unwrap()
.align_to(CACHELINE)
.unwrap();
let ptr = unsafe { alloc(layout) } as *mut T;
let slice = unsafe { slice::from_raw_parts(ptr, size) };
let boxed = Box::from(slice);
Pin::from(boxed)
}

/// Allocate an array aligned to a cacheline, and return it pinned.
Expand Down
34 changes: 13 additions & 21 deletions luma_core/src/ipc.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
use core::ptr::from_exposed_addr_mut;
use core::ptr;

//bits 0..=31 = physical address of ipc request
const HW_IPC_PPCMSG: usize = 0xCD00_0000usize; //from_exposed_addr_mut(0xCD00_0000);
const HW_IPC_PPCMSG: *mut u32 = ptr::without_provenance_mut(0xCD00_0000);

//bit 0 = X1 | Execute IPC request
//bit 1 = Y2 | Acknowledge IPC request
//bit 2 = Y1 | IPC request reply available
//bit 3 = X2 | Relaunch IPC
//bit 4 = IY1 | IPC request reply send out IPC interrupt
//bit 5 = IY2 | IPC request acknowledge sends out IPC interrupt
const HW_IPC_PPCCTRL: usize = 0xCD00_0004usize; //from_exposed_addr_mut(0xCD00_0004);
const HW_IPC_PPCCTRL: *mut u32 = ptr::without_provenance_mut(0xCD00_0004);

//bits 0..=31 = physical address of ipc request
const HW_IPC_ARMMSG: usize = 0xCD00_0008usize; //from_exposed_addr_mut(0xCD00_0008);
const HW_IPC_ARMMSG: *mut u32 = ptr::without_provenance_mut(0xCD00_0008);

//bit 0 = Y1 | IPC request reply available
//bit 1 = X2 | Relauch IPC
//bit 2 = X1 | Execute IPC request
//bit 3 = Y2 | Acknowledge IPC request
//bit 4 = IX1 | Execute ipc request send IPC interrupt
//bit 5 = IX2 | Relaunch IPC sends IPC interrupt
const HW_IPC_ARMCTRL: usize = 0xCD00_000Cusize; //from_exposed_addr_mut(0xCD00_000C);
const HW_IPC_ARMCTRL: *mut u32 = ptr::without_provenance_mut(0xCD00_000C);

/// IPC Message Address (for BOTH ARM AND PPC)
#[repr(transparent)]
Expand All @@ -32,23 +32,19 @@ impl IpcMessageAddress {
}

pub fn read_ppc() -> Self {
let hw_ipc_ppcmsg = from_exposed_addr_mut::<u32>(HW_IPC_PPCMSG);
Self(unsafe { hw_ipc_ppcmsg.read_volatile() })
Self(unsafe { HW_IPC_PPCMSG.read_volatile() })
}

pub fn write_ppc(self) {
let hw_ipc_ppcmsg = from_exposed_addr_mut::<u32>(HW_IPC_PPCMSG);
unsafe { hw_ipc_ppcmsg.write_volatile(self.0) }
unsafe { HW_IPC_PPCMSG.write_volatile(self.0) }
}

pub fn read_arm() -> Self {
let hw_ipc_armmsg = from_exposed_addr_mut::<u32>(HW_IPC_ARMMSG);
Self(unsafe { hw_ipc_armmsg.read_volatile() })
Self(unsafe { HW_IPC_ARMMSG.read_volatile() })
}

pub fn write_arm(self) {
let hw_ipc_armmsg = from_exposed_addr_mut::<u32>(HW_IPC_ARMMSG);
unsafe { hw_ipc_armmsg.write_volatile(self.0) }
unsafe { HW_IPC_ARMMSG.write_volatile(self.0) }
}

pub fn address(&self) -> u32 {
Expand Down Expand Up @@ -79,13 +75,11 @@ impl PpcIpcControl {
}

pub fn read() -> Self {
let hw_ipc_ppcctrl = from_exposed_addr_mut::<u32>(HW_IPC_PPCCTRL);
Self(unsafe { hw_ipc_ppcctrl.read_volatile() })
Self(unsafe { HW_IPC_PPCCTRL.read_volatile() })
}

pub fn write(self) {
let hw_ipc_ppcctrl = from_exposed_addr_mut::<u32>(HW_IPC_PPCCTRL);
unsafe { hw_ipc_ppcctrl.write_volatile(self.0) }
unsafe { HW_IPC_PPCCTRL.write_volatile(self.0) }
}

pub fn execute(&self) -> bool {
Expand Down Expand Up @@ -153,13 +147,11 @@ impl ArmIpcControl {
}

pub fn read() -> Self {
let hw_ipc_armctrl = from_exposed_addr_mut::<u32>(HW_IPC_ARMCTRL);
Self(unsafe { hw_ipc_armctrl.read_volatile() })
Self(unsafe { HW_IPC_ARMCTRL.read_volatile() })
}

pub fn write(self) {
let hw_ipc_armctrl = from_exposed_addr_mut::<u32>(HW_IPC_ARMCTRL);
unsafe { hw_ipc_armctrl.write_volatile(self.0) }
unsafe { HW_IPC_ARMCTRL.write_volatile(self.0) }
}

pub fn execute(&self) -> bool {
Expand Down
8 changes: 1 addition & 7 deletions luma_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@
//! **NOTE**: This is currently in a very experimental state and is subject to change.
#![no_std]
#![allow(unused_attributes)]
#![feature(
asm_experimental_arch,
box_into_boxed_slice,
allocator_api,
exposed_provenance,
strict_provenance
)]
#![feature(asm_experimental_arch, box_into_boxed_slice, allocator_api)]

extern crate alloc;

Expand Down
36 changes: 27 additions & 9 deletions luma_core/src/vi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@ use crate::allocate::alloc_aligned;
use crate::io::{read16, write16, write32};
use alloc::boxed::Box;
use core::pin::Pin;
use core::slice::{Chunks, ChunksMut};

/// A struct representing the eXternal FrameBuffer, or XFB. It represents the image that will be
/// sent to the screen, in YUYV format. It must be allocated as contiguous physical memory.
pub struct Xfb {
data: Pin<Box<[u8]>>,
data: Pin<Box<[u16]>>,
width: usize,
height: usize,
}

impl Xfb {
/// Allocate an XFB with the given width and height.
pub fn allocate(width: usize, height: usize) -> Xfb {
let stride = width * 2;
let stride = width;
let data = alloc_aligned(stride * height);
Xfb {
data,
Expand All @@ -37,19 +38,36 @@ impl Xfb {
self.height
}

/// Get the stride of this XFB, given the YUYV format this is always width × 2.
pub fn stride(&self) -> usize {
// YUYV always takes two bytes per pixel.
self.width * 2
/// Get the stride of this XFB. This is always equal to width for now.
pub fn stride_in_u16(&self) -> usize {
self.width
}

/// Get the stride of this XFB in bytes. Given the YUYV format this is always equal to
/// stride_in_u16() × 2.
pub fn stride_in_u8(&self) -> usize {
self.stride_in_u16() * 2
}

/// Get an immutable iterator over the rows of this XFB.
pub fn iter(&self) -> Chunks<u16> {
let stride = self.stride_in_u16();
self.data.chunks(stride)
}

/// Get a mutable iterator over the rows of this XFB.
pub fn iter_mut(&mut self) -> ChunksMut<u16> {
let stride = self.stride_in_u16();
self.data.chunks_mut(stride)
}

/// Return the raw pointer to this XFB.
pub fn as_ptr(&self) -> *const u8 {
pub fn as_ptr(&self) -> *const u16 {
self.data.as_ptr()
}

/// Return the raw mutable pointer to this XFB.
pub fn as_mut_ptr(&mut self) -> *mut u8 {
pub fn as_mut_ptr(&mut self) -> *mut u16 {
self.data.as_mut_ptr()
}
}
Expand Down Expand Up @@ -119,7 +137,7 @@ unsafe fn set_burst_blanking_interval_2(be2: u32, bs2: u32, be4: u32, bs4: u32)
}

unsafe fn set_xfb(addr: u32, xfb: &Xfb, bottom: bool) {
let stride = xfb.stride() as u32;
let stride = xfb.stride_in_u8() as u32;
let xfb = xfb.as_ptr();
let mut xfb = xfb as u32;
let shift;
Expand Down
36 changes: 17 additions & 19 deletions src/bin/vi-draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ const fn rgba2yuyv(pixel: i32, odd: bool) -> u16 {
}

/// Ported from Weston’s clients/simple-shm.c
fn paint_pixels(mut image: *mut u16, padding: i32, width: i32, height: i32, time: i32) {
fn paint_pixels(xfb: &mut Xfb, padding: i32, time: i32) {
let width = xfb.width() as i32;
let height = xfb.height() as i32;
let mut rows = xfb.iter_mut().skip(padding as usize);

let halfh = padding + (height - padding * 2) / 2;
let halfw = padding + (width - padding * 2) / 2;

Expand All @@ -50,30 +54,24 @@ fn paint_pixels(mut image: *mut u16, padding: i32, width: i32, height: i32, time
or *= or;
ir *= ir;

image = unsafe { image.offset((padding * width) as isize) };
for y in padding..(height - padding) {
let y2 = (y - halfh) * (y - halfh);
let row = rows.next().unwrap();

image = unsafe { image.offset(padding as isize) };
let y2 = (y - halfh) * (y - halfh);
for x in padding..(width - padding) {
let v;

/* squared distance from center */
let r2 = (x - halfw) * (x - halfw) + y2;

if r2 < ir {
v = (r2 / 32 + time / 4) * 0x0080401;
let v = if r2 < ir {
(r2 / 32 + time / 4) * 0x0080401
} else if r2 < or {
v = (y + time / 2) * 0x0080401;
(y + time / 2) * 0x0080401
} else {
v = (x + time) * 0x0080401;
}
(x + time) * 0x0080401
};

unsafe { *image = rgba2yuyv(v, (x & 1) != 0) };
image = unsafe { image.offset(1) };
row[x as usize] = rgba2yuyv(v, (x & 1) != 0);
}

image = unsafe { image.offset(padding as isize) };
}
}

Expand All @@ -83,15 +81,15 @@ fn main() {
let mut vi = Vi::setup(xfb);

// First fill the XFB with white.
let xfb = vi.xfb().as_mut_ptr() as *mut u16;
for i in 0..(640 * 480) {
unsafe { xfb.offset(i).write(0xff80) };
let xfb = vi.xfb();
for row in xfb.iter_mut() {
row.fill(0xff80);
}

// Then draw to it as fast as we can.
let mut i = 0;
loop {
paint_pixels(xfb, 20, 640, 480, i);
paint_pixels(xfb, 20, i);
i += 1;
}
}