mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
Add support for Mitsubishi M50740/50741 MCUs. [R. Belmont]
This commit is contained in:
parent
6d6e25adaf
commit
3f85549053
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -564,6 +564,8 @@ src/emu/cpu/m6502/m3745x.c svneol=native#text/plain
|
||||
src/emu/cpu/m6502/m3745x.h svneol=native#text/plain
|
||||
src/emu/cpu/m6502/m4510.c svneol=native#text/plain
|
||||
src/emu/cpu/m6502/m4510.h svneol=native#text/plain
|
||||
src/emu/cpu/m6502/m5074x.c svneol=native#text/plain
|
||||
src/emu/cpu/m6502/m5074x.h svneol=native#text/plain
|
||||
src/emu/cpu/m6502/m6502.c svneol=native#text/plain
|
||||
src/emu/cpu/m6502/m6502.h svneol=native#text/plain
|
||||
src/emu/cpu/m6502/m6502.txt svneol=native#text/plain
|
||||
|
@ -1036,6 +1036,7 @@ CPUOBJS += $(CPUOBJ)/m6502/deco16.o \
|
||||
$(CPUOBJ)/m6502/r65c02.o \
|
||||
$(CPUOBJ)/m6502/m740.o \
|
||||
$(CPUOBJ)/m6502/m3745x.o \
|
||||
$(CPUOBJ)/m6502/m5074x.o \
|
||||
|
||||
DASMOBJS +=
|
||||
endif
|
||||
@ -1120,6 +1121,9 @@ $(CPUOBJ)/m6502/m740.o: $(CPUSRC)/m6502/m740.c \
|
||||
$(CPUOBJ)/m6502/m3745x.o: $(CPUSRC)/m6502/m3745x.c \
|
||||
$(CPUSRC)/m6502/m3745x.h
|
||||
|
||||
$(CPUOBJ)/m6502/m5074x.o: $(CPUSRC)/m6502/m5074x.c \
|
||||
$(CPUSRC)/m6502/m5074x.h
|
||||
|
||||
# rule to generate the C files
|
||||
$(CPUOBJ)/m6502/deco16.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst
|
||||
@echo Generating DECO16 source file...
|
||||
|
513
src/emu/cpu/m6502/m5074x.c
Normal file
513
src/emu/cpu/m6502/m5074x.c
Normal file
@ -0,0 +1,513 @@
|
||||
/*
|
||||
Mitsubishi M5074x 8-bit microcontroller family
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "m5074x.h"
|
||||
|
||||
//**************************************************************************
|
||||
// MACROS / CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
#define IRQ_CNTRREQ (0x80)
|
||||
#define IRQ_CNTRENA (0x40)
|
||||
#define IRQ_TMR1REQ (0x20)
|
||||
#define IRQ_TMR1ENA (0x10)
|
||||
#define IRQ_TMR2REQ (0x08)
|
||||
#define IRQ_TMR2ENA (0x04)
|
||||
#define IRQ_INTREQ (0x02)
|
||||
#define IRQ_INTENA (0x01)
|
||||
|
||||
#define TMRC_TMRXREQ (0x80)
|
||||
#define TMRC_TMRXENA (0x40)
|
||||
#define TMRC_TMRXHLT (0x20)
|
||||
#define TMRC_TMRXMDE (0x0c)
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
const device_type M50740 = &device_creator<m50740_device>;
|
||||
const device_type M50741 = &device_creator<m50741_device>;
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// m5074x_device - constructor
|
||||
//-------------------------------------------------
|
||||
m5074x_device::m5074x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor internal_map) :
|
||||
m740_device(mconfig, type, name, tag, owner, clock),
|
||||
m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, internal_map),
|
||||
read_p0(*this),
|
||||
read_p1(*this),
|
||||
read_p2(*this),
|
||||
read_p3(*this),
|
||||
write_p0(*this),
|
||||
write_p1(*this),
|
||||
write_p2(*this),
|
||||
write_p3(*this)
|
||||
{
|
||||
}
|
||||
|
||||
void m5074x_device::device_config_complete()
|
||||
{
|
||||
m_shortname = "m5074x";
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void m5074x_device::device_start()
|
||||
{
|
||||
read_p0.resolve_safe(0);
|
||||
read_p1.resolve_safe(0);
|
||||
read_p2.resolve_safe(0);
|
||||
read_p3.resolve_safe(0);
|
||||
write_p0.resolve_safe();
|
||||
write_p1.resolve_safe();
|
||||
write_p2.resolve_safe();
|
||||
write_p3.resolve_safe();
|
||||
|
||||
for (int i = 0; i < NUM_TIMERS; i++)
|
||||
{
|
||||
m_timers[i] = timer_alloc(i, NULL);
|
||||
}
|
||||
|
||||
m740_device::device_start();
|
||||
|
||||
save_item(NAME(m_ports));
|
||||
save_item(NAME(m_ddrs));
|
||||
save_item(NAME(m_intctrl));
|
||||
save_item(NAME(m_tmrctrl));
|
||||
save_item(NAME(m_tmr12pre));
|
||||
save_item(NAME(m_tmr1));
|
||||
save_item(NAME(m_tmr2));
|
||||
save_item(NAME(m_tmrxpre));
|
||||
save_item(NAME(m_tmrx));
|
||||
save_item(NAME(m_tmr1latch));
|
||||
save_item(NAME(m_tmr2latch));
|
||||
save_item(NAME(m_tmrxlatch));
|
||||
save_item(NAME(m_last_all_ints));
|
||||
|
||||
memset(m_ports, 0, sizeof(m_ports));
|
||||
memset(m_ddrs, 0, sizeof(m_ddrs));
|
||||
m_intctrl = m_tmrctrl = 0;
|
||||
m_tmr12pre = m_tmrxpre = 0;
|
||||
m_tmr1 = m_tmr2 = m_tmrx = 0;
|
||||
m_last_all_ints = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void m5074x_device::device_reset()
|
||||
{
|
||||
m740_device::device_reset();
|
||||
|
||||
// all ports reset to input on startup
|
||||
memset(m_ports, 0, sizeof(m_ports));
|
||||
memset(m_ddrs, 0, sizeof(m_ddrs));
|
||||
m_intctrl = m_tmrctrl = 0;
|
||||
m_tmr12pre = m_tmrxpre = 0;
|
||||
m_tmr1 = m_tmr2 = m_tmrx = 0;
|
||||
}
|
||||
|
||||
void m5074x_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_1:
|
||||
m_tmr1--;
|
||||
|
||||
if (m_tmr1 <= 0)
|
||||
{
|
||||
m_intctrl |= IRQ_TMR1REQ;
|
||||
m_tmr1 = m_tmr1latch;
|
||||
recalc_irqs();
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMER_2:
|
||||
m_tmr2--;
|
||||
|
||||
if (m_tmr2 <= 0)
|
||||
{
|
||||
m_intctrl |= IRQ_TMR2REQ;
|
||||
m_tmr2 = m_tmr2latch;
|
||||
recalc_irqs();
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMER_X:
|
||||
m_tmrx--;
|
||||
|
||||
if (m_tmrx <= 0)
|
||||
{
|
||||
m_tmrctrl |= TMRC_TMRXREQ;
|
||||
m_tmrx = m_tmrxlatch;
|
||||
recalc_irqs();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void m5074x_device::execute_set_input(int inputnum, int state)
|
||||
{
|
||||
switch (inputnum)
|
||||
{
|
||||
case M5074X_INT1_LINE:
|
||||
if (state == ASSERT_LINE)
|
||||
{
|
||||
m_intctrl |= IRQ_INTREQ;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_intctrl &= ~IRQ_INTREQ;
|
||||
}
|
||||
break;
|
||||
|
||||
case M5074X_SET_OVERFLOW: // the base 740 class can handle this
|
||||
m740_device::execute_set_input(M740_SET_OVERFLOW, state);
|
||||
break;
|
||||
}
|
||||
|
||||
recalc_irqs();
|
||||
}
|
||||
|
||||
void m5074x_device::recalc_irqs()
|
||||
{
|
||||
UINT8 all_ints = 0;
|
||||
|
||||
if ((m_intctrl & (IRQ_CNTRREQ|IRQ_CNTRENA)) == (IRQ_CNTRREQ|IRQ_CNTRENA))
|
||||
{
|
||||
all_ints |= 0x01;
|
||||
}
|
||||
if ((m_tmrctrl & (TMRC_TMRXREQ|TMRC_TMRXENA)) == (TMRC_TMRXREQ|TMRC_TMRXENA))
|
||||
{
|
||||
all_ints |= 0x02;
|
||||
}
|
||||
if ((m_intctrl & (IRQ_TMR1REQ|IRQ_TMR1ENA)) == (IRQ_TMR1REQ|IRQ_TMR1ENA))
|
||||
{
|
||||
all_ints |= 0x04;
|
||||
}
|
||||
if ((m_intctrl & (IRQ_TMR2REQ|IRQ_TMR2ENA)) == (IRQ_TMR2REQ|IRQ_TMR2ENA))
|
||||
{
|
||||
all_ints |= 0x08;
|
||||
}
|
||||
if ((m_intctrl & (IRQ_INTREQ|IRQ_INTENA)) == (IRQ_INTREQ|IRQ_INTENA))
|
||||
{
|
||||
all_ints |= 0x10;
|
||||
}
|
||||
|
||||
// check all 6 IRQ bits for changes
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
// if bit is set now
|
||||
if (all_ints & (1 << i))
|
||||
{
|
||||
// and wasn't last time
|
||||
if (!(m_last_all_ints & (1 << i)))
|
||||
{
|
||||
m740_device::execute_set_input(M740_INT0_LINE + i, ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
else // bit is clear now
|
||||
{
|
||||
// ...and wasn't clear last time
|
||||
if (m_last_all_ints & (1 << i))
|
||||
{
|
||||
m740_device::execute_set_input(M740_INT0_LINE + i, CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_last_all_ints = all_ints;
|
||||
}
|
||||
|
||||
void m5074x_device::recalc_timer(int timer)
|
||||
{
|
||||
int hz;
|
||||
|
||||
switch (timer)
|
||||
{
|
||||
case 0:
|
||||
hz = clock() / 16;
|
||||
hz /= (m_tmr12pre + 2);
|
||||
m_timers[TIMER_1]->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
hz = clock() / 16;
|
||||
hz /= (m_tmr12pre + 2);
|
||||
m_timers[TIMER_2]->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Timer X modes: 00 = free run countdown, 01 = invert CNTR pin each time expires,
|
||||
// 10 = count each time CNTR pin inverts, 11 = count when CNTR pin low
|
||||
if ((m_tmrctrl & TMRC_TMRXMDE) == 0)
|
||||
{
|
||||
// stop bit?
|
||||
if (m_tmrctrl & TMRC_TMRXHLT)
|
||||
{
|
||||
m_timers[TIMER_X]->adjust(attotime::never, 0, attotime::never);
|
||||
}
|
||||
else
|
||||
{
|
||||
hz = clock() / 16;
|
||||
hz /= (m_tmrxpre + 2);
|
||||
m_timers[TIMER_X]->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalerror("M5074x: Unhandled timer X mode %d\n", (m_tmrctrl&TMRC_TMRXMDE)>>2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void m5074x_device::send_port(address_space &space, UINT8 offset, UINT8 data)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
write_p0(data);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
write_p1(data);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
write_p2(data);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
write_p3(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 m5074x_device::read_port(UINT8 offset)
|
||||
{
|
||||
UINT8 incoming = 0;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
incoming = read_p0();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
incoming = read_p1();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
incoming = read_p2();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
incoming = read_p3();
|
||||
break;
|
||||
}
|
||||
|
||||
// apply data direction registers
|
||||
incoming &= (m_ddrs[offset] ^ 0xff);
|
||||
// OR in ddr-masked version of port writes
|
||||
incoming |= (m_ports[offset] & m_ddrs[offset]);
|
||||
|
||||
return incoming;
|
||||
}
|
||||
|
||||
READ8_MEMBER(m5074x_device::ports_r)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
return read_port(0);
|
||||
|
||||
case 1:
|
||||
return m_ddrs[0];
|
||||
|
||||
case 2:
|
||||
return read_port(1);
|
||||
|
||||
case 3:
|
||||
return m_ddrs[1];
|
||||
|
||||
case 4:
|
||||
return read_port(2);
|
||||
|
||||
case 5:
|
||||
return m_ddrs[2];
|
||||
|
||||
case 8:
|
||||
return read_port(3);
|
||||
|
||||
case 9:
|
||||
return m_ddrs[3];
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m5074x_device::ports_w)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // p0
|
||||
send_port(space, 0, data & m_ddrs[0]);
|
||||
m_ports[0] = data;
|
||||
break;
|
||||
|
||||
case 1: // p0 ddr
|
||||
send_port(space, 0, m_ports[0] & data);
|
||||
m_ddrs[0] = data;
|
||||
break;
|
||||
|
||||
case 2: // p1
|
||||
send_port(space, 1, data & m_ddrs[1]);
|
||||
m_ports[1] = data;
|
||||
break;
|
||||
|
||||
case 3: // p1 ddr
|
||||
send_port(space, 1, m_ports[1] & data);
|
||||
m_ddrs[1] = data;
|
||||
break;
|
||||
|
||||
case 4: // p2
|
||||
send_port(space, 2, data & m_ddrs[2]);
|
||||
m_ports[2] = data;
|
||||
break;
|
||||
|
||||
case 5: // p2 ddr
|
||||
send_port(space, 2, m_ports[2] & data);
|
||||
m_ddrs[2] = data;
|
||||
break;
|
||||
|
||||
case 8: // p3
|
||||
send_port(space, 3, data & m_ddrs[3]);
|
||||
m_ports[3] = data;
|
||||
break;
|
||||
|
||||
case 9: // p3 ddr
|
||||
send_port(space, 3, m_ports[3] & data);
|
||||
m_ddrs[3] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(m5074x_device::tmrirq_r)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
return m_tmr12pre;
|
||||
|
||||
case 1:
|
||||
return m_tmr1;
|
||||
|
||||
case 2:
|
||||
return m_tmr2;
|
||||
|
||||
case 3:
|
||||
return m_tmrxpre;
|
||||
|
||||
case 4:
|
||||
return m_tmrx;
|
||||
|
||||
case 5:
|
||||
return m_intctrl;
|
||||
|
||||
case 6:
|
||||
return m_tmrctrl;
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m5074x_device::tmrirq_w)
|
||||
{
|
||||
// printf("%02x to tmrirq @ %d\n", data, offset);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
m_tmr12pre = data;
|
||||
recalc_timer(0);
|
||||
recalc_timer(1);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_tmr1 = m_tmr1latch = data;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_tmr2 = m_tmr2latch = data;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_tmrxpre = m_tmrxlatch = data;
|
||||
recalc_timer(2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_tmrx = data;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
m_intctrl = data;
|
||||
recalc_irqs();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
m_tmrctrl = data;
|
||||
recalc_irqs();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* M50740 - baseline for this familiy */
|
||||
static ADDRESS_MAP_START( m50740_map, AS_PROGRAM, 8, m50740_device )
|
||||
ADDRESS_MAP_GLOBAL_MASK(0x1fff)
|
||||
AM_RANGE(0x0000, 0x005f) AM_RAM
|
||||
AM_RANGE(0x00e0, 0x00e9) AM_READWRITE(ports_r, ports_w)
|
||||
AM_RANGE(0x00f9, 0x00ff) AM_READWRITE(tmrirq_r, tmrirq_w)
|
||||
AM_RANGE(0x1400, 0x1fff) AM_ROM AM_REGION(":m50740", 0)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
m50740_device::m50740_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
m5074x_device(mconfig, M50740, "Mitsubishi M50740", tag, owner, clock, ADDRESS_MAP_NAME(m50740_map))
|
||||
{
|
||||
}
|
||||
|
||||
m50740_device::m50740_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
|
||||
m5074x_device(mconfig, type, name, tag, owner, clock, ADDRESS_MAP_NAME(m50740_map))
|
||||
{
|
||||
}
|
||||
|
||||
/* M50741 - 50740 with a larger internal ROM */
|
||||
static ADDRESS_MAP_START( m50741_map, AS_PROGRAM, 8, m50741_device )
|
||||
ADDRESS_MAP_GLOBAL_MASK(0x1fff)
|
||||
AM_RANGE(0x0000, 0x005f) AM_RAM
|
||||
AM_RANGE(0x00e0, 0x00e9) AM_READWRITE(ports_r, ports_w)
|
||||
AM_RANGE(0x00f9, 0x00ff) AM_READWRITE(tmrirq_r, tmrirq_w)
|
||||
AM_RANGE(0x1000, 0x1fff) AM_ROM AM_REGION(":m50741", 0)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
m50741_device::m50741_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
m5074x_device(mconfig, M50740, "Mitsubishi M50741", tag, owner, clock, ADDRESS_MAP_NAME(m50741_map))
|
||||
{
|
||||
}
|
||||
|
||||
m50741_device::m50741_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
|
||||
m5074x_device(mconfig, type, name, tag, owner, clock, ADDRESS_MAP_NAME(m50741_map))
|
||||
{
|
||||
}
|
||||
|
141
src/emu/cpu/m6502/m5074x.h
Normal file
141
src/emu/cpu/m6502/m5074x.h
Normal file
@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __M5074X_H__
|
||||
#define __M5074X_H__
|
||||
|
||||
#include "m740.h"
|
||||
|
||||
//**************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_M5074X_PORT0_CALLBACKS(_read, _write) \
|
||||
downcast<m5074x_device *>(device)->set_p0_callbacks(DEVCB2_##_read, DEVCB2_##_write);
|
||||
|
||||
#define MCFG_M5074X_PORT1_CALLBACKS(_read, _write) \
|
||||
downcast<m5074x_device *>(device)->set_p1_callbacks(DEVCB2_##_read, DEVCB2_##_write);
|
||||
|
||||
#define MCFG_M5074X_PORT2_CALLBACKS(_read, _write) \
|
||||
downcast<m5074x_device *>(device)->set_p2_callbacks(DEVCB2_##_read, DEVCB2_##_write);
|
||||
|
||||
#define MCFG_M5074X_PORT3_CALLBACKS(_read, _write) \
|
||||
downcast<m5074x_device *>(device)->set_p3_callbacks(DEVCB2_##_read, DEVCB2_##_write);
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> m5074x_device
|
||||
|
||||
class m5074x_device : public m740_device
|
||||
{
|
||||
friend class m50740_device;
|
||||
friend class m50741_device;
|
||||
|
||||
enum
|
||||
{
|
||||
M5074X_INT1_LINE = INPUT_LINE_IRQ0,
|
||||
|
||||
M5074X_SET_OVERFLOW = M740_SET_OVERFLOW
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_1 = 0,
|
||||
TIMER_2,
|
||||
TIMER_X,
|
||||
|
||||
NUM_TIMERS
|
||||
};
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
m5074x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor internal_map);
|
||||
|
||||
const address_space_config m_program_config;
|
||||
|
||||
template<class _read, class _write> void set_p0_callbacks(_read rd, _write wr)
|
||||
{
|
||||
read_p0.set_callback(rd);
|
||||
write_p0.set_callback(wr);
|
||||
}
|
||||
|
||||
template<class _read, class _write> void set_p1_callbacks(_read rd, _write wr)
|
||||
{
|
||||
read_p1.set_callback(rd);
|
||||
write_p1.set_callback(wr);
|
||||
}
|
||||
|
||||
template<class _read, class _write> void set_p2_callbacks(_read rd, _write wr)
|
||||
{
|
||||
read_p2.set_callback(rd);
|
||||
write_p2.set_callback(wr);
|
||||
}
|
||||
|
||||
template<class _read, class _write> void set_p3_callbacks(_read rd, _write wr)
|
||||
{
|
||||
read_p3.set_callback(rd);
|
||||
write_p3.set_callback(wr);
|
||||
}
|
||||
|
||||
devcb2_read8 read_p0, read_p1, read_p2, read_p3;
|
||||
devcb2_write8 write_p0, write_p1, write_p2, write_p3;
|
||||
|
||||
DECLARE_READ8_MEMBER(ports_r);
|
||||
DECLARE_WRITE8_MEMBER(ports_w);
|
||||
DECLARE_READ8_MEMBER(tmrirq_r);
|
||||
DECLARE_WRITE8_MEMBER(tmrirq_w);
|
||||
|
||||
bool are_port_bits_output(UINT8 port, UINT8 mask) { return ((m_ddrs[port] & mask) == mask) ? true : false; }
|
||||
|
||||
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);
|
||||
virtual void device_config_complete();
|
||||
virtual void execute_set_input(int inputnum, int state);
|
||||
virtual const address_space_config *memory_space_config(address_spacenum spacenum) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
|
||||
|
||||
void send_port(address_space &space, UINT8 offset, UINT8 data);
|
||||
UINT8 read_port(UINT8 offset);
|
||||
|
||||
void recalc_irqs();
|
||||
void recalc_timer(int timer);
|
||||
|
||||
UINT8 m_ports[6], m_ddrs[6];
|
||||
UINT8 m_intctrl, m_tmrctrl;
|
||||
UINT8 m_tmr12pre, m_tmr1, m_tmr2, m_tmrxpre, m_tmrx;
|
||||
UINT8 m_tmr1latch, m_tmr2latch, m_tmrxlatch;
|
||||
UINT8 m_last_all_ints;
|
||||
|
||||
private:
|
||||
emu_timer *m_timers[NUM_TIMERS];
|
||||
};
|
||||
|
||||
class m50740_device : public m5074x_device
|
||||
{
|
||||
public:
|
||||
m50740_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
m50740_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class m50741_device : public m5074x_device
|
||||
{
|
||||
public:
|
||||
m50741_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
m50741_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
extern const device_type M50740;
|
||||
extern const device_type M50741;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user