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





                                                                               
                
                            
 











                                                                              
                                                   
 
                                 















                                                                                           
  
 







                                                                           
                                                                  
 
                            
 
                                        
 

                                                 







                                                  
                                                            
 

                                                                  









                                                                             
                                                 
 
                      
                                   
 


                                                             
 
                     
                      



















                                                                           










                      
                            
 
                     














                                                                              
                                                                 
 


                       
                                
 
                            

                                 
                                                                                                 
 
                                                
                 
                                                     
                         
                                         



                                       
                                                    


                                                     
                                                                                                       
                 
                                                     
                 
                                           
                 



                               
                                                    







                                                                    
                         







                                                                        

                                                          
                                               








                                                                                  
                                        




                      

 























                                                                              
                                     
         
                         
































                                                                                           






                                                             
                              
 
                                             

                           




                                                                               
                                       

                         
                      
                                             
                                                                                     


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

  machine/model3.c: functions emulating various aspects of the Model 3 hardware

*/

#include "emu.h"
#include "includes/model3.h"


/******************************************************************/
/* Real3D TAP Port                                                */
/******************************************************************/

/*
 * TAP Finite State Machine
 *
 * Y are states and X are outgoing paths. Constructed from information on page
 * 167 of the 3D-RAM manual.
 */

#define NEXT(new_state) fsm[m_tap_state][new_state]

static const int32_t fsm[][2] = {
							{  1,  0 },  // 0  Test-Logic/Reset
							{  1,  2 },  // 1  Run-Test/Idle
							{  3,  9 },  // 2  Select-DR-Scan
							{  4,  5 },  // 3  Capture-DR
							{  4,  5 },  // 4  Shift-DR
							{  6,  8 },  // 5  Exit1-DR
							{  6,  7 },  // 6  Pause-DR
							{  4,  8 },  // 7  Exit2-DR
							{  1,  2 },  // 8  Update-DR
							{ 10,  0 },  // 9  Select-IR-Scan
							{ 11, 12 },  // 10 Capture-IR
							{ 11, 12 },  // 11 Shift-IR
							{ 13, 15 },  // 12 Exit1-IR
							{ 13, 14 },  // 13 Pause-IR
							{ 11, 15 },  // 14 Exit2-IR
							{  1,  2 }   // 15 Update-IR
};


/*
 * insert_bit():
 *
 * Inserts a bit into an arbitrarily long bit field. Bit 0 is assumed to be
 * the MSB of the first byte in the buffer.
 */

static void insert_bit(uint8_t *buf, int32_t bit_num, int32_t bit)
{
	int32_t bit_in_byte;

	bit_in_byte = 7 - (bit_num & 7);

	buf[bit_num / 8] &= ~(1 << bit_in_byte);
	buf[bit_num / 8] |= (bit << bit_in_byte);
}

/*
 * insert_id():
 *
 * Inserts a 32-bit ID code into the ID bit field.
 */

void model3_state::insert_id(uint32_t id, int32_t start_bit)
{
	for (int i = 31; i >= 0; i--)
		insert_bit(m_id_data, start_bit++, (id >> i) & 1);
}

/*
 * shift():
 *
 * Shifts the data buffer right (towards LSB at byte 0) by 1 bit. The size of
 * the number of bits must be specified. The bit shifted out of the LSB is
 * returned.
 */

static int shift(uint8_t *data, int32_t num_bits)
{
	int32_t     i;
	int    shift_out, shift_in;

	/*
	 * This loop takes care of all the fully-filled bytes
	 */

	shift_in = 0;
	shift_out = 0;
	for (i = 0; i < num_bits / 8; i++)
	{
		shift_out = data[i] & 1;
		data[i] >>= 1;
		data[i] |= (shift_in << 7);
		shift_in = shift_out;   // carry over to next element's MSB
	}

	/*
	 * Take care of the last partial byte (if there is one)
	 */

	if ((num_bits & 7) != 0)
	{
		shift_out = (data[i] >> (8 - (num_bits & 7))) & 1;
		data[i] >>= 1;
		data[i] |= (shift_in << 7);
	}

	return shift_out;
}

/*
 * int tap_read(void);
 *
 * Reads TDO.
 *
 * Returns:
 *      TDO.
 */

int model3_state::tap_read()
{
	return m_tdo;
}

/*
 * void tap_write(int tck, int tms, int tdi, int trst);
 *
 * Writes to the TAP. State changes only occur on the rising edge of the clock
 * (tck = 1.)
 *
 * Parameters:
 *      tck  = Clock.
 *      tms  = Test mode select.
 *      tdi  = Serial data input. Must be 0 or 1 only!
 *      trst = Reset.
 */

