starting to make vga more modular, keyboard controls which screen is in scope

This commit is contained in:
Jack Halford 2018-02-10 18:18:58 +01:00
parent 7429ab83c8
commit 66d75c0895
6 changed files with 176 additions and 116 deletions

View file

@ -1 +1,32 @@
pub static KEY_CODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?";
pub static SCANCODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?";
use vga;
use cpuio;
use vga::buffer::{Writer, Screen};
pub fn kbd_loop(writer: &mut Writer) {
let terminal_one: vga::terminal::Terminal = vga::Screen::new();
// let terminal_two: vga::terminal::Terminal = vga::Screen::new();
let control = unsafe { cpuio::inb(0x64) };
if (control & 1) == 1 {
let scancode = unsafe { cpuio::inb(0x60) };
//TODO current_screen() with mutex lock?
let current_screen = terminal_one;
//TODO implement logic to translate scancode->ascii
match self::SCANCODE_TO_ASCII.get(scancode as usize) {
Some(ascii) => {
//TODO screen switching logic
// if let Some(action) = Screen::keypress(current_screen, *ascii as char) {
if let Some(action) = current_screen.keypress(*ascii as char) {
writer.action(action);
}
},
None =>{},
// None => println!("nokey ctrl {:x}", control),
}
}
}

View file

