Plane refactor
This commit is contained in:
parent
dc6def0ed0
commit
86c575e7bc
|
@ -19,6 +19,7 @@ repository = "https://github.com/rust-osdev/vga"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bitflags = "1.2.1"
|
||||||
conquer-once = { version = "0.2.0", default-features = false }
|
conquer-once = { version = "0.2.0", default-features = false }
|
||||||
spinning_top = { version = "0.1.0", features = ["nightly"] }
|
spinning_top = { version = "0.1.0", features = ["nightly"] }
|
||||||
x86_64 = "0.9.6"
|
x86_64 = "0.9.6"
|
||||||
|
|
|
@ -58,7 +58,7 @@ pub enum SequencerIndex {
|
||||||
SequencerReset = 0x0,
|
SequencerReset = 0x0,
|
||||||
/// Represents the `Clocking Mode` register index.
|
/// Represents the `Clocking Mode` register index.
|
||||||
ClockingMode = 0x1,
|
ClockingMode = 0x1,
|
||||||
/// Represents the Plane/Map mask register index.
|
/// Represents the `Plane/Map` mask register index.
|
||||||
PlaneMask = 0x2,
|
PlaneMask = 0x2,
|
||||||
/// Represents the `Character Font` register index.
|
/// Represents the `Character Font` register index.
|
||||||
CharacterFont = 0x3,
|
CharacterFont = 0x3,
|
||||||
|
|
79
src/vga.rs
79
src/vga.rs
|
@ -13,7 +13,9 @@ use super::{
|
||||||
GraphicsControllerIndex, GraphicsControllerRegisters, SequencerIndex, SequencerRegisters,
|
GraphicsControllerIndex, GraphicsControllerRegisters, SequencerIndex, SequencerRegisters,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use bitflags::bitflags;
|
||||||
use conquer_once::spin::Lazy;
|
use conquer_once::spin::Lazy;
|
||||||
|
use core::convert::TryFrom;
|
||||||
use spinning_top::Spinlock;
|
use spinning_top::Spinlock;
|
||||||
|
|
||||||
/// Provides mutable access to the vga graphics card.
|
/// Provides mutable access to the vga graphics card.
|
||||||
|
@ -49,11 +51,11 @@ impl From<FrameBuffer> for u32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a plane for reading and writing vga data.
|
/// Represents a plane for the `GraphicsControllerIndex::ReadPlaneSelect` register.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Plane {
|
pub enum ReadPlane {
|
||||||
/// Represents `Plane 0 (0x0)`.
|
/// Represents `Plane 0 (0x0)`.
|
||||||
Plane0 = 0x0,
|
Plane0 = 0x0,
|
||||||
/// Represents `Plane 1 (0x1)`.
|
/// Represents `Plane 1 (0x1)`.
|
||||||
|
@ -64,12 +66,60 @@ pub enum Plane {
|
||||||
Plane3 = 0x3,
|
Plane3 = 0x3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Plane> for u8 {
|
impl TryFrom<u8> for ReadPlane {
|
||||||
fn from(value: Plane) -> u8 {
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
0 => Ok(ReadPlane::Plane0),
|
||||||
|
1 => Ok(ReadPlane::Plane1),
|
||||||
|
2 => Ok(ReadPlane::Plane2),
|
||||||
|
3 => Ok(ReadPlane::Plane3),
|
||||||
|
_ => Err("ReadPlane only accepts values between 0-3!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ReadPlane> for u8 {
|
||||||
|
fn from(value: ReadPlane) -> u8 {
|
||||||
value as u8
|
value as u8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Represents the plane masks of the `SequencerIndex::PlaneMask` register.
|
||||||
|
pub struct PlaneMask: u8 {
|
||||||
|
/// Represents `Plane0` of vga memory.
|
||||||
|
const PLANE0 = 0b00000001;
|
||||||
|
/// Represents `Plane1` of vga memory.
|
||||||
|
const PLANE1 = 0b00000010;
|
||||||
|
/// Represents `Plane2` of vga memory.
|
||||||
|
const PLANE2 = 0b00000100;
|
||||||
|
/// Represents `Plane3` of vga memory.
|
||||||
|
const PLANE3 = 0b00001000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for PlaneMask {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
0 => Ok(PlaneMask::PLANE0),
|
||||||
|
1 => Ok(PlaneMask::PLANE1),
|
||||||
|
2 => Ok(PlaneMask::PLANE2),
|
||||||
|
3 => Ok(PlaneMask::PLANE3),
|
||||||
|
_ => Err("PlaneMask only accepts values between 0-3!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PlaneMask> for u8 {
|
||||||
|
fn from(value: PlaneMask) -> u8 {
|
||||||
|
value.bits()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a specified vga video mode.
|
/// Represents a specified vga video mode.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum VideoMode {
|
pub enum VideoMode {
|
||||||
|
@ -226,7 +276,7 @@ impl Vga {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Write font to plane
|
// Write font to plane
|
||||||
self.set_plane(Plane::Plane2);
|
self.set_plane_mask(PlaneMask::PLANE2);
|
||||||
|
|
||||||
let frame_buffer = u32::from(self.get_frame_buffer()) as *mut u8;
|
let frame_buffer = u32::from(self.get_frame_buffer()) as *mut u8;
|
||||||
|
|
||||||
|
@ -286,16 +336,17 @@ impl Vga {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turns on the given `Plane` in the vga graphics card.
|
/// Sets the plane mask of the sequencer controller, as specified by `plane_mask`.
|
||||||
pub fn set_plane(&mut self, plane: Plane) {
|
pub fn set_plane_mask(&mut self, plane_mask: PlaneMask) {
|
||||||
let mut plane = u8::from(plane);
|
|
||||||
|
|
||||||
plane &= 0x3;
|
|
||||||
|
|
||||||
self.graphics_controller_registers
|
|
||||||
.write(GraphicsControllerIndex::ReadPlaneSelect, plane);
|
|
||||||
self.sequencer_registers
|
self.sequencer_registers
|
||||||
.write(SequencerIndex::PlaneMask, 0x1 << plane);
|
.write(SequencerIndex::PlaneMask, u8::from(plane_mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the read plane of the graphics controller, as specified by `read_plane`.
|
||||||
|
pub fn set_read_plane(&mut self, read_plane: ReadPlane) {
|
||||||
|
let read_plane = u8::from(read_plane) & 0x3;
|
||||||
|
self.graphics_controller_registers
|
||||||
|
.write(GraphicsControllerIndex::ReadPlaneSelect, read_plane);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_registers(&mut self, configuration: &VgaConfiguration) {
|
fn set_registers(&mut self, configuration: &VgaConfiguration) {
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
colors::{Color16Bit, DEFAULT_PALETTE},
|
colors::{Color16Bit, DEFAULT_PALETTE},
|
||||||
vga::{Plane, Vga, VideoMode, VGA},
|
vga::{Vga, VideoMode, VGA},
|
||||||
};
|
};
|
||||||
|
use core::convert::TryInto;
|
||||||
use spinning_top::SpinlockGuard;
|
use spinning_top::SpinlockGuard;
|
||||||
|
|
||||||
const WIDTH: usize = 640;
|
const WIDTH: usize = 640;
|
||||||
const HEIGHT: usize = 480;
|
const HEIGHT: usize = 480;
|
||||||
|
|
||||||
static PLANES: &[Plane] = &[Plane::Plane0, Plane::Plane1, Plane::Plane2, Plane::Plane3];
|
|
||||||
|
|
||||||
/// A basic interface for interacting with vga graphics mode 640x480x16
|
/// A basic interface for interacting with vga graphics mode 640x480x16
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -37,7 +36,7 @@ impl Graphics640x480x16 {
|
||||||
// TODO: Clear the screen by using 4-plane mode instead of slow `set_pixel`.
|
// TODO: Clear the screen by using 4-plane mode instead of slow `set_pixel`.
|
||||||
for x in 0..WIDTH {
|
for x in 0..WIDTH {
|
||||||
for y in 0..HEIGHT {
|
for y in 0..HEIGHT {
|
||||||
self.set_pixel(x, y, Color16Bit::Yellow);
|
self.set_pixel(x, y, Color16Bit::Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,8 +55,9 @@ impl Graphics640x480x16 {
|
||||||
let mask = 0x80 >> (x & 7);
|
let mask = 0x80 >> (x & 7);
|
||||||
let mut plane_mask = 0x01;
|
let mut plane_mask = 0x01;
|
||||||
|
|
||||||
for plane in PLANES {
|
for plane in 0u8..4u8 {
|
||||||
vga.set_plane(*plane);
|
vga.set_read_plane(plane.try_into().unwrap());
|
||||||
|
vga.set_plane_mask(plane.try_into().unwrap());
|
||||||
let current_value = unsafe { frame_buffer.add(offset).read_volatile() };
|
let current_value = unsafe { frame_buffer.add(offset).read_volatile() };
|
||||||
let new_value = if plane_mask & color as u8 != 0 {
|
let new_value = if plane_mask & color as u8 != 0 {
|
||||||
current_value | mask
|
current_value | mask
|
||||||
|
|
Loading…
Reference in a new issue