Imported MSM5832 RTC from MESS. (no whatsnew)

This commit is contained in:
Curt Coder 2011-04-17 14:10:26 +00:00
parent c972282319
commit 4f3f0decb8
6 changed files with 1088 additions and 0 deletions

4
.gitattributes vendored
View File

@ -928,6 +928,10 @@ src/emu/mconfig.h svneol=native#text/plain
src/emu/memconv.h svneol=native#text/plain
src/emu/memory.c svneol=native#text/plain
src/emu/memory.h svneol=native#text/plain
src/emu/msm5832.c svneol=native#text/plain
src/emu/msm5832.h svneol=native#text/plain
src/emu/msm58321.c svneol=native#text/plain
src/emu/msm58321.h svneol=native#text/plain
src/emu/output.c svneol=native#text/plain
src/emu/output.h svneol=native#text/plain
src/emu/profiler.c svneol=native#text/plain

View File

@ -193,6 +193,7 @@ EMUMACHINEOBJS = \
$(EMUMACHINE)/mc146818.o \
$(EMUMACHINE)/mc6852.o \
$(EMUMACHINE)/mc68901.o \
$(EMUMACHINE)/msm5832.o \
$(EMUMACHINE)/msm58321.o \
$(EMUMACHINE)/microtch.o \
$(EMUMACHINE)/mos6529.o \

375
src/emu/msm5832.c Normal file
View File

