mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
-dp8573.cpp: Added DP8573 Real-Time Clock emulation. [Ryan Holtz]
-indigo.cpp: Hooked up new DP8573 implementation. [Ryan Holtz]
This commit is contained in:
parent
208182c9c4
commit
1b08996e2b
@ -3226,6 +3226,18 @@ if (MACHINES["DP83932C"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/dp8573.h,MACHINES["DP8573"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["DP8573"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/dp8573.cpp",
|
||||
MAME_DIR .. "src/devices/machine/dp8573.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/pc_lpt.h,MACHINES["PC_LPT"] = true
|
||||
|
@ -424,6 +424,7 @@ MACHINES["CR589"] = true
|
||||
--MACHINES["CS8221"] = true
|
||||
MACHINES["CXD1095"] = true
|
||||
MACHINES["DP8390"] = true
|
||||
--MACHINES["DP8573"] = true
|
||||
MACHINES["DS1204"] = true
|
||||
MACHINES["DS1205"] = true
|
||||
MACHINES["DS1302"] = true
|
||||
|
@ -424,6 +424,7 @@ MACHINES["CS8221"] = true
|
||||
MACHINES["CXD1095"] = true
|
||||
MACHINES["DP8390"] = true
|
||||
MACHINES["DP83932C"] = true
|
||||
MACHINES["DP8573"] = true
|
||||
--MACHINES["DS1204"] = true
|
||||
MACHINES["DS1302"] = true
|
||||
MACHINES["DS1315"] = true
|
||||
|
355
src/devices/machine/dp8573.cpp
Normal file
355
src/devices/machine/dp8573.cpp
Normal file
@ -0,0 +1,355 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/***************************************************************************
|
||||
|
||||
DP8573 Real Time Clock (RTC)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/dp8573.h"
|
||||
#include "machine/timehelp.h"
|
||||
|
||||
#define LOG_GENERAL (1 << 0)
|
||||
#define LOG_TICKS (1 << 1)
|
||||
#define LOG_ALL (LOG_GENERAL | LOG_TICKS)
|
||||
|
||||
#define VERBOSE (LOG_ALL)
|
||||
#include "logmacro.h"
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(DP8573, dp8573_device, "dp8573", "DP8573 Real-Time Clock")
|
||||
|
||||
dp8573_device::dp8573_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, DP8573, tag, owner, clock)
|
||||
, device_nvram_interface(mconfig, *this)
|
||||
, m_irq(*this)
|
||||
, m_pfail(*this)
|
||||
{
|
||||
}
|
||||
|
||||
void dp8573_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_ram));
|
||||
save_item(NAME(m_tscr));
|
||||
save_item(NAME(m_pfr));
|
||||
save_item(NAME(m_millis));
|
||||
|
||||
m_timer = timer_alloc(TIMER_ID);
|
||||
m_timer->adjust(attotime::never);
|
||||
|
||||
m_irq.resolve_safe();
|
||||
m_pfail.resolve_safe();
|
||||
}
|
||||
|
||||
void dp8573_device::device_reset()
|
||||
{
|
||||
memset(m_ram, 0, 32);
|
||||
|
||||
m_tscr = 0;
|
||||
m_pfr = 0;
|
||||
m_millis = 0;
|
||||
|
||||
system_time systime;
|
||||
machine().base_datetime(systime);
|
||||
|
||||
m_ram[REG_SECOND] = time_helper::make_bcd(systime.local_time.second);
|
||||
m_ram[REG_MINUTE] = time_helper::make_bcd(systime.local_time.minute);
|
||||
m_ram[REG_HOUR] = time_helper::make_bcd(systime.local_time.hour);
|
||||
m_ram[REG_DAY] = time_helper::make_bcd(systime.local_time.mday);
|
||||
m_ram[REG_MONTH] = time_helper::make_bcd(systime.local_time.month + 1);
|
||||
m_ram[REG_YEAR] = time_helper::make_bcd(systime.local_time.year % 100);
|
||||
m_ram[REG_DAYOFWEEK] = time_helper::make_bcd(systime.local_time.weekday + 1);
|
||||
m_ram[REG_RTMR] = RTMR_CSS;
|
||||
|
||||
m_timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1));
|
||||
}
|
||||
|
||||
void dp8573_device::save_registers()
|
||||
{
|
||||
m_ram[REG_SAVE_SECOND] = m_ram[REG_SECOND];
|
||||
m_ram[REG_SAVE_MINUTE] = m_ram[REG_MINUTE];
|
||||
m_ram[REG_SAVE_HOUR] = m_ram[REG_HOUR];
|
||||
m_ram[REG_SAVE_DAY] = m_ram[REG_DAY];
|
||||
m_ram[REG_SAVE_MONTH] = m_ram[REG_MONTH];
|
||||
}
|
||||
|
||||
void dp8573_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
if ((m_pfr & PFR_OSF) || !(m_ram[REG_RTMR] & RTMR_CSS))
|
||||
{
|
||||
LOGMASKED(LOG_TICKS, "Tick suppressed due to OSF or !CSS\n");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pfr ^= PFR_1MS;
|
||||
|
||||
m_millis++;
|
||||
bool carry = false;
|
||||
bool tens_carry = false;
|
||||
time_helper::inc_bcd(&m_millis, 0xff, 0x00, 0x09, &tens_carry);
|
||||
if (tens_carry)
|
||||
{
|
||||
m_pfr ^= PFR_10MS;
|
||||
carry = time_helper::inc_bcd(&m_ram[REG_HUNDREDTH], 0xff, 0x00, 0x99, &tens_carry);
|
||||
if (tens_carry)
|
||||
m_pfr ^= PFR_100MS;
|
||||
}
|
||||
if (carry)
|
||||
{
|
||||
m_pfr ^= PFR_1S;
|
||||
carry = time_helper::inc_bcd(&m_ram[REG_SECOND], 0xff, 0x00, 0x59, &tens_carry);
|
||||
if (tens_carry)
|
||||
m_pfr ^= PFR_10S;
|
||||
}
|
||||
if (carry)
|
||||
{
|
||||
m_pfr ^= PFR_1MIN;
|
||||
carry = time_helper::inc_bcd(&m_ram[REG_MINUTE], 0xff, 0x00, 0x59);
|
||||
}
|
||||
if (carry)
|
||||
{
|
||||
if (m_ram[REG_RTMR] & RTMR_12H)
|
||||
{
|
||||
carry = time_helper::inc_bcd(&m_ram[REG_HOUR], 0xff, 0x01, 0x12);
|
||||
if (carry)
|
||||
{
|
||||
m_ram[REG_HOUR] ^= 0x20;
|
||||
carry = !(m_ram[REG_HOUR] & 0x20);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
carry = time_helper::inc_bcd(&m_ram[REG_HOUR], 0xff, 0x00, 0x23);
|
||||
}
|
||||
}
|
||||
if (carry)
|
||||
{
|
||||
static const uint8_t daysinmonth[] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 };
|
||||
|
||||
time_helper::inc_bcd(&m_ram[REG_DAYOFWEEK], 0xff, 0x01, 0x07);
|
||||
|
||||
uint8_t month = time_helper::from_bcd(m_ram[REG_MONTH]);
|
||||
|
||||
uint8_t maxdays;
|
||||
if (month == 2 && (m_ram[REG_RTMR] & RTMR_LY) == 0)
|
||||
{
|
||||
maxdays = 0x29;
|
||||
}
|
||||
else if (month >= 1 && month <= 12)
|
||||
{
|
||||
maxdays = daysinmonth[month - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxdays = 0x31;
|
||||
}
|
||||
|
||||
carry = time_helper::inc_bcd(&m_ram[REG_DAY], 0xff, 0x01, maxdays);
|
||||
}
|
||||
if (carry)
|
||||
{
|
||||
carry = time_helper::inc_bcd(&m_ram[REG_MONTH], 0xff, 0x01, 0x12);
|
||||
}
|
||||
if (carry)
|
||||
{
|
||||
carry = time_helper::inc_bcd(&m_ram[REG_YEAR], 0xff, 0x00, 0x99);
|
||||
}
|
||||
if (carry)
|
||||
{
|
||||
// Advance the leap-year counter
|
||||
uint8_t leap = m_ram[REG_RTMR] & RTMR_LY;
|
||||
leap = (leap + 1) & RTMR_LY;
|
||||
m_ram[REG_RTMR] &= ~RTMR_LY;
|
||||
m_ram[REG_RTMR] |= leap;
|
||||
}
|
||||
|
||||
// Check for Time Save mode
|
||||
if (m_tscr & TSCR_TS)
|
||||
{
|
||||
save_registers();
|
||||
}
|
||||
|
||||
// Check for periodic interrupts
|
||||
const uint8_t icr0 = m_ram[REG_PFR_ICR0] & ~ICR0_RAM_MASK;
|
||||
const uint8_t pfr = m_pfr & ~ICR0_RAM_MASK;
|
||||
if (icr0 & pfr)
|
||||
{
|
||||
set_interrupt(MSR_PER);
|
||||
}
|
||||
|
||||
const uint8_t icr1 = m_ram[REG_TSCR_ICR1] & ICR1_COMPARE_MASK;
|
||||
if (icr1)
|
||||
{
|
||||
if (m_ram[REG_SECOND] == m_ram[REG_COMP_SECOND] ||
|
||||
m_ram[REG_MINUTE] == m_ram[REG_COMP_MINUTE] ||
|
||||
m_ram[REG_HOUR] == m_ram[REG_COMP_HOUR] ||
|
||||
m_ram[REG_DAY] == m_ram[REG_COMP_DAY] ||
|
||||
m_ram[REG_MONTH] == m_ram[REG_COMP_MONTH] ||
|
||||
m_ram[REG_DAYOFWEEK] == m_ram[REG_COMP_DAYOFWEEK])
|
||||
{
|
||||
set_interrupt(MSR_AL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dp8573_device::set_interrupt(uint8_t mask)
|
||||
{
|
||||
bool was_intr = m_ram[REG_MSR] & MSR_INT;
|
||||
m_ram[REG_MSR] |= mask;
|
||||
|
||||
if (m_ram[REG_MSR] & MSR_INT_MASK)
|
||||
m_ram[REG_MSR] |= MSR_INT;
|
||||
|
||||
if (!was_intr && (m_ram[REG_MSR] & MSR_INT))
|
||||
m_irq(1);
|
||||
}
|
||||
|
||||
void dp8573_device::clear_interrupt(uint8_t mask)
|
||||
{
|
||||
bool was_intr = m_ram[REG_MSR] & MSR_INT;
|
||||
m_ram[REG_MSR] &= ~mask;
|
||||
|
||||
if (was_intr && !(m_ram[REG_MSR] & MSR_INT))
|
||||
m_irq(0);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(dp8573_device::write)
|
||||
{
|
||||
LOGMASKED(LOG_GENERAL, "%s: DP8573 - Register Write: %02x = %02x\n", machine().describe_context(), offset, data);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case REG_MSR: // Main Status Register
|
||||
m_ram[offset] &= ~MSR_RAM_MASK;
|
||||
m_ram[offset] |= data & MSR_RAM_MASK;
|
||||
if (data & MSR_CLEARABLE_MASK)
|
||||
clear_interrupt(data & MSR_CLEARABLE_MASK);
|
||||
break;
|
||||
|
||||
case REG_RTMR: // Not Applicable / Real-Time Mode Register
|
||||
if (m_ram[REG_MSR] & MSR_RS)
|
||||
{
|
||||
const uint8_t old = m_ram[offset];
|
||||
m_ram[offset] = data;
|
||||
if ((old ^ data) & RTMR_12H)
|
||||
{
|
||||
uint8_t hour;
|
||||
if (old & RTMR_12H)
|
||||
hour = time_helper::from_bcd(m_ram[REG_HOUR] & 0x1f) + (BIT(m_ram[REG_HOUR], 5) ? 12 : 0);
|
||||
else
|
||||
hour = time_helper::from_bcd(m_ram[REG_HOUR]);
|
||||
|
||||
if (data & RTMR_12H)
|
||||
{
|
||||
m_ram[REG_HOUR] = time_helper::make_bcd(hour % 12);
|
||||
m_ram[REG_HOUR] |= (hour > 11) ? 0x20 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ram[REG_HOUR] = time_helper::make_bcd(hour);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_OMR: // Not Applicable / Output Mode Register
|
||||
if (m_ram[REG_MSR] & MSR_RS)
|
||||
{
|
||||
// Not yet implemented: Buffered Crystal Oscillator output on MFO pin
|
||||
m_ram[offset] = data;
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_PFR_ICR0: // Periodic Flag Register / Interrupt Control Register 0
|
||||
if (m_ram[REG_MSR] & MSR_RS)
|
||||
{
|
||||
m_ram[offset] = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pfr &= ~PFR_TM;
|
||||
m_pfr |= data & PFR_TM;
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_TSCR_ICR1: // Time Save Control Register / Interrupt Control Register 1
|
||||
if (m_ram[REG_MSR] & MSR_RS)
|
||||
{
|
||||
m_ram[offset] = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tscr = data & ~TSCR_NA;
|
||||
if (data & TSCR_TS)
|
||||
save_registers();
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_RAM_D1D0: // RAM, D1/D0 bits only
|
||||
m_ram[offset] = data & 3;
|
||||
break;
|
||||
|
||||
case REG_NA_0FH:
|
||||
case REG_NA_10H:
|
||||
case REG_NA_11H:
|
||||
case REG_NA_12H:
|
||||
break;
|
||||
|
||||
default:
|
||||
m_ram[offset] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(dp8573_device::read)
|
||||
{
|
||||
uint8_t ret = m_ram[offset];
|
||||
|
||||
if (offset >= REG_RTMR && offset <= REG_TSCR_ICR1)
|
||||
{
|
||||
if (m_ram[REG_MSR] & MSR_RS)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case REG_RTMR:
|
||||
case REG_OMR:
|
||||
ret = 0;
|
||||
break;
|
||||
case REG_PFR_ICR0:
|
||||
ret = m_pfr;
|
||||
m_pfr &= ~PFR_READ_CLEAR_MASK;
|
||||
break;
|
||||
case REG_TSCR_ICR1:
|
||||
ret = m_tscr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOGMASKED(LOG_GENERAL, "%s: DP8573 - Register Read: %02x = %02x\n", machine().describe_context(), offset, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dp8573_device::nvram_default()
|
||||
{
|
||||
memset(m_ram, 0, 32);
|
||||
|
||||
m_pfr = 0;
|
||||
m_ram[REG_RTMR] = RTMR_CSS;
|
||||
}
|
||||
|
||||
void dp8573_device::nvram_read(emu_file &file)
|
||||
{
|
||||
file.read(m_ram, 32);
|
||||
}
|
||||
|
||||
void dp8573_device::nvram_write(emu_file &file)
|
||||
{
|
||||
file.write(m_ram, 32);
|
||||
}
|
148
src/devices/machine/dp8573.h
Normal file
148
src/devices/machine/dp8573.h
Normal file
@ -0,0 +1,148 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/***************************************************************************
|
||||
|
||||
DP8573 Real Time Clock (RTC)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DEVICES_MACHINE_DP8573_H
|
||||
#define DEVICES_MACHINE_DP8573_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class dp8573_device : public device_t, public device_nvram_interface
|
||||
{
|
||||
public:
|
||||
dp8573_device(const machine_config &mconfig, const char *tag, device_t *owner)
|
||||
: dp8573_device(mconfig, tag, owner, 32768)
|
||||
{
|
||||
}
|
||||
|
||||
dp8573_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(write);
|
||||
DECLARE_READ8_MEMBER(read);
|
||||
|
||||
auto irq() { return m_irq.bind(); }
|
||||
auto power_fail() { return m_pfail.bind(); }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
// device_nvram_interface overrides
|
||||
virtual void nvram_default() override;
|
||||
virtual void nvram_read(emu_file &file) override;
|
||||
virtual void nvram_write(emu_file &file) override;
|
||||
|
||||
void save_registers();
|
||||
void set_interrupt(uint8_t mask);
|
||||
void clear_interrupt(uint8_t mask);
|
||||
|
||||
static const device_timer_id TIMER_ID = 0;
|
||||
|
||||
enum
|
||||
{
|
||||
REG_MSR = 0x00, // Main Status Register
|
||||
REG_RTMR = 0x01, // Not Applicable / Real-Time Mode Register
|
||||
REG_OMR = 0x02, // Not Applicable / Output Mode Register
|
||||
REG_PFR_ICR0 = 0x03, // Periodic Flag Register / Interrupt Control Register 0
|
||||
REG_TSCR_ICR1 = 0x04, // Time Save Control Register / Interrupt Control Register 1
|
||||
REG_HUNDREDTH = 0x05, // Hundredths and Teneths of a Second (0-99)
|
||||
REG_SECOND = 0x06, // Seconds (0-59)
|
||||
REG_MINUTE = 0x07, // Minutes (0-59)
|
||||
REG_HOUR = 0x08, // Hours (1-12, 0-23)
|
||||
REG_DAY = 0x09, // Day of Month (1-28/29/30/31)
|
||||
REG_MONTH = 0x0a, // Month (1-12)
|
||||
REG_YEAR = 0x0b, // Year (0-99)
|
||||
// 0x0c - RAM
|
||||
REG_RAM_D1D0 = 0x0d, // RAM, D1/D0 bits only
|
||||
REG_DAYOFWEEK = 0x0e, // Day of Week (1-7)
|
||||
REG_NA_0FH = 0x0f,
|
||||
REG_NA_10H = 0x10,
|
||||
REG_NA_11H = 0x11,
|
||||
REG_NA_12H = 0x12,
|
||||
REG_COMP_SECOND = 0x13, // Seconds Compare RAM (0-59)
|
||||
REG_COMP_MINUTE = 0x14, // Minutes Compare RAM (0-59)
|
||||
REG_COMP_HOUR = 0x15, // Hours Compare RAM (1-12, 0-23)
|
||||
REG_COMP_DAY = 0x16, // Day of Month Compare RAM (1-28/29/30/31)
|
||||
REG_COMP_MONTH = 0x17, // Month Compare RAM (1-12)
|
||||
REG_COMP_DAYOFWEEK = 0x18, // Day of Week Compare RAM (1-7)
|
||||
REG_SAVE_SECOND = 0x19, // Seconds Time Save RAM
|
||||
REG_SAVE_MINUTE = 0x1a, // Minutes Time Save RAM
|
||||
REG_SAVE_HOUR = 0x1b, // Hours Time Save RAM
|
||||
REG_SAVE_DAY = 0x1c, // Day of Month Time Save RAM
|
||||
REG_SAVE_MONTH = 0x1d, // Month Time Save RAM
|
||||
// 0x1e - RAM
|
||||
REG_TEST = 0x1f, // RAM / Test Mode Register
|
||||
|
||||
MSR_INT = 0x01, // Interrupt Status
|
||||
MSR_PF = 0x02, // Power Fail Interrupt
|
||||
MSR_PER = 0x04, // Period Interrupt
|
||||
MSR_AL = 0x08, // Alarm Interrupt
|
||||
MSR_RS = 0x40, // Register Select Bit
|
||||
MSR_RAM_MASK = 0xf0,
|
||||
MSR_INT_MASK = 0x0e,
|
||||
MSR_CLEARABLE_MASK = 0x0c,
|
||||
|
||||
PFR_1MIN = 0x01, // Minutes flag
|
||||
PFR_10S = 0x02, // 10-second flag
|
||||
PFR_1S = 0x04, // Seconds flag
|
||||
PFR_100MS = 0x08, // 100-millisecond flag
|
||||
PFR_10MS = 0x10, // 10-millisecond flag
|
||||
PFR_1MS = 0x20, // Millisecond flag
|
||||
PFR_OSF = 0x40, // Oscillator Failed / Single Supply Bit
|
||||
PFR_TM = 0x80, // Test Mode Enable
|
||||
PFR_READ_CLEAR_MASK = 0x3f,
|
||||
|
||||
TSCR_RAM_MASK = 0x3f,
|
||||
TSCR_NA = 0x40, // N/A
|
||||
TSCR_TS = 0x80, // Time Save Enable
|
||||
|
||||
RTMR_LY0 = 0x01, // Leap Year LSB
|
||||
RTMR_LY1 = 0x02, // Leap Year MSB
|
||||
RTMR_LY = 0x03,
|
||||
RTMR_12H = 0x04, // 12/!24 hour mode
|
||||
RTMR_CSS = 0x08, // Clock Start/!Stop
|
||||
RTMR_IPF = 0x10, // Interrupt PF Operation
|
||||
RTMR_RAM_MASK = 0xe0,
|
||||
|
||||
OMR_RAM_MASK = 0x7f,
|
||||
OMR_MO = 0x80, // MFO Pin as Oscillator
|
||||
|
||||
ICR0_MN = 0x01, // Minutes enable
|
||||
ICR0_TS = 0x02, // 10-second enable
|
||||
ICR0_S = 0x04, // Seconds enable
|
||||
ICR0_HM = 0x08, // 100 millisecond enable
|
||||
ICR0_TM = 0x10, // 10 millisecond enable
|
||||
ICR0_1M = 0x20, // Milliseconds enable
|
||||
ICR0_RAM_MASK = 0xc0,
|
||||
|
||||
ICR1_SC = 0x01, // Second compare enable
|
||||
ICR1_MN = 0x02, // Minute compare enable
|
||||
ICR1_HR = 0x04, // Hour compare enable
|
||||
ICR1_DOM = 0x08, // Day of month compare enable
|
||||
ICR1_MO = 0x10, // Month compare enable
|
||||
ICR1_DOW = 0x20, // Day of week compare enable
|
||||
ICR1_ALE = 0x40, // Alarm interrupt enable
|
||||
ICR1_PFE = 0x80, // Power fail interrupt enable
|
||||
ICR1_COMPARE_MASK = 0x3f
|
||||
};
|
||||
|
||||
uint8_t m_ram[32];
|
||||
uint8_t m_tscr;
|
||||
uint8_t m_pfr;
|
||||
uint8_t m_millis;
|
||||
|
||||
emu_timer *m_timer;
|
||||
|
||||
devcb_write_line m_irq;
|
||||
devcb_write_line m_pfail;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(DP8573, dp8573_device)
|
||||
|
||||
#endif // DEVICES_MACHINE_DP8573_H
|
@ -26,13 +26,15 @@ public:
|
||||
return (((data >> 4) & 15) * 10) + (data & 15);
|
||||
}
|
||||
|
||||
static int inc_bcd(uint8_t *data, int mask, int min, int max)
|
||||
static int inc_bcd(uint8_t *data, int mask, int min, int max, bool *tens_carry = nullptr)
|
||||
{
|
||||
int bcd = (*data + 1) & mask;
|
||||
int carry = 0;
|
||||
|
||||
if ((bcd & 0x0f) > 9)
|
||||
{
|
||||
if (tens_carry)
|
||||
*tens_carry = true;
|
||||
bcd &= 0xf0;
|
||||
bcd += 0x10;
|
||||
if (bcd > max)
|
||||
@ -41,6 +43,10 @@ public:
|
||||
carry = 1;
|
||||
}
|
||||
}
|
||||
else if (tens_carry)
|
||||
{
|
||||
*tens_carry = false;
|
||||
}
|
||||
|
||||
*data = (*data & ~mask) | (bcd & mask);
|
||||
return carry;
|
||||
|
@ -21,8 +21,10 @@
|
||||
#include "bus/scsi/scsi.h"
|
||||
#include "bus/scsi/scsicd.h"
|
||||
#include "bus/scsi/scsihd.h"
|
||||
//#include "cpu/dsp56k/dsp56k.h"
|
||||
#include "cpu/mips/mips1.h"
|
||||
#include "cpu/mips/mips3.h"
|
||||
#include "machine/dp8573.h"
|
||||
#include "machine/eepromser.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "machine/sgi.h"
|
||||
@ -34,14 +36,13 @@
|
||||
#define LOG_UNKNOWN (1 << 0)
|
||||
#define LOG_INT (1 << 1)
|
||||
#define LOG_HPC (1 << 2)
|
||||
#define LOG_RTC (1 << 3)
|
||||
#define LOG_EEPROM (1 << 4)
|
||||
#define LOG_DMA (1 << 5)
|
||||
#define LOG_SCSI (1 << 6)
|
||||
#define LOG_SCSI_DMA (1 << 7)
|
||||
#define LOG_DUART (1 << 8)
|
||||
#define LOG_PIT (1 << 9)
|
||||
#define LOG_ALL (LOG_UNKNOWN | LOG_INT | LOG_HPC | LOG_RTC | LOG_EEPROM | LOG_DMA | LOG_SCSI | LOG_SCSI_DMA | LOG_DUART | LOG_PIT)
|
||||
#define LOG_ALL (LOG_UNKNOWN | LOG_INT | LOG_HPC | LOG_EEPROM | LOG_DMA | LOG_SCSI | LOG_SCSI_DMA | LOG_DUART | LOG_PIT)
|
||||
|
||||
#define VERBOSE (0)
|
||||
#include "logmacro.h"
|
||||
@ -56,6 +57,7 @@ public:
|
||||
, m_scc(*this, "scc%u", 0U)
|
||||
, m_eeprom(*this, "eeprom")
|
||||
, m_pit(*this, "pit")
|
||||
, m_rtc(*this, "rtc")
|
||||
{
|
||||
}
|
||||
|
||||
@ -64,14 +66,13 @@ public:
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
static const device_timer_id TIMER_RTC = 0;
|
||||
|
||||
DECLARE_READ32_MEMBER(hpc_r);
|
||||
DECLARE_WRITE32_MEMBER(hpc_w);
|
||||
DECLARE_READ32_MEMBER(int_r);
|
||||
DECLARE_WRITE32_MEMBER(int_w);
|
||||
DECLARE_READ32_MEMBER(dspram_r);
|
||||
DECLARE_WRITE32_MEMBER(dspram_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(scsi_irq);
|
||||
|
||||
void set_timer_int_clear(uint32_t data);
|
||||
@ -142,37 +143,18 @@ protected:
|
||||
HPC_DMACTRL_ENABLE = 0x80
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
RTC_DAYOFWEEK = 0x0e,
|
||||
RTC_YEAR = 0x0b,
|
||||
RTC_MONTH = 0x0a,
|
||||
RTC_DAY = 0x09,
|
||||
RTC_HOUR = 0x08,
|
||||
RTC_MINUTE = 0x07,
|
||||
RTC_SECOND = 0x06,
|
||||
RTC_HUNDREDTH = 0x05
|
||||
};
|
||||
|
||||
struct rtc_t
|
||||
{
|
||||
uint8_t m_ram[32];
|
||||
};
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<wd33c93_device> m_wd33c93;
|
||||
required_device_array<scc85230_device, 3> m_scc;
|
||||
required_device<eeprom_serial_93cxx_device> m_eeprom;
|
||||
required_device<pit8254_device> m_pit;
|
||||
required_device<dp8573_device> m_rtc;
|
||||
|
||||
std::unique_ptr<uint32_t[]> m_dsp_ram;
|
||||
|
||||
hpc_t m_hpc;
|
||||
rtc_t m_rtc;
|
||||
uint8_t m_duart_int_status;
|
||||
|
||||
emu_timer *m_rtc_timer;
|
||||
|
||||
void indigo_timer_rtc();
|
||||
|
||||
static char const *const RS232A_TAG;
|
||||
static char const *const RS232B_TAG;
|
||||
|
||||
@ -222,8 +204,7 @@ protected:
|
||||
|
||||
void indigo_state::machine_start()
|
||||
{
|
||||
m_rtc_timer = timer_alloc(TIMER_RTC);
|
||||
m_rtc_timer->adjust(attotime::never);
|
||||
m_dsp_ram = std::make_unique<uint32_t[]>(0x8000);
|
||||
|
||||
save_item(NAME(m_hpc.m_misc_status));
|
||||
save_item(NAME(m_hpc.m_parbuf_ptr));
|
||||
@ -243,29 +224,24 @@ void indigo_state::machine_start()
|
||||
save_item(NAME(m_hpc.m_scsi0_dma_to_mem));
|
||||
save_item(NAME(m_hpc.m_scsi0_dma_active));
|
||||
|
||||
save_item(NAME(m_rtc.m_ram));
|
||||
|
||||
save_item(NAME(m_duart_int_status));
|
||||
|
||||
save_pointer(NAME(m_dsp_ram), 0x8000);
|
||||
}
|
||||
|
||||
void indigo_state::machine_reset()
|
||||
{
|
||||
memset(&m_hpc, 0, sizeof(hpc_t));
|
||||
memset(&m_dsp_ram[0], 0, sizeof(uint32_t) * 0x8000);
|
||||
|
||||
m_duart_int_status = 0;
|
||||
|
||||
// update RTC every 1/100th of a second
|
||||
m_rtc_timer->adjust(attotime::from_msec(10), 0, attotime::from_msec(10));
|
||||
}
|
||||
|
||||
READ32_MEMBER(indigo_state::hpc_r)
|
||||
{
|
||||
if (offset >= 0x0e00/4 && offset <= 0x0e7c/4)
|
||||
{
|
||||
uint8_t ret = m_rtc.m_ram[offset - 0xe00/4];
|
||||
LOGMASKED(LOG_RTC, "%s: RTC RAM[0x%02x] Read: %02x\n", machine().describe_context(), offset - 0xe00/4, ret);
|
||||
return ret;
|
||||
}
|
||||
return m_rtc->read(space, offset - 0xe00/4);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x005c/4:
|
||||
@ -421,27 +397,7 @@ WRITE32_MEMBER(indigo_state::hpc_w)
|
||||
{
|
||||
if (offset >= 0x0e00/4 && offset <= 0x0e7c/4)
|
||||
{
|
||||
LOGMASKED(LOG_RTC, "%s: RTC RAM[%02x] Write: %02x\n", machine().describe_context(), offset - 0xe00/4, (uint8_t)data);
|
||||
m_rtc.m_ram[offset - 0xe00/4] = (uint8_t)data;
|
||||
|
||||
switch (offset - 0xe00/4)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 4:
|
||||
if (!BIT(m_rtc.m_ram[0x00], 7))
|
||||
{
|
||||
if (BIT(data, 7))
|
||||
{
|
||||
m_rtc.m_ram[0x19] = m_rtc.m_ram[RTC_SECOND];
|
||||
m_rtc.m_ram[0x1a] = m_rtc.m_ram[RTC_MINUTE];
|
||||
m_rtc.m_ram[0x1b] = m_rtc.m_ram[RTC_HOUR];
|
||||
m_rtc.m_ram[0x1c] = m_rtc.m_ram[RTC_DAY];
|
||||
m_rtc.m_ram[0x1d] = m_rtc.m_ram[RTC_MONTH];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
m_rtc->write(space, offset - 0xe00/4, (uint8_t)data);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -709,18 +665,6 @@ WRITE_LINE_MEMBER(indigo_state::scsi_irq)
|
||||
}
|
||||
}
|
||||
|
||||
void indigo_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_RTC:
|
||||
indigo_timer_rtc();
|
||||
break;
|
||||
default:
|
||||
assert_always(false, "Unknown id in indigo_state::device_timer");
|
||||
}
|
||||
}
|
||||
|
||||
void indigo_state::set_timer_int_clear(uint32_t data)
|
||||
{
|
||||
if (BIT(data, 0))
|
||||
@ -818,53 +762,16 @@ WRITE32_MEMBER(indigo_state::int_w)
|
||||
LOGMASKED(LOG_INT, "%s: INT Write: %08x = %08x & %08x\n", machine().describe_context(), 0x1fbd9000 + offset*4, data, mem_mask);
|
||||
}
|
||||
|
||||
void indigo_state::indigo_timer_rtc()
|
||||
READ32_MEMBER(indigo_state::dspram_r)
|
||||
{
|
||||
m_rtc.m_ram[RTC_HUNDREDTH]++;
|
||||
LOGMASKED(LOG_INT, "%s: DSP RAM Read: %08x & %08x\n", machine().describe_context(), 0x1fbe0000 + offset*4, mem_mask);
|
||||
return m_dsp_ram[offset];
|
||||
}
|
||||
|
||||
if ((m_rtc.m_ram[RTC_HUNDREDTH] & 0x0f) == 0x0a)
|
||||
{
|
||||
m_rtc.m_ram[RTC_HUNDREDTH] -= 0x0a;
|
||||
m_rtc.m_ram[RTC_HUNDREDTH] += 0x10;
|
||||
if ((m_rtc.m_ram[RTC_HUNDREDTH] & 0xa0) == 0xa0)
|
||||
{
|
||||
m_rtc.m_ram[RTC_HUNDREDTH] = 0;
|
||||
m_rtc.m_ram[RTC_SECOND]++;
|
||||
|
||||
if ((m_rtc.m_ram[RTC_SECOND] & 0x0f) == 0x0a)
|
||||
{
|
||||
m_rtc.m_ram[RTC_SECOND] -= 0x0a;
|
||||
m_rtc.m_ram[RTC_SECOND] += 0x10;
|
||||
if (m_rtc.m_ram[RTC_SECOND] == 0x60)
|
||||
{
|
||||
m_rtc.m_ram[RTC_SECOND] = 0;
|
||||
m_rtc.m_ram[RTC_MINUTE]++;
|
||||
|
||||
if ((m_rtc.m_ram[RTC_MINUTE] & 0x0f) == 0x0a)
|
||||
{
|
||||
m_rtc.m_ram[RTC_MINUTE] -= 0x0a;
|
||||
m_rtc.m_ram[RTC_MINUTE] += 0x10;
|
||||
if (m_rtc.m_ram[RTC_MINUTE] == 0x60)
|
||||
{
|
||||
m_rtc.m_ram[RTC_MINUTE] = 0;
|
||||
m_rtc.m_ram[RTC_HOUR]++;
|
||||
|
||||
if ((m_rtc.m_ram[RTC_HOUR] & 0x0f) == 0x0a)
|
||||
{
|
||||
m_rtc.m_ram[RTC_HOUR] -= 0x0a;
|
||||
m_rtc.m_ram[RTC_HOUR] += 0x10;
|
||||
if (m_rtc.m_ram[RTC_HOUR] == 0x24)
|
||||
{
|
||||
m_rtc.m_ram[RTC_HOUR] = 0;
|
||||
m_rtc.m_ram[RTC_DAY]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WRITE32_MEMBER(indigo_state::dspram_w)
|
||||
{
|
||||
LOGMASKED(LOG_INT, "%s: DSP RAM Write: %08x = %08x & %08x\n", machine().describe_context(), 0x1fbe0000 + offset*4, data, mem_mask);
|
||||
COMBINE_DATA(&m_dsp_ram[offset]);
|
||||
}
|
||||
|
||||
void indigo_state::indigo_map(address_map &map)
|
||||
@ -878,6 +785,7 @@ void indigo_state::indigo_map(address_map &map)
|
||||
map(0x18000000, 0x187fffff).ram().share("share7");
|
||||
map(0x1fb80000, 0x1fb8ffff).rw(FUNC(indigo_state::hpc_r), FUNC(indigo_state::hpc_w));
|
||||
map(0x1fbd9000, 0x1fbd903f).rw(FUNC(indigo_state::int_r), FUNC(indigo_state::int_w));
|
||||
map(0x1fbe0000, 0x1fbe7fff).rw(FUNC(indigo_state::dspram_r), FUNC(indigo_state::dspram_w));
|
||||
}
|
||||
|
||||
void indigo3k_state::mem_map(address_map &map)
|
||||
@ -941,6 +849,8 @@ void indigo_state::indigo_base(machine_config &config)
|
||||
scsi.set_slot_device(2, "cdrom", SCSICD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_4));
|
||||
scsi.slot(2).set_option_machine_config("cdrom", cdrom_config);
|
||||
|
||||
DP8573(config, m_rtc);
|
||||
|
||||
WD33C93(config, m_wd33c93);
|
||||
m_wd33c93->set_scsi_port("scsi");
|
||||
m_wd33c93->irq_cb().set(FUNC(indigo_state::scsi_irq));
|
||||
|
@ -21180,6 +21180,7 @@ gldarrow // (c) 1984 Meyco Games
|
||||
|
||||
@source:mfabfz.cpp
|
||||
mfabfz //
|
||||
mfabfz64k //
|
||||
mfabfz85 //
|
||||
|
||||
@source:mgames.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user