mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
examples: fix betrusted LCD under Renode
This gets the Betrusted LCD demo working within emulation, which means it ought to work on real hardware. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
8920ab57cf
commit
1da460cd41
2 changed files with 62 additions and 30 deletions
|
|
@ -21,8 +21,8 @@ csr_base,spinor,0xf0008000,,
|
|||
csr_base,audio,0xf000a800,,
|
||||
csr_base,ctrl,0xf0000000,,
|
||||
csr_base,uart,0xf0001800,,
|
||||
csr_base,memlcd,0xf0004800,,
|
||||
csr_base,com,0xf0005000,,
|
||||
csr_base,memlcd,0xf0005000,,
|
||||
csr_base,com,0xf000c000,,
|
||||
csr_register,i2c_prescale,0xf0005800,1,rw
|
||||
csr_register,messible_in,0xf0006800,1,rw
|
||||
csr_register,i2c_command,0xf0005810,1,rw
|
||||
|
|
|
|||
|
|
|
@ -1,4 +1,5 @@
|
|||
use embedded_graphics::{drawable::Pixel, geometry::Size, pixelcolor::BinaryColor, DrawTarget};
|
||||
use xous::MemoryRange;
|
||||
|
||||
const FB_WIDTH_WORDS: usize = 11;
|
||||
const FB_WIDTH_PIXELS: usize = 336;
|
||||
|
|
@ -6,26 +7,37 @@ const FB_LINES: usize = 536;
|
|||
const FB_SIZE: usize = FB_WIDTH_WORDS * FB_LINES; // 44 bytes by 536 lines
|
||||
const CONFIG_CLOCK_FREQUENCY: u32 = 100_000_000;
|
||||
|
||||
// const MAX_FPS: u64 = 15;
|
||||
|
||||
const COMMAND_OFFSET: usize = 0;
|
||||
const BUSY_OFFSET: usize = 1;
|
||||
const PRESCALER_OFFSET: usize = 2;
|
||||
|
||||
pub struct XousDisplay {
|
||||
fb: &'static mut [u32; FB_WIDTH_PIXELS * FB_LINES],
|
||||
control: *mut u32,
|
||||
fb: MemoryRange,
|
||||
control: MemoryRange,
|
||||
}
|
||||
|
||||
impl XousDisplay {
|
||||
pub fn new() -> XousDisplay {
|
||||
let fb = unsafe { &mut *(0xb000_0000 as *mut [u32; FB_WIDTH_PIXELS * FB_LINES]) };
|
||||
let mut display = XousDisplay {
|
||||
fb,
|
||||
control: 0xf000_a000u32 as _,
|
||||
};
|
||||
let fb = xous::syscall::map_memory(
|
||||
xous::MemoryAddress::new(0xb000_0000),
|
||||
None,
|
||||
((FB_WIDTH_WORDS * FB_LINES * 4) + 4096) & !4095,
|
||||
xous::MemoryFlags::R | xous::MemoryFlags::W,
|
||||
)
|
||||
.expect("couldn't map control port");
|
||||
|
||||
let control = xous::syscall::map_memory(
|
||||
xous::MemoryAddress::new(0xf000_5000),
|
||||
None,
|
||||
4096,
|
||||
xous::MemoryFlags::R | xous::MemoryFlags::W,
|
||||
)
|
||||
.expect("couldn't map control port");
|
||||
let mut display = XousDisplay { fb, control };
|
||||
|
||||
display.set_clock(CONFIG_CLOCK_FREQUENCY);
|
||||
display.sync_clear();
|
||||
|
||||
display
|
||||
}
|
||||
|
||||
|
|
@ -41,28 +53,37 @@ impl XousDisplay {
|
|||
///
|
||||
fn set_clock(&mut self, clk_mhz: u32) {
|
||||
unsafe {
|
||||
self.control
|
||||
(self.control.as_ptr() as *mut u32)
|
||||
.add(PRESCALER_OFFSET)
|
||||
.write_volatile((clk_mhz / 2_000_000) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_all(&mut self) {
|
||||
unsafe { self.control.add(COMMAND_OFFSET).write_volatile(2) };
|
||||
unsafe {
|
||||
(self.control.as_ptr() as *mut u32)
|
||||
.add(COMMAND_OFFSET)
|
||||
.write_volatile(2)
|
||||
};
|
||||
}
|
||||
|
||||
fn update_dirty(&mut self) {
|
||||
unsafe { self.control.add(COMMAND_OFFSET).write_volatile(1) };
|
||||
unsafe {
|
||||
(self.control.as_ptr() as *mut u32)
|
||||
.add(COMMAND_OFFSET)
|
||||
.write_volatile(1)
|
||||
};
|
||||
}
|
||||
|
||||
/// "synchronous clear" -- must be called on init, so that the state of the LCD
|
||||
/// internal memory is consistent with the state of the frame buffer
|
||||
fn sync_clear(&mut self) {
|
||||
let framebuffer = self.fb.as_mut_ptr() as *mut u32;
|
||||
for words in 0..FB_SIZE {
|
||||
if words % FB_WIDTH_WORDS != 10 {
|
||||
self.fb[words] = 0xFFFF_FFFF;
|
||||
unsafe { framebuffer.add(words).write_volatile(0xFFFF_FFFF) };
|
||||
} else {
|
||||
self.fb[words] = 0x0000_FFFF;
|
||||
unsafe { framebuffer.add(words).write_volatile(0x0000_FFFF) };
|
||||
}
|
||||
}
|
||||
self.update_all(); // because we force an all update here
|
||||
|
|
@ -70,35 +91,46 @@ impl XousDisplay {
|
|||
}
|
||||
|
||||
fn busy(&self) -> bool {
|
||||
unsafe { self.control.add(BUSY_OFFSET).read_volatile() == 1 }
|
||||
unsafe {
|
||||
(self.control.as_ptr() as *mut u32)
|
||||
.add(BUSY_OFFSET)
|
||||
.read_volatile()
|
||||
== 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawTarget<BinaryColor> for XousDisplay {
|
||||
type Error = core::convert::Infallible;
|
||||
|
||||
/// Draw a `Pixel` that has a color defined as `Gray8`.
|
||||
/// Draw a `Pixel` that has a color defined as `BinaryColor`.
|
||||
fn draw_pixel(&mut self, pixel: Pixel<BinaryColor>) -> Result<(), Self::Error> {
|
||||
let Pixel(coord, color) = pixel;
|
||||
let framebuffer = self.fb.as_mut_ptr() as *mut u32;
|
||||
let offset = (coord.x / 32 + coord.y * FB_WIDTH_WORDS as i32) as usize;
|
||||
match color {
|
||||
BinaryColor::Off => {
|
||||
self.fb[(coord.x / 32 + coord.y * FB_WIDTH_WORDS as i32) as usize] |=
|
||||
1 << (coord.x % 32)
|
||||
unsafe {
|
||||
framebuffer.add(offset).write_volatile(
|
||||
framebuffer.add(offset).read_volatile() | (1 << (coord.x % 32)),
|
||||
)
|
||||
};
|
||||
}
|
||||
BinaryColor::On => {
|
||||
self.fb[(coord.x / 32 + coord.y * FB_WIDTH_WORDS as i32) as usize] &=
|
||||
!(1 << (coord.x % 32))
|
||||
unsafe {
|
||||
framebuffer.add(offset).write_volatile(
|
||||
framebuffer.add(offset).read_volatile() & !(1 << (coord.x % 32)),
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
// set the dirty bit on the line
|
||||
self.fb[(coord.y * FB_WIDTH_WORDS as i32 + (FB_WIDTH_WORDS as i32 - 1)) as usize] |=
|
||||
0x1_0000;
|
||||
|
||||
// self.buffer[(point.y * (WIDTH as i32) + point.x) as usize] = if color == BinaryColor::On {
|
||||
// LIGHT_COLOUR
|
||||
// } else {
|
||||
// DARK_COLOUR
|
||||
// };
|
||||
// set the dirty bit on the line
|
||||
unsafe {
|
||||
framebuffer
|
||||
.add(offset)
|
||||
.write_volatile(framebuffer.add(offset).read_volatile() | 0x1_0000)
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue