use crate::dev::framebuffer::{fb_clearscreen, fb_write_char_array}; use crate::spinlock::Spinlock; use crate::trafficcontrol::TrafficControl; pub struct FramebufferConsole { pub buffer: [[char; 20]; 15], // our font is 16x16, 320x240 is the standard res, so 20x15 pub cursor: (usize, usize), // (x, y) pub need_screen_clear: bool, } pub static FBCONSOLE: Spinlock = Spinlock::new(FramebufferConsole::empty()); impl FramebufferConsole { pub const fn empty() -> Self { Self { buffer: [[' '; 20]; 15], cursor: (0, 0), need_screen_clear: true, } } // does NOT send a framebuffer update! that's up to the caller pub fn scroll_terminal(&mut self) { for line_num in 0..(self.buffer.len() - 1) { let copy_from = self.buffer[line_num + 1]; self.buffer[line_num] = copy_from; } self.buffer[self.buffer.len() - 1] = [' '; 20]; self.need_screen_clear = true; } // DOES send a framebuffer update! pub fn clear_terminal(&mut self, tc: &mut TrafficControl) { self.need_screen_clear = false; self.buffer = [[' '; 20]; 15]; self.cursor = (0, 0); self.render(tc); } // DOES send a framebuffer update! pub fn printstr(&mut self, tc: &mut TrafficControl, str: &str) { for c in str.chars() { let mut was_special_char = false; if c == '\n' || c == '\r' { was_special_char = true; self.cursor.0 = 0; self.cursor.1 += 1; } if self.cursor.1 >= self.buffer.len() { self.cursor.0 = 0; self.cursor.1 = self.buffer.len() - 1; self.scroll_terminal(); } if c == '\x08' { was_special_char = true; // we don't clear the character, that's up to the terminal self.need_screen_clear = true; if self.cursor.0 > 0 { self.cursor.0 -= 1; } else { self.cursor.0 = 0; if self.cursor.1 > 0 { self.cursor.1 -= 1; self.cursor.0 = self.buffer[self.cursor.1].len() - 1; } } } if !was_special_char { self.buffer[self.cursor.1][self.cursor.0] = c; self.cursor.0 += 1; if self.cursor.0 >= self.buffer[self.cursor.1].len() { self.cursor.0 = 0; self.cursor.1 += 1; if self.cursor.1 >= self.buffer.len() { self.cursor.1 = self.buffer.len() - 1; self.scroll_terminal(); } } } } self.render(tc); } pub fn render(&mut self, tc: &mut TrafficControl) { if self.need_screen_clear { fb_clearscreen(tc); self.need_screen_clear = false; } for (y, line) in self.buffer.iter().enumerate() { fb_write_char_array(tc, 0, y * 16, line); } } }