Skeleton Rockwell 10788 chip emulation and use in gts1 - WIP (nw)

This commit is contained in:
jbu 2014-12-09 13:06:54 +01:00
parent afdc0a8e76
commit 1eaba9c168
5 changed files with 317 additions and 4 deletions

View File

@ -1302,6 +1302,15 @@ ifneq ($(filter PLA,$(MACHINES)),)
MACHINEOBJS += $(MACHINEOBJ)/pla.o
endif
#-------------------------------------------------
#
#@src/emu/machine/r10788.h,MACHINES += R10788
#-------------------------------------------------
ifneq ($(filter R10788,$(MACHINES)),)
MACHINEOBJS+= $(MACHINEOBJ)/r10788.o
endif
#-------------------------------------------------
#
#@src/emu/machine/rf5c296.h,MACHINES += RF5C296

195
src/emu/machine/r10788.c Normal file
View File

@ -0,0 +1,195 @@
/**********************************************************************
Rockwell 10788 General Purpose Keyboard and Display circuit
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
REGISTER DESCRIPTION
[ Opcodes IOL, I2 ]
NAME W/IO CS I/O CMD I/O Names
--------------------------------------------------------------
KTR 1 1 x x x 1 1 0 0 Transfer Keyboard Return
KTS 1 1 x x x 1 0 1 0 Transfer Keyboard Strobe
KLA 1 1 x x x 1 1 1 0 Load Display Register A
KLB 1 1 x x x 1 1 0 1 Load Display Register A
KDN 1 1 x x x 0 0 1 1 Turn On Display
KAF 1 1 x x x 1 0 1 1 Turn Off A
KBF 1 1 x x x 0 1 1 1 Turn Off B
KER 1 1 x x x 0 1 1 0 Reset Keyboard Error
Notes:
1.) W/IO is generated by the first word of the PPS IOL instruction.
2.) Polarities of I/O7, I/O6 and I/O5 must be the same as the
polarities of the chip select straps SC7, SC6 and SC5.
3.) KLA resets DA1-DA4 and DB1 and DB2 to VSS level. KLB resets
DB3 and DB4 to VSS level.
4.) KAF and KBF is used to blank the display without changing the
contents of display data registers.
5.) KAF resets output lines DA1, DA2, DA3, DA4, DB1 and DB2 to
VSS level. KBF resets output lines DB3 and DB4 to VSS level.
6.) KAF stops the circulation of the display register A, and KBF
stops the circulation of the display register B.
7.) KER takes a maximum of 10-bit times to complete (= 80 clocks)
Therefore, there must be at least 10 bit times between KER
and the next KTS instruction.
**********************************************************************/
#include "emu.h"
#include "machine/r10788.h"
/*************************************
*
* Device interface
*
*************************************/
const device_type R10788 = &device_creator<r10788_device>;
r10788_device::r10788_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, R10788, "Rockwell 10788", tag, owner, clock, "r10788", __FILE__),
m_reg(),
m_ktr(0), m_kts(0), m_kla(0), m_klb(0), m_enable(3), m_ker(0),
m_scan_counter(0),
m_display(*this)
{
}
/**
* @brief r10788_device::device_start device-specific startup
*/
void r10788_device::device_start()
{
m_display.resolve();
save_item(NAME(m_reg));
save_item(NAME(m_ktr));
save_item(NAME(m_kts));
save_item(NAME(m_kla));
save_item(NAME(m_klb));
save_item(NAME(m_enable));
save_item(NAME(m_ker));
save_item(NAME(m_scan_counter));
m_timer = timer_alloc(TIMER_DISPLAY);
/* Default clock is from CPU1 */
if (clock() == 0)
{
set_unscaled_clock(machine().firstcpu->clock());
}
m_timer->adjust(clocks_to_attotime(36));
}
/**
* @brief r10788_device::device_reset device-specific reset
*/
void r10788_device::device_reset()
{
for (int i = 0; i < 16; i++)
m_reg[0][i] = m_reg[1][i] = 0;
m_ktr = 0;
m_kts = 0;
m_kla = 0;
m_klb = 0;
m_enable = 3;
m_ker = 0;
m_scan_counter = 0;
}
/**
* @brief r10788_device::device_timer timer event callback
* @param timer emu_timer which fired
* @param id timer identifier
* @param param parameter
* @param ptr pointer parameter
*/
void r10788_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_scan_counter = (m_scan_counter + 1) % 16;
switch (id)
{
case TIMER_DISPLAY:
m_display(m_scan_counter, m_reg[0][m_scan_counter] << 4 | m_reg[1][m_scan_counter], 0xff);
break;
}
}
/*************************************
*
* Constants
*
*************************************/
/*************************************
*
* Command access handlers
*
*************************************/
WRITE8_MEMBER( r10788_device::io_w )
{
assert(offset < 16);
switch (offset)
{
case KTR: // Transfer Keyboard Return
m_ktr = data;
break;
case KTS: // Transfer Keyboard Strobe
m_kts = data;
break;
case KLA: // Load Display Register A
m_kla = data;
break;
case KLB: // Load Display Register B
m_klb = data;
break;
case KDN: // Turn On Display
m_enable = 1 | 2;
break;
case KAF: // Turn Off A
m_enable &= ~1;
break;
case KBF: // Turn Off B
m_enable &= ~1;
break;
case KER: // Reset Keyboard Error
m_ker = 10;
break;
}
}
READ8_MEMBER( r10788_device::io_r )
{
assert(offset < 16);
UINT8 data = 0xf;
switch (offset)
{
case KTR: // Transfer Keyboard Return
data = m_ktr;
break;
case KTS: // Transfer Keyboard Strobe
data = m_kts;
break;
case KLA: // Load Display Register A
data = m_kla;
break;
case KLB: // Load Display Register B
data = m_klb;
break;
case KDN: // Turn On Display
break;
case KAF: // Turn Off A
break;
case KBF: // Turn Off B
break;
case KER: // Reset Keyboard Error
break;
}
return data;
}

