(MESS) devcb2 migration. (nw)

This commit is contained in:
Michael Zapf 2014-03-19 23:53:59 +00:00
parent 4b03839955
commit 57a3ca60e9
7 changed files with 798 additions and 409 deletions

View File

@ -4,6 +4,29 @@
TMS9901 Programmable System Interface
+--------------+
RST1*| 1 | | 40| Vcc
CRUOUT | 2 +--+ 39| S0
CRUCLK | 3 38| P0
CRUIN | 4 37| P1
CE*| 5 36| S1
INT6*| 6 35| S2
INT5*| 7 34| INT7* / P15
INT4*| 8 33| INT8* / P14
INT3*| 9 32| INT9* / P13
Phi*|10 31| INT10* / P12
INTREQ*|11 30| INT11* / P11
IC3 |12 29| INT12* / P10
IC2 |13 28| INT13* / P9
IC1 |14 27| INT14* / P8
IC0 |15 26| P2
Vss |16 25| S3
INT1*|17 24| S4
INT2*|18 23| INT15* / P7
P6 |19 22| P3
P5 |20 21| P4
+--------------+
Overview:
TMS9901 is a support chip for TMS9900. It handles interrupts, provides
several I/O pins, and a timer (a.k.a. clock: it is merely a register which
@ -101,14 +124,36 @@ TODO: Tests on a real machine
#include "tms9901.h"
#define VERBOSE 1
#define LOG logerror
/*
Debugging flags.
*/
#define TRACE_PINS 0
#define TRACE_CLOCK 0
#define TRACE_MODE 0
/*
Constructor
*/
tms9901_device::tms9901_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, TMS9901, "TMS9901 Programmable System Interface", tag, owner, clock, "tms9901", __FILE__)
: device_t(mconfig, TMS9901, "TMS9901 Programmable System Interface", tag, owner, clock, "tms9901", __FILE__),
m_read_block(*this),
m_write_p0(*this),
m_write_p1(*this),
m_write_p2(*this),
m_write_p3(*this),
m_write_p4(*this),
m_write_p5(*this),
m_write_p6(*this),
m_write_p7(*this),
m_write_p8(*this),
m_write_p9(*this),
m_write_p10(*this),
m_write_p11(*this),
m_write_p12(*this),
m_write_p13(*this),
m_write_p14(*this),
m_write_p15(*this),
m_interrupt(*this)
{
}
@ -119,24 +164,25 @@ void tms9901_device::field_interrupts(void)
{
int current_ints;
/* int_state: state of lines int1-int15 */
// m_int_state: inverted state of lines INT1*-INT15*. Bits are set by set_single_int only.
current_ints = m_int_state;
if (m_clock_register != 0)
{ /* if timer is enabled, INT3 pin is overriden by timer */
{
// if timer is enabled, INT3 pin is overridden by timer
if (m_timer_int_pending)
{
if (VERBOSE>8) LOG("tms9901: timer fires\n");
if (TRACE_CLOCK) logerror("%s: timer fires\n", tag());
current_ints |= TMS9901_INT3;
}
else
{
if (VERBOSE>8) LOG("tms9901: timer clear\n");
if (TRACE_CLOCK) logerror("%s: timer clear\n", tag());
current_ints &= ~TMS9901_INT3;
}
}
/* enabled_ints: enabled interrupts */
/* mask out all int pins currently set as output */
// enabled_ints: enabled interrupts
// Remove all settings from pins that are set as outputs (INT7*-INT15* share the same pins as P15-P7)
current_ints &= m_enabled_ints & (~m_pio_direction_mirror);
// Check whether we have a new state. For systems that use level-triggered
@ -147,12 +193,12 @@ void tms9901_device::field_interrupts(void)
m_old_int_state = current_ints;
if (current_ints)
if (current_ints != 0)
{
// find which interrupt tripped us:
// the number of the first (i.e. least significant) non-zero bit among
// the 16 first bits
// we simply look for the first bit set to 1 in current_ints... */
// we simply look for the first bit set to 1 in current_ints...
int level = 0;
while ((current_ints & 1)==0)
@ -162,13 +208,13 @@ void tms9901_device::field_interrupts(void)
}
m_int_pending = true;
if (!m_interrupt.isnull())
m_interrupt(level, 1); // the offset carries the IC0-3 level
m_interrupt(level, 1, 0xff); // the offset carries the IC0-3 level
}
else
{
m_int_pending = false;
if (!m_interrupt.isnull())
m_interrupt(0xf, 0); //Spec: INTREQ*=1 <=> IC0,1,2,3 = 1111
m_interrupt(0xf, 0, 0xff); //Spec: INTREQ*=1 <=> IC0,1,2,3 = 1111
}
}
@ -176,8 +222,8 @@ void tms9901_device::field_interrupts(void)
function which should be called by the driver when the state of an INTn*
pin changes (only required if the pin is set up as an interrupt pin)
state == 0: INTn* is inactive (high)
state != 0: INTn* is active (low)
state == CLEAR_LINE: INTn* is inactive (high)
state == ASSERT_LINE: INTn* is active (low)
0<=pin_number<=15
*/
@ -189,7 +235,6 @@ void tms9901_device::set_single_int(int pin_number, int state)
else
m_int_state &= ~(1 << pin_number);
/* we do not need to always call this function - time for an optimization */
field_interrupts();
}
@ -236,42 +281,50 @@ READ8_MEMBER( tms9901_device::read )
{
case 0:
if (m_clock_mode)
{ /* clock mode */
{
// Clock mode. The LSB reflects the CB bit which is set to 1 for clock mode.
answer = ((m_clock_read_register & 0x7F) << 1) | 0x01;
}
else
{ /* interrupt mode */
// m_int_state stores the INTx values, which are inverted to the pin levels (INTx*)
answer = ((~m_int_state) & m_supported_int_mask) & 0xFF;
{
// Interrupt mode
// Note that we rely on the read function to deliver the same
// INTx levels that have been signaled via the set_single_int method.
// This may mean that those levels must be latched by the callee.
if (!m_read_block.isnull())
answer |= m_read_block(TMS9901_CB_INT7);
answer &= ~ m_pio_direction_mirror;
// Remove the bits that are set as outputs (can only be INT7*)
answer &= ~m_pio_direction_mirror;
// Set those bits here
answer |= (m_pio_output_mirror & m_pio_direction_mirror) & 0xFF;
}
if (TRACE_PINS) logerror("%s: input on lines INT7..CB = %02x\n", tag(), answer);
break;
case 1:
if (m_clock_mode)
{ /* clock mode */
{
// clock mode
answer = (m_clock_read_register & 0x3F80) >> 7;
if (!m_int_pending)
answer |= 0x80;
}
else
{ /* interrupt mode */
answer = ((~m_int_state) & m_supported_int_mask) >> 8;
{
// See above concerning the INT levels.
if (!m_read_block.isnull())
answer |= m_read_block(TMS9901_INT8_INT15);
answer &= ~ (m_pio_direction_mirror >> 8);
// Remove the bits that are set as outputs (can be any line)
answer &= ~(m_pio_direction_mirror >> 8);
answer |= (m_pio_output_mirror & m_pio_direction_mirror) >> 8;
}
if (TRACE_PINS) logerror("%s: input on lines INT15..INT8 = %02x\n", tag(), answer);
break;
case 2:
/* exit timer mode */
// MZ: See comments at the beginning. I'm pretty sure this is not correct.
// MZ: See comments at the beginning. I'm sure that we do not quit clock mode.
// m_clock_mode = false;
if (!m_read_block.isnull())
@ -279,20 +332,22 @@ READ8_MEMBER( tms9901_device::read )
else
answer = 0;
answer &= ~ m_pio_direction;
answer &= ~m_pio_direction;
answer |= (m_pio_output & m_pio_direction) & 0xFF;
if (TRACE_PINS) logerror("%s: input on lines P7..P0 = %02x\n", tag(), answer);
break;
case 3:
// MZ: see above
// m_clock_mode = false; // exit timer mode
// m_clock_mode = false;
if (!m_read_block.isnull())
answer = m_read_block(TMS9901_P8_P15);
else
answer = 0;
answer &= ~ (m_pio_direction >> 8);
answer &= ~(m_pio_direction >> 8);
answer |= (m_pio_output & m_pio_direction) >> 8;
if (TRACE_PINS) logerror("%s: input on lines P15..P8 = %02x\n", tag(), answer);
break;
}
@ -317,19 +372,94 @@ WRITE8_MEMBER ( tms9901_device::write )
{
data &= 1; /* clear extra bits */
offset &= 0x01F;
switch (offset)
if (offset >= 0x10)
{
case 0x00: /* write to mode bit */
int pin = offset & 0x0F;
if (TRACE_PINS) logerror("%s: output on P%d = %d\n", tag(), pin, data);
int bit = (1 << pin);
// MZ: see above - I think this is wrong
// m_clock_mode = false; // exit timer mode
// Once a value is written to a pin, the pin remains in output mode
// until the chip is reset
m_pio_direction |= bit;
// Latch the value
if (data)
m_pio_output |= bit;
else
m_pio_output &= ~bit;
if (pin >= 7)
{
// pins P7-P15 are mirrored as INT15*-INT7*,
// also using the same pins in the package
int mirror_bit = (1 << (22 - pin));
// See above
m_pio_direction_mirror |= mirror_bit;
if (data)
m_pio_output_mirror |= mirror_bit;
else
m_pio_output_mirror &= ~mirror_bit;
}
switch (offset)
{
case 0x10:
if (!m_write_p0.isnull()) m_write_p0(data); break;
case 0x11:
if (!m_write_p1.isnull()) m_write_p1(data); break;
case 0x12:
if (!m_write_p2.isnull()) m_write_p2(data); break;
case 0x13:
if (!m_write_p3.isnull()) m_write_p3(data); break;
case 0x14:
if (!m_write_p4.isnull()) m_write_p4(data); break;
case 0x15:
if (!m_write_p5.isnull()) m_write_p5(data); break;
case 0x16:
if (!m_write_p6.isnull()) m_write_p6(data); break;
case 0x17:
if (!m_write_p7.isnull()) m_write_p7(data); break;
case 0x18:
if (!m_write_p8.isnull()) m_write_p8(data); break;
case 0x19:
if (!m_write_p9.isnull()) m_write_p9(data); break;
case 0x1A:
if (!m_write_p10.isnull()) m_write_p10(data); break;
case 0x1B:
if (!m_write_p11.isnull()) m_write_p11(data); break;
case 0x1C:
if (!m_write_p12.isnull()) m_write_p12(data); break;
case 0x1D:
if (!m_write_p13.isnull()) m_write_p13(data); break;
case 0x1E:
if (!m_write_p14.isnull()) m_write_p14(data); break;
case 0x1F:
if (!m_write_p15.isnull()) m_write_p15(data); break;
}
return;
}
if (offset == 0)
{
// Write to control bit (CB)
if (data == 0)
{
/* we are quitting clock mode */
// Switch to interrupt mode; quit clock mode
m_clock_mode = false;
if (VERBOSE>5) LOG("tms9901: int mode\n");
if (TRACE_MODE) logerror("%s: int mode\n", tag());
}
else
{
m_clock_mode = true;
if (VERBOSE>5) LOG("tms9901: clock mode\n");
if (TRACE_MODE) logerror("%s: clock mode\n", tag());
// we are switching to clock mode: latch the current value of
// the decrementer register
if (m_clock_register != 0)
@ -337,131 +467,75 @@ WRITE8_MEMBER ( tms9901_device::write )
else
m_clock_read_register = 0; /* timer inactive... */
}
break;
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0A:
case 0x0B:
case 0x0C:
case 0x0D:
case 0x0E:
// write one bit to 9901 (bits 1-14)
//
// m_clock_mode==false ? Disable/Enable an interrupt
// : Bit in clock interval
//
// offset is the index of the modified bit of register (-> interrupt number -1)
if (m_clock_mode)
{ /* modify clock interval */
int mask = 1 << ((offset & 0x0F) - 1); /* corresponding mask */
}
else
{
if (offset == 0x0f)
{
if (m_clock_mode)
{ /* in clock mode this is the soft reset bit */
if (!data)
{ // TMS9901 soft reset (RST2*)
// Spec: "Writing a 0 to bit 15 while in the clock mode executes a soft reset on the I/O pins.
// [...] RST2* will program all ports to the input mode"
m_pio_direction = 0;
m_pio_direction_mirror = 0;
if (data)
m_clock_register |= mask; /* set bit */
// "RST1* (power-up reset) will reset all mask bits low."
// Spec is not clear on whether the mask bits are also reset by RST2*
// TODO: Check on a real machine. (I'd guess from the text they are not touched)
m_enabled_ints = 0;
if (TRACE_MODE) logerror("%s: Soft reset (RST2*)\n", tag());
}
}
else
m_clock_register &= ~mask; /* clear bit */
{ /* modify interrupt enable mask */
if (data)
m_enabled_ints |= 0x4000; /* set bit */
else
m_enabled_ints &= ~0x4000; /* unset bit */
/* reset clock timer (page 8) */
if (VERBOSE>6) LOG("tms9901: clock register = %04x\n", m_clock_register);
timer_reload();
}
else
{ /* modify interrupt enable mask */
int mask = 1 << (offset & 0x0F); /* corresponding mask */
if (data)
m_enabled_ints |= mask; /* set bit */
else
m_enabled_ints &= ~mask; /* unset bit */
if (offset == 3)
m_timer_int_pending = false; /* SBO 3 clears pending timer interrupt (??) */
if (VERBOSE>6) LOG("tms9901: interrupts = %04x\n", m_enabled_ints);
field_interrupts(); /* changed interrupt state */
}
break;
case 0x0F:
if (m_clock_mode)
{ /* in clock mode this is the soft reset bit */
if (!data)
{ // TMS9901 soft reset (RST2*)
// Spec: "Writing a 0 to bit 15 while in the clock mode executes a soft reset on the I/O pins.
// [...] RST2* will program all ports to the input mode"
m_pio_direction = 0;
m_pio_direction_mirror = 0;
// "RST1* (power-up reset) will reset all mask bits low."
// Spec is not clear on whether the mask bits are also reset by RST2*
// TODO: Check on a real machine. (I'd guess from the text they are not touched)
m_enabled_ints = 0;
if (VERBOSE>5) LOG("tms9901: Soft reset (RST2*)\n");
if (TRACE_PINS) logerror("%s: interrupts = %04x\n", tag(), m_enabled_ints);
field_interrupts(); /* changed interrupt state */
}
}
else
{ /* modify interrupt enable mask */
if (data)
m_enabled_ints |= 0x4000; /* set bit */
{
// write one bit to 9901 (bits 1-14)
//
// m_clock_mode==false ? Disable/Enable an interrupt
// : Bit in clock interval
//
// offset is the index of the modified bit of register (-> interrupt number -1)
if (m_clock_mode)
{ /* modify clock interval */
int bit = 1 << ((offset & 0x0F) - 1); /* corresponding mask */
if (data)
m_clock_register |= bit; /* set bit */
else
m_clock_register &= ~bit; /* clear bit */
/* reset clock timer (page 8) */
if (TRACE_CLOCK) logerror("%s: clock register = %04x\n", tag(), m_clock_register);
timer_reload();
}
else
m_enabled_ints &= ~0x4000; /* unset bit */
{ /* modify interrupt enable mask */
int bit = 1 << (offset & 0x0F); /* corresponding mask */
if (VERBOSE>6) LOG("tms9901: interrupts = %04x\n", m_enabled_ints);
field_interrupts(); /* changed interrupt state */
if (data)
m_enabled_ints |= bit; /* set bit */
else
m_enabled_ints &= ~bit; /* unset bit */
if (offset == 3)
m_timer_int_pending = false; /* SBO 3 clears pending timer interrupt (??) */
if (TRACE_MODE) logerror("%s: enabled interrupts = %04x\n", tag(), m_enabled_ints);
field_interrupts(); /* changed interrupt state */
}
}
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
case 0x18:
case 0x19:
case 0x1A:
case 0x1B:
case 0x1C:
case 0x1D:
case 0x1E:
case 0x1F:
int pin = offset & 0x0F;
if (VERBOSE>6) LOG("tms9901: output on P%d = %d\n", pin, data);
int mask = (1 << pin);
// MZ: see above - I think this is wrong
// m_clock_mode = false; // exit timer mode
m_pio_direction |= mask; /* set up as output pin */
if (data)
m_pio_output |= mask;
else
m_pio_output &= ~mask;
if (pin >= 7)
{ /* pins P7-P15 are mirrored as INT15*-INT7* */
int pin2 = 22 - pin;
int mask2 = (1 << pin2);
m_pio_direction_mirror |= mask2; /* set up as output pin */
if (data)
m_pio_output_mirror |= mask2;
else
m_pio_output_mirror &= ~ mask2;
}
if (!m_write_line[pin].isnull())
(m_write_line[pin])(data);
break;
}
}
@ -476,7 +550,7 @@ void tms9901_device::device_timer(emu_timer &timer, device_timer_id id, int para
if (id==DECREMENTER) // we have only that one
{
m_decrementer_value--;
if (VERBOSE>6) LOG("tms9901: decrementer = %d\n", m_decrementer_value);
if (TRACE_CLOCK) logerror("%s: decrementer = %d\n", tag(), m_decrementer_value);
if (m_decrementer_value<=0)
{
m_timer_int_pending = true; // decrementer interrupt requested
@ -507,7 +581,10 @@ void tms9901_device::device_reset(void)
m_pio_direction_mirror = 0;
m_pio_output = m_pio_output_mirror = 0;
// This is an interrupt level latch, positive logic (bit 0 = no int)
// The inputs are negative logic (INTx*)
m_int_state = 0;
m_old_int_state = -1;
field_interrupts();
@ -524,21 +601,28 @@ void tms9901_device::device_reset(void)
void tms9901_device::device_start(void)
{
const tms9901_interface *intf = reinterpret_cast<const tms9901_interface *>(static_config());
m_supported_int_mask = intf->interrupt_mask;
m_decrementer = timer_alloc(DECREMENTER);
m_decrementer->adjust(attotime::from_hz(clock() / 64.), 0, attotime::from_hz(clock() / 64.));
m_decrementer->enable(false);
m_read_block.resolve(intf->read_handler, *this);
for (int i=0; i < 16; i++)
{
m_write_line[i].resolve(intf->write_handler[i], *this);
}
m_interrupt.resolve(intf->interrupt_callback, *this);
m_read_block.resolve();
m_write_p0.resolve();
m_write_p1.resolve();
m_write_p2.resolve();
m_write_p3.resolve();
m_write_p4.resolve();
m_write_p5.resolve();
m_write_p6.resolve();
m_write_p7.resolve();
m_write_p8.resolve();
m_write_p9.resolve();
m_write_p10.resolve();
m_write_p11.resolve();
m_write_p12.resolve();
m_write_p13.resolve();
m_write_p14.resolve();
m_write_p15.resolve();
m_interrupt.resolve();
m_clock_register = 0;
}

View File

@ -23,10 +23,11 @@ extern const device_type TMS9901;
MACROS
***************************************************************************/
/* Masks for the interrupts levels available on TMS9901 */
// Masks for the interrupts levels available on TMS9901
#define TMS9901_INT1 0x0002
#define TMS9901_INT2 0x0004
#define TMS9901_INT3 0x0008 // overriden by the timer interrupt
#define TMS9901_INT3 0x0008 // overridden by the timer interrupt
#define TMS9901_INT4 0x0010
#define TMS9901_INT5 0x0020
#define TMS9901_INT6 0x0040
@ -52,14 +53,6 @@ enum
CLASS DEFINITION
***************************************************************************/
struct tms9901_interface
{
int interrupt_mask; // a bit for each input pin whose state is always notified to the TMS9901 core
devcb_read8 read_handler; // 4*8 bits, to be selected using the offset (0-3)
devcb_write_line write_handler[16]; // 16 Pn outputs
devcb_write8 interrupt_callback; // called when interrupt bus state changes
};
class tms9901_device : public device_t
{
public:
@ -70,6 +63,27 @@ public:
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
template<class _Object> static devcb2_base &static_set_readblock_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_read_block.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p0_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p0.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p1_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p1.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p2_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p2.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p3_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p3.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p4_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p4.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p5_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p5.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p6_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p6.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p7_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p7.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p8_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p8.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p9_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p9.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p10_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p10.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p11_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p11.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p12_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p12.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p13_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p13.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p14_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p14.set_callback(object); }
template<class _Object> static devcb2_base &static_set_p15_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_write_p15.set_callback(object); }
template<class _Object> static devcb2_base &static_set_intlevel_callback(device_t &device, _Object object) { return downcast<tms9901_device &>(device).m_interrupt.set_callback(object); }
private:
static const device_timer_id DECREMENTER = 0;
@ -77,18 +91,14 @@ private:
void timer_reload(void);
void field_interrupts(void);
virtual void device_start(void);
virtual void device_stop(void);
virtual void device_reset(void);
void device_start(void);
void device_stop(void);
void device_reset(void);
/* interrupt registers */
// mask: bit #n is set if pin #n is supported as an interrupt pin,
// i.e. the driver sends a notification whenever the pin state changes
// setting these bits is not required, but it saves you the trouble of
// saving the state of interrupt pins and feeding it to the port read
// handlers again
int m_supported_int_mask;
int m_int_state; // state of the int1-int15 lines (must be inverted when queried)
// State of the INT1-INT15 lines (must be inverted when queried)
// Note that the levels must also be delivered when reading the pins, which
// may require to latch the int levels.
int m_int_state;
int m_old_int_state; // stores the previous value to avoid useless INT line assertions
int m_enabled_ints; // interrupt enable mask
@ -127,18 +137,88 @@ private:
// =======================================================================
// Callbacks
devcb_resolved_read8 m_read_block;
devcb_resolved_write_line m_write_line[16];
devcb_resolved_write8 m_interrupt; // also delivers the interrupt level
// Read callback.
devcb2_read8 m_read_block;
// I/O lines, used for output. When used as inputs, the levels are delivered via the m_read_block
devcb2_write_line m_write_p0;
devcb2_write_line m_write_p1;
devcb2_write_line m_write_p2;
devcb2_write_line m_write_p3;
devcb2_write_line m_write_p4;
devcb2_write_line m_write_p5;
devcb2_write_line m_write_p6;
devcb2_write_line m_write_p7;
devcb2_write_line m_write_p8;
devcb2_write_line m_write_p9;
devcb2_write_line m_write_p10;
devcb2_write_line m_write_p11;
devcb2_write_line m_write_p12;
devcb2_write_line m_write_p13;
devcb2_write_line m_write_p14;
devcb2_write_line m_write_p15;
// The invocation corresponds to the INTREQ signal (with the level passed as data)
// and the address delivers the interrupt level (0-15)
devcb2_write8 m_interrupt;
};
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_TMS9901_ADD(_tag, _intrf, _rate) \
MCFG_DEVICE_ADD(_tag, TMS9901, _rate) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_TMS9901_READBLOCK_HANDLER( _read ) \
devcb = &tms9901_device::static_set_readblock_callback( *device, DEVCB2_##_read );
#define MCFG_TMS9901_P0_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p0_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P1_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p1_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P2_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p2_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P3_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p3_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P4_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p4_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P5_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p5_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P6_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p6_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P7_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p7_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P8_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p8_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P9_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p9_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P10_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p10_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P11_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p11_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P12_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p12_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P13_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p13_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P14_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p14_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_P15_HANDLER( _write ) \
devcb = &tms9901_device::static_set_p15_callback( *device, DEVCB2_##_write );
#define MCFG_TMS9901_INTLEVEL_HANDLER( _intlevel ) \
devcb = &tms9901_device::static_set_intlevel_callback( *device, DEVCB2_##_intlevel );
#endif /* __TMS9901_H__ */

View File

@ -275,10 +275,6 @@ public:
line_state m_video_wait; // reflects the line to the mapper for CRU query
int m_ready_line, m_ready_line1;
private:
//int m_joystick_select;
// Some values to keep. Rest is on the geneve_mapper.
};
/*
@ -551,40 +547,43 @@ WRITE8_MEMBER( geneve_state::tms9901_interrupt )
m_cpu->set_input_line(INT_9995_INT1, data);
}
/* tms9901 setup */
/*
// tms9901 setup
const tms9901_interface tms9901_wiring_geneve =
{
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INT8 | TMS9901_INTB | TMS9901_INTC, /* only input pins whose state is always known */
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INT8 | TMS9901_INTB | TMS9901_INTC,
// read handler
DEVCB_DRIVER_MEMBER(geneve_state, read_by_9901),
// read handler
DEVCB_DRIVER_MEMBER(geneve_state, read_by_9901),
{ /* write handlers */
DEVCB_DRIVER_LINE_MEMBER(geneve_state, peripheral_bus_reset),
DEVCB_DRIVER_LINE_MEMBER(geneve_state, VDP_reset),
DEVCB_DRIVER_LINE_MEMBER(geneve_state, joystick_select),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_DEVICE_LINE_MEMBER(GKEYBOARD_TAG, geneve_keyboard_device, reset_line),
DEVCB_DRIVER_LINE_MEMBER(geneve_state, extbus_wait_states),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(geneve_state, video_wait_states),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
{ // write handlers
DEVCB_DRIVER_LINE_MEMBER(geneve_state, peripheral_bus_reset),
DEVCB_DRIVER_LINE_MEMBER(geneve_state, VDP_reset),
DEVCB_DRIVER_LINE_MEMBER(geneve_state, joystick_select),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_DEVICE_LINE_MEMBER(GKEYBOARD_TAG, geneve_keyboard_device, reset_line),
DEVCB_DRIVER_LINE_MEMBER(geneve_state, extbus_wait_states),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(geneve_state, video_wait_states),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
/* interrupt handler */
DEVCB_DRIVER_MEMBER(geneve_state, tms9901_interrupt)
// interrupt handler
DEVCB_DRIVER_MEMBER(geneve_state, tms9901_interrupt)
};
*/
/*******************************************************************
Signal lines
*******************************************************************/
/*
inta is connected to both tms9901 IRQ1 line and to tms9995 INT4/EC line.
*/
@ -748,7 +747,15 @@ static MACHINE_CONFIG_START( geneve_60hz, geneve_state )
MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", geneve_state, geneve_hblank_interrupt, SCREEN_TAG, 0, 1) /* 262.5 in 60Hz, 312.5 in 50Hz */
// Main board components
MCFG_TMS9901_ADD(TMS9901_TAG, tms9901_wiring_geneve, 3000000)
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(geneve_state, read_by_9901) )
MCFG_TMS9901_P0_HANDLER( WRITELINE( geneve_state, peripheral_bus_reset) )
MCFG_TMS9901_P1_HANDLER( WRITELINE( geneve_state, VDP_reset) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( geneve_state, joystick_select) )
MCFG_TMS9901_P6_HANDLER( DEVWRITELINE( GKEYBOARD_TAG, geneve_keyboard_device, reset_line) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( geneve_state, extbus_wait_states) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( geneve_state, video_wait_states) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( geneve_state, tms9901_interrupt) )
// Mapper
MCFG_DEVICE_ADD(GMAPPER_TAG, GENEVE_MAPPER, 0)

View File

@ -167,6 +167,10 @@ private:
// Mapper registers
UINT8 m_mapper[16];
// Latch for 9901 INT2, INT1 lines
int m_9901_int;
void set_9901_int(int line, line_state state);
int m_ready_prev; // for debugging purposes only
};
@ -566,8 +570,8 @@ READ8_MEMBER( ti99_4p_state::read_by_9901 )
{
case TMS9901_CB_INT7:
// Read pins INT3*-INT7* of TI99's 9901.
// bit 1: INT1 status (interrupt; not set at this place)
// bit 2: INT2 status (interrupt; not set at this place)
// bit 1: INT1 status
// bit 2: INT2 status
// bit 3-7: keyboard status bits 0 to 4
//
// |K|K|K|K|K|I2|I1|C|
@ -584,7 +588,7 @@ READ8_MEMBER( ti99_4p_state::read_by_9901 )
{
answer &= ~(ioport("ALPHA")->read());
}
answer = (answer << 3) & 0xf8;
answer = (answer << 3) | m_9901_int;
break;
case TMS9901_INT8_INT15:
@ -679,37 +683,40 @@ WRITE_LINE_MEMBER( ti99_4p_state::cassette_output )
m_cassette->output((state!=0)? +1 : -1);
}
/* TMS9901 setup. The callback functions pass a reference to the TMS9901 as device. */
/*
// TMS9901 setup. The callback functions pass a reference to the TMS9901 as device.
const tms9901_interface tms9901_wiring_sgcpu =
{
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC, /* only input pins whose state is always known */
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC, // only input pins whose state is always known
// read handler
DEVCB_DRIVER_MEMBER(ti99_4p_state, read_by_9901),
// read handler
DEVCB_DRIVER_MEMBER(ti99_4p_state, read_by_9901),
{ // write handlers
DEVCB_NULL,
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, keyC0),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, keyC1),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, keyC2),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, alphaW),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, cs_motor),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, audio_gate),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, cassette_output),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
{ // write handlers
DEVCB_NULL,
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, keyC0),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, keyC1),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, keyC2),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, alphaW),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, cs_motor),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, audio_gate),
DEVCB_DRIVER_LINE_MEMBER(ti99_4p_state, cassette_output),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
/* interrupt handler */
DEVCB_DRIVER_MEMBER(ti99_4p_state, tms9901_interrupt)
// interrupt handler
DEVCB_DRIVER_MEMBER(ti99_4p_state, tms9901_interrupt)
};
*/
/***************************************************************************
Control lines
****************************************************************************/
@ -751,12 +758,18 @@ WRITE_LINE_MEMBER( ti99_4p_state::console_ready_dmux )
m_cpu->set_ready(combined);
}
void ti99_4p_state::set_9901_int( int line, line_state state)
{
m_tms9901->set_single_int(line, state);
// We latch the value for the read operation. Mind the negative logic.
if (state==CLEAR_LINE) m_9901_int |= (1<<line);
else m_9901_int &= ~(1<<line);
}
WRITE_LINE_MEMBER( ti99_4p_state::extint )
{
if (VERBOSE>6) LOG("ti99_4p: EXTINT level = %02x\n", state);
if (m_tms9901 != NULL)
m_tms9901->set_single_int(1, state);
set_9901_int(1, (line_state)state);
}
WRITE_LINE_MEMBER( ti99_4p_state::notconnected )
@ -836,7 +849,7 @@ void ti99_4p_state::machine_start()
*/
WRITE_LINE_MEMBER(ti99_4p_state::set_tms9901_INT2_from_v9938)
{
m_tms9901->set_single_int(2, state);
set_9901_int(2, (line_state)state);
}
/*
@ -844,10 +857,11 @@ WRITE_LINE_MEMBER(ti99_4p_state::set_tms9901_INT2_from_v9938)
*/
MACHINE_RESET_MEMBER(ti99_4p_state,ti99_4p)
{
m_tms9901->set_single_int(12, 0);
set_9901_int(12, CLEAR_LINE);
m_cpu->set_ready(ASSERT_LINE);
m_cpu->set_hold(CLEAR_LINE);
m_9901_int = 0x03; // INT2* and INT1* set to 1, i.e. inactive
}
TIMER_DEVICE_CALLBACK_MEMBER(ti99_4p_state::sgcpu_hblank_interrupt)
@ -873,7 +887,15 @@ static MACHINE_CONFIG_START( ti99_4p_60hz, ti99_4p_state )
MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", ti99_4p_state, sgcpu_hblank_interrupt, SCREEN_TAG, 0, 1)
// tms9901
MCFG_TMS9901_ADD(TMS9901_TAG, tms9901_wiring_sgcpu, 3000000)
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_4p_state, read_by_9901) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_4p_state, keyC0) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_4p_state, keyC1) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_4p_state, keyC2) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_4p_state, cs_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_4p_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_4p_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_4p_state, tms9901_interrupt) )
// Peripheral expansion box (SGCPU composition)
MCFG_DEVICE_ADD( PERIBOX_TAG, PERIBOX_SG, 0)

