diff --git a/src/emu/machine/tms1024.c b/src/emu/machine/tms1024.c index b5dfd018b87..d728f7dfd28 100644 --- a/src/emu/machine/tms1024.c +++ b/src/emu/machine/tms1024.c @@ -1,36 +1,75 @@ // license:BSD-3-Clause // copyright-holders:hap -/********************************************************************** +/* - Texas Instruments TMS1024, TMS1025 I/O expander emulation + Texas Instruments TMS1024/TMS1025 I/O expander + + No documentation was available, just a pinout. + Other than more port pins, TMS1025 is assumed to be same as TMS1024. + + TODO: + - writes to port 0 + - what's the MS pin? + - strobe is on rising edge? or falling edge? -**********************************************************************/ +*/ #include "machine/tms1024.h" const device_type TMS1024 = &device_creator; +const device_type TMS1025 = &device_creator; //------------------------------------------------- -// tms1024_device - constructor +// constructor //------------------------------------------------- tms1024_device::tms1024_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, TMS1024, "TMS1024", tag, owner, clock, "tms1024", __FILE__) + : device_t(mconfig, TMS1024, "TMS1024 I/O Expander", tag, owner, clock, "tms1024", __FILE__), + m_write_port1(*this), m_write_port2(*this), m_write_port3(*this), m_write_port4(*this), m_write_port5(*this), m_write_port6(*this), m_write_port7(*this) { } +tms1024_device::tms1024_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_write_port1(*this), m_write_port2(*this), m_write_port3(*this), m_write_port4(*this), m_write_port5(*this), m_write_port6(*this), m_write_port7(*this) +{ +} + +tms1025_device::tms1025_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : tms1024_device(mconfig, TMS1025, "TMS1025 I/O Expander", tag, owner, clock, "tms1025", __FILE__) +{ +} + + + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void tms1024_device::device_start() { - // resolve callbacks + // resolve callbacks (there is no port 0) + m_write_port1.resolve_safe(); m_write_port[0] = &m_write_port1; + m_write_port2.resolve_safe(); m_write_port[1] = &m_write_port2; + m_write_port3.resolve_safe(); m_write_port[2] = &m_write_port3; + m_write_port4.resolve_safe(); m_write_port[3] = &m_write_port4; + m_write_port5.resolve_safe(); m_write_port[4] = &m_write_port5; + m_write_port6.resolve_safe(); m_write_port[5] = &m_write_port6; + m_write_port7.resolve_safe(); m_write_port[6] = &m_write_port7; + + // zerofill + m_h = 0; + m_s = 0; + m_std = 0; // register for savestates + save_item(NAME(m_h)); + save_item(NAME(m_s)); + save_item(NAME(m_std)); } + //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- @@ -40,4 +79,33 @@ void tms1024_device::device_reset() } -// handlers + +//------------------------------------------------- +// handlers +//------------------------------------------------- + +WRITE8_MEMBER(tms1024_device::write_h) +{ + // H1,2,3,4: data for outputs A,B,C,D + m_h = data & 0xf; +} + +WRITE8_MEMBER(tms1024_device::write_s) +{ + // S0,1,2: select port + m_s = data & 7; +} + +WRITE_LINE_MEMBER(tms1024_device::write_std) +{ + state = (state) ? 1 : 0; + + // output on rising edge + if (state && !m_std) + { + if (m_s != 0) + (*m_write_port[m_s-1])((offs_t)(m_s-1), m_h); + } + + m_std = state; +} diff --git a/src/emu/machine/tms1024.h b/src/emu/machine/tms1024.h index e5afe4ea75e..e91c0ca5a2d 100644 --- a/src/emu/machine/tms1024.h +++ b/src/emu/machine/tms1024.h @@ -1,10 +1,39 @@ // license:BSD-3-Clause // copyright-holders:hap -/********************************************************************** +/* - Texas Instruments TMS1024, TMS1025 I/O expander emulation + Texas Instruments TMS1024/TMS1025 I/O expander -********************************************************************** +*/ + +#ifndef _TMS1024_H_ +#define _TMS1024_H_ + +#include "emu.h" + + +// ports setup + +// 4-bit ports (3210 = DCBA) +// valid ports: 4-7 for TMS1024, 1-7 for TMS1025 +#define MCFG_TMS1024_WRITE_PORT_CB(X, _devcb) \ + tms1024_device::set_write_port##X##_callback(*device, DEVCB_##_devcb); + +enum +{ + TMS1024_PORT1 = 0, + TMS1024_PORT2, + TMS1024_PORT3, + TMS1024_PORT4, + TMS1024_PORT5, + TMS1024_PORT6, + TMS1024_PORT7 +}; + + +// pinout reference + +/* ____ ____ ____ ____ Vss 1 |* \_/ | 28 H2 Vss 1 |* \_/ | 40 H2 @@ -23,48 +52,59 @@ D5 14 |___________| 15 A6 D4 14 | | 27 A7 A5 15 | | 26 D6 B5 16 | | 25 C6 - C5 17 | | 24 B6 - D5 18 | | 23 A6 - A2 19 | | 22 D2 - B2 20 |___________| 21 C2 + CE: Chip Enable C5 17 | | 24 B6 + MS: Master S.? D5 18 | | 23 A6 + STD: STrobe Data? A2 19 | | 22 D2 + S: Select B2 20 |___________| 21 C2 + H: Hold? -**********************************************************************/ +*/ -#ifndef _TMS1024_H_ -#define _TMS1024_H_ - -#include "emu.h" - - -//************************************************************************** -// INTERFACE CONFIGURATION MACROS -//************************************************************************** - -#define MCFG_TMS1024_ADD(_tag) \ - MCFG_DEVICE_ADD(_tag, TMS1024, 0) - - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> tms1024_device class tms1024_device : public device_t { public: tms1024_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + tms1024_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); // static configuration helpers + template static devcb_base &set_write_port1_callback(device_t &device, _Object object) { return downcast(device).m_write_port1.set_callback(object); } + template static devcb_base &set_write_port2_callback(device_t &device, _Object object) { return downcast(device).m_write_port2.set_callback(object); } + template static devcb_base &set_write_port3_callback(device_t &device, _Object object) { return downcast(device).m_write_port3.set_callback(object); } + template static devcb_base &set_write_port4_callback(device_t &device, _Object object) { return downcast(device).m_write_port4.set_callback(object); } + template static devcb_base &set_write_port5_callback(device_t &device, _Object object) { return downcast(device).m_write_port5.set_callback(object); } + template static devcb_base &set_write_port6_callback(device_t &device, _Object object) { return downcast(device).m_write_port6.set_callback(object); } + template static devcb_base &set_write_port7_callback(device_t &device, _Object object) { return downcast(device).m_write_port7.set_callback(object); } + + DECLARE_WRITE8_MEMBER(write_h); + DECLARE_WRITE8_MEMBER(write_s); + DECLARE_WRITE_LINE_MEMBER(write_std); protected: // device-level overrides virtual void device_start(); virtual void device_reset(); + + UINT8 m_h; // 4-bit data latch + UINT8 m_s; // 3-bit port select + UINT8 m_std; // strobe pin + + // callbacks + devcb_write8 m_write_port1, m_write_port2, m_write_port3, m_write_port4, m_write_port5, m_write_port6, m_write_port7; + devcb_write8 *m_write_port[7]; }; -// device type definition + +class tms1025_device : public tms1024_device +{ +public: + tms1025_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; + + + extern const device_type TMS1024; +extern const device_type TMS1025; #endif /* _TMS1024_H_ */ diff --git a/src/mess/drivers/hh_tms1k.c b/src/mess/drivers/hh_tms1k.c index b469d5d11b3..d0eaa7b6ced 100644 --- a/src/mess/drivers/hh_tms1k.c +++ b/src/mess/drivers/hh_tms1k.c @@ -118,6 +118,7 @@ #include "starwbc.lh" #include "stopthie.lh" #include "tandy12.lh" // clickable +//#include "tbreakup.lh" #include "tc4.lh" #include "einvader.lh" // test-layout(but still playable) @@ -3992,7 +3993,8 @@ MACHINE_CONFIG_END /*************************************************************************** - Tomy(tronics) Break Up + Tomy(tronics) Break Up (manufactured in Japan) + * PCB label TOMY B.O. * TMS1040 MP2726 TOMY WIPE (die labeled MP2726A) * TMS1025N2LL I/O expander * 2-digit 7seg display, 46 other leds, 1bit sound @@ -4002,15 +4004,40 @@ MACHINE_CONFIG_END - Japan: Block Attack - UK: Break-In + lamp translation table: led zz from game PCB = MESS lampyx: + + 00 = - 10 = lamp25 20 = lamp44 + 01 = lamp27 11 = lamp35 21 = lamp53 + 02 = lamp37 12 = lamp45 22 = lamp42 + 03 = lamp47 13 = lamp55 + 04 = lamp57 14 = lamp54 + 05 = lamp26 15 = lamp33 + 06 = lamp36 16 = lamp43 + 07 = lamp46 17 = lamp23 + 08 = lamp56 18 = lamp34 + 09 = lamp24 19 = lamp32 + + the 7seg panel is lamp0x and lamp1x(aka digit0/1), and the + 8(2*4) * 3 rectangular leds panel, where x=0,1,2,3: + + lamp7x lamp6x + lamp9x lamp8x + lamp11x lamp10x + ***************************************************************************/ class tbreakup_state : public hh_tms1k_state { public: tbreakup_state(const machine_config &mconfig, device_type type, const char *tag) - : hh_tms1k_state(mconfig, type, tag) + : hh_tms1k_state(mconfig, type, tag), + m_expander(*this, "expander") { } + required_device m_expander; + UINT8 m_exp_port[7]; + DECLARE_WRITE8_MEMBER(expander_w); + void prepare_display(); DECLARE_WRITE16_MEMBER(write_r); DECLARE_WRITE16_MEMBER(write_o); @@ -4021,33 +4048,89 @@ public: protected: virtual void machine_reset(); + virtual void machine_start(); }; // handlers void tbreakup_state::prepare_display() { + // 7seg leds from R0,R1 and O0-O6 + for (int y = 0; y < 2; y++) + { + m_display_segmask[y] = 0x7f; + m_display_state[y] = (m_r >> y & 1) ? (m_o & 0x7f) : 0; + } + + // 22 round leds from expander port 7 and O2-O7 + for (int y = 0; y < 4; y++) + m_display_state[y+2] = (m_exp_port[6] >> y & 1) ? (m_o & 0xfc) : 0; + + // 24 rectangular leds from expander ports 1-6 (not strobed) + for (int y = 0; y < 6; y++) + m_display_state[y+6] = m_exp_port[y]; + + set_display_size(8, 12); + display_update(); +} + +WRITE8_MEMBER(tbreakup_state::expander_w) +{ + // TMS1025 port 1-7 data + m_exp_port[offset] = data; + prepare_display(); } WRITE16_MEMBER(tbreakup_state::write_r) { + // R6: speaker out + m_speaker->level_w(data >> 6 & 1); + + // R7,R8: input mux + m_inp_mux = data >> 7 & 3; + + // R3-R5: TMS1025 port S + // R2: TMS1025 STD pin + m_expander->write_s(space, 0, data >> 3 & 7); + m_expander->write_std(data >> 2 & 1); + + // R0,R1: select digit + m_r = ~data; prepare_display(); } WRITE16_MEMBER(tbreakup_state::write_o) { + // O0-O3: TMS1025 port H + m_expander->write_h(space, 0, data & 0xf); + + // O0-O7: led state + m_o = data; prepare_display(); } READ8_MEMBER(tbreakup_state::read_k) { - return 0; + // K4: fixed input + // K8: multiplexed inputs + return (m_inp_matrix[2]->read() & 4) | (read_inputs(2) & 8); } // config static INPUT_PORTS_START( tbreakup ) + PORT_START("IN.0") // R7 K8 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Ball") + + PORT_START("IN.1") // R8 K8 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Hit") + + PORT_START("IN.2") // K4 + PORT_CONFNAME( 0x04, 0x00, DEF_STR( Lives ) ) + PORT_CONFSETTING( 0x00, "3" ) + PORT_CONFSETTING( 0x04, "5" ) + PORT_START("IN.3") // fake PORT_CONFNAME( 0x01, 0x00, "Skill Level" ) PORT_CHANGED_MEMBER(DEVICE_SELF, tbreakup_state, skill_switch, NULL) PORT_CONFSETTING( 0x00, "Pro 1" ) @@ -4072,6 +4155,15 @@ void tbreakup_state::machine_reset() set_clock(); } +void tbreakup_state::machine_start() +{ + hh_tms1k_state::machine_start(); + + // zerofill/register for savestates + memset(m_exp_port, 0, sizeof(m_exp_port)); + save_item(NAME(m_exp_port)); +} + static MACHINE_CONFIG_START( tbreakup, tbreakup_state ) /* basic machine hardware */ @@ -4079,9 +4171,18 @@ static MACHINE_CONFIG_START( tbreakup, tbreakup_state ) MCFG_TMS1XXX_READ_K_CB(READ8(tbreakup_state, read_k)) MCFG_TMS1XXX_WRITE_R_CB(WRITE16(tbreakup_state, write_r)) MCFG_TMS1XXX_WRITE_O_CB(WRITE16(tbreakup_state, write_o)) + + MCFG_DEVICE_ADD("expander", TMS1025, 0) + MCFG_TMS1024_WRITE_PORT_CB(1, WRITE8(tbreakup_state, expander_w)) + MCFG_TMS1024_WRITE_PORT_CB(2, WRITE8(tbreakup_state, expander_w)) + MCFG_TMS1024_WRITE_PORT_CB(3, WRITE8(tbreakup_state, expander_w)) + MCFG_TMS1024_WRITE_PORT_CB(4, WRITE8(tbreakup_state, expander_w)) + MCFG_TMS1024_WRITE_PORT_CB(5, WRITE8(tbreakup_state, expander_w)) + MCFG_TMS1024_WRITE_PORT_CB(6, WRITE8(tbreakup_state, expander_w)) + MCFG_TMS1024_WRITE_PORT_CB(7, WRITE8(tbreakup_state, expander_w)) MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_tms1k_state, display_decay_tick, attotime::from_msec(1)) -// MCFG_DEFAULT_LAYOUT(layout_tbreakup) +// MCFG_DEFAULT_LAYOUT(layout_tbreakup) MCFG_DEFAULT_LAYOUT(layout_hh_tms1k_test) /* no video! */