2025-09-11 16:00:04 -07:00
|
|
|
use crate::dev::{linebuffer_push, FRAMEBUFFER_HEIGHT, FRAMEBUFFER_WIDTH, LINEBUFFER_ADDR, LINEBUFFER_BPP};
|
2025-09-10 23:49:17 -07:00
|
|
|
use crate::trafficcontrol::TrafficControl;
|
|
|
|
|
use core::sync::atomic::Ordering;
|
|
|
|
|
|
|
|
|
|
pub mod console;
|
|
|
|
|
|
|
|
|
|
pub const VAPFONT: &[u8] = include_bytes!("./vapfont.data");
|
|
|
|
|
pub const VAPFONT_W: usize = 256;
|
|
|
|
|
pub const VAPFONT_H: usize = 112;
|
|
|
|
|
|
|
|
|
|
pub struct FBColor {
|
|
|
|
|
pub red: u8,
|
|
|
|
|
pub green: u8,
|
|
|
|
|
pub blue: u8,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub const FB_BG_COLOR: FBColor = FBColor {
|
|
|
|
|
red: 216,
|
|
|
|
|
green: 216,
|
|
|
|
|
blue: 216,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub const FB_FG_COLOR: FBColor = FBColor {
|
|
|
|
|
red: 0,
|
|
|
|
|
green: 0,
|
|
|
|
|
blue: 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
impl FBColor {
|
|
|
|
|
#[inline]
|
|
|
|
|
pub const fn to_bytes(&self) -> [u8; 3] {
|
|
|
|
|
[self.red, self.green, self.blue]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn fb_write_char_array(tc: &mut TrafficControl, mut x: usize, mut y: usize, chars: &[char]) {
|
|
|
|
|
const BYTES: [u8; 3] = FB_FG_COLOR.to_bytes();
|
2025-09-11 16:00:04 -07:00
|
|
|
let fbaddr = LINEBUFFER_ADDR.load(Ordering::Relaxed);
|
2025-09-10 23:49:17 -07:00
|
|
|
if fbaddr == 0 {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const CHAR_SIZE: usize = 16;
|
|
|
|
|
let mut drew_anything = false;
|
2025-09-11 16:00:04 -07:00
|
|
|
for line in 0..FRAMEBUFFER_HEIGHT {
|
|
|
|
|
for c in chars {
|
|
|
|
|
let c = *c;
|
|
|
|
|
if c == ' ' {
|
|
|
|
|
x += CHAR_SIZE;
|
|
|
|
|
} else if c as u8 > 32 {
|
|
|
|
|
let c = c as u8 - 32;
|
|
|
|
|
let cx = (c % 16) as usize * CHAR_SIZE;
|
|
|
|
|
let cy = (c / 16) as usize * CHAR_SIZE;
|
|
|
|
|
for row in 0..CHAR_SIZE {
|
|
|
|
|
if (y+row) != line {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
for col in 0..CHAR_SIZE {
|
|
|
|
|
let coff = (VAPFONT_W * (cy + row)) + (cx + col);
|
|
|
|
|
let draw = VAPFONT[coff / 8] & (0x80 >> (coff % 8));
|
|
|
|
|
if draw != 0 {
|
|
|
|
|
unsafe {
|
|
|
|
|
//let fb = (fbaddr as *mut u8).add(((y + row) * fbstride) + ((x + col) * 4)) as *mut u32;
|
|
|
|
|
let fb = (fbaddr as *mut u8).add((x + col) * 4) as *mut u32;
|
|
|
|
|
fb.write_volatile(u32::from_ne_bytes([0, BYTES[0], BYTES[1], BYTES[2]]));
|
|
|
|
|
drew_anything = true;
|
|
|
|
|
}
|
2025-09-10 23:49:17 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-11 16:00:04 -07:00
|
|
|
x += CHAR_SIZE;
|
2025-09-10 23:49:17 -07:00
|
|
|
}
|
2025-09-11 16:00:04 -07:00
|
|
|
}
|
|
|
|
|
if drew_anything {
|
|
|
|
|
linebuffer_push(tc, line as u32);
|
2025-09-10 23:49:17 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn fb_clearscreen(tc: &mut TrafficControl) {
|
|
|
|
|
const BYTES: [u8; 3] = FB_BG_COLOR.to_bytes();
|
2025-09-11 16:00:04 -07:00
|
|
|
let fbaddr = LINEBUFFER_ADDR.load(Ordering::Relaxed);
|
2025-09-10 23:49:17 -07:00
|
|
|
if fbaddr == 0 {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for y in 0..FRAMEBUFFER_HEIGHT {
|
|
|
|
|
for x in 0..FRAMEBUFFER_WIDTH {
|
|
|
|
|
unsafe {
|
2025-09-11 16:00:04 -07:00
|
|
|
//let fb = (fbaddr as *mut u8).add(((y)*fbstride) + ((x)*4)) as *mut u32;
|
|
|
|
|
let fb = (fbaddr as *mut u8).add(x*4) as *mut u32;
|
2025-09-10 23:49:17 -07:00
|
|
|
fb.write_volatile(u32::from_ne_bytes([0, BYTES[0], BYTES[1], BYTES[2]]));
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-11 16:00:04 -07:00
|
|
|
linebuffer_push(tc, y as u32);
|
2025-09-10 23:49:17 -07:00
|
|
|
}
|
|
|
|
|
}
|