moa/src/peripherals/macintosh/mainboard.rs

214 lines
6.6 KiB
Rust

use std::rc::Rc;
use std::cell::RefCell;
use crate::memory::Bus;
use crate::error::Error;
use crate::system::System;
use crate::signals::Signal;
use crate::devices::{Clock, ClockElapsed, Address, Addressable, Steppable, Transmutable, TransmutableBox, wrap_transmutable};
use crate::peripherals::z8530::Z8530;
use crate::peripherals::mos6522::Mos6522;
use crate::peripherals::macintosh::iwm::IWM;
use crate::peripherals::macintosh::video::MacVideo;
const DEV_NAME: &'static str = "mac";
pub struct Mainboard {
pub lower_bus: Rc<RefCell<Bus>>,
pub scc1: Z8530,
pub scc2: Z8530,
pub iwm: IWM,
pub via: Mos6522,
pub phase_read: PhaseRead,
pub 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 ram_len = ram.borrow_mut().as_addressable().unwrap().len();
let rom_len = rom.borrow_mut().as_addressable().unwrap().len();
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().blocks.clear();
lower_bus.borrow_mut().insert(0x000000, wrap_transmutable(AddressRepeater::new(ram.clone(), 32)));
lower_bus.borrow_mut().insert(0x400000, wrap_transmutable(AddressRepeater::new(rom.clone(), 16)));
lower_bus.borrow_mut().insert(0x600000, wrap_transmutable(AddressRepeater::new(rom.clone(), 16)));
} else {
println!("{}: overlay is 1 (startup)", DEV_NAME);
lower_bus.borrow_mut().blocks.clear();
lower_bus.borrow_mut().insert(0x000000, wrap_transmutable(AddressRepeater::new(rom.clone(), 16)));
lower_bus.borrow_mut().insert(0x200000, wrap_transmutable(AddressRepeater::new(rom.clone(), 16)));
lower_bus.borrow_mut().insert(0x400000, wrap_transmutable(AddressRepeater::new(rom.clone(), 16)));
lower_bus.borrow_mut().insert(0x600000, wrap_transmutable(AddressRepeater::new(ram.clone(), 16)));
}
});
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.scc1.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 {
// TODO phase read
Ok(())
} 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.scc1.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 {
// TODO phase read
Ok(())
} 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> {
Ok(())
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
Ok(())
}
}
pub struct AddressRepeater {
pub subdevice: TransmutableBox,
pub repeat: u8,
}
impl AddressRepeater {
pub fn new(subdevice: TransmutableBox, repeat: u8) -> Self {
Self {
subdevice,
repeat,
}
}
}
impl Addressable for AddressRepeater {
fn len(&self) -> usize {
let len = self.subdevice.borrow_mut().as_addressable().unwrap().len();
len * self.repeat as usize
}
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
let len = self.subdevice.borrow_mut().as_addressable().unwrap().len() as Address;
self.subdevice.borrow_mut().as_addressable().unwrap().read(addr % len, data)
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
let len = self.subdevice.borrow_mut().as_addressable().unwrap().len() as Address;
self.subdevice.borrow_mut().as_addressable().unwrap().write(addr % len, data)
}
}
impl Transmutable for AddressRepeater {
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
Some(self)
}
}