mirror of
https://github.com/holub/mame
synced 2025-05-05 22:04:43 +03:00
Added MCCS1850 RTC emulation. [Curt Coder]
This commit is contained in:
parent
41f86102e9
commit
83c16c9766
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -837,6 +837,8 @@ src/emu/machine/mc6852.c svneol=native#text/plain
|
|||||||
src/emu/machine/mc6852.h svneol=native#text/plain
|
src/emu/machine/mc6852.h svneol=native#text/plain
|
||||||
src/emu/machine/mc68901.c svneol=native#text/plain
|
src/emu/machine/mc68901.c svneol=native#text/plain
|
||||||
src/emu/machine/mc68901.h svneol=native#text/plain
|
src/emu/machine/mc68901.h svneol=native#text/plain
|
||||||
|
src/emu/machine/mccs1850.c svneol=native#text/plain
|
||||||
|
src/emu/machine/mccs1850.h svneol=native#text/plain
|
||||||
src/emu/machine/microtch.c svneol=native#text/plain
|
src/emu/machine/microtch.c svneol=native#text/plain
|
||||||
src/emu/machine/microtch.h svneol=native#text/plain
|
src/emu/machine/microtch.h svneol=native#text/plain
|
||||||
src/emu/machine/mm74c922.c svneol=native#text/plain
|
src/emu/machine/mm74c922.c svneol=native#text/plain
|
||||||
|
@ -194,6 +194,7 @@ EMUMACHINEOBJS = \
|
|||||||
$(EMUMACHINE)/mc146818.o \
|
$(EMUMACHINE)/mc146818.o \
|
||||||
$(EMUMACHINE)/mc6852.o \
|
$(EMUMACHINE)/mc6852.o \
|
||||||
$(EMUMACHINE)/mc68901.o \
|
$(EMUMACHINE)/mc68901.o \
|
||||||
|
$(EMUMACHINE)/mccs1850.o \
|
||||||
$(EMUMACHINE)/mm74c922.o \
|
$(EMUMACHINE)/mm74c922.o \
|
||||||
$(EMUMACHINE)/microtch.o \
|
$(EMUMACHINE)/microtch.o \
|
||||||
$(EMUMACHINE)/mos6529.o \
|
$(EMUMACHINE)/mos6529.o \
|
||||||
|
584
src/emu/machine/mccs1850.c
Normal file
584
src/emu/machine/mccs1850.c
Normal file
@ -0,0 +1,584 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
|
||||||
|
Motorola MCCS1850 Serial Real-Time Clock emulation
|
||||||
|
|
||||||
|
Copyright MESS Team.
|
||||||
|
Visit http://mamedev.org for licensing and usage restrictions.
|
||||||
|
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
|
||||||
|
- auto restart
|
||||||
|
- test mode
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mccs1850.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// MACROS / CONSTANTS
|
||||||
|
//**************************************************************************
|
||||||
|
|
||||||
|
#define LOG 0
|
||||||
|
|
||||||
|
|
||||||
|
#define RAM_SIZE 0x80
|
||||||
|
|
||||||
|
|
||||||
|
// serial state
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STATE_ADDRESS,
|
||||||
|
STATE_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// registers
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
REGISTER_COUNTER_LATCH = 0x20,
|
||||||
|
REGISTER_ALARM_LATCH = 0x24,
|
||||||
|
REGISTER_STATUS = 0x30,
|
||||||
|
REGISTER_CONTROL = 0x31,
|
||||||
|
REGISTER_TEST_1 = 0x3e,
|
||||||
|
REGISTER_TEST_2 = 0x3f,
|
||||||
|
REGISTER_TEST_KICK_START_COUNTER = 0x40,
|
||||||
|
REGISTER_TEST_PRESCALE_COUNTER = 0x43,
|
||||||
|
REGISTER_TEST_COUNTER_INCREMENT = 0x4f
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// clock status/interrupt register
|
||||||
|
#define STATUS_TM 0x20 // test mode
|
||||||
|
#define STATUS_FTU 0x10 // first time up
|
||||||
|
#define STATUS_IT 0x08 // interrupt true
|
||||||
|
#define STATUS_LB 0x04 // low battery
|
||||||
|
#define STATUS_AI 0x02 // alarm
|
||||||
|
#define STATUS_RPD 0x01 // request to power down
|
||||||
|
|
||||||
|
|
||||||
|
// clock control register
|
||||||
|
#define CONTROL_STR_STP 0x80 // start/stop
|
||||||
|
#define CONTROL_PD 0x40 // power down
|
||||||
|
#define CONTROL_AR 0x20 // auto restart
|
||||||
|
#define CONTROL_AE 0x10 // alarm enable
|
||||||
|
#define CONTROL_AC 0x08 // alarm clear
|
||||||
|
#define CONTROL_FTUC 0x04 // first time up clear
|
||||||
|
#define CONTROL_LBE 0x02 // low battery enable
|
||||||
|
#define CONTROL_RPCD 0x01 // request to power down clear
|
||||||
|
|
||||||
|
|
||||||
|
// test register 1
|
||||||
|
#define TEST1_DIV1 0x80 // divide by 1
|
||||||
|
#define TEST1_VOVR 0x40 // Vdd override
|
||||||
|
#define TEST1_VDDUP 0x20 // Vdd up
|
||||||
|
#define TEST1_VDDON 0x10 // Vdd on
|
||||||
|
#define TEST1_VRT 0x08 // valid RAM and time
|
||||||
|
#define TEST1_LOW_BAT 0x08 // low battery
|
||||||
|
#define TEST1_PCC 0x04 // programmable capacitor C (10.0 pF)
|
||||||
|
#define TEST1_PCB 0x02 // programmable capacitor B (5.0 pF)
|
||||||
|
#define TEST1_PCA 0x01 // programmable capacitor A (2.5 pF)
|
||||||
|
|
||||||
|
|
||||||
|
// test register 2
|
||||||
|
#define TEST2_OSCBY 0x80 // oscillator bypass
|
||||||
|
#define TEST2_COMPOVR 0x40 // comparator override
|
||||||
|
#define TEST2_POR 0x20 // power on reset
|
||||||
|
#define TEST2_SELTCK 0x10 // select test clock
|
||||||
|
#define TEST2_FRZ 0x08 // freeze mode
|
||||||
|
#define TEST2_DV_MASK 0x07 // divider bits select
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// GLOBAL VARIABLES
|
||||||
|
//**************************************************************************
|
||||||
|
|
||||||
|
// device type definition
|
||||||
|
const device_type MCCS1850 = &device_creator<mccs1850_device>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// INLINE HELPERS
|
||||||
|
//**************************************************************************
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// check_interrupt -
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
inline void mccs1850_device::check_interrupt()
|
||||||
|
{
|
||||||
|
UINT8 status = m_ram[REGISTER_STATUS];
|
||||||
|
UINT8 control = m_ram[REGISTER_CONTROL];
|
||||||
|
|
||||||
|
bool interrupt = (((status & STATUS_AI) && (control & CONTROL_AE)) // alarm interrupt
|
||||||
|
|| ((status & STATUS_LB) && (control & CONTROL_LBE)) // low battery
|
||||||
|
|| (status & STATUS_FTU) // first time up
|
||||||
|
|| (status & STATUS_RPD)); // request to power down
|
||||||
|
|
||||||
|
if (interrupt)
|
||||||
|
{
|
||||||
|
m_ram[REGISTER_STATUS] |= STATUS_IT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ram[REGISTER_STATUS] &= ~STATUS_IT;
|
||||||
|
}
|
||||||
|
|
||||||
|
devcb_call_write_line(&m_out_int_func, interrupt ? ASSERT_LINE : CLEAR_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// set_pse_line -
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
inline void mccs1850_device::set_pse_line(int state)
|
||||||
|
{
|
||||||
|
m_pse = state;
|
||||||
|
|
||||||
|
devcb_call_write_line(&m_out_pse_func, m_pse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// read_register -
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
inline UINT8 mccs1850_device::read_register(offs_t offset)
|
||||||
|
{
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case REGISTER_COUNTER_LATCH:
|
||||||
|
// load counter value into latch
|
||||||
|
m_ram[REGISTER_COUNTER_LATCH] = m_counter >> 24;
|
||||||
|
m_ram[REGISTER_COUNTER_LATCH + 1] = m_counter >> 16;
|
||||||
|
m_ram[REGISTER_COUNTER_LATCH + 2] = m_counter >> 8;
|
||||||
|
m_ram[REGISTER_COUNTER_LATCH + 3] = m_counter;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGISTER_TEST_1:
|
||||||
|
case REGISTER_TEST_2:
|
||||||
|
case REGISTER_TEST_KICK_START_COUNTER:
|
||||||
|
case REGISTER_TEST_PRESCALE_COUNTER:
|
||||||
|
case REGISTER_TEST_COUNTER_INCREMENT:
|
||||||
|
logerror("MCCS1850 '%s' Unsupported read from test register %02x!\n", tag(), offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_ram[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// write_register -
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
inline void mccs1850_device::write_register(offs_t offset, UINT8 data)
|
||||||
|
{
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case REGISTER_STATUS:
|
||||||
|
// read only
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGISTER_CONTROL:
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' Counter %s\n", tag(), (data & CONTROL_STR_STP) ? "Start" : "Stop");
|
||||||
|
m_clock_timer->enable(data & CONTROL_STR_STP);
|
||||||
|
|
||||||
|
if (data & CONTROL_PD)
|
||||||
|
{
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' Power Down\n", tag());
|
||||||
|
set_pse_line(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data & CONTROL_AR)
|
||||||
|
{
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' Auto Restart\n", tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data & CONTROL_AC)
|
||||||
|
{
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' Alarm Clear\n", tag());
|
||||||
|
m_ram[REGISTER_STATUS] &= ~STATUS_AI;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data & CONTROL_FTUC)
|
||||||
|
{
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' First Time Up Clear\n", tag());
|
||||||
|
m_ram[REGISTER_STATUS] &= ~STATUS_FTU;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data & CONTROL_RPCD)
|
||||||
|
{
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' Request to Power Down Clear\n", tag());
|
||||||
|
m_ram[REGISTER_STATUS] &= ~STATUS_RPD;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ram[REGISTER_CONTROL] = data & 0xb2;
|
||||||
|
|
||||||
|
check_interrupt();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGISTER_TEST_1:
|
||||||
|
case REGISTER_TEST_2:
|
||||||
|
case REGISTER_TEST_KICK_START_COUNTER:
|
||||||
|
case REGISTER_TEST_PRESCALE_COUNTER:
|
||||||
|
case REGISTER_TEST_COUNTER_INCREMENT:
|
||||||
|
logerror("MCCS1850 '%s' Unsupported write to test register %02x!\n", tag(), offset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
m_ram[offset] = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// advance_seconds -
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
inline void mccs1850_device::advance_seconds()
|
||||||
|
{
|
||||||
|
UINT32 alarm = (m_ram[REGISTER_ALARM_LATCH] << 24) | (m_ram[REGISTER_ALARM_LATCH + 1] << 16) | (m_ram[REGISTER_ALARM_LATCH + 2] << 8) | m_ram[REGISTER_ALARM_LATCH + 3];
|
||||||
|
|
||||||
|
m_counter++;
|
||||||
|
|
||||||
|
if (m_counter == alarm)
|
||||||
|
{
|
||||||
|
if (m_pse)
|
||||||
|
{
|
||||||
|
// trigger alarm
|
||||||
|
m_ram[REGISTER_STATUS] |= STATUS_AI;
|
||||||
|
|
||||||
|
check_interrupt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// wake up
|
||||||
|
set_pse_line(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// LIVE DEVICE
|
||||||
|
//**************************************************************************
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// mccs1850_device - constructor
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
mccs1850_device::mccs1850_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
|
: device_t(mconfig, MCCS1850, "MCCS1850", tag, owner, clock),
|
||||||
|
device_rtc_interface(mconfig, *this),
|
||||||
|
device_nvram_interface(mconfig, *this),
|
||||||
|
m_pse(1),
|
||||||
|
m_ce(0),
|
||||||
|
m_sck(0),
|
||||||
|
m_sdo(0),
|
||||||
|
m_sdi(0),
|
||||||
|
m_state(STATE_ADDRESS),
|
||||||
|
m_bits(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_config_complete - perform any
|
||||||
|
// operations now that the configuration is
|
||||||
|
// complete
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void mccs1850_device::device_config_complete()
|
||||||
|
{
|
||||||
|
// inherit a copy of the static data
|
||||||
|
const mccs1850_interface *intf = reinterpret_cast<const mccs1850_interface *>(static_config());
|
||||||
|
if (intf != NULL)
|
||||||
|
*static_cast<mccs1850_interface *>(this) = *intf;
|
||||||
|
|
||||||
|
// or initialize to defaults if none provided
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
|
||||||
|
memset(&m_out_pse_cb, 0, sizeof(m_out_pse_cb));
|
||||||
|
memset(&m_out_nuc_cb, 0, sizeof(m_out_nuc_cb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_start - device-specific startup
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void mccs1850_device::device_start()
|
||||||
|
{
|
||||||
|
// resolve callbacks
|
||||||
|
devcb_resolve_write_line(&m_out_int_func, &m_out_int_cb, this);
|
||||||
|
devcb_resolve_write_line(&m_out_pse_func, &m_out_pse_cb, this);
|
||||||
|
devcb_resolve_write_line(&m_out_nuc_func, &m_out_nuc_cb, 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));
|
||||||
|
|
||||||
|
// state saving
|
||||||
|
save_item(NAME(m_pse));
|
||||||
|
save_item(NAME(m_counter));
|
||||||
|
save_item(NAME(m_ce));
|
||||||
|
save_item(NAME(m_sck));
|
||||||
|
save_item(NAME(m_sdo));
|
||||||
|
save_item(NAME(m_sdi));
|
||||||
|
save_item(NAME(m_state));
|
||||||
|
save_item(NAME(m_address));
|
||||||
|
save_item(NAME(m_bits));
|
||||||
|
save_item(NAME(m_shift));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_reset - device-specific reset
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void mccs1850_device::device_reset()
|
||||||
|
{
|
||||||
|
memset(m_ram, 0xff, RAM_SIZE);
|
||||||
|
|
||||||
|
m_ram[REGISTER_STATUS] = 0x80 | STATUS_FTU;
|
||||||
|
m_ram[REGISTER_CONTROL] = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_timer - handler timer events
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void mccs1850_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case TIMER_CLOCK:
|
||||||
|
advance_seconds();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// rtc_set_time - called to initialize the RTC to
|
||||||
|
// a known state
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void mccs1850_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// nvram_default - called to initialize NVRAM to
|
||||||
|
// its default state
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void mccs1850_device::nvram_default()
|
||||||
|
{
|
||||||
|
memset(m_ram, 0xff, RAM_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// nvram_read - called to read NVRAM from the
|
||||||
|
// .nv file
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void mccs1850_device::nvram_read(emu_file &file)
|
||||||
|
{
|
||||||
|
file.read(m_ram, RAM_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// nvram_write - called to write NVRAM to the
|
||||||
|
// .nv file
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void mccs1850_device::nvram_write(emu_file &file)
|
||||||
|
{
|
||||||
|
file.write(m_ram, RAM_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// ce_w - chip enable write
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
WRITE_LINE_MEMBER( mccs1850_device::ce_w )
|
||||||
|
{
|
||||||
|
m_ce = state;
|
||||||
|
|
||||||
|
if (!m_ce)
|
||||||
|
{
|
||||||
|
m_state = STATE_ADDRESS;
|
||||||
|
m_bits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// sck_w - serial clock write
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
WRITE_LINE_MEMBER( mccs1850_device::sck_w )
|
||||||
|
{
|
||||||
|
if (!m_ce) return;
|
||||||
|
|
||||||
|
switch (m_state)
|
||||||
|
{
|
||||||
|
case STATE_ADDRESS:
|
||||||
|
if (m_sck && !state)
|
||||||
|
{
|
||||||
|
m_address <<= 1;
|
||||||
|
m_address |= m_sdi;
|
||||||
|
m_bits++;
|
||||||
|
|
||||||
|
if (m_bits == 8)
|
||||||
|
{
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' %s Address %u\n", tag(), BIT(m_address, 7) ? "Read" : "Write", m_address & 0x7f);
|
||||||
|
|
||||||
|
m_bits = 0;
|
||||||
|
m_state = STATE_DATA;
|
||||||
|
|
||||||
|
if (BIT(m_address, 7))
|
||||||
|
{
|
||||||
|
m_shift = read_register(m_address & 0x7f);
|
||||||
|
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' Data Out %02x\n", tag(), m_shift);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_DATA:
|
||||||
|
if (!BIT(m_address, 7) && m_sck && !state)
|
||||||
|
{
|
||||||
|
// shift data in
|
||||||
|
m_shift <<= 1;
|
||||||
|
m_shift |= m_sdi;
|
||||||
|
m_bits++;
|
||||||
|
|
||||||
|
if (m_bits == 8)
|
||||||
|
{
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' Data In %02x\n", tag(), m_shift);
|
||||||
|
|
||||||
|
write_register(m_address & 0x7f, m_shift);
|
||||||
|
|
||||||
|
m_bits = 0;
|
||||||
|
|
||||||
|
// increment address counter
|
||||||
|
m_address++;
|
||||||
|
m_address &= 0x7f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (BIT(m_address, 7) && !m_sck && state)
|
||||||
|
{
|
||||||
|
// shift data out
|
||||||
|
m_sdo = BIT(m_shift, 7);
|
||||||
|
m_shift <<= 1;
|
||||||
|
m_bits++;
|
||||||
|
|
||||||
|
if (m_bits == 8)
|
||||||
|
{
|
||||||
|
m_bits = 0;
|
||||||
|
|
||||||
|
// increment address counter
|
||||||
|
m_address++;
|
||||||
|
m_address &= 0x7f;
|
||||||
|
m_shift = read_register(m_address & 0x7f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sck = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// sdo_r - serial data out read
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
READ_LINE_MEMBER( mccs1850_device::sdo_r )
|
||||||
|
{
|
||||||
|
return m_sdo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// sdi_w - serial data in write
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
WRITE_LINE_MEMBER( mccs1850_device::sdi_w )
|
||||||
|
{
|
||||||
|
m_sdi = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// pwrsw_w - power switch write
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
WRITE_LINE_MEMBER( mccs1850_device::pwrsw_w )
|
||||||
|
{
|
||||||
|
if (!state)
|
||||||
|
{
|
||||||
|
if (m_pse)
|
||||||
|
{
|
||||||
|
// request to power down
|
||||||
|
m_ram[REGISTER_STATUS] |= STATUS_RPD;
|
||||||
|
check_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
set_pse_line(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// por_w - power on reset write
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
WRITE_LINE_MEMBER( mccs1850_device::por_w )
|
||||||
|
{
|
||||||
|
if (!state)
|
||||||
|
{
|
||||||
|
device_reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// test_w - test mode write
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
WRITE_LINE_MEMBER( mccs1850_device::test_w )
|
||||||
|
{
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' Test Mode\n", tag());
|
||||||
|
|
||||||
|
m_ram[REGISTER_STATUS] |= STATUS_TM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (LOG) logerror("MCCS1850 '%s' Normal Operation\n", tag());
|
||||||
|
|
||||||
|
m_ram[REGISTER_STATUS] &= ~STATUS_TM;
|
||||||
|
}
|
||||||
|
}
|
135
src/emu/machine/mccs1850.h
Normal file
135
src/emu/machine/mccs1850.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
|
||||||
|
Motorola MCCS1850 Serial Real-Time Clock emulation
|
||||||
|
|
||||||
|
Copyright MESS Team.
|
||||||
|
Visit http://mamedev.org for licensing and usage restrictions.
|
||||||
|
|
||||||
|
**********************************************************************
|
||||||
|
_____ _____
|
||||||
|
Vbat 1 |* \_/ | 16 Vdd
|
||||||
|
_POR 2 | | 15 TEST
|
||||||
|
_INT 3 | | 14 XTAL1
|
||||||
|
SCK 4 | MCCS1850 | 13 XTAL2
|
||||||
|
SDI 5 | | 12 _PWRSW
|
||||||
|
SDO 6 | | 11 NUC
|
||||||
|
CE 7 | | 10 _PSE
|
||||||
|
Vss 8 |_____________| 9 PSE
|
||||||
|
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __MCCS1850__
|
||||||
|
#define __MCCS1850__
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// INTERFACE CONFIGURATION MACROS
|
||||||
|
//**************************************************************************
|
||||||
|
|
||||||
|
#define MCFG_MCCS1850_ADD(_tag, _clock, _config) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, MCCS1850, _clock) \
|
||||||
|
MCFG_DEVICE_CONFIG(_config)
|
||||||
|
|
||||||
|
|
||||||
|
#define MCCS1850_INTERFACE(name) \
|
||||||
|
const mccs1850_interface (name) =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// TYPE DEFINITIONS
|
||||||
|
//**************************************************************************
|
||||||
|
|
||||||
|
// ======================> mccs1850_interface
|
||||||
|
|
||||||
|
struct mccs1850_interface
|
||||||
|
{
|
||||||
|
devcb_write_line m_out_int_cb;
|
||||||
|
devcb_write_line m_out_pse_cb;
|
||||||
|
devcb_write_line m_out_nuc_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ======================> mccs1850_device
|
||||||
|
|
||||||
|
class mccs1850_device : public device_t,
|
||||||
|
public device_rtc_interface,
|
||||||
|
public device_nvram_interface,
|
||||||
|
public mccs1850_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// construction/destruction
|
||||||
|
mccs1850_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
DECLARE_WRITE_LINE_MEMBER( ce_w );
|
||||||
|
DECLARE_WRITE_LINE_MEMBER( sck_w );
|
||||||
|
DECLARE_READ_LINE_MEMBER( sdo_r );
|
||||||
|
DECLARE_WRITE_LINE_MEMBER( sdi_w );
|
||||||
|
DECLARE_WRITE_LINE_MEMBER( pwrsw_w );
|
||||||
|
DECLARE_WRITE_LINE_MEMBER( por_w );
|
||||||
|
DECLARE_WRITE_LINE_MEMBER( test_w );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// device-level overrides
|
||||||
|
virtual void device_config_complete();
|
||||||
|
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_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
|
||||||
|
virtual bool rtc_is_year_2000_compliant() { return false; }
|
||||||
|
|
||||||
|
// device_nvram_interface overrides
|
||||||
|
virtual void nvram_default();
|
||||||
|
virtual void nvram_read(emu_file &file);
|
||||||
|
virtual void nvram_write(emu_file &file);
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline void check_interrupt();
|
||||||
|
inline void set_pse_line(int state);
|
||||||
|
inline UINT8 read_register(offs_t offset);
|
||||||
|
inline void write_register(offs_t offset, UINT8 data);
|
||||||
|
inline void advance_seconds();
|
||||||
|
|
||||||
|
static const device_timer_id TIMER_CLOCK = 0;
|
||||||
|
|
||||||
|
devcb_resolved_write_line m_out_int_func;
|
||||||
|
devcb_resolved_write_line m_out_pse_func;
|
||||||
|
devcb_resolved_write_line m_out_nuc_func;
|
||||||
|
|
||||||
|
UINT8 m_ram[0x80]; // RAM
|
||||||
|
|
||||||
|
// power supply
|
||||||
|
int m_pse; // power supply enable
|
||||||
|
|
||||||
|
// counter
|
||||||
|
UINT32 m_counter; // seconds counter
|
||||||
|
|
||||||
|
// serial interface
|
||||||
|
int m_ce; // chip enable
|
||||||
|
int m_sck; // serial clock
|
||||||
|
int m_sdo; // serial data out
|
||||||
|
int m_sdi; // serial data in
|
||||||
|
int m_state; // serial interface state
|
||||||
|
UINT8 m_address; // address counter
|
||||||
|
int m_bits; // bit counter
|
||||||
|
UINT8 m_shift; // shift register
|
||||||
|
|
||||||
|
// timers
|
||||||
|
emu_timer *m_clock_timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// device type definition
|
||||||
|
extern const device_type MCCS1850;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user