View File

@ -137,7 +137,11 @@ private:
void console_ready_join(int id, int state);
// Console type
int m_console;
int m_console;
// Latch for 9901 INT2, INT1 lines
int m_9901_int;
void set_9901_int(int line, line_state state);
// Connected devices
required_device<tms9900_device> m_cpu;
@ -443,8 +447,8 @@ READ8_MEMBER( ti99_4x_state::read_by_9901 )
case TMS9901_CB_INT7:
//
// Read pins INT3*-INT7* of TI99's 9901.
// bit 1: INT1 status (interrupt; not set at this place)
// bit 2: INT2 status (interrupt; not set at this place)
// bit 1: INT1 status
// bit 2: INT2 status
// bit 3-7: keyboard status bits 0 to 4
//
// |K|K|K|K|K|I2|I1|C|
@ -470,7 +474,7 @@ READ8_MEMBER( ti99_4x_state::read_by_9901 )
{
answer &= ~(ioport("ALPHA")->read());
}
answer = (answer << 3) & 0xf8;
answer = (answer << 3) | m_9901_int;
break;
@ -631,19 +635,27 @@ WRITE_LINE_MEMBER( ti99_4x_state::dbin_line )
/*****************************************************************************/
void ti99_4x_state::set_9901_int( int line, line_state state)
{
m_tms9901->set_single_int(line, state);
// We latch the value for the read operation. Mind the negative logic.
if (state==CLEAR_LINE) m_9901_int |= (1<<line);
else m_9901_int &= ~(1<<line);
}
/*
set the state of TMS9901's INT2 (called by the tms9928 core)
*/
WRITE_LINE_MEMBER( ti99_4x_state::set_tms9901_INT2 )
{
if (TRACE_INTERRUPTS) LOG("ti99_4x: VDP int 2 on tms9901, level=%d\n", state);
m_tms9901->set_single_int(2, state);
set_9901_int(2, (line_state)state);
}
WRITE_LINE_MEMBER(ti99_4x_state::set_tms9901_INT2_from_v9938)
{
if (TRACE_INTERRUPTS) LOG("ti99_4x: VDP int 2 on tms9901, level=%d\n", state);
m_tms9901->set_single_int(2, state);
set_9901_int(2, (line_state)state);
}
/*
@ -652,7 +664,7 @@ WRITE_LINE_MEMBER(ti99_4x_state::set_tms9901_INT2_from_v9938)
WRITE_LINE_MEMBER( ti99_4x_state::set_tms9901_INT12)
{
if (TRACE_INTERRUPTS) LOG("ti99_4x: joyport INT 12 on tms9901, level=%d\n", state);
m_tms9901->set_single_int(12, state);
set_9901_int(12, (line_state)state);
}
/*
@ -736,8 +748,7 @@ WRITE_LINE_MEMBER( ti99_4x_state::console_reset )
WRITE_LINE_MEMBER( ti99_4x_state::extint )
{
if (TRACE_INTERRUPTS) LOG("ti99_4x: EXTINT level = %02x\n", state);
if (m_tms9901 != NULL)
m_tms9901->set_single_int(1, state);
set_9901_int(1, (line_state)state);
}
WRITE_LINE_MEMBER( ti99_4x_state::notconnected )
@ -753,67 +764,70 @@ static TMS9928A_INTERFACE(ti99_4_tms9928a_interface)
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, set_tms9901_INT2)
};
/* TMS9901 setup. */
/* TMS9901 setup.
const tms9901_interface tms9901_wiring_ti99_4 =
{
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC, /* only input pins whose state is always known */
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC, // only input pins whose state is always known
// read handler
DEVCB_DRIVER_MEMBER(ti99_4x_state, read_by_9901),
// read handler
DEVCB_DRIVER_MEMBER(ti99_4x_state, read_by_9901),
// write handlers
{
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, handset_ack),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC0),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC1),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC2),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cs1_motor),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cs2_motor),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, audio_gate),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cassette_output),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
// write handlers
{
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, handset_ack),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC0),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC1),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC2),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cs1_motor),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cs2_motor),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, audio_gate),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cassette_output),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
// interrupt handler
DEVCB_DRIVER_MEMBER(ti99_4x_state, tms9901_interrupt)
// interrupt handler
DEVCB_DRIVER_MEMBER(ti99_4x_state, tms9901_interrupt)
};
*/
/*
const tms9901_interface tms9901_wiring_ti99_4a =
{
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC,
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC,
// read handler
DEVCB_DRIVER_MEMBER(ti99_4x_state, read_by_9901),
// read handler
DEVCB_DRIVER_MEMBER(ti99_4x_state, read_by_9901),
// write handlers
{
DEVCB_NULL,
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC0),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC1),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC2),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, alphaW),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cs1_motor),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cs2_motor),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, audio_gate),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cassette_output),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
// write handlers
{
DEVCB_NULL,
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC0),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC1),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, keyC2),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, alphaW),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cs1_motor),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cs2_motor),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, audio_gate),
DEVCB_DRIVER_LINE_MEMBER(ti99_4x_state, cassette_output),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
DEVCB_DRIVER_MEMBER(ti99_4x_state, tms9901_interrupt)
DEVCB_DRIVER_MEMBER(ti99_4x_state, tms9901_interrupt)
};
*/
/*
Devices attached to the databus multiplexer. We cannot solve this with
@ -886,6 +900,7 @@ MACHINE_RESET_MEMBER(ti99_4x_state,ti99_4)
{
m_cpu->set_ready(ASSERT_LINE);
m_cpu->set_hold(CLEAR_LINE);
m_9901_int = 0x03; // INT2* and INT1* set to 1, i.e. inactive
}
/*
@ -901,7 +916,18 @@ static MACHINE_CONFIG_START( ti99_4_60hz, ti99_4x_state )
MCFG_TI_TMS991x_ADD_NTSC(VIDEO_SYSTEM_TAG, TMS9918, ti99_4_tms9928a_interface)
/* Main board */
MCFG_TMS9901_ADD(TMS9901_TAG, tms9901_wiring_ti99_4, 3000000)
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_4x_state, read_by_9901) )
MCFG_TMS9901_P0_HANDLER( WRITELINE( ti99_4x_state, handset_ack) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_4x_state, keyC0) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_4x_state, keyC1) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_4x_state, keyC2) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_4x_state, cs1_motor) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( ti99_4x_state, cs2_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_4x_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_4x_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_4x_state, tms9901_interrupt) )
MCFG_DMUX_ADD( DATAMUX_TAG, datamux_conf )
MCFG_DMUX_READY_HANDLER( WRITELINE(ti99_4x_state, console_ready_dmux) )
MCFG_TI99_GROMPORT_ADD( GROMPORT_TAG )
@ -953,8 +979,19 @@ static MACHINE_CONFIG_START( ti99_4_50hz, ti99_4x_state )
/* video hardware */
MCFG_TI_TMS991x_ADD_PAL(VIDEO_SYSTEM_TAG, TMS9929, ti99_4_tms9928a_interface)
/* main board */
MCFG_TMS9901_ADD(TMS9901_TAG, tms9901_wiring_ti99_4, 3000000)
/* Main board */
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_4x_state, read_by_9901) )
MCFG_TMS9901_P0_HANDLER( WRITELINE( ti99_4x_state, handset_ack) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_4x_state, keyC0) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_4x_state, keyC1) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_4x_state, keyC2) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_4x_state, cs1_motor) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( ti99_4x_state, cs2_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_4x_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_4x_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_4x_state, tms9901_interrupt) )
MCFG_DMUX_ADD( DATAMUX_TAG, datamux_conf )
MCFG_DMUX_READY_HANDLER( WRITELINE(ti99_4x_state, console_ready_dmux) )
@ -1026,7 +1063,18 @@ static MACHINE_CONFIG_START( ti99_4a_60hz, ti99_4x_state )
MCFG_TI_TMS991x_ADD_NTSC(VIDEO_SYSTEM_TAG, TMS9918A, ti99_4_tms9928a_interface)
/* Main board */
MCFG_TMS9901_ADD(TMS9901_TAG, tms9901_wiring_ti99_4a, 3000000)
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_4x_state, read_by_9901) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_4x_state, keyC0) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_4x_state, keyC1) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_4x_state, keyC2) )
MCFG_TMS9901_P5_HANDLER( WRITELINE( ti99_4x_state, alphaW) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_4x_state, cs1_motor) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( ti99_4x_state, cs2_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_4x_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_4x_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_4x_state, tms9901_interrupt) )
MCFG_DMUX_ADD( DATAMUX_TAG, datamux_conf )
MCFG_DMUX_READY_HANDLER( WRITELINE(ti99_4x_state, console_ready_dmux) )
MCFG_TI99_GROMPORT_ADD( GROMPORT_TAG )
@ -1078,7 +1126,18 @@ static MACHINE_CONFIG_START( ti99_4a_50hz, ti99_4x_state )
MCFG_TI_TMS991x_ADD_PAL(VIDEO_SYSTEM_TAG, TMS9929A, ti99_4_tms9928a_interface)
/* Main board */
MCFG_TMS9901_ADD(TMS9901_TAG, tms9901_wiring_ti99_4a, 3000000)
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_4x_state, read_by_9901) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_4x_state, keyC0) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_4x_state, keyC1) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_4x_state, keyC2) )
MCFG_TMS9901_P5_HANDLER( WRITELINE( ti99_4x_state, alphaW) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_4x_state, cs1_motor) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( ti99_4x_state, cs2_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_4x_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_4x_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_4x_state, tms9901_interrupt) )
MCFG_DMUX_ADD( DATAMUX_TAG, datamux_conf )
MCFG_DMUX_READY_HANDLER( WRITELINE(ti99_4x_state, console_ready_dmux) )
MCFG_TI99_GROMPORT_ADD( GROMPORT_TAG )
@ -1147,7 +1206,18 @@ static MACHINE_CONFIG_START( ti99_4qi_60hz, ti99_4x_state )
MCFG_TI_TMS991x_ADD_NTSC(VIDEO_SYSTEM_TAG, TMS9918A, ti99_4_tms9928a_interface)
/* Main board */
MCFG_TMS9901_ADD(TMS9901_TAG, tms9901_wiring_ti99_4a, 3000000)
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_4x_state, read_by_9901) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_4x_state, keyC0) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_4x_state, keyC1) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_4x_state, keyC2) )
MCFG_TMS9901_P5_HANDLER( WRITELINE( ti99_4x_state, alphaW) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_4x_state, cs1_motor) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( ti99_4x_state, cs2_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_4x_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_4x_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_4x_state, tms9901_interrupt) )
MCFG_DMUX_ADD( DATAMUX_TAG, datamux_conf )
MCFG_DMUX_READY_HANDLER( WRITELINE(ti99_4x_state, console_ready_dmux) )
MCFG_TI99_GROMPORT_ADD( GROMPORT_TAG )
@ -1199,7 +1269,18 @@ static MACHINE_CONFIG_START( ti99_4qi_50hz, ti99_4x_state )
MCFG_TI_TMS991x_ADD_PAL(VIDEO_SYSTEM_TAG, TMS9929A, ti99_4_tms9928a_interface)
/* Main board */
MCFG_TMS9901_ADD(TMS9901_TAG, tms9901_wiring_ti99_4a, 3000000)
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_4x_state, read_by_9901) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_4x_state, keyC0) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_4x_state, keyC1) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_4x_state, keyC2) )
MCFG_TMS9901_P5_HANDLER( WRITELINE( ti99_4x_state, alphaW) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_4x_state, cs1_motor) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( ti99_4x_state, cs2_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_4x_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_4x_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_4x_state, tms9901_interrupt) )
MCFG_DMUX_ADD( DATAMUX_TAG, datamux_conf )
MCFG_DMUX_READY_HANDLER( WRITELINE(ti99_4x_state, console_ready_dmux) )
MCFG_TI99_GROMPORT_ADD( GROMPORT_TAG )
@ -1267,7 +1348,18 @@ static MACHINE_CONFIG_START( ti99_4ev_60hz, ti99_4x_state )
MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", ti99_4x_state, ti99_4ev_hblank_interrupt, SCREEN_TAG, 0, 1)
/* Main board */
MCFG_TMS9901_ADD(TMS9901_TAG, tms9901_wiring_ti99_4a, 3000000)
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_4x_state, read_by_9901) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_4x_state, keyC0) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_4x_state, keyC1) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_4x_state, keyC2) )
MCFG_TMS9901_P5_HANDLER( WRITELINE( ti99_4x_state, alphaW) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_4x_state, cs1_motor) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( ti99_4x_state, cs2_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_4x_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_4x_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_4x_state, tms9901_interrupt) )
MCFG_DMUX_ADD( DATAMUX_TAG, datamux_conf_ev )
MCFG_DMUX_READY_HANDLER( WRITELINE(ti99_4x_state, console_ready_dmux) )
MCFG_TI99_GROMPORT_ADD( GROMPORT_TAG )