@ -0,0 +1,375 @@
/**********************************************************************
OKI MSM5832 Real Time Clock/Calendar emulation
Copyright MESS Team.
Visit http://mamedev.org for licensing and usage restrictions.
**********************************************************************/
/*
TODO:
- 12/24 hour
- AM/PM
- leap year
- test input
- reference signal output
*/
#include "msm5832.h"
#include "machine/devhelpr.h"
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
#define LOG 0
// registers
enum
{
REGISTER_S1 = 0,
REGISTER_S10,
REGISTER_MI1,
REGISTER_MI10,
REGISTER_H1,
REGISTER_H10,
REGISTER_W,
REGISTER_D1,
REGISTER_D10,
REGISTER_MO1,
REGISTER_MO10,
REGISTER_Y1,
REGISTER_Y10,
REGISTER_REF = 15
};
// days per month
static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// devices
const device_type MSM5832 = msm5832_device_config::static_alloc_device_config;
//**************************************************************************
// DEVICE CONFIGURATION
//**************************************************************************
GENERIC_DEVICE_CONFIG_SETUP(msm5832, "MSM5832")
//**************************************************************************
// INLINE HELPERS
//**************************************************************************
//-------------------------------------------------
// read_counter -
//-------------------------------------------------
inline int msm5832_device::read_counter(int counter)
{
return (m_reg[counter + 1] * 10) + m_reg[counter];
}
//-------------------------------------------------
// write_counter -
//-------------------------------------------------
inline void msm5832_device::write_counter(int counter, int value)
{
m_reg[counter] = value % 10;
m_reg[counter + 1] = value / 10;
}
//-------------------------------------------------
// advance_seconds -
//-------------------------------------------------
inline void msm5832_device::advance_seconds()
{
int seconds = read_counter(REGISTER_S1);
seconds++;
if (seconds > 59)
{
seconds = 0;
advance_minutes();
}
write_counter(REGISTER_S1, seconds);
}
//-------------------------------------------------
// advance_minutes -
//-------------------------------------------------
inline void msm5832_device::advance_minutes()
{
int minutes = read_counter(REGISTER_MI1);
int hours = read_counter(REGISTER_H1);
int days = read_counter(REGISTER_D1);
int month = read_counter(REGISTER_MO1);
int year = read_counter(REGISTER_Y1);
int day_of_week = m_reg[REGISTER_W];
minutes++;
if (minutes > 59)
{
minutes = 0;
hours++;
}
if (hours > 23)
{
hours = 0;
days++;
day_of_week++;
}
if (day_of_week > 6)
{
day_of_week++;
}
if (days > DAYS_PER_MONTH[month - 1])
{
days = 1;
month++;
}
if (month > 12)
{
month = 1;
year++;
}
if (year > 99)
{
year = 0;
}
write_counter(REGISTER_MI1, minutes);
write_counter(REGISTER_H1, hours);
write_counter(REGISTER_D1, days);
write_counter(REGISTER_MO1, month);
write_counter(REGISTER_Y1, year);
m_reg[REGISTER_W] = day_of_week;
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// msm5832_device - constructor
//-------------------------------------------------
msm5832_device::msm5832_device(running_machine &_machine, const msm5832_device_config &config)
: device_t(_machine, config),
m_hold(0),
m_address(0),
m_read(0),
m_write(0),
m_cs(0),
m_config(config)
{
for (int i = 0; i < 13; i++)
m_reg[i] = 0;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void msm5832_device::device_start()
{
// allocate timers
m_clock_timer = timer_alloc(TIMER_CLOCK);
m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
// state saving
save_item(NAME(m_reg));
save_item(NAME(m_hold));
save_item(NAME(m_address));
save_item(NAME(m_read));
save_item(NAME(m_write));
save_item(NAME(m_cs));
}
//-------------------------------------------------
// device_timer - handler timer events
//-------------------------------------------------
void msm5832_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
case TIMER_CLOCK:
if (!m_hold)
{
advance_seconds();
}
break;
}
}
//-------------------------------------------------
// data_r -
//-------------------------------------------------
READ8_MEMBER( msm5832_device::data_r )
{
UINT8 data = 0;
if (m_cs && m_read)
{
if (m_address == REGISTER_REF)
{
// TODO reference output
}
else
{
data = m_reg[m_address];
}
}
if (LOG) logerror("MSM5832 '%s' Register Read %01x: %01x\n", tag(), m_address, data & 0x0f);
return data & 0x0f;
}
//-------------------------------------------------
// data_w -
//-------------------------------------------------
WRITE8_MEMBER( msm5832_device::data_w )
{
if (LOG) logerror("MSM5832 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f);
if (m_cs && m_write)
{
m_reg[m_address] = data & 0x0f;
}
}
//-------------------------------------------------
// address_w -
//-------------------------------------------------
void msm5832_device::address_w(UINT8 data)
{
if (LOG) logerror("MSM5832 '%s' Address: %01x\n", tag(), data & 0x0f);
m_address = data & 0x0f;
}
//-------------------------------------------------
// adj_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm5832_device::adj_w )
{
if (LOG) logerror("MSM5832 '%s' 30 ADJ: %u\n", tag(), state);
if (state)
{
int seconds = read_counter(REGISTER_S1);
if (seconds < 30)
{
write_counter(REGISTER_S1, 0);
}
else
{
write_counter(REGISTER_S1, 0);
advance_minutes();
}
}
}
//-------------------------------------------------
// test_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm5832_device::test_w )
{
if (LOG) logerror("MSM5832 '%s' TEST: %u\n", tag(), state);
}
//-------------------------------------------------
// hold_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm5832_device::hold_w )
{
if (LOG) logerror("MSM5832 '%s' HOLD: %u\n", tag(), state);
m_hold = state;
}
//-------------------------------------------------
// read_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm5832_device::read_w )
{
if (LOG) logerror("MSM5832 '%s' READ: %u\n", tag(), state);
m_read = state;
}
//-------------------------------------------------
// write_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm5832_device::write_w )
{
if (LOG) logerror("MSM5832 '%s' WR: %u\n", tag(), state);
m_write = state;
}
//-------------------------------------------------
// cs_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm5832_device::cs_w )
{
if (LOG) logerror("MSM5832 '%s' CS: %u\n", tag(), state);
m_cs = state;
}

118
src/emu/msm5832.h Normal file
View File

@ -0,0 +1,118 @@
/**********************************************************************
OKI MSM5832 Real Time Clock/Calendar emulation
Copyright MESS Team.
Visit http://mamedev.org for licensing and usage restrictions.
**********************************************************************
_____ _____
Vdd 1 |* \_/ | 18 HOLD
WRITE 2 | | 17 _XT
READ 3 | | 16 XT
A0 4 | | 15 +- 30 ADJ
A1 5 | MSM5832 | 14 TEST
A2 6 | | 13 GND
A3 7 | | 12 D3
CS 8 | | 11 D2
D0 9 |_____________| 10 D1
**********************************************************************/
#pragma once
#ifndef __MSM5832__
#define __MSM5832__
#include "emu.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_MSM5832_ADD(_tag, _clock) \
MCFG_DEVICE_ADD(_tag, MSM5832, _clock)
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> msm5832_device_config
class msm5832_device_config : public device_config
{
friend class msm5832_device;
// construction/destruction
msm5832_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
public:
// allocators
static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
virtual device_t *alloc_device(running_machine &machine) const;
};
// ======================> msm5832_device
class msm5832_device : public device_t
{
friend class msm5832_device_config;
// construction/destruction
msm5832_device(running_machine &_machine, const msm5832_device_config &_config);
public:
DECLARE_READ8_MEMBER( data_r );
DECLARE_WRITE8_MEMBER( data_w );
void address_w(UINT8 data);
DECLARE_WRITE_LINE_MEMBER( adj_w );
DECLARE_WRITE_LINE_MEMBER( test_w );
DECLARE_WRITE_LINE_MEMBER( hold_w );
DECLARE_WRITE_LINE_MEMBER( read_w );
DECLARE_WRITE_LINE_MEMBER( write_w );
DECLARE_WRITE_LINE_MEMBER( cs_w );
protected:
// device-level overrides
virtual void device_start();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
static const device_timer_id TIMER_CLOCK = 0;
inline int read_counter(int counter);
inline void write_counter(int counter, int value);
inline void advance_seconds();
inline void advance_minutes();
UINT8 m_reg[13]; // registers
int m_hold; // counter hold
int m_address; // address
int m_read;
int m_write;
int m_cs;
// timers
emu_timer *m_clock_timer;
const msm5832_device_config &m_config;
};
// device type definition
extern const device_type MSM5832;
#endif

450
src/emu/msm58321.c Normal file
View File

@ -0,0 +1,450 @@
/**********************************************************************
OKI MSM58321RS Real Time Clock/Calendar emulation
Copyright MESS Team.
Visit http://mamedev.org for licensing and usage restrictions.
**********************************************************************/
/*
TODO:
- 12/24 hour
- AM/PM
- leap year
- stop
- reset
- reference registers
*/
#include "msm58321.h"
#include "machine/devhelpr.h"
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
#define LOG 1
// registers
enum
{
REGISTER_S1 = 0,
REGISTER_S10,
REGISTER_MI1,
REGISTER_MI10,
REGISTER_H1,
REGISTER_H10,
REGISTER_W,
REGISTER_D1,
REGISTER_D10,
REGISTER_MO1,
REGISTER_MO10,
REGISTER_Y1,
REGISTER_Y10,
REGISTER_RESET,
REGISTER_REF0,
REGISTER_REF1
};
// days per month
static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// devices
const device_type MSM58321 = msm58321_device_config::static_alloc_device_config;
//**************************************************************************
// DEVICE CONFIGURATION
//**************************************************************************
GENERIC_DEVICE_CONFIG_SETUP(msm58321, "MSM58321")
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void msm58321_device_config::device_config_complete()
{
// inherit a copy of the static data
const msm58321_interface *intf = reinterpret_cast<const msm58321_interface *>(static_config());
if (intf != NULL)
*static_cast<msm58321_interface *>(this) = *intf;
// or initialize to defaults if none provided
else
{
memset(&m_out_busy_func, 0, sizeof(m_out_busy_func));
}
}
//**************************************************************************
// INLINE HELPERS
//**************************************************************************
//-------------------------------------------------
// read_counter -
//-------------------------------------------------
inline int msm58321_device::read_counter(int counter)
{
return (m_reg[counter + 1] * 10) + m_reg[counter];
}
//-------------------------------------------------
// write_counter -
//-------------------------------------------------
inline void msm58321_device::write_counter(int counter, int value)
{
m_reg[counter] = value % 10;
m_reg[counter + 1] = value / 10;
}
//-------------------------------------------------
// advance_seconds -
//-------------------------------------------------
inline void msm58321_device::advance_seconds()
{
int seconds = read_counter(REGISTER_S1);
seconds++;
if (seconds > 59)
{
seconds = 0;
advance_minutes();
}
write_counter(REGISTER_S1, seconds);
}
//-------------------------------------------------
// advance_minutes -
//-------------------------------------------------
inline void msm58321_device::advance_minutes()
{
int minutes = read_counter(REGISTER_MI1);
int hours = read_counter(REGISTER_H1);
int days = read_counter(REGISTER_D1);
int month = read_counter(REGISTER_MO1);
int year = read_counter(REGISTER_Y1);
int day_of_week = m_reg[REGISTER_W];
minutes++;
if (minutes > 59)
{
minutes = 0;
hours++;
}
if (hours > 23)
{
hours = 0;
days++;
day_of_week++;
}
if (day_of_week > 6)
{
day_of_week++;
}
if (days > DAYS_PER_MONTH[month - 1])
{
days = 1;
month++;
}
if (month > 12)
{
month = 1;
year++;
}
if (year > 99)
{
year = 0;
}
write_counter(REGISTER_MI1, minutes);
write_counter(REGISTER_H1, hours);
write_counter(REGISTER_D1, days);
write_counter(REGISTER_MO1, month);
write_counter(REGISTER_Y1, year);
m_reg[REGISTER_W] = day_of_week;
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// msm58321_device - constructor
//-------------------------------------------------
msm58321_device::msm58321_device(running_machine &_machine, const msm58321_device_config &config)
: device_t(_machine, config),
m_config(config)
{
for (int i = 0; i < 13; i++)
m_reg[i] = 0;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void msm58321_device::device_start()
{
// resolve callbacks
devcb_resolve_write_line(&m_out_busy_func, &m_config.m_out_busy_func, this);
// allocate timers
m_clock_timer = timer_alloc(TIMER_CLOCK);
m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
m_busy_timer = timer_alloc(TIMER_BUSY);
m_busy_timer->adjust(attotime::from_hz(clock() / 16384), 0, attotime::from_hz(clock() / 16384));
// state saving
save_item(NAME(m_cs1));
save_item(NAME(m_cs2));
save_item(NAME(m_busy));
save_item(NAME(m_read));
save_item(NAME(m_write));
save_item(NAME(m_address_write));
save_item(NAME(m_reg));
save_item(NAME(m_latch));
save_item(NAME(m_address));
}
//-------------------------------------------------
// device_timer - handler timer events
//-------------------------------------------------
void msm58321_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
case TIMER_CLOCK:
advance_seconds();
break;
case TIMER_BUSY:
devcb_call_write_line(&m_out_busy_func, m_busy);
m_busy = !m_busy;
break;
}
}
//-------------------------------------------------
// read -
//-------------------------------------------------
READ8_MEMBER( msm58321_device::read )
{
UINT8 data = 0;
if (m_cs1 && m_cs2)
{
if (m_read)
{
switch (m_address)
{
case REGISTER_RESET:
break;
case REGISTER_REF0:
case REGISTER_REF1:
break;
default:
data = m_reg[m_address];
break;
}
}
if (m_write)
{
if (m_address >= REGISTER_REF0)
{
// TODO: output reference values
}
}
}
if (LOG) logerror("MSM58321 '%s' Register Read %01x: %01x\n", tag(), m_address, data & 0x0f);
return data;
}
//-------------------------------------------------
// write -
//-------------------------------------------------
WRITE8_MEMBER( msm58321_device::write )
{
// latch data for future use
m_latch = data & 0x0f;
if (!m_cs1 || !m_cs2) return;
if (m_address_write)
{
if (LOG) logerror("MSM58321 '%s' Latch Address %01x\n", tag(), m_latch);
// latch address
m_address = m_latch;
}
if (m_write)
{
switch(m_address)
{
case REGISTER_RESET:
if (LOG) logerror("MSM58321 '%s' Reset\n", tag());
break;
case REGISTER_REF0:
case REGISTER_REF1:
if (LOG) logerror("MSM58321 '%s' Reference Signal\n", tag());
break;
default:
if (LOG) logerror("MSM58321 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f);
m_reg[m_address] = m_latch & 0x0f;
break;
}
}
}
//-------------------------------------------------
// cs1_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm58321_device::cs1_w )
{
if (LOG) logerror("MSM58321 '%s' CS1: %u\n", tag(), state);
m_cs1 = state;
}
//-------------------------------------------------
// cs2_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm58321_device::cs2_w )
{
if (LOG) logerror("MSM58321 '%s' CS2: %u\n", tag(), state);
m_cs2 = state;
}
//-------------------------------------------------
// read_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm58321_device::read_w )
{
if (LOG) logerror("MSM58321 '%s' READ: %u\n", tag(), state);
m_read = state;
}
//-------------------------------------------------
// write_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm58321_device::write_w )
{
if (LOG) logerror("MSM58321 '%s' WRITE: %u\n", tag(), state);
m_write = state;
}
//-------------------------------------------------
// address_write_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm58321_device::address_write_w )
{
if (LOG) logerror("MSM58321 '%s' ADDRESS WRITE: %u\n", tag(), state);
m_address_write = state;
if (m_address_write)
{
if (LOG) logerror("MSM58321 '%s' Latch Address %01x\n", tag(), m_latch);
// latch address
m_address = m_latch;
}
}
//-------------------------------------------------
// stop_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm58321_device::stop_w )
{
if (LOG) logerror("MSM58321 '%s' STOP: %u\n", tag(), state);
}
//-------------------------------------------------
// test_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( msm58321_device::test_w )
{
if (LOG) logerror("MSM58321 '%s' TEST: %u\n", tag(), state);
}
//-------------------------------------------------
// busy_r -
//-------------------------------------------------
READ_LINE_MEMBER( msm58321_device::busy_r )
{
return m_busy;
}

140
src/emu/msm58321.h Normal file
View File

@ -0,0 +1,140 @@
/**********************************************************************
OKI MSM58321RS Real Time Clock/Calendar emulation
Copyright MESS Team.
Visit http://mamedev.org for licensing and usage restrictions.
**********************************************************************
_____ _____
CS2 1 |* \_/ | 16 Vdd
WRITE 2 | | 15 XT
READ 3 | | 14 _XT
D0 4 | MSM58321 | 13 CS1
D1 5 | RTC58321 | 12 TEST
D2 6 | | 11 STOP
D3 7 | | 10 _BUSY
GND 8 |_____________| 9 ADDRESS WRITE
**********************************************************************/
#pragma once
#ifndef __MSM58321__
#define __MSM58321__
#include "emu.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_MSM58321_ADD(_tag, _clock, _config) \
MCFG_DEVICE_ADD(_tag, MSM58321, _clock) \
MCFG_DEVICE_CONFIG(_config)
#define MSM58321_INTERFACE(name) \
const msm58321_interface (name) =
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> msm58321_interface
struct msm58321_interface
{
devcb_write_line m_out_busy_func;
};
// ======================> msm58321_device_config
class msm58321_device_config : public device_config,
public msm58321_interface
{
friend class msm58321_device;
// construction/destruction
msm58321_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
public:
// allocators
static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
virtual device_t *alloc_device(running_machine &machine) const;
protected:
// device_config overrides
virtual void device_config_complete();
};
// ======================> msm58321_device
class msm58321_device : public device_t
{
friend class msm58321_device_config;
// construction/destruction
msm58321_device(running_machine &_machine, const msm58321_device_config &_config);
public:
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
DECLARE_WRITE_LINE_MEMBER( cs1_w );
DECLARE_WRITE_LINE_MEMBER( cs2_w );
DECLARE_WRITE_LINE_MEMBER( read_w );
DECLARE_WRITE_LINE_MEMBER( write_w );
DECLARE_WRITE_LINE_MEMBER( address_write_w );
DECLARE_WRITE_LINE_MEMBER( stop_w );
DECLARE_WRITE_LINE_MEMBER( test_w );
DECLARE_READ_LINE_MEMBER( busy_r );
protected:
// device-level overrides
virtual void device_start();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
static const device_timer_id TIMER_CLOCK = 0;
static const device_timer_id TIMER_BUSY = 1;
inline int read_counter(int counter);
inline void write_counter(int counter, int value);
inline void advance_seconds();
inline void advance_minutes();
devcb_resolved_write_line m_out_busy_func;
int m_cs1; // chip select 1
int m_cs2; // chip select 2
int m_busy; // busy flag
int m_read; // read data
int m_write; // write data
int m_address_write; // write address
UINT8 m_reg[13]; // registers
UINT8 m_latch; // data latch (not present in real chip)
UINT8 m_address; // address latch
// timers
emu_timer *m_clock_timer;
emu_timer *m_busy_timer;
const msm58321_device_config &m_config;
};
// device type definition
extern const device_type MSM58321;
#endif