adds docs
working on widetick
This commit is contained in:
parent
b40c3c503f
commit
8f6f9cb64d
@ -3,7 +3,7 @@ use crate::parts::via6522::VIA6522;
|
|||||||
use core::constants::constants_system::*;
|
use core::constants::constants_system::*;
|
||||||
use core::mos6502cpu::cpu::Mos6502Cpu;
|
use core::mos6502cpu::cpu::Mos6502Cpu;
|
||||||
use core::periph::at28c256::At28C256;
|
use core::periph::at28c256::At28C256;
|
||||||
use core::periph::rom_chip::RomChip;
|
use core::traits::rom_chip::RomChip;
|
||||||
use core::constants::constants_via6522::*;
|
use core::constants::constants_via6522::*;
|
||||||
|
|
||||||
/// Backplane
|
/// Backplane
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use core::computers::ram_rom::backplane::RamRomComputer;
|
use core::computers::ram_rom::backplane::RamRomComputer;
|
||||||
use core::periph::backplane::Backplane;
|
use core::traits::backplane::Backplane;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|||||||
@ -1,16 +1,11 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use core::computers::ram_rom::RamRomComputer;
|
use core::computers::ram_rom::RamRomComputer;
|
||||||
use core::periph::backplane::Backplane;
|
use core::traits::backplane::Backplane;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let bytes = include_bytes!("/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin");
|
||||||
println!("Taxation is theft");
|
println!("Taxation is theft");
|
||||||
let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin";
|
|
||||||
let bytes = match fs::read(path) {
|
|
||||||
Ok(bytes) => {
|
|
||||||
println!("Loaded {} bytes", bytes.len());
|
|
||||||
bytes
|
|
||||||
},
|
|
||||||
Err(e) => vec![]
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut ramrom_computer = RamRomComputer::program_rom((&bytes[..]).to_vec());
|
let mut ramrom_computer = RamRomComputer::program_rom((&bytes[..]).to_vec());
|
||||||
|
|
||||||
@ -19,9 +14,17 @@ fn main() {
|
|||||||
ramrom_computer.data_bus(),
|
ramrom_computer.data_bus(),
|
||||||
ramrom_computer.address_bus()
|
ramrom_computer.address_bus()
|
||||||
);
|
);
|
||||||
|
println!("--TICK--");
|
||||||
ramrom_computer.tick2(0x4005, 0b0000_0001, ramrom_computer.data_bus());
|
ramrom_computer.tick2(0x4005, 0b0000_0001, ramrom_computer.data_bus());
|
||||||
println!("COMPUTER: Read {:02x} from ROM / {:04x} from Address bus",
|
println!("COMPUTER: Read {:02x} from ROM / {:04x} from Address bus",
|
||||||
ramrom_computer.data_bus(),
|
ramrom_computer.data_bus(),
|
||||||
ramrom_computer.address_bus()
|
ramrom_computer.address_bus()
|
||||||
);
|
);
|
||||||
|
println!("--TICK--");
|
||||||
|
ramrom_computer.tick2(0x4005, 0b0000_0000, ramrom_computer.data_bus());
|
||||||
|
println!("COMPUTER: Read {:02x} from ROM / {:04x} from Address bus",
|
||||||
|
ramrom_computer.data_bus(),
|
||||||
|
ramrom_computer.address_bus()
|
||||||
|
);
|
||||||
|
println!("--TICK--");
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use core::computers::rom_only::RomOnlyComputer;
|
use core::computers::rom_only::RomOnlyComputer;
|
||||||
use core::periph::backplane::Backplane;
|
use core::traits::backplane::Backplane;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Taxation is theft");
|
println!("Taxation is theft");
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use core::computers::rom_only::RomOnlyComputer;
|
use core::computers::rom_only::RomOnlyComputer;
|
||||||
use core::periph::backplane::Backplane;
|
use core::traits::backplane::Backplane;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Taxation is theft");
|
println!("Taxation is theft");
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::computers::ram_rom::RamRomComputer;
|
use crate::computers::ram_rom::RamRomComputer;
|
||||||
use crate::periph::at28c256::At28C256;
|
use crate::periph::at28c256::At28C256;
|
||||||
use crate::periph::backplane::Backplane;
|
use crate::traits::backplane::Backplane;
|
||||||
use crate::periph::hm62256::Hm62256;
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
|
||||||
|
|
||||||
@ -53,5 +53,17 @@ impl Backplane for RamRomComputer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tick_rom(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) -> (u8) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tick_via(&mut self, address: u16, data: u8, cs: bool, rw: bool, ce: bool) -> (u8, u8, bool) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,26 +2,50 @@ use std::collections::BTreeMap;
|
|||||||
use crate::computers::ram_rom::RamRomComputer;
|
use crate::computers::ram_rom::RamRomComputer;
|
||||||
use crate::traits::bus_device::BusDevice;
|
use crate::traits::bus_device::BusDevice;
|
||||||
|
|
||||||
|
struct ChipSignals {
|
||||||
|
cs: bool,
|
||||||
|
oe: bool,
|
||||||
|
we: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RomRamChips {
|
||||||
|
At28C256,
|
||||||
|
Hm62256
|
||||||
|
}
|
||||||
|
|
||||||
impl RamRomComputer {
|
impl RamRomComputer {
|
||||||
|
pub fn signal_tick(&mut self, address: u16, data: u8) {
|
||||||
|
println!("⏲️RAM ROM COMPUTER SIGNAL TICK");
|
||||||
|
|
||||||
|
// no CPU to tick.
|
||||||
|
|
||||||
|
let mut ram_state = ChipSignals { oe: false, we: false, cs: false};
|
||||||
|
let mut rom_state = ChipSignals { oe: false, we: false, cs: false};
|
||||||
|
|
||||||
|
|
||||||
|
// Tick the RAM
|
||||||
|
// Tick the ROM
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tick2(&mut self, address: u16, control: u8, data: u8) -> (u8) {
|
pub fn tick2(&mut self, address: u16, control: u8, data: u8) -> (u8) {
|
||||||
println!("RAM ROM Computer tick starting");
|
println!("RAM ROM Computer tick starting / {address:04x} {control:08b} {data:02x}");
|
||||||
|
|
||||||
// tick the parts
|
// tick the parts
|
||||||
let (_, new_data) = self.rom.tick(address, data, control == 1);
|
|
||||||
let (_, new_data2) = self.ram.tick(address, data, control == 1, true);
|
|
||||||
|
|
||||||
// map of memory
|
// map of memory
|
||||||
// 0x0000 -> 0x3fff -> RAM (HM62256)
|
// 0x0000 -> 0x3fff -> RAM (HM62256)
|
||||||
// 0x4000 -> 0x7fff -> ROM (At28C256)
|
// 0x4000 -> 0x7fff -> ROM (At28C256)
|
||||||
match address {
|
match address {
|
||||||
0x0000..=0x3fff => {
|
0x0000..=0x3fff => {
|
||||||
self.data_bus = new_data
|
println!("__DATA TARGETTING ROM BEING STORED ON DATA BUS");
|
||||||
}
|
}
|
||||||
0x4000 ..=0x7fff => {
|
0x4000 ..=0x7fff => {
|
||||||
self.data_bus = new_data2
|
println!("__DATA TARGETTING RRAAMM GETTING STORED ON DATA BUS");
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
let (_, rom_data_bus) = self.rom.tick(address, data, control == 1);
|
||||||
|
let (_, ram_data_bus) = self.ram.tick(address, data, control == 1, true);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
|
use log::debug;
|
||||||
use crate::computers::rom_only::RomOnlyComputer;
|
use crate::computers::rom_only::RomOnlyComputer;
|
||||||
use crate::periph::backplane::Backplane;
|
use crate::traits::backplane::Backplane;
|
||||||
|
|
||||||
impl Backplane for RomOnlyComputer {
|
impl Backplane for RomOnlyComputer {
|
||||||
fn data_bus(&self) -> u8 { self.data_bus }
|
fn data_bus(&self) -> u8 { self.data_bus }
|
||||||
@ -17,7 +18,6 @@ impl Backplane for RomOnlyComputer {
|
|||||||
|
|
||||||
fn tick(&mut self) {
|
fn tick(&mut self) {
|
||||||
println!("COMPUTER: Preparing to tick.");
|
println!("COMPUTER: Preparing to tick.");
|
||||||
|
|
||||||
// do are we being addressed?
|
// do are we being addressed?
|
||||||
println!("COMPUTER: BUSSES PRE: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode);
|
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);
|
let (new_addr, new_data) = self.rom.tick(self.address_bus, self.data_bus, self.read_mode);
|
||||||
@ -26,4 +26,18 @@ impl Backplane for RomOnlyComputer {
|
|||||||
println!("COMPUTER: BUSSES POST: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode);
|
println!("COMPUTER: BUSSES POST: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode);
|
||||||
println!("COMPUTER: Done ticking.");
|
println!("COMPUTER: Done ticking.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool) {
|
||||||
|
debug!("This system has no ram. ROM only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
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_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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::periph::at28c256::At28C256;
|
use crate::periph::at28c256::At28C256;
|
||||||
use crate::periph::backplane::Backplane;
|
use crate::traits::backplane::Backplane;
|
||||||
|
|
||||||
pub mod backplane;
|
pub mod backplane;
|
||||||
pub mod new;
|
pub mod new;
|
||||||
|
|||||||
@ -17,4 +17,8 @@ impl BusDevice for Mos6502Cpu {
|
|||||||
fn set_data_bus(&mut self, new_value: u8) {
|
fn set_data_bus(&mut self, new_value: u8) {
|
||||||
self.data_bus = new_value;
|
self.data_bus = new_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn talking_to_me(&self, address: u16) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
9
core/src/periph/README
Normal file
9
core/src/periph/README
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Peripherals
|
||||||
|
|
||||||
|
At28C256 - 256 byte static ram
|
||||||
|
Hm682256 - 256 byte ROM
|
||||||
|
Kim1_Keypad - Keypad for KIM-1 Computer
|
||||||
|
mos6520 - Peripheral Adapter
|
||||||
|
mos6522 - Versatile Interface Adapter (6520++)
|
||||||
|
mos6530 - RRIOT (Ram, Rom, Input, Output, Timers)
|
||||||
|
|
||||||
@ -21,7 +21,8 @@ mod test {
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::constants::constants_system::SIZE_1KB;
|
use crate::constants::constants_system::SIZE_1KB;
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::traits::memory_chip::MemoryChip;
|
||||||
|
use crate::traits::rom_chip::RomChip;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
8
core/src/periph/at28c256/control.rs
Normal file
8
core/src/periph/at28c256/control.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::periph::at28c256::At28C256;
|
||||||
|
use crate::traits::bus_control_byte::BusControlByte;
|
||||||
|
|
||||||
|
const CTRL_CS: u8 = 0b0000_0001;
|
||||||
|
const CTRL_WE: u8 = 0b0000_0010;
|
||||||
|
const CTRL_OE: u8 = 0b0000_0100;
|
||||||
|
|
||||||
|
pub struct At28c256Control {}
|
||||||
@ -15,6 +15,9 @@ impl Default for At28C256 {
|
|||||||
data_bus: 0x00,
|
data_bus: 0x00,
|
||||||
offset: 0x0000,
|
offset: 0x0000,
|
||||||
max_offset: 0x3fff,
|
max_offset: 0x3fff,
|
||||||
|
cs: false,
|
||||||
|
oe: false,
|
||||||
|
we: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,9 +6,10 @@ pub mod program;
|
|||||||
pub mod dump;
|
pub mod dump;
|
||||||
pub mod checksum;
|
pub mod checksum;
|
||||||
pub mod blocks;
|
pub mod blocks;
|
||||||
|
pub mod control;
|
||||||
|
pub mod signal_tick;
|
||||||
|
|
||||||
use crate::constants::constants_system::SIZE_32KB;
|
use crate::traits::rom_chip::RomChip;
|
||||||
use crate::periph::rom_chip::RomChip;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
/// At28C256
|
/// At28C256
|
||||||
@ -18,10 +19,15 @@ use std::io::Read;
|
|||||||
/// 256kbit storage
|
/// 256kbit storage
|
||||||
/// 32kbyte storage
|
/// 32kbyte storage
|
||||||
pub struct At28C256 {
|
pub struct At28C256 {
|
||||||
|
// Logical parts
|
||||||
data_bus: u8,
|
data_bus: u8,
|
||||||
address_bus: u16,
|
address_bus: u16,
|
||||||
data: Box<[u8]>,
|
data: Box<[u8]>,
|
||||||
// where in the computer memory map do we live?
|
// where in the computer memory map do we live?
|
||||||
offset: u16,
|
offset: u16,
|
||||||
max_offset: u16
|
max_offset: u16,
|
||||||
|
// Physical Parts
|
||||||
|
cs: bool,
|
||||||
|
we: bool,
|
||||||
|
oe: bool
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,10 @@ impl At28C256 {
|
|||||||
address_bus: 0x0000,
|
address_bus: 0x0000,
|
||||||
data_bus: 0x00,
|
data_bus: 0x00,
|
||||||
offset,
|
offset,
|
||||||
max_offset
|
max_offset,
|
||||||
|
cs: false,
|
||||||
|
oe: false,
|
||||||
|
we: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,8 @@ impl At28C256 {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::traits::memory_chip::MemoryChip;
|
||||||
|
use crate::traits::rom_chip::RomChip;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -26,5 +27,6 @@ mod test {
|
|||||||
let new_data: Vec<u8> = vec![0xff, 0xff, 0xff, 0xff];
|
let new_data: Vec<u8> = vec![0xff, 0xff, 0xff, 0xff];
|
||||||
chip.program(new_data.into());
|
chip.program(new_data.into());
|
||||||
assert_eq!(0xff, chip.read(&0x0000));
|
assert_eq!(0xff, chip.read(&0x0000));
|
||||||
|
assert_eq!(0x00, chip.read(&0x05));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
use crate::constants::constants_system::SIZE_32KB;
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
use crate::periph::at28c256::At28C256;
|
use crate::periph::at28c256::At28C256;
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::traits::memory_chip::MemoryChip;
|
||||||
|
use crate::traits::rom_chip::RomChip;
|
||||||
|
|
||||||
impl RomChip for At28C256 {
|
impl MemoryChip for At28C256 {
|
||||||
|
fn read(&self, offset: &u16) -> u8 {
|
||||||
/// read
|
/// read
|
||||||
///
|
///
|
||||||
/// Reads a byte from memory.
|
/// Reads a byte from memory.
|
||||||
/// Returns a 0x00 if there is no data at that location but is still in ROM address range
|
/// Returns a 0x00 if there is no data at that location but is still in ROM address range
|
||||||
fn read(&self, offset: &u16) -> u8 {
|
|
||||||
println!("STARTING READ FROM At28C256 ${:04x} | ${:04x} | ${:04x}", self.offset, offset, self.max_offset);
|
println!("STARTING READ FROM At28C256 ${:04x} | ${:04x} | ${:04x}", self.offset, offset, self.max_offset);
|
||||||
if offset < &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.");
|
println!("Unable to read from ${offset:04x} as it it out of range.");
|
||||||
@ -20,18 +21,18 @@ impl RomChip for At28C256 {
|
|||||||
0x00
|
0x00
|
||||||
} else {
|
} else {
|
||||||
self.data[*offset as usize]
|
self.data[*offset as usize]
|
||||||
|
} }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
impl RomChip for At28C256 {
|
||||||
|
|
||||||
/// program
|
/// program
|
||||||
///
|
///
|
||||||
/// Writes new data to the memory chip
|
/// Writes new data to the memory chip
|
||||||
fn program(new_data: &[u8; SIZE_32KB]) -> Box<At28C256> {
|
fn program(new_data: &[u8]) -> Box<At28C256> {
|
||||||
println!("Writing new chip.");
|
println!("Writing new chip.");
|
||||||
let mut working = At28C256::default();
|
let mut working = At28C256::default();
|
||||||
working.data = Box::new(*new_data);
|
working.data = new_data.to_vec().into_boxed_slice();
|
||||||
working.into()
|
Box::new(working)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
51
core/src/periph/at28c256/signal_tick.rs
Normal file
51
core/src/periph/at28c256/signal_tick.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
|
use crate::periph::at28c256::At28C256;
|
||||||
|
|
||||||
|
const CHIP_SIZE: usize = SIZE_32KB ;
|
||||||
|
|
||||||
|
impl At28C256 {
|
||||||
|
/// Tick the ROM
|
||||||
|
/// address_bus
|
||||||
|
/// data_bus
|
||||||
|
/// CS -> Chip Select
|
||||||
|
/// OE -> Output Enable
|
||||||
|
/// WE -> Write Enable
|
||||||
|
pub fn signal_tick(&mut self, address_bus: u16, data_bus: u8, cs: bool, oe: bool, we: bool) -> (u8) {
|
||||||
|
|
||||||
|
// if we aren't selected and we aren't able to write to the bus...
|
||||||
|
if !cs || !we || !oe { return data_bus };
|
||||||
|
|
||||||
|
// if we aren't being addressed directly
|
||||||
|
if !(address_bus <= self.max_offset && address_bus >= self.offset) {
|
||||||
|
return data_bus
|
||||||
|
};
|
||||||
|
|
||||||
|
let internal_address = address_bus - self.offset;
|
||||||
|
|
||||||
|
let result = if internal_address < CHIP_SIZE as u16 {
|
||||||
|
self.data[internal_address as usize]
|
||||||
|
} else {
|
||||||
|
data_bus
|
||||||
|
};
|
||||||
|
println!("At28C256 EADDR: ${address_bus:04x} IADDR: ${internal_address:04x} = {result:02x}");
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,8 +8,10 @@ impl At28C256 {
|
|||||||
address >= self.offset && address < 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) {
|
pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) {
|
||||||
print!("At28C256: Tick starting for A${address_bus:04x} D${data_bus:02x} R{read_mode}");
|
println!("At28C256: Tick starting for A${address_bus:04x} D${data_bus:02x} R{read_mode}");
|
||||||
|
|
||||||
// we aren't being addressed
|
// we aren't being addressed
|
||||||
// OR
|
// OR
|
||||||
@ -17,7 +19,6 @@ impl At28C256 {
|
|||||||
if !self.talking_to_me(address_bus) ||
|
if !self.talking_to_me(address_bus) ||
|
||||||
!read_mode {
|
!read_mode {
|
||||||
// ...go away.
|
// ...go away.
|
||||||
// println!("At28C256 Tick not for me.");
|
|
||||||
return (address_bus, data_bus)
|
return (address_bus, data_bus)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ impl At28C256 {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::traits::rom_chip::RomChip;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
pub trait Backplane {
|
|
||||||
fn data_bus(&self) -> u8;
|
|
||||||
fn address_bus(&self) -> u16;
|
|
||||||
fn read_mode(&self) -> bool;
|
|
||||||
fn set_read_mode(&mut self, new_mode: bool);
|
|
||||||
fn set_data_bus(&mut self, new_value: u8);
|
|
||||||
fn set_address_bus(&mut self, new_value: u16);
|
|
||||||
fn tick(&mut self);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
pub trait BusDevice {
|
|
||||||
fn talking_to_me(&self, address: u16) -> bool;
|
|
||||||
}
|
|
||||||
8
core/src/periph/hm62256/control.rs
Normal file
8
core/src/periph/hm62256/control.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
use crate::traits::bus_control_byte::BusControlByte;
|
||||||
|
|
||||||
|
const CTRL_CS: u8 = 0b0000_0001;
|
||||||
|
const CTRL_WE: u8 = 0b0000_0010;
|
||||||
|
const CTRL_OE: u8 = 0b0000_0100;
|
||||||
|
|
||||||
|
pub struct Hm62256Control;
|
||||||
@ -11,7 +11,10 @@ impl Default for Hm62256 {
|
|||||||
offset: 0x0000,
|
offset: 0x0000,
|
||||||
data: boxed_array,
|
data: boxed_array,
|
||||||
address_bus: 0x0000,
|
address_bus: 0x0000,
|
||||||
data_bus: 0x00
|
data_bus: 0x00,
|
||||||
|
cs: false,
|
||||||
|
oe: false,
|
||||||
|
we: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,10 +6,11 @@ pub mod tick;
|
|||||||
pub mod default;
|
pub mod default;
|
||||||
pub mod new;
|
pub mod new;
|
||||||
pub mod dump;
|
pub mod dump;
|
||||||
|
mod control;
|
||||||
|
|
||||||
use crate::constants::constants_system::SIZE_32KB;
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
use crate::periph::ram_chip::RamChip;
|
use crate::traits::ram_chip::RamChip;
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::traits::rom_chip::RomChip;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
/// Hitachi Semiconductor
|
/// Hitachi Semiconductor
|
||||||
@ -19,13 +20,20 @@ pub struct Hm62256 {
|
|||||||
pub(crate) offset: u16,
|
pub(crate) offset: u16,
|
||||||
pub(crate) data: Box<[u8]>,
|
pub(crate) data: Box<[u8]>,
|
||||||
pub(crate) address_bus: u16,
|
pub(crate) address_bus: u16,
|
||||||
pub(crate) data_bus: u8
|
pub(crate) data_bus: u8,
|
||||||
|
// Chip Select
|
||||||
|
pub(crate) cs: bool,
|
||||||
|
// Write Enable
|
||||||
|
pub(crate) we: bool,
|
||||||
|
// Output Enable
|
||||||
|
pub(crate) oe: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use rand::random;
|
use rand::random;
|
||||||
|
use crate::traits::memory_chip::MemoryChip;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn smoke() {
|
fn smoke() {
|
||||||
|
|||||||
@ -7,7 +7,10 @@ impl Hm62256 {
|
|||||||
offset: base_offset,
|
offset: base_offset,
|
||||||
data: vec![0; SIZE_32KB].into_boxed_slice(),
|
data: vec![0; SIZE_32KB].into_boxed_slice(),
|
||||||
address_bus: 0x0000,
|
address_bus: 0x0000,
|
||||||
data_bus: 0x00
|
data_bus: 0x00,
|
||||||
|
cs: false,
|
||||||
|
oe: false,
|
||||||
|
we: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::constants::constants_system::SIZE_32KB;
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
use crate::periph::hm62256::Hm62256;
|
use crate::periph::hm62256::Hm62256;
|
||||||
use crate::periph::ram_chip::RamChip;
|
use crate::traits::ram_chip::RamChip;
|
||||||
|
|
||||||
impl RamChip for Hm62256 {
|
impl RamChip for Hm62256 {
|
||||||
fn write(&mut self, offset: &u16, value: &u8) {
|
fn write(&mut self, offset: &u16, value: &u8) {
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
use log::debug;
|
use log::debug;
|
||||||
use crate::constants::constants_system::SIZE_32KB;
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
use crate::periph::hm62256::Hm62256;
|
use crate::periph::hm62256::Hm62256;
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::traits::memory_chip::MemoryChip;
|
||||||
|
use crate::traits::rom_chip::RomChip;
|
||||||
impl RomChip for Hm62256 {
|
|
||||||
|
|
||||||
|
|
||||||
|
impl MemoryChip for Hm62256 {
|
||||||
fn read(&self, offset: &u16) -> u8 {
|
fn read(&self, offset: &u16) -> u8 {
|
||||||
// loops memory around past 32k
|
// loops memory around past 32k
|
||||||
let effective = *offset as i32 % SIZE_32KB as i32;
|
let effective = *offset as i32 % SIZE_32KB as i32;
|
||||||
self.data[effective as usize]
|
self.data[effective as usize]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn program(_: &[u8; SIZE_32KB]) -> Box<Self> {
|
impl RomChip for Hm62256 {
|
||||||
|
fn program(_: &[u8]) -> Box<Self> {
|
||||||
debug!("Dont program ram.");
|
debug!("Dont program ram.");
|
||||||
Hm62256::default().into()
|
Hm62256::default().into()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
pub mod rom_chip;
|
|
||||||
pub mod at28c256;
|
pub mod at28c256;
|
||||||
pub mod hm62256;
|
pub mod hm62256;
|
||||||
pub mod ram_chip;
|
pub mod mos6520;
|
||||||
pub mod mos6522;
|
pub mod mos6522;
|
||||||
pub mod mos6530;
|
pub mod mos6530;
|
||||||
pub mod kim1_keypad;
|
pub mod kim1_keypad;
|
||||||
mod bus_device;
|
|
||||||
pub mod backplane;
|
|
||||||
|
|||||||
65
core/src/periph/mos6520/mod.rs
Normal file
65
core/src/periph/mos6520/mod.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
mod tod;
|
||||||
|
mod reset;
|
||||||
|
|
||||||
|
use crate::traits::memory_chip::MemoryChip;
|
||||||
|
use crate::traits::ram_chip::RamChip;
|
||||||
|
use crate::traits::rom_chip::RomChip;
|
||||||
|
use crate::traits::via_chip::ViaChip;
|
||||||
|
|
||||||
|
pub struct Mos6520 {
|
||||||
|
// Parallel ports A & B data registers
|
||||||
|
port_a: u8,
|
||||||
|
port_b: u8,
|
||||||
|
ddra: 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,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 MemoryChip for Mos6520 {
|
||||||
|
fn read(&self, offset: &u16) -> u8 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RomChip for Mos6520 {
|
||||||
|
fn program(new_data: &[u8]) -> Box<Self> {
|
||||||
|
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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
26
core/src/periph/mos6520/reset.rs
Normal file
26
core/src/periph/mos6520/reset.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use crate::periph::mos6520::Mos6520;
|
||||||
|
|
||||||
|
impl Mos6520 {
|
||||||
|
/// reset
|
||||||
|
///
|
||||||
|
/// Simulates holding Reset pin low
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.port_a = 0x00;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
26
core/src/periph/mos6520/tod.rs
Normal file
26
core/src/periph/mos6520/tod.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
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; }
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,3 +2,4 @@ pub mod mos6530;
|
|||||||
pub mod tick;
|
pub mod tick;
|
||||||
mod new;
|
mod new;
|
||||||
mod dump;
|
mod dump;
|
||||||
|
mod viachip;
|
||||||
52
core/src/periph/mos6530/viachip.rs
Normal file
52
core/src/periph/mos6530/viachip.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
use log::debug;
|
||||||
|
use crate::constants::constants_system::{SIZE_1KB, SIZE_32KB};
|
||||||
|
use crate::periph::mos6530::mos6530::Mos6530;
|
||||||
|
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 RamChip for Mos6530 {
|
||||||
|
fn write(&mut self, offset: &u16, value: &u8) {
|
||||||
|
debug!("🐙 Writing ${value:02x} to ${offset:04x}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryChip for Mos6530 {
|
||||||
|
fn read(&self, offset: &u16) -> u8 {
|
||||||
|
debug!("🐙 Reading from ${offset:04x}");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RomChip for Mos6530 {
|
||||||
|
fn program(new_data: &[u8]) -> Box<Self> {
|
||||||
|
debug!("🐙 programming {}b to ROM", new_data.len());
|
||||||
|
Box::new(Mos6530 {
|
||||||
|
data: new_data.to_vec().try_into().unwrap(),
|
||||||
|
ram: [0x00; 64],
|
||||||
|
porta: 0,
|
||||||
|
portb: 0,
|
||||||
|
data_bus: 0,
|
||||||
|
address_bus: 0,
|
||||||
|
cs1: false,
|
||||||
|
cs2: false,
|
||||||
|
rw: false,
|
||||||
|
reset: false,
|
||||||
|
io_offset: 0,
|
||||||
|
ram_offset: 0,
|
||||||
|
rom_offset: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ViaChip for Mos6530 {
|
||||||
|
fn set_port_ddr(&mut self, port_index: u8, value: u8) {
|
||||||
|
debug!("🐙Setting DDR{port_index} to {value:02x}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_port_data(&mut self, port_index: u8, value: u8) {
|
||||||
|
debug!("🐙Setting PORT{port_index} to {value:02x}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
use crate::periph::rom_chip::RomChip;
|
|
||||||
|
|
||||||
pub trait RamChip: RomChip {
|
|
||||||
fn write(&mut self, offset: &u16, value: &u8);
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
use crate::constants::constants_system::SIZE_32KB;
|
|
||||||
|
|
||||||
pub trait RomChip {
|
|
||||||
/// Read
|
|
||||||
///
|
|
||||||
/// Reads a single byte from the specified address
|
|
||||||
fn read(&self, offset: &u16) -> u8;
|
|
||||||
/// Program
|
|
||||||
///
|
|
||||||
/// Replaces all data in the ROM chip
|
|
||||||
fn program(new_data: &[u8; SIZE_32KB]) -> Box<Self>;
|
|
||||||
}
|
|
||||||
34
core/src/traits/backplane.rs
Normal file
34
core/src/traits/backplane.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
pub trait Backplane {
|
||||||
|
fn data_bus(&self) -> u8;
|
||||||
|
fn address_bus(&self) -> u16;
|
||||||
|
fn read_mode(&self) -> bool;
|
||||||
|
fn set_read_mode(&mut self, new_mode: bool);
|
||||||
|
fn set_data_bus(&mut self, new_value: u8);
|
||||||
|
fn set_address_bus(&mut self, new_value: u16);
|
||||||
|
|
||||||
|
/// Tick
|
||||||
|
///
|
||||||
|
/// Master tick method to handle ticking all subsystems.
|
||||||
|
fn tick(&mut self);
|
||||||
|
|
||||||
|
/// tick_rom
|
||||||
|
///
|
||||||
|
/// Tick a ROM chip
|
||||||
|
///
|
||||||
|
/// returns (data_for_databus)
|
||||||
|
fn tick_ram(&mut self, address: u16, data: u8, cs: bool, oe: bool, we: bool);
|
||||||
|
|
||||||
|
/// 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);
|
||||||
|
|
||||||
|
/// 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);
|
||||||
|
}
|
||||||
10
core/src/traits/bus_control_byte.rs
Normal file
10
core/src/traits/bus_control_byte.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use crate::traits::bus_device::BusDevice;
|
||||||
|
|
||||||
|
/// BusControlByte
|
||||||
|
///
|
||||||
|
/// Used to allow passing of a component specific set of
|
||||||
|
/// properties to be used with the universal tick
|
||||||
|
pub trait BusControlByte<T: BusDevice> {
|
||||||
|
fn from_byte(source: u8) -> T;
|
||||||
|
}
|
||||||
|
|
||||||
@ -4,5 +4,5 @@ pub trait BusDevice {
|
|||||||
|
|
||||||
fn set_address_bus(&mut self, new_value: u16);
|
fn set_address_bus(&mut self, new_value: u16);
|
||||||
fn set_data_bus(&mut self, new_value: u8);
|
fn set_data_bus(&mut self, new_value: u8);
|
||||||
|
fn talking_to_me(&self, address: u16) -> bool;
|
||||||
}
|
}
|
||||||
|
|||||||
6
core/src/traits/memory_chip.rs
Normal file
6
core/src/traits/memory_chip.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
pub trait MemoryChip {
|
||||||
|
/// Read
|
||||||
|
///
|
||||||
|
/// Reads a single byte from the specified address
|
||||||
|
fn read(&self, offset: &u16) -> u8;
|
||||||
|
}
|
||||||
@ -1 +1,7 @@
|
|||||||
pub mod bus_device;
|
pub mod bus_device;
|
||||||
|
pub mod bus_control_byte;
|
||||||
|
pub mod memory_chip;
|
||||||
|
pub mod rom_chip;
|
||||||
|
pub mod ram_chip;
|
||||||
|
pub mod via_chip;
|
||||||
|
pub mod backplane;
|
||||||
|
|||||||
7
core/src/traits/ram_chip.rs
Normal file
7
core/src/traits/ram_chip.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
use crate::traits::memory_chip::MemoryChip;
|
||||||
|
use crate::traits::rom_chip::RomChip;
|
||||||
|
|
||||||
|
pub trait RamChip: MemoryChip {
|
||||||
|
fn write(&mut self, offset: &u16, value: &u8);
|
||||||
|
}
|
||||||
9
core/src/traits/rom_chip.rs
Normal file
9
core/src/traits/rom_chip.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
|
use crate::traits::memory_chip::MemoryChip;
|
||||||
|
|
||||||
|
pub trait RomChip: MemoryChip {
|
||||||
|
/// Program
|
||||||
|
///
|
||||||
|
/// Replaces all data in the chip
|
||||||
|
fn program(new_data: &[u8]) -> Box<Self>;
|
||||||
|
}
|
||||||
15
core/src/traits/via_chip.rs
Normal file
15
core/src/traits/via_chip.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use crate::traits::ram_chip::RamChip;
|
||||||
|
use crate::traits::rom_chip::RomChip;
|
||||||
|
|
||||||
|
pub trait ViaChip: RamChip + RomChip {
|
||||||
|
/// 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);
|
||||||
|
|
||||||
|
/// set_port_data
|
||||||
|
///
|
||||||
|
/// Sets the
|
||||||
|
fn set_port_data(&mut self, port_index: u8, value: u8);
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test123() {
|
||||||
|
|
||||||
|
}
|
||||||
BIN
resources/docs/6530-Commodore.pdf
Normal file
BIN
resources/docs/6530-Commodore.pdf
Normal file
Binary file not shown.
BIN
resources/docs/6530.pdf
Normal file
BIN
resources/docs/6530.pdf
Normal file
Binary file not shown.
BIN
resources/docs/rockwell_r6520_pia.pdf
Normal file
BIN
resources/docs/rockwell_r6520_pia.pdf
Normal file
Binary file not shown.
BIN
resources/docs/w65c22.pdf
Normal file
BIN
resources/docs/w65c22.pdf
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user