/* machine/model3.c: functions emulating various aspects of the Model 3 hardware */ #include "driver.h" static int m3_step; /******************************************************************/ /* 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[state][new_state] static INT32 state; // current state static INT32 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 }; /* * TAP Registers */ static UINT64 current_instruction; // latched IR (not always equal to IR) static UINT64 ir; // instruction register (46 bits) static UINT8 id_data[32]; // ASIC ID code data buffer static INT32 id_size; // size of ID data in bits //static INT32 ptr; // current bit ptr for data static int tdo; // bit shifted out to TDO /* * 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 *buf, INT32 bit_num, INT32 bit) { INT32 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. */ static void insert_id(UINT32 id, INT32 start_bit) { INT32 i; for (i = 31; i >= 0; i--) insert_bit(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 *data, INT32 num_bits) { INT32 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_tap_read(void) { return 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_tap_write(int tck, int tms, int tdi, int trst) { if (!tck) return; state = NEXT(tms); switch (state) { case 3: // Capture-DR /* * 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. */ if (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 (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 (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); } break; case 4: // Shift-DR tdo = shift(id_data, id_size); break; case 10: // Capture-IR /* * Load lower 2 bits with 01 as per IEEE 1149.1-1990 */ ir = 1; break; case 11: // Shift-IR /* * Shift IR towards output and load in new data from TDI */ tdo = ir & 1; // shift LSB to output ir >>= 1; ir |= ((UINT64) tdi << 45); break; case 15: // Update-IR /* * Latch IR (technically, this should occur on the falling edge of * TCK) */ ir &= U64(0x3fffffffffff); current_instruction = ir; break; default: break; } } /* * void tap_reset(void); * * Resets the TAP (simulating a power up or SCAN_RST signal.) */ void model3_tap_reset(void) { id_size = 197; // 197 bits state = 0; // test-logic/reset } /* * void model3_machine_init(int step) * * step = BCD hardware rev. 0x10 for 1.0, 0x15 for 1.5, 0x20 for 2.0, etc. * */ void model3_machine_init(int step) { m3_step = step; } /*****************************************************************************/ /* Epson RTC-72421 */ static UINT8 rtc_get_reg(int reg) { mame_system_time systime; mame_get_current_datetime(Machine, &systime); switch(reg) { case 0: // 1-second digit return (systime.local_time.second % 10) & 0xf; case 1: // 10-seconds digit return (systime.local_time.second / 10) & 0x7; case 2: // 1-minute digit return (systime.local_time.minute % 10) & 0xf; case 3: // 10-minute digit return (systime.local_time.minute / 10) & 0x7; case 4: // 1-hour digit return (systime.local_time.hour % 10) & 0xf; case 5: // 10-hours digit return (systime.local_time.hour / 10) & 0x7; case 6: // 1-day digit (days in month) return (systime.local_time.mday % 10) & 0xf; case 7: // 10-days digit return (systime.local_time.mday / 10) & 0x3; case 8: // 1-month digit return ((systime.local_time.month + 1) % 10) & 0xf; case 9: // 10-months digit return ((systime.local_time.month + 1) / 10) & 0x1; case 10: // 1-year digit return (systime.local_time.year % 10) & 0xf; case 11: // 10-years digit return ((systime.local_time.year % 100) / 10) & 0xf; case 12: // day of the week return systime.local_time.weekday & 0x7; case 13: return 0; case 14: return 0; case 15: return 0; default: fatalerror("RTC-72421: Unknown reg %02X", reg); return 0; } } READ32_HANDLER(rtc72421_r) { int reg = offset; UINT32 data; data = rtc_get_reg(reg) << 24; data |= 0x30000; /* these bits are set to pass the battery voltage test */ return data; } WRITE32_HANDLER(rtc72421_w) { }