mirror of
https://github.com/holub/mame
synced 2025-04-16 05:24:54 +03:00
Z180 ASCI (#9762)
New working machines ----------------------------------- Micromint SB180 [Miodrag Milanovic] -z180: implemented ASCI serial communication [Miodrag Milanovic] -tim011: hookup serial keyboard [Miodrag Milanovic] -20pacgal: Add support for terminal
This commit is contained in:
parent
4a587fd7c1
commit
b26c4ed848
@ -2789,6 +2789,8 @@ if CPUS["Z180"] then
|
||||
MAME_DIR .. "src/devices/cpu/z180/z180ops.h",
|
||||
MAME_DIR .. "src/devices/cpu/z180/z180tbl.h",
|
||||
MAME_DIR .. "src/devices/cpu/z180/z180xy.hxx",
|
||||
MAME_DIR .. "src/devices/cpu/z180/z180asci.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/z180/z180asci.h",
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -4763,6 +4763,7 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/rvoice.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/sacstate.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/sartorius.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/sb180.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/sb8085.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/sbrain.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/seattlecmp.cpp",
|
||||
|
@ -93,16 +93,12 @@ z180_device::z180_device(const machine_config &mconfig, device_type type, const
|
||||
, m_program_config("program", ENDIANNESS_LITTLE, 8, 20, 0, 16, 12, internal_map)
|
||||
, m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0)
|
||||
, m_decrypted_opcodes_config("opcodes", ENDIANNESS_LITTLE, 8, 20, 0, 16, 12, internal_map)
|
||||
, m_asci(*this, "asci_%u", 0U)
|
||||
, m_extended_io(extended_io)
|
||||
, m_tend0_cb(*this)
|
||||
, m_tend1_cb(*this)
|
||||
{
|
||||
// some arbitrary initial values
|
||||
m_asci_cntla[0] = m_asci_cntla[1] = 0;
|
||||
m_asci_cntlb[0] = m_asci_cntlb[1] = 0;
|
||||
m_asci_stat[0] = 0;
|
||||
m_asci_tdr[0] = m_asci_tdr[1] = 0;
|
||||
m_asci_rdr[0] = m_asci_rdr[1] = 0;
|
||||
m_csio_trdr = 0;
|
||||
m_tmdr[0].w = m_tmdr[1].w = 0;
|
||||
m_rldr[0].w = m_rldr[1].w = 0xffff;
|
||||
@ -133,8 +129,6 @@ hd64180rp_device::hd64180rp_device(const machine_config &mconfig, const char *ta
|
||||
z8s180_device::z8s180_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: z180_device(mconfig, type, tag, owner, clock, false, address_map_constructor())
|
||||
{
|
||||
// some arbitrary initial values
|
||||
m_asci_tc[0].w = m_asci_tc[1].w = 0;
|
||||
}
|
||||
|
||||
z8s180_device::z8s180_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
@ -242,60 +236,6 @@ bool z180_device::get_tend1()
|
||||
#define _LY m_IY.b.l
|
||||
|
||||
|
||||
/* 00 ASCI control register A ch 0 */
|
||||
#define Z180_CNTLA0_MPE 0x80
|
||||
#define Z180_CNTLA0_RE 0x40
|
||||
#define Z180_CNTLA0_TE 0x20
|
||||
#define Z180_CNTLA0_RTS0 0x10
|
||||
#define Z180_CNTLA0_MPBR_EFR 0x08
|
||||
#define Z180_CNTLA0_MODE_DATA 0x04
|
||||
#define Z180_CNTLA0_MODE_PARITY 0x02
|
||||
#define Z180_CNTLA0_MODE_STOPB 0x01
|
||||
|
||||
/* 01 ASCI control register A ch 1 */
|
||||
#define Z180_CNTLA1_MPE 0x80
|
||||
#define Z180_CNTLA1_RE 0x40
|
||||
#define Z180_CNTLA1_TE 0x20
|
||||
#define Z180_CNTLA1_CKA1D 0x10
|
||||
#define Z180_CNTLA1_MPBR_EFR 0x08
|
||||
#define Z180_CNTLA1_MODE 0x07
|
||||
|
||||
/* 02 ASCI control register B ch 0 */
|
||||
#define Z180_CNTLB0_MPBT 0x80
|
||||
#define Z180_CNTLB0_MP 0x40
|
||||
#define Z180_CNTLB0_CTS_PS 0x20
|
||||
#define Z180_CNTLB0_PEO 0x10
|
||||
#define Z180_CNTLB0_DR 0x08
|
||||
#define Z180_CNTLB0_SS 0x07
|
||||
|
||||
/* 03 ASCI control register B ch 1 */
|
||||
#define Z180_CNTLB1_MPBT 0x80
|
||||
#define Z180_CNTLB1_MP 0x40
|
||||
#define Z180_CNTLB1_CTS_PS 0x20
|
||||
#define Z180_CNTLB1_PEO 0x10
|
||||
#define Z180_CNTLB1_DR 0x08
|
||||
#define Z180_CNTLB1_SS 0x07
|
||||
|
||||
/* 04 ASCI status register 0 (all bits read-only except RIE and TIE) */
|
||||
#define Z180_STAT0_RDRF 0x80
|
||||
#define Z180_STAT0_OVRN 0x40
|
||||
#define Z180_STAT0_PE 0x20
|
||||
#define Z180_STAT0_FE 0x10
|
||||
#define Z180_STAT0_RIE 0x08
|
||||
#define Z180_STAT0_DCD0 0x04
|
||||
#define Z180_STAT0_TDRE 0x02
|
||||
#define Z180_STAT0_TIE 0x01
|
||||
|
||||
/* 05 ASCI status register 1 (all bits read-only except RIE, CTS1E and TIE) */
|
||||
#define Z180_STAT1_RDRF 0x80
|
||||
#define Z180_STAT1_OVRN 0x40
|
||||
#define Z180_STAT1_PE 0x20
|
||||
#define Z180_STAT1_FE 0x10
|
||||
#define Z180_STAT1_RIE 0x08
|
||||
#define Z180_STAT1_CTS1E 0x04
|
||||
#define Z180_STAT1_TDRE 0x02
|
||||
#define Z180_STAT1_TIE 0x01
|
||||
|
||||
/* 0a CSI/O control/status register (EF is read-only) */
|
||||
#define Z180_CNTR_EF 0x80
|
||||
#define Z180_CNTR_EIE 0x40
|
||||
@ -315,26 +255,6 @@ bool z180_device::get_tend1()
|
||||
#define Z180_TCR_TDE1 0x02
|
||||
#define Z180_TCR_TDE0 0x01
|
||||
|
||||
/* 12 (Z8S180/Z8L180) ASCI extension control register 0 (break detect is read-only) */
|
||||
#define Z180_ASEXT0_DCD0 0x40
|
||||
#define Z180_ASEXT0_CTS0 0x20
|
||||
#define Z180_ASEXT0_X1_BIT_CLK0 0x10
|
||||
#define Z180_ASEXT0_BRG0_MODE 0x08
|
||||
#define Z180_ASEXT0_BRK_EN 0x04
|
||||
#define Z180_ASEXT0_BRK_DET 0x02
|
||||
#define Z180_ASEXT0_BRK_SEND 0x01
|
||||
|
||||
#define Z180_ASEXT0_MASK 0x7f
|
||||
|
||||
/* 13 (Z8S180/Z8L180) ASCI extension control register 1 (break detect is read-only) */
|
||||
#define Z180_ASEXT1_X1_BIT_CLK1 0x10
|
||||
#define Z180_ASEXT1_BRG1_MODE 0x08
|
||||
#define Z180_ASEXT1_BRK_EN 0x04
|
||||
#define Z180_ASEXT1_BRK_DET 0x02
|
||||
#define Z180_ASEXT1_BRK_SEND 0x01
|
||||
|
||||
#define Z180_ASEXT1_MASK 0x1f
|
||||
|
||||
/* 1e (Z8S180/Z8L180) clock multiplier */
|
||||
#define Z180_CMR_X2 0x80
|
||||
#define Z180_CMR_LOW_NOISE 0x40
|
||||
@ -505,54 +425,28 @@ uint8_t z180_device::z180_internal_port_read(uint8_t port)
|
||||
switch (port)
|
||||
{
|
||||
case 0x00:
|
||||
data = m_asci_cntla[0];
|
||||
LOG("Z180 CNTLA0 rd $%02x\n", data);
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
data = m_asci_cntla[1];
|
||||
LOG("Z180 CNTLA1 rd $%02x\n", data);
|
||||
data = m_asci[port & 1]->cntla_r();
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
data = m_asci_cntlb[0];
|
||||
LOG("Z180 CNTLB0 rd $%02x\n", data);
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
data = m_asci_cntlb[1];
|
||||
LOG("Z180 CNTLB1 rd $%02x\n", data);
|
||||
data = m_asci[port & 1]->cntlb_r();
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
data = m_asci_stat[0];
|
||||
data |= 0x02; // kludge for 20pacgal
|
||||
LOG("Z180 STAT0 rd $%02x\n", data);
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
data = m_asci_stat[1];
|
||||
LOG("Z180 STAT1 rd $%02x\n", data);
|
||||
data = m_asci[port & 1]->stat_r();
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
data = m_asci_tdr[0];
|
||||
LOG("Z180 TDR0 rd $%02x\n", data);
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
data = m_asci_tdr[1];
|
||||
LOG("Z180 TDR1 rd $%02x\n", data);
|
||||
data = m_asci[port & 1]->tdr_r();
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
data = m_asci_rdr[0];
|
||||
LOG("Z180 RDR0 rd $%02x\n", data);
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
data = m_asci_rdr[1];
|
||||
LOG("Z180 RDR1 rd $%02x\n", data);
|
||||
data = m_asci[port & 1]->rdr_r();
|
||||
break;
|
||||
|
||||
case 0x0a:
|
||||
@ -869,53 +763,28 @@ void z180_device::z180_internal_port_write(uint8_t port, uint8_t data)
|
||||
switch (port)
|
||||
{
|
||||
case 0x00:
|
||||
LOG("Z180 CNTLA0 wr $%02x\n", data);
|
||||
m_asci_cntla[0] = data;
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
LOG("Z180 CNTLA1 wr $%02x\n", data);
|
||||
m_asci_cntla[1] = data;
|
||||
m_asci[port & 1]->cntla_w(data);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
LOG("Z180 CNTLB0 wr $%02x\n", data);
|
||||
m_asci_cntlb[0] = data;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
LOG("Z180 CNTLB1 wr $%02x\n", data);
|
||||
m_asci_cntlb[1] = data;
|
||||
m_asci[port & 1]->cntlb_w(data);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
LOG("Z180 STAT0 wr $%02x ($%02x)\n", data, data & (Z180_STAT0_RIE | Z180_STAT0_TIE));
|
||||
m_asci_stat[0] = (m_asci_stat[0] & ~(Z180_STAT0_RIE | Z180_STAT0_TIE)) | (data & (Z180_STAT0_RIE | Z180_STAT0_TIE));
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
LOG("Z180 STAT1 wr $%02x ($%02x)\n", data, data & (Z180_STAT1_RIE | Z180_STAT1_CTS1E | Z180_STAT1_TIE));
|
||||
m_asci_stat[1] = (m_asci_stat[1] & ~(Z180_STAT1_RIE | Z180_STAT1_CTS1E | Z180_STAT1_TIE)) | (data & (Z180_STAT1_RIE | Z180_STAT1_CTS1E | Z180_STAT1_TIE));
|
||||
m_asci[port & 1]->stat_w(data);
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
LOG("Z180 TDR0 wr $%02x\n", data);
|
||||
m_asci_tdr[0] = data;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
LOG("Z180 TDR1 wr $%02x\n", data);
|
||||
m_asci_tdr[1] = data;
|
||||
m_asci[port & 1]->tdr_w(data);
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
LOG("Z180 RDR0 wr $%02x\n", data);
|
||||
m_asci_rdr[0] = data;
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
LOG("Z180 RDR1 wr $%02x\n", data);
|
||||
m_asci_rdr[1] = data;
|
||||
m_asci[port & 1]->rdr_w(data);
|
||||
break;
|
||||
|
||||
case 0x0a:
|
||||
@ -1152,33 +1021,18 @@ uint8_t z8s180_device::z180_internal_port_read(uint8_t port)
|
||||
switch (port)
|
||||
{
|
||||
case 0x12:
|
||||
data = m_asci_ext[0];
|
||||
LOG("Z180 ASEXT0 rd $%02x ($%02x)\n", data, m_asci_ext[0]);
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
data = m_asci_ext[1];
|
||||
LOG("Z180 ASEXT1 rd $%02x ($%02x)\n", data, m_asci_ext[1]);
|
||||
data = m_asci[port & 1]->asext_r();
|
||||
break;
|
||||
|
||||
case 0x1a:
|
||||
LOG("Z180 ASTC0L wr $%02x\n", data);
|
||||
m_asci_tc[0].b.l = data;
|
||||
break;
|
||||
|
||||
case 0x1b:
|
||||
LOG("Z180 ASTC0H wr $%02x\n", data);
|
||||
m_asci_tc[0].b.h = data;
|
||||
data = m_asci[port & 1]->astcl_r();
|
||||
break;
|
||||
|
||||
case 0x1c:
|
||||
LOG("Z180 ASTC1L wr $%02x\n", data);
|
||||
m_asci_tc[1].b.l = data;
|
||||
break;
|
||||
|
||||
case 0x1d:
|
||||
LOG("Z180 ASTC1H wr $%02x\n", data);
|
||||
m_asci_tc[1].b.h = data;
|
||||
data = m_asci[port & 1]->astcl_r();
|
||||
break;
|
||||
|
||||
case 0x1e:
|
||||
@ -1204,33 +1058,18 @@ void z8s180_device::z180_internal_port_write(uint8_t port, uint8_t data)
|
||||
switch (port)
|
||||
{
|
||||
case 0x12:
|
||||
LOG("Z180 ASEXT0 wr $%02x ($%02x)\n", data, data & Z180_ASEXT0_MASK & ~Z180_ASEXT0_BRK_DET);
|
||||
m_asci_ext[0] = (m_asci_ext[0] & Z180_ASEXT0_BRK_DET) | (data & Z180_ASEXT0_MASK & ~Z180_ASEXT0_BRK_DET);
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
LOG("Z180 ASEXT1 wr $%02x ($%02x)\n", data, data & Z180_ASEXT1_MASK & ~Z180_ASEXT1_BRK_DET);
|
||||
m_asci_ext[1] = (m_asci_ext[1] & Z180_ASEXT1_BRK_DET) | (data & Z180_ASEXT1_MASK & ~Z180_ASEXT1_BRK_DET);
|
||||
m_asci[port & 1]->asext_w(data);
|
||||
break;
|
||||
|
||||
case 0x1a:
|
||||
data = m_asci_tc[0].b.l;
|
||||
LOG("Z180 ASTC0L rd $%02x ($%04x)\n", data, m_asci_tc[0].w);
|
||||
break;
|
||||
|
||||
case 0x1b:
|
||||
data = m_asci_tc[0].b.h;
|
||||
LOG("Z180 ASTC0H rd $%02x ($%04x)\n", data, m_asci_tc[0].w);
|
||||
m_asci[port & 1]->astcl_w(data);
|
||||
break;
|
||||
|
||||
case 0x1c:
|
||||
data = m_asci_tc[1].b.l;
|
||||
LOG("Z180 ASTC1L rd $%02x ($%04x)\n", data, m_asci_tc[1].w);
|
||||
break;
|
||||
|
||||
case 0x1d:
|
||||
data = m_asci_tc[1].b.h;
|
||||
LOG("Z180 ASTC1H rd $%02x ($%04x)\n", data, m_asci_tc[1].w);
|
||||
m_asci[port & 1]->astch_w(data);
|
||||
break;
|
||||
|
||||
case 0x1e:
|
||||
@ -1725,18 +1564,8 @@ void z180_device::device_start()
|
||||
|
||||
state_add(Z180_IOLINES, "IOLINES", m_ioltemp).mask(0xffffff).callimport();
|
||||
|
||||
state_add(Z180_CNTLA0, "CNTLA0", m_asci_cntla[0]);
|
||||
state_add(Z180_CNTLB0, "CNTLB0", m_asci_cntlb[0]);
|
||||
state_add(Z180_STAT0, "STAT0", m_asci_stat[0]);
|
||||
state_add(Z180_TDR0, "TDR0", m_asci_tdr[0]);
|
||||
state_add(Z180_RDR0, "RDR0", m_asci_rdr[0]);
|
||||
|
||||
state_add(Z180_CNTLA1, "CNTLA1", m_asci_cntla[1]);
|
||||
state_add(Z180_CNTLB1, "CNTLB1", m_asci_cntlb[1]);
|
||||
state_add(Z180_STAT1, "STAT1", m_asci_stat[1]);
|
||||
state_add(Z180_TDR1, "TDR1", m_asci_tdr[1]);
|
||||
state_add(Z180_RDR1, "RDR1", m_asci_rdr[1]);
|
||||
|
||||
m_asci[0]->state_add(*this);
|
||||
m_asci[1]->state_add(*this);
|
||||
state_add(Z180_CNTR, "CNTR", m_csio_cntr).mask(Z180_CNTR_MASK);
|
||||
state_add(Z180_TRDR, "TRDR", m_csio_trdr);
|
||||
|
||||
@ -1798,11 +1627,6 @@ void z180_device::device_start()
|
||||
save_item(NAME(m_tmdrh));
|
||||
save_item(NAME(m_tmdr_latch));
|
||||
|
||||
save_item(NAME(m_asci_cntla));
|
||||
save_item(NAME(m_asci_cntlb));
|
||||
save_item(NAME(m_asci_stat));
|
||||
save_item(NAME(m_asci_tdr));
|
||||
save_item(NAME(m_asci_rdr));
|
||||
save_item(NAME(m_csio_cntr));
|
||||
save_item(NAME(m_csio_trdr));
|
||||
save_item(NAME(m_tmdr[0].w));
|
||||
@ -1841,18 +1665,9 @@ void z8s180_device::device_start()
|
||||
{
|
||||
z180_device::device_start();
|
||||
|
||||
state_add(Z180_ASEXT0, "ASEXT0", m_asci_ext[0]).mask(Z180_ASEXT0_MASK);
|
||||
state_add(Z180_ASTC0, "ASTC0", m_asci_tc[0].w);
|
||||
|
||||
state_add(Z180_ASEXT1, "ASEXT1", m_asci_ext[1]).mask(Z180_ASEXT1_MASK);
|
||||
state_add(Z180_ASTC1, "ASTC1", m_asci_tc[1].w);
|
||||
|
||||
state_add(Z180_CMR, "CMR", m_cmr).mask(Z180_CMR_MASK);
|
||||
state_add(Z180_CCR, "CCR", m_ccr);
|
||||
|
||||
save_item(NAME(m_asci_ext));
|
||||
save_item(NAME(m_asci_tc[0].w));
|
||||
save_item(NAME(m_asci_tc[1].w));
|
||||
save_item(NAME(m_cmr));
|
||||
save_item(NAME(m_ccr));
|
||||
}
|
||||
@ -1912,12 +1727,6 @@ void z180_device::device_reset()
|
||||
m_frc_prescale = 0;
|
||||
|
||||
/* reset io registers */
|
||||
m_asci_cntla[0] = (m_asci_cntla[0] & Z180_CNTLA0_MPBR_EFR) | Z180_CNTLA0_RTS0;
|
||||
m_asci_cntla[1] = (m_asci_cntla[1] & Z180_CNTLA1_MPBR_EFR) | Z180_CNTLA1_CKA1D;
|
||||
m_asci_cntlb[0] = (m_asci_cntlb[0] & (Z180_CNTLB0_MPBT | Z180_CNTLB0_CTS_PS)) | 0x07;
|
||||
m_asci_cntlb[1] = (m_asci_cntlb[1] & Z180_CNTLB1_MPBT) | 0x07;
|
||||
m_asci_stat[0] = m_asci_stat[0] & (Z180_STAT0_DCD0 | Z180_STAT0_TDRE);
|
||||
m_asci_stat[1] = Z180_STAT1_TDRE;
|
||||
m_csio_cntr = 0x07;
|
||||
m_tcr = 0x00;
|
||||
m_dma_iar1.b.h2 = 0x00;
|
||||
@ -1936,17 +1745,35 @@ void z180_device::device_reset()
|
||||
z180_mmu();
|
||||
}
|
||||
|
||||
void z180_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
Z180ASCI_CHANNEL_0(config, m_asci[0], DERIVED_CLOCK(1,2));
|
||||
|
||||
Z180ASCI_CHANNEL_1(config, m_asci[1], DERIVED_CLOCK(1,2));
|
||||
}
|
||||
|
||||
void z8s180_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
Z180ASCI_EXT_CHANNEL_0(config, m_asci[0], DERIVED_CLOCK(1,2));
|
||||
|
||||
Z180ASCI_EXT_CHANNEL_1(config, m_asci[1], DERIVED_CLOCK(1,2));
|
||||
}
|
||||
|
||||
void z8s180_device::device_reset()
|
||||
{
|
||||
z180_device::device_reset();
|
||||
|
||||
m_asci_ext[0] = 0x00;
|
||||
m_asci_ext[1] = 0x00;
|
||||
m_cmr = 0x00;
|
||||
m_ccr = 0x00;
|
||||
notify_clock_changed();
|
||||
}
|
||||
|
||||
void z8s180_device::device_clock_changed()
|
||||
{
|
||||
m_asci[0]->set_clock((m_cmr & 0x80) ? DERIVED_CLOCK(2,1) : (m_ccr & 0x80) ? DERIVED_CLOCK(1,1) : DERIVED_CLOCK(1,2));
|
||||
m_asci[1]->set_clock((m_cmr & 0x80) ? DERIVED_CLOCK(2,1) : (m_ccr & 0x80) ? DERIVED_CLOCK(1,1) : DERIVED_CLOCK(1,2));
|
||||
}
|
||||
|
||||
/* Handle PRT timers, decreasing them after 20 clocks and returning the new icount base that needs to be used for the next check */
|
||||
void z180_device::clock_timers()
|
||||
{
|
||||
@ -2005,6 +1832,9 @@ int z180_device::check_interrupts()
|
||||
|
||||
if (m_irq_state[2] != CLEAR_LINE && (m_itc & Z180_ITC_ITE2) == Z180_ITC_ITE2)
|
||||
m_int_pending[Z180_INT_IRQ2] = 1;
|
||||
|
||||
m_int_pending[Z180_INT_ASCI0] = m_asci[0]->check_interrupt();
|
||||
m_int_pending[Z180_INT_ASCI1] = m_asci[1]->check_interrupt();
|
||||
}
|
||||
|
||||
for (i = 0; i <= Z180_INT_MAX; i++)
|
||||
@ -2012,6 +1842,8 @@ int z180_device::check_interrupts()
|
||||
{
|
||||
cycles += take_interrupt(i);
|
||||
m_int_pending[i] = 0;
|
||||
if (i == Z180_INT_ASCI0) m_asci[0]->clear_interrupt();
|
||||
if (i == Z180_INT_ASCI1) m_asci[1]->clear_interrupt();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "machine/z80daisy.h"
|
||||
|
||||
#include "z180asci.h"
|
||||
|
||||
enum
|
||||
{
|
||||
@ -107,10 +107,23 @@ class z180_device : public cpu_device, public z80_daisy_chain_interface
|
||||
public:
|
||||
auto tend0_wr_callback() { return m_tend0_cb.bind(); }
|
||||
auto tend1_wr_callback() { return m_tend1_cb.bind(); }
|
||||
auto txa0_wr_callback() { return subdevice<z180asci_channel_base>("asci_0")->txa_handler(); }
|
||||
auto txa1_wr_callback() { return subdevice<z180asci_channel_base>("asci_1")->txa_handler(); }
|
||||
auto rts0_wr_callback() { return subdevice<z180asci_channel_base>("asci_0")->rts_handler(); }
|
||||
auto cka0_wr_callback() { return subdevice<z180asci_channel_base>("asci_0")->cka_handler(); }
|
||||
auto cka1_wr_callback() { return subdevice<z180asci_channel_base>("asci_1")->cka_handler(); }
|
||||
|
||||
bool get_tend0();
|
||||
bool get_tend1();
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( rxa0_w ) { m_asci[0]->rxa_wr(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( rxa1_w ) { m_asci[1]->rxa_wr(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( cts0_w ) { m_asci[0]->cts_wr(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( cts1_w ) { m_asci[1]->cts_wr(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( dcd0_w ) { m_asci[0]->dcd_wr(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( cka0_w ) { m_asci[0]->cka_wr(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( cka1_w ) { m_asci[1]->cka_wr(state); }
|
||||
|
||||
protected:
|
||||
// construction/destruction
|
||||
z180_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool extended_io, address_map_constructor internal_map);
|
||||
@ -119,6 +132,7 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
|
||||
@ -150,6 +164,7 @@ protected:
|
||||
address_space_config m_program_config;
|
||||
address_space_config m_io_config;
|
||||
address_space_config m_decrypted_opcodes_config;
|
||||
required_device_array<z180asci_channel_base, 2> m_asci;
|
||||
|
||||
void set_address_width(int bits);
|
||||
|
||||
@ -169,11 +184,6 @@ private:
|
||||
uint8_t m_tmdr_latch; // flag latched TMDR0H, TMDR1H values
|
||||
uint8_t m_read_tcr_tmdr[2]; // flag to indicate that TCR or TMDR was read
|
||||
uint32_t m_iol; // I/O line status bits
|
||||
uint8_t m_asci_cntla[2]; // ASCI control register A ch 0-1
|
||||
uint8_t m_asci_cntlb[2]; // ASCI control register B ch 0-1
|
||||
uint8_t m_asci_stat[2]; // ASCI status register 0-1
|
||||
uint8_t m_asci_tdr[2]; // ASCI transmit data register 0-1
|
||||
uint8_t m_asci_rdr[2]; // ASCI receive data register 0-1
|
||||
uint8_t m_csio_cntr; // CSI/O control/status register
|
||||
uint8_t m_csio_trdr; // CSI/O transmit/receive register
|
||||
PAIR16 m_tmdr[2]; // PRT data register ch 0-1
|
||||
@ -1822,6 +1832,8 @@ protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_clock_changed() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return BIT(m_cmr, 7) ? (clocks * 2) : BIT(m_ccr, 7) ? clocks : (clocks + 2 - 1) / 2; }
|
||||
@ -1831,8 +1843,6 @@ protected:
|
||||
virtual void z180_internal_port_write(uint8_t port, uint8_t data) override;
|
||||
|
||||
private:
|
||||
uint8_t m_asci_ext[2]; // ASCI extension control register 0-1
|
||||
PAIR16 m_asci_tc[2]; // ASCI time constant ch 0-1
|
||||
uint8_t m_cmr; // clock multiplier
|
||||
uint8_t m_ccr; // chip control register
|
||||
};
|
||||
|
702
src/devices/cpu/z180/z180asci.cpp
Normal file
702
src/devices/cpu/z180/z180asci.cpp
Normal file
@ -0,0 +1,702 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Miodrag Milanovic
|
||||
/*********************************************************************
|
||||
|
||||
z180asci.cpp
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "z180.h"
|
||||
|
||||
//#define VERBOSE 1
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
/* 00 ASCI control register A ch 0 */
|
||||
static constexpr u8 Z180_CNTLA_MPE = 0x80;
|
||||
static constexpr u8 Z180_CNTLA_RE = 0x40;
|
||||
static constexpr u8 Z180_CNTLA_TE = 0x20;
|
||||
static constexpr u8 Z180_CNTLA_RTS0 = 0x10;
|
||||
static constexpr u8 Z180_CNTLA_MPBR_EFR = 0x08;
|
||||
static constexpr u8 Z180_CNTLA_MODE = 0x07;
|
||||
static constexpr u8 Z180_CNTLA_MODE_DATA = 0x04;
|
||||
static constexpr u8 Z180_CNTLA_MODE_PARITY = 0x02;
|
||||
static constexpr u8 Z180_CNTLA_MODE_STOPB = 0x01;
|
||||
|
||||
/* 01 ASCI control register A ch 1 */
|
||||
static constexpr u8 Z180_CNTLA1_CKA1D = 0x10;
|
||||
|
||||
/* 02/03 ASCI control register B ch 0 */
|
||||
static constexpr u8 Z180_CNTLB_MPBT = 0x80;
|
||||
static constexpr u8 Z180_CNTLB_MP = 0x40;
|
||||
static constexpr u8 Z180_CNTLB_CTS_PS = 0x20;
|
||||
static constexpr u8 Z180_CNTLB_PEO = 0x10;
|
||||
static constexpr u8 Z180_CNTLB_DR = 0x08;
|
||||
static constexpr u8 Z180_CNTLB_SS = 0x07;
|
||||
|
||||
/* 04 ASCI status register 0 (all bits read-only except RIE and TIE) */
|
||||
static constexpr u8 Z180_STAT_RDRF = 0x80;
|
||||
static constexpr u8 Z180_STAT_OVRN = 0x40;
|
||||
static constexpr u8 Z180_STAT_PE = 0x20;
|
||||
static constexpr u8 Z180_STAT_FE = 0x10;
|
||||
static constexpr u8 Z180_STAT_RIE = 0x08;
|
||||
static constexpr u8 Z180_STAT_DCD0 = 0x04;
|
||||
static constexpr u8 Z180_STAT_TDRE = 0x02;
|
||||
static constexpr u8 Z180_STAT_TIE = 0x01;
|
||||
|
||||
/* 05 ASCI status register 1 (all bits read-only except RIE, CTS1E and TIE) */
|
||||
static constexpr u8 Z180_STAT1_CTS1E = 0x04;
|
||||
|
||||
/* 12/13 (Z8S180/Z8L180) ASCI extension control register 0 (break detect is read-only) */
|
||||
static constexpr u8 Z180_ASEXT_DCD0 = 0x40;
|
||||
static constexpr u8 Z180_ASEXT_CTS0 = 0x20;
|
||||
static constexpr u8 Z180_ASEXT_X1_BIT_CLK0 = 0x10;
|
||||
static constexpr u8 Z180_ASEXT_BRG0_MODE = 0x08;
|
||||
static constexpr u8 Z180_ASEXT_BRK_EN = 0x04;
|
||||
static constexpr u8 Z180_ASEXT_BRK_DET = 0x02;
|
||||
static constexpr u8 Z180_ASEXT_BRK_SEND = 0x01;
|
||||
|
||||
static constexpr u8 Z180_ASEXT0_MASK = 0x7f;
|
||||
static constexpr u8 Z180_ASEXT1_MASK = 0x1f;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_channel_base
|
||||
//**************************************************************************
|
||||
|
||||
z180asci_channel_base::z180asci_channel_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const int id, const bool ext)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, m_rcv_clock(nullptr)
|
||||
, m_tra_clock(nullptr)
|
||||
, m_bit_rate(attotime::never)
|
||||
, m_sample_rate(attotime::never)
|
||||
, m_txa_handler(*this)
|
||||
, m_rts_handler(*this)
|
||||
, m_cka_handler(*this)
|
||||
, m_cts(0)
|
||||
, m_dcd(0)
|
||||
, m_irq(0)
|
||||
, m_rts(0)
|
||||
, m_divisor(0)
|
||||
, m_id(id)
|
||||
, m_ext(ext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void z180asci_channel_base::device_resolve_objects()
|
||||
{
|
||||
// resolve callbacks
|
||||
m_txa_handler.resolve_safe();
|
||||
m_rts_handler.resolve_safe();
|
||||
m_cka_handler.resolve_safe();
|
||||
}
|
||||
|
||||
void z180asci_channel_base::device_start()
|
||||
{
|
||||
save_item(NAME(m_asci_cntla));
|
||||
save_item(NAME(m_asci_cntlb));
|
||||
save_item(NAME(m_asci_stat));
|
||||
save_item(NAME(m_asci_tdr));
|
||||
save_item(NAME(m_asci_rdr));
|
||||
if (m_ext)
|
||||
{
|
||||
save_item(NAME(m_asci_ext));
|
||||
save_item(NAME(m_asci_tc.w));
|
||||
}
|
||||
save_item(NAME(m_tsr));
|
||||
save_item(NAME(m_rsr));
|
||||
save_item(NAME(m_data_fifo));
|
||||
save_item(NAME(m_error_fifo));
|
||||
save_item(NAME(m_fifo_wr));
|
||||
save_item(NAME(m_fifo_rd));
|
||||
|
||||
save_item(NAME(m_cts));
|
||||
save_item(NAME(m_dcd));
|
||||
save_item(NAME(m_irq));
|
||||
save_item(NAME(m_txa));
|
||||
save_item(NAME(m_rxa));
|
||||
save_item(NAME(m_rts));
|
||||
|
||||
save_item(NAME(m_divisor));
|
||||
|
||||
save_item(NAME(m_clock_state));
|
||||
|
||||
save_item(NAME(m_tx_counter));
|
||||
save_item(NAME(m_tx_state));
|
||||
|
||||
save_item(NAME(m_rx_state));
|
||||
save_item(NAME(m_rx_bits));
|
||||
save_item(NAME(m_rx_counter));
|
||||
save_item(NAME(m_rx_count_to));
|
||||
save_item(NAME(m_rx_total_bits));
|
||||
save_item(NAME(m_rx_enabled));
|
||||
|
||||
save_item(NAME(m_bit_rate));
|
||||
save_item(NAME(m_sample_rate));
|
||||
|
||||
|
||||
m_rcv_clock = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z180asci_channel_base::rcv_clock), this));
|
||||
m_tra_clock = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z180asci_channel_base::tra_clock), this));
|
||||
|
||||
}
|
||||
|
||||
void z180asci_channel_base::device_reset()
|
||||
{
|
||||
m_asci_ext = 0;
|
||||
m_asci_tc.w = 0;
|
||||
|
||||
m_fifo_wr = 0;
|
||||
m_fifo_rd = 0;
|
||||
|
||||
output_txa(1);
|
||||
output_rts(1);
|
||||
|
||||
m_tsr = 0;
|
||||
m_rxa = 1;
|
||||
m_clock_state = 0;
|
||||
m_tx_state = STATE_WAIT;
|
||||
m_rx_state = STATE_START;
|
||||
m_rx_bits = 0;
|
||||
m_rx_enabled = true;
|
||||
|
||||
m_tx_counter = 0;
|
||||
m_rx_counter = 0;
|
||||
m_rx_count_to = 1;
|
||||
}
|
||||
|
||||
void z180asci_channel_base::device_clock_changed()
|
||||
{
|
||||
uint32_t brg_divisor;
|
||||
// Divide ratio
|
||||
m_divisor = (m_asci_ext & Z180_ASEXT_X1_BIT_CLK0) ? 1 : ((m_asci_cntlb & Z180_CNTLB_DR) ? 64 : 16);
|
||||
|
||||
if ((m_asci_cntlb & Z180_CNTLB_SS) == Z180_CNTLB_SS)
|
||||
{
|
||||
// External clock
|
||||
brg_divisor = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_asci_ext & Z180_ASEXT_BRG0_MODE)
|
||||
{
|
||||
// Extended boud rate generator mode
|
||||
brg_divisor = m_asci_tc.w + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Regular bitrate generator mode
|
||||
brg_divisor = 1 << (m_asci_cntlb & Z180_CNTLB_SS);
|
||||
brg_divisor *= ((m_asci_cntlb & Z180_CNTLB_CTS_PS) ? 30 : 10); // Prescale
|
||||
}
|
||||
}
|
||||
|
||||
if (brg_divisor)
|
||||
{
|
||||
LOG("Z180 ASCI%d set bitrate %d\n", m_id, uint32_t(clock() / brg_divisor / m_divisor));
|
||||
m_bit_rate = attotime::from_hz(clock() / brg_divisor / m_divisor);
|
||||
m_sample_rate = attotime::from_hz(clock() / brg_divisor);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("Z180 ASCI%d set bitrate 0, using external\n", m_id);
|
||||
m_bit_rate = attotime::never;
|
||||
m_sample_rate = attotime::never;
|
||||
}
|
||||
|
||||
m_tra_clock->adjust(attotime::never);
|
||||
m_rx_state = STATE_START;
|
||||
m_rx_count_to = 1;
|
||||
if(!m_sample_rate.is_never())
|
||||
m_rcv_clock->adjust(m_sample_rate, 0, m_sample_rate);
|
||||
}
|
||||
|
||||
uint8_t z180asci_channel_base::cntla_r()
|
||||
{
|
||||
LOG("Z180 CNTLA%d rd $%02x\n", m_id, m_asci_cntla);
|
||||
return m_asci_cntla;
|
||||
}
|
||||
|
||||
uint8_t z180asci_channel_base::cntlb_r()
|
||||
{
|
||||
uint8_t data = (m_asci_cntlb & 0x0d) | (m_cts << 5);
|
||||
LOG("Z180 CNTLB%d rd $%02x\n", m_id, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t z180asci_channel_base::stat_r()
|
||||
{
|
||||
LOG("Z180 STAT%d rd $%02x\n", m_id, m_asci_stat);
|
||||
return m_asci_stat;
|
||||
}
|
||||
|
||||
uint8_t z180asci_channel_base::tdr_r()
|
||||
{
|
||||
LOG("Z180 TDR%d rd $%02x\n", m_id, m_asci_tdr);
|
||||
return m_asci_tdr;
|
||||
}
|
||||
|
||||
uint8_t z180asci_channel_base::rdr_r()
|
||||
{
|
||||
LOG("Z180 RDR%d rd $%02x\n", m_id, m_asci_rdr);
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
if (m_fifo_rd != m_fifo_wr)
|
||||
{
|
||||
m_asci_rdr = m_data_fifo[m_fifo_rd];
|
||||
m_asci_stat &= ~(Z180_STAT_OVRN | Z180_STAT_PE | Z180_STAT_FE);
|
||||
m_asci_stat |= m_error_fifo[m_fifo_rd];
|
||||
if (m_asci_stat & (Z180_STAT_OVRN | Z180_STAT_PE | Z180_STAT_FE))
|
||||
m_irq = 1;
|
||||
m_fifo_rd = (m_fifo_rd + 1) & 3;
|
||||
if (m_fifo_rd == m_fifo_wr) // empty
|
||||
m_asci_stat &= ~Z180_STAT_RDRF;
|
||||
}
|
||||
}
|
||||
return m_asci_rdr;
|
||||
}
|
||||
|
||||
uint8_t z180asci_channel_base::asext_r()
|
||||
{
|
||||
LOG("Z180 ASEXT%d rd $%02x\n", m_id, m_asci_ext);
|
||||
return m_asci_ext;
|
||||
}
|
||||
|
||||
uint8_t z180asci_channel_base::astcl_r()
|
||||
{
|
||||
LOG("Z180 ASTC%dL rd $%02x ($%04x)\n", m_id, m_asci_tc.b.l, m_asci_tc.w);
|
||||
return m_asci_tc.b.l;
|
||||
}
|
||||
|
||||
uint8_t z180asci_channel_base::astch_r()
|
||||
{
|
||||
LOG("Z180 ASTC%dH rd $%02x ($%04x)\n", m_id, m_asci_tc.b.h, m_asci_tc.w);
|
||||
return m_asci_tc.b.h;
|
||||
}
|
||||
|
||||
void z180asci_channel_base::update_total_bits()
|
||||
{
|
||||
m_rx_total_bits = (m_asci_cntla & Z180_CNTLA_MODE_DATA) ? 8 : 7;
|
||||
m_rx_total_bits += (m_asci_cntla & Z180_CNTLA_MODE_STOPB) ? 2 : 1;
|
||||
m_rx_total_bits += (m_asci_cntlb & Z180_CNTLB_MP) ? 1 : ((m_asci_cntla & Z180_CNTLA_MODE_PARITY) ? 1 : 0);
|
||||
}
|
||||
|
||||
void z180asci_channel_base::cntla_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 CNTLA%d wr $%02x\n", m_id, data);
|
||||
m_asci_cntla = data & ~(Z180_CNTLA_MPBR_EFR | Z180_CNTLA_RTS0);
|
||||
output_rts(BIT(data,4)); // Z180_CNTLA_RTS0
|
||||
if (data & Z180_CNTLA_MPBR_EFR) // Error Flag Reset
|
||||
{
|
||||
m_asci_stat &= ~(Z180_STAT_OVRN | Z180_STAT_PE | Z180_STAT_FE);
|
||||
m_asci_ext &= ~(Z180_ASEXT_BRK_DET);
|
||||
}
|
||||
update_total_bits();
|
||||
}
|
||||
|
||||
void z180asci_channel_base::cntlb_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 CNTLB%d wr $%02x\n", m_id, data);
|
||||
m_asci_cntlb = data;
|
||||
device_clock_changed();
|
||||
update_total_bits();
|
||||
}
|
||||
|
||||
void z180asci_channel_base::tdr_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 TDR%d wr $%02x\n", m_id, data);
|
||||
m_asci_tdr = data;
|
||||
m_asci_stat &= ~Z180_STAT_TDRE;
|
||||
|
||||
if (!m_bit_rate.is_never())
|
||||
m_tra_clock->adjust(m_bit_rate, 0, m_bit_rate);
|
||||
}
|
||||
|
||||
void z180asci_channel_base::rdr_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 RDR%d wr $%02x\n", m_id, data);
|
||||
if (!(m_asci_stat & Z180_STAT_RDRF))
|
||||
set_fifo_data(data, 0);
|
||||
}
|
||||
|
||||
void z180asci_channel_base::asext_w(uint8_t data)
|
||||
{
|
||||
if (m_asci_ext & Z180_ASEXT_BRK_EN)
|
||||
m_tx_state = (m_asci_ext & Z180_ASEXT_BRK_SEND) ? STATE_BREAK : STATE_WAIT;
|
||||
device_clock_changed();
|
||||
}
|
||||
|
||||
void z180asci_channel_base::astcl_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 ASTC%dL wr $%02x\n", m_id, data);
|
||||
m_asci_tc.b.l = data;
|
||||
device_clock_changed();
|
||||
}
|
||||
|
||||
void z180asci_channel_base::astch_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 ASTC%dH wr $%02x\n", m_id, data);
|
||||
m_asci_tc.b.h = data;
|
||||
device_clock_changed();
|
||||
}
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( z180asci_channel_base::cts_wr )
|
||||
{
|
||||
if (m_id)
|
||||
{
|
||||
// For channel 1, CTS can be disabled
|
||||
if ((m_asci_stat && Z180_STAT1_CTS1E) == 0) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For channel 0, high resets TDRE
|
||||
if (m_ext && state && (m_asci_ext && Z180_ASEXT_CTS0) == 0)
|
||||
m_asci_stat |= Z180_STAT_TDRE;
|
||||
}
|
||||
m_cts = state;
|
||||
}
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( z180asci_channel_base::dcd_wr )
|
||||
{
|
||||
if (m_id)
|
||||
return;
|
||||
|
||||
// In extended mode, DCD autoenables RX if configured
|
||||
if (m_ext && (m_asci_ext && Z180_ASEXT_DCD0) == 0)
|
||||
{
|
||||
m_rx_enabled = state ? false : true;
|
||||
if (state)
|
||||
m_asci_ext &= ~(Z180_ASEXT_BRK_DET);
|
||||
}
|
||||
|
||||
m_dcd = state;
|
||||
if (m_dcd)
|
||||
m_irq = 1;
|
||||
}
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( z180asci_channel_base::rxa_wr )
|
||||
{
|
||||
m_rxa = state;
|
||||
}
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( z180asci_channel_base::cka_wr )
|
||||
{
|
||||
// For channel 1, CKA can be disabled
|
||||
if (m_id && (m_asci_cntla && Z180_CNTLA1_CKA1D)) return;
|
||||
|
||||
if(state != m_clock_state)
|
||||
{
|
||||
m_clock_state = state;
|
||||
if(!state)
|
||||
{
|
||||
m_tx_counter++;
|
||||
if (m_tx_counter != m_divisor) return;
|
||||
m_tx_counter = 0;
|
||||
if (m_asci_cntla & Z180_CNTLA_TE)
|
||||
transmit_edge();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rx_counter++;
|
||||
if (m_rx_counter != m_rx_count_to) return;
|
||||
m_rx_counter = 0;
|
||||
if (m_rx_enabled && (m_asci_cntla & Z180_CNTLA_RE))
|
||||
receive_edge();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void z180asci_channel_base::prepare_tsr()
|
||||
{
|
||||
int bits = (m_asci_cntla & Z180_CNTLA_MODE_DATA) ? 8 : 7;
|
||||
|
||||
m_tsr = (m_asci_cntla & Z180_CNTLA_MODE_STOPB) ? 3 : 1; // stop bit(s)
|
||||
|
||||
if ((m_asci_cntlb & Z180_CNTLB_MP) || (m_asci_cntla & Z180_CNTLA_MODE_PARITY))
|
||||
{
|
||||
m_tsr <<= 1;
|
||||
if (m_asci_cntlb & Z180_CNTLB_MP)
|
||||
{
|
||||
m_tsr |= (m_asci_cntlb & Z180_CNTLB_MPBT) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t parity = 0;
|
||||
for (int i = 0; i < bits; i++)
|
||||
parity ^= BIT(m_asci_tdr, i);
|
||||
if (m_asci_cntlb & Z180_CNTLB_PEO) parity ^= 1; // odd parity
|
||||
m_tsr |= parity;
|
||||
}
|
||||
}
|
||||
m_tsr <<= bits;
|
||||
m_tsr |= m_asci_tdr;
|
||||
m_tsr <<= 1; // start bit
|
||||
}
|
||||
|
||||
void z180asci_channel_base::transmit_edge()
|
||||
{
|
||||
if (m_asci_cntla & Z180_CNTLA_TE)
|
||||
{
|
||||
switch (m_tx_state)
|
||||
{
|
||||
case STATE_DATA:
|
||||
output_txa(BIT(m_tsr, 0));
|
||||
m_tsr >>= 1;
|
||||
if (m_tsr == 0)
|
||||
{
|
||||
m_asci_stat |= Z180_STAT_TDRE;
|
||||
if (m_asci_stat & Z180_STAT_TIE)
|
||||
{
|
||||
m_irq = 1;
|
||||
}
|
||||
m_tx_state = STATE_WAIT;
|
||||
m_tra_clock->adjust(attotime::never);
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT:
|
||||
if ((m_asci_stat & Z180_STAT_TDRE) == 0)
|
||||
{
|
||||
prepare_tsr();
|
||||
m_tx_state = STATE_DATA;
|
||||
}
|
||||
break;
|
||||
case STATE_BREAK:
|
||||
output_txa(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void z180asci_channel_base::update_received()
|
||||
{
|
||||
uint8_t rx_error = 0;
|
||||
int stop_bits = (m_asci_cntla & Z180_CNTLA_MODE_STOPB) ? 2 : 1;
|
||||
if (m_rsr == 0) // Break detect
|
||||
{
|
||||
m_asci_ext |= Z180_ASEXT_BRK_DET;
|
||||
}
|
||||
uint8_t stop_val = (m_asci_cntla & Z180_CNTLA_MODE_STOPB) ? 3: 1;
|
||||
if ((m_rsr & stop_val) != stop_val)
|
||||
rx_error |= Z180_STAT_FE;
|
||||
|
||||
if (m_asci_cntlb & Z180_CNTLB_MP)
|
||||
{
|
||||
m_asci_cntla |= ((m_rsr >> stop_bits) & 1) ? Z180_CNTLA_MPBR_EFR : 0;
|
||||
}
|
||||
else if (m_asci_cntla & Z180_CNTLA_MODE_PARITY)
|
||||
{
|
||||
uint8_t parity = 0;
|
||||
for (int i = 0; i < ((m_asci_cntla & Z180_CNTLA_MODE_DATA) ? 8 : 7); i++)
|
||||
parity ^= BIT(m_rsr, i);
|
||||
if (m_asci_cntlb & Z180_CNTLB_PEO) parity ^= 1; // odd parity
|
||||
if (((m_rsr >> stop_bits) & 1) != parity)
|
||||
rx_error |= Z180_STAT_PE;
|
||||
}
|
||||
// Skip only if MPE mode active and MPB is 0
|
||||
if (!((m_asci_cntla & Z180_CNTLA_MPE) && ((m_asci_cntla & Z180_CNTLA_MPBR_EFR) == 0)))
|
||||
{
|
||||
set_fifo_data(m_rsr, rx_error);
|
||||
}
|
||||
}
|
||||
|
||||
void z180asci_channel_base::receive_edge()
|
||||
{
|
||||
if (!m_rx_enabled) return;
|
||||
|
||||
if (m_asci_cntla & Z180_CNTLA_RE)
|
||||
{
|
||||
switch (m_rx_state)
|
||||
{
|
||||
case STATE_START:
|
||||
if(m_rxa == 0)
|
||||
{
|
||||
m_rx_state = STATE_DATA;
|
||||
m_rx_bits = 0;
|
||||
m_rsr = 0;
|
||||
if(!(m_bit_rate.is_never()))
|
||||
m_rcv_clock->adjust((m_divisor == 1) ? m_bit_rate : (m_bit_rate * 3) / 2, 0, m_bit_rate);
|
||||
else
|
||||
m_rx_count_to = (m_divisor == 1) ? m_divisor : (m_divisor * 3) / 2;
|
||||
}
|
||||
break;
|
||||
case STATE_DATA:
|
||||
m_rsr |= m_rxa << m_rx_bits;
|
||||
m_rx_bits++;
|
||||
m_rx_count_to = m_divisor;
|
||||
if (m_rx_bits == m_rx_total_bits)
|
||||
{
|
||||
update_received();
|
||||
m_rx_state = STATE_START;
|
||||
if(!m_sample_rate.is_never())
|
||||
m_rcv_clock->adjust(m_sample_rate, 0, m_sample_rate);
|
||||
else
|
||||
m_rx_count_to = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void z180asci_channel_base::set_fifo_data(uint8_t data, uint8_t error)
|
||||
{
|
||||
m_data_fifo[m_fifo_wr] = data;
|
||||
m_error_fifo[m_fifo_wr] = error;
|
||||
if (((m_fifo_wr + 1) & 3) == m_fifo_rd) // overrun
|
||||
{
|
||||
m_error_fifo[m_fifo_wr] |= Z180_STAT_OVRN;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_error_fifo[m_fifo_wr] &= Z180_STAT_OVRN;
|
||||
m_fifo_wr = (m_fifo_wr + 1) & 3;
|
||||
}
|
||||
m_asci_stat |= Z180_STAT_RDRF;
|
||||
if (m_asci_stat & Z180_STAT_RIE)
|
||||
{
|
||||
m_irq = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void z180asci_channel_base::output_txa(int txa)
|
||||
{
|
||||
if (m_txa != txa)
|
||||
{
|
||||
m_txa = txa;
|
||||
m_txa_handler(m_txa);
|
||||
}
|
||||
}
|
||||
|
||||
void z180asci_channel_base::output_rts(int rts)
|
||||
{
|
||||
if (m_rts != rts)
|
||||
{
|
||||
m_rts = rts;
|
||||
m_rts_handler(m_rts);
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_channel_0
|
||||
//**************************************************************************
|
||||
|
||||
z180asci_channel_0::z180asci_channel_0(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const bool ext)
|
||||
: z180asci_channel_base(mconfig, type, tag, owner, clock, 0, ext)
|
||||
{
|
||||
}
|
||||
|
||||
z180asci_channel_0::z180asci_channel_0(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: z180asci_channel_0(mconfig, Z180ASCI_CHANNEL_0, tag, owner, clock, false)
|
||||
{
|
||||
}
|
||||
|
||||
void z180asci_channel_0::device_reset()
|
||||
{
|
||||
z180asci_channel_base::device_reset();
|
||||
cntla_w((m_asci_cntla & Z180_CNTLA_MPBR_EFR) | Z180_CNTLA_RTS0);
|
||||
cntlb_w((m_asci_cntlb & (Z180_CNTLB_MPBT | Z180_CNTLB_CTS_PS)) | 0x07);
|
||||
m_asci_stat = (m_asci_stat & Z180_STAT_DCD0) | Z180_STAT_TDRE;
|
||||
}
|
||||
|
||||
void z180asci_channel_0::state_add(device_state_interface &parent)
|
||||
{
|
||||
parent.state_add(Z180_CNTLA0, "CNTLA0", m_asci_cntla);
|
||||
parent.state_add(Z180_CNTLB0, "CNTLB0", m_asci_cntlb);
|
||||
parent.state_add(Z180_STAT0, "STAT0", m_asci_stat);
|
||||
parent.state_add(Z180_TDR0, "TDR0", m_asci_tdr);
|
||||
parent.state_add(Z180_RDR0, "RDR0", m_asci_rdr);
|
||||
if (m_ext)
|
||||
{
|
||||
parent.state_add(Z180_ASEXT0, "ASEXT0", m_asci_ext).mask(Z180_ASEXT0_MASK);
|
||||
parent.state_add(Z180_ASTC0, "ASTC0", m_asci_tc.w);
|
||||
}
|
||||
}
|
||||
|
||||
void z180asci_channel_0::stat_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 STAT0 wr $%02x ($%02x)\n", data, data & (Z180_STAT_RIE | Z180_STAT_TIE));
|
||||
m_asci_stat = (m_asci_stat & ~(Z180_STAT_RIE | Z180_STAT_TIE)) | (data & (Z180_STAT_RIE | Z180_STAT_TIE));
|
||||
}
|
||||
|
||||
void z180asci_channel_0::asext_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 ASEXT0 wr $%02x ($%02x)\n", data, data & Z180_ASEXT0_MASK & ~Z180_ASEXT_BRK_DET);
|
||||
m_asci_ext = (m_asci_ext & Z180_ASEXT_BRK_DET) | (data & Z180_ASEXT0_MASK & ~Z180_ASEXT_BRK_DET);
|
||||
z180asci_channel_base::asext_w(data);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_channel_1
|
||||
//**************************************************************************
|
||||
|
||||
z180asci_channel_1::z180asci_channel_1(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const bool ext)
|
||||
: z180asci_channel_base(mconfig, type, tag, owner, clock, 1, ext)
|
||||
{
|
||||
}
|
||||
|
||||
z180asci_channel_1::z180asci_channel_1(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: z180asci_channel_1(mconfig, Z180ASCI_CHANNEL_1, tag, owner, clock, false)
|
||||
{
|
||||
}
|
||||
void z180asci_channel_1::device_reset()
|
||||
{
|
||||
z180asci_channel_base::device_reset();
|
||||
cntla_w((m_asci_cntla & Z180_CNTLA_MPBR_EFR) | Z180_CNTLA1_CKA1D);
|
||||
cntlb_w((m_asci_cntlb & Z180_CNTLB_MPBT) | 0x07);
|
||||
m_asci_stat = Z180_STAT_TDRE;
|
||||
}
|
||||
|
||||
void z180asci_channel_1::state_add(device_state_interface &parent)
|
||||
{
|
||||
parent.state_add(Z180_CNTLA1, "CNTLA1", m_asci_cntla);
|
||||
parent.state_add(Z180_CNTLB1, "CNTLB1", m_asci_cntlb);
|
||||
parent.state_add(Z180_STAT1, "STAT1", m_asci_stat);
|
||||
parent.state_add(Z180_TDR1, "TDR1", m_asci_tdr);
|
||||
parent.state_add(Z180_RDR1, "RDR1", m_asci_rdr);
|
||||
if (m_ext)
|
||||
{
|
||||
parent.state_add(Z180_ASEXT1, "ASEXT1", m_asci_ext).mask(Z180_ASEXT1_MASK);
|
||||
parent.state_add(Z180_ASTC1, "ASTC1", m_asci_tc.w);
|
||||
}
|
||||
}
|
||||
|
||||
void z180asci_channel_1::stat_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 STAT1 wr $%02x ($%02x)\n", data, data & (Z180_STAT_RIE | Z180_STAT1_CTS1E | Z180_STAT_TIE));
|
||||
m_asci_stat = (m_asci_stat & ~(Z180_STAT_RIE | Z180_STAT1_CTS1E | Z180_STAT_TIE)) | (data & (Z180_STAT_RIE | Z180_STAT1_CTS1E | Z180_STAT_TIE));
|
||||
}
|
||||
|
||||
void z180asci_channel_1::asext_w(uint8_t data)
|
||||
{
|
||||
LOG("Z180 ASEXT1 wr $%02x ($%02x)\n", data, data & Z180_ASEXT1_MASK & ~Z180_ASEXT_BRK_DET);
|
||||
m_asci_ext = (m_asci_ext & Z180_ASEXT_BRK_DET) | (data & Z180_ASEXT1_MASK & ~Z180_ASEXT_BRK_DET);
|
||||
z180asci_channel_base::asext_w(data);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_ext_channel_0
|
||||
//**************************************************************************
|
||||
|
||||
z180asci_ext_channel_0::z180asci_ext_channel_0(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: z180asci_channel_0(mconfig, Z180ASCI_EXT_CHANNEL_0, tag, owner, clock, true)
|
||||
{
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_channel_1
|
||||
//**************************************************************************
|
||||
|
||||
z180asci_ext_channel_1::z180asci_ext_channel_1(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: z180asci_channel_1(mconfig, Z180ASCI_EXT_CHANNEL_1, tag, owner, clock, true)
|
||||
{
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(Z180ASCI_CHANNEL_0, z180asci_channel_0, "z180asci_channel_0", "Z180 ASCI Channel 0")
|
||||
DEFINE_DEVICE_TYPE(Z180ASCI_CHANNEL_1, z180asci_channel_1, "z180asci_channel_1", "Z180 ASCI Channel 1")
|
||||
|
||||
DEFINE_DEVICE_TYPE(Z180ASCI_EXT_CHANNEL_0, z180asci_ext_channel_0, "z180asci_ext_channel_0", "Z180 ASCI Extended Channel 0")
|
||||
DEFINE_DEVICE_TYPE(Z180ASCI_EXT_CHANNEL_1, z180asci_ext_channel_1, "z180asci_ext_channel_1", "Z180 ASCI Extended Channel 1")
|
201
src/devices/cpu/z180/z180asci.h
Normal file
201
src/devices/cpu/z180/z180asci.h
Normal file
@ -0,0 +1,201 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Miodrag Milanovic
|
||||
/*********************************************************************
|
||||
|
||||
z180asci.h
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef MAME_CPU_Z180_Z180ASCI_H
|
||||
#define MAME_CPU_Z180_Z180ASCI_H
|
||||
|
||||
#pragma once
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_channel_base
|
||||
//**************************************************************************
|
||||
|
||||
class z180asci_channel_base : public device_t
|
||||
{
|
||||
public:
|
||||
// inline configuration
|
||||
auto txa_handler() { return m_txa_handler.bind(); }
|
||||
auto rts_handler() { return m_rts_handler.bind(); }
|
||||
auto cka_handler() { return m_cka_handler.bind(); }
|
||||
|
||||
uint8_t cntla_r();
|
||||
uint8_t cntlb_r();
|
||||
uint8_t stat_r();
|
||||
uint8_t tdr_r();
|
||||
uint8_t rdr_r();
|
||||
uint8_t asext_r();
|
||||
uint8_t astcl_r();
|
||||
uint8_t astch_r();
|
||||
void cntla_w(uint8_t data);
|
||||
void cntlb_w(uint8_t data);
|
||||
virtual void stat_w(uint8_t data) = 0;
|
||||
void tdr_w(uint8_t data);
|
||||
void rdr_w(uint8_t data);
|
||||
virtual void asext_w(uint8_t data);
|
||||
void astcl_w(uint8_t data);
|
||||
void astch_w(uint8_t data);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( rxa_wr );
|
||||
DECLARE_WRITE_LINE_MEMBER( cts_wr );
|
||||
DECLARE_WRITE_LINE_MEMBER( dcd_wr );
|
||||
DECLARE_WRITE_LINE_MEMBER( cka_wr );
|
||||
|
||||
virtual void state_add(device_state_interface &parent) = 0;
|
||||
|
||||
int check_interrupt() { return m_irq; }
|
||||
void clear_interrupt() { m_irq = 0; }
|
||||
protected:
|
||||
z180asci_channel_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const int id, const bool ext);
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_clock_changed() override;
|
||||
|
||||
void transmit_edge();
|
||||
void receive_edge();
|
||||
void set_fifo_data(uint8_t data, uint8_t error);
|
||||
void prepare_tsr();
|
||||
void update_received();
|
||||
void update_total_bits();
|
||||
|
||||
enum serial_state
|
||||
{
|
||||
STATE_START,
|
||||
STATE_DATA,
|
||||
STATE_WAIT,
|
||||
STATE_BREAK
|
||||
};
|
||||
|
||||
|
||||
void output_txa(int txa);
|
||||
void output_rts(int rts);
|
||||
TIMER_CALLBACK_MEMBER(rcv_clock) { receive_edge(); }
|
||||
TIMER_CALLBACK_MEMBER(tra_clock) { transmit_edge(); }
|
||||
|
||||
emu_timer *m_rcv_clock;
|
||||
emu_timer *m_tra_clock;
|
||||
attotime m_bit_rate;
|
||||
attotime m_sample_rate;
|
||||
|
||||
devcb_write_line m_txa_handler;
|
||||
devcb_write_line m_rts_handler;
|
||||
devcb_write_line m_cka_handler;
|
||||
|
||||
uint8_t m_asci_cntla; // ASCI control register A
|
||||
uint8_t m_asci_cntlb; // ASCI control register B
|
||||
uint8_t m_asci_stat; // ASCI status register
|
||||
uint8_t m_asci_tdr; // ASCI transmit data register
|
||||
uint8_t m_asci_rdr; // ASCI receive data register
|
||||
uint8_t m_asci_ext; // ASCI extension control register
|
||||
PAIR16 m_asci_tc; // ASCI time constant
|
||||
|
||||
uint16_t m_tsr;
|
||||
uint16_t m_rsr;
|
||||
uint8_t m_data_fifo[4];
|
||||
uint8_t m_error_fifo[4];
|
||||
uint8_t m_fifo_wr;
|
||||
uint8_t m_fifo_rd;
|
||||
|
||||
uint8_t m_cts;
|
||||
uint8_t m_dcd;
|
||||
uint8_t m_irq;
|
||||
uint8_t m_txa;
|
||||
uint8_t m_rxa;
|
||||
uint8_t m_rts;
|
||||
|
||||
uint32_t m_divisor;
|
||||
|
||||
uint8_t m_clock_state;
|
||||
uint8_t m_tx_state;
|
||||
uint8_t m_rx_state;
|
||||
uint8_t m_rx_bits;
|
||||
|
||||
uint8_t m_tx_counter;
|
||||
uint8_t m_rx_counter;
|
||||
uint8_t m_rx_count_to;
|
||||
uint8_t m_rx_total_bits;
|
||||
|
||||
bool m_rx_enabled;
|
||||
|
||||
const int m_id;
|
||||
const bool m_ext;
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_channel_0
|
||||
//**************************************************************************
|
||||
|
||||
class z180asci_channel_0 : public z180asci_channel_base
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
z180asci_channel_0(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
void stat_w(uint8_t data) override;
|
||||
void asext_w(uint8_t data) override;
|
||||
void state_add(device_state_interface &parent) override;
|
||||
protected:
|
||||
z180asci_channel_0(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const bool ext);
|
||||
// device-level overrides
|
||||
virtual void device_reset() override;
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_channel_1
|
||||
//**************************************************************************
|
||||
|
||||
class z180asci_channel_1 : public z180asci_channel_base
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
z180asci_channel_1(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
void stat_w(uint8_t data) override;
|
||||
void asext_w(uint8_t data) override;
|
||||
void state_add(device_state_interface &parent) override;
|
||||
protected:
|
||||
z180asci_channel_1(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const bool ext);
|
||||
// device-level overrides
|
||||
virtual void device_reset() override;
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_ext_channel_0
|
||||
//**************************************************************************
|
||||
|
||||
class z180asci_ext_channel_0 : public z180asci_channel_0
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
z180asci_ext_channel_0(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
// z180asci_ext_channel_1
|
||||
//**************************************************************************
|
||||
|
||||
class z180asci_ext_channel_1 : public z180asci_channel_1
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
z180asci_ext_channel_1(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
DECLARE_DEVICE_TYPE(Z180ASCI_CHANNEL_0, z180asci_channel_0)
|
||||
DECLARE_DEVICE_TYPE(Z180ASCI_CHANNEL_1, z180asci_channel_1)
|
||||
|
||||
DECLARE_DEVICE_TYPE(Z180ASCI_EXT_CHANNEL_0, z180asci_ext_channel_0)
|
||||
DECLARE_DEVICE_TYPE(Z180ASCI_EXT_CHANNEL_1, z180asci_ext_channel_1)
|
||||
|
||||
#endif // MAME_CPU_Z180_Z180ASCI_H
|
@ -86,7 +86,6 @@ Graphics: CY37256P160-83AC x 2 (Ultra37000 CPLD family - 160 pin TQFP, 256 Macro
|
||||
#include "emu.h"
|
||||
#include "includes/20pacgal.h"
|
||||
|
||||
#include "cpu/z180/z180.h"
|
||||
#include "machine/eepromser.h"
|
||||
#include "machine/watchdog.h"
|
||||
#include "speaker.h"
|
||||
@ -396,12 +395,25 @@ WRITE_LINE_MEMBER(_20pacgal_state::vblank_irq)
|
||||
m_maincpu->set_input_line(0, HOLD_LINE); // TODO: assert breaks the inputs in 25pacman test mode
|
||||
}
|
||||
|
||||
static DEVICE_INPUT_DEFAULTS_START( null_modem )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_115200 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_115200 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
|
||||
DEVICE_INPUT_DEFAULTS_END
|
||||
|
||||
void _20pacgal_state::_20pacgal(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
Z8S180(config, m_maincpu, MAIN_CPU_CLOCK); // 18.432MHz verified on PCB
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &_20pacgal_state::_20pacgal_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &_20pacgal_state::_20pacgal_io_map);
|
||||
m_maincpu->txa0_wr_callback().set("rs232", FUNC(rs232_port_device::write_txd));
|
||||
|
||||
RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
|
||||
m_rs232->set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(null_modem));
|
||||
m_rs232->rxd_handler().set(m_maincpu, FUNC(z180_device::rxa0_w));
|
||||
|
||||
EEPROM_93C46_8BIT(config, m_eeprom);
|
||||
|
||||
@ -420,6 +432,14 @@ void _20pacgal_state::_20pacgal(machine_config &config)
|
||||
DAC_8BIT_R2R(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // unknown DAC
|
||||
}
|
||||
|
||||
static DEVICE_INPUT_DEFAULTS_START( null_modem_57600 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_57600 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_57600 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
|
||||
DEVICE_INPUT_DEFAULTS_END
|
||||
|
||||
void _25pacman_state::_25pacman(machine_config &config)
|
||||
{
|
||||
_20pacgal(config);
|
||||
@ -428,6 +448,8 @@ void _25pacman_state::_25pacman(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &_25pacman_state::_25pacman_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &_25pacman_state::_25pacman_io_map);
|
||||
|
||||
m_rs232->set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(null_modem_57600));
|
||||
|
||||
AMD_29LV200T(config, "flash");
|
||||
}
|
||||
|
||||
|
124
src/mame/drivers/sb180.cpp
Normal file
124
src/mame/drivers/sb180.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Miodrag Milanovic
|
||||
/***************************************************************************
|
||||
|
||||
Micromint SB180
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/z180/z180.h"
|
||||
#include "imagedev/floppy.h"
|
||||
#include "formats/imd_dsk.h"
|
||||
#include "machine/upd765.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
|
||||
#define FDC9266_TAG "u24"
|
||||
|
||||
class sb180_state : public driver_device
|
||||
{
|
||||
public:
|
||||
sb180_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_fdc(*this, FDC9266_TAG)
|
||||
, m_floppy(*this, FDC9266_TAG ":%u", 0)
|
||||
{ }
|
||||
|
||||
void sb180(machine_config &config);
|
||||
|
||||
private:
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void sb180_io(address_map &map);
|
||||
void sb180_mem(address_map &map);
|
||||
|
||||
required_device<z180_device> m_maincpu;
|
||||
required_device<upd765a_device> m_fdc;
|
||||
required_device_array<floppy_connector, 4> m_floppy;
|
||||
};
|
||||
|
||||
void sb180_state::sb180_mem(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x00000, 0x01fff).rom().mirror(0x3e000);
|
||||
map(0x40000, 0x7ffff).ram(); // 256KB RAM 8 * 41256 DRAM
|
||||
}
|
||||
|
||||
void sb180_state::sb180_io(address_map &map)
|
||||
{
|
||||
map.global_mask(0xff);
|
||||
map.unmap_value_high();
|
||||
map(0x00, 0x7f).ram(); /* Z180 internal registers */
|
||||
map(0x80, 0x81).m(m_fdc, FUNC(upd765a_device::map));
|
||||
map(0xa0, 0xa0).rw(m_fdc, FUNC(upd765a_device::dma_r), FUNC(upd765a_device::dma_w));
|
||||
}
|
||||
|
||||
/* Input ports */
|
||||
static INPUT_PORTS_START( sb180 )
|
||||
INPUT_PORTS_END
|
||||
|
||||
void sb180_state::machine_reset()
|
||||
{
|
||||
// motor is actually connected on TXS pin of CPU
|
||||
for (auto &drive : m_floppy)
|
||||
{
|
||||
if (drive->get_device())
|
||||
drive->get_device()->mon_w(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void sb180_floppies(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("35dd", FLOPPY_35_DD);
|
||||
}
|
||||
|
||||
static void sb180_floppy_formats(format_registration &fr)
|
||||
{
|
||||
fr.add_mfm_containers();
|
||||
fr.add(FLOPPY_IMD_FORMAT);
|
||||
}
|
||||
|
||||
static DEVICE_INPUT_DEFAULTS_START( terminal )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
|
||||
DEVICE_INPUT_DEFAULTS_END
|
||||
|
||||
void sb180_state::sb180(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
HD64180RP(config, m_maincpu, XTAL(12'288'000)); // location U17 HD64180
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &sb180_state::sb180_mem);
|
||||
m_maincpu->set_addrmap(AS_IO, &sb180_state::sb180_io);
|
||||
m_maincpu->tend1_wr_callback().set(m_fdc, FUNC(upd765a_device::tc_line_w));
|
||||
m_maincpu->txa1_wr_callback().set("rs232", FUNC(rs232_port_device::write_txd));
|
||||
|
||||
// FDC9266 location U24
|
||||
UPD765A(config, m_fdc, XTAL(8'000'000));
|
||||
m_fdc->intrq_wr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ2);
|
||||
m_fdc->drq_wr_callback().set_inputline(m_maincpu, Z180_INPUT_LINE_DREQ1);
|
||||
|
||||
/* floppy drives */
|
||||
FLOPPY_CONNECTOR(config, m_floppy[0], sb180_floppies, "35dd", sb180_floppy_formats);
|
||||
FLOPPY_CONNECTOR(config, m_floppy[1], sb180_floppies, "35dd", sb180_floppy_formats);
|
||||
FLOPPY_CONNECTOR(config, m_floppy[2], sb180_floppies, "35dd", sb180_floppy_formats);
|
||||
FLOPPY_CONNECTOR(config, m_floppy[3], sb180_floppies, "35dd", sb180_floppy_formats);
|
||||
|
||||
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal"));
|
||||
rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal)); // must be below the DEVICE_INPUT_DEFAULTS_START block
|
||||
rs232.rxd_handler().set(m_maincpu, FUNC(z180_device::rxa1_w));
|
||||
}
|
||||
|
||||
/* ROM definition */
|
||||
ROM_START( sb180 )
|
||||
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "monitor.bin", 0x0000, 0x2000, CRC(49640012) SHA1(ea571dc7476430e31b74bd1ab7a577e9013ad0bd))
|
||||
ROM_END
|
||||
|
||||
/* Driver */
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
|
||||
COMP( 1985, sb180, 0, 0, sb180, sb180, sb180_state, empty_init, "Micromint", "SB180", MACHINE_NO_SOUND)
|
@ -14,6 +14,7 @@
|
||||
#include "formats/imd_dsk.h"
|
||||
#include "formats/tim011_dsk.h"
|
||||
#include "machine/upd765.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
|
||||
@ -136,6 +137,14 @@ static void tim011_floppy_formats(format_registration &fr)
|
||||
fr.add(FLOPPY_TIM011_FORMAT);
|
||||
}
|
||||
|
||||
static DEVICE_INPUT_DEFAULTS_START( keyboard )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_ODD )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
|
||||
DEVICE_INPUT_DEFAULTS_END
|
||||
|
||||
void tim011_state::tim011_palette(palette_device &palette) const
|
||||
{
|
||||
static constexpr rgb_t tim011_pens[4] = {
|
||||
@ -155,6 +164,7 @@ void tim011_state::tim011(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &tim011_state::tim011_mem);
|
||||
m_maincpu->set_addrmap(AS_IO, &tim011_state::tim011_io);
|
||||
m_maincpu->tend1_wr_callback().set(m_fdc, FUNC(upd765a_device::tc_line_w));
|
||||
m_maincpu->txa1_wr_callback().set("rs232", FUNC(rs232_port_device::write_txd));
|
||||
|
||||
// CDP1802(config, "keyboard", XTAL(1'750'000)); // CDP1802, unknown clock
|
||||
|
||||
@ -179,6 +189,10 @@ void tim011_state::tim011(machine_config &config)
|
||||
screen.set_visarea(0, 512-1, 0, 256-1);
|
||||
screen.set_screen_update(FUNC(tim011_state::screen_update_tim011));
|
||||
screen.set_palette(m_palette);
|
||||
|
||||
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "keyboard"));
|
||||
rs232.set_option_device_input_defaults("keyboard", DEVICE_INPUT_DEFAULTS_NAME(keyboard));
|
||||
rs232.rxd_handler().set(m_maincpu, FUNC(z180_device::rxa1_w));
|
||||
}
|
||||
|
||||
/* ROM definition */
|
||||
|
@ -12,10 +12,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpu/z180/z180.h"
|
||||
#include "machine/eepromser.h"
|
||||
#include "machine/intelfsh.h"
|
||||
#include "sound/dac.h"
|
||||
#include "sound/namco.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "emupal.h"
|
||||
|
||||
class _20pacgal_state : public driver_device
|
||||
@ -33,7 +35,8 @@ public:
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_eeprom(*this, "eeprom"),
|
||||
m_palette(*this, "palette"),
|
||||
m_dac(*this, "dac")
|
||||
m_dac(*this, "dac"),
|
||||
m_rs232(*this, "rs232")
|
||||
{ }
|
||||
|
||||
void _20pacgal(machine_config &config);
|
||||
@ -57,10 +60,11 @@ protected:
|
||||
uint8_t m_game_selected = 0; /* 0 = Ms. Pac-Man, 1 = Galaga */
|
||||
|
||||
/* devices */
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<z180_device> m_maincpu;
|
||||
required_device<eeprom_serial_93cxx_device> m_eeprom;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<dac_8bit_r2r_device> m_dac;
|
||||
required_device<rs232_port_device> m_rs232;
|
||||
|
||||
/* memory */
|
||||
std::unique_ptr<uint8_t[]> m_sprite_gfx_ram;
|
||||
|
@ -37551,6 +37551,9 @@ savia84 //
|
||||
@source:savquest.cpp
|
||||
savquest //
|
||||
|
||||
@source:sb180.cpp
|
||||
sb180 //
|
||||
|
||||
@source:sb8085.cpp
|
||||
sb8085 //
|
||||
|
||||
|
@ -946,6 +946,7 @@ sapi1.cpp
|
||||
sartorius.cpp
|
||||
saturn.cpp
|
||||
savia84.cpp
|
||||
sb180.cpp
|
||||
sb8085.cpp
|
||||
sbc6510.cpp
|
||||
sbrain.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user