summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/bus/plus4/c1551.cpp
blob: 575f3e651711bec518619b7288cd7ef09f0074e4 (plain) (tree)
1
2
3
4
5
6
7
8
9

                               



                                                                       

                                                                       
                







                                                                            




                               
 
 




                                                                            
                                                                  


















                                                                                                                
                                                             





                                                   
                               

                                                   
                                    


          
                               
 







                               
 
          
 
                         

                              
                                        






                                   
                                     


          
                               
 







                         
 
          
 


                                 


                                  
                       
                                      




                                       
 



                                                   
                                         


          
                               
 







                            
 
          



                           
                                          


          
                               
 







                            
 
          



                           
                                    
 
                                                   
 





                       
                                     






                                           
                                       


          
                               
 







                            
 
          
 
                         

              
                                   









                                    
                                        


          
                               
 







                                
 
          













                                 



                                                   
                                       


          
                               
 







                           
 
          



                               
                                       


          
                               
 







                            
 
          
 
                         






                           
                                        


          
                               
 







                            
 
          




                             



                                                   





                                                                                                            


                                                   
                                    

                                                   



                                                         


                                                   
                                    

                                                   
                                                     


                          


                                                   
                                                 

                                                   
                                                      


                                                                                                           


                                            
                                                





                                                                         
                                                




                                                                        
 
                                                               
                                                                                 
                                                                                                             
 
                                                



                                                   














                                                   
                                                           










                                                                            













                                                                                                           
                                   





                              







                                                   
                                 
 

                        




                                                        
                                   





                                     
                               






                                                   
                                 



                           
 
                       












                                                   
                                                                                           
















                                                                            


                                                   
                                               


                                               

                                                                                                                                                                                                     














                                                                       


                                                   
                                                                                                                                                 
 
                                                                                  
 
                                  
         
                                                          









                                                   
                                                                                                                                              
 
                                  
         
                                                          
         


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

    Commodore 1551 Single Disk Drive emulation

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

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



//**************************************************************************
//  DEVICE DEFINITIONS
//**************************************************************************

DEFINE_DEVICE_TYPE(C1551, c1551_device, "c1551", "Commodore 1551")


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

	// write protect sense
	data |= !m_floppy->wpt_r() << 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
	m_led[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_t 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_t 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));
}

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

//-------------------------------------------------
//  ADDRESS_MAP( c1551_mem )
//-------------------------------------------------

void c1551_device::c1551_mem(address_map &map)
{
	map(0x0000, 0x07ff).mirror(0x0800).ram();
	map(0x4000, 0x4007).mirror(0x3ff8).rw(this, FUNC(c1551_device::tpi0_r), FUNC(c1551_device::tpi0_w));
	map(0xc000, 0xffff).rom().region(M6510T_TAG, 0);
}


//-------------------------------------------------
//  SLOT_INTERFACE( c1551_floppies )
//-------------------------------------------------

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


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

FLOPPY_FORMATS_MEMBER( c1551_device::floppy_formats )
	FLOPPY_D64_FORMAT,
	FLOPPY_G64_FORMAT
FLOPPY_FORMATS_END


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

MACHINE_CONFIG_START(c1551_device::device_add_mconfig)
	MCFG_DEVICE_ADD(M6510T_TAG, M6510T, XTAL(16'000'000)/8)
	MCFG_DEVICE_PROGRAM_MAP(c1551_mem)
	MCFG_M6510T_PORT_CALLBACKS(READ8(*this, c1551_device, port_r), WRITE8(*this, c1551_device, port_w))
	MCFG_QUANTUM_PERFECT_CPU(M6510T_TAG)

	MCFG_PLS100_ADD(PLA_TAG)
	MCFG_DEVICE_ADD(M6523_0_TAG, TPI6525, 0)
	MCFG_TPI6525_IN_PA_CB(READ8(*this, c1551_device, tcbm_data_r))
	MCFG_TPI6525_OUT_PA_CB(WRITE8(*this, c1551_device, tcbm_data_w))
	MCFG_TPI6525_IN_PB_CB(READ8(C64H156_TAG, c64h156_device, yb_r))
	MCFG_TPI6525_OUT_PB_CB(WRITE8(C64H156_TAG, c64h156_device, yb_w))
	MCFG_TPI6525_IN_PC_CB(READ8(*this, c1551_device, tpi0_pc_r))
	MCFG_TPI6525_OUT_PC_CB(WRITE8(*this, c1551_device, tpi0_pc_w))
	MCFG_DEVICE_ADD(M6523_1_TAG, TPI6525, 0)
	MCFG_TPI6525_IN_PA_CB(READ8(*this, c1551_device, tcbm_data_r))
	MCFG_TPI6525_OUT_PA_CB(WRITE8(*this, c1551_device, tcbm_data_w))
	MCFG_TPI6525_IN_PB_CB(READ8(*this, c1551_device, tpi1_pb_r))
	MCFG_TPI6525_IN_PC_CB(READ8(*this, c1551_device, tpi1_pc_r))
	MCFG_TPI6525_OUT_PC_CB(WRITE8(*this, c1551_device, tpi1_pc_w))

	MCFG_DEVICE_ADD(C64H156_TAG, C64H156, XTAL(16'000'000))
	MCFG_64H156_BYTE_CALLBACK(WRITELINE(C64H156_TAG, c64h156_device, atni_w))
	MCFG_FLOPPY_DRIVE_ADD_FIXED(C64H156_TAG":0", c1551_floppies, "525ssqd", c1551_device::floppy_formats)

	MCFG_PLUS4_PASSTHRU_EXPANSION_SLOT_ADD()
MACHINE_CONFIG_END


//-------------------------------------------------
//  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_t clock)
	: device_t(mconfig, C1551, tag, owner, clock)
	, 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_floppy(*this, C64H156_TAG":0:525ssqd")
	, m_exp(*this, PLUS4_EXPANSION_SLOT_TAG)
	, m_jp1(*this, "JP1")
	, m_led(*this, "led%u", 0U)
	, m_tcbm_data(0xff)
	, m_status(1)
	, m_dav(1)
	, m_ack(1)
	, m_dev(0)
	, m_irq_timer(nullptr)
{
}


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

void c1551_device::device_start()
{
	m_led.resolve();

	// allocate timers
	m_irq_timer = timer_alloc();
	m_irq_timer->adjust(attotime::zero, CLEAR_LINE);

	// install image callbacks
	m_ga->set_floppy(m_floppy);

	// 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_t 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_t 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_t c1551_device::plus4_cd_r(address_space &space, offs_t offset, uint8_t 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_t 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);
}