@ -9,7 +9,7 @@ extern crate volatile;
extern crate rlibc;
#[macro_use]
mod vga_buffer;
mod vga;
#[allow(dead_code)]
mod cpuio;
@ -17,39 +17,30 @@ mod keyboard;
#[no_mangle]
pub extern fn kmain() -> ! {
use vga_buffer::WRITER;
use vga_buffer::Color;
use vga_buffer::ColorCode;
// use vga::VgaScreen;
// use vga::color::Color;
// use vga::color::ColorCode;
WRITER.lock().reset_screen();
WRITER.lock().color_code = ColorCode::new(Color::Yellow, Color::Black);
println!(r#" ,--, "#);
println!(r#" ,--.'| ,----, "#);
println!(r#" ,--, | : .' .' \ "#);
println!(r#",---.'| : ' ,----,' | "#);
println!(r#"; : | | ; | : . ; "#);
println!(r#"| | : _' | ; |.' / "#);
println!(r#": : |.' | `----'/ ; "#);
println!(r#"| ' ' ; : / ; / "#);
println!(r#"\ \ .'. | ; / /-, "#);
println!(r#" `---`: | ' / / /.`| "#);
println!(r#" ' ; |./__; : "#);
println!(r#" | : ;| : .' "#);
println!(r#" ' ,/ ; | .' "#);
println!(r#" '--' `---' "#);
WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black);
println!(">> Kernel startup...");
loop {
let control = unsafe { cpuio::inb(0x64) };
if (control & 1) == 1 {
let keycode = unsafe { cpuio::inb(0x60) };
match keyboard::KEY_CODE_TO_ASCII.get(keycode as usize) {
Some(ascii) => print!("{}", *ascii as char),
None =>{},
// None => println!("nokey ctrl {:x}", control),
}
}
}
// WRITER.lock().reset_screen();
// WRITER.lock().color_code = ColorCode::new(Color::Yellow, Color::Black);
// println!(r#" ,--, "#);
// println!(r#" ,--.'| ,----, "#);
// println!(r#" ,--, | : .' .' \ "#);
// println!(r#",---.'| : ' ,----,' | "#);
// println!(r#"; : | | ; | : . ; "#);
// println!(r#"| | : _' | ; |.' / "#);
// println!(r#": : |.' | `----'/ ; "#);
// println!(r#"| ' ' ; : / ; / "#);
// println!(r#"\ \ .'. | ; / /-, "#);
// println!(r#" `---`: | ' / / /.`| "#);
// println!(r#" ' ; |./__; : "#);
// println!(r#" | : ;| : .' "#);
// println!(r#" ' ,/ ; | .' "#);
// println!(r#" '--' `---' "#);
// WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black);
// println!(">> Kernel startup...");
unsafe { loop { keyboard::kbd_loop(&mut vga::buffer::WRITER); } };
}
#[lang = "eh_personality"] #[no_mangle]
@ -59,11 +50,12 @@ pub extern fn eh_personality() {
#[lang = "panic_fmt"] #[no_mangle]
pub extern fn panic_fmt(
fmt: core::fmt::Arguments, file: &'static str, line: u32)
// fmt: core::fmt::Arguments, file: &'static str, line: u32
)
-> ! {
println!("PANIC: {}", fmt);
println!("FILE: {}", file);
println!("LINE: {}", line);
// println!("PANIC: {}", fmt);
// println!("FILE: {}", file);
// println!("LINE: {}", line);
loop {}
}

View file

@ -7,24 +7,33 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use volatile::Volatile;
use super::{Color, ColorCode};
use core::ptr::Unique;
use core::fmt;
use spin::Mutex;
use volatile::Volatile;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct ScreenChar {
ascii_character: u8,
color_code: ColorCode,
}
const BUFFER_HEIGHT: usize = 25;
const BUFFER_WIDTH: usize = 80;
pub static WRITER: Mutex<Writer> = Mutex::new(Writer {
pub struct Writer {
pub column_position: usize,
pub color_code: ColorCode,
vgabuffer: Unique<Buffer>,
}
// Writer is the default object to use to print to screen
pub static mut WRITER: Writer = Writer {
column_position: 0,
color_code: ColorCode::new(Color::White, Color::Black),
vgabuffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) },
});
// cursor is lightgray for everyone
static CURSOR: ScreenChar = ScreenChar {
ascii_character: b' ',
color_code: ColorCode::new(Color::LightGray, Color::LightGray),
};
// blank is black for everyone, could make screens choose this
@ -33,29 +42,14 @@ static BLANK: ScreenChar = ScreenChar {
color_code: ColorCode::new(Color::White, Color::Black),
};
pub struct Writer {
column_position: usize,
pub color_code: ColorCode,
vgabuffer: Unique<Buffer>,
}
macro_rules! println {
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}
macro_rules! print {
($($arg:tt)*) => ({
$crate::vga_buffer::print(format_args!($($arg)*));
});
}
pub fn print(args: fmt::Arguments) {
use core::fmt::Write;
WRITER.lock().write_fmt(args).unwrap();
}
impl Writer {
pub fn action(&mut self, action: BufferAction) {
match action {
BufferAction::WRITE_BYTE(ascii) => self.write_byte(ascii as u8),
BufferAction::CLEAR_SCREEN => self.reset_screen(),
}
}
pub fn reset_screen(&mut self)
{
let color_code = self.color_code;
@ -72,7 +66,7 @@ impl Writer {
pub fn write_byte(&mut self, byte: u8) {
match byte {
b'\n' => self.new_line(),
b'\n' => { self.new_line(); }
byte => {
if self.column_position >= BUFFER_WIDTH {
self.new_line();
@ -87,9 +81,6 @@ impl Writer {
self.column_position += 1;
}
}
let row = BUFFER_HEIGHT - 1;
let col = self.column_position;
self.buffer().chars[row][col].write(CURSOR);
}
fn buffer(&mut self) -> &mut Buffer {
@ -97,11 +88,6 @@ impl Writer {
}
fn new_line(&mut self) {
// remove cursor if newline isnt from end of screen
if self.column_position < BUFFER_WIDTH {
let col = self.column_position;
self.buffer().chars[BUFFER_HEIGHT - 1][col].write(BLANK);
}
for row in 1..BUFFER_HEIGHT {
for col in 0..BUFFER_WIDTH {
let buffer = self.buffer();
@ -129,44 +115,19 @@ impl fmt::Write for Writer {
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum Color {
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Brown = 6,
LightGray = 7,
DarkGray = 8,
LightBlue = 9,
LightGreen = 10,
LightCyan = 11,
LightRed = 12,
Pink = 13,
Yellow = 14,
White = 15,
}
#[derive(Debug, Clone, Copy)]
pub struct ColorCode(u8);
impl ColorCode {
pub const fn new(foreground: Color, background: Color) -> ColorCode {
ColorCode((background as u8) << 4 | (foreground as u8))
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct ScreenChar {
ascii_character: u8,
color_code: ColorCode,
}
struct Buffer {
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
}
pub enum BufferAction {
WRITE_BYTE(char),
CLEAR_SCREEN,
}
/// Implementors of this trait can use the vga screen for any purpose
pub trait Screen {
fn new() -> Self; //
fn keypress(self, keycode: char) -> Option<BufferAction>;
// fn load();
// fn unload() -> ;
}

View file

@ -0,0 +1,30 @@
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum Color {
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Brown = 6,
LightGray = 7,
DarkGray = 8,
LightBlue = 9,
LightGreen = 10,
LightCyan = 11,
LightRed = 12,
Pink = 13,
Yellow = 14,
White = 15,
}
#[derive(Debug, Clone, Copy)]
pub struct ColorCode(u8);
impl ColorCode {
pub const fn new(foreground: Color, background: Color) -> ColorCode {
ColorCode((background as u8) << 4 | (foreground as u8))
}
}

27
kernel-rs/src/vga/mod.rs Normal file
View file

@ -0,0 +1,27 @@
#[macro_use]
pub mod buffer;
pub mod color;
pub mod terminal;
pub use self::color::{Color, ColorCode};
pub use self::buffer::{WRITER, Screen, BufferAction};
// use self::buffer::Writer;
// use core::fmt;
// use core::ptr::Unique;
// macro_rules! println {
// ($fmt:expr) => (print!(concat!($fmt, "\n")));
// ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
// }
// macro_rules! print {
// ($($arg:tt)*) => ({
// $crate::vga::print(format_args!($($arg)*));
// });
// }
// pub fn print(args: fmt::Arguments) {
// use core::fmt::Write;
// self::WRITER.write_fmt(args).unwrap();
// }

View file

@ -0,0 +1,19 @@
//! terminal.rs implements a basic cursor terminal using the vga::buffer module
use super::{Color, ColorCode};
use vga;
// cursor is lightgray for everyone
static CURSOR: ColorCode = ColorCode::new(Color::LightGray, Color::White);
pub struct Terminal { }
impl vga::Screen for Terminal {
fn new() -> Terminal {
Terminal { }
}
fn keypress(self, ascii: char) -> Option<vga::BufferAction> {
Some(vga::BufferAction::WRITE_BYTE(ascii))
}
}