more fixed stuff
This commit is contained in:
@@ -5,3 +5,4 @@ edition = "2024"
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
rand = "0.9.0"
|
||||
once_cell = "0.1"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
use crate::mos6502cpu::cpu::Mos6502Cpu;
|
||||
use crate::periph::ram_chip::RamChip;
|
||||
|
||||
/// BackplaneBuilder
|
||||
///
|
||||
/// Builds a Backplane for a 6502 Emulated PC
|
||||
struct BackplaneBuilder {
|
||||
cpu: Mos6502Cpu,
|
||||
// ram_modules: Vec<dyn RamChip>
|
||||
}
|
||||
|
||||
impl BackplaneBuilder {
|
||||
pub fn add_cpu(mut self, new_cpu: Mos6502Cpu) -> Self {
|
||||
self.cpu = new_cpu;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_ram(mut self, new_ram: impl RamChip) -> Self {
|
||||
// self.ram_modules.push(new_ram);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod beneater;
|
||||
pub mod rom_only;
|
||||
pub mod kim1;
|
||||
pub mod ram_rom;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
use crate::periph::at28c256::At28C256;
|
||||
use crate::periph::backplane::Backplane;
|
||||
use crate::periph::hm62256::Hm62256;
|
||||
|
||||
pub struct RamRomComputer {
|
||||
rom: At28C256,
|
||||
ram: Hm62256,
|
||||
data_bus: u8,
|
||||
address_bus: u16,
|
||||
read_mode: bool,
|
||||
}
|
||||
|
||||
impl Backplane for RamRomComputer {
|
||||
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 tick(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
fn set_read_mode(&mut self, new_mode: bool) {
|
||||
self.read_mode = new_mode;
|
||||
}
|
||||
|
||||
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 RamRomComputer {
|
||||
pub fn new() -> RamRomComputer {
|
||||
RamRomComputer {
|
||||
rom: At28C256::default(),
|
||||
ram: Hm62256::default(),
|
||||
data_bus: 0x00,
|
||||
address_bus: 0x0000,
|
||||
/// is the CPU reading from the 'other' device?
|
||||
read_mode: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod backplane;
|
||||
@@ -1,34 +1,59 @@
|
||||
use crate::constants::constants_system::{SIZE_32KB, SIZE_64KB};
|
||||
use crate::periph::at28c256::At28C256;
|
||||
use crate::periph::hm62256::Hm62256;
|
||||
use crate::periph::backplane::Backplane;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
|
||||
pub struct RomOnlyComputer {
|
||||
rom: At28C256,
|
||||
data_bus: u8,
|
||||
address_bus: u16
|
||||
address_bus: u16,
|
||||
read_mode: bool,
|
||||
}
|
||||
|
||||
impl Backplane for RomOnlyComputer {
|
||||
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!("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);
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
impl RomOnlyComputer {
|
||||
pub fn new() -> RomOnlyComputer {
|
||||
RomOnlyComputer::program(&[0x00; SIZE_32KB])
|
||||
let mut working = vec![0x00u8; SIZE_32KB];
|
||||
for index in 0..SIZE_32KB {
|
||||
working[index] = index as u8;
|
||||
}
|
||||
RomOnlyComputer::program(working)
|
||||
}
|
||||
|
||||
pub fn program(rom: &[u8; SIZE_32KB]) -> RomOnlyComputer {
|
||||
|
||||
pub fn program(rom: Vec<u8>) -> RomOnlyComputer {
|
||||
RomOnlyComputer {
|
||||
rom: *At28C256::new(0x000, rom),
|
||||
rom: At28C256::new(0x000, 0x3fff, rom),
|
||||
address_bus: 0x0000,
|
||||
data_bus: 0x00
|
||||
data_bus: 0x00,
|
||||
read_mode: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(&mut self) {
|
||||
println!("Preparing to tick.");
|
||||
|
||||
// do are we being addressed?
|
||||
|
||||
|
||||
|
||||
println!("Done ticking.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
use std::borrow::ToOwned;
|
||||
use once_cell::unsync::Lazy;
|
||||
|
||||
pub const TEST_RESOURCES_ROOT: &str = "/home/tmerritt/Projects/resources/test";
|
||||
pub const TEST_PERIPH_ROOT: &str = "/home/tmerritt/Projects/resources/test/periph";
|
||||
pub const TEST_PERIPH_AT28C256_ROOT: &str = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256";
|
||||
|
||||
@@ -3,3 +3,4 @@ pub mod constants_isa_stub;
|
||||
pub mod constants_system;
|
||||
pub mod constants_via6522;
|
||||
pub mod constants_mos6530;
|
||||
pub mod constants_test;
|
||||
|
||||
@@ -11,3 +11,4 @@ pub mod op_info;
|
||||
pub mod operand;
|
||||
pub mod operation;
|
||||
pub mod periph;
|
||||
mod backplane;
|
||||
|
||||
@@ -526,7 +526,7 @@ impl Mos6502Cpu {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
@@ -537,6 +537,12 @@ mod test {
|
||||
fn clc() {
|
||||
// setup the CPU for our test
|
||||
let mut cpu = Mos6502Cpu::default();
|
||||
|
||||
// tick through the reset cycle
|
||||
while !cpu.has_reset {
|
||||
cpu.tick();
|
||||
}
|
||||
println!("DONE RESET TICKS");
|
||||
cpu.flags.set_flag(Carry);
|
||||
// Load our 'test program'
|
||||
cpu.memory[0x6000] = ISA_OP_CLC;
|
||||
@@ -763,3 +769,4 @@ mod test {
|
||||
assert_eq!(cpu.memory[0xab], 0b1010_1010);;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -13,14 +13,12 @@ impl Mos6502Cpu {
|
||||
working
|
||||
}
|
||||
|
||||
|
||||
pub(crate) fn reset_cpu(&mut self) {
|
||||
self.microcode_step = 7 + 4;
|
||||
self.microcode_step = 7 + 6;
|
||||
// self = &mut Mos6502Cpu::default();
|
||||
println!("Should tick 7 times, then 4 cycles to read the reset and int vectors.");
|
||||
println!("Should tick 7 times, then 6 cycles to read the reset and int vectors.");
|
||||
// read the value at 0xfffa 0xfffb for our NMI vector.
|
||||
// read the value at 0xfffc 0xfffd for our reset vector.
|
||||
// read the value at 0xfffe 0xffff for our int vector
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
use crate::constants::constants_system::SIZE_32KB;
|
||||
use crate::periph::at28c256::At28C256;
|
||||
use crate::constants::constants_test::*;
|
||||
|
||||
impl At28C256 {
|
||||
/// checksum
|
||||
///
|
||||
/// calculates and returns the checksum for the loaded binary.
|
||||
/// files with all zero will calculate to zero
|
||||
pub fn checksum(&self) -> u8 {
|
||||
At28C256::checksum_static(&self.data[..])
|
||||
}
|
||||
|
||||
pub fn checksum_static(data: &[u8]) -> u8 {
|
||||
data.iter().fold(0u8, |acc, &b| acc.wrapping_add(b))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use crate::constants::constants_system::SIZE_1KB;
|
||||
use crate::periph::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");
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,12 @@ impl Default for At28C256 {
|
||||
let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice
|
||||
.try_into()
|
||||
.expect("Failed to convert Vec to boxed array");
|
||||
At28C256 { data: boxed_array,
|
||||
address_bus: 0x0000,
|
||||
data_bus: 0x00,
|
||||
offset: 0x0000
|
||||
At28C256 {
|
||||
data: boxed_array,
|
||||
address_bus: 0x0000,
|
||||
data_bus: 0x00,
|
||||
offset: 0x0000,
|
||||
max_offset: 0x3fff,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ pub mod tick;
|
||||
mod new;
|
||||
mod program;
|
||||
mod dump;
|
||||
mod checksum;
|
||||
|
||||
use crate::constants::constants_system::SIZE_32KB;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
@@ -11,37 +12,15 @@ use std::io::Read;
|
||||
|
||||
/// At28C256
|
||||
///
|
||||
/// Represents a single At28C256 Chip
|
||||
/// Represents a single At28C256 EEPROM Chip
|
||||
///
|
||||
/// 256kbit storage
|
||||
/// 32kbyte storage
|
||||
pub struct At28C256 {
|
||||
data_bus: u8,
|
||||
address_bus: u16,
|
||||
data: Box<[u8; SIZE_32KB]>,
|
||||
data: Box<[u8]>,
|
||||
// where in the computer memory map do we live?
|
||||
offset: u16
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::constants::constants_system::SIZE_1KB;
|
||||
|
||||
#[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] = 0xea;
|
||||
}
|
||||
for offset in 0..SIZE_32KB {
|
||||
if offset.is_multiple_of(SIZE_1KB) {};
|
||||
assert_eq!(0xea, data.read(&(offset as u16)));
|
||||
}
|
||||
}
|
||||
offset: u16,
|
||||
max_offset: u16
|
||||
}
|
||||
|
||||
@@ -2,12 +2,15 @@ use crate::constants::constants_system::SIZE_32KB;
|
||||
use crate::periph::at28c256::At28C256;
|
||||
|
||||
impl At28C256 {
|
||||
pub fn new(offset: u16, data: &[u8; SIZE_32KB]) -> Self {
|
||||
pub fn new(offset: u16, max_offset: u16, data: Vec<u8>) -> Self {
|
||||
println!("NEW At28C256 with checksum ${:02x}", At28C256::checksum_static(&data[..]));
|
||||
|
||||
At28C256 {
|
||||
data: (*data).into(),
|
||||
data: data.into_boxed_slice(),
|
||||
address_bus: 0x0000,
|
||||
data_bus: 0x00,
|
||||
offset
|
||||
offset,
|
||||
max_offset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,40 +3,66 @@ use crate::periph::at28c256::At28C256;
|
||||
use crate::periph::hm62256::Hm62256;
|
||||
|
||||
impl At28C256 {
|
||||
fn max_address(&self) -> u16 {
|
||||
self.offset + SIZE_32KB as u16
|
||||
fn talking_to_me(&self, address: u16) -> bool {
|
||||
address >= self.offset && address < self.max_offset
|
||||
}
|
||||
|
||||
|
||||
pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) {
|
||||
if address_bus.gt(&self.offset) & address_bus.lt(&self.max_address()) {
|
||||
if read_mode {
|
||||
panic!("UNABLE TO WRITE TO ROM");
|
||||
} else {
|
||||
// has to be read mode. its a rom.
|
||||
return (address_bus, data_bus)
|
||||
}
|
||||
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)
|
||||
}
|
||||
// not for us.
|
||||
(address_bus, self.data[address_bus as usize])
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
println!("At28C256: Read... {:02x}", self.data_bus);
|
||||
println!("At28C256: Done with ticking the AtC256");
|
||||
(address_bus, self.data_bus)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::fs;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn smoke() { assert!(true); }
|
||||
|
||||
#[test]
|
||||
fn write_to_memory_read_back_works_at_0() {
|
||||
let mut rom = At28C256::default();
|
||||
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![]
|
||||
}
|
||||
};
|
||||
|
||||
rom.tick(0x0000, 0xab, false);
|
||||
let (_, new_data) = rom.tick(0x0000, 0x00, true);
|
||||
let mut rom = At28C256::new(0x0000, 0x3fff, bytes);
|
||||
|
||||
assert_eq!(new_data, 0xab);
|
||||
assert_eq!(rom.checksum(), 0x58);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
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);
|
||||
}
|
||||
@@ -7,12 +7,11 @@ impl Hm62256 {
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool, cs: bool) -> (u16, u8) {
|
||||
println!("HM62256RAM TICK START -> 0x{address_bus:04x} 0x{data_bus:02x} {read_mode} {cs}");
|
||||
if !(address_bus.gt( &self.offset) && address_bus.le(&self.max_address())) {
|
||||
return (address_bus, data_bus);
|
||||
}
|
||||
|
||||
println!("HM62256RAM TICK START -> 0x{address_bus:04x} 0x{data_bus:02x} {read_mode} {cs}");
|
||||
|
||||
self.address_bus = address_bus;
|
||||
self.data_bus = data_bus;
|
||||
let addr = address_bus.wrapping_sub(self.offset) + self.offset;
|
||||
|
||||
@@ -6,3 +6,4 @@ pub mod mos6522;
|
||||
pub mod mos6530;
|
||||
pub mod kim1_keypad;
|
||||
mod bus_device;
|
||||
pub mod backplane;
|
||||
|
||||
@@ -46,6 +46,10 @@ pub struct Mos6522 {
|
||||
}
|
||||
|
||||
impl Mos6522 {
|
||||
pub fn max_offset(&self) -> u16 {
|
||||
self.offset + 0x10
|
||||
}
|
||||
|
||||
pub fn start_clocks(&mut self) {
|
||||
loop {
|
||||
let cycle_start = Instant::now();
|
||||
@@ -66,40 +70,40 @@ mod test {
|
||||
#[test]
|
||||
fn registers() {
|
||||
let mut x = Mos6522::new();
|
||||
x.tick(0b0000_0000, VIA6522_DDRA, false, true);
|
||||
x.tick(VIA6522_DDRA as u16, 0b0000_0000, false, true);
|
||||
assert_eq!(x.dda, 0b0000_0000);
|
||||
x.tick(0b1111_1111, VIA6522_DDRA, false, true);
|
||||
x.tick(VIA6522_DDRA as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.dda, 0b1111_1111);
|
||||
|
||||
x.tick(0b0000_0000, VIA6522_DDRB, false, true);
|
||||
x.tick(VIA6522_DDRB as u16, 0b0000_0000, false, true);
|
||||
assert_eq!(x.ddb, 0b0000_0000);
|
||||
x.tick(0b1111_1111, VIA6522_DDRB, false, true);
|
||||
x.tick(VIA6522_DDRB as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.ddb, 0b1111_1111);
|
||||
|
||||
x.tick(0b0000_0000, VIA6522_ORA, false, true);
|
||||
assert_eq!(x.porta, 0b0000_0000);
|
||||
x.tick(0b1111_1111, VIA6522_ORA, false, true);
|
||||
assert_eq!(x.porta, 0b1111_1111);
|
||||
x.tick(VIA6522_ORA as u16, 0b0000_0000, false, true);
|
||||
assert_eq!(x.ora, 0b0000_0000);
|
||||
x.tick(VIA6522_ORA as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.ora, 0b1111_1111);
|
||||
|
||||
x.tick(0b0000_0000, VIA6522_ORB, false, true);
|
||||
assert_eq!(x.portb, 0b0000_0000);
|
||||
x.tick(0b1111_1111, VIA6522_ORB, false, true);
|
||||
assert_eq!(x.portb, 0b1111_1111);
|
||||
x.tick(VIA6522_ORB as u16, 0b0000_0000, false, true);
|
||||
assert_eq!(x.orb, 0b0000_0000);
|
||||
x.tick(VIA6522_ORB as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.orb, 0b1111_1111);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn partial_output_porta() {
|
||||
let mut x = Mos6522::new();
|
||||
x.tick(0b1010_1010, VIA6522_DDRA, false, true);
|
||||
x.tick(0b1111_1111, VIA6522_ORA, false, true);
|
||||
x.tick(VIA6522_DDRA as u16, 0b1010_1010, false, true);
|
||||
x.tick(VIA6522_ORA as u16,0b1111_1111, false, true);
|
||||
assert_eq!(x.porta, 0b1010_1010);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn partial_output_portb() {
|
||||
let mut x = Mos6522::new();
|
||||
x.tick(0b0101_0101, VIA6522_DDRB, false, true);
|
||||
x.tick(0b1111_1111, VIA6522_ORB, false, true);
|
||||
x.tick(VIA6522_DDRB as u16, 0b0101_0101, false, true);
|
||||
x.tick(VIA6522_ORB as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.portb, 0b0101_0101);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@ impl Mos6522 {
|
||||
/// data_bus -> 8 bits from the data bus
|
||||
/// control -> 4 bits to identify which register to control
|
||||
pub fn tick(&mut self, address_bus: u16, data_bus: u8,reset: bool, rw: bool) -> (u16, u8) {
|
||||
if !(address_bus.gt( &self.offset) && address_bus.le(&self.max_address())) {
|
||||
if !(address_bus >= self.offset && address_bus.le(&self.max_address())) {
|
||||
return (address_bus, data_bus);
|
||||
}
|
||||
|
||||
let local_address = address_bus - self.offset;
|
||||
|
||||
println!("Mos6522 Tick Start -> D:0x{data_bus:02x} / A:0x{address_bus:02x} / {rw} (Actual 0x{local_address:02x}");
|
||||
println!("Mos6522 Tick Start -> D:0x{data_bus:02x} / A:0x{address_bus:02x} / {rw} (Actual 0x{local_address:02x} / 0b{local_address:08b})");
|
||||
if reset {
|
||||
// reset process
|
||||
println!("Resetting Mos6522");
|
||||
@@ -35,25 +35,28 @@ impl Mos6522 {
|
||||
self.data_bus = data_bus;
|
||||
match local_address as u8 {
|
||||
VIA6522_DDRA => {
|
||||
debug!("Setting DDA to 0x{data_bus:02x}");
|
||||
println!("Setting DDA to 0x{data_bus:02x}");
|
||||
// setting the Data Direction for Port A
|
||||
self.dda = data_bus;
|
||||
},
|
||||
VIA6522_DDRB => {
|
||||
debug!("Setting DDB to 0x{data_bus:02x}");
|
||||
// setting the data direction for port b
|
||||
self.ddb = data_bus;
|
||||
},
|
||||
VIA6522_ORB => {
|
||||
// writing data to ORB
|
||||
let masked_data = data_bus & self.ddb;
|
||||
debug!("Setting ORB to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
|
||||
println!("Setting ORB to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
|
||||
self.orb = data_bus;
|
||||
self.portb = masked_data;
|
||||
},
|
||||
VIA6522_DDRB => {
|
||||
println!("Setting DDB to 0x{data_bus:02x}");
|
||||
// setting the data direction for port b
|
||||
self.ddb = data_bus;
|
||||
},
|
||||
|
||||
VIA6522_ORA => {
|
||||
// writing data to ORA
|
||||
let masked_data = data_bus & self.dda;
|
||||
debug!("Setting ORA to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
|
||||
println!("Setting ORA to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
|
||||
self.ora = data_bus;
|
||||
self.porta = masked_data;
|
||||
},
|
||||
_ => {}
|
||||
|
||||
@@ -12,8 +12,6 @@ use crate::periph::mos6522::mos6522::Mos6522;
|
||||
/// 64 bytes RAM
|
||||
/// IO Ports (A, B)
|
||||
/// Timer
|
||||
///
|
||||
/// SEE ALSO Mos6532
|
||||
pub struct Mos6530 {
|
||||
pub(crate) data: [u8; SIZE_1KB],
|
||||
pub(crate) ram: [u8; 64],
|
||||
@@ -30,3 +28,4 @@ pub struct Mos6530 {
|
||||
pub(crate) ram_offset: u16,
|
||||
pub(crate) rom_offset: u16
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user