diff options
Diffstat (limited to 'src/devices/machine/mc68681.cpp')
-rw-r--r-- | src/devices/machine/mc68681.cpp | 157 |
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; |