From 5ac1220284792c6bb76e22c91082078bbfbbc504 Mon Sep 17 00:00:00 2001 From: mamehaze Date: Tue, 10 Mar 2015 11:40:07 +0000 Subject: the V53 SCU is a i8251 clone, but with the command / mode registers separated, and only Asynchronous transfer mode available, this splits the function into something we can use for that purpose (nw) --- src/emu/cpu/nec/v53.c | 72 ++---- src/emu/cpu/nec/v53.h | 13 +- src/emu/machine/am9517a.c | 14 +- src/emu/machine/am9517a.h | 2 +- src/emu/machine/i8251.c | 542 +++++++++++++++++++++++++--------------------- src/emu/machine/i8251.h | 14 ++ 6 files changed, 342 insertions(+), 315 deletions(-) diff --git a/src/emu/cpu/nec/v53.c b/src/emu/cpu/nec/v53.c index 812f652717a..f7c460dbf3d 100644 --- a/src/emu/cpu/nec/v53.c +++ b/src/emu/cpu/nec/v53.c @@ -3,7 +3,7 @@ // V33 / V33A cores with onboard peripherals // Interrupt Controller is uPD71059 equivalent (a PIC8259 clone?) -// DMA Controller can operate in modes providing a subset of the uPD71071 or uPD71037 functionality (some modes unavailable / settings ignored) (uPD71071 mode is an extended am9517a, uPD71037 mode is ??) +// DMA Controller can operate in modes providing a subset of the uPD71071 or uPD71037 functionality (some modes unavailable / settings ignored) (uPD71071 mode is an extended 8237A, uPD71037 mode is plain 8237A) // Serial Controller is based on the uPD71051 but with some changes (i8251 clone?) // Timer Unit is functionally identical to uPD71054 (which in turn is said to be the same as a pit8253) @@ -216,7 +216,7 @@ void v53_base_device::install_peripheral_io() } else // uPD71071 mode { - space(AS_IO).install_readwrite_handler(base+0x00, base+0x0f, read8_delegate(FUNC(upd71071_v53_device::read), (upd71071_v53_device*)m_dma_71071mode), write8_delegate(FUNC(upd71071_v53_device::write), (upd71071_v53_device*)m_dma_71071mode), 0xffff); + space(AS_IO).install_readwrite_handler(base+0x00, base+0x0f, read8_delegate(FUNC(upd71071_v53_device::read), (upd71071_v53_device*)m_v53dmau), write8_delegate(FUNC(upd71071_v53_device::write), (upd71071_v53_device*)m_v53dmau), 0xffff); } } @@ -231,9 +231,7 @@ void v53_base_device::install_peripheral_io() } else { - space(AS_IO).install_readwrite_handler(base+0x00, base+0x01, read8_delegate(FUNC(v53_base_device::icu_0_r), this), write8_delegate(FUNC(v53_base_device::icu_0_w), this), 0x00ff); - space(AS_IO).install_readwrite_handler(base+0x02, base+0x03, read8_delegate(FUNC(v53_base_device::icu_1_r), this), write8_delegate(FUNC(v53_base_device::icu_1_w), this), 0x00ff); - + space(AS_IO).install_readwrite_handler(base+0x00, base+0x03, read8_delegate(FUNC(pic8259_device::read), (pic8259_device*)m_v53icu), write8_delegate(FUNC(pic8259_device::write), (pic8259_device*)m_v53icu), 0x00ff); } } @@ -277,31 +275,7 @@ void v53_base_device::install_peripheral_io() } -/*** ICU ***/ - - - -READ8_MEMBER(v53_base_device::icu_0_r) -{ - printf("v53: icu_0_r\n"); - return 0; -} - -WRITE8_MEMBER(v53_base_device::icu_0_w) -{ - printf("v53: icu_0_w %02x\n", data); -} - -READ8_MEMBER(v53_base_device::icu_1_r) -{ - printf("v53: icu_1_r\n"); - return 0; -} -WRITE8_MEMBER(v53_base_device::icu_1_w) -{ - printf("v53: icu_1_w %02x\n", data); -} /*** SCU ***/ @@ -346,15 +320,15 @@ WRITE8_MEMBER(v53_base_device::scu_simk_w) /*** TCU ***/ -WRITE8_MEMBER(v53_base_device::tmu_tct0_w) { m_pit->write(space, 0, data); } -WRITE8_MEMBER(v53_base_device::tmu_tct1_w) { m_pit->write(space, 1, data); } -WRITE8_MEMBER(v53_base_device::tmu_tct2_w) { m_pit->write(space, 2, data); } -WRITE8_MEMBER(v53_base_device::tmu_tmd_w) { m_pit->write(space, 3, data); } +WRITE8_MEMBER(v53_base_device::tmu_tct0_w) { m_v53tcu->write(space, 0, data); } +WRITE8_MEMBER(v53_base_device::tmu_tct1_w) { m_v53tcu->write(space, 1, data); } +WRITE8_MEMBER(v53_base_device::tmu_tct2_w) { m_v53tcu->write(space, 2, data); } +WRITE8_MEMBER(v53_base_device::tmu_tmd_w) { m_v53tcu->write(space, 3, data); } -READ8_MEMBER(v53_base_device::tmu_tst0_r) { return m_pit->read(space, 0); } -READ8_MEMBER(v53_base_device::tmu_tst1_r) { return m_pit->read(space, 1); } -READ8_MEMBER(v53_base_device::tmu_tst2_r) { return m_pit->read(space, 2); } +READ8_MEMBER(v53_base_device::tmu_tst0_r) { return m_v53tcu->read(space, 0); } +READ8_MEMBER(v53_base_device::tmu_tst1_r) { return m_v53tcu->read(space, 1); } +READ8_MEMBER(v53_base_device::tmu_tst2_r) { return m_v53tcu->read(space, 2); } /*** DMA ***/ @@ -363,7 +337,7 @@ WRITE_LINE_MEMBER(v53_base_device::dreq0_trampoline_w) { if (!(m_SCTL & 0x02)) { - m_dma_71071mode->dreq0_w(state); + m_v53dmau->dreq0_w(state); } else { @@ -375,7 +349,7 @@ WRITE_LINE_MEMBER(v53_base_device::dreq1_trampoline_w) { if (!(m_SCTL & 0x02)) { - m_dma_71071mode->dreq1_w(state); + m_v53dmau->dreq1_w(state); } else { @@ -387,7 +361,7 @@ WRITE_LINE_MEMBER(v53_base_device::dreq2_trampoline_w) { if (!(m_SCTL & 0x02)) { - m_dma_71071mode->dreq2_w(state); + m_v53dmau->dreq2_w(state); } else { @@ -399,7 +373,7 @@ WRITE_LINE_MEMBER(v53_base_device::dreq3_trampoline_w) { if (!(m_SCTL & 0x02)) { - m_dma_71071mode->dreq3_w(state); + m_v53dmau->dreq3_w(state); } else { @@ -411,7 +385,7 @@ WRITE_LINE_MEMBER(v53_base_device::hack_trampoline_w) { if (!(m_SCTL & 0x02)) { - m_dma_71071mode->hack_w(state); + m_v53dmau->hack_w(state); } else { @@ -459,7 +433,7 @@ ADDRESS_MAP_END WRITE_LINE_MEMBER(v53_base_device::dma_hrq_changed) { // pass this back to the driver? / expose externally? - m_dma_71071mode->hack_w(state); + m_v53dmau->hack_w(state); } WRITE8_MEMBER(v53_base_device::dma_io_3_w) @@ -481,7 +455,7 @@ READ8_MEMBER(v53_base_device::get_pic_ack) WRITE_LINE_MEMBER( v53_base_device::upd71059_irq_w) { - printf("upd71059_irq_w %d", state); + printf("upd71059_irq_w %d\n", state); } static MACHINE_CONFIG_FRAGMENT( v53 ) @@ -489,7 +463,7 @@ static MACHINE_CONFIG_FRAGMENT( v53 ) MCFG_PIT8253_CLK0(16000000/2/8) //MCFG_PIT8253_OUT0_HANDLER(WRITELINE(v53_base_device, pit_out0)) - MCFG_DEVICE_ADD("upd71071dma", UPD71071_V53, 4000000) + MCFG_DEVICE_ADD("upd71071dma", V53_DMAU, 4000000) MCFG_I8237_OUT_HREQ_CB(WRITELINE(v53_base_device, dma_hrq_changed)) MCFG_I8237_OUT_IOW_3_CB(WRITE8(v53_base_device, dma_io_3_w)) MCFG_I8237_IN_MEMR_CB(READ8(v53_base_device, dma_memin_r)) @@ -497,7 +471,7 @@ static MACHINE_CONFIG_FRAGMENT( v53 ) MCFG_PIC8259_ADD( "upd71059pic", WRITELINE(v53_base_device, upd71059_irq_w), VCC, READ8(v53_base_device,get_pic_ack)) - MCFG_DEVICE_ADD("upd71051", I8251, 0) + MCFG_DEVICE_ADD("v53scu", V53_SCU, 0) MACHINE_CONFIG_END @@ -510,10 +484,10 @@ machine_config_constructor v53_base_device::device_mconfig_additions() const v53_base_device::v53_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, offs_t fetch_xor, UINT8 prefetch_size, UINT8 prefetch_cycles, UINT32 chip_type) : nec_common_device(mconfig, type, name, tag, owner, clock, shortname, true, fetch_xor, prefetch_size, prefetch_cycles, chip_type), m_io_space_config( "io", ENDIANNESS_LITTLE, 16, 16, 0, ADDRESS_MAP_NAME( v53_internal_port_map ) ), - m_pit(*this, "pit"), - m_dma_71071mode(*this, "upd71071dma"), - m_upd71059(*this, "upd71059pic"), - m_upd71051(*this, "upd71051") + m_v53tcu(*this, "pit"), + m_v53dmau(*this, "upd71071dma"), + m_v53icu(*this, "upd71059pic"), + m_v53scu(*this, "v53scu") { } diff --git a/src/emu/cpu/nec/v53.h b/src/emu/cpu/nec/v53.h index a298f266862..1f2cd3fffd2 100644 --- a/src/emu/cpu/nec/v53.h +++ b/src/emu/cpu/nec/v53.h @@ -62,11 +62,6 @@ public: DECLARE_READ8_MEMBER(scu_simk_r); DECLARE_WRITE8_MEMBER(scu_simk_w); - // ICU - DECLARE_READ8_MEMBER(icu_0_r); - DECLARE_WRITE8_MEMBER(icu_0_w); - DECLARE_READ8_MEMBER(icu_1_r); - DECLARE_WRITE8_MEMBER(icu_1_w); void install_peripheral_io(); @@ -81,10 +76,10 @@ public: } } - required_device m_pit; - required_device m_dma_71071mode; - required_device m_upd71059; - required_device m_upd71051; + required_device m_v53tcu; + required_device m_v53dmau; + required_device m_v53icu; + required_device m_v53scu; DECLARE_WRITE_LINE_MEMBER(dreq0_trampoline_w); DECLARE_WRITE_LINE_MEMBER(dreq1_trampoline_w); diff --git a/src/emu/machine/am9517a.c b/src/emu/machine/am9517a.c index f5f66309848..0104ff077d6 100644 --- a/src/emu/machine/am9517a.c +++ b/src/emu/machine/am9517a.c @@ -4,7 +4,12 @@ AMD AM9517A Intel 8237A - NEC UPD71071 + NEC uPD71037 + + NEC uPD71071 (extended version of above) + + a variant is used in the V53 CPU which offers subsets of both the + uPD71071 and uPD71037 functionality depending on a mode bit. Multimode DMA Controller emulation @@ -17,7 +22,6 @@ TODO: - - memory-to-memory transfer - external EOP */ @@ -47,7 +51,7 @@ //************************************************************************** const device_type AM9517A = &device_creator; -const device_type UPD71071_V53 = &device_creator; +const device_type V53_DMAU = &device_creator; //************************************************************************** @@ -471,7 +475,7 @@ inline void am9517a_device::end_of_process() am9517a_device::am9517a_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname) - : device_t(mconfig, AM9517A, name, tag, owner, clock, shortname, __FILE__), + : device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__), device_execute_interface(mconfig, *this), m_icount(0), m_hack(0), @@ -525,7 +529,7 @@ am9517a_device::am9517a_device(const machine_config &mconfig, const char *tag, d } upd71071_v53_device::upd71071_v53_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : am9517a_device(mconfig, UPD71071_V53, "UPD71071 (V53)", tag, owner, clock, "upd71071_v53") + : am9517a_device(mconfig, V53_DMAU, "V53 DMAU", tag, owner, clock, "v53_dmau") { } diff --git a/src/emu/machine/am9517a.h b/src/emu/machine/am9517a.h index e665a108f00..3a0eb2a6432 100644 --- a/src/emu/machine/am9517a.h +++ b/src/emu/machine/am9517a.h @@ -183,7 +183,7 @@ protected: // device type definition extern const device_type AM9517A; -extern const device_type UPD71071_V53; +extern const device_type V53_DMAU; /*************************************************************************** diff --git a/src/emu/machine/i8251.c b/src/emu/machine/i8251.c index 07e3edd8ad6..59da201a4d5 100644 --- a/src/emu/machine/i8251.c +++ b/src/emu/machine/i8251.c @@ -3,6 +3,12 @@ i8251.c Intel 8251 Universal Synchronous/Asynchronous Receiver Transmitter code + NEC uPD71051 is a clone + + The V53/V53A use a customized version with only the Asynchronous mode + and a split command / mode register + + *********************************************************************/ @@ -23,11 +29,30 @@ //************************************************************************** const device_type I8251 = &device_creator; +const device_type V53_SCU = &device_creator; //------------------------------------------------- // i8251_device - constructor //------------------------------------------------- +i8251_device::i8251_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname) + : device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__), + device_serial_interface(mconfig, *this), + m_txd_handler(*this), + m_dtr_handler(*this), + m_rts_handler(*this), + m_rxrdy_handler(*this), + m_txrdy_handler(*this), + m_txempty_handler(*this), + m_syndet_handler(*this), + m_cts(1), + m_dsr(1), + m_rxd(0), + m_rxc(0), + m_txc(0) +{ +} + i8251_device::i8251_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, I8251, "8251 USART", tag, owner, clock, "i8251", __FILE__), device_serial_interface(mconfig, *this), @@ -46,6 +71,12 @@ i8251_device::i8251_device(const machine_config &mconfig, const char *tag, devic { } +v53_scu_device::v53_scu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : i8251_device(mconfig, V53_SCU, "V53 SCU", tag, owner, clock, "v53_scu") +{ +} + + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -325,302 +356,311 @@ void i8251_device::device_reset() control_w -------------------------------------------------*/ -WRITE8_MEMBER(i8251_device::control_w) +WRITE8_MEMBER(i8251_device::command_w) { - if (m_flags & I8251_EXPECTING_MODE) + /* command */ + LOG(("I8251: Command byte\n")); + + m_command = data; + + LOG(("Command byte: %02x\n", data)); + + if (data & (1<<7)) { - if (m_flags & I8251_EXPECTING_SYNC_BYTE) - { - LOG(("I8251: Sync byte\n")); + LOG(("hunt mode\n")); + } - LOG(("Sync byte: %02x\n", data)); - /* store sync byte written */ - m_sync_bytes[m_sync_byte_offset] = data; - m_sync_byte_offset++; + if (data & (1<<5)) + { + LOG(("/rts set to 0\n")); + } + else + { + LOG(("/rts set to 1\n")); + } - if (m_sync_byte_offset == m_sync_byte_count) + if (data & (1<<2)) + { + LOG(("receive enable\n")); + } + else + { + LOG(("receive disable\n")); + } + + if (data & (1<<1)) + { + LOG(("/dtr set to 0\n")); + } + else + { + LOG(("/dtr set to 1\n")); + } + + if (data & (1<<0)) + { + LOG(("transmit enable\n")); + + /* if we get a tx enable with a disable pending, cancel the disable */ + m_disable_tx_pending = false; + } + else + { + if (m_tx_busy) + { + if (!m_disable_tx_pending) { - /* finished transfering sync bytes, now expecting command */ - m_flags &= ~(I8251_EXPECTING_MODE | I8251_EXPECTING_SYNC_BYTE); - m_sync_byte_offset = 0; - // m_status = I8251_STATUS_TX_EMPTY | I8251_STATUS_TX_READY; + LOG(("Tx busy, set pending disable\n")); } + m_disable_tx_pending = true; + m_command |= (1<<0); } else { - LOG(("I8251: Mode byte\n")); - - m_mode_byte = data; - - /* Synchronous or Asynchronous? */ - if ((data & 0x03)!=0) + LOG(("transmit disable\n")); + if ((data & (1<<0))==0) { - /* Asynchronous - - bit 7,6: stop bit length - 0 = inhibit - 1 = 1 bit - 2 = 1.5 bits - 3 = 2 bits - bit 5: parity type - 0 = parity odd - 1 = parity even - bit 4: parity test enable - 0 = disable - 1 = enable - bit 3,2: character length - 0 = 5 bits - 1 = 6 bits - 2 = 7 bits - 3 = 8 bits - bit 1,0: baud rate factor - 0 = defines command byte for synchronous or asynchronous - 1 = x1 - 2 = x16 - 3 = x64 - */ - - LOG(("I8251: Asynchronous operation\n")); - - LOG(("Character length: %d\n", (((data>>2) & 0x03)+5))); - - parity_t parity; - - if (data & (1<<4)) - { - LOG(("enable parity checking\n")); - - if (data & (1<<5)) - { - LOG(("even parity\n")); - parity = PARITY_EVEN; - } - else - { - LOG(("odd parity\n")); - parity = PARITY_ODD; - } - } - else - { - LOG(("parity check disabled\n")); - parity = PARITY_NONE; - } - - stop_bits_t stop_bits; - - switch ((data>>6) & 0x03) - { - case 0: - default: - stop_bits = STOP_BITS_0; - LOG(("stop bit: inhibit\n")); - break; - - case 1: - stop_bits = STOP_BITS_1; - LOG(("stop bit: 1 bit\n")); - break; - - case 2: - stop_bits = STOP_BITS_1_5; - LOG(("stop bit: 1.5 bits\n")); - break; - - case 3: - stop_bits = STOP_BITS_2; - LOG(("stop bit: 2 bits\n")); - break; - } - - int data_bits_count = ((data>>2) & 0x03)+5; - - set_data_frame(1, data_bits_count, parity, stop_bits); - receive_register_reset(); - - switch (data & 0x03) - { - case 1: m_br_factor = 1; break; - case 2: m_br_factor = 16; break; - case 3: m_br_factor = 64; break; - } - - m_rxc_count = m_txc_count = 0; - -#if 0 - /* data bits */ - m_receive_char_length = (((data>>2) & 0x03)+5); - - if (data & (1<<4)) - { - /* parity */ - m_receive_char_length++; - } + /* held in high state when transmit disable */ + m_txd_handler(1); + } + } + } - /* stop bits */ - m_receive_char_length++; - m_receive_flags &=~I8251_TRANSFER_RECEIVE_SYNCHRONISED; - m_receive_flags |= I8251_TRANSFER_RECEIVE_WAITING_FOR_START_BIT; -#endif - /* not expecting mode byte now */ - m_flags &= ~I8251_EXPECTING_MODE; -// m_status = I8251_STATUS_TX_EMPTY | I8251_STATUS_TX_READY; - } - else - { - /* bit 7: Number of sync characters - 0 = 1 character - 1 = 2 character - bit 6: Synchronous mode - 0 = Internal synchronisation - 1 = External synchronisation - bit 5: parity type - 0 = parity odd - 1 = parity even - bit 4: parity test enable - 0 = disable - 1 = enable - bit 3,2: character length - 0 = 5 bits - 1 = 6 bits - 2 = 7 bits - 3 = 8 bits - bit 1,0 = 0 - */ - LOG(("I8251: Synchronous operation\n")); + /* bit 7: + 0 = normal operation + 1 = hunt mode + bit 6: + 0 = normal operation + 1 = internal reset + bit 5: + 0 = /RTS set to 1 + 1 = /RTS set to 0 + bit 4: + 0 = normal operation + 1 = reset error flag + bit 3: + 0 = normal operation + 1 = send break character + bit 2: + 0 = receive disable + 1 = receive enable + bit 1: + 0 = /DTR set to 1 + 1 = /DTR set to 0 + bit 0: + 0 = transmit disable + 1 = transmit enable + */ - /* setup for sync byte(s) */ - m_flags |= I8251_EXPECTING_SYNC_BYTE; - m_sync_byte_offset = 0; - if (data & 0x07) - { - m_sync_byte_count = 1; - } - else - { - m_sync_byte_count = 2; - } + m_rts_handler(!BIT(data, 5)); + m_dtr_handler(!BIT(data, 1)); - } - } + if (data & (1<<4)) + { + m_status &= ~(I8251_STATUS_PARITY_ERROR | I8251_STATUS_OVERRUN_ERROR | I8251_STATUS_FRAMING_ERROR); } - else + + if (data & (1<<6)) { - /* command */ - LOG(("I8251: Command byte\n")); + // datasheet says "returns to mode format", not + // completely resets the chip. behavior of DEC Rainbow + // backs this up. + m_flags |= I8251_EXPECTING_MODE; + } - m_command = data; + update_rx_ready(); + update_tx_ready(); +} - LOG(("Command byte: %02x\n", data)); +WRITE8_MEMBER(i8251_device::mode_w) +{ + LOG(("I8251: Mode byte\n")); - if (data & (1<<7)) - { - LOG(("hunt mode\n")); - } + m_mode_byte = data; - if (data & (1<<5)) + /* Synchronous or Asynchronous? */ + if ((data & 0x03) != 0) + { + /* Asynchronous + + bit 7,6: stop bit length + 0 = inhibit + 1 = 1 bit + 2 = 1.5 bits + 3 = 2 bits + bit 5: parity type + 0 = parity odd + 1 = parity even + bit 4: parity test enable + 0 = disable + 1 = enable + bit 3,2: character length + 0 = 5 bits + 1 = 6 bits + 2 = 7 bits + 3 = 8 bits + bit 1,0: baud rate factor + 0 = defines command byte for synchronous or asynchronous + 1 = x1 + 2 = x16 + 3 = x64 + */ + + LOG(("I8251: Asynchronous operation\n")); + + LOG(("Character length: %d\n", (((data >> 2) & 0x03) + 5))); + + parity_t parity; + + if (data & (1 << 4)) { - LOG(("/rts set to 0\n")); + LOG(("enable parity checking\n")); + + if (data & (1 << 5)) + { + LOG(("even parity\n")); + parity = PARITY_EVEN; + } + else + { + LOG(("odd parity\n")); + parity = PARITY_ODD; + } } else { - LOG(("/rts set to 1\n")); + LOG(("parity check disabled\n")); + parity = PARITY_NONE; } - if (data & (1<<2)) - { - LOG(("receive enable\n")); - } - else + stop_bits_t stop_bits; + + switch ((data >> 6) & 0x03) { - LOG(("receive disable\n")); + case 0: + default: + stop_bits = STOP_BITS_0; + LOG(("stop bit: inhibit\n")); + break; + + case 1: + stop_bits = STOP_BITS_1; + LOG(("stop bit: 1 bit\n")); + break; + + case 2: + stop_bits = STOP_BITS_1_5; + LOG(("stop bit: 1.5 bits\n")); + break; + + case 3: + stop_bits = STOP_BITS_2; + LOG(("stop bit: 2 bits\n")); + break; } - if (data & (1<<1)) + int data_bits_count = ((data >> 2) & 0x03) + 5; + + set_data_frame(1, data_bits_count, parity, stop_bits); + receive_register_reset(); + + switch (data & 0x03) { - LOG(("/dtr set to 0\n")); + case 1: m_br_factor = 1; break; + case 2: m_br_factor = 16; break; + case 3: m_br_factor = 64; break; } - else + + m_rxc_count = m_txc_count = 0; + +#if 0 + /* data bits */ + m_receive_char_length = (((data >> 2) & 0x03) + 5); + + if (data & (1 << 4)) { - LOG(("/dtr set to 1\n")); + /* parity */ + m_receive_char_length++; } - if (data & (1<<0)) - { - LOG(("transmit enable\n")); + /* stop bits */ + m_receive_char_length++; + + m_receive_flags &= ~I8251_TRANSFER_RECEIVE_SYNCHRONISED; + m_receive_flags |= I8251_TRANSFER_RECEIVE_WAITING_FOR_START_BIT; +#endif + /* not expecting mode byte now */ + m_flags &= ~I8251_EXPECTING_MODE; + // m_status = I8251_STATUS_TX_EMPTY | I8251_STATUS_TX_READY; + } + else + { + /* bit 7: Number of sync characters + 0 = 1 character + 1 = 2 character + bit 6: Synchronous mode + 0 = Internal synchronisation + 1 = External synchronisation + bit 5: parity type + 0 = parity odd + 1 = parity even + bit 4: parity test enable + 0 = disable + 1 = enable + bit 3,2: character length + 0 = 5 bits + 1 = 6 bits + 2 = 7 bits + 3 = 8 bits + bit 1,0 = 0 + */ + LOG(("I8251: Synchronous operation\n")); - /* if we get a tx enable with a disable pending, cancel the disable */ - m_disable_tx_pending = false; + /* setup for sync byte(s) */ + m_flags |= I8251_EXPECTING_SYNC_BYTE; + m_sync_byte_offset = 0; + if (data & 0x07) + { + m_sync_byte_count = 1; } else { - if (m_tx_busy) - { - if (!m_disable_tx_pending) - { - LOG(("Tx busy, set pending disable\n")); - } - m_disable_tx_pending = true; - m_command |= (1<<0); - } - else - { - LOG(("transmit disable\n")); - if ((data & (1<<0))==0) - { - /* held in high state when transmit disable */ - m_txd_handler(1); - } - } + m_sync_byte_count = 2; } + } +} - /* bit 7: - 0 = normal operation - 1 = hunt mode - bit 6: - 0 = normal operation - 1 = internal reset - bit 5: - 0 = /RTS set to 1 - 1 = /RTS set to 0 - bit 4: - 0 = normal operation - 1 = reset error flag - bit 3: - 0 = normal operation - 1 = send break character - bit 2: - 0 = receive disable - 1 = receive enable - bit 1: - 0 = /DTR set to 1 - 1 = /DTR set to 0 - bit 0: - 0 = transmit disable - 1 = transmit enable - */ - - m_rts_handler(!BIT(data, 5)); - m_dtr_handler(!BIT(data, 1)); - - if (data & (1<<4)) +WRITE8_MEMBER(i8251_device::control_w) +{ + if (m_flags & I8251_EXPECTING_MODE) + { + if (m_flags & I8251_EXPECTING_SYNC_BYTE) { - m_status &= ~(I8251_STATUS_PARITY_ERROR | I8251_STATUS_OVERRUN_ERROR | I8251_STATUS_FRAMING_ERROR); - } + LOG(("I8251: Sync byte\n")); - if (data & (1<<6)) + LOG(("Sync byte: %02x\n", data)); + /* store sync byte written */ + m_sync_bytes[m_sync_byte_offset] = data; + m_sync_byte_offset++; + + if (m_sync_byte_offset == m_sync_byte_count) + { + /* finished transfering sync bytes, now expecting command */ + m_flags &= ~(I8251_EXPECTING_MODE | I8251_EXPECTING_SYNC_BYTE); + m_sync_byte_offset = 0; + // m_status = I8251_STATUS_TX_EMPTY | I8251_STATUS_TX_READY; + } + } + else { - // datasheet says "returns to mode format", not - // completely resets the chip. behavior of DEC Rainbow - // backs this up. - m_flags |= I8251_EXPECTING_MODE; + mode_w(space, offset, data); } - - update_rx_ready(); - update_tx_ready(); - + } + else + { + command_w(space, offset, data); } } diff --git a/src/emu/machine/i8251.h b/src/emu/machine/i8251.h index cd42f114254..1806894b5c3 100644 --- a/src/emu/machine/i8251.h +++ b/src/emu/machine/i8251.h @@ -40,6 +40,7 @@ class i8251_device : public device_t, { public: // construction/destruction + i8251_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname); i8251_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); // static configuration helpers @@ -55,6 +56,8 @@ public: DECLARE_WRITE8_MEMBER(data_w); DECLARE_READ8_MEMBER(status_r); DECLARE_WRITE8_MEMBER(control_w); + DECLARE_WRITE8_MEMBER(command_w); + DECLARE_WRITE8_MEMBER(mode_w); DECLARE_WRITE_LINE_MEMBER( write_rxd ); DECLARE_WRITE_LINE_MEMBER( write_cts ); @@ -132,7 +135,18 @@ private: bool m_disable_tx_pending; }; +class v53_scu_device : public i8251_device +{ +public: + // construction/destruction + v53_scu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; + + + // device type definition extern const device_type I8251; +extern const device_type V53_SCU; + #endif /* __I8251_H__ */ -- cgit v1.2.3