summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Couriersud <couriersud@users.noreply.github.com>2008-08-22 21:25:49 +0000
committer Couriersud <couriersud@users.noreply.github.com>2008-08-22 21:25:49 +0000
commitd8d031e8d3b9f023d0180279b944b0dfecaeb2eb (patch)
treef750862e9d862022494d51d65f11bf227b299804
parent85e674d7fb9c93a709f9ffff21be83988ad9b959 (diff)
Adds new generic latch device
8 bit latch interface and emulation Generic emulation of 74LS174/175, 74LS259 and other latches. Apart from providing synched latch operation, these latches can be configured to read their input bitwise from other devices as well and individual bits can be connected to discrete nodes. Please see audio/dkong.c for examples.
-rw-r--r--.gitattributes2
-rw-r--r--src/emu/emu.mak1
-rw-r--r--src/emu/machine/latch8.c254
-rw-r--r--src/emu/machine/latch8.h143
4 files changed, 400 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
index 108445bfb23..b998862313f 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -632,6 +632,8 @@ src/emu/machine/intelfsh.c svneol=native#text/plain
src/emu/machine/intelfsh.h svneol=native#text/plain
src/emu/machine/laserdsc.c svneol=native#text/plain
src/emu/machine/laserdsc.h svneol=native#text/plain
+src/emu/machine/latch8.c svneol=native#text/plain
+src/emu/machine/latch8.h svneol=native#text/plain
src/emu/machine/mb3773.c svneol=native#text/plain
src/emu/machine/mb3773.h svneol=native#text/plain
src/emu/machine/mb87078.c svneol=native#text/plain
diff --git a/src/emu/emu.mak b/src/emu/emu.mak
index 3caeb4c09d9..e1d5cc79733 100644
--- a/src/emu/emu.mak
+++ b/src/emu/emu.mak
@@ -138,6 +138,7 @@ EMUMACHINEOBJS = \
$(EMUMACHINE)/i2cmem.o \
$(EMUMACHINE)/idectrl.o \
$(EMUMACHINE)/intelfsh.o \
+ $(EMUMACHINE)/latch8.o \
$(EMUMACHINE)/laserdsc.o \
$(EMUMACHINE)/mb3773.o \
$(EMUMACHINE)/mb87078.o \
diff --git a/src/emu/machine/latch8.c b/src/emu/machine/latch8.c
new file mode 100644
index 00000000000..3668adcbcc2
--- /dev/null
+++ b/src/emu/machine/latch8.c
@@ -0,0 +1,254 @@
+/**********************************************************************
+
+ 8 bit latch interface and emulation
+
+ 2008/08 couriersud
+
+**********************************************************************/
+
+#include "driver.h"
+#include "memconv.h"
+#include "sound/discrete.h"
+#include "latch8.h"
+
+typedef struct _latch8_t latch8_t;
+struct _latch8_t
+{
+ latch8_config *intf;
+ UINT8 value;
+ UINT8 has_node_map;
+ UINT8 has_devread;
+ UINT8 has_read;
+ const device_config *devices[8];
+};
+
+/* ----------------------------------------------------------------------- */
+
+INLINE latch8_t *get_safe_token(const device_config *device) {
+ assert( device != NULL );
+ assert( device->token != NULL );
+ assert( device->type == LATCH8 );
+ return ( latch8_t * ) device->token;
+}
+
+
+static TIMER_CALLBACK( latch8_timerproc )
+{
+ const device_config *device = ptr;
+ latch8_t *latch8 = get_safe_token(device);
+ UINT8 new_val = param & 0xFF;
+ UINT8 mask = param >> 8;
+ UINT8 old_val = latch8->value;
+
+ latch8->value = (latch8->value & ~mask) | (new_val & mask);
+
+ if (latch8->has_node_map)
+ {
+ int i;
+ UINT8 changed = old_val ^ latch8->value;
+ for (i=0; i<8; i++)
+ if (((changed & (1<<i)) != 0) && latch8->intf->node_map[i] != 0)
+ discrete_sound_w(device->machine, latch8->intf->node_map[i] , (latch8->value >> i) & 1);
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+READ8_DEVICE_HANDLER( latch8_r )
+{
+ latch8_t *latch8 = get_safe_token(device);
+ UINT8 res;
+
+ assert(offset == 0);
+
+ res = latch8->value;
+ if (latch8->has_devread)
+ {
+ int i;
+ for (i=0; i<8; i++)
+ {
+ const device_config *read_dev = latch8->devices[i];
+ if (read_dev != NULL)
+ {
+ res &= ~( 1 << i);
+ res |= ((latch8->intf->devread[i].devread_handler(read_dev, 0) >> latch8->intf->devread[i].from_bit) & 0x01) << i;
+ }
+ }
+ }
+ if (latch8->has_read)
+ {
+ int i;
+ for (i=0; i<8; i++)
+ {
+ if (latch8->intf->devread[i].read_handler != NULL)
+ {
+ res &= ~( 1 << i);
+ res |= ((latch8->intf->devread[i].read_handler(device->machine, 0) >> latch8->intf->devread[i].from_bit) & 0x01) << i;
+ }
+ }
+ }
+
+ return (res & ~latch8->intf->mask) ^ latch8->intf->xor;
+}
+
+
+WRITE8_DEVICE_HANDLER( latch8_w )
+{
+ assert(offset == 0);
+
+ timer_call_after_resynch((void *)device, (0xFF << 8) | data, latch8_timerproc);
+}
+
+
+WRITE8_DEVICE_HANDLER( latch8_reset)
+{
+ latch8_t *latch8 = get_safe_token(device);
+
+ assert(offset == 0);
+
+ latch8->value = 0;
+}
+
+/* read bit x */
+/* return (latch >> x) & 0x01 */
+
+INLINE UINT8 latch8_bitx_r(const device_config *device, offs_t offset, int bit)
+{
+ latch8_t *latch8 = get_safe_token(device);
+
+ assert( offset == 0);
+
+ return (latch8->value >> bit) & 0x01;
+}
+
+READ8_DEVICE_HANDLER( latch8_bit0_r) { return latch8_bitx_r(device, offset, 0); }
+READ8_DEVICE_HANDLER( latch8_bit1_r) { return latch8_bitx_r(device, offset, 1); }
+READ8_DEVICE_HANDLER( latch8_bit2_r) { return latch8_bitx_r(device, offset, 2); }
+READ8_DEVICE_HANDLER( latch8_bit3_r) { return latch8_bitx_r(device, offset, 3); }
+READ8_DEVICE_HANDLER( latch8_bit4_r) { return latch8_bitx_r(device, offset, 4); }
+READ8_DEVICE_HANDLER( latch8_bit5_r) { return latch8_bitx_r(device, offset, 5); }
+READ8_DEVICE_HANDLER( latch8_bit6_r) { return latch8_bitx_r(device, offset, 6); }
+READ8_DEVICE_HANDLER( latch8_bit7_r) { return latch8_bitx_r(device, offset, 7); }
+
+READ8_DEVICE_HANDLER( latch8_bit0_q_r) { return latch8_bitx_r(device, offset, 0) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit1_q_r) { return latch8_bitx_r(device, offset, 1) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit2_q_r) { return latch8_bitx_r(device, offset, 2) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit3_q_r) { return latch8_bitx_r(device, offset, 3) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit4_q_r) { return latch8_bitx_r(device, offset, 4) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit5_q_r) { return latch8_bitx_r(device, offset, 5) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit6_q_r) { return latch8_bitx_r(device, offset, 6) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit7_q_r) { return latch8_bitx_r(device, offset, 7) ^ 1; }
+
+/* write bit x from data into bit determined by offset */
+/* latch = (latch & ~(1<<offset)) | (((data >> x) & 0x01) << offset) */
+
+INLINE void latch8_bitx_w(const device_config *device, int bit, offs_t offset, UINT8 data)
+{
+ UINT8 mask = (1<<offset);
+ UINT8 masked_data = (((data >> bit) & 0x01) << offset);
+
+ assert( offset < 8);
+
+ timer_call_after_resynch((void *) device, (mask << 8) | masked_data, latch8_timerproc);
+}
+
+WRITE8_DEVICE_HANDLER( latch8_bit0_w ) { latch8_bitx_w(device, 0, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit1_w ) { latch8_bitx_w(device, 1, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit2_w ) { latch8_bitx_w(device, 2, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit3_w ) { latch8_bitx_w(device, 3, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit4_w ) { latch8_bitx_w(device, 4, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit5_w ) { latch8_bitx_w(device, 0, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit6_w ) { latch8_bitx_w(device, 0, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit7_w ) { latch8_bitx_w(device, 0, offset, data); }
+
+/* ----------------------------------------------------------------------- */
+
+/* device interface */
+
+static DEVICE_START( latch8 )
+{
+ latch8_t *latch8 = get_safe_token(device);
+ char unique_tag[30];
+ int i;
+
+ /* validate arguments */
+ assert(strlen(device->tag) < 20);
+
+ latch8->intf = device->inline_config;
+
+ latch8->value = 0x0;
+
+ /* setup nodemap */
+ for (i=0; i<8; i++)
+ if (latch8->intf->node_map[i] )
+ latch8->has_node_map = 1;
+
+ /* setup device read handlers */
+ for (i=0; i<8; i++)
+ if (latch8->intf->devread[i].tag != NULL)
+ {
+ if (latch8->devices[i] != NULL)
+ fatalerror("Device %s: Bit %d already has a handler.\n", device->tag, i);
+ latch8->devices[i] = devtag_get_device(device->machine,
+ latch8->intf->devread[i].type,
+ latch8->intf->devread[i].tag);
+ if (latch8->devices[i] == NULL)
+ fatalerror("Device %s: Unable to find device %s\n", device->tag, latch8->intf->devread[i].tag);
+ latch8->has_devread = 1;
+ }
+
+ /* setup machine read handlers */
+ for (i=0; i<8; i++)
+ if (latch8->intf->devread[i].read_handler != NULL)
+ {
+ if (latch8->devices[i] != NULL)
+ fatalerror("Device %s: Bit %d already has a handler.\n", device->tag, i);
+ latch8->has_read = 1;
+ }
+
+ state_save_combine_module_and_tag(unique_tag, "latch8", device->tag);
+
+ state_save_register_item(unique_tag, 0, latch8->value);
+}
+
+
+static DEVICE_RESET( latch8 )
+{
+ latch8_t *latch8 = get_safe_token(device);
+
+ latch8->value = 0;
+}
+
+
+static DEVICE_SET_INFO( latch8 )
+{
+ switch (state)
+ {
+ /* no parameters to set */
+ }
+}
+
+
+DEVICE_GET_INFO( latch8 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(latch8_t); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(latch8_config); break;
+ case DEVINFO_INT_CLASS: info->i = DEVICE_CLASS_PERIPHERAL; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_SET_INFO: info->set_info = DEVICE_SET_INFO_NAME(latch8); break;
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(latch8);break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(latch8);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: info->s = "8 bit latch"; break;
+ case DEVINFO_STR_FAMILY: info->s = "Latches"; break;
+ case DEVINFO_STR_VERSION: info->s = "1.0"; break;
+ case DEVINFO_STR_SOURCE_FILE: info->s = __FILE__; break;
+ case DEVINFO_STR_CREDITS: info->s = "Copyright Nicola Salmoria and the MAME Team"; break;
+ }
+}
diff --git a/src/emu/machine/latch8.h b/src/emu/machine/latch8.h
new file mode 100644
index 00000000000..b3c75cbfcc1
--- /dev/null
+++ b/src/emu/machine/latch8.h
@@ -0,0 +1,143 @@
+/**********************************************************************
+
+ 8 bit latch interface and emulation
+
+ Generic emulation of 74LS174/175, 74LS259 and other latches.
+ Apart from providing synched latch operation, these
+ latches can be configured to read their input bitwise from other
+ devices as well and individual bits can be connected to
+ discrete nodes.
+
+ Please see audio/dkong.c for examples.
+
+**********************************************************************/
+
+#ifndef __LATCH8_H_
+#define __LATCH8_H_
+
+#define LATCH8 DEVICE_GET_INFO_NAME(latch8)
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _latch8_devread latch8_devread;
+struct _latch8_devread
+{
+ /* only for byte reads, does not affect bit reads and node_map */
+ UINT32 from_bit;
+ device_type type;
+ const char *tag;
+ read8_device_func devread_handler;
+ read8_machine_func read_handler;
+};
+
+typedef struct _latch8_config latch8_config;
+struct _latch8_config
+{
+ /* only for byte reads, does not affect bit reads and node_map */
+ UINT32 mask;
+ UINT32 xor; /* after mask */
+ UINT32 node_map[8];
+ latch8_devread devread[8];
+};
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+/* add device */
+#define MDRV_LATCH8_ADD(_tag) \
+ MDRV_DEVICE_ADD(_tag, LATCH8)
+
+/* Bit mask specifying bits to be masked *out* */
+#define MDRV_LATCH8_MASK(_mask) \
+ MDRV_DEVICE_CONFIG_DATA32(latch8_config, mask, _mask)
+
+/* Bit mask specifying bits to be inverted */
+#define MDRV_LATCH8_INVERT(_xor) \
+ MDRV_DEVICE_CONFIG_DATA32(latch8_config, xor, _xor)
+
+/* Write bit to discrete node */
+#define MDRV_LATCH8_DISCRETE_NODE(_bit, _node) \
+ MDRV_DEVICE_CONFIG_DATA32(latch8_config, node_map[_bit], _node)
+
+/* Upon read, replace bits by reading from another device handler */
+#define MDRV_LATCH8_DEVREAD(_bit, _type, _tag, _handler, _from_bit) \
+ MDRV_DEVICE_CONFIG_DATA32(latch8_config, devread[_bit].from_bit, _from_bit) \
+ MDRV_DEVICE_CONFIG_DATAPTR(latch8_config, devread[_bit].type, _type) \
+ MDRV_DEVICE_CONFIG_DATAPTR(latch8_config, devread[_bit].tag, _tag) \
+ MDRV_DEVICE_CONFIG_DATAPTR(latch8_config, devread[_bit].devread_handler, _handler)
+
+/* Upon read, replace bits by reading from another machine handler */
+#define MDRV_LATCH8_READ(_bit, _handler, _from_bit) \
+ MDRV_DEVICE_CONFIG_DATA32(latch8_config, devread[_bit].from_bit, _from_bit) \
+ MDRV_DEVICE_CONFIG_DATAPTR(latch8_config, devread[_bit].read_handler, _handler)
+
+/* remove device */
+#define MDRV_LATCH8_REMOVE(_tag) \
+ MDRV_DEVICE_REMOVE(LATCH8, _type)
+
+/* Accessor macros */
+
+#define AM_LATCH8_READ(_tag) \
+ AM_DEVREAD(LATCH8, _tag, latch8_r)
+
+#define AM_LATCH8_READBIT(_tag, _bit) \
+ AM_DEVREAD(LATCH8, _tag, latch8_bit ## _bit ## _q_r)
+
+#define AM_LATCH8_WRITE(_tag) \
+ AM_DEVWRITE(LATCH8, _tag, latch8_w)
+
+#define AM_LATCH8_READWRITE(_tag) \
+ AM_DEVREADWRITE(LATCH8, _tag, latch8_r, latch8_w)
+
+/* device interface */
+DEVICE_GET_INFO( latch8 );
+
+/* write & read full byte */
+
+READ8_DEVICE_HANDLER( latch8_r);
+WRITE8_DEVICE_HANDLER( latch8_w);
+
+/* reset the latch */
+
+WRITE8_DEVICE_HANDLER( latch8_reset);
+
+/* read bit x */
+/* return (latch >> x) & 0x01 */
+
+READ8_DEVICE_HANDLER( latch8_bit0_r);
+READ8_DEVICE_HANDLER( latch8_bit1_r);
+READ8_DEVICE_HANDLER( latch8_bit2_r);
+READ8_DEVICE_HANDLER( latch8_bit3_r);
+READ8_DEVICE_HANDLER( latch8_bit4_r);
+READ8_DEVICE_HANDLER( latch8_bit5_r);
+READ8_DEVICE_HANDLER( latch8_bit6_r);
+READ8_DEVICE_HANDLER( latch8_bit7_r);
+
+/* read inverted bit x */
+/* return (latch >> x) & 0x01 */
+
+READ8_DEVICE_HANDLER( latch8_bit0_q_r);
+READ8_DEVICE_HANDLER( latch8_bit1_q_r);
+READ8_DEVICE_HANDLER( latch8_bit2_q_r);
+READ8_DEVICE_HANDLER( latch8_bit3_q_r);
+READ8_DEVICE_HANDLER( latch8_bit4_q_r);
+READ8_DEVICE_HANDLER( latch8_bit5_q_r);
+READ8_DEVICE_HANDLER( latch8_bit6_q_r);
+READ8_DEVICE_HANDLER( latch8_bit7_q_r);
+
+/* write bit x from data into bit determined by offset */
+/* latch = (latch & ~(1<<offset)) | (((data >> x) & 0x01) << offset) */
+
+WRITE8_DEVICE_HANDLER( latch8_bit0_w );
+WRITE8_DEVICE_HANDLER( latch8_bit1_w );
+WRITE8_DEVICE_HANDLER( latch8_bit2_w );
+WRITE8_DEVICE_HANDLER( latch8_bit3_w );
+WRITE8_DEVICE_HANDLER( latch8_bit4_w );
+WRITE8_DEVICE_HANDLER( latch8_bit5_w );
+WRITE8_DEVICE_HANDLER( latch8_bit6_w );
+WRITE8_DEVICE_HANDLER( latch8_bit7_w );
+
+#endif /* __LATCH8_H_ */