about summary refs log tree commit diff
path: root/src/mem.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem.rs')
-rwxr-xr-xsrc/mem.rs244
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,
+}