public registers and plane mask
This commit is contained in:
parent
3eae6fb32d
commit
a05f2cc826
|
@ -67,7 +67,7 @@ pub struct AttributeControllerRegisters {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttributeControllerRegisters {
|
impl AttributeControllerRegisters {
|
||||||
pub fn new() -> AttributeControllerRegisters {
|
pub(crate) fn new() -> AttributeControllerRegisters {
|
||||||
AttributeControllerRegisters {
|
AttributeControllerRegisters {
|
||||||
arx_index: Port::new(ARX_INDEX_ADDRESS),
|
arx_index: Port::new(ARX_INDEX_ADDRESS),
|
||||||
arx_data: Port::new(ARX_DATA_ADDRESS),
|
arx_data: Port::new(ARX_DATA_ADDRESS),
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub struct ColorPaletteRegisters {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ColorPaletteRegisters {
|
impl ColorPaletteRegisters {
|
||||||
pub fn new() -> ColorPaletteRegisters {
|
pub(crate) fn new() -> ColorPaletteRegisters {
|
||||||
ColorPaletteRegisters {
|
ColorPaletteRegisters {
|
||||||
data_port: Port::new(COLOR_PALETTE_DATA_ADDRESS),
|
data_port: Port::new(COLOR_PALETTE_DATA_ADDRESS),
|
||||||
index_read_port: Port::new(COLOR_PALETTE_INDEX_READ_ADDRESS),
|
index_read_port: Port::new(COLOR_PALETTE_INDEX_READ_ADDRESS),
|
||||||
|
|
|
@ -79,7 +79,7 @@ pub struct CrtcControllerRegisters {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrtcControllerRegisters {
|
impl CrtcControllerRegisters {
|
||||||
pub fn new() -> CrtcControllerRegisters {
|
pub(crate) fn new() -> CrtcControllerRegisters {
|
||||||
CrtcControllerRegisters {
|
CrtcControllerRegisters {
|
||||||
crx_index_cga: Port::new(CRX_INDEX_CGA_ADDRESS),
|
crx_index_cga: Port::new(CRX_INDEX_CGA_ADDRESS),
|
||||||
crx_index_mda: Port::new(CRX_INDEX_MDA_ADDRESS),
|
crx_index_mda: Port::new(CRX_INDEX_MDA_ADDRESS),
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub struct GeneralRegisters {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GeneralRegisters {
|
impl GeneralRegisters {
|
||||||
pub fn new() -> GeneralRegisters {
|
pub(crate) fn new() -> GeneralRegisters {
|
||||||
GeneralRegisters {
|
GeneralRegisters {
|
||||||
st00_read: PortReadOnly::new(ST00_READ_ADDRESS),
|
st00_read: PortReadOnly::new(ST00_READ_ADDRESS),
|
||||||
st01_read_cga: PortReadOnly::new(ST01_READ_CGA_ADDRESS),
|
st01_read_cga: PortReadOnly::new(ST01_READ_CGA_ADDRESS),
|
||||||
|
|
|
@ -44,7 +44,7 @@ pub struct GraphicsControllerRegisters {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GraphicsControllerRegisters {
|
impl GraphicsControllerRegisters {
|
||||||
pub fn new() -> GraphicsControllerRegisters {
|
pub(crate) fn new() -> GraphicsControllerRegisters {
|
||||||
GraphicsControllerRegisters {
|
GraphicsControllerRegisters {
|
||||||
grx_index: Port::new(GRX_INDEX_ADDRESS),
|
grx_index: Port::new(GRX_INDEX_ADDRESS),
|
||||||
grx_data: Port::new(GRX_DATA_ADDRESS),
|
grx_data: Port::new(GRX_DATA_ADDRESS),
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub use color_palette::ColorPaletteRegisters;
|
||||||
pub use crtc_controller::{CrtcControllerIndex, CrtcControllerRegisters};
|
pub use crtc_controller::{CrtcControllerIndex, CrtcControllerRegisters};
|
||||||
pub use general::GeneralRegisters;
|
pub use general::GeneralRegisters;
|
||||||
pub use graphics_controller::{GraphicsControllerIndex, GraphicsControllerRegisters};
|
pub use graphics_controller::{GraphicsControllerIndex, GraphicsControllerRegisters};
|
||||||
pub use sequencer::{SequencerIndex, SequencerRegisters};
|
pub use sequencer::{PlaneMask, SequencerIndex, SequencerRegisters};
|
||||||
|
|
||||||
const ST00_READ_ADDRESS: u16 = 0x3C2;
|
const ST00_READ_ADDRESS: u16 = 0x3C2;
|
||||||
const ST01_READ_CGA_ADDRESS: u16 = 0x3DA;
|
const ST01_READ_CGA_ADDRESS: u16 = 0x3DA;
|
||||||
|
|
|
@ -1,6 +1,46 @@
|
||||||
use super::{SRX_DATA_ADDRESS, SRX_INDEX_ADDRESS};
|
use super::{SRX_DATA_ADDRESS, SRX_INDEX_ADDRESS};
|
||||||
|
use bitflags::bitflags;
|
||||||
|
use core::convert::TryFrom;
|
||||||
use x86_64::instructions::port::Port;
|
use x86_64::instructions::port::Port;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Represents the plane masks of the `SequencerIndex::PlaneMask` register.
|
||||||
|
pub struct PlaneMask: u8 {
|
||||||
|
/// Represents none of the plane masks of vga memory.
|
||||||
|
const NONE = 0b0000_0000;
|
||||||
|
/// Represents `Plane0` of vga memory.
|
||||||
|
const PLANE0 = 0b0000_0001;
|
||||||
|
/// Represents `Plane1` of vga memory.
|
||||||
|
const PLANE1 = 0b0000_0010;
|
||||||
|
/// Represents `Plane2` of vga memory.
|
||||||
|
const PLANE2 = 0b0000_0100;
|
||||||
|
/// Represents `Plane3` of vga memory.
|
||||||
|
const PLANE3 = 0b0000_1000;
|
||||||
|
/// Represents all of the plane masks of vga memory.
|
||||||
|
const ALL_PLANES = Self::PLANE0.bits() | Self::PLANE1.bits() | Self::PLANE2.bits() | Self::PLANE3.bits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 an index for the seqeuncer registers.
|
/// Represents an index for the seqeuncer registers.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
@ -32,7 +72,7 @@ pub struct SequencerRegisters {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SequencerRegisters {
|
impl SequencerRegisters {
|
||||||
pub fn new() -> SequencerRegisters {
|
pub(crate) fn new() -> SequencerRegisters {
|
||||||
SequencerRegisters {
|
SequencerRegisters {
|
||||||
srx_index: Port::new(SRX_INDEX_ADDRESS),
|
srx_index: Port::new(SRX_INDEX_ADDRESS),
|
||||||
srx_data: Port::new(SRX_DATA_ADDRESS),
|
srx_data: Port::new(SRX_DATA_ADDRESS),
|
||||||
|
@ -51,6 +91,11 @@ impl SequencerRegisters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the plane mask of the sequencer controller, as specified by `plane_mask`.
|
||||||
|
pub fn set_plane_mask(&mut self, plane_mask: PlaneMask) {
|
||||||
|
self.write(SequencerIndex::PlaneMask, u8::from(plane_mask));
|
||||||
|
}
|
||||||
|
|
||||||
fn set_index(&mut self, index: SequencerIndex) {
|
fn set_index(&mut self, index: SequencerIndex) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.srx_index.write(u8::from(index));
|
self.srx_index.write(u8::from(index));
|
||||||
|
|
62
src/vga.rs
62
src/vga.rs
|
@ -10,10 +10,10 @@ use super::{
|
||||||
registers::{
|
registers::{
|
||||||
AttributeControllerIndex, AttributeControllerRegisters, ColorPaletteRegisters,
|
AttributeControllerIndex, AttributeControllerRegisters, ColorPaletteRegisters,
|
||||||
CrtcControllerIndex, CrtcControllerRegisters, EmulationMode, GeneralRegisters,
|
CrtcControllerIndex, CrtcControllerRegisters, EmulationMode, GeneralRegisters,
|
||||||
GraphicsControllerIndex, GraphicsControllerRegisters, SequencerIndex, SequencerRegisters,
|
GraphicsControllerIndex, GraphicsControllerRegisters, PlaneMask, SequencerIndex,
|
||||||
|
SequencerRegisters,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bitflags::bitflags;
|
|
||||||
use conquer_once::spin::Lazy;
|
use conquer_once::spin::Lazy;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use spinning_top::Spinlock;
|
use spinning_top::Spinlock;
|
||||||
|
@ -86,44 +86,6 @@ impl From<ReadPlane> for u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
/// Represents the plane masks of the `SequencerIndex::PlaneMask` register.
|
|
||||||
pub struct PlaneMask: u8 {
|
|
||||||
/// Represents none of the plane masks of vga memory.
|
|
||||||
const NONE = 0b0000_0000;
|
|
||||||
/// Represents `Plane0` of vga memory.
|
|
||||||
const PLANE0 = 0b0000_0001;
|
|
||||||
/// Represents `Plane1` of vga memory.
|
|
||||||
const PLANE1 = 0b0000_0010;
|
|
||||||
/// Represents `Plane2` of vga memory.
|
|
||||||
const PLANE2 = 0b0000_0100;
|
|
||||||
/// Represents `Plane3` of vga memory.
|
|
||||||
const PLANE3 = 0b0000_1000;
|
|
||||||
/// Represents all of the plane masks of vga memory.
|
|
||||||
const ALL_PLANES = Self::PLANE0.bits() | Self::PLANE1.bits() | Self::PLANE2.bits() | Self::PLANE3.bits();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -140,12 +102,12 @@ pub enum VideoMode {
|
||||||
/// Represents a vga graphics card with it's common registers,
|
/// Represents a vga graphics card with it's common registers,
|
||||||
/// as well as the most recent video mode.
|
/// as well as the most recent video mode.
|
||||||
pub struct Vga {
|
pub struct Vga {
|
||||||
general_registers: GeneralRegisters,
|
pub general_registers: GeneralRegisters,
|
||||||
sequencer_registers: SequencerRegisters,
|
pub sequencer_registers: SequencerRegisters,
|
||||||
graphics_controller_registers: GraphicsControllerRegisters,
|
pub graphics_controller_registers: GraphicsControllerRegisters,
|
||||||
attribute_controller_registers: AttributeControllerRegisters,
|
pub attribute_controller_registers: AttributeControllerRegisters,
|
||||||
crtc_controller_registers: CrtcControllerRegisters,
|
pub crtc_controller_registers: CrtcControllerRegisters,
|
||||||
color_palette_registers: ColorPaletteRegisters,
|
pub color_palette_registers: ColorPaletteRegisters,
|
||||||
most_recent_video_mode: Option<VideoMode>,
|
most_recent_video_mode: Option<VideoMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +242,7 @@ impl Vga {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Write font to plane
|
// Write font to plane
|
||||||
self.set_plane_mask(PlaneMask::PLANE2);
|
self.sequencer_registers.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;
|
||||||
|
|
||||||
|
@ -340,12 +302,6 @@ impl Vga {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the plane mask of the sequencer controller, as specified by `plane_mask`.
|
|
||||||
pub fn set_plane_mask(&mut self, plane_mask: PlaneMask) {
|
|
||||||
self.sequencer_registers
|
|
||||||
.write(SequencerIndex::PlaneMask, u8::from(plane_mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the read plane of the graphics controller, as specified by `read_plane`.
|
/// Sets the read plane of the graphics controller, as specified by `read_plane`.
|
||||||
pub fn set_read_plane(&mut self, read_plane: ReadPlane) {
|
pub fn set_read_plane(&mut self, read_plane: ReadPlane) {
|
||||||
let read_plane = u8::from(read_plane) & 0x3;
|
let read_plane = u8::from(read_plane) & 0x3;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
colors::{Color16Bit, DEFAULT_PALETTE},
|
colors::{Color16Bit, DEFAULT_PALETTE},
|
||||||
vga::{PlaneMask, Vga, VideoMode, VGA},
|
registers::PlaneMask,
|
||||||
|
vga::{Vga, VideoMode, VGA},
|
||||||
};
|
};
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use spinning_top::SpinlockGuard;
|
use spinning_top::SpinlockGuard;
|
||||||
|
@ -35,7 +36,8 @@ impl Graphics640x480x16 {
|
||||||
/// Clears the screen by setting all pixels to `Color16Bit::Black`.
|
/// Clears the screen by setting all pixels to `Color16Bit::Black`.
|
||||||
pub fn clear_screen(&self) {
|
pub fn clear_screen(&self) {
|
||||||
let (mut vga, frame_buffer) = self.get_frame_buffer();
|
let (mut vga, frame_buffer) = self.get_frame_buffer();
|
||||||
vga.set_plane_mask(PlaneMask::ALL_PLANES);
|
vga.sequencer_registers
|
||||||
|
.set_plane_mask(PlaneMask::ALL_PLANES);
|
||||||
vga.set_graphics_enable_set_reset(PlaneMask::NONE);
|
vga.set_graphics_enable_set_reset(PlaneMask::NONE);
|
||||||
for offset in 0..ALL_PLANES_SCREEN_SIZE {
|
for offset in 0..ALL_PLANES_SCREEN_SIZE {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -58,7 +60,8 @@ impl Graphics640x480x16 {
|
||||||
|
|
||||||
for plane in 0u8..4u8 {
|
for plane in 0u8..4u8 {
|
||||||
vga.set_read_plane(plane.try_into().unwrap());
|
vga.set_read_plane(plane.try_into().unwrap());
|
||||||
vga.set_plane_mask(plane.try_into().unwrap());
|
vga.sequencer_registers
|
||||||
|
.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