From f4f129a75208ccf5d6a19b1cb81c56d4d95fd61f Mon Sep 17 00:00:00 2001 From: Ben Bridle Date: Mon, 30 Sep 2024 12:28:24 +1300 Subject: Make Bedrock parametric over devices The core Bedrock struct is now parametric over individual Device structs, rather than over a single DeviceBus. This change was made so that devices can be implemented separately to one another. The implementation of the evaluate method has also been changed to make it potentially slightly more efficient, by replacing pop-then-push combinations with get operations. --- src/device_bus.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 11 deletions(-) (limited to 'src/device_bus.rs') diff --git a/src/device_bus.rs b/src/device_bus.rs index 38a1a24..aaa0717 100644 --- a/src/device_bus.rs +++ b/src/device_bus.rs @@ -1,19 +1,82 @@ use crate::*; -pub trait DeviceBus { - fn read_u8(&mut self, port: u8) -> u8; - fn write_u8(&mut self, value: u8, port: u8) -> Option; +pub trait Device { + fn read(&mut self, port: u8) -> u8; + fn write(&mut self, port: u8, value: u8) -> Option; + fn wake(&mut self) -> bool; +} + +impl Device for () { + fn read(&mut self, _: u8) -> u8 { 0 } + fn write(&mut self, _: u8, _: u8) -> Option { None } + fn wake(&mut self) -> bool { false } +} + + +pub struct DeviceBus { + pub dev_0: D0, + pub dev_1: D1, + pub dev_2: D2, + pub dev_3: D3, + pub dev_4: D4, + pub dev_5: D5, + pub dev_6: D6, + pub dev_7: D7, + pub dev_8: D8, + pub dev_9: D9, + pub dev_a: DA, + pub dev_b: DB, + pub dev_c: DC, + pub dev_d: DD, + pub dev_e: DE, + pub dev_f: DF, +} - fn read_u16(&mut self, port: u8) -> u16 { - let high = self.read_u8(port); - let low = self.read_u8(port.wrapping_add(1)); - u16::from_be_bytes([high, low]) +impl +DeviceBus { + pub fn read_u8(&mut self, port: u8) -> u8 { + match port & 0xf0 { + 0x00 => self.dev_0.read(port & 0x0f), + 0x10 => self.dev_1.read(port & 0x0f), + 0x20 => self.dev_2.read(port & 0x0f), + 0x30 => self.dev_3.read(port & 0x0f), + 0x40 => self.dev_4.read(port & 0x0f), + 0x50 => self.dev_5.read(port & 0x0f), + 0x60 => self.dev_6.read(port & 0x0f), + 0x70 => self.dev_7.read(port & 0x0f), + 0x80 => self.dev_8.read(port & 0x0f), + 0x90 => self.dev_9.read(port & 0x0f), + 0xA0 => self.dev_a.read(port & 0x0f), + 0xB0 => self.dev_b.read(port & 0x0f), + 0xC0 => self.dev_c.read(port & 0x0f), + 0xD0 => self.dev_d.read(port & 0x0f), + 0xE0 => self.dev_e.read(port & 0x0f), + 0xF0 => self.dev_f.read(port & 0x0f), + _ => unreachable!(), + } } - fn write_u16(&mut self, value: u16, port: u8) -> Option { - let [h, l] = value.to_be_bytes(); - self.write_u8(h, port); - self.write_u8(l, port.wrapping_add(1)) + pub fn write_u8(&mut self, port: u8, value: u8) -> Option { + match port & 0xf0 { + 0x00 => self.dev_0.write(port & 0x0f, value), + 0x10 => self.dev_1.write(port & 0x0f, value), + 0x20 => self.dev_2.write(port & 0x0f, value), + 0x30 => self.dev_3.write(port & 0x0f, value), + 0x40 => self.dev_4.write(port & 0x0f, value), + 0x50 => self.dev_5.write(port & 0x0f, value), + 0x60 => self.dev_6.write(port & 0x0f, value), + 0x70 => self.dev_7.write(port & 0x0f, value), + 0x80 => self.dev_8.write(port & 0x0f, value), + 0x90 => self.dev_9.write(port & 0x0f, value), + 0xA0 => self.dev_a.write(port & 0x0f, value), + 0xB0 => self.dev_b.write(port & 0x0f, value), + 0xC0 => self.dev_c.write(port & 0x0f, value), + 0xD0 => self.dev_d.write(port & 0x0f, value), + 0xE0 => self.dev_e.write(port & 0x0f, value), + 0xF0 => self.dev_f.write(port & 0x0f, value), + _ => unreachable!(), + } } } -- cgit v1.2.3-70-g09d2