summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/kb3600.cpp
blob: 5400d8ac1a8826834fb7602a83a08c277401ad64 (plain) (tree)
1
2
3
4
5
6

                               



                                                                       










                                                                      
                
                   
 

                     







                                                                            
                                                                                 
 







                                                                            
                                                                                                             
                                                       












                                  
 
                                    
         
                         
         








                                                   












                                          




                                                                              

                  


                               
                                  



                                                   




                                                   


                                                   








                                                                                            
                                  












                                                          


                                            


                                             
                         





                                                     
 

                                         

                                        
                                                              
                                 

                                                                




                                                                      





                                                                         

                                                       

                                 
                                                                               
                         
                                                         










                         
                                 








                                                   
                             
 
                            
 
                              


                    
// license:BSD-3-Clause
// copyright-holders:R. Belmont
/**********************************************************************

    General Instruments AY-5-3600 Keyboard Encoder emulation

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

/*

    TODO:

    - scan timer clock frequency
    - more accurate emulation of real chip

*/

#include "emu.h"
#include "kb3600.h"

//#define VERBOSE 1
#include "logmacro.h"



//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

// devices
DEFINE_DEVICE_TYPE(AY3600, ay3600_device, "ay3600", "AY-5-3600 Keyboard Encoder")

//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  ay3600_device - constructor
//-------------------------------------------------

ay3600_device::ay3600_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, AY3600, tag, owner, clock),
	m_read_x0(*this),
	m_read_x1(*this),
	m_read_x2(*this),
	m_read_x3(*this),
	m_read_x4(*this),
	m_read_x5(*this),
	m_read_x6(*this),
	m_read_x7(*this),
	m_read_x8(*this),
	m_read_shift(*this),
	m_read_control(*this),
	m_write_data_ready(*this),
	m_write_ako(*this)
{
	for (auto & elem : m_x_mask)
	{
		elem = 0;
	}
}

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

void ay3600_device::device_start()
{
	// resolve callbacks
	m_read_x0.resolve_safe(0);
	m_read_x1.resolve_safe(0);
	m_read_x2.resolve_safe(0);
	m_read_x3.resolve_safe(0);
	m_read_x4.resolve_safe(0);
	m_read_x5.resolve_safe(0);
	m_read_x6.resolve_safe(0);
	m_read_x7.resolve_safe(0);
	m_read_x8.resolve_safe(0);
	m_read_shift.resolve_safe(0);
	m_read_control.resolve_safe(0);
	m_write_data_ready.resolve_safe();
	m_write_ako.resolve_safe();

	// allocate timers
	m_scan_timer = timer_alloc();
	m_scan_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));

	m_ako = 0;

	// state saving
	save_item(NAME(m_b));
	save_item(NAME(m_ako));
	save_item(NAME(m_x_mask));
}


//-------------------------------------------------
//  device_start - device-specific reset
//-------------------------------------------------

void ay3600_device::device_reset()
{
}

//-------------------------------------------------
//  device_timer - handler timer events
//-------------------------------------------------

void ay3600_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	int ako = 0;

	for (int x = 0; x < 9; x++)
	{
		uint16_t data = 0;

		switch(x)
		{
			case 0: data = m_read_x0(); break;
			case 1: data = m_read_x1(); break;
			case 2: data = m_read_x2(); break;
			case 3: data = m_read_x3(); break;
			case 4: data = m_read_x4(); break;
			case 5: data = m_read_x5(); break;
			case 6: data = m_read_x6(); break;
			case 7: data = m_read_x7(); break;
			case 8: data = m_read_x8(); break;
		}

		for (int y = 0; y < 10; y++)
		{
			int b = (x * 10) + y;

			if (b > 63)
			{
				b -= 64;
				b = 0x100 | b;
			}

			b |= (m_read_shift() << 6);
			b |= (m_read_control() << 7);

			if (BIT(data, y))
			{
				ako = 1;

				if (!(m_x_mask[x] & (1 << y)))
				{
					m_x_mask[x] |= (1 << y);

					if (m_b != b)
					{
						m_b = b;

						m_write_data_ready(1);

						if (ako != m_ako)
						{
							m_write_ako(ako);
							m_ako = ako;
						}
						return;
					}
				}
			}
			else    // key released, unmark it from the "down" info
			{
				m_x_mask[x] &= ~(1 << y);
			}
		}
	}

	if (!ako)
	{
		m_b = -1;
	}

	if (ako != m_ako)
	{
		m_write_ako(ako);
		m_ako = ako;
	}
}


//-------------------------------------------------
//  b_r -
//-------------------------------------------------

uint16_t ay3600_device::b_r()
{
	uint16_t data = m_b;

	m_write_data_ready(0);

	return data;
}