summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/fidel_clockdiv.cpp
blob: 13ec96c2ee113d0ce51c81366deef022204b5445 (plain) (tree)
1
2
3
4
5
6
7
8
9



                                                                               

                                                                                        
 

                                                                            

                                                                                  


                                                                                  


                                                                               
                                   

 
                
 
                                          
 

                                                                                        

 
 



                                                            
                                                                                                                         






                                                            
                                                                                                                         




                                               
 
                 
 
                                                          
 
                                   


                                                                            
                                                                       
 

                                      

 
                                                        
 









                                                        

                                        
                                             

                                                                          
                                                                                          
                                               









                                      
                














                                                                                                                                    
 
// license:BSD-3-Clause
// copyright-holders:hap
/******************************************************************************

Fidelity Electronics 6502 dynamic(offset-dependent) CPU clock divider base class.
Used to compensate slow memory chips in chess computer models: SC12, AS12, PC, EAS, EAG.

TODO:
- improve clock divider? it seems a little bit slower than the real machine.
  Currently, a dummy timer workaround is needed, or it's much worse (doing it with
  a synchronize() will make it even worse).
  Is the problem here due to timing of CPU addressbus changes? We can only 'sense'
  the addressbus at read or write accesses.

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

#include "emu.h"
#include "machine/fidel_clockdiv.h"


// machine start

void fidel_clockdiv_state::machine_start()
{
	// dummy timer for cpu divider
	m_div_timer = machine().scheduler().timer_alloc(timer_expired_delegate(), this);
}


// input ports

INPUT_PORTS_START( fidel_clockdiv_2 )
	PORT_START("div_config") // hardwired, default to /2
	PORT_CONFNAME( 0x03, 0x02, "CPU Divider" ) PORT_CHANGED_MEMBER(DEVICE_SELF, fidel_clockdiv_state, div_changed, 0)
	PORT_CONFSETTING(    0x00, "Disabled" )
	PORT_CONFSETTING(    0x02, "2" )
	PORT_CONFSETTING(    0x03, "4" )
INPUT_PORTS_END

INPUT_PORTS_START( fidel_clockdiv_4 )
	PORT_START("div_config") // hardwired, default to /4
	PORT_CONFNAME( 0x03, 0x03, "CPU Divider" ) PORT_CHANGED_MEMBER(DEVICE_SELF, fidel_clockdiv_state, div_changed, 0)
	PORT_CONFSETTING(    0x00, "Disabled" )
	PORT_CONFSETTING(    0x02, "2" )
	PORT_CONFSETTING(    0x03, "4" )
INPUT_PORTS_END


// implementation

void fidel_clockdiv_state::div_set_cpu_freq(offs_t offset)
{
	if (offset != m_div_status)
	{
		// when a13/a14 is high, XTAL goes through divider(s)
		// (depending on factory-set jumper, either one or two 7474)
		m_maincpu->set_clock_scale(offset ? m_div_scale : 1.0);

		m_div_status = offset;
	}
}

void fidel_clockdiv_state::div_refresh(ioport_value val)
{
	if (val == 0xff)
	{
		// bail out if there is no cpu divider
		ioport_port *inp = ioport("div_config");
		if (inp == nullptr)
			return;

		val = inp->read();
	}

	m_maincpu->set_clock_scale(1.0);
	m_div_status = ~0;
	m_div_scale = (val & 1) ? 0.25 : 0.5;

	// stop high frequency background timer if cpu divider is disabled
	attotime period = (val) ? attotime::from_hz(m_maincpu->clock()) : attotime::never;
	m_div_timer->adjust(period, 0, period);

	// set up memory passthroughs
	if (m_read_tap)
	{
		m_read_tap->remove();
		m_write_tap->remove();
		m_read_tap = nullptr;
		m_write_tap = nullptr;
	}

	if (val)
	{
		address_space &program = m_maincpu->space(AS_PROGRAM);

		m_read_tap = program.install_read_tap(0x0000, 0xffff, "program_div_r",[this](offs_t offset, u8 &data, u8 mem_mask)
		{
			if (!machine().side_effects_disabled())
				div_set_cpu_freq(offset & 0x6000);
			return data;
		});
		m_write_tap = program.install_write_tap(0x0000, 0xffff, "program_div_w",[this](offs_t offset, u8 &data, u8 mem_mask)
		{
			div_set_cpu_freq(offset & 0x6000);
			return data;
		});
	}
}