View File

@ -297,6 +297,10 @@ private:
int m_nready_prev;
void console_ready_join(int id, int state);
// Latch for 9901 INT2, INT1 lines
int m_9901_int;
void set_9901_int(int line, line_state state);
// Connected devices
required_device<tms9995_device> m_cpu;
required_device<tms9901_device> m_tms9901;
@ -563,8 +567,8 @@ READ8_MEMBER( ti99_8_state::read_by_9901 )
case TMS9901_CB_INT7:
// Read pins INT3*-INT7* of TI99's 9901.
//
// (bit 1: INT1 status)
// (bit 2: INT2 status)
// bit 1: INT1 status
// bit 2: INT2 status
// bits 3-4: unused?
// bit 5: ???
// bit 6-7: keyboard status bits 0 through 1
@ -580,7 +584,7 @@ READ8_MEMBER( ti99_8_state::read_by_9901 )
{
answer = ioport(column[m_keyboard_column])->read();
}
answer = (answer << 6) & 0xc0;
answer = (answer << 6) | m_9901_int;
break;
@ -714,45 +718,55 @@ WRITE8_MEMBER( ti99_8_state::tms9901_interrupt )
m_cpu->set_input_line(INT_9995_INT1, data);
}
/*
const tms9901_interface tms9901_wiring_ti99_8 =
{
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC,
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC,
// read handler
DEVCB_DRIVER_MEMBER(ti99_8_state, read_by_9901),
// read handler
DEVCB_DRIVER_MEMBER(ti99_8_state, read_by_9901),
// write handlers
{
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, keyC0),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, keyC1),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, keyC2),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, keyC3),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, CRUS),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, PTGEN),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, cassette_motor),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, audio_gate),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, cassette_output),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
// write handlers
{
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, keyC0),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, keyC1),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, keyC2),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, keyC3),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, CRUS),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, PTGEN),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, cassette_motor),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, audio_gate),
DEVCB_DRIVER_LINE_MEMBER(ti99_8_state, cassette_output),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
DEVCB_DRIVER_MEMBER(ti99_8_state, tms9901_interrupt)
DEVCB_DRIVER_MEMBER(ti99_8_state, tms9901_interrupt)
};
*/
/*****************************************************************************/
void ti99_8_state::set_9901_int( int line, line_state state)
{
m_tms9901->set_single_int(line, state);
// We latch the value for the read operation. Mind the negative logic.
if (state==CLEAR_LINE) m_9901_int |= (1<<line);
else m_9901_int &= ~(1<<line);
}
/*
set the state of TMS9901's INT2 (called by the tms9928 core)
*/
WRITE_LINE_MEMBER( ti99_8_state::set_tms9901_INT2 )
{
if (TRACE_INTERRUPTS) LOG("ti99_8: VDP int 2 on tms9901, level=%02x\n", state);
m_tms9901->set_single_int(2, state);
set_9901_int(2, (line_state)state);
}
/***********************************************************
@ -829,8 +843,7 @@ WRITE_LINE_MEMBER( ti99_8_state::console_reset )
WRITE_LINE_MEMBER( ti99_8_state::extint )
{
if (TRACE_READY) LOG("ti99_8: EXTINT level = %02x\n", state);
if (m_tms9901 != NULL)
m_tms9901->set_single_int(1, state);
set_9901_int(1, (line_state)state);
}
WRITE_LINE_MEMBER( ti99_8_state::notconnected )
@ -1004,6 +1017,9 @@ MACHINE_RESET_MEMBER(ti99_8_state, ti99_8)
// But we assert the line here so that the system starts running
m_nready_combined = 0;
m_gromport->set_grom_base(0x9800, 0xfff1);
// Clear INT1 and INT2 latch (negative logic)
m_9901_int = 0x03;
}
static MACHINE_CONFIG_START( ti99_8_60hz, ti99_8_state )
@ -1017,7 +1033,19 @@ static MACHINE_CONFIG_START( ti99_8_60hz, ti99_8_state )
MCFG_TI998_ADD_NTSC(VIDEO_SYSTEM_TAG, TMS9118, ti99_8_tms9118a_interface)
/* Main board */
MCFG_TMS9901_ADD( TMS9901_TAG, tms9901_wiring_ti99_8, XTAL_10_738635MHz/4.0)
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, XTAL_10_738635MHz/4.0)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_8_state, read_by_9901) )
MCFG_TMS9901_P0_HANDLER( WRITELINE( ti99_8_state, keyC0) )
MCFG_TMS9901_P1_HANDLER( WRITELINE( ti99_8_state, keyC1) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_8_state, keyC2) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_8_state, keyC3) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_8_state, CRUS) )
MCFG_TMS9901_P5_HANDLER( WRITELINE( ti99_8_state, PTGEN) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_8_state, cassette_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_8_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_8_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_8_state, tms9901_interrupt) )
MCFG_MAINBOARD8_ADD( MAINBOARD8_TAG, mapper_conf )
MCFG_MAINBOARD8_READY_CALLBACK(WRITELINE(ti99_8_state, console_ready_mapper))
MCFG_TI99_GROMPORT_ADD( GROMPORT_TAG )
@ -1073,7 +1101,19 @@ static MACHINE_CONFIG_START( ti99_8_50hz, ti99_8_state )
MCFG_TI998_ADD_PAL(VIDEO_SYSTEM_TAG, TMS9129, ti99_8_tms9118a_interface)
/* Main board */
MCFG_TMS9901_ADD( TMS9901_TAG, tms9901_wiring_ti99_8, XTAL_10_738635MHz/4.0 )
MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, XTAL_10_738635MHz/4.0)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_8_state, read_by_9901) )
MCFG_TMS9901_P0_HANDLER( WRITELINE( ti99_8_state, keyC0) )
MCFG_TMS9901_P1_HANDLER( WRITELINE( ti99_8_state, keyC1) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( ti99_8_state, keyC2) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( ti99_8_state, keyC3) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( ti99_8_state, CRUS) )
MCFG_TMS9901_P5_HANDLER( WRITELINE( ti99_8_state, PTGEN) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( ti99_8_state, cassette_motor) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( ti99_8_state, audio_gate) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( ti99_8_state, cassette_output) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( ti99_8_state, tms9901_interrupt) )
MCFG_MAINBOARD8_ADD( MAINBOARD8_TAG, mapper_conf )
MCFG_TI99_GROMPORT_ADD( GROMPORT_TAG )
MCFG_GROMPORT_READY_HANDLER( WRITELINE(ti99_8_state, console_ready_cart) )

