moa/emulator/systems/macintosh/src/peripherals/mainboard.rs
transistor 7c279613cc Moved AddressRepeater to core, and renamed AddressAdapter
AddressRepeater now takes the range it should repeat over, which only
really affects its reported size.

AddressAdapter is now AddressRightShifter, which is literally the operation
it performs, where the input is still the bits to shift the address right by
2022-10-01 21:01:56 -07:00

167 lines
5.4 KiB
Rust

use std::rc::Rc;
use std::cell::RefCell;
use moa_core::{System, Bus, Error, Observable, Clock, ClockElapsed, Address, Addressable, AddressRepeater, Steppable, Transmutable, TransmutableBox, wrap_transmutable};
use moa_peripherals_mos::Mos6522;
use moa_peripherals_zilog::Z8530;
use crate::peripherals::iwm::IWM;
const DEV_NAME: &'static str = "mac";
pub struct Mainboard {
lower_bus: Rc<RefCell<Bus>>,
scc1: Z8530,
scc2: Z8530,
iwm: IWM,
via: Mos6522,
phase_read: PhaseRead,
last_sec: Clock,
}
impl Mainboard {
pub fn create(ram: TransmutableBox, rom: TransmutableBox) -> Result<Self, Error> {
let scc1 = Z8530::new();
let scc2 = Z8530::new();
let iwm = IWM::new();
let via = Mos6522::new();
let phase_read = PhaseRead::new();
let lower_bus = Rc::new(RefCell::new(Bus::new()));
let mainboard = Self {
lower_bus: lower_bus.clone(),
scc1,
scc2,
iwm,
via,
phase_read,
last_sec: 0,
};
mainboard.via.port_a.set_observer(move |port| {
if (port.data & 0x10) == 0 {
println!("{}: overlay is 0 (normal)", DEV_NAME);
lower_bus.borrow_mut().clear_all_bus_devices();
lower_bus.borrow_mut().insert(0x000000, wrap_transmutable(AddressRepeater::new(ram.clone(), 0x400000)));
lower_bus.borrow_mut().insert(0x400000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000)));
lower_bus.borrow_mut().insert(0x600000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000)));
} else {
println!("{}: overlay is 1 (startup)", DEV_NAME);
lower_bus.borrow_mut().clear_all_bus_devices();
lower_bus.borrow_mut().insert(0x000000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000)));
lower_bus.borrow_mut().insert(0x200000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000)));
lower_bus.borrow_mut().insert(0x400000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000)));
lower_bus.borrow_mut().insert(0x600000, wrap_transmutable(AddressRepeater::new(ram.clone(), 0x200000)));
}
});
mainboard.via.port_a.notify();
Ok(mainboard)
}
}
impl Addressable for Mainboard {
fn len(&self) -> usize {
0x01000000
}
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
if addr < 0x800000 {
self.lower_bus.borrow_mut().read(addr, data)
} else if addr >= 0x900000 && addr < 0xA00000 {
self.scc1.read((addr >> 9) & 0x0F, data)
} else if addr >= 0xB00000 && addr < 0xC00000 {
self.scc2.read((addr >> 9) & 0x0F, data)
} else if addr >= 0xD00000 && addr < 0xE00000 {
self.iwm.read((addr >> 9) & 0x0F, data)
} else if addr >= 0xE80000 && addr < 0xF00000 {
self.via.read((addr >> 9) & 0x0F, data)
} else if addr >= 0xF00000 && addr < 0xF80000 {
self.phase_read.read(addr, data)
} else if addr >= 0xF80000 && addr < 0xF80010 {
// Debugger
Ok(())
} else {
Err(Error::new(&format!("Error reading address {:#010x}", addr)))
}
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
if addr < 0x800000 {
self.lower_bus.borrow_mut().write(addr, data)
} else if addr >= 0x900000 && addr < 0xA00000 {
self.scc1.write((addr >> 9) & 0x0F, data)
} else if addr >= 0xB00000 && addr < 0xC00000 {
self.scc2.write((addr >> 9) & 0x0F, data)
} else if addr >= 0xD00000 && addr < 0xE00000 {
self.iwm.write((addr >> 9) & 0x0F, data)
} else if addr >= 0xE80000 && addr < 0xF00000 {
self.via.write((addr >> 9) & 0x0F, data)
} else if addr >= 0xF00000 && addr < 0xF80000 {
self.phase_read.write(addr, data)
} else {
Err(Error::new(&format!("Error writing address {:#010x}", addr)))
}
}
}
impl Steppable for Mainboard {
fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> {
let elapsed = self.via.step(system)?;
// TODO should this be 1 second, or a multiple of 979_200, which is an 8th of the CPU clock
if self.last_sec + 1_000_000_000 > system.clock {
self.last_sec += 1_000_000_000;
//let port_a = self.via.port_a.borrow_mut();
// TODO how will the ca1/ca2 cb1/cb2 pins work in the via
system.get_interrupt_controller().set(true, 1, 25)?;
}
Ok(elapsed)
}
}
impl Transmutable for Mainboard {
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
Some(self)
}
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
Some(self)
}
}
pub struct PhaseRead {
}
impl PhaseRead {
pub fn new() -> Self {
Self {
}
}
}
impl Addressable for PhaseRead {
fn len(&self) -> usize {
0x80000
}
fn read(&mut self, _addr: Address, data: &mut [u8]) -> Result<(), Error> {
// TODO I'm not sure how this is supposed to work
data[0] = 0x00;
Ok(())
}
fn write(&mut self, _addr: Address, _data: &[u8]) -> Result<(), Error> {
// TODO I'm not sure how this is supposed to work
Ok(())
}
}