summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/z180/z180.cpp256
-rw-r--r--src/devices/cpu/z180/z180.h26
-rw-r--r--src/devices/cpu/z180/z180asci.cpp702
-rw-r--r--src/devices/cpu/z180/z180asci.h201
-rw-r--r--src/mame/drivers/20pacgal.cpp24
-rw-r--r--src/mame/drivers/sb180.cpp124
-rw-r--r--src/mame/drivers/tim011.cpp14
-rw-r--r--src/mame/includes/20pacgal.h8
-rw-r--r--src/mame/mame.lst3
-rw-r--r--src/mame/mess.flt1
10 files changed, 1136 insertions, 223 deletions
diff --git a/src/devices/cpu/z180/z180.cpp b/src/devices/cpu/z180/z180.cpp
index 6c68b877bca..db7b4a3026b 100644
--- a/src/devices/cpu/z180/z180.cpp
+++ b/src/devices/cpu/z180/z180.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;
}
diff --git a/src/devices/cpu/z180/z180.h b/src/devices/cpu/z180/z180.h
index 94b95d1488e..62213845b05 100644
--- a/src/devices/cpu/z180/z180.h
+++ b/src/devices/cpu/z180/z180.h
@@ -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
};
diff --git a/src/devices/cpu/z180/z180asci.cpp b/src/devices/cpu/z180/z180asci.cpp
new file mode 100644
index 00000000000..69c225accaa
--- /dev/null
+++ b/src/devices/cpu/z180/z180asci.cpp
@@ -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")
diff --git a/src/devices/cpu/z180/z180asci.h b/src/devices/cpu/z180/z180asci.h
new file mode 100644
index 00000000000..3794fe635a8
--- /dev/null
+++ b/src/devices/cpu/z180/z180asci.h
@@ -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
diff --git a/src/mame/drivers/20pacgal.cpp b/src/mame/drivers/20pacgal.cpp
index 94ab22a608a..762873f99f1 100644
--- a/src/mame/drivers/20pacgal.cpp
+++ b/src/mame/drivers/20pacgal.cpp
@@ -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");
}
diff --git a/src/mame/drivers/sb180.cpp b/src/mame/drivers/sb180.cpp
new file mode 100644
index 00000000000..80d3f2a180b
--- /dev/null
+++ b/src/mame/drivers/sb180.cpp
@@ -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)
diff --git a/src/mame/drivers/tim011.cpp b/src/mame/drivers/tim011.cpp
index 66234dbea39..bef566f56b3 100644
--- a/src/mame/drivers/tim011.cpp
+++ b/src/mame/drivers/tim011.cpp
@@ -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 */
diff --git a/src/mame/includes/20pacgal.h b/src/mame/includes/20pacgal.h
index 8d03e964985..77c74f6948f 100644
--- a/src/mame/includes/20pacgal.h
+++ b/src/mame/includes/20pacgal.h
@@ -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;
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 68e8dad0378..017c66a5dc6 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -37551,6 +37551,9 @@ savia84 //
@source:savquest.cpp
savquest //
+@source:sb180.cpp
+sb180 //
+
@source:sb8085.cpp
sb8085 //
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index 0f7c8b6f2a4..29d6941871c 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -946,6 +946,7 @@ sapi1.cpp
sartorius.cpp
saturn.cpp
savia84.cpp
+sb180.cpp
sb8085.cpp
sbc6510.cpp
sbrain.cpp