diff options
author | 2019-10-29 13:43:49 -0400 | |
---|---|---|
committer | 2019-10-29 13:43:49 -0400 | |
commit | 7d862e69f9d6ca22b5516212e4f4ea10f13899a4 (patch) | |
tree | e035cac1168eaf3331617d79ea3363b73b10a5a0 | |
parent | 3151dbd31b1eebce1bce6f8780e3afe90def0cfd (diff) |
Add preliminary MK68564 device (nw)
-rw-r--r-- | src/devices/machine/z80sio.cpp | 405 | ||||
-rw-r--r-- | src/devices/machine/z80sio.h | 92 | ||||
-rw-r--r-- | src/mame/drivers/e9161.cpp | 5 |
3 files changed, 489 insertions, 13 deletions
diff --git a/src/devices/machine/z80sio.cpp b/src/devices/machine/z80sio.cpp index ae93bdd2848..9b259c5c824 100644 --- a/src/devices/machine/z80sio.cpp +++ b/src/devices/machine/z80sio.cpp @@ -45,6 +45,15 @@ * Transmitter FIFO 1 ------------------------------------------------------------------------- * = Features that has been implemented n/a = features that will not + + Mostek not only second-sourced the Z80 SIO but redesigned it for + 68000 compatibility as the MK68564 SIO. This 48-pin device has a + revamped register interface with five address inputs to make every + register separately selectable, and most control registers may be read + back as written. The RxRDY and TxRDY pins are separate here, and many + control bits have been shifted around. The MK68564 also features a + built-in baud rate generator (not compatible with the Z8530 SCC's). + ***************************************************************************/ #include "emu.h" @@ -237,11 +246,13 @@ constexpr uint16_t SDLC_RESIDUAL = 0x1d0f; //************************************************************************** // device type definition -DEFINE_DEVICE_TYPE(Z80SIO_CHANNEL, z80sio_channel, "z80sio_channel", "Z80 SIO channel") -DEFINE_DEVICE_TYPE(I8274_CHANNEL, i8274_channel, "i8274_channel", "Intel 8274 MPSC channel") -DEFINE_DEVICE_TYPE(Z80SIO, z80sio_device, "z80sio", "Z80 SIO") -DEFINE_DEVICE_TYPE(I8274_NEW, i8274_new_device, "i8274_new", "Intel 8274 MPSC (new)") // Remove trailing N when z80dart.cpp's 8274 implementation is fully replaced -DEFINE_DEVICE_TYPE(UPD7201_NEW, upd7201_new_device, "upd7201_new", "NEC uPD7201 MPSC (new)") // Remove trailing N when z80dart.cpp's 7201 implementation is fully replaced +DEFINE_DEVICE_TYPE(Z80SIO_CHANNEL, z80sio_channel, "z80sio_channel", "Z80 SIO channel") +DEFINE_DEVICE_TYPE(I8274_CHANNEL, i8274_channel, "i8274_channel", "Intel 8274 MPSC channel") +DEFINE_DEVICE_TYPE(MK68564_CHANNEL, mk68564_channel, "mk68564_channel", "Mostek MK68564 SIO channel") +DEFINE_DEVICE_TYPE(Z80SIO, z80sio_device, "z80sio", "Z80 SIO") +DEFINE_DEVICE_TYPE(I8274_NEW, i8274_new_device, "i8274_new", "Intel 8274 MPSC (new)") // Remove trailing N when z80dart.cpp's 8274 implementation is fully replaced +DEFINE_DEVICE_TYPE(UPD7201_NEW, upd7201_new_device, "upd7201_new", "NEC uPD7201 MPSC (new)") // Remove trailing N when z80dart.cpp's 7201 implementation is fully replaced +DEFINE_DEVICE_TYPE(MK68564, mk68564_device, "mk68564", "Mostek MK68564 SIO") //------------------------------------------------- // device_add_mconfig - add device configuration @@ -258,6 +269,12 @@ void i8274_new_device::device_add_mconfig(machine_config &config) I8274_CHANNEL(config, CHANB_TAG, 0); } +void mk68564_device::device_add_mconfig(machine_config &config) +{ + MK68564_CHANNEL(config, CHANA_TAG, 0); + MK68564_CHANNEL(config, CHANB_TAG, 0); +} + //************************************************************************** // LIVE DEVICE @@ -290,11 +307,16 @@ inline bool z80sio_channel::receive_allowed() const return (m_wr3 & WR3_RX_ENABLE) && (!(m_wr3 & WR3_AUTO_ENABLES) || !m_dcd); } -inline bool z80sio_channel::transmit_allowed() const +bool z80sio_channel::transmit_allowed() const { return (m_wr5 & WR5_TX_ENABLE) && (!(m_wr3 & WR3_AUTO_ENABLES) || !m_cts); } +bool mk68564_channel::transmit_allowed() const +{ + return (m_wr5 & WR5_TX_ENABLE) && (!m_tx_auto_enable || !m_cts); +} + inline void z80sio_channel::set_rts(int state) { if (bool(m_rts) != bool(state)) @@ -393,6 +415,11 @@ upd7201_new_device::upd7201_new_device(const machine_config &mconfig, const char { } +mk68564_device::mk68564_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + i8274_new_device(mconfig, MK68564, tag, owner, clock) +{ +} + //------------------------------------------------- // device_validity_check - device-specific validation //------------------------------------------------- @@ -947,6 +974,14 @@ i8274_channel::i8274_channel(const machine_config &mconfig, const char *tag, dev { } +mk68564_channel::mk68564_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : z80sio_channel(mconfig, MK68564_CHANNEL, tag, owner, clock, RR1_END_OF_FRAME | RR1_CRC_FRAMING_ERROR | RR1_RESIDUE_CODE_MASK) + , m_tx_auto_enable(false) + , m_brg_tc(0) + , m_brg_control(0) +{ +} + //------------------------------------------------- // resove_objects - channel setup @@ -1016,6 +1051,15 @@ void z80sio_channel::device_start() save_item(NAME(m_cts)); } +void mk68564_channel::device_start() +{ + z80sio_channel::device_start(); + + save_item(NAME(m_tx_auto_enable)); + save_item(NAME(m_brg_tc)); + save_item(NAME(m_brg_control)); +} + //------------------------------------------------- // reset - reset channel status @@ -1066,6 +1110,15 @@ void z80sio_channel::device_reset() m_uart->reset_interrupts(); } +void mk68564_channel::device_reset() +{ + z80sio_channel::device_reset(); + + m_tx_auto_enable = false; + m_brg_tc = 0; + m_brg_control = 0; +} + bool z80sio_channel::is_tx_idle() const { return (m_tx_sr & TX_SR_MASK) == TX_SR_MASK; @@ -1337,7 +1390,7 @@ void z80sio_channel::trigger_ext_int() //------------------------------------------------- // get_clock_mode - get clock divisor //------------------------------------------------- -int z80sio_channel::get_clock_mode() +int z80sio_channel::get_clock_mode() const { //LOG("%s %s\n",FUNCNAME, tag()); int clocks = 1; @@ -1385,7 +1438,7 @@ void z80sio_channel::update_dtr_rts_break() //------------------------------------------------- // get_rx_word_length - get receive word length //------------------------------------------------- -int z80sio_channel::get_rx_word_length() +int z80sio_channel::get_rx_word_length() const { LOG("%s %s\n",FUNCNAME, tag()); int bits = 5; @@ -2524,3 +2577,339 @@ WRITE_LINE_MEMBER( z80sio_channel::txc_w ) } m_tx_clock = state; } + +//************************************************************************** +// MK68564 REGISTER INTERFACE +//************************************************************************** + +//------------------------------------------------- +// cmdreg_r - read from command register +//------------------------------------------------- +uint8_t mk68564_channel::cmdreg_r() +{ + return m_wr0; +} + + +//------------------------------------------------- +// cmdreg_w - write to command register +//------------------------------------------------- +void mk68564_channel::cmdreg_w(uint8_t data) +{ + // TODO: bit 0 sets loop mode (no register select) + // FIXME: no return from interrupt command + do_sioreg_wr0(data); +} + + +//------------------------------------------------- +// modectl_r - read from mode control register +//------------------------------------------------- +uint8_t mk68564_channel::modectl_r() +{ + return m_wr4; +} + + +//------------------------------------------------- +// modectl_w - write to mode control register +//------------------------------------------------- +void mk68564_channel::modectl_w(uint8_t data) +{ + do_sioreg_wr4(data); +} + + +//------------------------------------------------- +// intctl_r - read from interrupt control register +//------------------------------------------------- +uint8_t mk68564_channel::intctl_r() +{ + return m_wr1 | (m_wr5 & WR5_CRC16 ? 0x80 : 0); +} + + +//------------------------------------------------- +// intctl_w - write to interrupt control register +//------------------------------------------------- +void mk68564_channel::intctl_w(uint8_t data) +{ + if (BIT(data, 7)) + m_wr5 |= WR5_CRC16; + else + m_wr5 &= ~WR5_CRC16; + + // TODO: bits 5 and 6 are independent RxRDY and WxRDY enables + do_sioreg_wr1(data & 0x7f); +} + + +//------------------------------------------------- +// sync1_r - read from sync word register 1 +//------------------------------------------------- +uint8_t mk68564_channel::sync1_r() +{ + return m_wr6; +} + + +//------------------------------------------------- +// sync1_w - write to sync word register 1 +//------------------------------------------------- +void mk68564_channel::sync1_w(uint8_t data) +{ + do_sioreg_wr6(data); +} + + +//------------------------------------------------- +// sync2_r - read from sync word register 2 +//------------------------------------------------- +uint8_t mk68564_channel::sync2_r() +{ + return m_wr7; +} + + +//------------------------------------------------- +// sync2_w - write to sync word register 2 +//------------------------------------------------- +void mk68564_channel::sync2_w(uint8_t data) +{ + do_sioreg_wr7(data); +} + + +//------------------------------------------------- +// rcvctl_r - read from receiver control register +//------------------------------------------------- +uint8_t mk68564_channel::rcvctl_r() +{ + return bitswap<8>(m_wr3, 6, 7, 5, 4, 3, 2, 1, 0) & ~WR3_ENTER_HUNT_PHASE; +} + + +//------------------------------------------------- +// rcvctl_w - write to receiver control register +//------------------------------------------------- +void mk68564_channel::rcvctl_w(uint8_t data) +{ + do_sioreg_wr3(bitswap<8>(data, 6, 7, 5, 4, 3, 2, 1, 0)); +} + + +//------------------------------------------------- +// xmtctl_r - read from transmitter control +// register +//------------------------------------------------- +uint8_t mk68564_channel::xmtctl_r() +{ + uint8_t xmtctl = 0; + if (m_wr5 & WR5_TX_ENABLE) + xmtctl |= 0x01; + if (m_wr5 & WR5_RTS) + xmtctl |= 0x02; + if (m_wr5 & WR5_DTR) + xmtctl |= 0x04; + if (m_wr5 & WR5_TX_CRC_ENABLE) + xmtctl |= 0x08; + if (m_wr5 & WR5_SEND_BREAK) + xmtctl |= 0x10; + if (m_tx_auto_enable) + xmtctl |= 0x20; + xmtctl |= (m_wr5 & 0x40) << 1; + xmtctl |= (m_wr5 & 0x80) >> 1; + return xmtctl; +} + + +//------------------------------------------------- +// xmtctl_w - write to transmitter control +// register +//------------------------------------------------- +void mk68564_channel::xmtctl_w(uint8_t data) +{ + uint8_t control = + (BIT(data, 0) ? WR5_TX_ENABLE : 0) | + (BIT(data, 1) ? WR5_RTS : 0) | + (BIT(data, 2) ? WR5_DTR : 0) | + (BIT(data, 3) ? WR5_TX_CRC_ENABLE : 0) | + (BIT(data, 4) ? WR5_SEND_BREAK : 0) | + (data & 0x40) << 1 | + (data & 0x80) >> 1 | + (m_wr5 & WR5_CRC16); + do_sioreg_wr5(control); + + m_tx_auto_enable = BIT(data, 5); +} + + +//------------------------------------------------- +// tcreg_r - read from time constant register +//------------------------------------------------- +uint8_t mk68564_channel::tcreg_r() +{ + return m_brg_tc; +} + + +//------------------------------------------------- +// tcreg_w - write to time constant register +//------------------------------------------------- +void mk68564_channel::tcreg_w(uint8_t data) +{ + logerror("Time constant = %d\n", data); + m_brg_tc = data; +} + + +//------------------------------------------------- +// brgctl_r - read from baud rate generator +// control register +//------------------------------------------------- +uint8_t mk68564_channel::brgctl_r() +{ + return m_brg_control; +} + + +//------------------------------------------------- +// brgctl_w - write to baud rate generator +// control register +//------------------------------------------------- +void mk68564_channel::brgctl_w(uint8_t data) +{ + // TODO: actually emulate this + logerror("BRG %sabled, divide by %d, RxC %sternal, TxC %sternal\n", + BIT(data, 0) ? "en" : "dis", + BIT(data, 1) ? 64 : 4, + BIT(data, 2) ? "in" : "ex", + BIT(data, 3) ? "in" : "ex"); + + // unused bits are always zero + m_brg_control = data & 0x0f; +} + + +//------------------------------------------------- +// vectrg_w - write to the interrupt vector +// register (only one exists) +//------------------------------------------------- +void mk68564_device::vectrg_w(uint8_t data) +{ + m_chanB->do_sioreg_wr2(data); +} + + +//------------------------------------------------- +// read - 68000 compatible bus read +//------------------------------------------------- +uint8_t mk68564_device::read(offs_t offset) +{ + mk68564_channel &channel = downcast<mk68564_channel &>(BIT(offset, 4) ? *m_chanB : *m_chanA); + + switch (offset & 0x0f) + { + case 0x00: + return channel.cmdreg_r(); + + case 0x01: + return channel.modectl_r(); + + case 0x02: + return channel.intctl_r(); + + case 0x03: + return channel.sync1_r(); + + case 0x04: + return channel.sync2_r(); + + case 0x05: + return channel.rcvctl_r(); + + case 0x06: + return channel.xmtctl_r(); + + case 0x07: + return channel.do_sioreg_rr0(); + + case 0x08: + return channel.do_sioreg_rr1(); + + case 0x09: + return channel.data_read(); + + case 0x0a: + return channel.tcreg_r(); + + case 0x0b: + return channel.brgctl_r(); + + case 0x0c: // vector register is addressable through either channel + return read_vector(); + + default: // unused registers read as FF + return 0xff; + } +} + + +//------------------------------------------------- +// write - 68000 compatible bus write +//------------------------------------------------- +void mk68564_device::write(offs_t offset, uint8_t data) +{ + mk68564_channel &channel = downcast<mk68564_channel &>(BIT(offset, 4) ? *m_chanB : *m_chanA); + + switch (offset & 0x0f) + { + case 0x00: + channel.cmdreg_w(data); + break; + + case 0x01: + channel.modectl_w(data); + break; + + case 0x02: + channel.intctl_w(data); + break; + + case 0x03: + channel.sync1_w(data); + break; + + case 0x04: + channel.sync2_w(data); + break; + + case 0x05: + channel.rcvctl_w(data); + break; + + case 0x06: + channel.xmtctl_w(data); + break; + + case 0x09: + channel.data_write(data); + break; + + case 0x0a: + channel.tcreg_w(data); + break; + + case 0x0b: + channel.brgctl_w(data); + break; + + case 0x0c: // vector register is addressable through either channel + vectrg_w(data); + break; + + default: + LOG("Write %02X to unused/read-only register %02X\n", data, offset & 0x1f); + break; + } +} diff --git a/src/devices/machine/z80sio.h b/src/devices/machine/z80sio.h index c2d1c5e0f8e..df1044ef6f8 100644 --- a/src/devices/machine/z80sio.h +++ b/src/devices/machine/z80sio.h @@ -49,6 +49,31 @@ R S S D K S D S S R D R S S D K S D S S R C A A A A E B B B B B A A A A E B B B B T T + _____ _____ + D1 1|* \_/ |48 D0 + D3 2| |47 D2 + D5 3| |46 D4 + D7 4| |45 D6 + _INTR 5| |44 R/_W + IEO 6| |43 _IACK + IEI 7| |42 _DTACK + _M1 8| |41 _CS + _RESET 9| |40 _RxRDYB + _RxRDYA 10| |39 _TxRDYB + _TxRDYA 11| DIP48 |38 GND + Vcc 12| MK68564 |37 _IEI + _IEO 13| SIO |36 _SYNCB + _SYNCA 14| |35 _TxCB + _TxCA 15| |34 _RxCB + _RxCA 16| |29 RxDB + RxDA 17| |28 TxDB + TxDA 18| |27 _DTRB + _DTRA 19| |26 _RTSB + _RTSA 20| |25 _CTSB + _CTSA 21| |24 _DCDB + _DCDA 22| |23 A1 + A2 23| |22 A3 + A4 24|_____________|21 A5 ***************************************************************************/ @@ -80,6 +105,7 @@ class z80sio_channel : public device_t friend class z80sio_device; friend class i8274_new_device; friend class upd7201_new_device; + friend class mk68564_device; public: z80sio_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -199,8 +225,8 @@ protected: void set_dtr(int state); void set_rts(int state); - int get_clock_mode(); - int get_rx_word_length(); + int get_clock_mode() const; + int get_rx_word_length() const; int get_tx_word_length() const; // receiver state @@ -258,14 +284,14 @@ protected: int m_index; z80sio_device *m_uart; -private: +protected: // helpers void out_txd_cb(int state); void out_rts_cb(int state); void out_dtr_cb(int state); void set_ready(bool ready); bool receive_allowed() const; - bool transmit_allowed() const; + virtual bool transmit_allowed() const; void receive_enabled(); void enter_hunt_mode(); @@ -304,6 +330,47 @@ public: }; +// ======================> mk68564_channel + +class mk68564_channel : public z80sio_channel +{ + friend class mk68564_device; + +public: + mk68564_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + virtual bool transmit_allowed() const override; + +private: + uint8_t cmdreg_r(); + void cmdreg_w(uint8_t data); + uint8_t modectl_r(); + void modectl_w(uint8_t data); + uint8_t intctl_r(); + void intctl_w(uint8_t data); + uint8_t sync1_r(); + void sync1_w(uint8_t data); + uint8_t sync2_r(); + void sync2_w(uint8_t data); + uint8_t rcvctl_r(); + void rcvctl_w(uint8_t data); + uint8_t xmtctl_r(); + void xmtctl_w(uint8_t data); + uint8_t tcreg_r(); + void tcreg_w(uint8_t data); + uint8_t brgctl_r(); + void brgctl_w(uint8_t data); + + bool m_tx_auto_enable; + uint8_t m_brg_tc; + uint8_t m_brg_control; +}; + + // ======================> z80sio_device class z80sio_device : public device_t, @@ -443,9 +510,26 @@ public: upd7201_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +class mk68564_device : public i8274_new_device +{ +public: + mk68564_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + uint8_t read(offs_t offset); + void write(offs_t offset, uint8_t data); + +protected: + // device_t overrides + virtual void device_add_mconfig(machine_config &config) override; + +private: + void vectrg_w(uint8_t data); +}; + // device type declaration DECLARE_DEVICE_TYPE(Z80SIO, z80sio_device) DECLARE_DEVICE_TYPE(I8274_NEW, i8274_new_device) DECLARE_DEVICE_TYPE(UPD7201_NEW, upd7201_new_device) +DECLARE_DEVICE_TYPE(MK68564, mk68564_device) #endif // MAME_MACHINE_Z80SIO_H diff --git a/src/mame/drivers/e9161.cpp b/src/mame/drivers/e9161.cpp index d87dbb0f5f5..4901a34a4c9 100644 --- a/src/mame/drivers/e9161.cpp +++ b/src/mame/drivers/e9161.cpp @@ -12,6 +12,7 @@ #include "emu.h" #include "cpu/m68000/m68000.h" #include "machine/hd63450.h" +#include "machine/z80sio.h" #include "video/am8052.h" @@ -62,7 +63,7 @@ void e9161_state::mem_map(address_map &map) map(0xffe000, 0xffe03f).rw(m_dmac, FUNC(hd63450_device::read), FUNC(hd63450_device::write)); map(0xffe802, 0xffe803).w("crtc", FUNC(am8052_device::pointer_w)); map(0xffe804, 0xffe805).w("crtc", FUNC(am8052_device::data_w)); - //map(0xfff600, 0xfff63f).rw("sio", FUNC(mk68564_device::read), FUNC(mk68564_device::write)).umask16(0x00ff); + map(0xfff600, 0xfff63f).rw("sio", FUNC(mk68564_device::read), FUNC(mk68564_device::write)).umask16(0x00ff); } @@ -78,6 +79,8 @@ void e9161_state::e9161(machine_config &config) HD63450(config, m_dmac, 8'000'000, m_maincpu); AM8052(config, "crtc", 8'000'000); + + MK68564(config, "sio", 4'000'000); } |