72
src/emu/machine/r10788.h Normal file
View File

@ -0,0 +1,72 @@
/**********************************************************************
Rockwell 10788 General Purpose Keyboard and Display circuit
Juergen Buchmueller <pullmoll@t-online.de>
The device decodes reads/write to a 16 byte I/O range defined
by three wired inputs SC5, SC6 and SC7. The range is one of
80-8f, 90-9f, ..., f0-ff depending on the wiring.
**********************************************************************/
#ifndef __R10788_H__
#define __R10788_H__
#include "device.h"
/*************************************
*
* Device configuration macros
*
*************************************/
/* Set the writer used to update a display digit */
#define MCFG_R10788_UPDATE(_devcb) \
r10788_device::set_update(*device, DEVCB_##_devcb);
class r10788_device : public device_t
{
public:
r10788_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~r10788_device() {}
enum {
KTR = 0xc, //!< Transfer Keyboard Return
KTS = 0xa, //!< Transfer Keyboard Strobe
KLA = 0xe, //!< Load Display Register A
KLB = 0xd, //!< Load Display Register B
KDN = 0x3, //!< Turn On Display
KAF = 0xb, //!< Turn Off A
KBF = 0x7, //!< Turn Off B
KER = 0x6 //!< Reset Keyboard Error
};
DECLARE_READ8_MEMBER ( io_r );
DECLARE_WRITE8_MEMBER( io_w );
template<class _Object> static devcb_base &set_update(device_t &device, _Object object) { return downcast<r10788_device &>(device).m_display.set_callback(object); }
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
static const device_timer_id TIMER_DISPLAY = 0;
UINT8 m_reg[2][16]; //!< display registers
UINT8 m_ktr; //!< transfer keyboard return value
UINT8 m_kts; //!< transfer keyboard strobe value
UINT8 m_kla; //!< display register A value
UINT8 m_klb; //!< display register B value
UINT8 m_enable; //!< display enable flags for A (1) and B (2)
UINT8 m_ker; //!< keyboard error value
int m_scan_counter; //!< current display scan
devcb_write8 m_display; //!< display updater
emu_timer* m_timer; //!< timer running at clock / 18 / 36
};
extern const device_type R10788;
#endif /* __R10788_H__ */

View File

@ -67,6 +67,7 @@ ToDo:
#include "machine/genpin.h"
#include "machine/r10788.h"
#include "cpu/pps4/pps4.h"
#include "gts1.lh"
@ -87,12 +88,19 @@ public:
{ }
DECLARE_DRIVER_INIT(gts1);
DECLARE_WRITE8_MEMBER(gts1_display_w);
DECLARE_READ8_MEMBER (gts1_io_r);
DECLARE_WRITE8_MEMBER(gts1_io_w);
DECLARE_READ8_MEMBER (gts1_pa_r);
DECLARE_WRITE8_MEMBER(gts1_pa_w);
DECLARE_WRITE8_MEMBER(gts1_pb_w);
private:
virtual void machine_reset();
required_device<cpu_device> m_maincpu;
// required_device<r10788_device> m_gpkd; // FIXME: doesn't compile
UINT8 m_io[256];
UINT8 m_counter;
UINT8 m_6351_addr;
};
@ -101,12 +109,14 @@ static ADDRESS_MAP_START( gts1_map, AS_PROGRAM, 8, gts1_state )
ADDRESS_MAP_END
static ADDRESS_MAP_START( gts1_data, AS_DATA, 8, gts1_state )
AM_RANGE(0x0000, 0x0fff) AM_RAM // not correct
AM_RANGE(0x0000, 0x00ff) AM_RAM // not correct
ADDRESS_MAP_END
static ADDRESS_MAP_START( gts1_io, AS_IO, 8, gts1_state )
AM_RANGE(0x0000, 0x00ff) AM_RAM // connects to all the other chips
AM_RANGE(0x0100, 0x0100) AM_READ (gts1_pa_r) AM_WRITE(gts1_pa_w)
AM_RANGE(0x00d0, 0x00df) AM_DEVREADWRITE ( "r10788", r10788_device, io_r, io_w )
AM_RANGE(0x0000, 0x00ff) AM_READ ( gts1_io_r ) AM_WRITE( gts1_io_w ) // connects to all the other chips
AM_RANGE(0x0100, 0x0100) AM_READ ( gts1_pa_r ) AM_WRITE( gts1_pa_w )
AM_RANGE(0x0101, 0x0101) AM_WRITE(gts1_pb_w)
ADDRESS_MAP_END
@ -199,6 +209,29 @@ DRIVER_INIT_MEMBER(gts1_state,gts1)
{
}
/**
* @brief write a 8seg display value
* @param offset digit number 0 .. 19
* @param data 4-bit value to display
*/
WRITE8_MEMBER(gts1_state::gts1_display_w)
{
output_set_digit_value(offset, data);
}
READ8_MEMBER (gts1_state::gts1_io_r)
{
UINT8 data = m_io[offset] & 0x0f;
LOG(("%s: io[%02x] -> %x\n", __FUNCTION__, offset, data));
return data;
}
WRITE8_MEMBER(gts1_state::gts1_io_w)
{
LOG(("%s: io[%02x] <- %x\n", __FUNCTION__, offset, data));
m_io[offset] = data;
}
READ8_MEMBER (gts1_state::gts1_pa_r)
{
// return ROM nibble
@ -232,8 +265,11 @@ static MACHINE_CONFIG_START( gts1, gts1_state )
//MCFG_NVRAM_ADD_0FILL("nvram")
/* General Purpose Display and Keyboard */
MCFG_R10788_UPDATE( WRITE8(gts1_state,gts1_display_w) )
/* Video */
MCFG_DEFAULT_LAYOUT(layout_gts1)
MCFG_DEFAULT_LAYOUT( layout_gts1 )
/* Sound */
MCFG_FRAGMENT_ADD( genpin_audio )

View File

@ -499,6 +499,7 @@ MACHINES += PCKEYBRD
MACHINES += PIC8259
MACHINES += PIT8253
MACHINES += PLA
MACHINES += R10788
#MACHINES += PROFILE
#MACHINES += R64H156
MACHINES += RF5C296