View File

@ -70,6 +70,8 @@
#include "tm990189.lh"
#include "tm990189v.lh"
#define TMS9901_0_TAG "tms9901_usr"
#define TMS9901_1_TAG "tms9901_sys"
class tm990189_state : public driver_device
{
@ -81,7 +83,9 @@ public:
m_cass(*this, "cassette"),
m_tms9918(*this, "tms9918" ),
m_maincpu(*this, "maincpu"),
m_cassette(*this, "cassette") { }
m_cassette(*this, "cassette"),
m_tms9901_usr(*this, TMS9901_0_TAG),
m_tms9901_sys(*this, TMS9901_1_TAG) { }
required_device<tms9980a_device> m_tms9980a;
required_device<speaker_sound_device> m_speaker;
@ -158,6 +162,8 @@ private:
void digitsel(int offset, bool state);
required_device<cpu_device> m_maincpu;
required_device<cassette_image_device> m_cassette;
required_device<tms9901_device> m_tms9901_usr;
required_device<tms9901_device> m_tms9901_sys;
};
@ -304,7 +310,9 @@ WRITE_LINE_MEMBER( tm990189_state::usr9901_led3_w )
WRITE8_MEMBER( tm990189_state::sys9901_interrupt_callback )
{
machine().device<tms9901_device>("tms9901_0")->set_single_int(5, (data!=0)? ASSERT_LINE:CLEAR_LINE);
// machine().device<tms9901_device>("tms9901_0")->set_single_int(5, (data!=0)? ASSERT_LINE:CLEAR_LINE);
// TODO: Check this
m_tms9901_usr->set_single_int(5, (data!=0)? ASSERT_LINE:CLEAR_LINE);
}
READ8_MEMBER( tm990189_state::sys9901_r )
@ -624,70 +632,75 @@ WRITE8_MEMBER( tm990189_state::video_joy_w )
m_joy2y_timer->reset(attotime::from_usec(ioport("JOY2_Y")->read()*28+28));
}
/* user tms9901 setup */
/*
// user tms9901 setup
static const tms9901_interface usr9901reset_param =
{
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INT3 | TMS9901_INT4 | TMS9901_INT5 | TMS9901_INT6, /* only input pins whose state is always known */
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INT3 | TMS9901_INT4 | TMS9901_INT5 | TMS9901_INT6, // only input pins whose state is always known
/* Read handler. Covers all input lines (see tms9901.h) */
DEVCB_NULL,
// Read handler. Covers all input lines (see tms9901.h)
DEVCB_NULL,
/* write handlers */
{
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, usr9901_led0_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, usr9901_led1_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, usr9901_led2_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, usr9901_led3_w),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
// write handlers
{
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, usr9901_led0_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, usr9901_led1_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, usr9901_led2_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, usr9901_led3_w),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
/* interrupt handler */
DEVCB_DRIVER_MEMBER(tm990189_state, usr9901_interrupt_callback)
// interrupt handler
DEVCB_DRIVER_MEMBER(tm990189_state, usr9901_interrupt_callback)
};
*/
/* system tms9901 setup */
/*
// system tms9901 setup
static const tms9901_interface sys9901reset_param =
{
0, /* only input pins whose state is always known */
0, // only input pins whose state is always known
/* Read handler. Covers all input lines (see tms9901.h) */
DEVCB_DRIVER_MEMBER(tm990189_state, sys9901_r),
// Read handler. Covers all input lines (see tms9901.h)
DEVCB_DRIVER_MEMBER(tm990189_state, sys9901_r),
/* write handlers */
{
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_digitsel0_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_digitsel1_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_digitsel2_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_digitsel3_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment0_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment1_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment2_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment3_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment4_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment5_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment6_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment7_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_dsplytrgr_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_shiftlight_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_spkrdrive_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_tapewdata_w)
},
// write handlers
{
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_digitsel0_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_digitsel1_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_digitsel2_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_digitsel3_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment0_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment1_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment2_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment3_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment4_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment5_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment6_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_segment7_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_dsplytrgr_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_shiftlight_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_spkrdrive_w),
DEVCB_DRIVER_LINE_MEMBER(tm990189_state, sys9901_tapewdata_w)
},
/* interrupt handler */
DEVCB_DRIVER_MEMBER(tm990189_state, sys9901_interrupt_callback)
// interrupt handler
DEVCB_DRIVER_MEMBER(tm990189_state, sys9901_interrupt_callback)
};
*/
/*
Memory map:
@ -800,12 +813,12 @@ ADDRESS_MAP_END
*/
static ADDRESS_MAP_START( tm990_189_cru_map, AS_IO, 8, tm990189_state )
AM_RANGE(0x0000, 0x003f) AM_DEVREAD("tms9901_0", tms9901_device, read) /* user I/O tms9901 */
AM_RANGE(0x0040, 0x006f) AM_DEVREAD("tms9901_1", tms9901_device, read) /* system I/O tms9901 */
AM_RANGE(0x0000, 0x003f) AM_DEVREAD(TMS9901_0_TAG, tms9901_device, read) /* user I/O tms9901 */
AM_RANGE(0x0040, 0x006f) AM_DEVREAD(TMS9901_1_TAG, tms9901_device, read) /* system I/O tms9901 */
AM_RANGE(0x0080, 0x00cf) AM_DEVREAD("tms9902", tms9902_device, cruread) /* optional tms9902 */
AM_RANGE(0x0000, 0x01ff) AM_DEVWRITE("tms9901_0", tms9901_device, write) /* user I/O tms9901 */
AM_RANGE(0x0200, 0x03ff) AM_DEVWRITE("tms9901_1", tms9901_device, write) /* system I/O tms9901 */
AM_RANGE(0x0000, 0x01ff) AM_DEVWRITE(TMS9901_0_TAG, tms9901_device, write) /* user I/O tms9901 */
AM_RANGE(0x0200, 0x03ff) AM_DEVWRITE(TMS9901_1_TAG, tms9901_device, write) /* system I/O tms9901 */
AM_RANGE(0x0400, 0x05ff) AM_DEVWRITE("tms9902", tms9902_device, cruwrite) /* optional tms9902 */
ADDRESS_MAP_END
@ -837,8 +850,34 @@ static MACHINE_CONFIG_START( tm990_189, tm990189_state )
/* Devices */
MCFG_CASSETTE_ADD( "cassette", default_cassette_interface )
MCFG_TMS9901_ADD("tms9901_0", usr9901reset_param, 2000000)
MCFG_TMS9901_ADD("tms9901_1", sys9901reset_param, 2000000)
MCFG_DEVICE_ADD(TMS9901_0_TAG, TMS9901, 2000000)
MCFG_TMS9901_P0_HANDLER( WRITELINE( tm990189_state, usr9901_led0_w) )
MCFG_TMS9901_P1_HANDLER( WRITELINE( tm990189_state, usr9901_led1_w) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( tm990189_state, usr9901_led2_w) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( tm990189_state, usr9901_led3_w) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( tm990189_state, usr9901_interrupt_callback) )
MCFG_DEVICE_ADD(TMS9901_1_TAG, TMS9901, 2000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(tm990189_state, sys9901_r) )
MCFG_TMS9901_P0_HANDLER( WRITELINE( tm990189_state, sys9901_digitsel0_w) )
MCFG_TMS9901_P1_HANDLER( WRITELINE( tm990189_state, sys9901_digitsel1_w) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( tm990189_state, sys9901_digitsel2_w) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( tm990189_state, sys9901_digitsel3_w) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( tm990189_state, sys9901_segment0_w) )
MCFG_TMS9901_P5_HANDLER( WRITELINE( tm990189_state, sys9901_segment1_w) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( tm990189_state, sys9901_segment2_w) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( tm990189_state, sys9901_segment3_w) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( tm990189_state, sys9901_segment4_w) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( tm990189_state, sys9901_segment5_w) )
MCFG_TMS9901_P10_HANDLER( WRITELINE( tm990189_state, sys9901_segment6_w) )
MCFG_TMS9901_P11_HANDLER( WRITELINE( tm990189_state, sys9901_segment7_w) )
MCFG_TMS9901_P12_HANDLER( WRITELINE( tm990189_state, sys9901_dsplytrgr_w) )
MCFG_TMS9901_P13_HANDLER( WRITELINE( tm990189_state, sys9901_shiftlight_w) )
MCFG_TMS9901_P14_HANDLER( WRITELINE( tm990189_state, sys9901_spkrdrive_w) )
MCFG_TMS9901_P15_HANDLER( WRITELINE( tm990189_state, sys9901_tapewdata_w) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( tm990189_state, sys9901_interrupt_callback) )
MCFG_TMS9902_ADD("tms9902", tms9902_params, 2000000)
MCFG_TM990_189_RS232_ADD("rs232")
MCFG_TIMER_DRIVER_ADD_PERIODIC("display_timer", tm990189_state, display_callback, attotime::from_hz(30))
@ -869,8 +908,33 @@ static MACHINE_CONFIG_START( tm990_189_v, tm990189_state )
/* Devices */
MCFG_CASSETTE_ADD( "cassette", default_cassette_interface )
MCFG_TMS9901_ADD("tms9901_0", usr9901reset_param, 2000000)
MCFG_TMS9901_ADD("tms9901_1", sys9901reset_param, 2000000)
MCFG_DEVICE_ADD(TMS9901_0_TAG, TMS9901, 2000000)
MCFG_TMS9901_P0_HANDLER( WRITELINE( tm990189_state, usr9901_led0_w) )
MCFG_TMS9901_P1_HANDLER( WRITELINE( tm990189_state, usr9901_led1_w) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( tm990189_state, usr9901_led2_w) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( tm990189_state, usr9901_led3_w) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( tm990189_state, usr9901_interrupt_callback) )
MCFG_DEVICE_ADD(TMS9901_1_TAG, TMS9901, 2000000)
MCFG_TMS9901_READBLOCK_HANDLER( READ8(tm990189_state, sys9901_r) )
MCFG_TMS9901_P0_HANDLER( WRITELINE( tm990189_state, sys9901_digitsel0_w) )
MCFG_TMS9901_P1_HANDLER( WRITELINE( tm990189_state, sys9901_digitsel1_w) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( tm990189_state, sys9901_digitsel2_w) )
MCFG_TMS9901_P3_HANDLER( WRITELINE( tm990189_state, sys9901_digitsel3_w) )
MCFG_TMS9901_P4_HANDLER( WRITELINE( tm990189_state, sys9901_segment0_w) )
MCFG_TMS9901_P5_HANDLER( WRITELINE( tm990189_state, sys9901_segment1_w) )
MCFG_TMS9901_P6_HANDLER( WRITELINE( tm990189_state, sys9901_segment2_w) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( tm990189_state, sys9901_segment3_w) )
MCFG_TMS9901_P8_HANDLER( WRITELINE( tm990189_state, sys9901_segment4_w) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( tm990189_state, sys9901_segment5_w) )
MCFG_TMS9901_P10_HANDLER( WRITELINE( tm990189_state, sys9901_segment6_w) )
MCFG_TMS9901_P11_HANDLER( WRITELINE( tm990189_state, sys9901_segment7_w) )
MCFG_TMS9901_P12_HANDLER( WRITELINE( tm990189_state, sys9901_dsplytrgr_w) )
MCFG_TMS9901_P13_HANDLER( WRITELINE( tm990189_state, sys9901_shiftlight_w) )
MCFG_TMS9901_P14_HANDLER( WRITELINE( tm990189_state, sys9901_spkrdrive_w) )
MCFG_TMS9901_P15_HANDLER( WRITELINE( tm990189_state, sys9901_tapewdata_w) )
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( tm990189_state, sys9901_interrupt_callback) )
MCFG_TMS9902_ADD("tms9902", tms9902_params, 2000000)
MCFG_TM990_189_RS232_ADD("rs232")
MCFG_TIMER_DRIVER_ADD_PERIODIC("display_timer", tm990189_state, display_callback, attotime::from_hz(30))