diff --git a/Cargo.lock b/Cargo.lock index 263a8b5..1470c39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -497,14 +497,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "beneater" -version = "0.1.0" -dependencies = [ - "core", - "macroquad 0.4.14", -] - [[package]] name = "bit-set" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index d7dfc39..ff22a3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [ "core", "cli", "macroquad", - "beneater" +# "beneater" ] resolver="2" diff --git a/beneater/src/parts/backplane.rs b/beneater/src/parts/backplane.rs index d11f0cf..ecb091e 100644 --- a/beneater/src/parts/backplane.rs +++ b/beneater/src/parts/backplane.rs @@ -1,7 +1,7 @@ use crate::parts::mos6522_peripheral::Mos6522Peripheral; use crate::parts::via6522::VIA6522; use core::constants::constants_system::*; -use core::mos6502cpu::cpu::Mos6502Cpu; +use core::mos6502cpu::Mos6502Cpu; use core::periph::at28c256::At28C256; use core::traits::rom_chip::RomChip; use core::constants::constants_via6522::*; diff --git a/cli/src/bin/kim1.rs b/cli/src/bin/kim1.rs index eec3ada..481a05a 100644 --- a/cli/src/bin/kim1.rs +++ b/cli/src/bin/kim1.rs @@ -1,5 +1,5 @@ use core::computers::kim1::Kim1; - +use core::constants::constants_system::*; fn main() { println!("Taxation is theft."); diff --git a/cli/src/bin/ram_rom.rs b/cli/src/bin/ram_rom.rs index 89fdd1d..d25cfef 100644 --- a/cli/src/bin/ram_rom.rs +++ b/cli/src/bin/ram_rom.rs @@ -1,4 +1,4 @@ -use core::computers::ram_rom::backplane::RamRomComputer; +use core::computers::ram_rom::RamRomComputer; use core::traits::backplane::Backplane; use std::fs; diff --git a/cli/src/bin/ticker.rs b/cli/src/bin/ticker.rs deleted file mode 100644 index 160d067..0000000 --- a/cli/src/bin/ticker.rs +++ /dev/null @@ -1,5 +0,0 @@ -use core::mos6502cpu::cpu::Mos6502Cpu; - -fn main() { - let x = Mos6502Cpu::default(); -} diff --git a/core/src/computers/beneater/backplane.rs b/core/src/computers/beneater/backplane.rs new file mode 100644 index 0000000..5942fc9 --- /dev/null +++ b/core/src/computers/beneater/backplane.rs @@ -0,0 +1,52 @@ +use crate::computers::beneater::BenEater; +use crate::traits::backplane::Backplane; + +impl Backplane for BenEater { + fn data_bus(&self) -> u8 { + self.data_bus + } + + fn address_bus(&self) -> u16 { + self.address_bus + } + + fn read_mode(&self) -> bool { + self.read_mode + } + + fn set_read_mode(&mut self, new_mode: bool) { + self.read_mode = new_mode + } + + fn set_data_bus(&mut self, new_value: u8) { + self.data_bus = new_value + } + + fn set_address_bus(&mut self, new_value: u16) { + self.address_bus = new_value + } + + fn tick(&mut self) { + println!("Tick the system."); + + self.tick_ram(self.address_bus, self.data_bus, true, true, true); + self.tick_rom(self.address_bus, true, true); + self.tick_via(self.address_bus, self.data_bus, true, true, self.read_mode, true, true); + } + + fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) -> u8 { + println!("Ticking RAM"); + 0x00 + } + + fn tick_rom(&mut self, address: u16, cs: bool, oe: bool) -> u8 { + println!("Ticking ROM"); + 0x00 + } + + fn tick_via(&mut self, address: u16, data: u8, cs0: bool, cs1: bool, rw: bool, rs0: bool, rs1: bool) -> (u8, bool, bool) { + println!("Ticking VIA 6522"); + let (new_address, new_data) = self.via.tick(self.address_bus, self.data_bus, false, self.read_mode); + (new_data, false, false) + } +} \ No newline at end of file diff --git a/core/src/computers/beneater/beneater.rs b/core/src/computers/beneater/beneater.rs deleted file mode 100644 index e69de29..0000000 diff --git a/core/src/computers/beneater/mod.rs b/core/src/computers/beneater/mod.rs index 0188360..880b0d6 100644 --- a/core/src/computers/beneater/mod.rs +++ b/core/src/computers/beneater/mod.rs @@ -1 +1,12 @@ -pub mod beneater; +mod backplane; + +use crate::mos6502cpu::Mos6502Cpu; +use crate::periph::mos6522::mos6522::Mos6522; + +pub struct BenEater { + cpu: Mos6502Cpu, + via: Mos6522, + data_bus: u8, + address_bus: u16, + read_mode: bool +} diff --git a/core/src/computers/kim1/mod.rs b/core/src/computers/kim1/mod.rs index 2b4a0c5..2c43c07 100644 --- a/core/src/computers/kim1/mod.rs +++ b/core/src/computers/kim1/mod.rs @@ -2,14 +2,9 @@ pub mod new; pub mod tick; pub mod reset; -use std::fs; -use std::path::Path; -use crate::constants::constants_system::SIZE_1KB; use crate::mos6502cpu::Mos6502Cpu; -use crate::periph::at28c256::At28C256; use crate::periph::hm62256::Hm62256; use crate::periph::kim1_keypad::Kim1Keypad; -use crate::periph::mos6522::mos6522::Mos6522; use crate::periph::mos6530::mos6530::Mos6530; /// Represents a KIM-1 diff --git a/core/src/computers/mod.rs b/core/src/computers/mod.rs index 80916a1..f5d33eb 100644 --- a/core/src/computers/mod.rs +++ b/core/src/computers/mod.rs @@ -2,3 +2,4 @@ pub mod beneater; pub mod rom_only; pub mod kim1; pub mod ram_rom; +pub mod tim1; diff --git a/core/src/computers/ram_rom/backplane.rs b/core/src/computers/ram_rom/backplane.rs index 2017e73..75d31e6 100644 --- a/core/src/computers/ram_rom/backplane.rs +++ b/core/src/computers/ram_rom/backplane.rs @@ -1,9 +1,9 @@ +use log::debug; use crate::computers::ram_rom::RamRomComputer; use crate::periph::at28c256::At28C256; use crate::traits::backplane::Backplane; use crate::periph::hm62256::Hm62256; - impl Backplane for RamRomComputer { fn data_bus(&self) -> u8 { self.data_bus @@ -45,7 +45,7 @@ impl Backplane for RamRomComputer { 0x4000..=0x7fff => { // ROM println!("ADDRESSING ROM"); - let (rom_address_bus, rom_data_bus) = self.rom.tick(self.address_bus, self.data_bus, self.read_mode); + let rom_data_bus = self.rom.signal_tick(self.address_bus, self.data_bus, true, true, true); self.data_bus = rom_data_bus; } _ => { @@ -54,16 +54,19 @@ impl Backplane for RamRomComputer { } } - fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) { - todo!() + fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) -> u8 { + debug!("Ticking ram with A${address:04x} D${data:02x} CS:{cs} OE:{oe} WE:{we}"); + 0 } - fn tick_rom(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) -> (u8) { - todo!() + fn tick_rom(&mut self, address: u16, cs: bool, oe: bool) -> u8 { + debug!("Ticking rom with A${address:04x} CS:{cs} OE:{oe}"); + 0 } - fn tick_via(&mut self, address: u16, data: u8, cs: bool, rw: bool, ce: bool) -> (u8, u8, bool) { - todo!() + fn tick_via(&mut self, address: u16, data: u8, cs0: bool, cs1: bool, rw: bool, rs0: bool, rs1: bool) -> (u8, bool, bool) { + debug!("Ticking Via with A${address:04x} D${data:02x} cs0:{cs0} cs1:{cs1} rw:{rw} rs0:{rs0} rs1:{rs1}"); + (0, false, false) } } diff --git a/core/src/computers/ram_rom/tick2.rs b/core/src/computers/ram_rom/tick2.rs index e314cdf..21aec55 100644 --- a/core/src/computers/ram_rom/tick2.rs +++ b/core/src/computers/ram_rom/tick2.rs @@ -44,7 +44,7 @@ impl RamRomComputer { } _ => {} }; - let (_, rom_data_bus) = self.rom.tick(address, data, control == 1); + let rom_data_bus = self.rom.signal_tick(self.address_bus ,self.data_bus, true ,true , true); let (_, ram_data_bus) = self.ram.tick(address, data, control == 1, true); 0 } diff --git a/core/src/computers/rom_only/backplane.rs b/core/src/computers/rom_only/backplane.rs index 92f8b12..b7a7d2d 100644 --- a/core/src/computers/rom_only/backplane.rs +++ b/core/src/computers/rom_only/backplane.rs @@ -17,27 +17,29 @@ impl Backplane for RomOnlyComputer { } fn tick(&mut self) { - println!("COMPUTER: Preparing to tick."); +// println!("COMPUTER: Preparing to tick."); // do are we being addressed? - println!("COMPUTER: BUSSES PRE: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode); - let (new_addr, new_data) = self.rom.tick(self.address_bus, self.data_bus, self.read_mode); - self.set_address_bus(new_addr); +// println!("COMPUTER: BUSSES PRE: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode); + let new_data = self.rom.signal_tick(self.address_bus, self.data_bus, true, true, true); + // tick(self.address_bus, self.data_bus, self.read_mode); + self.set_address_bus(self.address_bus); self.set_data_bus(new_data); - println!("COMPUTER: BUSSES POST: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode); - println!("COMPUTER: Done ticking."); +// println!("COMPUTER: BUSSES POST: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode); +// println!("COMPUTER: Done ticking."); } - fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) { + fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) -> u8 { debug!("This system has no ram. ROM only."); + 0x00 } - fn tick_rom(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) -> (u8) { - let (_, data) = self.rom.tick(address, data, true); - data + fn tick_rom(&mut self, address: u16, cs: bool, oe: bool) -> u8 { + let data = self.rom.signal_tick(address, self.data_bus, cs, oe, true); + data } - fn tick_via(&mut self, address: u16, data: u8, cs: bool, rw: bool, ce: bool) -> (u8, u8, bool) { - debug!("This system has no VIA controllers. ROM only"); - (0,0,true) + fn tick_via(&mut self, address: u16, data: u8, cs0: bool, cs1: bool, rw: bool, rs0: bool, rs1: bool) -> (u8, bool, bool) { + debug!("This system has no VIA controllers. ROM only"); + (0,false,false) } } diff --git a/core/src/computers/rom_only/mod.rs b/core/src/computers/rom_only/mod.rs index d548820..db2c083 100644 --- a/core/src/computers/rom_only/mod.rs +++ b/core/src/computers/rom_only/mod.rs @@ -19,7 +19,7 @@ impl RomOnlyComputer { // tick the parts... println!("WIDETICK: A:${address:04x} D:${data:02x} C:b{control:08b}"); - let (_, new_data) = self.rom.tick(address, data, control == 0x01); + let new_data = self.rom.signal_tick(self.address_bus, self.data_bus, true, true, true); println!("\nNew Data : {new_data:02x}"); self.set_data_bus(new_data); new_data diff --git a/core/src/computers/tim1/mod.rs b/core/src/computers/tim1/mod.rs new file mode 100644 index 0000000..d6710aa --- /dev/null +++ b/core/src/computers/tim1/mod.rs @@ -0,0 +1,8 @@ +use crate::mos6502cpu::Mos6502Cpu; +use crate::periph::mos6530::mos6530::Mos6530; + +pub struct Tim1 { + cpu: Mos6502Cpu, + pia: Mos6530 +} + diff --git a/core/src/constants/constants_via6522.rs b/core/src/constants/constants_via6522.rs index 1286151..73df2d5 100644 --- a/core/src/constants/constants_via6522.rs +++ b/core/src/constants/constants_via6522.rs @@ -17,4 +17,3 @@ pub const VIA6522_ACR: u8 = 0b1100; pub const VIA6522_PCR: u8 = 0b1101; pub const VIA6522_IFR: u8 = 0b1110; pub const VIA6522_IER: u8 = 0b1111; - diff --git a/core/src/mos6502cpu/bus_device.rs b/core/src/mos6502cpu/bus_device.rs index f001eb1..ae089be 100644 --- a/core/src/mos6502cpu/bus_device.rs +++ b/core/src/mos6502cpu/bus_device.rs @@ -2,6 +2,12 @@ use crate::mos6502cpu::Mos6502Cpu; use crate::traits::bus_device::BusDevice; impl BusDevice for Mos6502Cpu { + fn min_offset(&self) -> u16 { 0 } + + fn max_offset(&self) -> u16 { + 0x7fff + } + fn address_bus(&self) -> u16 { self.address_bus } @@ -18,7 +24,4 @@ impl BusDevice for Mos6502Cpu { self.data_bus = new_value; } - fn talking_to_me(&self, address: u16) -> bool { - todo!() - } } \ No newline at end of file diff --git a/core/src/periph/at28c256/blocks.rs b/core/src/periph/at28c256/blocks.rs index 9d754d1..4e744cb 100644 --- a/core/src/periph/at28c256/blocks.rs +++ b/core/src/periph/at28c256/blocks.rs @@ -6,32 +6,3 @@ impl At28C256 { self.data.chunks(size) } } - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn smoke() { assert!(true); } - - #[test] - fn full_chunks_come_back_ok() { - let test_data = (0..255).collect(); - let mut chip = At28C256::new(0x0000, 0x3fff, test_data); - - let chunks = chip.chunks(16); - assert_eq!(chunks.len(), 16); - } - - #[test] - fn partial_blocks_come_back_ok() { - let test_data = (0..=3).collect(); - let mut chip = At28C256::new(0x0000, 0x3fff, test_data); - - let chunks = chip.chunks(16); - assert_eq!(chunks.len(), 1); - for chunk in chunks { - assert_eq!(chunk.len(), 4); - } - } -} diff --git a/core/src/periph/at28c256/bus_device.rs b/core/src/periph/at28c256/bus_device.rs new file mode 100644 index 0000000..c6d91a2 --- /dev/null +++ b/core/src/periph/at28c256/bus_device.rs @@ -0,0 +1,28 @@ +use crate::periph::at28c256::At28C256; +use crate::traits::bus_device::BusDevice; + +impl BusDevice for At28C256 { + fn min_offset(&self) -> u16 { + self.offset + } + + fn max_offset(&self) -> u16 { + self.max_offset + } + + fn address_bus(&self) -> u16 { + self.address_bus + } + + fn data_bus(&self) -> u8 { + self.data_bus + } + + fn set_address_bus(&mut self, new_value: u16) { + self.address_bus = new_value + } + + fn set_data_bus(&mut self, new_value: u8) { + self.data_bus = new_value + } +} diff --git a/core/src/periph/at28c256/checksum.rs b/core/src/periph/at28c256/checksum.rs index e3298dc..55a3aa8 100644 --- a/core/src/periph/at28c256/checksum.rs +++ b/core/src/periph/at28c256/checksum.rs @@ -16,66 +16,3 @@ impl At28C256 { } } -#[cfg(test)] -mod test { - use std::fs; - use std::path::Path; - use crate::constants::constants_system::SIZE_1KB; - use crate::traits::memory_chip::MemoryChip; - use crate::traits::rom_chip::RomChip; - use super::*; - - #[test] - fn smoke() { assert!(true); } - - #[test] - fn programmed_data_reads_back_same() { - let mut data = At28C256::default(); - for i in 0..SIZE_32KB { - data.data[i] = 0xeau8; - } - for offset in 0..SIZE_32KB { - if offset.is_multiple_of(SIZE_1KB) {}; - assert_eq!(0xea, data.read(&(offset as u16))); - } - } - - #[test] - fn checksums_calculate_correctly_for_zero() { - let data1 = [0x00u8; SIZE_32KB]; - assert_eq!(0x00, At28C256::checksum_static(&data1)); - } - - #[test] - fn checksums_calculate_for_1_byte() { - let data = [0xff; 1]; - assert_eq!(0xff, At28C256::checksum_static(&data)); - } - - #[test] - fn checksums_calculate_for_2_bytes() { - let data = [0xff; 2]; - // 0xff + 0xff = 0x1fe - assert_eq!(0xfe, At28C256::checksum_static(&data)); - } - - #[test] - fn checksums_calculate_for_first_80_bytes() { - println!("STARTING TEST"); - let mut checksum = 0x00; - - let path = format!("{}{}", TEST_PERIPH_AT28C256_ROOT, "/checksum.bin"); - println!("READING [{path}]"); - let data = fs::read(path); - match data { - Ok(bytes) => { - println!("Read {} bytes", bytes.len()); - checksum = At28C256::checksum_static(&bytes); - println!("Checksum: 0x{:02x}", checksum); - } - Err(e) => eprintln!("Failed to read file: {}", e), - } - assert_eq!(0x58, checksum); - println!("TEST COMPLETE"); - } -} diff --git a/core/src/periph/at28c256/default.rs b/core/src/periph/at28c256/default.rs index 018161e..f84bd92 100644 --- a/core/src/periph/at28c256/default.rs +++ b/core/src/periph/at28c256/default.rs @@ -21,13 +21,3 @@ impl Default for At28C256 { } } } - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn smoke() { - assert!(true); - } -} diff --git a/core/src/periph/at28c256/memory_chip.rs b/core/src/periph/at28c256/memory_chip.rs new file mode 100644 index 0000000..c536c6e --- /dev/null +++ b/core/src/periph/at28c256/memory_chip.rs @@ -0,0 +1,16 @@ +use log::debug; +use crate::periph::at28c256::At28C256; +use crate::traits::bus_device::BusDevice; +use crate::traits::memory_chip::MemoryChip; + +impl MemoryChip for At28C256 { + /// read + /// + /// Reads a byte from memory. + /// Returns a 0x00 if there is no data at that location but is still in ROM address range + fn read(&self, offset: &u16) -> u8 { + let effective = self.internal_address(*offset); + debug!("STARTING READ FROM At28C256 ${:04x} | ${:04x} / ${effective:04x} | ${:04x}", self.offset, offset, self.max_offset); + if effective >= self.data.len() as u16 { 0x00 } else { self.data[effective as usize] } + } +} \ No newline at end of file diff --git a/core/src/periph/at28c256/mod.rs b/core/src/periph/at28c256/mod.rs index 745ad39..588c999 100644 --- a/core/src/periph/at28c256/mod.rs +++ b/core/src/periph/at28c256/mod.rs @@ -1,6 +1,5 @@ pub mod default; pub mod rom_chip; -pub mod tick; pub mod new; pub mod program; pub mod dump; @@ -8,9 +7,9 @@ pub mod checksum; pub mod blocks; pub mod control; pub mod signal_tick; +pub mod memory_chip; +pub mod bus_device; -use crate::traits::rom_chip::RomChip; -use std::io::Read; /// At28C256 /// @@ -31,3 +30,152 @@ pub struct At28C256 { we: bool, oe: bool } + +#[cfg(test)] +mod test { + use crate::traits::rom_chip::RomChip; + use std::io::Read; + use std::fs; + use crate::constants::constants_system::*; + use crate::constants::constants_test::*; + use crate::periph::at28c256::At28C256; + use crate::traits::bus_device::BusDevice; + use crate::traits::memory_chip::MemoryChip; + + #[test] + fn smoke() { assert!(true); } + + #[test] + fn checksum_binary_loads() { + let path = format!("{}/{}", TEST_PERIPH_AT28C256_ROOT, "checksum.bin"); + let bytes = match fs::read(path) { + Ok(bytes) => { + println!("Read {} bytes.", bytes.len()); + bytes + }, + Err(e) => { + eprintln!("FAIL to read rom."); + panic!("No rom no run."); + } + }; + + let mut rom = At28C256::new(0x0000, 0x3fff, bytes); + + assert_eq!(rom.checksum(), 0x58); + } + + #[test] + fn full_chunks_come_back_ok() { + let test_data = (0..255).collect(); + let mut chip = At28C256::new(0x0000, 0x3fff, test_data); + + let chunks = chip.chunks(16); + assert_eq!(chunks.len(), 16); + } + + #[test] + fn partial_blocks_come_back_ok() { + let test_data = (0..=3).collect(); + let mut chip = At28C256::new(0x0000, 0x3fff, test_data); + + let chunks = chip.chunks(16); + assert_eq!(chunks.len(), 1); + for chunk in chunks { + assert_eq!(chunk.len(), 4); + } + } + + + #[test] + fn programmed_data_reads_back_same() { + let mut data = At28C256::default(); + for i in 0..SIZE_32KB { + data.data[i] = 0xeau8; + } + for offset in 0..(SIZE_32KB - 1) { + assert_eq!(0xea, data.read(&(offset as u16))); + } + } + + #[test] + fn checksums_calculate_correctly_for_zero() { + let data1 = [0x00u8; SIZE_32KB]; + assert_eq!(0x00, At28C256::checksum_static(&data1)); + } + + #[test] + fn checksums_calculate_for_1_byte() { + let data = [0xff; 1]; + assert_eq!(0xff, At28C256::checksum_static(&data)); + } + + #[test] + fn checksums_calculate_for_2_bytes() { + let data = [0xff; 2]; + // 0xff + 0xff = 0x1fe + assert_eq!(0xfe, At28C256::checksum_static(&data)); + } + + #[test] + fn checksums_calculate_for_first_80_bytes() { + println!("STARTING TEST"); + let mut checksum = 0x00; + + let path = format!("{}{}", TEST_PERIPH_AT28C256_ROOT, "/checksum.bin"); + println!("READING [{path}]"); + let data = fs::read(path); + match data { + Ok(bytes) => { + println!("Read {} bytes", bytes.len()); + checksum = At28C256::checksum_static(&bytes); + println!("Checksum: 0x{:02x}", checksum); + } + Err(e) => eprintln!("Failed to read file: {}", e), + } + assert_eq!(0x58, checksum); + println!("TEST COMPLETE"); + } + + #[test] + fn address_data_set_reads() { + let mut x = At28C256::new(0x0000, 0x3fff, vec![0xea; SIZE_32KB]); + + // set both... + x.set_address_bus(0x3000); + x.set_data_bus(0xab); + assert_eq!(0xab, x.data_bus()); + assert_eq!(0x3000, x.address_bus()); + + // ...set address... + x.set_address_bus(0x2000); + assert_eq!(0x2000, x.address_bus()); + assert_eq!(0xab, x.data_bus()); + + // ...set data. + x.set_data_bus(0xba); + assert_eq!(0xba, x.data_bus()); + assert_eq!(0x2000, x.address_bus()); + } + + fn programming_chip_changes_contents() { + let mut chip = At28C256::new(0x0000, 0x3fff, vec![]); + + assert_eq!(0x00, chip.read(&0x0000)); + + let new_data: Vec = vec![0xff, 0xff, 0xff, 0xff]; + chip.program(new_data.into()); + assert_eq!(0xff, chip.read(&0x0000)); + assert_eq!(0x00, chip.read(&0x05)); + } + + #[test] + fn correct_flags_required() { + let mut chip = At28C256::new(0x0000, 0x3fff, vec![0xff]); + assert_eq!(0xab, chip.signal_tick(0x0000, 0xab, false, true, true)); + assert_eq!(0xab, chip.signal_tick(0x0000, 0xab, true, true, false)); + assert_eq!(0xab, chip.signal_tick(0x0000, 0xab, false, true, false)); + assert_eq!(0xff, chip.signal_tick(0x0000, 0xab, true, true, true)); + assert_eq!(0xab, chip.signal_tick(0x0000, 0xab, true, false, true)); + } + +} diff --git a/core/src/periph/at28c256/program.rs b/core/src/periph/at28c256/program.rs index cd835c6..3daf627 100644 --- a/core/src/periph/at28c256/program.rs +++ b/core/src/periph/at28c256/program.rs @@ -9,24 +9,3 @@ impl At28C256 { } } -#[cfg(test)] -mod test { - use crate::traits::memory_chip::MemoryChip; - use crate::traits::rom_chip::RomChip; - use super::*; - - #[test] - fn smoke() { assert!(true) } - - #[test] - fn programming_chip_changes_contents() { - let mut chip = At28C256::new(0x0000, 0x3fff, vec![]); - - assert_eq!(0x00, chip.read(&0x0000)); - - let new_data: Vec = vec![0xff, 0xff, 0xff, 0xff]; - chip.program(new_data.into()); - assert_eq!(0xff, chip.read(&0x0000)); - assert_eq!(0x00, chip.read(&0x05)); - } -} diff --git a/core/src/periph/at28c256/rom_chip.rs b/core/src/periph/at28c256/rom_chip.rs index d50002a..c50c137 100644 --- a/core/src/periph/at28c256/rom_chip.rs +++ b/core/src/periph/at28c256/rom_chip.rs @@ -1,29 +1,10 @@ +use log::debug; use crate::constants::constants_system::SIZE_32KB; use crate::periph::at28c256::At28C256; +use crate::traits::bus_device::BusDevice; use crate::traits::memory_chip::MemoryChip; use crate::traits::rom_chip::RomChip; -impl MemoryChip for At28C256 { - fn read(&self, offset: &u16) -> u8 { - /// read - /// - /// Reads a byte from memory. - /// Returns a 0x00 if there is no data at that location but is still in ROM address range - println!("STARTING READ FROM At28C256 ${:04x} | ${:04x} | ${:04x}", self.offset, offset, self.max_offset); - if offset < &self.offset || offset > &self.max_offset { - println!("Unable to read from ${offset:04x} as it it out of range."); - return 0x00; - } else { - println!("OK READ FROM GOOD AREA total len = {}", self.data.len()); - } - - if *offset >= self.data.len() as u16 { - 0x00 - } else { - self.data[*offset as usize] - } } -} - impl RomChip for At28C256 { /// program /// @@ -34,14 +15,4 @@ impl RomChip for At28C256 { working.data = new_data.to_vec().into_boxed_slice(); Box::new(working) } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn smoke() { - assert!(true); - } -} +} \ No newline at end of file diff --git a/core/src/periph/at28c256/signal_tick.rs b/core/src/periph/at28c256/signal_tick.rs index 685b6a4..650112d 100644 --- a/core/src/periph/at28c256/signal_tick.rs +++ b/core/src/periph/at28c256/signal_tick.rs @@ -31,21 +31,3 @@ impl At28C256 { result } } - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn smoke() { assert!(true) } - - #[test] - fn correct_flags_required() { - let mut chip = At28C256::new(0x0000, 0x3fff, vec![0xff]); - assert_eq!(0xab, chip.signal_tick(0x0000, 0xab, false, true, true)); - assert_eq!(0xab, chip.signal_tick(0x0000, 0xab, true, true, false)); - assert_eq!(0xab, chip.signal_tick(0x0000, 0xab, false, true, false)); - assert_eq!(0xff, chip.signal_tick(0x0000, 0xab, true, true, true)); - assert_eq!(0xab, chip.signal_tick(0x0000, 0xab, true, false, true)); - } -} diff --git a/core/src/periph/at28c256/tick.rs b/core/src/periph/at28c256/tick.rs deleted file mode 100644 index 5e978ee..0000000 --- a/core/src/periph/at28c256/tick.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::constants::constants_system::SIZE_32KB; -use crate::periph::at28c256::At28C256; -use crate::periph::hm62256::Hm62256; - -impl At28C256 { - fn talking_to_me(&self, address: u16) -> bool { - //println!("Checking on {address:04x} in range of {:04x} {:04x}", self.offset, self.max_offset); - address >= self.offset && address < self.max_offset - } - - - - pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) { - println!("At28C256: Tick starting for A${address_bus:04x} D${data_bus:02x} R{read_mode}"); - - // we aren't being addressed - // OR - // we arent reading from the ROM... - if !self.talking_to_me(address_bus) || - !read_mode { - // ...go away. - return (address_bus, data_bus) - } - - // print!("At28C256 tick for me."); - let effective = address_bus - self.offset; - if effective < self.max_offset { - if effective < self.data.len() as u16 { - self.data_bus = self.data[effective as usize]; - } else { - self.data_bus = 0x00; - } - } else { - println!("At28C256: OUTSIDE RANGE. :("); - return (address_bus, data_bus) - } - - // print!("At28C256: Read... {:02x}", self.data_bus); - (address_bus, self.data_bus) - } -} - -#[cfg(test)] -mod test { - use std::fs; - use crate::traits::rom_chip::RomChip; - use super::*; - - #[test] - fn smoke() { assert!(true); } - - #[test] - fn checksum_binary_loads() { - let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin"; - let bytes = match fs::read(path) { - Ok(bytes) => { - println!("Read {} bytes.", bytes.len()); - bytes - }, - Err(e) => { - eprintln!("FAIL to read rom."); - panic!("No rom no run."); - vec![] - } - }; - - let mut rom = At28C256::new(0x0000, 0x3fff, bytes); - - assert_eq!(rom.checksum(), 0x58); - } -} \ No newline at end of file diff --git a/core/src/periph/hm62256/default.rs b/core/src/periph/hm62256/default.rs index 46bf649..a95f7df 100644 --- a/core/src/periph/hm62256/default.rs +++ b/core/src/periph/hm62256/default.rs @@ -9,6 +9,7 @@ impl Default for Hm62256 { boxed_slice.try_into().expect("Unable to box the ram"); Hm62256 { offset: 0x0000, + max_offset: 0x2000, data: boxed_array, address_bus: 0x0000, data_bus: 0x00, diff --git a/core/src/periph/hm62256/mod.rs b/core/src/periph/hm62256/mod.rs index 775af1b..2661f6e 100644 --- a/core/src/periph/hm62256/mod.rs +++ b/core/src/periph/hm62256/mod.rs @@ -18,6 +18,7 @@ use log::debug; /// 32KByte pub struct Hm62256 { pub(crate) offset: u16, + pub(crate) max_offset: u16, pub(crate) data: Box<[u8]>, pub(crate) address_bus: u16, pub(crate) data_bus: u8, diff --git a/core/src/periph/hm62256/new.rs b/core/src/periph/hm62256/new.rs index 2b0af21..89fb56c 100644 --- a/core/src/periph/hm62256/new.rs +++ b/core/src/periph/hm62256/new.rs @@ -5,6 +5,7 @@ impl Hm62256 { pub fn new(base_offset: u16) -> Self { Self { offset: base_offset, + max_offset: base_offset + SIZE_32KB as u16, data: vec![0; SIZE_32KB].into_boxed_slice(), address_bus: 0x0000, data_bus: 0x00, diff --git a/core/src/periph/hm62256/ramchip.rs b/core/src/periph/hm62256/ramchip.rs index 9c29eca..602dbb4 100644 --- a/core/src/periph/hm62256/ramchip.rs +++ b/core/src/periph/hm62256/ramchip.rs @@ -1,7 +1,35 @@ use crate::constants::constants_system::SIZE_32KB; use crate::periph::hm62256::Hm62256; +use crate::traits::bus_device::BusDevice; use crate::traits::ram_chip::RamChip; +impl BusDevice for Hm62256 { + fn min_offset(&self) -> u16 { + self.offset + } + + fn max_offset(&self) -> u16 { + self.max_offset + } + + fn address_bus(&self) -> u16 { + self.address_bus + } + + fn data_bus(&self) -> u8 { + self.data_bus + } + + fn set_address_bus(&mut self, new_value: u16) { + self.address_bus = new_value + } + + fn set_data_bus(&mut self, new_value: u8) { + self.data_bus = new_value + } + +} + impl RamChip for Hm62256 { fn write(&mut self, offset: &u16, value: &u8) { let effective = *offset as i32 % SIZE_32KB as i32; diff --git a/core/src/periph/mos6520/bus_device.rs b/core/src/periph/mos6520/bus_device.rs new file mode 100644 index 0000000..00bf416 --- /dev/null +++ b/core/src/periph/mos6520/bus_device.rs @@ -0,0 +1,26 @@ +use crate::periph::mos6520::Mos6520; +use crate::traits::bus_device::BusDevice; + +impl BusDevice for Mos6520 { + fn min_offset(&self) -> u16 { + self.offset + } + + fn max_offset(&self) -> u16 { self.max_offset } + + fn address_bus(&self) -> u16 { + self.address_bus + } + + fn data_bus(&self) -> u8 { + self.data_bus + } + + fn set_address_bus(&mut self, new_value: u16) { + self.address_bus = new_value + } + + fn set_data_bus(&mut self, new_value: u8) { + self.data_bus = new_value + } +} diff --git a/core/src/periph/mos6520/mod.rs b/core/src/periph/mos6520/mod.rs index 5694c24..04a4333 100644 --- a/core/src/periph/mos6520/mod.rs +++ b/core/src/periph/mos6520/mod.rs @@ -1,65 +1,51 @@ -mod tod; -mod reset; +pub mod reset; +pub mod bus_device; +pub mod via_chip; +pub mod new; +pub mod tick; +use crate::traits::bus_device::BusDevice; use crate::traits::memory_chip::MemoryChip; use crate::traits::ram_chip::RamChip; use crate::traits::rom_chip::RomChip; use crate::traits::via_chip::ViaChip; +/* +The MCS6520 Peripheral Adapter is designed to solve a broad range of peripheral +control problems in the implementation of microcomputer systems. This device allows +a very effective trade-off between software and hardware by providing significant +capability and flexibility in a low cost chip. When coupled with the power and +speed of the MCS6500 family of microprocessors, the MCS6S20 allows implementation +of very complex systems at a minimum overall cost. +Control of peripheral devices is handled primarily through two 8-bit bi-directional ports. + +Each of these lines can be programmed to act as either an input or +an output. In addition, four peripheral control/interrupt input lines are provided. +These lines can be used to interrupt the processor or for "hand-shaking" data +be tween the processor and a peripheral device. + */ pub struct Mos6520 { // Parallel ports A & B data registers port_a: u8, - port_b: u8, + out_a: u8, + in_a: u8, ddra: u8, + port_b: u8, + out_b: u8, + in_b: u8, ddrb: u8, - // Timer registers and control - tmr_a: u16, - latch_a: u16, - ctrl_a: u8, - tmr_b: u16, - latch_b: u16, - ctrl_b: u8, // Interrupt control register icr: u8, - // TOD clock raw BCD registers - tod_hours: u8, - tod_minutes: u8, - tod_seconds: u8, - tod_tenths: u8, - tod_frozen: bool, + // External Address and Data Bus + address_bus: u16, + data_bus: u8, + // Offsets + offset: u16, + max_offset: u16 } -impl RamChip for Mos6520 { - fn write(&mut self, offset: &u16, value: &u8) { - match offset & 0x0F { - 0x0 => { self.port_a = *value; } - 0x1 => { self.ddra = *value; } - 0x4 => { self.latch_a = (self.latch_a & 0xFF00) | *value as u16; } - 0x5 => { self.latch_a = (self.latch_a & 0x00FF) | ((*value as u16) << 8); } - 0x8..=0xB => { self.write_tod((offset & 0x03) as u8, *value); } - _ => {} - } +impl Mos6520 { + pub fn debug_dump(&self) { + println!("DUMPING STATE: \nPORT_A:\t{:08b}\nIN_A:\t{:08b}\nOUT_A:\t{:08b}\nDDRA:\t{:08b}", self.port_a, self.in_a, self.out_a, self.ddra); } } - -impl MemoryChip for Mos6520 { - fn read(&self, offset: &u16) -> u8 { - todo!() - } -} - -impl RomChip for Mos6520 { - fn program(new_data: &[u8]) -> Box { - todo!() - } -} - -impl ViaChip for Mos6520 { - fn set_port_ddr(&mut self, port_index: u8, value: u8) { - todo!() - } - - fn set_port_data(&mut self, port_index: u8, value: u8) { - todo!() - } -} \ No newline at end of file diff --git a/core/src/periph/mos6520/new.rs b/core/src/periph/mos6520/new.rs new file mode 100644 index 0000000..2c7e196 --- /dev/null +++ b/core/src/periph/mos6520/new.rs @@ -0,0 +1,21 @@ +use crate::periph::mos6520::Mos6520; + +impl Mos6520 { + pub fn new(start_offset: u16) -> Self { + Self { + port_a: 0, + out_a: 0, + port_b: 0, + out_b: 0, + ddra: 0, + ddrb: 0, + icr: 0, + address_bus: 0, + data_bus: 0, + offset: start_offset, + max_offset: start_offset + 4, + in_a: 0, + in_b: 0, + } + } +} diff --git a/core/src/periph/mos6520/reset.rs b/core/src/periph/mos6520/reset.rs index b2161b8..e8379a3 100644 --- a/core/src/periph/mos6520/reset.rs +++ b/core/src/periph/mos6520/reset.rs @@ -9,18 +9,6 @@ impl Mos6520 { self.port_b = 0x00; self.ddra = 0x00; self.ddrb = 0x00; - self.tmr_a = 0x00; - self.latch_a = 0x00; - self.ctrl_a = 0x00; - self.tmr_b = 0x00; - self.latch_b = 0x00; - self.ctrl_b = 0x00; self.icr = 0x00; - self.tod_hours = 0x01; - self.tod_minutes = 0x00; - self.tod_seconds = 0x00; - self.tod_tenths = 0x00; - self.tod_frozen = false; } } - diff --git a/core/src/periph/mos6520/tick.rs b/core/src/periph/mos6520/tick.rs new file mode 100644 index 0000000..466038d --- /dev/null +++ b/core/src/periph/mos6520/tick.rs @@ -0,0 +1,83 @@ +use log::debug; +use crate::periph::mos6520::Mos6520; +use crate::traits::bus_device::BusDevice; + +impl Mos6520 { + pub fn tick(&mut self, address_bus: u16, data_bus: u8) -> u8 { + self.address_bus = address_bus; + self.data_bus = data_bus; + + println!("Preparing to tick MOS6520"); + + // are we changing our state? + let effective = self.internal_address(self.address_bus); + + match effective { + 0x00 => { + // ddra + // println!("DDRA -> {:02x} -> {:02x}", self.ddra, self.data_bus); + self.ddra = self.data_bus; + } + 0x01 => { + // port a + // println!("PORT A -> {:02x} -> {:02x}", self.port_a, self.data_bus); + self.port_a = self.data_bus; + } + 0x02 => { + // ddrb + // println!("DDRB -> {:02x}", self.ddrb); + self.ddrb = self.data_bus; + } + 0x03 => { + // port b + // println!("PORT B -> {:02x}", self.port_b); + self.port_b = self.data_bus; + } + _ => { + panic!("Unable to access via 6520 at offset ${effective}") + } + } + + self.tick_port_a(); + self.tick_port_b(); + + self.data_bus + } + + fn tick_port_a(&mut self) { + self.out_a = 0x00; + self.in_a = 0x00; + + for current_bit in 0..8 { + let bit_mask = 1 << current_bit; + let is_output = (self.ddra & bit_mask) != 0; + let is_set = (self.port_a & bit_mask) != 0; + + match (is_output, is_set) { + (true, true) => self.out_a |= bit_mask, + (false, true) => self.in_a |= bit_mask, + _ => {} + } + } + + println!("Time to tick the device on port a"); + } + + fn tick_port_b(&mut self) { + self.out_b = 0x00; + self.in_b = 0x00; + + for current_bit in 0..8 { + let bit_mask = 1 << current_bit; + let is_output = (self.ddrb & bit_mask) != 0; + let is_set = (self.port_b & bit_mask) != 0; + + match (is_output, is_set) { + (true, true) => self.out_b |= bit_mask, + (false, true) => self.in_b |= bit_mask, + _ => {} + } + } + println!("Time to tick the device on port b"); + } +} diff --git a/core/src/periph/mos6520/tod.rs b/core/src/periph/mos6520/tod.rs deleted file mode 100644 index c162425..0000000 --- a/core/src/periph/mos6520/tod.rs +++ /dev/null @@ -1,26 +0,0 @@ -use crate::periph::mos6520::Mos6520; - -impl Mos6520 { - fn read_tod(&mut self, sub: u8) -> u8 { - match sub { - 0 => { self.tod_frozen = true; self.tod_hours }, - 1 => self.tod_minutes, - 2 => self.tod_seconds, - 3 => { - self.tod_frozen = false; - self.tod_tenths - } - _ => 0 - } - } - - pub(crate) fn write_tod(&mut self, sub: u8, value: u8) { - match sub { - 0 => { self.tod_hours = value; self.tod_frozen = true; } - 1 => self.tod_minutes = value, - 2 => self.tod_seconds = value, - 3 => { self.tod_tenths = value; self.tod_frozen = false; } - _ => {} - } - } -} \ No newline at end of file diff --git a/core/src/periph/mos6520/via_chip.rs b/core/src/periph/mos6520/via_chip.rs new file mode 100644 index 0000000..f7462bd --- /dev/null +++ b/core/src/periph/mos6520/via_chip.rs @@ -0,0 +1,126 @@ +use log::debug; +use crate::periph::mos6520::Mos6520; +use crate::traits::memory_chip::MemoryChip; +use crate::traits::ram_chip::RamChip; +use crate::traits::rom_chip::RomChip; +use crate::traits::via_chip::ViaChip; + +impl RomChip for Mos6520 { + fn program(new_data: &[u8]) -> Box { + debug!("This has no rom. Cant program."); + todo!() + } +} + +impl RamChip for Mos6520 { + fn write(&mut self, offset: &u16, value: &u8) { + debug!("This has no ROM / ${offset:04x} ${value:02x}"); + } +} + +impl MemoryChip for Mos6520 { + fn read(&self, offset: &u16) -> u8 { + debug!("This has no ROM ${offset:04x}"); + 0 + } +} + +impl ViaChip for Mos6520 { + fn set_port_ddr(&mut self, port_index: u8, value: u8) { + match port_index { + 1 => { + self.ddra = value; + }, + 2 => { + self.ddrb = value; + } + _ => { + debug!("Invalid Port"); + } + } + + self.update_ports(); + } + + fn set_port_data(&mut self, port_index: u8, value: u8) { + match port_index { + 1 => { + self.port_a = value; + }, + 2 => { + self.port_b = value; + } + _ => { + debug!("Invalid Port"); + } + } + self.update_ports(); + } +} + +impl Mos6520 { + fn update_ports(&mut self) { + debug!("PortA: DDR {:08b}", self.port_a); + debug!("PortB: DDR {:08b}", self.port_b); + } +} + +#[cfg(test)] +mod test { + use crate::periph::mos6520::Mos6520; + + const DDRA_OFFSET: u8 = 0x00; + const PORTA_OFFSET: u8 = 0x01; + const DDRB_OFFSET: u8 = 0x02; + const PORTB_OFFSET: u8 = 0x03; + + fn actual(base: u16, offset: u8) -> u16 { + base + offset as u16 + } + + #[test] + fn ddrb_tests() { + let mut x = Mos6520::new(0x1000); + let params = vec![ + // Offset data outa ina ddra porta + (DDRB_OFFSET, 0xff, 0x00, 0x00, 0xff, 0x00), + (PORTB_OFFSET, 0xff, 0xff, 0x00, 0xff, 0xff), + (DDRB_OFFSET, 0xaa, 0xaa, 0x55, 0xaa, 0xff), + (DDRB_OFFSET, 0x55, 0x55, 0xaa, 0x55, 0xff), + (PORTB_OFFSET, 0xf0, 0x50, 0xa0, 0x55, 0xf0), + (PORTB_OFFSET, 0x0f, 0x05, 0x0a, 0x55, 0x0f), + (DDRB_OFFSET, 0xff, 0x0f, 0x00, 0xff, 0x0f) + ]; + + for (offset, data, outb, inb, ddrb, portb) in params { + x.tick(actual(x.offset, offset), data); + assert_eq!(outb, x.out_b); + assert_eq!(inb, x.in_b); + assert_eq!(ddrb, x.ddrb); + assert_eq!(portb, x.port_b); + } + } + + #[test] + fn ddra_tests() { + let mut x = Mos6520::new(0x1000); + let params = vec![ + // Offset data outa ina ddra porta + (DDRA_OFFSET, 0xff, 0x00, 0x00, 0xff, 0x00), + (PORTA_OFFSET, 0xff, 0xff, 0x00, 0xff, 0xff), + (DDRA_OFFSET, 0xaa, 0xaa, 0x55, 0xaa, 0xff), + (DDRA_OFFSET, 0x55, 0x55, 0xaa, 0x55, 0xff), + (PORTA_OFFSET, 0xf0, 0x50, 0xa0, 0x55, 0xf0), + (PORTA_OFFSET, 0x0f, 0x05, 0x0a, 0x55, 0x0f), + (DDRA_OFFSET, 0xff, 0x0f, 0x00, 0xff, 0x0f) + ]; + + for (offset, data, outa, ina, ddra, porta) in params { + x.tick(actual(x.offset, offset), data); + assert_eq!(outa, x.out_a); + assert_eq!(ina, x.in_a); + assert_eq!(ddra, x.ddra); + assert_eq!(porta, x.port_a); + } + } +} diff --git a/core/src/periph/mos6530/mod.rs b/core/src/periph/mos6530/mod.rs index c8f6431..d14e5bb 100644 --- a/core/src/periph/mos6530/mod.rs +++ b/core/src/periph/mos6530/mod.rs @@ -1,5 +1,5 @@ pub mod mos6530; pub mod tick; -mod new; -mod dump; -mod viachip; \ No newline at end of file +pub mod new; +pub mod dump; +pub mod viachip; \ No newline at end of file diff --git a/core/src/periph/mos6530/mos6530.rs b/core/src/periph/mos6530/mos6530.rs index 7a72b0d..349552a 100644 --- a/core/src/periph/mos6530/mos6530.rs +++ b/core/src/periph/mos6530/mos6530.rs @@ -13,19 +13,19 @@ use crate::periph::mos6522::mos6522::Mos6522; /// IO Ports (A, B) /// Timer pub struct Mos6530 { - pub(crate) data: [u8; SIZE_1KB], - pub(crate) ram: [u8; 64], - pub(crate) porta: u8, - pub(crate) portb: u8, - pub(crate) data_bus: u8, - pub(crate) address_bus: u16, - pub(crate) cs1: bool, - pub(crate) cs2: bool, + pub data: [u8; SIZE_1KB], + pub ram: [u8; 64], + pub porta: u8, + pub portb: u8, + pub data_bus: u8, + pub address_bus: u16, + pub cs1: bool, + pub cs2: bool, // when true, CPU is reading - pub(crate) rw: bool, - pub(crate) reset: bool, - pub(crate) io_offset: u16, - pub(crate) ram_offset: u16, - pub(crate) rom_offset: u16 + pub rw: bool, + pub reset: bool, + pub io_offset: u16, + pub ram_offset: u16, + pub rom_offset: u16 } diff --git a/core/src/periph/mos6530/viachip.rs b/core/src/periph/mos6530/viachip.rs index cb45ecc..b316838 100644 --- a/core/src/periph/mos6530/viachip.rs +++ b/core/src/periph/mos6530/viachip.rs @@ -1,11 +1,39 @@ use log::debug; use crate::constants::constants_system::{SIZE_1KB, SIZE_32KB}; use crate::periph::mos6530::mos6530::Mos6530; +use crate::traits::bus_device::BusDevice; use crate::traits::memory_chip::MemoryChip; use crate::traits::ram_chip::RamChip; use crate::traits::rom_chip::RomChip; use crate::traits::via_chip::ViaChip; +impl BusDevice for Mos6530 { + fn min_offset(&self) -> u16 { + self.ram_offset + } + + fn max_offset(&self) -> u16 { + self.min_offset() + SIZE_1KB as u16 + } + + fn address_bus(&self) -> u16 { + self.address_bus + } + + fn data_bus(&self) -> u8 { + self.data_bus + } + + fn set_address_bus(&mut self, new_value: u16) { + self.address_bus = new_value + } + + fn set_data_bus(&mut self, new_value: u8) { + self.data_bus = new_value + } + +} + impl RamChip for Mos6530 { fn write(&mut self, offset: &u16, value: &u8) { debug!("🐙 Writing ${value:02x} to ${offset:04x}"); @@ -49,4 +77,3 @@ impl ViaChip for Mos6530 { debug!("🐙Setting PORT{port_index} to {value:02x}"); } } - diff --git a/core/src/traits/backplane.rs b/core/src/traits/backplane.rs index ce0b354..b8c6978 100644 --- a/core/src/traits/backplane.rs +++ b/core/src/traits/backplane.rs @@ -16,19 +16,20 @@ pub trait Backplane { /// Tick a ROM chip /// /// returns (data_for_databus) - fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool); + fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) -> u8; /// tick_rom /// /// Tick a ROM chip /// /// returns (data_for_databus) - fn tick_rom(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) -> (u8); + fn tick_rom(&mut self, address: u16, cs: bool, oe: bool) -> u8; /// tick_via /// /// Tick a VIA chip /// - /// returns (portA, portB, interrupt) - fn tick_via(&mut self, address: u16, data: u8, cs: bool, rw: bool, ce: bool) -> (u8, u8, bool); + /// returns (data, irqa, irqb) + fn tick_via(&mut self, address: u16, data: u8, cs0: bool, cs1: bool, rw: bool, rs0: bool, rs1: bool) -> (u8, bool, bool); } + diff --git a/core/src/traits/bus_device.rs b/core/src/traits/bus_device.rs index 848a307..557b6c6 100644 --- a/core/src/traits/bus_device.rs +++ b/core/src/traits/bus_device.rs @@ -1,8 +1,33 @@ + pub trait BusDevice { + fn min_offset(&self) -> u16; + fn max_offset(&self) -> u16; fn address_bus(&self) -> u16; fn data_bus(&self) -> u8; fn set_address_bus(&mut self, new_value: u16); fn set_data_bus(&mut self, new_value: u8); - fn talking_to_me(&self, address: u16) -> bool; + fn talking_to_me(&self, address: u16) -> bool { + address >= self.min_offset() && address < self.max_offset() + } + + /// internal_address + /// + /// Converts from a system-wide address to a device specific address + /// + /// ex: 0x3000 to a ROM chip with min_offset = 0x2000 + /// -> internal_address = 0x1000 <-- read this offset from data array + /// -> external_address = 0x3000 + fn internal_address(&self, address: u16) -> u16 { + // println!("MINOFFSET ${:04x}", self.min_offset()); + let mo = self.max_offset(); + let result= if address > mo { + address - self.max_offset() + } else { + address + }; + // println!("RESULT = {:04x}", result - self.min_offset()); + + result - self.min_offset() + } } diff --git a/core/src/traits/memory_chip.rs b/core/src/traits/memory_chip.rs index 835871a..d451da0 100644 --- a/core/src/traits/memory_chip.rs +++ b/core/src/traits/memory_chip.rs @@ -1,4 +1,6 @@ -pub trait MemoryChip { +use crate::traits::bus_device::BusDevice; + +pub trait MemoryChip : BusDevice { /// Read /// /// Reads a single byte from the specified address diff --git a/core/src/traits/mod.rs b/core/src/traits/mod.rs index c26e9cf..29b2941 100644 --- a/core/src/traits/mod.rs +++ b/core/src/traits/mod.rs @@ -5,3 +5,4 @@ pub mod rom_chip; pub mod ram_chip; pub mod via_chip; pub mod backplane; +mod timer_chip; diff --git a/core/src/traits/ram_chip.rs b/core/src/traits/ram_chip.rs index 16a5d8a..431504d 100644 --- a/core/src/traits/ram_chip.rs +++ b/core/src/traits/ram_chip.rs @@ -1,7 +1,8 @@ use crate::periph::hm62256::Hm62256; +use crate::traits::bus_device::BusDevice; use crate::traits::memory_chip::MemoryChip; use crate::traits::rom_chip::RomChip; -pub trait RamChip: MemoryChip { +pub trait RamChip: MemoryChip + BusDevice { fn write(&mut self, offset: &u16, value: &u8); } diff --git a/core/src/traits/rom_chip.rs b/core/src/traits/rom_chip.rs index 0041c3e..f1413fe 100644 --- a/core/src/traits/rom_chip.rs +++ b/core/src/traits/rom_chip.rs @@ -1,7 +1,8 @@ use crate::constants::constants_system::SIZE_32KB; +use crate::traits::bus_device::BusDevice; use crate::traits::memory_chip::MemoryChip; -pub trait RomChip: MemoryChip { +pub trait RomChip: MemoryChip + BusDevice { /// Program /// /// Replaces all data in the chip diff --git a/core/src/traits/timer_chip.rs b/core/src/traits/timer_chip.rs new file mode 100644 index 0000000..48f3e21 --- /dev/null +++ b/core/src/traits/timer_chip.rs @@ -0,0 +1,16 @@ +use crate::traits::bus_device::BusDevice; + +pub trait TimerChip: BusDevice { + /// set_timer + /// + /// Set current value of timer + fn set_timer(&mut self, timer_index: u8, new_value: u16); + + /// get_timer + /// + /// Read current value of timer + fn get_timer(&mut self, timer_index: u8) -> u16; + + /// Advance Timer circutry 1 cycle + fn tick(&mut self); +} \ No newline at end of file diff --git a/core/src/traits/via_chip.rs b/core/src/traits/via_chip.rs index 8606870..4788605 100644 --- a/core/src/traits/via_chip.rs +++ b/core/src/traits/via_chip.rs @@ -1,15 +1,21 @@ +use log::debug; +use crate::traits::bus_device::BusDevice; use crate::traits::ram_chip::RamChip; use crate::traits::rom_chip::RomChip; -pub trait ViaChip: RamChip + RomChip { +pub trait ViaChip: RamChip + RomChip + BusDevice { /// set_port_ddr /// /// Sets the Data Direction Register in the VIA chip for the specified /// port. - fn set_port_ddr(&mut self, port_index: u8, value: u8); + fn set_port_ddr(&mut self, port_index: u8, value: u8) { + debug!("Please implement this."); + } /// set_port_data /// /// Sets the - fn set_port_data(&mut self, port_index: u8, value: u8); + fn set_port_data(&mut self, port_index: u8, value: u8) { + debug!("Please implement this."); + } } \ No newline at end of file diff --git a/core/tests/at28c256.rs b/core/tests/at28c256.rs deleted file mode 100644 index 1295628..0000000 --- a/core/tests/at28c256.rs +++ /dev/null @@ -1,6 +0,0 @@ -use super::*; - -#[test] -fn test123() { - -} \ No newline at end of file diff --git a/core/tests/base.rs b/core/tests/base.rs new file mode 100644 index 0000000..fd1cd1f --- /dev/null +++ b/core/tests/base.rs @@ -0,0 +1,4 @@ +#[test] +fn test() { + assert!(true); +} diff --git a/core/tests/execution_tests.rs b/core/tests/execution_tests.rs deleted file mode 100644 index 8b13789..0000000 --- a/core/tests/execution_tests.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/core/tests/instruction_encode_decode.rs b/core/tests/instruction_encode_decode.rs deleted file mode 100644 index 8b13789..0000000 --- a/core/tests/instruction_encode_decode.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/resources/docs/6820_hardware_manual.pdf b/resources/docs/6820_hardware_manual.pdf new file mode 100644 index 0000000..4fb96a1 Binary files /dev/null and b/resources/docs/6820_hardware_manual.pdf differ diff --git a/resources/kim1/6530-002_fillerbyte00-0x1c00.bin b/resources/pia/6530-002_fillerbyte00-0x1c00.bin similarity index 100% rename from resources/kim1/6530-002_fillerbyte00-0x1c00.bin rename to resources/pia/6530-002_fillerbyte00-0x1c00.bin diff --git a/resources/kim1/6530-003_fillerbyte00-0x1800.bin b/resources/pia/6530-003_fillerbyte00-0x1800.bin similarity index 100% rename from resources/kim1/6530-003_fillerbyte00-0x1800.bin rename to resources/pia/6530-003_fillerbyte00-0x1800.bin diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -}