From f59da7c8ab252479af905476c16dc4e724880cfa Mon Sep 17 00:00:00 2001 From: arbee Date: Sun, 20 Aug 2023 20:43:54 -0400 Subject: apple/egret.cpp: Overhaul, part 1 [R. Belmont] - Clock/calendar now is synced to the system time at startup - Modernized member naming, types, and logging - Split into a subdevice per version instead of a version select variable (you will need new ROM sets, but this means future changes won't require that) --- src/mame/apple/egret.cpp | 572 +++++++++++++++++++++++++-------------------- src/mame/apple/egret.h | 160 +++++++------ src/mame/apple/maciici.cpp | 2 +- src/mame/apple/maciivx.cpp | 2 +- src/mame/apple/maclc.cpp | 2 +- src/mame/apple/maclc3.cpp | 2 +- 6 files changed, 410 insertions(+), 330 deletions(-) diff --git a/src/mame/apple/egret.cpp b/src/mame/apple/egret.cpp index 6c1e5d9d8e0..7d5abdcc64d 100644 --- a/src/mame/apple/egret.cpp +++ b/src/mame/apple/egret.cpp @@ -1,9 +1,14 @@ // license:BSD-3-Clause // copyright-holders:R. Belmont /* - Apple "Egret" ADB/system controller MCU + Apple "Egret" ADB/I2C/power management microcontroller Emulation by R. Belmont + Egret is a 68HC05EG with 2 8-bit GPIO ports and 1 4-bit GPIO port. Egret handles + ADB, I2C, and basic power management. The 68HC05EG is basically the same as a 68HC05E1. + + TODO: make proper 68HC05E1 base class and rebase this and Cuda on it. Merge this with Cuda? + Port definitions, primarily from the schematics. Port A: @@ -19,8 +24,8 @@ Port B: - x------- O DFAC bit clock - -x------ ? DFAC data I/O (used in both directions) + x------- O DFAC bit clock (I2C SCL) + -x------ ? DFAC data I/O (I2C SDA) --x----- ? VIA shift register data (used in both directions) ---x---- O VIA clock ----x--- I VIA SYS_SESSION @@ -44,34 +49,26 @@ Caboose appears to be a slightly modified version of Egret with keysense support added to its power management functions. It may also retain Egret's ADB interface, though the Quadra 900 & 950 disconnect its port pins from the ADB data line, which is instead connected to a PIC. - */ - -//#define EGRET_SUPER_VERBOSE - #include "emu.h" #include "egret.h" #include "cpu/m6805/m6805.h" -#include "sound/asc.h" -//************************************************************************** -// MACROS / CONSTANTS -//************************************************************************** - -#define EGRET_CPU_TAG "egret" +#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 -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** +#define VERBOSE (0) +#include "logmacro.h" -DEFINE_DEVICE_TYPE(EGRET, egret_device, "egret", "Apple Egret") +DEFINE_DEVICE_TYPE(EGRET_V100, egret_100_device, "egret100", "Apple Egret 1.00 ADB/I2C") +DEFINE_DEVICE_TYPE(EGRET_V101_EARLY, egret_101early_device, "egret101e", "Apple Egret 1.01 (early) ADB/I2C") +DEFINE_DEVICE_TYPE(EGRET_V101, egret_101_device, "egret101", "Apple Egret 1.01 ADB/I2C") ROM_START( egret ) - ROM_REGION(0x4400, EGRET_CPU_TAG, 0) - ROM_LOAD( "341s0851.bin", 0x1100, 0x1100, CRC(ea9ea6e4) SHA1(8b0dae3ec66cdddbf71567365d2c462688aeb571) ) - ROM_LOAD( "341s0850.bin", 0x2200, 0x1100, CRC(4906ecd0) SHA1(95e08ba0c5d4b242f115f104aba9905dbd3fd87c) ) - ROM_LOAD( "344s0100.bin", 0x3300, 0x1100, CRC(59e2b6b6) SHA1(540e752b7da521f1bdb16e0ad7c5f46ddc92d4e9) ) + ROM_REGION(0x1100, "roms", 0) ROM_END //------------------------------------------------- @@ -86,9 +83,9 @@ void egret_device::egret_map(address_map &map) 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(); // work RAM and stack + 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(EGRET_CPU_TAG, 0); + map(0x0f00, 0x1fff).rom().region("roms", 0); } @@ -114,6 +111,90 @@ const tiny_rom_entry *egret_device::device_rom_region() const //************************************************************************** // LIVE DEVICE //************************************************************************** +egret_device::egret_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, type, tag, owner, clock), + device_nvram_interface(mconfig, *this), + write_reset(*this), + write_linechange(*this), + write_via_clock(*this), + write_via_data(*this), + write_iic_scl(*this), + write_iic_sda(*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_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) +#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() +{ +#if USE_BUS_ADB + for (int i = 0; i < 2; i++) + { + 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); }); + } + } +#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)); + save_item(NAME(m_adb_device_out)); + save_item(NAME(m_adb_device_poweron)); +#endif +} + +void egret_device::device_reset() +{ +#if USE_BUS_ADB + m_adb_device_out[0] = m_adb_device_out[1] = true; + 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(); +} + #if USE_BUS_ADB void egret_device::adb_w(int id, int state) { @@ -138,115 +219,148 @@ void egret_device::adb_change() } #endif -void egret_device::send_port(uint8_t offset, uint8_t data) +void egret_device::send_port(u8 offset, u8 data) { switch (offset) { case 0: // port A - /* printf("ADB:%d DFAC:%d PowerEnable:%d\n", - (data & 0x80) ? 1 : 0, - (data & 0x10) ? 1 : 0, - (data & 0x02) ? 1 : 0);*/ - #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(); #else - if ((data & 0x80) != last_adb) + if ((data & 0x80) != m_last_adb) { - m_adb_dtime = (int)(machine().time().as_ticks(1000000) - last_adb_time); - /* - if (data & 0x80) - { - printf("EG ADB: 1->0 time %d\n", m_adb_dtime); - } - else - { - printf("EG ADB: 0->1 time %d\n", m_adb_dtime); - } - */ + 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 - adb_in = (data & 0x80) ? true : false; + m_adb_in = (data & 0x80) ? true : false; write_linechange(((data & 0x80) >> 7) ^ 1); - last_adb = data & 0x80; - last_adb_time = machine().time().as_ticks(1000000); + m_last_adb = data & 0x80; + m_last_adb_time = machine().time().as_ticks(1000000); } #endif break; case 1: // port B { - if (xcvr_session != ((data>>1)&1)) + if (m_xcvr_session != ((data>>1)&1)) { - #ifdef EGRET_SUPER_VERBOSE - printf("EG-> XCVR_SESSION: %d (PC=%x)\n", (data>>1)&1, m_maincpu->pc()); - #endif - 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 (via_data != ((data>>5)&1)) + if (m_via_data != ((data>>5)&1)) { - #ifdef EGRET_SUPER_VERBOSE - printf("EG-> VIA_DATA: %d (PC=%x)\n", (data>>5)&1, m_maincpu->pc()); - #endif - via_data = (data>>5) & 1; - write_via_data(via_data); + 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 (via_clock != ((data>>4)&1)) + if (m_via_clock != ((data>>4)&1)) { - #ifdef EGRET_SUPER_VERBOSE - printf("EG-> VIA_CLOCK: %d (PC=%x)\n", ((data>>4)&1)^1, m_maincpu->pc()); - #endif - via_clock = (data>>4) & 1; - write_via_clock(via_clock); + 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; case 2: // port C - if ((data & 8) != reset_line) + if ((data & 8) != m_reset_line) { - #ifdef EGRET_SUPER_VERBOSE - printf("680x0 reset: %d -> %d\n", (ports[2] & 8)>>3, (data & 8)>>3); - #endif - reset_line = (data & 8); + LOGMASKED(LOG_HOSTCOMM, "680x0 reset: %d -> %d\n", (m_ports[2] & 8)>>3, (data & 8)>>3); + m_reset_line = (data & 8); // falling edge, should reset the machine too - if ((ports[2] & 8) && !(data&8)) + if ((m_ports[2] & 8) && !(data&8)) { // if PRAM's waiting to be loaded, transfer it now - if (!pram_loaded) + if (!m_pram_loaded) { - memcpy(pram, disk_pram, 0x100); - pram_loaded = true; + 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_reset((reset_line & 8) ? ASSERT_LINE : CLEAR_LINE); + write_reset((m_reset_line & 8) ? ASSERT_LINE : CLEAR_LINE); } break; } } -uint8_t egret_device::ddr_r(offs_t offset) +u8 egret_device::ddr_r(offs_t offset) { - return ddrs[offset]; + return m_ddrs[offset]; } -void egret_device::ddr_w(offs_t offset, uint8_t data) +void egret_device::ddr_w(offs_t offset, u8 data) { /* printf("%02x to DDR %c\n", data, 'A' + offset);*/ - send_port(offset, ports[offset] & data); + send_port(offset, m_ports[offset] & data); + + m_ddrs[offset] = data; + + if (offset == 1) // port B + { + // 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. - ddrs[offset] = data; + // 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)); + } + } } -uint8_t egret_device::ports_r(offs_t offset) +u8 egret_device::ports_r(offs_t offset) { - uint8_t incoming = 0; + u8 incoming = 0; switch (offset) { @@ -255,9 +369,9 @@ uint8_t egret_device::ports_r(offs_t offset) 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; #else - incoming |= adb_in ? 0x40 : 0; + incoming |= m_adb_in ? 0x40 : 0; #endif - if (egret_controls_power) + if (m_egret_controls_power) { incoming |= 0x02; // indicate soft power, indicate chassis switch on } @@ -269,14 +383,14 @@ uint8_t egret_device::ports_r(offs_t offset) case 1: // port B incoming |= 0x01; // always show +5v active - incoming |= via_full<<2; - incoming |= sys_session<<3; - incoming |= via_data<<5; - incoming |= 0x40; // show DFAC line high + 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 (egret_controls_power) + if (m_egret_controls_power) { incoming |= 0x3; // trickle sense active, bit 0 pulled up as per schematics } @@ -284,29 +398,29 @@ uint8_t egret_device::ports_r(offs_t offset) } // apply data direction registers - incoming &= (ddrs[offset] ^ 0xff); + incoming &= (m_ddrs[offset] ^ 0xff); // add in ddr-masked version of port writes - incoming |= (ports[offset] & ddrs[offset]); + incoming |= (m_ports[offset] & m_ddrs[offset]); return incoming; } -void egret_device::ports_w(offs_t offset, uint8_t data) +void egret_device::ports_w(offs_t offset, u8 data) { send_port(offset, data); - ports[offset] = data; + m_ports[offset] = data; } -uint8_t egret_device::pll_r() +u8 egret_device::pll_r() { - return pll_ctrl; + return m_pll_ctrl; } -void egret_device::pll_w(uint8_t data) +void egret_device::pll_w(u8 data) { #ifdef EGRET_SUPER_VERBOSE - if (pll_ctrl != data) + if (m_pll_ctrl != data) { 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], @@ -317,171 +431,65 @@ void egret_device::pll_w(uint8_t data) (data & 0x08) ? 1 : 0); } #endif - pll_ctrl = data; + m_pll_ctrl = data; } -uint8_t egret_device::timer_ctrl_r() +u8 egret_device::timer_ctrl_r() { - return timer_ctrl; + return m_timer_ctrl; } -void egret_device::timer_ctrl_w(uint8_t data) +void egret_device::timer_ctrl_w(u8 data) { // printf("%02x to timer control\n", data); - timer_ctrl = data; + m_timer_ctrl = data; } -uint8_t egret_device::timer_counter_r() +u8 egret_device::timer_counter_r() { - return timer_counter; + return m_timer_counter; } -void egret_device::timer_counter_w(uint8_t data) +void egret_device::timer_counter_w(u8 data) { // printf("%02x to timer/counter\n", data); - timer_counter = data; + m_timer_counter = data; } -uint8_t egret_device::onesec_r() +u8 egret_device::onesec_r() { - return onesec; + return m_onesec; } -void egret_device::onesec_w(uint8_t data) +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 ((onesec & 0x40) && !(data & 0x40)) + if ((m_onesec & 0x40) && !(data & 0x40)) { m_maincpu->set_input_line(M68HC05EG_INT_CPI, CLEAR_LINE); } - onesec = data; -} - -uint8_t egret_device::pram_r(offs_t offset) -{ - return pram[offset]; -} - -void egret_device::pram_w(offs_t offset, uint8_t data) -{ - pram[offset] = data; -} - -//------------------------------------------------- -// egret_device - constructor -//------------------------------------------------- - -egret_device::egret_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, EGRET, tag, owner, clock), - device_nvram_interface(mconfig, *this), - write_reset(*this), - write_linechange(*this), - write_via_clock(*this), - write_via_data(*this), - m_maincpu(*this, EGRET_CPU_TAG) -#if USE_BUS_ADB - , m_adb_connector{{*this, "adb1"}, {*this, finder_base::DUMMY_TAG}} -#endif -{ + m_onesec = data; } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void egret_device::device_start() +u8 egret_device::pram_r(offs_t offset) { -#if USE_BUS_ADB - for (int i = 0; i < 2; i++) - { - 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); }); - } - } -#endif - - m_timer = timer_alloc(FUNC(egret_device::seconds_tick), this); - - save_item(NAME(ddrs[0])); - save_item(NAME(ddrs[1])); - save_item(NAME(ddrs[2])); - save_item(NAME(ports[0])); - save_item(NAME(ports[1])); - save_item(NAME(ports[2])); - save_item(NAME(pll_ctrl)); - save_item(NAME(timer_ctrl)); - save_item(NAME(timer_counter)); - save_item(NAME(onesec)); - save_item(NAME(xcvr_session)); - save_item(NAME(via_full)); - save_item(NAME(sys_session)); - save_item(NAME(via_data)); - save_item(NAME(via_clock)); - save_item(NAME(adb_in)); - save_item(NAME(reset_line)); - save_item(NAME(m_adb_dtime)); - save_item(NAME(pram_loaded)); - save_item(NAME(pram)); - save_item(NAME(disk_pram)); -#if USE_BUS_ADB - save_item(NAME(m_adb_out)); - save_item(NAME(m_adb_device_out)); - save_item(NAME(m_adb_device_poweron)); -#endif - - uint8_t *rom = device().machine().root_device().memregion(device().subtag(EGRET_CPU_TAG))->base(); - - if (rom) - { - memcpy(rom, rom+rom_offset, 0x1100); - } + return m_pram[offset]; } - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void egret_device::device_reset() +void egret_device::pram_w(offs_t offset, u8 data) { - ddrs[0] = ddrs[1] = ddrs[2] = 0; - ports[0] = ports[1] = ports[2] = 0; - - #if USE_BUS_ADB - m_adb_device_out[0] = m_adb_device_out[1] = true; - m_adb_device_poweron[0] = m_adb_device_poweron[1] = true; - #endif - - m_timer->adjust(attotime::never); - - egret_controls_power = false; // set to hard power control - adb_in = true; // line is pulled up to +5v, so nothing plugged in would read as "1" - reset_line = 0; - xcvr_session = 0; - via_full = 0; - sys_session = 0; - via_data = 0; - via_clock = 0; - pll_ctrl = 0; - timer_ctrl = 0; - timer_counter = 0; - last_adb_time = m_maincpu->total_cycles(); - onesec = 0; - last_adb = 0; + m_pram[offset] = data; } TIMER_CALLBACK_MEMBER(egret_device::seconds_tick) { - onesec |= 0x40; + m_onesec |= 0x40; - if (onesec & 0x10) + if (m_onesec & 0x10) { m_maincpu->set_input_line(M68HC05EG_INT_CPI, ASSERT_LINE); } @@ -492,49 +500,52 @@ TIMER_CALLBACK_MEMBER(egret_device::seconds_tick) // once the Egret reboots the 68k void egret_device::nvram_default() { - memset(pram, 0, 0x100); - memset(disk_pram, 0, 0x100); + 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 - pram[0x1] = 0x80; - pram[0x2] = 0x4f; - pram[0x3] = 0x48; - pram[0x8] = 0x13; - pram[0x9] = 0x88; - pram[0xb] = 0x4c; - pram[0xc] = 0x4e; - pram[0xd] = 0x75; - pram[0xe] = 0x4d; - pram[0xf] = 0x63; - pram[0x10] = 0xa8; - pram[0x14] = 0xcc; - pram[0x15] = 0x0a; - pram[0x16] = 0xcc; - pram[0x17] = 0x0a; - pram[0x1d] = 0x02; - pram[0x1e] = 0x63; - pram[0x6f] = 0x28; - pram[0x70] = 0x83; - pram[0x71] = 0x26; - pram[0x77] = 0x01; - pram[0x78] = 0xff; - pram[0x79] = 0xff; - pram[0x7a] = 0xff; - pram[0x7b] = 0xdf; - pram[0x7d] = 0x09; - pram[0xf3] = 0x12; - pram[0xf9] = 0x01; - pram[0xf3] = 0x12; - pram[0xfb] = 0x8d; - pram_loaded = false; + 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_pram_loaded = false; } bool egret_device::nvram_read(util::read_stream &file) { size_t actual; - if (!file.read(disk_pram, 0x100, actual) && actual == 0x100) + if (!file.read(m_disk_pram, 0x100, actual) && actual == 0x100) { - pram_loaded = false; + LOGMASKED(LOG_PRAM, "PRAM read from disk OK"); + m_pram_loaded = false; return true; } return false; @@ -543,5 +554,56 @@ bool egret_device::nvram_read(util::read_stream &file) bool egret_device::nvram_write(util::write_stream &file) { size_t actual; - return !file.write(pram, 0x100, actual) && actual == 0x100; + return !file.write(m_pram, 0x100, actual) && actual == 0x100; +} + +// Egret v1.00 ------------------------------------------------------------------------ + +ROM_START(egret100) + ROM_REGION(0x1100, "roms", 0) + ROM_LOAD("344s0100.bin", 0x0000, 0x1100, CRC(59e2b6b6) SHA1(540e752b7da521f1bdb16e0ad7c5f46ddc92d4e9)) +ROM_END + +const tiny_rom_entry *egret_100_device::device_rom_region() const +{ + return ROM_NAME(egret100); +} + +egret_100_device::egret_100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : egret_device(mconfig, EGRET_V100, tag, owner, clock) +{ +} + +// Egret v1.01 (early) ------------------------------------------------------------------------ + +ROM_START(egret101early) + ROM_REGION(0x1100, "roms", 0) + ROM_LOAD("341s0850.bin", 0x0000, 0x1100, CRC(4906ecd0) SHA1(95e08ba0c5d4b242f115f104aba9905dbd3fd87c)) +ROM_END + +const tiny_rom_entry *egret_101early_device::device_rom_region() const +{ + return ROM_NAME(egret101early); +} + +egret_101early_device::egret_101early_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : egret_device(mconfig, EGRET_V101_EARLY, tag, owner, clock) +{ +} + +// Egret v1.01 ------------------------------------------------------------------------ + +ROM_START(egret101) + ROM_REGION(0x1100, "roms", 0) + ROM_LOAD("341s0851.bin", 0x0000, 0x1100, CRC(ea9ea6e4) SHA1(8b0dae3ec66cdddbf71567365d2c462688aeb571)) +ROM_END + +const tiny_rom_entry *egret_101_device::device_rom_region() const +{ + return ROM_NAME(egret101); +} + +egret_101_device::egret_101_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : egret_device(mconfig, EGRET_V101, tag, owner, clock) +{ } diff --git a/src/mame/apple/egret.h b/src/mame/apple/egret.h index 14f97ff3c83..c63b7f54cb9 100644 --- a/src/mame/apple/egret.h +++ b/src/mame/apple/egret.h @@ -11,57 +11,41 @@ #include "bus/adb/adb.h" #endif -//************************************************************************** -// MACROS / CONSTANTS -//************************************************************************** - -#define EGRET_TAG "egret" - -#define EGRET_341S0851 0x1100 -#define EGRET_341S0850 0x2200 -#define EGRET_344S0100 0x3300 - - //************************************************************************** // TYPE DEFINITIONS //************************************************************************** -// ======================> egret_device - +/// \brief Base class for Apple Egret devices. +/// +/// Egret is a semi-custom Motorola 68HC05 microcontroller with +/// on-board RAM and ROM plus several GPIO pins. Egret handles +/// simple power management, the Apple Desktop Bus, I2C, real-time +/// clock, and parameter RAM. class egret_device : public device_t, public device_nvram_interface { public: // construction/destruction - egret_device(const machine_config &mconfig, const char *tag, device_t *owner, int type) - : egret_device(mconfig, tag, owner, (uint32_t)0) - { - set_type(type); - } - - egret_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // inline configuration helpers - void set_type(int type) { rom_offset = type; } + egret_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); // device_config_nvram_interface overrides virtual void nvram_default() override; virtual bool nvram_read(util::read_stream &file) override; virtual bool nvram_write(util::write_stream &file) override; - uint8_t ddr_r(offs_t offset); - void ddr_w(offs_t offset, uint8_t data); - uint8_t ports_r(offs_t offset); - void ports_w(offs_t offset, uint8_t data); - uint8_t pll_r(); - void pll_w(uint8_t data); - uint8_t timer_ctrl_r(); - void timer_ctrl_w(uint8_t data); - uint8_t timer_counter_r(); - void timer_counter_w(uint8_t data); - uint8_t onesec_r(); - void onesec_w(uint8_t data); - uint8_t pram_r(offs_t offset); - void pram_w(offs_t offset, uint8_t data); + 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); @@ -70,25 +54,28 @@ public: #endif // interface routines - uint8_t get_xcvr_session() { return xcvr_session; } - void set_via_full(uint8_t val) { via_full = val; } - void set_sys_session(uint8_t val) { sys_session = val; } - uint8_t get_via_data() { return via_data; } - void set_via_data(uint8_t dat) { via_data = dat; } - uint8_t get_via_clock() { return via_clock; } - void set_adb_line(int linestate) { adb_in = (linestate == ASSERT_LINE) ? true : false; } - - int rom_offset; + u8 get_xcvr_session() { return m_xcvr_session; } + void set_via_full(u8 val) { m_via_full = val; } + void set_sys_session(u8 val) { m_sys_session = 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); } 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(); } 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; void egret_map(address_map &map); + protected: // device-level overrides virtual void device_start() override; @@ -99,31 +86,34 @@ protected: TIMER_CALLBACK_MEMBER(seconds_tick); required_device m_maincpu; + required_shared_ptr m_internal_ram; + required_region_ptr m_rom; private: - uint8_t ddrs[3]{}; - uint8_t ports[3]{}; - uint8_t pll_ctrl = 0; - uint8_t timer_ctrl = 0; - uint8_t timer_counter = 0; - uint8_t onesec = 0; - uint8_t xcvr_session = 0; - uint8_t via_full = 0; - uint8_t sys_session = 0; - uint8_t via_data = 0; - uint8_t via_clock = 0; - uint8_t last_adb = 0; - uint64_t last_adb_time = 0; - bool egret_controls_power = false; - bool adb_in = false; - int reset_line = 0; - int m_adb_dtime = 0; - emu_timer *m_timer = nullptr; - uint8_t pram[0x100]{}; - uint8_t disk_pram[0x100]{}; - bool pram_loaded = false; - - #if USE_BUS_ADB + 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; + u8 m_via_data; + u8 m_via_clock; + u8 m_last_adb; + u64 m_last_adb_time; + bool m_egret_controls_power; + 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]; adb_device *m_adb_device[2]{}; bool m_adb_device_out[2]{}; @@ -131,10 +121,38 @@ private: bool m_adb_out = false; #endif - void send_port(uint8_t offset, uint8_t data); + void send_port(u8 offset, u8 data); +}; +class egret_100_device : public egret_device +{ +public: + egret_100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; +}; + +class egret_101early_device : public egret_device +{ +public: + egret_101early_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; +}; + +class egret_101_device : public egret_device +{ +public: + egret_101_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; }; // device type definition -DECLARE_DEVICE_TYPE(EGRET, egret_device) +DECLARE_DEVICE_TYPE(EGRET_V100, egret_100_device) +DECLARE_DEVICE_TYPE(EGRET_V101_EARLY, egret_101early_device) +DECLARE_DEVICE_TYPE(EGRET_V101, egret_101_device) #endif // MAME_APPLE_EGRET_H diff --git a/src/mame/apple/maciici.cpp b/src/mame/apple/maciici.cpp index 9c887c39cb2..e691bc0221e 100644 --- a/src/mame/apple/maciici.cpp +++ b/src/mame/apple/maciici.cpp @@ -624,7 +624,7 @@ void maciici_state::maciisi(machine_config &config) m_via1->writepb_handler().set(FUNC(maciici_state::via_out_b_iisi)); m_via1->cb2_handler().set(FUNC(maciici_state::via_out_cb2_iisi)); - EGRET(config, m_egret, EGRET_344S0100); + EGRET_V100(config, m_egret, XTAL(32'768)); m_egret->reset_callback().set(FUNC(maciici_state::egret_reset_w)); m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_egret->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); diff --git a/src/mame/apple/maciivx.cpp b/src/mame/apple/maciivx.cpp index 562fa38f67d..1d47e7c68c6 100644 --- a/src/mame/apple/maciivx.cpp +++ b/src/mame/apple/maciivx.cpp @@ -365,7 +365,7 @@ void maciivx_state::maciivx(machine_config &config) maciiv_base(config); - EGRET(config, m_egret, EGRET_341S0851); + EGRET_V101(config, m_egret, XTAL(32'768)); m_egret->reset_callback().set(FUNC(maciivx_state::egret_reset_w)); m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_egret->via_clock_callback().set(m_vasp, FUNC(vasp_device::cb1_w)); diff --git a/src/mame/apple/maclc.cpp b/src/mame/apple/maclc.cpp index 5e0d3f0f03f..9b8caf5807e 100644 --- a/src/mame/apple/maclc.cpp +++ b/src/mame/apple/maclc.cpp @@ -354,7 +354,7 @@ void maclc_state::maclc_base(machine_config &config) MACADB(config, m_macadb, C15M); - EGRET(config, m_egret, EGRET_341S0850); + EGRET_V101_EARLY(config, m_egret, XTAL(32'768)); m_egret->reset_callback().set(FUNC(maclc_state::egret_reset_w)); m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_egret->via_clock_callback().set(m_v8, FUNC(v8_device::cb1_w)); diff --git a/src/mame/apple/maclc3.cpp b/src/mame/apple/maclc3.cpp index 901dbc09c08..613c8313409 100644 --- a/src/mame/apple/maclc3.cpp +++ b/src/mame/apple/maclc3.cpp @@ -291,7 +291,7 @@ void macvail_state::maclc3(machine_config &config) maclc3_base(config); m_maincpu->set_addrmap(AS_PROGRAM, &macvail_state::maclc3_map); - EGRET(config, m_egret, EGRET_341S0851); + EGRET_V101(config, m_egret, XTAL(32'768)); m_egret->reset_callback().set(FUNC(macvail_state::cuda_reset_w)); m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_egret->via_clock_callback().set(m_sonora, FUNC(sonora_device::cb1_w)); -- cgit v1.2.3