From 90984dd2b8a278e3cbd44a3e408f3f71d6a9c7a6 Mon Sep 17 00:00:00 2001 From: arbee Date: Sat, 15 Jun 2024 19:53:18 -0400 Subject: cpu/m6805: Added new devices for 68HC05E1 and 68HC05E4. [R. Belmont] apple/cuda.cpp: Refactored using 68HC05E1 and 68HC05E4 devices as a base. [R. Belmont] apple/egret.cpp: Refactored using 68HC05E1 device as a base. [R. Belmont] apple/macquadra630.cpp: Switched to the correct Cuda 2.40, which no longer crashes during boot with the refactored devices. [R. Belmont] --- scripts/src/cpu.lua | 2 + src/devices/cpu/m6805/m68hc05e1.cpp | 293 +++++++++++++++++++++ src/devices/cpu/m6805/m68hc05e1.h | 99 ++++++++ src/mame/apple/cuda.cpp | 492 ++++++++++++----------------------- src/mame/apple/cuda.h | 59 ++--- src/mame/apple/egret.cpp | 493 ++++++++++++------------------------ src/mame/apple/egret.h | 49 +--- src/mame/apple/macquadra630.cpp | 7 +- 8 files changed, 753 insertions(+), 741 deletions(-) create mode 100644 src/devices/cpu/m6805/m68hc05e1.cpp create mode 100644 src/devices/cpu/m6805/m68hc05e1.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 3f2f6f2de42..17f01f97fdc 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1947,6 +1947,8 @@ if CPUS["M6805"] then MAME_DIR .. "src/devices/cpu/m6805/m68705.h", MAME_DIR .. "src/devices/cpu/m6805/m68hc05.cpp", MAME_DIR .. "src/devices/cpu/m6805/m68hc05.h", + MAME_DIR .. "src/devices/cpu/m6805/m68hc05e1.cpp", + MAME_DIR .. "src/devices/cpu/m6805/m68hc05e1.h", } end diff --git a/src/devices/cpu/m6805/m68hc05e1.cpp b/src/devices/cpu/m6805/m68hc05e1.cpp new file mode 100644 index 00000000000..468261c4738 --- /dev/null +++ b/src/devices/cpu/m6805/m68hc05e1.cpp @@ -0,0 +1,293 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/* + Motorola M68HC05E1/E4/etc. 8-bit microcontroller family +*/ + +#include "emu.h" +#include "m68hc05e1.h" +#include "6805dasm.h" + +#define VERBOSE (0) +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(M68HC05E1, m68hc05e1_device, "m68hc05e1", "Motorola M68HC05E1") +DEFINE_DEVICE_TYPE(M68HC05E5, m68hc05e5_device, "m68hc05e5", "Motorola M68HC05E5") + +constexpr int M68HC05EX_INT_IRQ = M6805_IRQ_LINE; +constexpr int M68HC05EX_INT_TIMER = M68HC05EX_INT_IRQ + 1; +constexpr int M68HC05EX_INT_CPI = M68HC05EX_INT_IRQ + 2; + +m68hc05ex_device::m68hc05ex_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int addrbits, address_map_constructor internal_map) : + m6805_base_device(mconfig, tag, owner, clock, type, {s_hc_s_ops, s_hc_cycles, 13, 0x00ff, 0x00c0, 0xfffc}), + m_program_config("program", ENDIANNESS_BIG, 8, addrbits, 0, internal_map), + m_read_p(*this, 0), + m_write_p(*this), + m_pll_ctrl(0), m_timer_ctrl(0), m_onesec(0) +{ + std::fill(std::begin(m_pullups), std::end(m_pullups), 0); +} + +void m68hc05ex_device::device_start() +{ + m6805_base_device::device_start(); + + save_item(NAME(m_ports)); + save_item(NAME(m_ddrs)); + save_item(NAME(m_pll_ctrl)); + save_item(NAME(m_timer_ctrl)); + save_item(NAME(m_onesec)); + + memset(m_ports, 0, sizeof(m_ports)); + memset(m_ddrs, 0, sizeof(m_ddrs)); + + m_timer = timer_alloc(FUNC(m68hc05e1_device::seconds_tick), this); + m_prog_timer = timer_alloc(FUNC(m68hc05e1_device::timer_tick), this); +} + +void m68hc05ex_device::device_reset() +{ + m6805_base_device::device_reset(); + rm16(0x1ffe, m_pc); + + // all ports reset to input on startup + memset(m_ports, 0, sizeof(m_ports)); + memset(m_ddrs, 0, sizeof(m_ddrs)); +} + +device_memory_interface::space_config_vector m68hc05ex_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_program_config) + }; +} + +void m68hc05ex_device::interrupt_vector() +{ + if (BIT(m_pending_interrupts, M68HC05EX_INT_IRQ)) + { + m_pending_interrupts &= ~(1 << M68HC05EX_INT_IRQ); + rm16(0x1ffa, m_pc); + } + else if (BIT(m_pending_interrupts, M68HC05EX_INT_TIMER)) + { + m_pending_interrupts &= ~(1 << M68HC05EX_INT_TIMER); + rm16(0x1ff8, m_pc); + } + else if (BIT(m_pending_interrupts, M68HC05EX_INT_CPI)) + { + m_pending_interrupts &= ~(1 << M68HC05EX_INT_CPI); + rm16(0x1ff6, m_pc); + } +} + +u64 m68hc05ex_device::execute_clocks_to_cycles(u64 clocks) const noexcept +{ + return (clocks + 1) / 2; +} + +u64 m68hc05ex_device::execute_cycles_to_clocks(u64 cycles) const noexcept +{ + return cycles * 2; +} + +std::unique_ptr m68hc05ex_device::create_disassembler() +{ + return std::make_unique(); +} + +void m68hc05ex_device::send_port(u8 offset, u8 data) +{ + m_write_p[offset](data); +} + +u8 m68hc05ex_device::ports_r(offs_t offset) +{ + u8 incoming = m_read_p[offset](); + + // apply data direction registers + incoming &= (m_ddrs[offset] ^ 0xff); + // OR in ddr-masked version of port writes + incoming |= (m_ports[offset] & m_ddrs[offset]); + + return incoming; +} + +void m68hc05ex_device::ports_w(offs_t offset, u8 data) +{ + send_port(offset, (data & m_ddrs[offset]) | (m_pullups[offset] & ~m_ddrs[offset])); + m_ports[offset] = data; +} + +u8 m68hc05ex_device::ddrs_r(offs_t offset) +{ + return m_ddrs[offset]; +} + +void m68hc05ex_device::ddrs_w(offs_t offset, u8 data) +{ + send_port(offset, (m_ports[offset] & data) | (m_pullups[offset] & ~data)); + m_ddrs[offset] = data; +} + +u8 m68hc05ex_device::pll_r() +{ + return m_pll_ctrl; +} + +void m68hc05ex_device::pll_w(u8 data) +{ + // Motorola documentation for both the 68HC05E1 and E5 says that rate 3 (4 MHz) is illegal. + // The Cuda code sets it to 2 MHz, but comments in the code as well as the cycle counts in + // the ADB routines indicate the CPU is intended to run at 4.2 MHz, not 2.1. + // So we do this little cheat. + if ((data & 3) == 2) + { + data |= 3; + } + + if (m_pll_ctrl != data) + { + static const int clocks[4] = {524288, 1048576, 2097152, 4194304}; + LOG("PLL ctrl: clock %d TCS:%d BCS:%d AUTO:%d BWC:%d PLLON:%d (PC=%x)\n", clocks[data & 3], + (data & 0x80) ? 1 : 0, + (data & 0x40) ? 1 : 0, + (data & 0x20) ? 1 : 0, + (data & 0x10) ? 1 : 0, + (data & 0x08) ? 1 : 0, pc()); + + m_prog_timer->adjust(attotime::from_hz(clocks[data & 3] / 1024), 0, attotime::from_hz(clocks[data & 3] / 1024)); + } + + m_pll_ctrl = data; +} + +u8 m68hc05ex_device::timer_ctrl_r() +{ + return m_timer_ctrl; +} + +void m68hc05ex_device::timer_ctrl_w(u8 data) +{ + if ((m_timer_ctrl & 0x80) && !(data & 0x80)) + { + set_input_line(M68HC05EX_INT_TIMER, CLEAR_LINE); + m_timer_ctrl &= ~0x80; + } + else if ((m_timer_ctrl & 0x40) && !(data & 0x40)) + { + set_input_line(M68HC05EX_INT_TIMER, CLEAR_LINE); + m_timer_ctrl &= ~0x40; + } + + m_timer_ctrl &= 0xc0; + m_timer_ctrl |= (data & ~0xc0); +} + +u8 m68hc05ex_device::timer_counter_r() +{ + // this returns an always-incrementing 8-bit value incremented at 1/4th of the CPU's clock rate. + return (total_cycles() / 4) % 256; +} + +u8 m68hc05ex_device::onesec_r() +{ + return m_onesec; +} + +void m68hc05ex_device::onesec_w(u8 data) +{ + m_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1)); + + if ((m_onesec & 0x40) && !(data & 0x40)) + { + set_input_line(M68HC05EX_INT_CPI, CLEAR_LINE); + } + + m_onesec = data; +} + +TIMER_CALLBACK_MEMBER(m68hc05ex_device::seconds_tick) +{ + m_onesec |= 0x40; + + if (m_onesec & 0x10) + { + set_input_line(M68HC05EX_INT_CPI, ASSERT_LINE); + } +} + +TIMER_CALLBACK_MEMBER(m68hc05ex_device::timer_tick) +{ + m_timer_ctrl |= 0x80; + + if (m_timer_ctrl & 0x20) + { + set_input_line(M68HC05EX_INT_TIMER, ASSERT_LINE); + } +} + +// M68HC05E1 +void m68hc05e1_device::m68hc05e1_map(address_map &map) +{ + map(0x0000, 0x0002).rw(FUNC(m68hc05e1_device::ports_r), FUNC(m68hc05e1_device::ports_w)); + map(0x0004, 0x0006).rw(FUNC(m68hc05e1_device::ddrs_r), FUNC(m68hc05e1_device::ddrs_w)); + map(0x0007, 0x0007).rw(FUNC(m68hc05e1_device::pll_r), FUNC(m68hc05e1_device::pll_w)); + map(0x0008, 0x0008).rw(FUNC(m68hc05e1_device::timer_ctrl_r), FUNC(m68hc05e1_device::timer_ctrl_w)); + map(0x0009, 0x0009).r(FUNC(m68hc05e1_device::timer_counter_r)); + map(0x0012, 0x0012).rw(FUNC(m68hc05e1_device::onesec_r), FUNC(m68hc05e1_device::onesec_w)); + map(0x0090, 0x01ff).ram().share(m_internal_ram); // work RAM and stack + map(0x0f00, 0x1fff).rom().region(DEVICE_SELF, 0); +} + +m68hc05e1_device::m68hc05e1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + m68hc05ex_device(mconfig, M68HC05E1, tag, owner, clock, 13, address_map_constructor(FUNC(m68hc05e1_device::m68hc05e1_map), this)), + m_internal_ram(*this, "internal_ram") +{ +} + +m68hc05e1_device::m68hc05e1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int addrbits, address_map_constructor internal_map) : + m68hc05ex_device(mconfig, M68HC05E1, tag, owner, clock, 13, internal_map), + m_internal_ram(*this, "internal_ram") +{ +} + +u8 m68hc05e1_device::read_internal_ram(offs_t offset) +{ + return m_internal_ram[offset]; +} + +void m68hc05e1_device::write_internal_ram(offs_t offset, u8 data) +{ + m_internal_ram[offset] = data; +} + +// M68HC05E5 - Same as E1 with more ROM and SPI and I2C hardware support +void m68hc05e5_device::m68hc05e5_map(address_map &map) +{ + map(0x0000, 0x0002).rw(FUNC(m68hc05e5_device::ports_r), FUNC(m68hc05e5_device::ports_w)); + map(0x0004, 0x0006).rw(FUNC(m68hc05e5_device::ddrs_r), FUNC(m68hc05e5_device::ddrs_w)); + map(0x0007, 0x0007).rw(FUNC(m68hc05e5_device::pll_r), FUNC(m68hc05e5_device::pll_w)); + map(0x0008, 0x0008).rw(FUNC(m68hc05e5_device::timer_ctrl_r), FUNC(m68hc05e5_device::timer_ctrl_w)); + map(0x0009, 0x0009).r(FUNC(m68hc05e5_device::timer_counter_r)); +// map(0x000a, 0x000c) // SSI (SPI) registers + map(0x0012, 0x0012).rw(FUNC(m68hc05e5_device::onesec_r), FUNC(m68hc05e5_device::onesec_w)); + map(0x0090, 0x01ff).ram().share(m_internal_ram); // work RAM and stack + map(0x0b00, 0x1fff).rom().region(DEVICE_SELF, 0); +} + +m68hc05e5_device::m68hc05e5_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + m68hc05e1_device(mconfig, M68HC05E5, tag, owner, clock, 13, address_map_constructor(FUNC(m68hc05e5_device::m68hc05e5_map), this)), + m_internal_ram(*this, "internal_ram") +{ +} + +u8 m68hc05e5_device::read_internal_ram(offs_t offset) +{ + return m_internal_ram[offset]; +} + +void m68hc05e5_device::write_internal_ram(offs_t offset, u8 data) +{ + m_internal_ram[offset] = data; +} diff --git a/src/devices/cpu/m6805/m68hc05e1.h b/src/devices/cpu/m6805/m68hc05e1.h new file mode 100644 index 00000000000..77e9b2afba7 --- /dev/null +++ b/src/devices/cpu/m6805/m68hc05e1.h @@ -0,0 +1,99 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +#ifndef MAME_CPU_M6805_M68HC05E1_H +#define MAME_CPU_M6805_M68HC05E1_H + +#pragma once + +#include "emu.h" +#include "m6805.h" + +class m68hc05ex_device : public m6805_base_device +{ + friend class m68hc05e1_device; + +public: + const address_space_config m_program_config; + + template auto read_p() { return m_read_p[Bit].bind(); } + template auto write_p() { return m_write_p[Bit].bind(); } + template void set_pullups(u8 mask) { m_pullups[Bit] = mask; } + +protected: + // construction/destruction + m68hc05ex_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int addrbits, address_map_constructor internal_map); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual space_config_vector memory_space_config() const override; + + virtual void interrupt_vector() override; + + virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override; + virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override; + virtual std::unique_ptr create_disassembler() override; + + u8 ports_r(offs_t offset); + void ports_w(offs_t offset, u8 data); + u8 ddrs_r(offs_t offset); + void ddrs_w(offs_t offset, u8 data); + u8 read_port(u8 offset); + void send_port(u8 offset, u8 data); + u8 pll_r(); + void pll_w(u8 data); + u8 timer_ctrl_r(); + void timer_ctrl_w(u8 data); + u8 timer_counter_r(); + u8 onesec_r(); + void onesec_w(u8 data); + + devcb_read8::array<5> m_read_p; + devcb_write8::array<5> m_write_p; + + u8 m_ports[4], m_ddrs[4], m_pullups[4]; + u8 m_pll_ctrl; + u8 m_timer_ctrl; + u8 m_onesec; + emu_timer *m_timer, *m_prog_timer; + + TIMER_CALLBACK_MEMBER(seconds_tick); + TIMER_CALLBACK_MEMBER(timer_tick); +}; + +class m68hc05e1_device : public m68hc05ex_device +{ +public: + m68hc05e1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + u8 read_internal_ram(offs_t offset); + void write_internal_ram(offs_t offset, u8 data); + +protected: + m68hc05e1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int addrbits, address_map_constructor internal_map); + + required_shared_ptr m_internal_ram; + +private: + void m68hc05e1_map(address_map &map); +}; + +class m68hc05e5_device : public m68hc05e1_device +{ +public: + m68hc05e5_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + u8 read_internal_ram(offs_t offset); + void write_internal_ram(offs_t offset, u8 data); + +protected: + required_shared_ptr m_internal_ram; + +private: + void m68hc05e5_map(address_map &map); +}; + +DECLARE_DEVICE_TYPE(M68HC05E1, m68hc05e1_device) +DECLARE_DEVICE_TYPE(M68HC05E5, m68hc05e5_device) + +#endif // MAME_CPU_M6805_M58HC05E1_H diff --git a/src/mame/apple/cuda.cpp b/src/mame/apple/cuda.cpp index 7087dbf76d9..6d2d21ba29a 100644 --- a/src/mame/apple/cuda.cpp +++ b/src/mame/apple/cuda.cpp @@ -17,11 +17,11 @@ x------- O ADB data line out -x------ I ADB data line in --x----- I "1" for passive or soft power, "off sense" for secure - ---x---- O DFAC latch + ---x---- O DFAC latch / wake-up ----x--- O "Fast Reset" -----x-- I Keyboard power switch ------x- I 1 for secure or passive power, chassis switch for soft - -------x ? 1 for passive, power supply control on secure/soft power, input on secure/soft also? + -------x ? Power Fail warning, 1 = power ok, 0 = failing Port B: @@ -45,7 +45,7 @@ 341S0285 - No version (x.xx) - PMac 4400 + Mac clones ("Cuda Lite" with 768 bytes more ROM + PS/2 keyboard/mouse support) 341S0060 - 0x00020028 (2.40) - Performa/Quadra 6xx, PMac 6200, x400, some x500, Pippin, "Gossamer" G3, others? (verified found in PMac 5500-225, G3-333) - 341S???? - 0x00020026 (2.38) - Macintosh TV + 341S0789 - 0x00020026 (2.38) - Macintosh TV 341S0788 - 0x00020025 (2.37) - LC 475/575/Quadra 605, Quadra 660AV/840AV, PMac 7200 341S0417 - 0x00020023 (2.35) - Color Classic */ @@ -76,23 +76,16 @@ ROM_START( cuda ) ROM_REGION(0x100, "defaultnv", ROMREGION_ERASE00) ROM_END -void cuda_device::cuda_map(address_map &map) -{ - map(0x0000, 0x0002).rw(FUNC(cuda_device::ports_r), FUNC(cuda_device::ports_w)); - map(0x0004, 0x0006).rw(FUNC(cuda_device::ddr_r), FUNC(cuda_device::ddr_w)); - map(0x0007, 0x0007).rw(FUNC(cuda_device::pll_r), FUNC(cuda_device::pll_w)); - map(0x0008, 0x0008).rw(FUNC(cuda_device::timer_ctrl_r), FUNC(cuda_device::timer_ctrl_w)); - map(0x0009, 0x0009).r(FUNC(cuda_device::timer_counter_r)); - map(0x0012, 0x0012).rw(FUNC(cuda_device::onesec_r), FUNC(cuda_device::onesec_w)); - map(0x0090, 0x00ff).ram().share(m_internal_ram); // work RAM and stack. RTC at 0xab-0xae on 2.37 and 2.40 - map(0x0100, 0x01ff).rw(FUNC(cuda_device::pram_r), FUNC(cuda_device::pram_w)); - map(0x0f00, 0x1fff).rom().region("roms", 0); -} - void cuda_device::device_add_mconfig(machine_config &config) { - M68HC05EG(config, m_maincpu, XTAL(32'768)*128); // Intended to run 4.1 MHz, the ADB timings in uS are twice as long as spec at 2.1 - m_maincpu->set_addrmap(AS_PROGRAM, &cuda_device::cuda_map); + M68HC05E1(config, m_maincpu, XTAL(32'768) * 128); // Intended to run 4.1 MHz, the ADB timings in uS are twice as long as spec at 2.1 + m_maincpu->read_p<0>().set(FUNC(cuda_device::pa_r)); + m_maincpu->read_p<1>().set(FUNC(cuda_device::pb_r)); + m_maincpu->read_p<2>().set(FUNC(cuda_device::pc_r)); + m_maincpu->write_p<0>().set(FUNC(cuda_device::pa_w)); + m_maincpu->write_p<1>().set(FUNC(cuda_device::pb_w)); + m_maincpu->write_p<2>().set(FUNC(cuda_device::pc_w)); + m_maincpu->set_pullups<1>(0xc0); // pull-ups on port B bits 6 & 7 (DFAC/I2C SDA & SCL) } const tiny_rom_entry *cuda_device::device_rom_region() const @@ -113,362 +106,196 @@ cuda_device::cuda_device(const machine_config &mconfig, device_type type, const write_via_data(*this), write_iic_scl(*this), write_iic_sda(*this), + write_dfac_latch(*this), m_maincpu(*this, "cudamcu"), - m_internal_ram(*this, "internal_ram"), - m_rom(*this, "roms"), m_default_nvram(*this, "defaultnv"), - m_pll_ctrl(0), m_timer_ctrl(0), m_onesec(0), - m_treq(0), m_byteack(0), m_tip(0), m_via_data(0), m_via_clock(0), m_last_adb(0), + m_treq(0), m_byteack(0), m_tip(0), m_via_data(0), m_last_adb(0), m_iic_sda(0), m_last_adb_time(0), m_cuda_controls_power(false), m_adb_in(false), m_reset_line(0), m_adb_dtime(0), m_pram_loaded(false) { - std::fill(std::begin(m_pram), std::end(m_pram), 0); std::fill(std::begin(m_disk_pram), std::end(m_disk_pram), 0); - std::fill(std::begin(m_ports), std::end(m_ports), 0); - std::fill(std::begin(m_ddrs), std::end(m_ddrs), 0); } void cuda_device::device_start() { - m_timer = timer_alloc(FUNC(cuda_device::seconds_tick), this); - m_prog_timer = timer_alloc(FUNC(cuda_device::timer_tick), this); - - save_item(NAME(m_ddrs[0])); - save_item(NAME(m_ddrs[1])); - save_item(NAME(m_ddrs[2])); - save_item(NAME(m_ports[0])); - save_item(NAME(m_ports[1])); - save_item(NAME(m_ports[2])); - save_item(NAME(m_pll_ctrl)); - save_item(NAME(m_timer_ctrl)); - save_item(NAME(m_onesec)); save_item(NAME(m_treq)); save_item(NAME(m_byteack)); save_item(NAME(m_tip)); save_item(NAME(m_via_data)); - save_item(NAME(m_via_clock)); save_item(NAME(m_adb_in)); save_item(NAME(m_reset_line)); save_item(NAME(m_adb_dtime)); save_item(NAME(m_pram_loaded)); - save_item(NAME(m_pram)); save_item(NAME(m_disk_pram)); #if ((VERBOSE & LOG_PACKETS) == LOG_PACKETS) - m_maincpu->space().install_read_tap(0xba, 0xba, 0, "cuda", [this](offs_t offset, u8 &data, u8 mem_mask) { - if (m_maincpu->pc() == 0x12b3) { - LOG("Got command %02x\n", data); - } - }); + m_maincpu->space().install_read_tap(0xba, 0xba, 0, "cudamcu", [this](offs_t offset, u8 &data, u8 mem_mask) + { + if (m_maincpu->pc() == 0x12b3) + { + LOG("Got command %02x\n", data); + } + }); #endif + + m_maincpu->space().install_write_tap(4, 4, 0, "cudapfw", [](offs_t offset, u8 &data, u8 mem_mask) + { + // Intercept DDR write for port A to make PFW (bit 0) always an input. The way the Cuda firmware is written + // would not work on a stock 68HC05E1, so it's likely the actual part was lightly customized in this manner. + data &= ~0x01; + return data; + }); } void cuda_device::device_reset() { - m_timer->adjust(attotime::never); - m_prog_timer->adjust(attotime::never); - m_last_adb_time = m_maincpu->total_cycles(); } -void cuda_device::send_port(u8 offset, u8 data) +void cuda_device::pa_w(u8 data) { - switch (offset) - { - case 0: // port A - if ((data & 0x80) != m_last_adb) - { - if (data & 0x80) - { - LOGMASKED(LOG_ADB, "ADB: 1->0 time %lld\n", machine().time().as_ticks(1000000) - m_last_adb_time); - } - else - { - LOGMASKED(LOG_ADB, "ADB: 0->1 time %lld\n", machine().time().as_ticks(1000000) - m_last_adb_time); - } - - // allow the linechange handler to override us - m_adb_in = (data & 0x80) ? true : false; + write_dfac_latch(BIT(data, 4)); - m_adb_dtime = (int)(machine().time().as_ticks(1000000) - m_last_adb_time); - write_linechange(((data & 0x80) >> 7) ^ 1); + if ((data & 0x80) != m_last_adb) + { + if (data & 0x80) + { + LOGMASKED(LOG_ADB, "ADB: 1->0 time %lld\n", machine().time().as_ticks(1000000) - m_last_adb_time); + } + else + { + LOGMASKED(LOG_ADB, "ADB: 0->1 time %lld\n", machine().time().as_ticks(1000000) - m_last_adb_time); + } - m_last_adb = data & 0x80; - m_last_adb_time = machine().time().as_ticks(1000000); - } - break; + // allow the linechange handler to override us + m_adb_in = (data & 0x80) ? true : false; - case 1: // port B - { - if (m_treq != ((data>>1)&1)) - { - LOGMASKED(LOG_HOSTCOMM, "CU-> TREQ: %d (PC=%x)\n", (data>>1)&1, m_maincpu->pc()); - m_treq = (data>>1) & 1; - } - if (m_via_data != ((data>>5)&1)) - { - LOGMASKED(LOG_HOSTCOMM, "CU-> VIA_DATA: %d (PC=%x)\n", (data>>5)&1, m_maincpu->pc()); - m_via_data = (data>>5) & 1; - write_via_data(m_via_data); - } - if (m_via_clock != ((data>>4)&1)) - { - LOGMASKED(LOG_HOSTCOMM, "CU-> VIA_CLOCK: %d (PC=%x)\n", ((data>>4)&1)^1, m_maincpu->pc()); - m_via_clock = (data>>4) & 1; - write_via_clock(m_via_clock); - } - } - break; + m_adb_dtime = (int)(machine().time().as_ticks(1000000) - m_last_adb_time); + write_linechange(((data & 0x80) >> 7) ^ 1); - case 2: // port C - if ((data & 8) != m_reset_line) - { - LOGMASKED(LOG_HOSTCOMM, "680x0 reset: %d -> %d (PC=%x)\n", (m_ports[2] & 8)>>3, (data & 8)>>3, m_maincpu->pc()); - m_reset_line = (data & 8); - // falling edge, should reset the machine too - if ((m_ports[2] & 8) && !(data&8)) - { - write_reset(ASSERT_LINE); - write_reset(CLEAR_LINE); - - // if PRAM's waiting to be loaded, transfer it now - if (!m_pram_loaded) - { - memcpy(m_pram, m_disk_pram, 0x100); - - system_time systime; - struct tm cur_time, macref; - machine().current_datetime(systime); - - cur_time.tm_sec = systime.local_time.second; - cur_time.tm_min = systime.local_time.minute; - cur_time.tm_hour = systime.local_time.hour; - cur_time.tm_mday = systime.local_time.mday; - cur_time.tm_mon = systime.local_time.month; - cur_time.tm_year = systime.local_time.year - 1900; - cur_time.tm_isdst = 0; - - macref.tm_sec = 0; - macref.tm_min = 0; - macref.tm_hour = 0; - macref.tm_mday = 1; - macref.tm_mon = 0; - macref.tm_year = 4; - macref.tm_isdst = 0; - u32 ref = (u32)mktime(¯ef); - - u32 seconds = (u32)((u32)mktime(&cur_time) - ref); - m_internal_ram[0xae - 0x90] = seconds & 0xff; - m_internal_ram[0xad - 0x90] = (seconds >> 8) & 0xff; - m_internal_ram[0xac - 0x90] = (seconds >> 16) & 0xff; - m_internal_ram[0xab - 0x90] = (seconds >> 24) & 0xff; - - LOGMASKED(LOG_PRAM, "Syncing PRAM to saved/default and RTC to current date/time %08x\n", seconds); - m_pram_loaded = true; - } - } - } - break; + m_last_adb = data & 0x80; + m_last_adb_time = machine().time().as_ticks(1000000); } } -u8 cuda_device::ddr_r(offs_t offset) -{ - return m_ddrs[offset]; -} - -void cuda_device::ddr_w(offs_t offset, u8 data) +void cuda_device::pb_w(u8 data) { - send_port(offset, m_ports[offset] & data); - - m_ddrs[offset] = data; - - if (offset == 1) // port B + if (m_treq != BIT(data, 1)) { - // For IIC, Cuda sets the SCL and SDA data bits to 0 and toggles the lines - // purely with the DDRs. When DDR is set, the 0 is driven onto the line and - // the line is 0. When DDR is clear, the line is not driven by the 68HC05 and - // external pullup resistors drive the line to a 1. - - // If both SCL and SDA data are 0, we're doing IIC - if ((m_ports[offset] & 0x80) == 0) - { - u8 iic_data = (data & 0xc0) ^ 0xc0; - LOGMASKED(LOG_I2C, "I2C: SCL %d SDA %d\n", BIT(iic_data, 7), BIT(iic_data, 6)); - write_iic_sda(BIT(iic_data, 6)); - write_iic_scl(BIT(iic_data, 7)); - } + LOGMASKED(LOG_HOSTCOMM, "CU-> TREQ: %d (PC=%x)\n", (data>>1)&1, m_maincpu->pc()); + m_treq = (data>>1) & 1; } + + LOGMASKED(LOG_HOSTCOMM, "CU-> VIA_DATA: %d VIA_CLOCK %d (PC=%x)\n", BIT(data, 5), BIT(data, 4), m_maincpu->pc()); + write_via_data(BIT(data, 5)); + write_via_clock(BIT(data, 4)); +// printf("SDA: %d SCL: %d\n", BIT(data, 6), BIT(data, 7)); + write_iic_sda(BIT(data, 6)); + write_iic_scl(BIT(data, 7)); } -u8 cuda_device::ports_r(offs_t offset) +void cuda_device::pc_w(u8 data) { - u8 incoming = 0; - - switch (offset) + if ((data & 8) != m_reset_line) { - case 0: // port A - if (m_cuda_controls_power) - { - incoming = 0x20; // pull up + chassis switch (which is 0 = on) - } - else - { - incoming = 0x02 | 0x01; // pull-up + PFW - } + LOGMASKED(LOG_HOSTCOMM, "680x0 reset: %d -> %d (PC=%x)\n", m_reset_line, BIT(data, 3), m_maincpu->pc()); + // falling edge, should reset the machine too + if (!m_reset_line && BIT(data, 3)) + { + write_reset(ASSERT_LINE); + write_reset(CLEAR_LINE); + m_reset_line = BIT(data, 3); - if (m_adb_in) + // if PRAM's waiting to be loaded, transfer it now + if (!m_pram_loaded) { - incoming |= 0x40; - } - break; - - case 1: // port B - incoming |= 0x01; // +5v sense - incoming |= m_byteack<<2; - incoming |= m_tip<<3; - incoming |= m_via_data<<5; - incoming |= m_iic_sda ? 0x40 : 0; - incoming |= 0x80; - break; - - case 2: // port C - if (m_cuda_controls_power) - { - incoming = 0x02 | 0x01; // soft power: trickle sense + pull-up - } - else - { - incoming = 0x02 | 0x01; // secure power: pull-up + file server - } - break; - } - - // apply data direction registers - incoming &= (m_ddrs[offset] ^ 0xff); - // add in ddr-masked version of port writes - incoming |= (m_ports[offset] & m_ddrs[offset]); + for (int byte = 0; byte < 256; byte++) + { + m_maincpu->write_internal_ram(0x70 + byte, m_disk_pram[byte]); + } - // HACK: don't know how this works on h/w... - if (!offset) - { - incoming |= 0x01; + system_time systime; + struct tm cur_time, macref; + machine().current_datetime(systime); + + cur_time.tm_sec = systime.local_time.second; + cur_time.tm_min = systime.local_time.minute; + cur_time.tm_hour = systime.local_time.hour; + cur_time.tm_mday = systime.local_time.mday; + cur_time.tm_mon = systime.local_time.month; + cur_time.tm_year = systime.local_time.year - 1900; + cur_time.tm_isdst = 0; + + macref.tm_sec = 0; + macref.tm_min = 0; + macref.tm_hour = 0; + macref.tm_mday = 1; + macref.tm_mon = 0; + macref.tm_year = 4; + macref.tm_isdst = 0; + u32 ref = (u32)mktime(¯ef); + + u32 seconds = (u32)((u32)mktime(&cur_time) - ref); + m_maincpu->write_internal_ram(0xae - 0x90, seconds & 0xff); + m_maincpu->write_internal_ram(0xad - 0x90, (seconds >> 8) & 0xff); + m_maincpu->write_internal_ram(0xac - 0x90, (seconds >> 16) & 0xff); + m_maincpu->write_internal_ram(0xab - 0x90, (seconds >> 24) & 0xff); + + LOGMASKED(LOG_PRAM, "Syncing PRAM to saved/default and RTC to current date/time %08x\n", seconds); + m_pram_loaded = true; + } + } } - - return incoming; -} - -void cuda_device::ports_w(offs_t offset, u8 data) -{ - send_port(offset, data); - - m_ports[offset] = data; } -u8 cuda_device::pll_r() +u8 cuda_device::pa_r() { - return m_pll_ctrl; -} + u8 rv = 0; -void cuda_device::pll_w(u8 data) -{ - // Motorola documentation for both the 68HC05E1 and E5 says that rate 3 (4 MHz) is illegal. - // The Cuda code sets it to 2 MHz, but comments in the code as well as the cycle counts in - // the ADB routines indicate the CPU is intended to run at 4.2 MHz, not 2.1. - // So we do this little cheat. - if ((data & 3) == 2) + if (m_cuda_controls_power) { - data |= 3; + rv = 0x20 | 0x01; // pull up + chassis switch (which is 0 = on) } - - if (m_pll_ctrl != data) + else { - static const int clocks[4] = { 524288, 1048576, 2097152, 4194304 }; - LOG("PLL ctrl: clock %d TCS:%d BCS:%d AUTO:%d BWC:%d PLLON:%d (PC=%x)\n", clocks[data&3], - (data & 0x80) ? 1 : 0, - (data & 0x40) ? 1 : 0, - (data & 0x20) ? 1 : 0, - (data & 0x10) ? 1 : 0, - (data & 0x08) ? 1 : 0, m_maincpu->pc()); - - m_prog_timer->adjust(attotime::from_hz(clocks[data & 3]/1024), 0, attotime::from_hz(clocks[data & 3]/1024)); + rv = 0x02 | 0x01; // pull-up + PFW } - m_pll_ctrl = data; -} -u8 cuda_device::timer_ctrl_r() -{ - return m_timer_ctrl; -} - -void cuda_device::timer_ctrl_w(u8 data) -{ - if ((m_timer_ctrl & 0x80) && !(data & 0x80)) + if (m_adb_in) { - m_maincpu->set_input_line(M68HC05EG_INT_TIMER, CLEAR_LINE); - m_timer_ctrl &= ~0x80; + rv |= 0x40; } - else if ((m_timer_ctrl & 0x40) && !(data & 0x40)) - { - m_maincpu->set_input_line(M68HC05EG_INT_TIMER, CLEAR_LINE); - m_timer_ctrl &= ~0x40; - } - - m_timer_ctrl &= 0xc0; - m_timer_ctrl |= (data & ~0xc0); -} -u8 cuda_device::timer_counter_r() -{ - // this returns an always-incrementing 8-bit value incremented at 1/4th of the CPU's clock rate. - return (m_maincpu->total_cycles() / 4) % 256; + return rv; } -u8 cuda_device::onesec_r() +u8 cuda_device::pb_r() { - return m_onesec; -} - -void cuda_device::onesec_w(u8 data) -{ - m_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1)); - - if ((m_onesec & 0x40) && !(data & 0x40)) - { - m_maincpu->set_input_line(M68HC05EG_INT_CPI, CLEAR_LINE); - } + u8 rv = 0; - m_onesec = data; -} + rv |= 0x01; // +5v sense + rv |= m_byteack << 2; + rv |= m_tip << 3; + rv |= m_via_data << 5; + rv |= m_iic_sda ? 0x40 : 0; + rv |= 0x80; -u8 cuda_device::pram_r(offs_t offset) -{ - return m_pram[offset]; + return rv; } -void cuda_device::pram_w(offs_t offset, u8 data) +u8 cuda_device::pc_r() { - m_pram[offset] = data; -} + u8 rv = 0; -TIMER_CALLBACK_MEMBER(cuda_device::seconds_tick) -{ - m_onesec |= 0x40; - - if (m_onesec & 0x10) + if (m_cuda_controls_power) { - m_maincpu->set_input_line(M68HC05EG_INT_CPI, ASSERT_LINE); + rv = 0x02 | 0x01; // soft power: trickle sense + pull-up } -} - -TIMER_CALLBACK_MEMBER(cuda_device::timer_tick) -{ - m_timer_ctrl |= 0x80; - - if (m_timer_ctrl & 0x20) + else { - m_maincpu->set_input_line(M68HC05EG_INT_TIMER, ASSERT_LINE); + rv = 0x02 | 0x01; // secure power: pull-up + file server } + return rv; } // The 6805 program clears PRAM on startup (on h/w it's always running once a battery is inserted). @@ -477,7 +304,6 @@ TIMER_CALLBACK_MEMBER(cuda_device::timer_tick) void cuda_device::nvram_default() { LOGMASKED(LOG_PRAM, "Using default PRAM\n"); - memset(m_pram, 0, 0x100); memcpy(m_disk_pram, m_default_nvram, 256); m_pram_loaded = false; } @@ -497,14 +323,19 @@ bool cuda_device::nvram_read(util::read_stream &file) bool cuda_device::nvram_write(util::write_stream &file) { LOGMASKED(LOG_PRAM, "Writing PRAM to disk\n"); - auto const [err, actual] = write(file, m_pram, 0x100); + for (int byte = 0; byte < 256; byte++) + { + m_disk_pram[byte] = m_maincpu->read_internal_ram(0x70 + byte); + } + + auto const [err, actual] = write(file, m_disk_pram, 0x100); return !err; } // Cuda v2.XX ------------------------------------------------------------------------ ROM_START( cuda2xx ) - ROM_REGION(0x1100, "roms", 0) + ROM_REGION(0x1100, "cudamcu", 0) ROM_DEFAULT_BIOS("341s0788") ROM_SYSTEM_BIOS(0, "341s0417", "Cuda 2.35 (341S0417)") @@ -535,16 +366,8 @@ cuda_2xx_device::cuda_2xx_device(const machine_config &mconfig, const char *tag, // Cuda v3.02 ------------------------------------------------------------------------ -void cuda_302_device::cuda_map(address_map &map) -{ - cuda_device::cuda_map(map); - map(0x000b, 0x000b).r(FUNC(cuda_302_device::portb_r)); - map(0x0080, 0x008f).ram(); - map(0x0b00, 0x1fff).rom().region("roms", 0); -} - ROM_START( cuda302 ) - ROM_REGION(0x1500, "roms", 0) + ROM_REGION(0x1500, "cudamcu", 0) ROM_LOAD( "341s0262.bin", 0x0000, 0x1500, CRC(f43a803d) SHA1(c9b2f2c4ea174a01073a9d20b16b362ddc3715a6) ) ROM_REGION(0x100, "defaultnv", 0) @@ -556,33 +379,45 @@ const tiny_rom_entry *cuda_302_device::device_rom_region() const return ROM_NAME( cuda302 ); } -cuda_302_device::cuda_302_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - cuda_device(mconfig, CUDA_V302, tag, owner, clock) +void cuda_302_device::device_add_mconfig(machine_config &config) { + M68HC05E5(config, m_maincpu, XTAL(32'768) * 128); // Intended to run 4.1 MHz, the ADB timings in uS are twice as long as spec at 2.1 + m_maincpu->read_p<0>().set(FUNC(cuda_302_device::pa_r)); + m_maincpu->read_p<1>().set(FUNC(cuda_302_device::pb_r)); + m_maincpu->read_p<2>().set(FUNC(cuda_302_device::pc_r)); + m_maincpu->write_p<0>().set(FUNC(cuda_302_device::pa_w)); + m_maincpu->write_p<1>().set(FUNC(cuda_302_device::pb_w)); + m_maincpu->write_p<2>().set(FUNC(cuda_302_device::pc_w)); + m_maincpu->set_pullups<1>(0xc0); // pull-ups on port B bits 6 & 7 (DFAC/I2C SDA & SCL) } -u8 cuda_302_device::portb_r() +cuda_302_device::cuda_302_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + cuda_device(mconfig, CUDA_V302, tag, owner, clock) { - return 0x80; } // Cuda Lite ------------------------------------------------------------------------ -void cuda_lite_device::cuda_map(address_map &map) -{ - cuda_device::cuda_map(map); - map(0x000b, 0x000b).r(FUNC(cuda_lite_device::portb_r)); - map(0x0080, 0x008f).ram(); - map(0x0c00, 0x1fff).rom().region("roms", 0); -} ROM_START( cudalite ) - ROM_REGION(0x1400, "roms", 0) - ROM_LOAD( "341s0285.bin", 0x0000, 0x1400, CRC(ba2707da) SHA1(3fb8d610cd738699b2981d37e9fa37c1e515a423) ) + ROM_REGION(0x1500, "cudamcu", 0) + ROM_LOAD( "341s0285.bin", 0x0100, 0x1400, CRC(ba2707da) SHA1(3fb8d610cd738699b2981d37e9fa37c1e515a423) ) ROM_REGION(0x100, "defaultnv", 0) ROM_LOAD( "cuda_nvram.bin", 0x000000, 0x000100, CRC(6e3da389) SHA1(e5b13a2a904cc9fc612ed25b76718c501c11b00a) ) ROM_END +void cuda_lite_device::device_add_mconfig(machine_config &config) +{ + M68HC05E5(config, m_maincpu, XTAL(32'768) * 128); // Intended to run 4.1 MHz, the ADB timings in uS are twice as long as spec at 2.1 + m_maincpu->read_p<0>().set(FUNC(cuda_lite_device::pa_r)); + m_maincpu->read_p<1>().set(FUNC(cuda_lite_device::pb_r)); + m_maincpu->read_p<2>().set(FUNC(cuda_lite_device::pc_r)); + m_maincpu->write_p<0>().set(FUNC(cuda_lite_device::pa_w)); + m_maincpu->write_p<1>().set(FUNC(cuda_lite_device::pb_w)); + m_maincpu->write_p<2>().set(FUNC(cuda_lite_device::pc_w)); + m_maincpu->set_pullups<1>(0xc0); // pull-ups on port B bits 6 & 7 (DFAC/I2C SDA & SCL) +} + const tiny_rom_entry *cuda_lite_device::device_rom_region() const { return ROM_NAME( cudalite ); @@ -592,8 +427,3 @@ cuda_lite_device::cuda_lite_device(const machine_config &mconfig, const char *ta cuda_device(mconfig, CUDA_LITE, tag, owner, clock) { } - -u8 cuda_lite_device::portb_r() -{ - return 0x80; -} diff --git a/src/mame/apple/cuda.h b/src/mame/apple/cuda.h index 754d943b813..f87bdcd40aa 100644 --- a/src/mame/apple/cuda.h +++ b/src/mame/apple/cuda.h @@ -5,9 +5,11 @@ #pragma once +#include "cpu/m6805/m68hc05e1.h" + /// \brief Base class for Apple Cuda devices. /// -/// Cuda is a semi-custom Motorola 68HC05 microcontroller with +/// Cuda is a semi-custom Motorola 68HC05E1 microcontroller with /// on-board RAM and ROM plus several GPIO pins. Cuda handles /// simple power management, the Apple Desktop Bus, I2C, real-time /// clock, and parameter RAM. @@ -22,27 +24,12 @@ public: virtual bool nvram_read(util::read_stream &file) override; virtual bool nvram_write(util::write_stream &file) override; - u8 ddr_r(offs_t offset); - void ddr_w(offs_t offset, u8 data); - u8 ports_r(offs_t offset); - void ports_w(offs_t offset, u8 data); - u8 pll_r(); - void pll_w(u8 data); - u8 timer_ctrl_r(); - void timer_ctrl_w(u8 data); - u8 timer_counter_r(); - u8 onesec_r(); - void onesec_w(u8 data); - u8 pram_r(offs_t offset); - void pram_w(offs_t offset, u8 data); - // VIA interface routines u8 get_treq() { return m_treq; } void set_tip(u8 val) { m_tip = val; } void set_byteack(u8 val) { m_byteack = val; } u8 get_via_data() { return m_via_data; } void set_via_data(u8 dat) { m_via_data = dat; } - u8 get_via_clock() { return m_via_clock; } void set_adb_line(int linestate) { m_adb_in = (linestate == ASSERT_LINE) ? true : false; } void set_iic_sda(u8 data) { m_iic_sda = (data & 1); } int get_adb_dtime() { return m_adb_dtime; } @@ -55,10 +42,10 @@ public: auto via_data_callback() { return write_via_data.bind(); } auto iic_scl_callback() { return write_iic_scl.bind(); } auto iic_sda_callback() { return write_iic_sda.bind(); } + auto dfac_latch_callback() { return write_dfac_latch.bind(); } - devcb_write_line write_reset, write_linechange, write_via_clock, write_via_data, write_iic_scl, write_iic_sda; - - virtual void cuda_map(address_map &map); + devcb_write_line write_reset, write_linechange, write_via_clock, write_via_data; + devcb_write_line write_iic_scl, write_iic_sda, write_dfac_latch; protected: // device-level overrides @@ -67,32 +54,26 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual const tiny_rom_entry *device_rom_region() const override; - TIMER_CALLBACK_MEMBER(seconds_tick); - TIMER_CALLBACK_MEMBER(timer_tick); - - required_device m_maincpu; - required_shared_ptr m_internal_ram; - required_region_ptr m_rom; + required_device m_maincpu; required_region_ptr m_default_nvram; + u8 pa_r(); + u8 pb_r(); + u8 pc_r(); + void pa_w(u8 data); + void pb_w(u8 data); + void pc_w(u8 data); + private: - u8 m_ddrs[3]{}; - u8 m_ports[3]{}; - u8 m_pll_ctrl; - u8 m_timer_ctrl; - u8 m_onesec; - u8 m_treq, m_byteack, m_tip, m_via_data, m_via_clock, m_last_adb; + u8 m_treq, m_byteack, m_tip, m_via_data, m_last_adb; u8 m_iic_sda; u64 m_last_adb_time; bool m_cuda_controls_power; bool m_adb_in; s32 m_reset_line; s32 m_adb_dtime; - emu_timer *m_timer, *m_prog_timer; - u8 m_pram[0x100]{}, m_disk_pram[0x100]{}; + u8 m_disk_pram[0x100]{}; bool m_pram_loaded; - - void send_port(u8 offset, u8 data); }; class cuda_2xx_device : public cuda_device @@ -109,27 +90,23 @@ class cuda_302_device : public cuda_device public: cuda_302_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - void cuda_map(address_map &map) override; - protected: virtual const tiny_rom_entry *device_rom_region() const override; + virtual void device_add_mconfig(machine_config &config) override; private: - u8 portb_r(); }; class cuda_lite_device : public cuda_device { public: cuda_lite_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - - void cuda_map(address_map &map) override; + virtual void device_add_mconfig(machine_config &config) override; protected: virtual const tiny_rom_entry *device_rom_region() const override; private: - u8 portb_r(); }; // device type definition diff --git a/src/mame/apple/egret.cpp b/src/mame/apple/egret.cpp index 59d152ded5b..b076ba14ab2 100644 --- a/src/mame/apple/egret.cpp +++ b/src/mame/apple/egret.cpp @@ -53,20 +53,19 @@ #include "emu.h" #include "egret.h" -#include "cpu/m6805/m6805.h" #define LOG_ADB (1U << 1) // low-level ADB details -#define LOG_I2C (1U << 2) // low-level I2C details -#define LOG_PRAM (1U << 3) // PRAM handling info -#define LOG_HOSTCOMM (1U << 4) // communications with the host +#define LOG_PRAM (1U << 2) // PRAM handling info +#define LOG_HOSTCOMM (1U << 3) // communications with the host #define VERBOSE (0) + #include "logmacro.h" DEFINE_DEVICE_TYPE(EGRET, egret_device, "egret", "Apple Egret ADB/I2C") ROM_START( egret ) - ROM_REGION(0x1100, "roms", 0) + ROM_REGION(0x1100, "egret", 0) ROM_DEFAULT_BIOS("341s0851") ROM_SYSTEM_BIOS(0, "344s0100", "Egret 1.00 (344S0100)") @@ -79,34 +78,18 @@ ROM_START( egret ) ROMX_LOAD("341s0851.bin", 0x0000, 0x1100, CRC(ea9ea6e4) SHA1(8b0dae3ec66cdddbf71567365d2c462688aeb571), ROM_BIOS(2)) ROM_END -//------------------------------------------------- -// ADDRESS_MAP -//------------------------------------------------- - -void egret_device::egret_map(address_map &map) -{ - map(0x0000, 0x0002).rw(FUNC(egret_device::ports_r), FUNC(egret_device::ports_w)); - map(0x0004, 0x0006).rw(FUNC(egret_device::ddr_r), FUNC(egret_device::ddr_w)); - map(0x0007, 0x0007).rw(FUNC(egret_device::pll_r), FUNC(egret_device::pll_w)); - map(0x0008, 0x0008).rw(FUNC(egret_device::timer_ctrl_r), FUNC(egret_device::timer_ctrl_w)); - map(0x0009, 0x0009).rw(FUNC(egret_device::timer_counter_r), FUNC(egret_device::timer_counter_w)); - map(0x0012, 0x0012).rw(FUNC(egret_device::onesec_r), FUNC(egret_device::onesec_w)); - map(0x0090, 0x00ff).ram().share(m_internal_ram); // work RAM and stack - map(0x0100, 0x01ff).rw(FUNC(egret_device::pram_r), FUNC(egret_device::pram_w)); - map(0x0f00, 0x1fff).rom().region("roms", 0); -} - - -//------------------------------------------------- -// device_add_mconfig - add device configuration -//------------------------------------------------- - void egret_device::device_add_mconfig(machine_config &config) { - M68HC05EG(config, m_maincpu, XTAL(32'768)*128); // Intended to run 4.1 MHz, the ADB timings in uS are twice as long as spec at 2.1 - m_maincpu->set_addrmap(AS_PROGRAM, &egret_device::egret_map); + M68HC05E1(config, m_maincpu, XTAL(32'768)*128); // Intended to run 4.1 MHz, the ADB timings are twice as long as spec at 2.048 MHz + m_maincpu->read_p<0>().set(FUNC(egret_device::pa_r)); + m_maincpu->read_p<1>().set(FUNC(egret_device::pb_r)); + m_maincpu->read_p<2>().set(FUNC(egret_device::pc_r)); + m_maincpu->write_p<0>().set(FUNC(egret_device::pa_w)); + m_maincpu->write_p<1>().set(FUNC(egret_device::pb_w)); + m_maincpu->write_p<2>().set(FUNC(egret_device::pc_w)); + m_maincpu->set_pullups<1>(0x40); // pull-up on port B bit 6 - #if USE_BUS_ADB +#if USE_BUS_ADB ADB_CONNECTOR(config, "adb1", adb_device::default_devices, "a9m0330", false); #endif } @@ -116,9 +99,6 @@ const tiny_rom_entry *egret_device::device_rom_region() const return ROM_NAME( egret ); } -//************************************************************************** -// LIVE DEVICE -//************************************************************************** egret_device::egret_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, EGRET, tag, owner, clock), device_nvram_interface(mconfig, *this), @@ -126,24 +106,19 @@ egret_device::egret_device(const machine_config &mconfig, const char *tag, devic write_linechange(*this), write_via_clock(*this), write_via_data(*this), - write_iic_scl(*this), - write_iic_sda(*this), + write_dfac_scl(*this), + write_dfac_sda(*this), + write_dfac_latch(*this), m_maincpu(*this, "egret"), - m_internal_ram(*this, "internal_ram"), - m_rom(*this, "roms"), - m_pll_ctrl(0), m_timer_ctrl(0), m_onesec(0), - m_xcvr_session(0), m_via_full(0), m_sys_session(0), m_via_data(0), m_via_clock(0), m_last_adb(0), + m_xcvr_session(0), m_via_full(0), m_sys_session(0), m_via_data(0), m_last_adb(0), m_last_adb_time(0), m_egret_controls_power(false), m_adb_in(false), - m_reset_line(0), m_adb_dtime(0), m_pram_loaded(false), m_iic_sda(1) + m_reset_line(0), m_adb_dtime(0), m_pram_loaded(false) #if USE_BUS_ADB , m_adb_connector{{*this, "adb1"}, {*this, finder_base::DUMMY_TAG}} #endif { - std::fill(std::begin(m_pram), std::end(m_pram), 0); std::fill(std::begin(m_disk_pram), std::end(m_disk_pram), 0); - std::fill(std::begin(m_ports), std::end(m_ports), 0); - std::fill(std::begin(m_ddrs), std::end(m_ddrs), 0); } void egret_device::device_start() @@ -154,36 +129,20 @@ void egret_device::device_start() m_adb_device[i] = m_adb_connector[i] ? m_adb_connector[i]->get_device() : nullptr; if (m_adb_device[i]) { - m_adb_device[i]->adb_r().set([this, i](int state) - { adb_w(i, state); }); - m_adb_device[i]->poweron_r().set([this, i](int state) - { adb_poweron_w(i, state); }); + m_adb_device[i]->adb_r().set([this, i](int state) { adb_w(i, state); }); + m_adb_device[i]->poweron_r().set([this, i](int state) { adb_poweron_w(i, state); }); } } #endif - m_timer = timer_alloc(FUNC(egret_device::seconds_tick), this); - - save_item(NAME(m_ddrs[0])); - save_item(NAME(m_ddrs[1])); - save_item(NAME(m_ddrs[2])); - save_item(NAME(m_ports[0])); - save_item(NAME(m_ports[1])); - save_item(NAME(m_ports[2])); - save_item(NAME(m_pll_ctrl)); - save_item(NAME(m_timer_ctrl)); - save_item(NAME(m_timer_counter)); - save_item(NAME(m_onesec)); save_item(NAME(m_xcvr_session)); save_item(NAME(m_via_full)); save_item(NAME(m_sys_session)); save_item(NAME(m_via_data)); - save_item(NAME(m_via_clock)); save_item(NAME(m_adb_in)); save_item(NAME(m_reset_line)); save_item(NAME(m_adb_dtime)); save_item(NAME(m_pram_loaded)); - save_item(NAME(m_pram)); save_item(NAME(m_disk_pram)); #if USE_BUS_ADB save_item(NAME(m_adb_out)); @@ -199,7 +158,6 @@ void egret_device::device_reset() m_adb_device_poweron[0] = m_adb_device_poweron[1] = true; #endif - m_timer->adjust(attotime::never); m_last_adb_time = m_maincpu->total_cycles(); } @@ -218,7 +176,7 @@ void egret_device::adb_poweron_w(int id, int state) void egret_device::adb_change() { bool adb = m_adb_out & m_adb_device_out[0] & m_adb_device_out[1]; - logerror("adb c:%d 1:%d 2:%d -> %d (%02x %02x)\n", m_adb_out, m_adb_device_out[0], m_adb_device_out[1], adb, ddrs[0], ports[0]); + LOG("adb c:%d 1:%d 2:%d -> %d (%02x %02x)\n", m_adb_out, m_adb_device_out[0], m_adb_device_out[1], adb, ddrs[0], ports[0]); for (int i = 0; i != 2; i++) if (m_adb_device[i]) { @@ -227,280 +185,151 @@ void egret_device::adb_change() } #endif -void egret_device::send_port(u8 offset, u8 data) +void egret_device::pa_w(u8 data) { - switch (offset) - { - case 0: // port A + write_dfac_latch(BIT(data, 4)); + #if USE_BUS_ADB - // the line goes to a mosfet pulling the adb data line to graound, hence the inversion - m_adb_out = !(data & 0x80); - adb_change(); + // the line goes to a mosfet pulling the adb data line to ground, hence the inversion + m_adb_out = !(data & 0x80); + adb_change(); #else - if ((data & 0x80) != m_last_adb) - { - m_adb_dtime = (int)(machine().time().as_ticks(1000000) - m_last_adb_time); - - if (data & 0x80) - { - LOGMASKED(LOG_ADB, "ADB: 1->0 time %lld\n", machine().time().as_ticks(1000000) - m_last_adb_time); - } - else - { - LOGMASKED(LOG_ADB, "ADB: 0->1 time %lld\n", machine().time().as_ticks(1000000) - m_last_adb_time); - } - - // allow the linechange handler to override us - m_adb_in = (data & 0x80) ? true : false; - - write_linechange(((data & 0x80) >> 7) ^ 1); - - m_last_adb = data & 0x80; - m_last_adb_time = machine().time().as_ticks(1000000); - } -#endif - break; + if ((data & 0x80) != m_last_adb) + { + m_adb_dtime = (int)(machine().time().as_ticks(1000000) - m_last_adb_time); - case 1: // port B - { - if (m_xcvr_session != ((data>>1)&1)) - { - LOGMASKED(LOG_HOSTCOMM, "EG-> XCVR_SESSION: %d (PC=%x)\n", (data>>1)&1, m_maincpu->pc()); - m_xcvr_session = (data>>1) & 1; - } - if (m_via_data != ((data>>5)&1)) - { - LOGMASKED(LOG_HOSTCOMM, "EG-> VIA_DATA: %d (PC=%x)\n", (data >> 5) & 1, m_maincpu->pc()); - m_via_data = (data>>5) & 1; - write_via_data(m_via_data); - } - if (m_via_clock != ((data>>4)&1)) - { - LOGMASKED(LOG_HOSTCOMM, "EG-> VIA_CLOCK: %d (PC=%x)\n", ((data >> 4) & 1) ^ 1, m_maincpu->pc()); - m_via_clock = (data>>4) & 1; - write_via_clock(m_via_clock); - } - } - break; + if (data & 0x80) + { + LOGMASKED(LOG_ADB, "ADB: 1->0 time %lld\n", machine().time().as_ticks(1000000) - m_last_adb_time); + } + else + { + LOGMASKED(LOG_ADB, "ADB: 0->1 time %lld\n", machine().time().as_ticks(1000000) - m_last_adb_time); + } - case 2: // port C - if ((data & 8) != m_reset_line) - { - LOGMASKED(LOG_HOSTCOMM, "680x0 reset: %d -> %d\n", (m_ports[2] & 8)>>3, (data & 8)>>3); - m_reset_line = (data & 8); + // allow the linechange handler to override us + m_adb_in = (data & 0x80) ? true : false; - // falling edge, should reset the machine too - if ((m_ports[2] & 8) && !(data&8)) - { - // if PRAM's waiting to be loaded, transfer it now - if (!m_pram_loaded) - { - memcpy(m_pram, m_disk_pram, 0x100); - m_pram_loaded = true; - - system_time systime; - struct tm cur_time, macref; - machine().current_datetime(systime); - - cur_time.tm_sec = systime.local_time.second; - cur_time.tm_min = systime.local_time.minute; - cur_time.tm_hour = systime.local_time.hour; - cur_time.tm_mday = systime.local_time.mday; - cur_time.tm_mon = systime.local_time.month; - cur_time.tm_year = systime.local_time.year - 1900; - cur_time.tm_isdst = 0; - - macref.tm_sec = 0; - macref.tm_min = 0; - macref.tm_hour = 0; - macref.tm_mday = 1; - macref.tm_mon = 0; - macref.tm_year = 4; - macref.tm_isdst = 0; - u32 ref = (u32)mktime(¯ef); - - u32 seconds = (u32)((u32)mktime(&cur_time) - ref); - m_internal_ram[0xae - 0x90] = seconds & 0xff; - m_internal_ram[0xad - 0x90] = (seconds >> 8) & 0xff; - m_internal_ram[0xac - 0x90] = (seconds >> 16) & 0xff; - m_internal_ram[0xab - 0x90] = (seconds >> 24) & 0xff; - - LOGMASKED(LOG_PRAM, "Syncing PRAM to saved/default and RTC to current date/time %08x\n", seconds); - } - } + write_linechange(((data & 0x80) >> 7) ^ 1); - write_reset((m_reset_line & 8) ? ASSERT_LINE : CLEAR_LINE); - } - break; + m_last_adb = data & 0x80; + m_last_adb_time = machine().time().as_ticks(1000000); } +#endif } -u8 egret_device::ddr_r(offs_t offset) +void egret_device::pb_w(u8 data) { - return m_ddrs[offset]; + if (m_xcvr_session != BIT(data, 1)) + { + LOGMASKED(LOG_HOSTCOMM, "EG-> XCVR_SESSION: %d (PC=%x)\n", (data >> 1) & 1, m_maincpu->pc()); + m_xcvr_session = BIT(data, 1); + } + + LOGMASKED(LOG_HOSTCOMM, "EG->VIA VIA_DATA: %d VIA_CLOCK: %d (PC=%x)\n", BIT(data, 5), BIT(data, 4), m_maincpu->pc()); + write_via_data(BIT(data, 5)); + write_via_clock(BIT(data, 4)); + write_dfac_sda(BIT(data, 6)); + write_dfac_scl(BIT(data, 7)); } -void egret_device::ddr_w(offs_t offset, u8 data) +void egret_device::pc_w(u8 data) { -/* printf("%02x to DDR %c\n", data, 'A' + offset);*/ - - send_port(offset, m_ports[offset] & data); - - m_ddrs[offset] = data; - - if (offset == 1) // port B + if ((data & 8) != m_reset_line) { - // For IIC, the 68HC05 sets the SCL and SDA data bits to 0 and toggles the lines - // purely with the DDRs. When DDR is set, the 0 is driven onto the line and - // the line is 0. When DDR is clear, the line is not driven by the 68HC05 and - // external pullup resistors drive the line to a 1. + LOGMASKED(LOG_HOSTCOMM, "680x0 reset\n"); - // If both SCL and SDA data are 0, we're doing IIC - if ((m_ports[offset] & 0x80) == 0) + // falling edge, should reset the machine too + // TODO: find falling edge + if ((m_reset_line & 8) && !(data & 8)) { - u8 iic_data = (data & 0xc0) ^ 0xc0; - LOGMASKED(LOG_I2C, "I2C: SCL %d SDA %d\n", BIT(iic_data, 7), BIT(iic_data, 6)); - write_iic_sda(BIT(iic_data, 6)); - write_iic_scl(BIT(iic_data, 7)); + // if PRAM's waiting to be loaded, transfer it now + if (!m_pram_loaded) + { + for (int byte = 0; byte < 256; byte++) + { + m_maincpu->write_internal_ram(0x70 + byte, m_disk_pram[byte]); + } + m_pram_loaded = true; + + system_time systime; + struct tm cur_time, macref; + machine().current_datetime(systime); + + cur_time.tm_sec = systime.local_time.second; + cur_time.tm_min = systime.local_time.minute; + cur_time.tm_hour = systime.local_time.hour; + cur_time.tm_mday = systime.local_time.mday; + cur_time.tm_mon = systime.local_time.month; + cur_time.tm_year = systime.local_time.year - 1900; + cur_time.tm_isdst = 0; + + macref.tm_sec = 0; + macref.tm_min = 0; + macref.tm_hour = 0; + macref.tm_mday = 1; + macref.tm_mon = 0; + macref.tm_year = 4; + macref.tm_isdst = 0; + u32 ref = (u32)mktime(¯ef); + + u32 seconds = (u32)((u32)mktime(&cur_time) - ref); + m_maincpu->write_internal_ram(0xae - 0x90, seconds & 0xff); + m_maincpu->write_internal_ram(0xad - 0x90, (seconds >> 8) & 0xff); + m_maincpu->write_internal_ram(0xac - 0x90, (seconds >> 16) & 0xff); + m_maincpu->write_internal_ram(0xab - 0x90, (seconds >> 24) & 0xff); + + LOGMASKED(LOG_PRAM, "Syncing PRAM to saved/default and RTC to current date/time %08x\n", seconds); + } } + + m_reset_line = (data & 8); + write_reset((m_reset_line & 8) ? ASSERT_LINE : CLEAR_LINE); } } -u8 egret_device::ports_r(offs_t offset) +u8 egret_device::pa_r() { - u8 incoming = 0; + u8 rv = 0; - switch (offset) - { - case 0: // port A #if USE_BUS_ADB - incoming |= (m_adb_out & m_adb_device_out[0] & m_adb_device_out[1]) ? 0x40 : 0; - incoming |= (m_adb_device_poweron[0] & m_adb_device_poweron[1]) ? 0x04 : 0; + rv |= (m_adb_out & m_adb_device_out[0] & m_adb_device_out[1]) ? 0x40 : 0; + rv |= (m_adb_device_poweron[0] & m_adb_device_poweron[1]) ? 0x04 : 0; #else - incoming |= m_adb_in ? 0x40 : 0; + rv |= m_adb_in ? 0x40 : 0; #endif - if (m_egret_controls_power) - { - incoming |= 0x02; // indicate soft power, indicate chassis switch on - } - else - { - //incoming |= 0x01; // enable control panel enabled - } - break; - - case 1: // port B - incoming |= 0x01; // always show +5v active - incoming |= m_via_full<<2; - incoming |= m_sys_session<<3; - incoming |= m_via_data<<5; - incoming |= m_iic_sda ? 0x40 : 0; - break; - - case 2: // port C - if (m_egret_controls_power) - { - incoming |= 0x3; // trickle sense active, bit 0 pulled up as per schematics - } - break; - } - - // apply data direction registers - incoming &= (m_ddrs[offset] ^ 0xff); - // add in ddr-masked version of port writes - incoming |= (m_ports[offset] & m_ddrs[offset]); - - return incoming; -} - -void egret_device::ports_w(offs_t offset, u8 data) -{ - send_port(offset, data); - - m_ports[offset] = data; -} - -u8 egret_device::pll_r() -{ - return m_pll_ctrl; -} - -void egret_device::pll_w(u8 data) -{ - #ifdef EGRET_SUPER_VERBOSE - if (m_pll_ctrl != data) + if (m_egret_controls_power) { - static const int clocks[4] = { 524288, 1048576, 2097152, 4194304 }; - printf("PLL ctrl: clock %d TCS:%d BCS:%d AUTO:%d BWC:%d PLLON:%d\n", clocks[data&3], - (data & 0x80) ? 1 : 0, - (data & 0x40) ? 1 : 0, - (data & 0x20) ? 1 : 0, - (data & 0x10) ? 1 : 0, - (data & 0x08) ? 1 : 0); + rv |= 0x02; // indicate soft power, indicate chassis switch on } - #endif - m_pll_ctrl = data; -} - -u8 egret_device::timer_ctrl_r() -{ - return m_timer_ctrl; -} - -void egret_device::timer_ctrl_w(u8 data) -{ -// printf("%02x to timer control\n", data); - m_timer_ctrl = data; -} - -u8 egret_device::timer_counter_r() -{ - return m_timer_counter; -} - -void egret_device::timer_counter_w(u8 data) -{ -// printf("%02x to timer/counter\n", data); - m_timer_counter = data; -} - -u8 egret_device::onesec_r() -{ - return m_onesec; -} - -void egret_device::onesec_w(u8 data) -{ -// printf("%02x to one-second control\n", data); - - m_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1)); - - if ((m_onesec & 0x40) && !(data & 0x40)) + else { - m_maincpu->set_input_line(M68HC05EG_INT_CPI, CLEAR_LINE); + //rv |= 0x01; // enable control panel enabled } - m_onesec = data; -} - -u8 egret_device::pram_r(offs_t offset) -{ - return m_pram[offset]; + return rv; } -void egret_device::pram_w(offs_t offset, u8 data) +u8 egret_device::pb_r() { - m_pram[offset] = data; + u8 rv = 0; + rv |= 0x01; // always show +5v active + rv |= m_via_full << 2; + rv |= m_sys_session << 3; + rv |= m_via_data << 5; + rv |= 0x40; + return rv; } -TIMER_CALLBACK_MEMBER(egret_device::seconds_tick) +u8 egret_device::pc_r() { - m_onesec |= 0x40; - - if (m_onesec & 0x10) + u8 rv = 0; + if (m_egret_controls_power) { - m_maincpu->set_input_line(M68HC05EG_INT_CPI, ASSERT_LINE); + rv |= 0x3; // trickle sense active, bit 0 pulled up as per schematics } + + return rv; } // the 6805 program clears PRAM on startup (on h/w it's always running once a battery is inserted) @@ -508,42 +337,41 @@ TIMER_CALLBACK_MEMBER(egret_device::seconds_tick) // once the Egret reboots the 68k void egret_device::nvram_default() { - memset(m_pram, 0, 0x100); memset(m_disk_pram, 0, 0x100); LOGMASKED(LOG_PRAM, "PRAM reset to default"); // IIsi and IIvx both default PRAM to this, it seems a reasonable default for Egret systems - m_pram[0x1] = 0x80; - m_pram[0x2] = 0x4f; - m_pram[0x3] = 0x48; - m_pram[0x8] = 0x13; - m_pram[0x9] = 0x88; - m_pram[0xb] = 0x4c; - m_pram[0xc] = 0x4e; - m_pram[0xd] = 0x75; - m_pram[0xe] = 0x4d; - m_pram[0xf] = 0x63; - m_pram[0x10] = 0xa8; - m_pram[0x14] = 0xcc; - m_pram[0x15] = 0x0a; - m_pram[0x16] = 0xcc; - m_pram[0x17] = 0x0a; - m_pram[0x1d] = 0x02; - m_pram[0x1e] = 0x63; - m_pram[0x6f] = 0x28; - m_pram[0x70] = 0x83; - m_pram[0x71] = 0x26; - m_pram[0x77] = 0x01; - m_pram[0x78] = 0xff; - m_pram[0x79] = 0xff; - m_pram[0x7a] = 0xff; - m_pram[0x7b] = 0xdf; - m_pram[0x7d] = 0x09; - m_pram[0xf3] = 0x12; - m_pram[0xf9] = 0x01; - m_pram[0xf3] = 0x12; - m_pram[0xfb] = 0x8d; + m_disk_pram[0x1] = 0x80; + m_disk_pram[0x2] = 0x4f; + m_disk_pram[0x3] = 0x48; + m_disk_pram[0x8] = 0x13; + m_disk_pram[0x9] = 0x88; + m_disk_pram[0xb] = 0x4c; + m_disk_pram[0xc] = 0x4e; + m_disk_pram[0xd] = 0x75; + m_disk_pram[0xe] = 0x4d; + m_disk_pram[0xf] = 0x63; + m_disk_pram[0x10] = 0xa8; + m_disk_pram[0x14] = 0xcc; + m_disk_pram[0x15] = 0x0a; + m_disk_pram[0x16] = 0xcc; + m_disk_pram[0x17] = 0x0a; + m_disk_pram[0x1d] = 0x02; + m_disk_pram[0x1e] = 0x63; + m_disk_pram[0x6f] = 0x28; + m_disk_pram[0x70] = 0x83; + m_disk_pram[0x71] = 0x26; + m_disk_pram[0x77] = 0x01; + m_disk_pram[0x78] = 0xff; + m_disk_pram[0x79] = 0xff; + m_disk_pram[0x7a] = 0xff; + m_disk_pram[0x7b] = 0xdf; + m_disk_pram[0x7d] = 0x09; + m_disk_pram[0xf3] = 0x12; + m_disk_pram[0xf9] = 0x01; + m_disk_pram[0xf3] = 0x12; + m_disk_pram[0xfb] = 0x8d; m_pram_loaded = false; } @@ -561,6 +389,11 @@ bool egret_device::nvram_read(util::read_stream &file) bool egret_device::nvram_write(util::write_stream &file) { - auto const [err, actual] = write(file, m_pram, 0x100); + for (int byte = 0; byte < 256; byte++) + { + m_disk_pram[byte] = m_maincpu->read_internal_ram(0x70 + byte); + } + + auto const [err, actual] = write(file, m_disk_pram, 0x100); return !err; } diff --git a/src/mame/apple/egret.h b/src/mame/apple/egret.h index ede590998c0..b4919afe76e 100644 --- a/src/mame/apple/egret.h +++ b/src/mame/apple/egret.h @@ -5,6 +5,8 @@ #pragma once +#include "cpu/m6805/m68hc05e1.h" + #define USE_BUS_ADB (0) #if USE_BUS_ADB @@ -32,21 +34,6 @@ public: virtual bool nvram_read(util::read_stream &file) override; virtual bool nvram_write(util::write_stream &file) override; - u8 ddr_r(offs_t offset); - void ddr_w(offs_t offset, u8 data); - u8 ports_r(offs_t offset); - void ports_w(offs_t offset, u8 data); - u8 pll_r(); - void pll_w(u8 data); - u8 timer_ctrl_r(); - void timer_ctrl_w(u8 data); - u8 timer_counter_r(); - void timer_counter_w(u8 data); - u8 onesec_r(); - void onesec_w(u8 data); - u8 pram_r(offs_t offset); - void pram_w(offs_t offset, u8 data); - #if USE_BUS_ADB void adb_w(int id, int state); void adb_poweron_w(int id, int state); @@ -61,20 +48,20 @@ public: void set_via_data(u8 dat) { m_via_data = dat; } u8 get_via_clock() { return m_via_clock; } void set_adb_line(int linestate) { m_adb_in = (linestate == ASSERT_LINE) ? true : false; } - void set_iic_sda(u8 data) { m_iic_sda = (data & 1); } auto reset_callback() { return write_reset.bind(); } auto linechange_callback() { return write_linechange.bind(); } auto via_clock_callback() { return write_via_clock.bind(); } auto via_data_callback() { return write_via_data.bind(); } - auto iic_scl_callback() { return write_iic_scl.bind(); } - auto iic_sda_callback() { return write_iic_sda.bind(); } + auto dfac_scl_callback() { return write_dfac_scl.bind(); } + auto dfac_sda_callback() { return write_dfac_sda.bind(); } + auto dfac_latch_callback() { return write_dfac_latch.bind(); } devcb_write_line write_reset, write_linechange; devcb_write_line write_via_clock, write_via_data; - devcb_write_line write_iic_scl, write_iic_sda; + devcb_write_line write_dfac_scl, write_dfac_sda, write_dfac_latch; - void egret_map(address_map &map); + required_device m_maincpu; protected: // device-level overrides @@ -83,19 +70,7 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual const tiny_rom_entry *device_rom_region() const override; - TIMER_CALLBACK_MEMBER(seconds_tick); - - required_device m_maincpu; - required_shared_ptr m_internal_ram; - required_region_ptr m_rom; - private: - u8 m_ddrs[3]{}; - u8 m_ports[3]{}; - u8 m_pll_ctrl; - u8 m_timer_ctrl; - u8 m_timer_counter; - u8 m_onesec; u8 m_xcvr_session; u8 m_via_full; u8 m_sys_session; @@ -107,11 +82,8 @@ private: bool m_adb_in; s32 m_reset_line; s32 m_adb_dtime; - emu_timer *m_timer; - u8 m_pram[0x100]{}; u8 m_disk_pram[0x100]{}; bool m_pram_loaded; - u8 m_iic_sda; #if USE_BUS_ADB optional_device m_adb_connector[2]; @@ -121,7 +93,12 @@ private: bool m_adb_out = false; #endif - void send_port(u8 offset, u8 data); + u8 pa_r(); + u8 pb_r(); + u8 pc_r(); + void pa_w(u8 data); + void pb_w(u8 data); + void pc_w(u8 data); }; // device type definition diff --git a/src/mame/apple/macquadra630.cpp b/src/mame/apple/macquadra630.cpp index 9d030c8566b..1d27f000d70 100644 --- a/src/mame/apple/macquadra630.cpp +++ b/src/mame/apple/macquadra630.cpp @@ -29,6 +29,9 @@ the 53C96's transfer count is zero. The earlier ROM has the same logic as previous (and later!) 53C96 machines and works fine. + Video in chips + + ****************************************************************************/ #include "emu.h" @@ -167,10 +170,8 @@ void quadra630_state::macqd630(machine_config &config) MACADB(config, m_macadb, C15M); - // TODO: recapamac.com.au's logic board photos show Cuda 2.40 for both Q630 and LC580, - // but both ROM versions have issues syncing with 2.38 and 2.40 while 2.37 works. CUDA_V2XX(config, m_cuda, XTAL(32'768)); - m_cuda->set_default_bios_tag("341s0788"); + m_cuda->set_default_bios_tag("341s0060"); m_cuda->reset_callback().set(FUNC(quadra630_state::cuda_reset_w)); m_cuda->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_cuda->via_clock_callback().set(m_primetimeii, FUNC(primetime_device::cb1_w)); -- cgit v1.2.3