void model3_state::tap_write(int tck, int tms, int tdi, int trst)
{
	if (!tck)
		return;

	m_tap_state = NEXT(tms);

	switch (m_tap_state)
	{
	case 3:     // Capture-DR
		//printf("capture dr (IR = %08X%08X\n", (uint32_t)(m_ir >> 32),(uint32_t)(m_ir));

		if (m_ir == 0x000023fffffffffeU)
		{
			for (auto & elem : m_id_data)
			{
				elem = 0;
			}

			m_id_size = 41;

			uint64_t res = 0x0040000000;

			int start_bit = 0;
			for (int i = 41; i >= 0; i--)
				insert_bit(m_id_data, start_bit++, ((uint64_t)(1 << i) & res) ? 1 : 0);
		}
		else if (m_ir == 0x00000c631f8c7ffeU)
		{
			tap_set_asic_ids();
		}
		break;

	case 4:     // Shift-DR

		m_tdo = shift(m_id_data, m_id_size);
		break;

	case 10:    // Capture-IR

		/*
		 * Load lower 2 bits with 01 as per IEEE 1149.1-1990
		 */

		m_ir = 1;
		break;

	case 11:    // Shift-IR

		/*
		 * Shift IR towards output and load in new data from TDI
		 */

		m_tdo = m_ir & 1;   // shift LSB to output
		m_ir >>= 1;
		m_ir |= ((uint64_t) tdi << 45);
		break;

	case 15:    // Update-IR

		/*
		 * Latch IR (technically, this should occur on the falling edge of
		 * TCK)
		 */

		m_ir &= 0x3fffffffffffU;
		break;

	default:
		break;
	}
}

void model3_state::tap_set_asic_ids()
{
	/*
	 * Read ASIC IDs.
	 *
	 * The ID Sequence is:
	 *  - Jupiter
	 *  - Mercury
	 *  - Venus
	 *  - Earth
	 *  - Mars
	 *  - Mars (again)
	 *
	 * Note that different Model 3 steps have different chip
	 * revisions, hence the different IDs returned below.
	 *
	 * On Step 1.5 and 1.0, instruction 0x0C631F8C7FFE is used to retrieve
	 * the ID codes but Step 2.0 is a little weirder. It seems to use this
	 * and either the state of the TAP after reset or other instructions
	 * to read the IDs as well. This can be emulated in one of 2 ways:
	 * Ignore the instruction and always load up the data or load the
	 * data on TAP reset and when the instruction is issued.
	 */

	for (auto & elem : m_id_data)
	{
		elem = 0;
	}

	if (m_m3_step == 0x10)
	{
		insert_id(0x116C7057, 1 + 0 * 32);
		insert_id(0x216C3057, 1 + 1 * 32);
		insert_id(0x116C4057, 1 + 2 * 32);
		insert_id(0x216C5057, 1 + 3 * 32);
		insert_id(0x116C6057, 1 + 4 * 32 + 1);
		insert_id(0x116C6057, 1 + 5 * 32 + 1);
	}
	else if (m_m3_step == 0x15)
	{
		insert_id(0x316C7057, 1 + 0 * 32);
		insert_id(0x316C3057, 1 + 1 * 32);
		insert_id(0x216C4057, 1 + 2 * 32);      // Lost World may to use 0x016C4057
		insert_id(0x316C5057, 1 + 3 * 32);
		insert_id(0x216C6057, 1 + 4 * 32 + 1);
		insert_id(0x216C6057, 1 + 5 * 32 + 1);
	}
	else if (m_m3_step >= 0x20)
	{
		insert_id(0x416C7057, 1 + 0 * 32);
		insert_id(0x416C3057, 1 + 1 * 32);
		insert_id(0x316C4057, 1 + 2 * 32);
		insert_id(0x416C5057, 1 + 3 * 32);
		insert_id(0x316C6057, 1 + 4 * 32 + 1);
		insert_id(0x316C6057, 1 + 5 * 32 + 1);
	}

	m_id_size = 197;  // 197 bits
}


/*
 * void tap_reset(void);
 *
 * Resets the TAP (simulating a power up or SCAN_RST signal.)
 */

void model3_state::tap_reset()
{
	m_tap_state = 0;  // test-logic/reset

	tap_set_asic_ids();
}

/*****************************************************************************/
/* Epson RTC-72421 */

READ32_MEMBER(model3_state::rtc72421_r)
{
	int reg = offset;
	uint32_t data;
	data = m_rtc->read(space, reg) << 24;
	data |= 0x30000;    /* these bits are set to pass the battery voltage test */
	return data;
}

WRITE32_MEMBER(model3_state::rtc72421_w)
{
	m_rtc->write(space, offset, data >> 24);
}