diff options
Diffstat (limited to 'src/mem.rs')
-rwxr-xr-x | src/mem.rs | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/src/mem.rs b/src/mem.rs new file mode 100755 index 0000000..34d16c6 --- /dev/null +++ b/src/mem.rs @@ -0,0 +1,244 @@ +use std::sync::mpsc::SyncSender; + +use armv4t_emu::Memory; + +pub struct Mem<'m> { + pub inner: &'m mut [u8], + pub tx: SyncSender<Event>, +} + +impl<'m> Memory for Mem<'m> { + fn r8(&mut self, addr: u32) -> u8 { + self.special_addr(addr, false); + + self.inner[addr as usize] + } + + fn r16(&mut self, addr: u32) -> u16 { + self.special_addr(addr, false); + + u16::from_be_bytes([self.inner[addr as usize], self.inner[addr as usize + 1]]) + } + + fn r32(&mut self, addr: u32) -> u32 { + self.special_addr(addr, false); + + u32::from_be_bytes([ + self.inner[addr as usize], + self.inner[addr as usize + 1], + self.inner[addr as usize + 2], + self.inner[addr as usize + 3], + ]) + } + + fn w8(&mut self, addr: u32, val: u8) { + self.special_addr(addr, true); + + self.inner[addr as usize] = val; + } + + fn w16(&mut self, addr: u32, val: u16) { + self.special_addr(addr, true); + + let bytes = val.to_be_bytes(); + self.inner[addr as usize] = bytes[0]; + self.inner[addr as usize + 1] = bytes[1]; + } + + fn w32(&mut self, addr: u32, val: u32) { + self.special_addr(addr, true); + + let bytes = val.to_be_bytes(); + self.inner[addr as usize] = bytes[0]; + self.inner[addr as usize + 1] = bytes[1]; + self.inner[addr as usize + 2] = bytes[2]; + self.inner[addr as usize + 3] = bytes[3]; + } +} + +impl<'m> Mem<'m> { + const IO: u32 = 0x00020000; + const IO_END: u32 = 0x000200FF; + + pub const CTSI_ASIC_WATCHDOG: usize = Self::IO as usize | 0x03; + pub const CTSI_IRQ_LINES: usize = Self::IO as usize | 0x09; + pub const CTSI_CLOCK_CONTROL: usize = Self::IO as usize | 0x0D; + + pub const CCONT_WRITE: usize = Self::IO as usize | 0x2C; + pub const GENSIO_START_TRANSACTION: usize = Self::IO as usize | 0x2D; + pub const UIF_CTRL_IO_2: usize = Self::IO as usize | 0x32; + pub const CCONT_READ: usize = Self::IO as usize | 0x6C; + pub const GENSIO_STATUS: usize = Self::IO as usize | 0x6D; + pub const GENSIO_LCD_CTRL: usize = Self::IO as usize | 0x6E; + + pub fn set_gensio_status(&mut self, state: GensioState) { + let byte = &mut self.inner[Self::GENSIO_STATUS]; + + match state { + GensioState::DataWrite => *byte |= 1, + GensioState::TransactionReady => *byte |= 2, + GensioState::DataRead => *byte |= 5, + } + } + + pub fn gensio_status_clear(&mut self) { + self.inner[Self::GENSIO_STATUS] = 0x00; + } + + fn special_addr(&mut self, addr: u32, write: bool) { + if (Self::IO..=Self::IO_END).contains(&addr) { + self.special_io(addr, write) + } + } + + fn special_io(&mut self, addr: u32, write: bool) { + let io_addr = addr ^ Self::IO; + + let meaning = match io_addr { + // 00-3F + 0x00 => "ASIC Version", + 0x01 => "MCU reset control register", + 0x02 => "DSP reset control register", + + 0x03 => { + self.tx.send(Event::Ctsi(Ctsi::AsicWatchdog)).unwrap(); + + "CTSI ASIC Watchdog Write Register" + } + 0x0A => "CTSI FIQ lines mask", + 0x0B => "CTSI IRQ lines mask ", + 0x0D => { + self.tx.send(Event::Ctsi(Ctsi::WriteClockControl)).unwrap(); + + "CTSI Clock Control Register" + } + 0x20 => "McuGenIO Signal Lines", + 0x28 => "Keyboard ROW signal lines", + 0x2A => "Keyboard COL signal lines", + 0x2C => { + self.tx.send(Event::GenSIO(GenSIO::CContWrite)).unwrap(); + + "CCont write" + } + 0x2D => { + self.tx + .send(Event::GenSIO(GenSIO::StartTransaction)) + .unwrap(); + + "GENSIO start transaction" + } + 0x2E => "GENSIO LCD data write", + 0x32 => { + self.tx.send(Event::Uif(Uif::CtrlIo2)).unwrap(); + + "UIF CTRL IO 2" + } + addr if addr >= 0x36 && addr <= 0x3F => "SIM something [0x36 to 0x3F]", + + // 40-7F + 0x6B => "Keyboard COL interrupt mask", + 0x6C => "CCont read", + 0x6D => { + self.gensio_status(); + "GENSIO status" + } + 0x6E => { + self.tx.send(Event::GenSIO(GenSIO::LcdCtrl)).unwrap(); + + "GENSIO LCD Ctrl" + } + 0x6F => "GENSIO - 3/SELECT1", + 0x70 => "CTRL I/O Direction 0,1", + 0x71 => "CTRL I/O Direction 1,1", + 0x72 => "CTRL I/O Direction 2,1", + 0x73 => "CTRL I/O Direction 3,1", + + //80-BF + 0xA8 => "Keyboard ROW I/O direction", + 0xAD => "GENSIO - 1/SELECT2", + 0xAE => "GENSIO - 2/SELECT2", + 0xAF => "GENSIO - 3/SELECT2", + 0xB0 => "CTRL I/O Direction 0,2", + 0xB1 => "CTRL I/O Direction 1,2", + 0xB2 => "CTRL I/O Direction 2,2", + 0xB3 => "CTRL I/O Direction 3,2", + + //C0-FF + 0xED => "GENSIO - 1/SELECT3", + 0xEE => "GENSIO - 2/SELECT3", + 0xEF => "GENSIO - 3/SELECT3", + 0xF0 => "CTRL I/O Input 0", + 0xF1 => "CTRL I/O Input 1", + 0xF2 => "CTRL I/O Input 2", + 0xF3 => "CTRL I/O Input 3", + + _ => "unknown IO", + }; + + let read_write = if write { "w" } else { "r" }; + + log::info!("IO {read_write} [{io_addr:02X}] - {meaning}"); + } + + fn gensio_status(&mut self) { + let base = (Self::IO | 0x2D) as usize; + let ctrl_io_dir_1 = self.inner[base]; + log::info!("CTRL Start Transaction -- {:08b}", ctrl_io_dir_1); + + log::info!("GENSIO Status -- {:08b}", self.inner[Self::GENSIO_STATUS]); + + self.print_ctrl_io_direction_1(); + self.print_ctrl_io_direction_2(); + } + + fn print_ctrl_io_direction_1(&self) { + let base = (Self::IO | 0x70) as usize; + let ctrl_io_dir_1 = &self.inner[base..base + 4]; + log::info!( + "CTRL I/O Direction (1) -- {:08b} {:08b} {:08b} {:08b}", + ctrl_io_dir_1[0], + ctrl_io_dir_1[1], + ctrl_io_dir_1[2], + ctrl_io_dir_1[3] + ); + } + + fn print_ctrl_io_direction_2(&self) { + let base = (Self::IO | 0xB0) as usize; + let ctrl_io_dir_1 = &self.inner[base..base + 4]; + log::info!( + "CTRL I/O Direction (2) -- {:08b} {:08b} {:08b} {:08b}", + ctrl_io_dir_1[0], + ctrl_io_dir_1[1], + ctrl_io_dir_1[2], + ctrl_io_dir_1[3] + ); + } +} + +pub enum GensioState { + DataWrite, + TransactionReady, + DataRead, +} + +pub enum Event { + GenSIO(GenSIO), + Ctsi(Ctsi), + Uif(Uif), +} + +pub enum GenSIO { + StartTransaction, + CContWrite, + LcdCtrl, +} + +pub enum Ctsi { + AsicWatchdog, + WriteClockControl, +} + +pub enum Uif { + CtrlIo2, +} |