use super::{SRX_DATA_ADDRESS, SRX_INDEX_ADDRESS};
use bitflags::bitflags;
use core::convert::TryFrom;
use x86_64::instructions::port::Port;
bitflags! {
pub struct PlaneMask: u8 {
const NONE = 0b0000_0000;
const PLANE0 = 0b0000_0001;
const PLANE1 = 0b0000_0010;
const PLANE2 = 0b0000_0100;
const PLANE3 = 0b0000_1000;
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()
}
}
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum SequencerIndex {
SequencerReset = 0x0,
ClockingMode = 0x1,
PlaneMask = 0x2,
CharacterFont = 0x3,
MemoryMode = 0x4,
CounterReset = 0x7,
}
impl From<SequencerIndex> for u8 {
fn from(value: SequencerIndex) -> u8 {
value as u8
}
}
#[derive(Debug)]
pub struct SequencerRegisters {
srx_index: Port<u8>,
srx_data: Port<u8>,
}
impl SequencerRegisters {
pub(crate) fn new() -> SequencerRegisters {
SequencerRegisters {
srx_index: Port::new(SRX_INDEX_ADDRESS),
srx_data: Port::new(SRX_DATA_ADDRESS),
}
}
pub fn read(&mut self, index: SequencerIndex) -> u8 {
self.set_index(index);
unsafe { self.srx_data.read() }
}
pub fn write(&mut self, index: SequencerIndex, value: u8) {
self.set_index(index);
unsafe {
self.srx_data.write(value);
}
}
pub fn set_plane_mask(&mut self, plane_mask: PlaneMask) {
let original_value = self.read(SequencerIndex::PlaneMask) & 0xF0;
self.write(
SequencerIndex::PlaneMask,
original_value | u8::from(plane_mask),
);
}
fn set_index(&mut self, index: SequencerIndex) {
unsafe {
self.srx_index.write(u8::from(index));
}
}
}