summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/c2031.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/c2031.c')
-rw-r--r--src/mess/machine/c2031.c502
1 files changed, 502 insertions, 0 deletions
diff --git a/src/mess/machine/c2031.c b/src/mess/machine/c2031.c
new file mode 100644
index 00000000000..d733e47840d
--- /dev/null
+++ b/src/mess/machine/c2031.c
@@ -0,0 +1,502 @@
+/**********************************************************************
+
+ Commodore 2031 Single Disk Drive emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+
+#include "c1541.h"
+#include "c2031.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define M6502_TAG "ucd5"
+#define M6522_0_TAG "uab1"
+#define M6522_1_TAG "ucd4"
+#define C64H156_TAG "64h156"
+
+
+enum
+{
+ LED_POWER = 0,
+ LED_ACT
+};
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type C2031 = &device_creator<c2031_device>;
+
+
+//-------------------------------------------------
+// ROM( c2031 )
+//-------------------------------------------------
+
+ROM_START( c2031 )
+ ROM_REGION( 0x4000, M6502_TAG, 0 )
+ ROM_LOAD( "901484-03.u5f", 0x0000, 0x2000, CRC(ee4b893b) SHA1(54d608f7f07860f24186749f21c96724dd48bc50) )
+ ROM_LOAD( "901484-05.u5h", 0x2000, 0x2000, CRC(6a629054) SHA1(ec6b75ecfdd4744e5d57979ef6af990444c11ae1) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c2031_device::device_rom_region() const
+{
+ return ROM_NAME( c2031 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c2031_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c2031_mem, AS_PROGRAM, 8, c2031_device )
+ AM_RANGE(0x0000, 0x07ff) AM_MIRROR(0x6000) AM_RAM
+ AM_RANGE(0x1800, 0x180f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_0_TAG, via6522_device, read, write)
+ AM_RANGE(0x1c00, 0x1c0f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_1_TAG, via6522_device, read, write)
+ AM_RANGE(0x8000, 0xbfff) AM_MIRROR(0x4000) AM_ROM AM_REGION(M6502_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// via6522_interface via0_intf
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( c2031_device::via0_irq_w )
+{
+ m_via0_irq = state;
+
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+READ8_MEMBER( c2031_device::via0_pa_r )
+{
+ /*
+
+ bit description
+
+ PA0 DI0
+ PA1 DI1
+ PA2 DI2
+ PA3 DI3
+ PA4 DI4
+ PA5 DI5
+ PA6 DI6
+ PA7 DI7
+
+ */
+
+ return m_bus->dio_r();
+}
+
+WRITE8_MEMBER( c2031_device::via0_pa_w )
+{
+ /*
+
+ bit description
+
+ PA0 DI0
+ PA1 DI1
+ PA2 DI2
+ PA3 DI3
+ PA4 DI4
+ PA5 DI5
+ PA6 DI6
+ PA7 DI7
+
+ */
+
+ m_bus->dio_w(this, data);
+}
+
+READ8_MEMBER( c2031_device::via0_pb_r )
+{
+ /*
+
+ bit description
+
+ PB0 ATNA
+ PB1 NRFD
+ PB2 NDAC
+ PB3 EOI
+ PB4 T/_R
+ PB5 HD SEL
+ PB6 DAV
+ PB7 _ATN
+
+ */
+
+ UINT8 data = 0;
+
+ // not ready for data
+ data |= m_bus->nrfd_r() << 1;
+
+ // not data accepted
+ data |= m_bus->ndac_r() << 2;
+
+ // end or identify
+ data |= m_bus->eoi_r() << 3;
+
+ // data valid
+ data |= m_bus->dav_r() << 6;
+
+ // attention
+ data |= !m_bus->atn_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c2031_device::via0_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0 ATNA
+ PB1 NRFD
+ PB2 NDAC
+ PB3 EOI
+ PB4 T/_R
+ PB5 HD SEL
+ PB6 DAV
+ PB7 _ATN
+
+ */
+
+ int atna = BIT(data, 0);
+ int nrfd = BIT(data, 1);
+ int ndac = BIT(data, 2);
+
+ // not ready for data
+ m_nrfd_out = nrfd;
+
+ // not data accepted
+ m_ndac_out = ndac;
+
+ // end or identify
+ m_bus->eoi_w(this, BIT(data, 3));
+
+ // data valid
+ m_bus->dav_w(this, BIT(data, 6));
+
+ // attention acknowledge
+ m_atna = atna;
+
+ if ((!m_bus->atn_r()) ^ atna)
+ {
+ nrfd = ndac = 0;
+ }
+
+ m_bus->nrfd_w(this, nrfd);
+ m_bus->ndac_w(this, ndac);
+
+ m_via0->write_ca2(get_device_number());
+}
+
+READ_LINE_MEMBER( c2031_device::via0_ca1_r )
+{
+ return !m_bus->atn_r();
+}
+
+READ_LINE_MEMBER( c2031_device::via0_ca2_r )
+{
+ return get_device_number();
+}
+
+static const via6522_interface via0_intf =
+{
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via0_pa_r),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via0_pb_r),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via0_ca1_r),
+ DEVCB_NULL,
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via0_ca2_r),
+ DEVCB_NULL,
+
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via0_pa_w),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via0_pb_w),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL, // PLL SYN
+
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via0_irq_w)
+};
+
+
+//-------------------------------------------------
+// via6522_interface via1_intf
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( c2031_device::via1_irq_w )
+{
+ m_via1_irq = state;
+
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+READ8_MEMBER( c2031_device::via1_pb_r )
+{
+ /*
+
+ bit signal description
+
+ PB0
+ PB1
+ PB2
+ PB3
+ PB4 WPS write protect sense
+ PB5
+ PB6
+ PB7 SYNC SYNC detect line
+
+ */
+
+ UINT8 data = 0;
+
+ // write protect sense
+ data |= !floppy_wpt_r(m_image) << 4;
+
+ // SYNC detect line
+ data |= m_ga->sync_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c2031_device::via1_pb_w )
+{
+ /*
+
+ bit signal description
+
+ PB0 STP0 stepping motor bit 0
+ PB1 STP1 stepping motor bit 1
+ PB2 MTR motor ON/OFF
+ PB3 ACT drive 0 LED
+ PB4
+ PB5 DS0 density select 0
+ PB6 DS1 density select 1
+ PB7 SYNC SYNC detect line
+
+ */
+
+ // spindle motor
+ m_ga->mtr_w(BIT(data, 2));
+
+ // stepper motor
+ m_ga->stp_w(data & 0x03);
+
+ // activity LED
+ output_set_led_value(LED_ACT, BIT(data, 3));
+
+ // density select
+ m_ga->ds_w((data >> 5) & 0x03);
+}
+
+static const via6522_interface via1_intf =
+{
+ DEVCB_DEVICE_MEMBER(C64H156_TAG, c64h156_device, yb_r),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via1_pb_r),
+ DEVCB_DEVICE_LINE_MEMBER(C64H156_TAG, c64h156_device, byte_r),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+
+ DEVCB_DEVICE_MEMBER(C64H156_TAG, c64h156_device, yb_w),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via1_pb_w),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_DEVICE_LINE_MEMBER(C64H156_TAG, c64h156_device, soe_w),
+ DEVCB_DEVICE_LINE_MEMBER(C64H156_TAG, c64h156_device, oe_w),
+
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, c2031_device, via1_irq_w)
+};
+
+
+//-------------------------------------------------
+// C64H156_INTERFACE( ga_intf )
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( c2031_device::byte_w )
+{
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, state);
+
+ m_via1->write_ca1(state);
+}
+
+static C64H156_INTERFACE( ga_intf )
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, c2031_device, byte_w)
+};
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( c2031 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c2031 )
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c2031_mem)
+ MCFG_QUANTUM_PERFECT_CPU(M6502_TAG)
+
+ MCFG_VIA6522_ADD(M6522_0_TAG, XTAL_16MHz/16, via0_intf)
+ MCFG_VIA6522_ADD(M6522_1_TAG, XTAL_16MHz/16, via1_intf)
+
+ MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, c1541_floppy_interface)
+ MCFG_64H156_ADD(C64H156_TAG, XTAL_16MHz, ga_intf)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor c2031_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( c2031 );
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// get_device_number -
+//-------------------------------------------------
+
+inline int c2031_device::get_device_number()
+{
+ int state = 1;
+
+ switch (m_address)
+ {
+ case 8: state = (m_atna && m_nrfd_out); break;
+ case 9: state = m_nrfd_out; break;
+ case 10: state = m_atna; break;
+ case 11: state = 1; break;
+ }
+
+ return state;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c2031_device - constructor
+//-------------------------------------------------
+
+c2031_device::c2031_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, C2031, "C2031", tag, owner, clock),
+ device_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, M6502_TAG),
+ m_via0(*this, M6522_0_TAG),
+ m_via1(*this, M6522_1_TAG),
+ m_ga(*this, C64H156_TAG),
+ m_image(*this, FLOPPY_0),
+ m_nrfd_out(1),
+ m_ndac_out(1),
+ m_atna(1),
+ m_via0_irq(0),
+ m_via1_irq(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void c2031_device::device_start()
+{
+ // install image callbacks
+ floppy_install_unload_proc(m_image, c2031_device::on_disk_change);
+ floppy_install_load_proc(m_image, c2031_device::on_disk_change);
+
+ // register for state saving
+ save_item(NAME(m_nrfd_out));
+ save_item(NAME(m_ndac_out));
+ save_item(NAME(m_atna));
+ save_item(NAME(m_via0_irq));
+ save_item(NAME(m_via1_irq));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void c2031_device::device_reset()
+{
+ m_maincpu->reset();
+
+ m_via0->reset();
+ m_via1->reset();
+}
+
+
+//-------------------------------------------------
+// ieee488_atn_w -
+//-------------------------------------------------
+
+void c2031_device::ieee488_atn(int state)
+{
+ int nrfd = m_nrfd_out;
+ int ndac = m_ndac_out;
+
+ m_via0->write_ca1(!state);
+
+ if ((!state) ^ m_atna)
+ {
+ nrfd = ndac = 0;
+ }
+
+ m_bus->nrfd_w(this, nrfd);
+ m_bus->ndac_w(this, ndac);
+}
+
+
+//-------------------------------------------------
+// ieee488_ifc_w -
+//-------------------------------------------------
+
+void c2031_device::ieee488_ifc(int state)
+{
+ if (!state)
+ {
+ device_reset();
+ }
+}
+
+
+//-------------------------------------------------
+// on_disk_change -
+//-------------------------------------------------
+
+void c2031_device::on_disk_change(device_image_interface &image)
+{
+ c2031_device *c2031 = static_cast<c2031_device *>(image.device().owner());
+
+ int wp = floppy_wpt_r(image);
+ c2031->m_ga->on_disk_changed(wp);
+}