summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/bus/ieee488/c2031.cpp
blob: b10d14891d536c9068eebc9eac57db6c422ab26c (plain) (tree)
1
2
3
4
5
6
7
8
9

                               



                                                                       

                                                                       
                







                                                                            



                                













                                                                            
                                                                  
















                                                                                                                 
                                                             








                                                   






                                                                                                                    

 










                                                                                                          
                               
 







                       
 
          







                                        
                               
 







                       
 
          







                                       
                               
 







                          
 
          
 
                         






















                                        
                               
 







                          
 
          






























                                               











                                                                                                          
                                           
 







                                                   
 
          
 
                         

                              
                                        










                                        
                                           
 







                                                    
 
          







                                  
                                      




                                       











                                                             

                                                   
                                    

                                                   



                                                         


                                                   
                                    

                                                   



                                                     


                                                   
                                                 

                                                   
                                                      

                                                              

                                           
                                                                  




                                                                            
 
                                                                  






                                                                               
 
                                                               
                                                                         
                                                                                                             



                                                   






















                                                           












                                                                            
                                                   
         



                                                      














                                                                            
                                                                                                           







                                                     
                                   





                       









                                                   
                        
                                  
                                   















                                                   
                           
 

                        





























                                                   
                            


                               

                      
 
// license:BSD-3-Clause
// copyright-holders:Curt Coder
/**********************************************************************

    Commodore 2031 Single Disk Drive emulation

**********************************************************************/

#include "emu.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
//**************************************************************************

DEFINE_DEVICE_TYPE(C2031, c2031_device, "c2031", "Commodore 2031")


//-------------------------------------------------
//  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 tiny_rom_entry *c2031_device::device_rom_region() const
{
	return ROM_NAME( c2031 );
}


//-------------------------------------------------
//  ADDRESS_MAP( c2031_mem )
//-------------------------------------------------

void c2031_device::c2031_mem(address_map &map)
{
	map(0x0000, 0x07ff).mirror(0x6000).ram();
	map(0x1800, 0x180f).mirror(0x63f0).rw(M6522_0_TAG, FUNC(via6522_device::read), FUNC(via6522_device::write));
	map(0x1c00, 0x1c0f).mirror(0x63f0).rw(M6522_1_TAG, FUNC(via6522_device::read), FUNC(via6522_device::write));
	map(0x8000, 0xbfff).mirror(0x4000).rom().region(M6502_TAG, 0);
}


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_t 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());
}


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_t data = 0;

	// write protect sense
	data |= !m_floppy->wpt_r() << 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
	m_led[LED_ACT] = BIT(data, 3);

	// density select
	m_ga->ds_w((data >> 5) & 0x03);
}


//-------------------------------------------------
//  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);
}


//-------------------------------------------------
//  SLOT_INTERFACE( c2031_floppies )
//-------------------------------------------------

static void c2031_floppies(device_slot_interface &device)
{
	device.option_add("525ssqd", FLOPPY_525_SSQD);
}


//-------------------------------------------------
//  FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------

FLOPPY_FORMATS_MEMBER( c2031_device::floppy_formats )
	FLOPPY_D64_FORMAT,
	FLOPPY_G64_FORMAT
FLOPPY_FORMATS_END


//-------------------------------------------------
//  device_add_mconfig - add device configuration
//-------------------------------------------------

MACHINE_CONFIG_START(c2031_device::device_add_mconfig)
	MCFG_DEVICE_ADD(M6502_TAG, M6502, XTAL(16'000'000)/16)
	MCFG_DEVICE_PROGRAM_MAP(c2031_mem)
	MCFG_QUANTUM_PERFECT_CPU(M6502_TAG)

	MCFG_DEVICE_ADD(M6522_0_TAG, VIA6522, XTAL(16'000'000)/16)
	MCFG_VIA6522_READPA_HANDLER(READ8(*this, c2031_device, via0_pa_r))
	MCFG_VIA6522_READPB_HANDLER(READ8(*this, c2031_device, via0_pb_r))
	MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(*this, c2031_device, via0_pa_w))
	MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(*this, c2031_device, via0_pb_w))
	MCFG_VIA6522_IRQ_HANDLER(WRITELINE(*this, c2031_device, via0_irq_w))

	MCFG_DEVICE_ADD(M6522_1_TAG, VIA6522, XTAL(16'000'000)/16)
	MCFG_VIA6522_READPA_HANDLER(READ8(C64H156_TAG, c64h156_device, yb_r))
	MCFG_VIA6522_READPB_HANDLER(READ8(*this, c2031_device, via1_pb_r))
	MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(C64H156_TAG, c64h156_device, yb_w))
	MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(*this, c2031_device, via1_pb_w))
	MCFG_VIA6522_CA2_HANDLER(WRITELINE(C64H156_TAG, c64h156_device, soe_w))
	MCFG_VIA6522_CB2_HANDLER(WRITELINE(C64H156_TAG, c64h156_device, oe_w))
	MCFG_VIA6522_IRQ_HANDLER(WRITELINE(*this, c2031_device, via1_irq_w))

	MCFG_DEVICE_ADD(C64H156_TAG, C64H156, XTAL(16'000'000))
	MCFG_64H156_BYTE_CALLBACK(WRITELINE(*this, c2031_device, byte_w))
	MCFG_FLOPPY_DRIVE_ADD_FIXED(C64H156_TAG":0", c2031_floppies, "525ssqd", c2031_device::floppy_formats)
MACHINE_CONFIG_END


//-------------------------------------------------
//  INPUT_PORTS( c2031 )
//-------------------------------------------------

static INPUT_PORTS_START( c2031 )
	PORT_START("ADDRESS")
	PORT_DIPNAME( 0x03, 0x00, "Device Address" )
	PORT_DIPSETTING(    0x00, "8" )
	PORT_DIPSETTING(    0x01, "9" )
	PORT_DIPSETTING(    0x02, "10" )
	PORT_DIPSETTING(    0x03, "11" )
INPUT_PORTS_END


//-------------------------------------------------
//  input_ports - device-specific input ports
//-------------------------------------------------

ioport_constructor c2031_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( c2031 );
}



//**************************************************************************
//  INLINE HELPERS
//**************************************************************************

//-------------------------------------------------
//  get_device_number -
//-------------------------------------------------

inline int c2031_device::get_device_number()
{
	int state = 1;

	switch ((m_slot->get_address() - 8) & 0x03)
	{
	case 0: state = (m_atna && m_nrfd_out); break;
	case 1: state = m_nrfd_out;             break;
	case 2: state = m_atna;                 break;
	case 3: 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_t clock)
	: device_t(mconfig, 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_floppy(*this, C64H156_TAG":0:525ssqd")
	, m_address(*this, "ADDRESS")
	, m_led(*this, "led%u", 0U)
	, m_nrfd_out(1)
	, m_ndac_out(1)
	, m_atna(1)
	, m_ifc(0)
	, m_via0_irq(0)
	, m_via1_irq(0)
{
}


//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void c2031_device::device_start()
{
	m_led.resolve();
	// install image callbacks
	m_ga->set_floppy(m_floppy);

	// 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 (!m_ifc && state)
	{
		device_reset();
	}

	m_ifc = state;
}