mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Made Epson R4543 RTC a proper RTC device, eliminates duplicated code in Namco Systems 12 and 23 [R. Belmont]
This commit is contained in:
parent
ba5468b246
commit
449d8c260a
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1178,6 +1178,8 @@ src/emu/machine/rp5c15.c svneol=native#text/plain
|
||||
src/emu/machine/rp5c15.h svneol=native#text/plain
|
||||
src/emu/machine/rp5h01.c svneol=native#text/plain
|
||||
src/emu/machine/rp5h01.h svneol=native#text/plain
|
||||
src/emu/machine/rtc4543.c svneol=native#text/plain
|
||||
src/emu/machine/rtc4543.h svneol=native#text/plain
|
||||
src/emu/machine/rtc65271.c svneol=native#text/plain
|
||||
src/emu/machine/rtc65271.h svneol=native#text/plain
|
||||
src/emu/machine/rtc9701.c svneol=native#text/plain
|
||||
|
@ -239,6 +239,7 @@ EMUMACHINEOBJS = \
|
||||
$(EMUMACHINE)/rp5c01.o \
|
||||
$(EMUMACHINE)/rp5c15.o \
|
||||
$(EMUMACHINE)/rp5h01.o \
|
||||
$(EMUMACHINE)/rtc4543.o \
|
||||
$(EMUMACHINE)/rtc65271.o \
|
||||
$(EMUMACHINE)/rtc9701.o \
|
||||
$(EMUMACHINE)/s3c2400.o \
|
||||
|
191
src/emu/machine/rtc4543.c
Normal file
191
src/emu/machine/rtc4543.c
Normal file
@ -0,0 +1,191 @@
|
||||
/**********************************************************************
|
||||
|
||||
rtc4543.c - Epson R4543 real-time clock chip emulation
|
||||
by R. Belmont
|
||||
|
||||
TODO: writing (not done by System 12 or 23 so no test case)
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "rtc4543.h"
|
||||
|
||||
//**************************************************************************
|
||||
// MACROS / CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
const device_type RTC4543 = &device_creator<rtc4543_device>;
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// rtc4543_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
rtc4543_device::rtc4543_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, RTC4543, "Epson R4543", tag, owner, clock),
|
||||
device_rtc_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void rtc4543_device::device_start()
|
||||
{
|
||||
// allocate timers
|
||||
m_clock_timer = timer_alloc();
|
||||
m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
|
||||
|
||||
// state saving
|
||||
save_item(NAME(m_ce));
|
||||
save_item(NAME(m_clk));
|
||||
save_item(NAME(m_wr));
|
||||
save_item(NAME(m_data));
|
||||
save_item(NAME(m_regs));
|
||||
save_item(NAME(m_curreg));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void rtc4543_device::device_reset()
|
||||
{
|
||||
set_current_time(machine());
|
||||
|
||||
m_ce = 0;
|
||||
m_wr = 0;
|
||||
m_clk = 0;
|
||||
m_data = 0;
|
||||
m_curreg = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_timer - handler timer events
|
||||
//-------------------------------------------------
|
||||
|
||||
void rtc4543_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
advance_seconds();
|
||||
}
|
||||
|
||||
|
||||
INLINE UINT8 make_bcd(UINT8 data)
|
||||
{
|
||||
return ((data / 10) << 4) | (data % 10);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rtc_clock_updated -
|
||||
//-------------------------------------------------
|
||||
|
||||
void rtc4543_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
|
||||
{
|
||||
static const int weekday[7] = { 7, 1, 2, 3, 4, 5, 6 };
|
||||
|
||||
m_regs[0] = make_bcd(second); // seconds (BCD, 0-59) in bits 0-6, bit 7 = battery low
|
||||
m_regs[1] = make_bcd(minute); // minutes (BCD, 0-59)
|
||||
m_regs[2] = make_bcd(hour); // hour (BCD, 0-23)
|
||||
m_regs[3] = make_bcd(weekday[day_of_week]); // low nibble = day of the week
|
||||
m_regs[3] |= (make_bcd(day) & 0x0f)<<4; // high nibble = low digit of day
|
||||
m_regs[4] = (make_bcd(day) >> 4); // low nibble = high digit of day
|
||||
m_regs[4] |= (make_bcd(month & 0x0f)<<4); // high nibble = low digit of month
|
||||
m_regs[5] = make_bcd(month & 0x0f) >> 4; // low nibble = high digit of month
|
||||
m_regs[5] |= (make_bcd(year % 10) << 4); // high nibble = low digit of year
|
||||
m_regs[6] = make_bcd(year % 100) >> 4; // low nibble = tens digit of year (BCD, 0-9)
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// ce_w - chip enable write
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( rtc4543_device::ce_w )
|
||||
{
|
||||
if (VERBOSE) printf("RTC4543 '%s' CE: %u\n", tag(), state);
|
||||
|
||||
if (!state && m_ce) // complete transfer
|
||||
{
|
||||
}
|
||||
else if (state && !m_ce) // start new data transfer
|
||||
{
|
||||
m_curreg = 0;
|
||||
m_bit = 8; // force immediate reload of output data
|
||||
}
|
||||
|
||||
m_ce = state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// wr_w - data direction line write
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( rtc4543_device::wr_w )
|
||||
{
|
||||
if (VERBOSE) logerror("RTC4543 '%s' WR: %u\n", tag(), state);
|
||||
|
||||
m_wr = state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// clk_w - serial clock write
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( rtc4543_device::clk_w )
|
||||
{
|
||||
if (VERBOSE) logerror("RTC4543 '%s' CLK: %u\n", tag(), state);
|
||||
|
||||
if (!m_ce) return;
|
||||
|
||||
if (!m_clk && state) // rising edge - read data becomes valid here
|
||||
{
|
||||
if (m_bit > 7) // reload data?
|
||||
{
|
||||
m_bit = 0;
|
||||
m_data = m_regs[m_curreg++];
|
||||
}
|
||||
else // no reload, just continue with the current byte
|
||||
{
|
||||
m_data <<= 1;
|
||||
}
|
||||
|
||||
m_bit++;
|
||||
}
|
||||
else if (m_clk && !state) // falling edge - write data becomes valid here
|
||||
{
|
||||
}
|
||||
|
||||
m_clk = state;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// data_w - I/O write
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( rtc4543_device::data_w )
|
||||
{
|
||||
if (VERBOSE) logerror("RTC4543 '%s' I/O: %u\n", tag(), state);
|
||||
|
||||
m_data |= (state & 1);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// data_r - I/O read
|
||||
//-------------------------------------------------
|
||||
|
||||
READ_LINE_MEMBER( rtc4543_device::data_r )
|
||||
{
|
||||
return (m_data & 0x80) ? 1 : 0;
|
||||
}
|
||||
|
72
src/emu/machine/rtc4543.h
Normal file
72
src/emu/machine/rtc4543.h
Normal file
@ -0,0 +1,72 @@
|
||||
/**********************************************************************
|
||||
|
||||
rtc4543.h - Epson R4543 real-time clock emulation
|
||||
by R. Belmont
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __RTC4543_H__
|
||||
#define __RTC4543_H__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_RTC4543_ADD(_tag, _clock) \
|
||||
MCFG_DEVICE_ADD(_tag, RTC4543, _clock)
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> rtc4543_device
|
||||
|
||||
class rtc4543_device : public device_t,
|
||||
public device_rtc_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
rtc4543_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( ce_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( wr_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( clk_w );
|
||||
DECLARE_READ_LINE_MEMBER( data_r );
|
||||
DECLARE_WRITE_LINE_MEMBER( data_w );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
// device_rtc_interface overrides
|
||||
virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second);
|
||||
virtual bool rtc_feature_leap_year() { return true; }
|
||||
|
||||
private:
|
||||
int m_ce;
|
||||
int m_clk;
|
||||
int m_wr;
|
||||
int m_data;
|
||||
int m_regs[7];
|
||||
int m_curreg;
|
||||
int m_bit;
|
||||
|
||||
// timers
|
||||
emu_timer *m_clock_timer;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type RTC4543;
|
||||
|
||||
#endif
|
@ -1039,6 +1039,7 @@ Notes:
|
||||
#include "includes/psx.h"
|
||||
#include "machine/at28c16.h"
|
||||
#include "sound/c352.h"
|
||||
#include "machine/rtc4543.h"
|
||||
|
||||
#define VERBOSE_LEVEL ( 0 )
|
||||
|
||||
@ -1047,8 +1048,10 @@ class namcos12_state : public psx_state
|
||||
public:
|
||||
namcos12_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: psx_state(mconfig, type, tag),
|
||||
m_rtc(*this, "rtc"),
|
||||
m_sharedram(*this, "sharedram") { }
|
||||
|
||||
required_device<rtc4543_device> m_rtc;
|
||||
required_shared_ptr<UINT32> m_sharedram;
|
||||
UINT32 m_n_bankoffset;
|
||||
|
||||
@ -1467,59 +1470,21 @@ READ8_MEMBER(namcos12_state::s12_mcu_pa_r)
|
||||
|
||||
WRITE8_MEMBER(namcos12_state::s12_mcu_pa_w)
|
||||
{
|
||||
|
||||
// bit 0 = chip enable for the RTC
|
||||
// reset the state on the rising edge of the bit
|
||||
if ((!(m_s12_porta & 1)) && (data & 1))
|
||||
{
|
||||
m_s12_rtcstate = 0;
|
||||
}
|
||||
|
||||
m_rtc->ce_w(data & 1);
|
||||
m_s12_porta = data;
|
||||
}
|
||||
|
||||
INLINE UINT8 make_bcd(UINT8 data)
|
||||
{
|
||||
return ((data / 10) << 4) | (data % 10);
|
||||
}
|
||||
|
||||
READ8_MEMBER(namcos12_state::s12_mcu_rtc_r)
|
||||
{
|
||||
UINT8 ret = 0;
|
||||
system_time systime;
|
||||
static const int weekday[7] = { 7, 1, 2, 3, 4, 5, 6 };
|
||||
UINT8 ret = 0;
|
||||
|
||||
machine().current_datetime(systime);
|
||||
|
||||
switch (m_s12_rtcstate)
|
||||
{
|
||||
case 0:
|
||||
ret = make_bcd(systime.local_time.second); // seconds (BCD, 0-59) in bits 0-6, bit 7 = battery low
|
||||
break;
|
||||
case 1:
|
||||
ret = make_bcd(systime.local_time.minute); // minutes (BCD, 0-59)
|
||||
break;
|
||||
case 2:
|
||||
ret = make_bcd(systime.local_time.hour); // hour (BCD, 0-23)
|
||||
break;
|
||||
case 3:
|
||||
ret = make_bcd(weekday[systime.local_time.weekday]); // low nibble = day of the week
|
||||
ret |= (make_bcd(systime.local_time.mday) & 0x0f)<<4; // high nibble = low digit of day
|
||||
break;
|
||||
case 4:
|
||||
ret = (make_bcd(systime.local_time.mday) >> 4); // low nibble = high digit of day
|
||||
ret |= (make_bcd(systime.local_time.month + 1) & 0x0f)<<4; // high nibble = low digit of month
|
||||
break;
|
||||
case 5:
|
||||
ret = make_bcd(systime.local_time.month + 1) >> 4; // low nibble = high digit of month
|
||||
ret |= (make_bcd(systime.local_time.year % 10) << 4); // high nibble = low digit of year
|
||||
break;
|
||||
case 6:
|
||||
ret = make_bcd(systime.local_time.year % 100) >> 4; // low nibble = tens digit of year (BCD, 0-9)
|
||||
break;
|
||||
}
|
||||
|
||||
m_s12_rtcstate++;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
m_rtc->clk_w(0);
|
||||
m_rtc->clk_w(1);
|
||||
ret <<= 1;
|
||||
ret |= m_rtc->data_r();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1682,6 +1647,8 @@ static MACHINE_CONFIG_START( coh700, namcos12_state )
|
||||
|
||||
MCFG_MACHINE_RESET_OVERRIDE(namcos12_state, namcos12 )
|
||||
|
||||
MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_PSXGPU_ADD( "maincpu", "gpu", CXD8654Q, 0x200000, XTAL_53_693175MHz )
|
||||
MCFG_PSXGPU_VBLANK_CALLBACK( vblank_state_delegate( FUNC( namcos12_sub_irq ), (namcos12_state *) owner ) )
|
||||
|
@ -1228,6 +1228,7 @@ Notes:
|
||||
#include "cpu/sh2/sh2.h"
|
||||
#include "sound/c352.h"
|
||||
#include "machine/nvram.h"
|
||||
#include "machine/rtc4543.h"
|
||||
|
||||
#define S23_BUSCLOCK (66664460/2) /* 33MHz CPU bus clock / input, somehow derived from 14.31721 MHz crystal */
|
||||
#define S23_H8CLOCK (14745600)
|
||||
@ -1320,6 +1321,7 @@ class namcos23_state : public driver_device
|
||||
public:
|
||||
namcos23_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag) ,
|
||||
m_rtc(*this, "rtc"),
|
||||
m_shared_ram(*this, "shared_ram"),
|
||||
m_charram(*this, "charram"),
|
||||
m_textram(*this, "textram"),
|
||||
@ -1333,6 +1335,7 @@ public:
|
||||
render_t m_render;
|
||||
|
||||
tilemap_t *m_bgtilemap;
|
||||
required_device<rtc4543_device> m_rtc;
|
||||
required_shared_ptr<UINT32> m_shared_ram;
|
||||
required_shared_ptr<UINT32> m_charram;
|
||||
required_shared_ptr<UINT32> m_textram;
|
||||
@ -2610,57 +2613,21 @@ READ8_MEMBER(namcos23_state::s23_mcu_pa_r)
|
||||
WRITE8_MEMBER(namcos23_state::s23_mcu_pa_w)
|
||||
{
|
||||
// bit 0 = chip enable for the RTC
|
||||
// reset the state on the rising edge of the bit
|
||||
if ((!(m_s23_porta & 1)) && (data & 1))
|
||||
{
|
||||
m_s23_rtcstate = 0;
|
||||
}
|
||||
|
||||
m_rtc->ce_w(data & 1);
|
||||
m_s23_porta = data;
|
||||
}
|
||||
|
||||
INLINE UINT8 make_bcd(UINT8 data)
|
||||
{
|
||||
return ((data / 10) << 4) | (data % 10);
|
||||
}
|
||||
|
||||
READ8_MEMBER(namcos23_state::s23_mcu_rtc_r)
|
||||
{
|
||||
UINT8 ret = 0;
|
||||
system_time systime;
|
||||
static const int weekday[7] = { 7, 1, 2, 3, 4, 5, 6 };
|
||||
UINT8 ret = 0;
|
||||
|
||||
machine().current_datetime(systime);
|
||||
|
||||
switch (m_s23_rtcstate)
|
||||
{
|
||||
case 0:
|
||||
ret = make_bcd(systime.local_time.second); // seconds (BCD, 0-59) in bits 0-6, bit 7 = battery low
|
||||
break;
|
||||
case 1:
|
||||
ret = make_bcd(systime.local_time.minute); // minutes (BCD, 0-59)
|
||||
break;
|
||||
case 2:
|
||||
ret = make_bcd(systime.local_time.hour); // hour (BCD, 0-23)
|
||||
break;
|
||||
case 3:
|
||||
ret = make_bcd(weekday[systime.local_time.weekday]); // low nibble = day of the week
|
||||
ret |= (make_bcd(systime.local_time.mday) & 0x0f)<<4; // high nibble = low digit of day
|
||||
break;
|
||||
case 4:
|
||||
ret = (make_bcd(systime.local_time.mday) >> 4); // low nibble = high digit of day
|
||||
ret |= (make_bcd(systime.local_time.month + 1) & 0x0f)<<4; // high nibble = low digit of month
|
||||
break;
|
||||
case 5:
|
||||
ret = make_bcd(systime.local_time.month + 1) >> 4; // low nibble = high digit of month
|
||||
ret |= (make_bcd(systime.local_time.year % 10) << 4); // high nibble = low digit of year
|
||||
break;
|
||||
case 6:
|
||||
ret = make_bcd(systime.local_time.year % 100) >> 4; // low nibble = tens digit of year (BCD, 0-9)
|
||||
break;
|
||||
}
|
||||
|
||||
m_s23_rtcstate++;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
m_rtc->clk_w(0);
|
||||
m_rtc->clk_w(1);
|
||||
ret <<= 1;
|
||||
ret |= m_rtc->data_r();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -3161,6 +3128,8 @@ static MACHINE_CONFIG_START( gorgon, namcos23_state )
|
||||
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(60000))
|
||||
|
||||
MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
|
||||
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(S23_VSYNC1)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // Not in any way accurate
|
||||
@ -3206,6 +3175,8 @@ static MACHINE_CONFIG_START( s23, namcos23_state )
|
||||
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(60000))
|
||||
|
||||
MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
|
||||
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(S23_VSYNC1)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // Not in any way accurate
|
||||
@ -3247,6 +3218,8 @@ static MACHINE_CONFIG_START( ss23, namcos23_state )
|
||||
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(60000))
|
||||
|
||||
MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
|
||||
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(S23_VSYNC1)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // Not in any way accurate
|
||||
|
Loading…
Reference in New Issue
Block a user