use super::IoRegisters;
pub const SIZE: usize = 0x400;
const REGS: usize = 0x300;
const CONTRAST: usize = 0x301;
const DSPCTL: usize = 0x303;
const DON_BIT: u8 = 0x8;
const CRC_BASE: usize = 0x304;
const LPD: usize = 0x308;
const T1_CTRL: usize = 0x30E;
const T2_CTRL: usize = 0x30F;
const TIMER1: usize = 0x3F7;
const TIMER2: usize = 0x3F8;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LewisIo {
pub(crate) mem: Vec<u8>,
}
impl Default for LewisIo {
fn default() -> Self {
Self::new()
}
}
impl LewisIo {
pub fn new() -> Self {
Self { mem: vec![0; SIZE] }
}
pub fn peek(&self, io: &IoRegisters, offset: u32) -> u8 {
let off = offset as usize % SIZE;
match off {
CRC_BASE..=0x307 => ((io.crc() >> ((off - CRC_BASE) * 4)) & 0xF) as u8,
LPD => 0,
T1_CTRL => io.timers.read_t1_ctrl(),
T2_CTRL => io.timers.read_t2_ctrl(),
TIMER1 => io.timers.t1,
TIMER2..=0x3FF => io.timers.read_t2_nibble((off - TIMER2) as u8),
_ => self.mem[off],
}
}
pub fn write(&mut self, io: &mut IoRegisters, offset: u32, nibble: u8) {
let off = offset as usize % SIZE;
let v = nibble & 0xF;
match off {
CRC_BASE..=0x307 => io.set_crc_nibble(off - CRC_BASE, v),
LPD => {}
T1_CTRL => io.timers.write_t1_ctrl(v),
T2_CTRL => io.timers.write_t2_ctrl(v),
TIMER1 => io.timers.write_t1(v),
TIMER2..=0x3FF => io.timers.write_t2_nibble((off - TIMER2) as u8, v),
_ => self.mem[off] = v,
}
}
pub fn display_on(&self) -> bool {
self.mem[DSPCTL] & DON_BIT != 0
}
pub fn contrast(&self) -> u8 {
self.mem[CONTRAST] | ((self.mem[DSPCTL] >> 1) & 1) << 4
}
pub fn ram_nibble(&self, off: usize) -> u8 {
if off < REGS { self.mem[off] } else { 0 }
}
pub fn reset(&mut self) {
self.mem[REGS..].fill(0);
}
}