diff options
Diffstat (limited to 'src/emu/bus/plus4/c1551.c')
-rw-r--r-- | src/emu/bus/plus4/c1551.c | 598 |
1 files changed, 598 insertions, 0 deletions
diff --git a/src/emu/bus/plus4/c1551.c b/src/emu/bus/plus4/c1551.c new file mode 100644 index 00000000000..56cb71d2adf --- /dev/null +++ b/src/emu/bus/plus4/c1551.c @@ -0,0 +1,598 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder +/********************************************************************** + + Commodore 1551 Single Disk Drive emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "c1551.h" + + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define M6510T_TAG "u2" +#define M6523_0_TAG "u3" +#define M6523_1_TAG "ci_u2" +#define C64H156_TAG "u6" +#define PLA_TAG "u1" + + +enum +{ + LED_POWER = 0, + LED_ACT +}; + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type C1551 = &device_creator<c1551_device>; + + +//------------------------------------------------- +// ROM( c1551 ) +//------------------------------------------------- + +ROM_START( c1551 ) // schematic 251860 + ROM_REGION( 0x4000, M6510T_TAG, 0 ) + ROM_LOAD( "318001-01.u4", 0x0000, 0x4000, CRC(6d16d024) SHA1(fae3c788ad9a6cc2dbdfbcf6c0264b2ca921d55e) ) + + ROM_REGION( 0xf5, PLA_TAG, 0 ) // schematic 251925 + ROM_LOAD( "251641-03.u1", 0x00, 0xf5, NO_DUMP ) +ROM_END + + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const rom_entry *c1551_device::device_rom_region() const +{ + return ROM_NAME( c1551 ); +} + + +//------------------------------------------------- +// M6510_INTERFACE( cpu_intf ) +//------------------------------------------------- + +READ8_MEMBER( c1551_device::port_r ) +{ + /* + + bit description + + P0 + P1 + P2 + P3 + P4 WPS + P5 + P6 + P7 BYTE LTCHED + + */ + + UINT8 data = 0; + + // write protect sense + data |= !floppy_wpt_r(m_image) << 4; + + // byte latched + data |= m_ga->atn_r() << 7; + + return data; +} + +WRITE8_MEMBER( c1551_device::port_w ) +{ + /* + + bit description + + P0 STP0A + P1 STP0B + P2 MTR0 + P3 ACT0 + P4 + P5 DS0 + P6 DS1 + P7 + + */ + + // stepper motor + m_ga->stp_w(data & 0x03); + + // spindle motor + m_ga->mtr_w(BIT(data, 2)); + + // activity LED + output_set_led_value(LED_ACT, BIT(data, 3)); + + // density select + m_ga->ds_w((data >> 5) & 0x03); +} + +//------------------------------------------------- +// tpi6525_interface tpi0_intf +//------------------------------------------------- + +READ8_MEMBER( c1551_device::tcbm_data_r ) +{ + /* + + bit description + + PA0 TCBM PA0 + PA1 TCBM PA1 + PA2 TCBM PA2 + PA3 TCBM PA3 + PA4 TCBM PA4 + PA5 TCBM PA5 + PA6 TCBM PA6 + PA7 TCBM PA7 + + */ + + return m_tcbm_data; +} + +WRITE8_MEMBER( c1551_device::tcbm_data_w ) +{ + /* + + bit description + + PA0 TCBM PA0 + PA1 TCBM PA1 + PA2 TCBM PA2 + PA3 TCBM PA3 + PA4 TCBM PA4 + PA5 TCBM PA5 + PA6 TCBM PA6 + PA7 TCBM PA7 + + */ + + m_tcbm_data = data; +} + +READ8_MEMBER( c1551_device::tpi0_r ) +{ + UINT8 data = m_tpi0->read(space, offset); + + m_ga->ted_w(0); + m_ga->ted_w(1); + + return data; +} + +WRITE8_MEMBER( c1551_device::tpi0_w ) +{ + m_tpi0->write(space, offset, data); + + m_ga->ted_w(0); + m_ga->ted_w(1); +} + +READ8_MEMBER( c1551_device::tpi0_pc_r ) +{ + /* + + bit description + + PC0 + PC1 + PC2 + PC3 + PC4 + PC5 JP1 + PC6 _SYNC + PC7 TCBM DAV + + */ + + UINT8 data = 0; + + // JP1 + data |= m_jp1->read() << 5; + + // SYNC detect line + data |= m_ga->sync_r() << 6; + + // TCBM data valid + data |= m_dav << 7; + + return data; +} + +WRITE8_MEMBER( c1551_device::tpi0_pc_w ) +{ + /* + + bit description + + PC0 TCBM STATUS0 + PC1 TCBM STATUS1 + PC2 TCBM DEV + PC3 TCBM ACK + PC4 MODE + PC5 + PC6 + PC7 + + */ + + // TCBM status + m_status = data & 0x03; + + // TCBM device number + m_dev = BIT(data, 2); + + // TCBM acknowledge + m_ack = BIT(data, 3); + + // read/write mode + m_ga->oe_w(BIT(data, 4)); +} + +static const tpi6525_interface tpi0_intf = +{ + DEVCB_NULL, + DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1551_device, tcbm_data_r), + DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1551_device, tcbm_data_w), + DEVCB_DEVICE_MEMBER(C64H156_TAG, c64h156_device, yb_r), + DEVCB_DEVICE_MEMBER(C64H156_TAG, c64h156_device, yb_w), + DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1551_device, tpi0_pc_r), + DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1551_device, tpi0_pc_w), + DEVCB_NULL, + DEVCB_NULL +}; + + +//------------------------------------------------- +// tpi6525_interface tpi1_intf +//------------------------------------------------- + +READ8_MEMBER( c1551_device::tpi1_pb_r ) +{ + /* + + bit description + + PB0 STATUS0 + PB1 STATUS1 + PB2 + PB3 + PB4 + PB5 + PB6 + PB7 + + */ + + return m_status & 0x03; +} + +READ8_MEMBER( c1551_device::tpi1_pc_r ) +{ + /* + + bit description + + PC0 + PC1 + PC2 + PC3 + PC4 + PC5 + PC6 + PC7 TCBM ACK + + */ + + UINT8 data = 0; + + // TCBM acknowledge + data |= m_ack << 7; + + return data; +} + +WRITE8_MEMBER( c1551_device::tpi1_pc_w ) +{ + /* + + bit description + + PC0 + PC1 + PC2 + PC3 + PC4 + PC5 + PC6 TCBM DAV + PC7 + + */ + + // TCBM data valid + m_dav = BIT(data, 6); +} + +static const tpi6525_interface tpi1_intf = +{ + DEVCB_NULL, + DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1551_device, tcbm_data_r), + DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1551_device, tcbm_data_w), + DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1551_device, tpi1_pb_r), + DEVCB_NULL, + DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1551_device, tpi1_pc_r), + DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, c1551_device, tpi1_pc_w), + DEVCB_NULL, + DEVCB_NULL +}; + + +//------------------------------------------------- +// ADDRESS_MAP( c1551_mem ) +//------------------------------------------------- + +static ADDRESS_MAP_START( c1551_mem, AS_PROGRAM, 8, c1551_device ) + AM_RANGE(0x0000, 0x07ff) AM_MIRROR(0x0800) AM_RAM + AM_RANGE(0x4000, 0x4007) AM_MIRROR(0x3ff8) AM_READWRITE(tpi0_r, tpi0_w) + AM_RANGE(0xc000, 0xffff) AM_ROM AM_REGION(M6510T_TAG, 0) +ADDRESS_MAP_END + + +//------------------------------------------------- +// C64H156_INTERFACE( ga_intf ) +//------------------------------------------------- + +static C64H156_INTERFACE( ga_intf ) +{ + DEVCB_NULL, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF, c64h156_device, atni_w) +}; + + +//------------------------------------------------- +// LEGACY_FLOPPY_OPTIONS( c1541 ) +//------------------------------------------------- + +static LEGACY_FLOPPY_OPTIONS_START( c1541 ) + LEGACY_FLOPPY_OPTION( c1541, "g64", "Commodore 1541 GCR Disk Image", g64_dsk_identify, g64_dsk_construct, NULL, NULL ) + LEGACY_FLOPPY_OPTION( c1541, "d64", "Commodore 1541 Disk Image", d64_dsk_identify, d64_dsk_construct, NULL, NULL ) +LEGACY_FLOPPY_OPTIONS_END + + +//------------------------------------------------- +// floppy_interface c1551_floppy_interface +//------------------------------------------------- + +static const floppy_interface c1551_floppy_interface = +{ + DEVCB_NULL, + DEVCB_NULL, + DEVCB_NULL, + DEVCB_NULL, + DEVCB_NULL, + FLOPPY_STANDARD_5_25_SSDD, + LEGACY_FLOPPY_OPTIONS_NAME(c1541), + "floppy_5_25", + NULL +}; + + +//------------------------------------------------- +// MACHINE_DRIVER( c1551 ) +//------------------------------------------------- + +static MACHINE_CONFIG_FRAGMENT( c1551 ) + MCFG_CPU_ADD(M6510T_TAG, M6510T, XTAL_16MHz/8) + MCFG_CPU_PROGRAM_MAP(c1551_mem) + MCFG_M6510T_PORT_CALLBACKS(READ8(c1551_device, port_r), WRITE8(c1551_device, port_w)) + MCFG_QUANTUM_PERFECT_CPU(M6510T_TAG) + + MCFG_PLS100_ADD(PLA_TAG) + MCFG_TPI6525_ADD(M6523_0_TAG, tpi0_intf) + MCFG_TPI6525_ADD(M6523_1_TAG, tpi1_intf) + + MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, c1551_floppy_interface) + MCFG_64H156_ADD(C64H156_TAG, XTAL_16MHz, ga_intf) + + MCFG_PLUS4_PASSTHRU_EXPANSION_SLOT_ADD() +MACHINE_CONFIG_END + + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor c1551_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( c1551 ); +} + + +//------------------------------------------------- +// INPUT_PORTS( c1551 ) +//------------------------------------------------- + +static INPUT_PORTS_START( c1551 ) + PORT_START("JP1") + PORT_DIPNAME( 0x01, 0x00, "Device Number" ) + PORT_DIPSETTING( 0x00, "8" ) + PORT_DIPSETTING( 0x01, "9" ) +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor c1551_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( c1551 ); +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// c1551_device - constructor +//------------------------------------------------- + +c1551_device::c1551_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, C1551, "C1551", tag, owner, clock, "c1551", __FILE__), + device_plus4_expansion_card_interface(mconfig, *this), + m_maincpu(*this, M6510T_TAG), + m_tpi0(*this, M6523_0_TAG), + m_tpi1(*this, M6523_1_TAG), + m_ga(*this, C64H156_TAG), + m_pla(*this, PLA_TAG), + m_image(*this, FLOPPY_0), + m_exp(*this, PLUS4_EXPANSION_SLOT_TAG), + m_jp1(*this, "JP1"), + m_tcbm_data(0xff), + m_status(1), + m_dav(1), + m_ack(1), + m_dev(0) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void c1551_device::device_start() +{ + // allocate timers + m_irq_timer = timer_alloc(); + m_irq_timer->adjust(attotime::zero, CLEAR_LINE); + + // install image callbacks + m_ga->set_floppy(m_image); + + // register for state saving + save_item(NAME(m_tcbm_data)); + save_item(NAME(m_status)); + save_item(NAME(m_dav)); + save_item(NAME(m_ack)); + save_item(NAME(m_dev)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void c1551_device::device_reset() +{ + m_maincpu->reset(); + + m_tpi0->reset(); + + m_exp->reset(); + + // initialize gate array + m_ga->test_w(1); + m_ga->soe_w(1); + m_ga->accl_w(1); + m_ga->atna_w(1); +} + + +//------------------------------------------------- +// device_timer - handler timer events +//------------------------------------------------- + +void c1551_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + m_maincpu->set_input_line(M6502_IRQ_LINE, param); + + if (param == ASSERT_LINE) + { + // Ts = 0.7*R2*C1 = 0.7*100R*0.1uF = 7us + m_irq_timer->adjust(attotime::from_usec(7), CLEAR_LINE); + } + else + { + // Tm = 0.7*(R1+R2)*C1 = 0.7*(120K+100R)*0.1uF = 0.008407s + m_irq_timer->adjust(attotime::from_usec(8407), ASSERT_LINE); + } +} + + +//------------------------------------------------- +// tpi1_selected - +//------------------------------------------------- + +bool c1551_device::tpi1_selected(offs_t offset) +{ +#ifdef PLA_DUMPED + int mux = 0, ras = 0, phi0 = 0, f7 = 0; + UINT16 input = A5 << 15 | A6 << 14 | A7 << 13 | A8 << 12 | A9 << 11 | mux << 10 | A10 << 9 | m_dev << 8 | ras << 7 | phi0 << 6 | A15 << 5 | A14 << 4 | A13 << 3 | A12 << 2 | A11 << 1 | f7; + UINT8 data = m_pla->read(input); + return BIT(data, 0) ? true : false; +#endif + + offs_t start_address = m_dev ? 0xfee0 : 0xfec0; + + if (offset >= start_address && offset < (start_address + 0x20)) + { + return true; + } + + return false; +} + + +//------------------------------------------------- +// plus4_cd_r - cartridge data read +//------------------------------------------------- + +UINT8 c1551_device::plus4_cd_r(address_space &space, offs_t offset, UINT8 data, int ba, int cs0, int c1l, int c2l, int cs1, int c1h, int c2h) +{ + data = m_exp->cd_r(space, offset, data, ba, cs0, c1l, c2l, cs1, c1h, c2h); + + if (tpi1_selected(offset)) + { + data = m_tpi1->read(space, offset & 0x07); + } + + return data; +} + + +//------------------------------------------------- +// plus4_cd_w - cartridge data write +//------------------------------------------------- + +void c1551_device::plus4_cd_w(address_space &space, offs_t offset, UINT8 data, int ba, int cs0, int c1l, int c2l, int cs1, int c1h, int c2h) +{ + if (tpi1_selected(offset)) + { + m_tpi1->write(space, offset & 0x07, data); + } + + m_exp->cd_w(space, offset, data, ba, cs0, c1l, c2l, cs1, c1h, c2h); +} |