summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/dl1416.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/dl1416.cpp')
-rw-r--r--src/devices/video/dl1416.cpp297
1 files changed, 297 insertions, 0 deletions
diff --git a/src/devices/video/dl1416.cpp b/src/devices/video/dl1416.cpp
new file mode 100644
index 00000000000..b017e9994e1
--- /dev/null
+++ b/src/devices/video/dl1416.cpp
@@ -0,0 +1,297 @@
+// license:GPL-2.0+
+// copyright-holders:Dirk Best
+/*****************************************************************************
+ *
+ * DL1416
+ *
+ *
+ * 4-Digit 16-Segment Alphanumeric Intelligent Display
+ * with Memory/Decoder/Driver
+ *
+ * Notes:
+ * - Currently supports the DL1416T and by virtue of it being nearly the same, the DL1414.
+ * - Partial support for DL1416B is available, it just needs the right
+ * character set and MAME core support for its display.
+ * - Cursor support is implemented but not tested, as the AIM65 does not
+ * seem to use it.
+ *
+ * Todo:
+ * - Is the DL1416A identical to the DL1416T? If not, we need to add
+ * support for it.
+ * - Add proper support for DL1414 (pretty much DL1416T without the cursor)
+ *
+ * Changes:
+ * - 2007-07-30: Initial version. [Dirk Best]
+ * - 2008-02-25: Converted to the new device interface. [Dirk Best]
+ * - 2008-12-18: Cleanups. [Dirk Best]
+ * - 2011-10-08: Changed the ram to store character rather than segment data. [Lord Nightmare]
+ *
+ *
+ * We use the following order for the segments:
+ *
+ * 000 111
+ * 7D A E2
+ * 7 D A E 2
+ * 7 DAE 2
+ * 888 999
+ * 6 CBF 3
+ * 6 C B F 3
+ * 6C B F3
+ * 555 444
+ *
+ ****************************************************************************/
+
+#include "emu.h"
+#include "dl1416.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define SEG_UNDEF (0xfffe)
+#define SEG_BLANK (0)
+#define SEG_CURSOR (0xffff)
+#define CURSOR_ON (1)
+#define CURSOR_OFF (0)
+
+/* character set DL1416T */
+static const UINT16 dl1416t_segments[128] = {
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ 0x0000, 0x2421, 0x0480, 0x0f3c, /* ! " # */
+ 0x0fbb, 0x5f99, 0xa579, 0x4000, /* $ % & ' */
+ 0xc000, 0x3000, 0xff00, 0x0f00, /* ( ) * + */
+ 0x1000, 0x0300, 0x0020, 0x5000, /* , - . / */
+ 0x0ce1, 0x0c00, 0x0561, 0x0d21, /* 0 1 2 3 */
+ 0x0d80, 0x09a1, 0x09e1, 0x0c01, /* 4 5 6 7 */
+ 0x0de1, 0x0da1, 0x0021, 0x1001, /* 8 9 : ; */
+ 0x5030, 0x0330, 0xa030, 0x0a07, /* < = > ? */
+ 0x097f, 0x03cf, 0x0e3f, 0x00f3, /* @ A B C */
+ 0x0c3f, 0x01f3, 0x01c3, 0x02fb, /* D E F G */
+ 0x03cc, 0x0c33, 0x0c63, 0xc1c0, /* H I J K */
+ 0x00f0, 0x60cc, 0xa0cc, 0x00ff, /* L M N O */
+ 0x03c7, 0x80ff, 0x83c7, 0x03bb, /* P Q R S */
+ 0x0c03, 0x00fc, 0x50c0, 0x90cc, /* T U V W */
+ 0xf000, 0x6800, 0x5033, 0x00e1, /* X Y Z [ */
+ 0xa000, 0x001e, 0x9000, 0x0030, /* \ ] ^ _ */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
+ SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF /* undefined */
+};
+
+
+/*****************************************************************************
+ DEVICE INTERFACE
+*****************************************************************************/
+
+dl1416_device::dl1416_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_enable(FALSE),
+ m_chip_enable(FALSE),
+ m_cursor_enable(FALSE),
+ m_update(*this)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ m_digit_ram[i] = 0;
+ m_cursor_state[i] = 0;
+ }
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dl1416_device::device_start()
+{
+ /* register for state saving */
+ save_item(NAME(m_chip_enable));
+ save_item(NAME(m_cursor_enable));
+ save_item(NAME(m_write_enable));
+ save_item(NAME(m_digit_ram));
+
+ m_update.resolve();
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void dl1416_device::device_reset()
+{
+ int i;
+ UINT16 pattern;
+ /* disable all lines */
+ m_chip_enable = FALSE;
+ m_write_enable = FALSE;
+ m_cursor_enable = FALSE;
+
+ /* randomize digit and cursor memory */
+ for (i = 0; i < 4; i++)
+ {
+ m_digit_ram[i] = machine().rand()&0x3F;
+ // TODO: only enable the following line if the device actually has a cursor (DL1416T and DL1416B), if DL1414 then cursor is always 0!
+ //m_cursor_state[i] = ((device->machine().rand()&0xFF) >= 0x80) ? CURSOR_ON : CURSOR_OFF;
+ m_cursor_state[i] = CURSOR_OFF;
+ pattern = dl1416t_segments[m_digit_ram[i]];
+
+ /* If cursor for this digit position is enabled and segment is not */
+ /* undefined, replace digit with cursor */
+ if ((m_cursor_state[i] == CURSOR_ON) && (pattern != SEG_UNDEF))
+ pattern = SEG_CURSOR;
+
+ /* Undefined characters are replaced by blanks */
+ if (pattern == SEG_UNDEF)
+ pattern = SEG_BLANK;
+
+ /* Call update function */
+ if (!m_update.isnull())
+ m_update((offs_t)i, pattern);
+ }
+}
+
+
+const device_type DL1416B = &device_creator<dl1416b_device>;
+
+dl1416b_device::dl1416b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : dl1416_device(mconfig, DL1416B, "DL1416B", tag, owner, clock, "dl1416b", __FILE__)
+{
+}
+
+
+const device_type DL1416T = &device_creator<dl1416t_device>;
+
+dl1416t_device::dl1416t_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : dl1416_device(mconfig, DL1416T, "DL1416T", tag, owner, clock, "dl1416t", __FILE__)
+{
+}
+
+
+/*****************************************************************************
+ IMPLEMENTATION
+*****************************************************************************/
+
+/* write enable, active low */
+WRITE_LINE_MEMBER( dl1416_device::wr_w )
+{
+ m_write_enable = !state;
+}
+
+/* chip enable, active low */
+WRITE_LINE_MEMBER( dl1416_device::ce_w )
+{
+ m_chip_enable = !state;
+}
+
+/* cursor enable, active low */
+WRITE_LINE_MEMBER( dl1416_device::cu_w )
+{
+ m_cursor_enable = !state;
+}
+
+/* data */
+WRITE8_MEMBER( dl1416_device::data_w )
+{
+ offset &= 0x03; /* A0-A1 */
+ data &= 0x7f; /* D0-D6 */
+
+ /* Only try to update the data if we are enabled and write is enabled */
+ if (m_chip_enable && m_write_enable)
+ {
+ /* fprintf(stderr,"DL1416 Write: Cursor: %d, Offset: %d, Data: %02X\n (%c)", m_cursor_enable, offset, data, data); */
+ int i, pattern, previous_state;
+
+ if (m_cursor_enable) /* cursor enable is set */
+ {
+ if (type() == DL1416B)
+ {
+ /* DL1416B uses offset to decide cursor pos to change and D0 to hold new state */
+
+ /* The cursor will be set if D0 is high and the original */
+ /* character restored otherwise */
+ previous_state = m_cursor_state[offset];
+ m_cursor_state[offset] = data & 1 ? CURSOR_ON : CURSOR_OFF;
+
+ if (previous_state != m_cursor_state[offset])
+ {
+ pattern = dl1416t_segments[m_digit_ram[offset]];
+
+ /* If cursor for this digit position is enabled and segment is not */
+ /* undefined, replace digit with cursor */
+ if ((m_cursor_state[offset] == CURSOR_ON) && (pattern != SEG_UNDEF))
+ pattern = SEG_CURSOR;
+
+ /* Undefined characters are replaced by blanks */
+ if (pattern == SEG_UNDEF)
+ pattern = SEG_BLANK;
+
+ /* Call update function */
+ if (!m_update.isnull())
+ m_update(offset, pattern, mem_mask);
+ }
+ }
+ else {
+ /* DL1416T uses a bitmap of 4 data bits D0,D1,D2,D3 to decide cursor pos to change and new state */
+
+ for (i = 0; i < 4; i++)
+ {
+ /* The cursor will be set if D0-D3 is high and the original */
+ /* character at the appropriate position restored otherwise */
+ previous_state = m_cursor_state[i];
+ m_cursor_state[i] = data & (1<<i) ? CURSOR_ON : CURSOR_OFF;
+
+ if (previous_state != m_cursor_state[i])
+ {
+ pattern = dl1416t_segments[m_digit_ram[i]];
+
+ /* If cursor for this digit position is enabled and segment is not */
+ /* undefined, replace digit with cursor */
+ if ((m_cursor_state[i] == CURSOR_ON) && (pattern != SEG_UNDEF))
+ pattern = SEG_CURSOR;
+
+ /* Undefined characters are replaced by blanks */
+ if (pattern == SEG_UNDEF)
+ pattern = SEG_BLANK;
+
+ /* Call update function */
+ if (!m_update.isnull())
+ m_update(i, pattern, mem_mask);
+ }
+ }
+ }
+ }
+ else /* cursor enable is not set, so standard write */
+ {
+ /* Save written value */
+ m_digit_ram[offset] = data&0x3f;
+
+ /* Load segment pattern from ROM */
+ pattern = dl1416t_segments[data]; /** TODO: handle DL1416T vs DL1416B vs DL1414 here */
+
+ /* If cursor for this digit position is enabled and segment is not */
+ /* undefined, replace digit with cursor */
+ if ((m_cursor_state[offset] == CURSOR_ON) && (pattern != SEG_UNDEF))
+ pattern = SEG_CURSOR;
+
+ /* Undefined characters are replaced by blanks */
+ if (pattern == SEG_UNDEF)
+ pattern = SEG_BLANK;
+
+ /* Call update function */
+ if (!m_update.isnull())
+ m_update(offset, pattern, mem_mask);
+ }
+ }
+}