summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/mc68681.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/mc68681.cpp')
-rw-r--r--src/devices/machine/mc68681.cpp157
1 files changed, 127 insertions, 30 deletions
diff --git a/src/devices/machine/mc68681.cpp b/src/devices/machine/mc68681.cpp
index 577b9355c39..2f79b82da1b 100644
--- a/src/devices/machine/mc68681.cpp
+++ b/src/devices/machine/mc68681.cpp
@@ -1,7 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:Mariusz Wojcieszek, R. Belmont
/*
+ 2681 DUART
68681 DUART
+ 28C94 QUART
Written by Mariusz Wojcieszek
Updated by Jonathan Gevaryahu AKA Lord Nightmare
@@ -50,9 +52,12 @@ static const int baud_rate_ACR_1[] = { 75, 110, 134, 150, 300, 600, 1200, 2000,
#define CHANA_TAG "cha"
#define CHANB_TAG "chb"
+#define CHANC_TAG "chc"
+#define CHAND_TAG "chd"
// device type definition
const device_type MC68681 = &device_creator<mc68681_device>;
+const device_type SC28C94 = &device_creator<sc28c94_device>;
const device_type MC68681_CHANNEL = &device_creator<mc68681_channel>;
MACHINE_CONFIG_FRAGMENT( duart68681 )
@@ -60,17 +65,28 @@ MACHINE_CONFIG_FRAGMENT( duart68681 )
MCFG_DEVICE_ADD(CHANB_TAG, MC68681_CHANNEL, 0)
MACHINE_CONFIG_END
+MACHINE_CONFIG_FRAGMENT( quart28c94 )
+ MCFG_DEVICE_ADD(CHANA_TAG, MC68681_CHANNEL, 0)
+ MCFG_DEVICE_ADD(CHANB_TAG, MC68681_CHANNEL, 0)
+ MCFG_DEVICE_ADD(CHANC_TAG, MC68681_CHANNEL, 0)
+ MCFG_DEVICE_ADD(CHAND_TAG, MC68681_CHANNEL, 0)
+MACHINE_CONFIG_END
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
-mc68681_device::mc68681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MC68681, "MC68681 DUART", tag, owner, clock, "mc68681", __FILE__),
+mc68681_base_device::mc68681_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
m_chanA(*this, CHANA_TAG),
m_chanB(*this, CHANB_TAG),
+ m_chanC(*this, CHANC_TAG),
+ m_chanD(*this, CHAND_TAG),
write_irq(*this),
write_a_tx(*this),
write_b_tx(*this),
+ write_c_tx(*this),
+ write_d_tx(*this),
read_inport(*this),
write_outport(*this),
ip3clk(0),
@@ -83,14 +99,24 @@ mc68681_device::mc68681_device(const machine_config &mconfig, const char *tag, d
{
}
+mc68681_device::mc68681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mc68681_base_device(mconfig, MC68681, "MC68681 DUART", tag, owner, clock, "mc68681", __FILE__)
+{
+}
+
+sc28c94_device::sc28c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mc68681_base_device(mconfig, SC28C94, "SC28C94 QUART", tag, owner, clock, "sc28c94", __FILE__)
+{
+}
+
//-------------------------------------------------
// static_set_clocks - configuration helper to set
// the external clocks
//-------------------------------------------------
-void mc68681_device::static_set_clocks(device_t &device, int clk3, int clk4, int clk5, int clk6)
+void mc68681_base_device::static_set_clocks(device_t &device, int clk3, int clk4, int clk5, int clk6)
{
- mc68681_device &duart = downcast<mc68681_device &>(device);
+ mc68681_base_device &duart = downcast<mc68681_base_device &>(device);
duart.ip3clk = clk3;
duart.ip4clk = clk4;
duart.ip5clk = clk5;
@@ -101,15 +127,17 @@ void mc68681_device::static_set_clocks(device_t &device, int clk3, int clk4, int
device start callback
-------------------------------------------------*/
-void mc68681_device::device_start()
+void mc68681_base_device::device_start()
{
write_irq.resolve_safe();
write_a_tx.resolve_safe();
write_b_tx.resolve_safe();
+ write_c_tx.resolve_safe();
+ write_d_tx.resolve_safe();
read_inport.resolve();
write_outport.resolve_safe();
- duart_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mc68681_device::duart_timer_callback),this), nullptr);
+ duart_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mc68681_base_device::duart_timer_callback),this), nullptr);
save_item(NAME(ACR));
save_item(NAME(IMR));
@@ -125,7 +153,7 @@ void mc68681_device::device_start()
device reset callback
-------------------------------------------------*/
-void mc68681_device::device_reset()
+void mc68681_base_device::device_reset()
{
ACR = 0; /* Interrupt Vector Register */
IVR = 0x0f; /* Interrupt Vector Register */
@@ -141,12 +169,17 @@ void mc68681_device::device_reset()
write_outport(OPR ^ 0xff);
}
-machine_config_constructor mc68681_device::device_mconfig_additions() const
+machine_config_constructor mc68681_base_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( duart68681 );
}
-void mc68681_device::update_interrupts()
+machine_config_constructor sc28c94_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( quart28c94 );
+}
+
+void mc68681_base_device::update_interrupts()
{
/* update SR state and update interrupt ISR state for the following bits:
SRn: bits 7-4: handled elsewhere.
@@ -208,7 +241,7 @@ void mc68681_device::update_interrupts()
}
}
-double mc68681_device::duart68681_get_ct_rate()
+double mc68681_base_device::duart68681_get_ct_rate()
{
double rate = 0.0f;
@@ -250,19 +283,19 @@ double mc68681_device::duart68681_get_ct_rate()
return rate;
}
-uint16_t mc68681_device::duart68681_get_ct_count()
+uint16_t mc68681_base_device::duart68681_get_ct_count()
{
double clock = duart68681_get_ct_rate();
return (duart_timer->remaining() * clock).as_double();
}
-void mc68681_device::duart68681_start_ct(int count)
+void mc68681_base_device::duart68681_start_ct(int count)
{
double clock = duart68681_get_ct_rate();
duart_timer->adjust(attotime::from_hz(clock) * count, 0);
}
-TIMER_CALLBACK_MEMBER( mc68681_device::duart_timer_callback )
+TIMER_CALLBACK_MEMBER( mc68681_base_device::duart_timer_callback )
{
if (ACR & 0x40)
{
@@ -320,13 +353,41 @@ TIMER_CALLBACK_MEMBER( mc68681_device::duart_timer_callback )
}
-READ8_MEMBER( mc68681_device::read )
+READ8_MEMBER( sc28c94_device::read )
+{
+ uint8_t r = 0;
+ offset &= 0x1f;
+
+ if (offset < 0x10)
+ {
+ return mc68681_base_device::read(space, offset, mem_mask);
+ }
+
+ switch (offset)
+ {
+ case 0x10: /* MR1A/MR2C */
+ case 0x11: /* SRC */
+ case 0x13: /* Rx Holding Register C */
+ r = m_chanC->read_chan_reg(offset & 3);
+ break;
+
+ case 0x18: /* MR1D/MR2D */
+ case 0x19: /* SRD */
+ case 0x1b: /* RHRD */
+ r = m_chanD->read_chan_reg(offset & 3);
+ break;
+ }
+
+ return r;
+}
+
+READ8_MEMBER( mc68681_base_device::read )
{
uint8_t r = 0xff;
offset &= 0xf;
- LOG(( "Reading 68681 (%s) reg %x (%s) ", tag(), offset, duart68681_reg_read_names[offset] ));
+ LOG(( "Reading 68681 (%s) reg %x (%s)\n", tag(), offset, duart68681_reg_read_names[offset] ));
switch (offset)
{
@@ -424,7 +485,34 @@ READ8_MEMBER( mc68681_device::read )
return r;
}
-WRITE8_MEMBER( mc68681_device::write )
+WRITE8_MEMBER( sc28c94_device::write )
+{
+ offset &= 0x1f;
+
+ if (offset < 0x10)
+ {
+ mc68681_base_device::write(space, offset, data, mem_mask);
+ }
+
+ switch(offset)
+ {
+ case 0x10: /* MRC */
+ case 0x11: /* CSRC */
+ case 0x12: /* CRC */
+ case 0x13: /* THRC */
+ m_chanC->write_chan_reg(offset&3, data);
+ break;
+
+ case 0x18: /* MRC */
+ case 0x19: /* CSRC */
+ case 0x1a: /* CRC */
+ case 0x1b: /* THRC */
+ m_chanD->write_chan_reg(offset&3, data);
+ break;
+ }
+}
+
+WRITE8_MEMBER( mc68681_base_device::write )
{
offset &= 0x0f;
LOG(( "Writing 68681 (%s) reg %x (%s) with %04x\n", tag(), offset, duart68681_reg_write_names[offset], data ));
@@ -516,7 +604,7 @@ WRITE8_MEMBER( mc68681_device::write )
}
}
-WRITE_LINE_MEMBER( mc68681_device::ip0_w )
+WRITE_LINE_MEMBER( mc68681_base_device::ip0_w )
{
uint8_t newIP = (IP_last_state & ~0x01) | ((state == ASSERT_LINE) ? 1 : 0);
@@ -536,7 +624,7 @@ WRITE_LINE_MEMBER( mc68681_device::ip0_w )
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER( mc68681_device::ip1_w )
+WRITE_LINE_MEMBER( mc68681_base_device::ip1_w )
{
uint8_t newIP = (IP_last_state & ~0x02) | ((state == ASSERT_LINE) ? 2 : 0);
@@ -556,7 +644,7 @@ WRITE_LINE_MEMBER( mc68681_device::ip1_w )
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER( mc68681_device::ip2_w )
+WRITE_LINE_MEMBER( mc68681_base_device::ip2_w )
{
uint8_t newIP = (IP_last_state & ~0x04) | ((state == ASSERT_LINE) ? 4 : 0);
@@ -576,7 +664,7 @@ WRITE_LINE_MEMBER( mc68681_device::ip2_w )
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER( mc68681_device::ip3_w )
+WRITE_LINE_MEMBER( mc68681_base_device::ip3_w )
{
uint8_t newIP = (IP_last_state & ~0x08) | ((state == ASSERT_LINE) ? 8 : 0);
@@ -596,21 +684,21 @@ WRITE_LINE_MEMBER( mc68681_device::ip3_w )
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER( mc68681_device::ip4_w )
+WRITE_LINE_MEMBER( mc68681_base_device::ip4_w )
{
uint8_t newIP = (IP_last_state & ~0x10) | ((state == ASSERT_LINE) ? 0x10 : 0);
// TODO: special mode for ip4 (Ch. A Rx clock)
IP_last_state = newIP;
}
-WRITE_LINE_MEMBER( mc68681_device::ip5_w )
+WRITE_LINE_MEMBER( mc68681_base_device::ip5_w )
{
uint8_t newIP = (IP_last_state & ~0x20) | ((state == ASSERT_LINE) ? 0x20 : 0);
// TODO: special mode for ip5 (Ch. B Tx clock)
IP_last_state = newIP;
}
-mc68681_channel *mc68681_device::get_channel(int chan)
+mc68681_channel *mc68681_base_device::get_channel(int chan)
{
if (chan == 0)
{
@@ -620,7 +708,7 @@ mc68681_channel *mc68681_device::get_channel(int chan)
return m_chanB;
}
-int mc68681_device::calc_baud(int ch, uint8_t data)
+int mc68681_base_device::calc_baud(int ch, uint8_t data)
{
int baud_rate;
@@ -661,15 +749,16 @@ int mc68681_device::calc_baud(int ch, uint8_t data)
LOG(( "Unsupported transmitter clock: channel %d, clock select = %02x\n", ch, data ));
}
+ //printf("%s ch %d setting baud to %d\n", tag(), ch, baud_rate);
return baud_rate;
}
-void mc68681_device::clear_ISR_bits(int mask)
+void mc68681_base_device::clear_ISR_bits(int mask)
{
ISR &= ~mask;
}
-void mc68681_device::set_ISR_bits(int mask)
+void mc68681_base_device::set_ISR_bits(int mask)
{
ISR |= mask;
}
@@ -690,7 +779,7 @@ mc68681_channel::mc68681_channel(const machine_config &mconfig, const char *tag,
void mc68681_channel::device_start()
{
- m_uart = downcast<mc68681_device *>(owner());
+ m_uart = downcast<mc68681_base_device *>(owner());
m_ch = m_uart->get_ch(this); // get our channel number
save_item(NAME(CR));
@@ -793,15 +882,23 @@ void mc68681_channel::tra_callback()
if ((MR2&0xC0) != 0x80)
{
int bit = transmit_register_get_data_bit();
-// printf("%s ch %d transmit %d\n", tag(), m_ch, bit);
+ //printf("%s ch %d transmit %d\n", tag(), m_ch, bit);
if (m_ch == 0)
{
m_uart->write_a_tx(bit);
}
- else
+ else if (m_ch == 1)
{
m_uart->write_b_tx(bit);
}
+ else if (m_ch == 2)
+ {
+ m_uart->write_c_tx(bit);
+ }
+ else if (m_ch == 3)
+ {
+ m_uart->write_d_tx(bit);
+ }
}
else // must call this to advance the transmitter
{
@@ -1157,7 +1254,7 @@ void mc68681_channel::write_TX(uint8_t data)
printf("Write %02x to TX when TX not ready!\n", data);
}*/
-// printf("%s ch %d Tx %02x\n", tag(), m_ch, data);
+ //printf("%s ch %d Tx %02x\n", tag(), m_ch, data);
tx_ready = 0;
SR &= ~STATUS_TRANSMITTER_READY;