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.cpp364
1 files changed, 194 insertions, 170 deletions
diff --git a/src/devices/video/dl1416.cpp b/src/devices/video/dl1416.cpp
index 7bec9bc693f..752dbc2af13 100644
--- a/src/devices/video/dl1416.cpp
+++ b/src/devices/video/dl1416.cpp
@@ -1,5 +1,5 @@
// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// copyright-holders:Dirk Best, Vas Crabb
/*****************************************************************************
*
* DL1416
@@ -9,22 +9,22 @@
* 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.
+ * - Currently supports the DL1416T and by virtue of it being nearly the
+ * same, the DL1414.
+ * - The DL1416B uses a simpler sequence to control cursor display, and
+ * has a '.' segment but is otherwise fully compatible with the DL1416T.
* - 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)
+ * TODO:
+ * - '.' segment for DL1414T and DL1416B
*
* 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]
+ * - 2017-02-11: Better signal-level interface, better support for variants [Vas Crabb]
*
*
* We use the following order for the segments:
@@ -44,19 +44,19 @@
#include "emu.h"
#include "dl1416.h"
+namespace {
/***************************************************************************
CONSTANTS
***************************************************************************/
-#define SEG_UNDEF (0xfffe)
-#define SEG_BLANK (0)
-#define SEG_CURSOR (0xffff)
-#define CURSOR_ON (1)
-#define CURSOR_OFF (0)
+constexpr uint16_t SEG_BLANK = 0x0000;
+constexpr uint16_t SEG_UNDEF = SEG_BLANK;
+constexpr uint16_t SEG_CURSOR = 0xffff;
+
/* character set DL1416T */
-static const uint16_t dl1416t_segments[128] = {
+uint16_t const 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 */
@@ -92,90 +92,174 @@ static const uint16_t dl1416t_segments[128] = {
};
-/*****************************************************************************
- DEVICE INTERFACE
-*****************************************************************************/
+class dl1414t_device : public dl1414_device
+{
+public:
+ dl1414t_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : dl1414_device(mconfig, DL1414T, "DL1414T", tag, owner, clock, "dl1414t", __FILE__)
+ {
+ }
-dl1416_device::dl1416_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t 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)
+protected:
+ virtual uint16_t translate(uint8_t digit, bool cursor) const override
+ {
+ return dl1416t_segments[digit & 0x7f];
+ }
+};
+
+
+class dl1416b_device : public dl1416_device
{
- for (int i = 0; i < 4; i++)
+public:
+ dl1416b_device(machine_config const &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : dl1416_device(mconfig, DL1416B, "DL1416B", tag, owner, clock, "dl1416b", __FILE__)
{
- m_digit_ram[i] = 0;
- m_cursor_state[i] = 0;
}
-}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+ virtual DECLARE_WRITE8_MEMBER(bus_w) override
+ {
+ if (!cu_in())
+ set_cursor_state(offset, BIT(data, 0));
+ else
+ dl1416_device::bus_w(space, offset, data, mem_mask);
+ }
-void dl1416_device::device_start()
+protected:
+ virtual uint16_t translate(uint8_t digit, bool cursor) const override
+ {
+ return cursor ? SEG_CURSOR : dl1416t_segments[digit & 0x7f];
+ }
+};
+
+
+class dl1416t_device : public dl1416_device
{
- /* 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));
+public:
+ dl1416t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : dl1416_device(mconfig, DL1416T, "DL1416T", tag, owner, clock, "dl1416t", __FILE__)
+ {
+ }
+
+ virtual DECLARE_WRITE8_MEMBER(bus_w) override
+ {
+ if (!cu_in())
+ for (unsigned i = 0; 4 > i; ++i) set_cursor_state(i, BIT(data, i));
+ else
+ dl1416_device::bus_w(space, offset, data, mem_mask);
+ }
+
+protected:
+ virtual uint16_t translate(uint8_t digit, bool cursor) const override
+ {
+ digit &= 0x7f;
+ return (cursor && (0x20 <= digit) && (0x5f >= digit)) ? SEG_CURSOR : dl1416t_segments[digit];
+ }
+};
+
+} // anonymous namespace
+
+
+
+/*****************************************************************************
+ DEVICE TYPE GLOBALS
+*****************************************************************************/
+
+device_type const DL1414T = &device_creator<dl1414t_device>;
+device_type const DL1416B = &device_creator<dl1416b_device>;
+device_type const DL1416T = &device_creator<dl1416t_device>;
+
+
- m_update.resolve();
+/*****************************************************************************
+ DEVICE INTERFACE
+*****************************************************************************/
+
+dl1414_device::dl1414_device(
+ machine_config const &mconfig,
+ device_type type,
+ char const *name,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock,
+ char const *shortname,
+ char const *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source)
+ , m_update_cb(*this)
+ , m_digit_ram{ 0x00, 0x00, 0x00, 0x00 }
+ , m_cursor_state{ false, false, false, false }
+ , m_wr_in(true)
+ , m_ce_in(true)
+ , m_addr_in(0x00)
+ , m_data_in(0x00)
+{
+}
+
+dl1416_device::dl1416_device(
+ machine_config const &mconfig,
+ device_type type,
+ char const *name,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock,
+ char const *shortname,
+ char const *source)
+ : dl1414_device(mconfig, type, name, tag, owner, clock, shortname, source)
+ , m_cu_in(true)
+{
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// device_start - device-specific startup
//-------------------------------------------------
-void dl1416_device::device_reset()
+void dl1414_device::device_start()
{
- int i;
- uint16_t 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_update_cb.resolve_safe();
+
+ // register for state saving
+ save_item(NAME(m_digit_ram));
+ save_item(NAME(m_cursor_state));
+ save_item(NAME(m_wr_in));
+ save_item(NAME(m_ce_in));
+ save_item(NAME(m_addr_in));
+ save_item(NAME(m_data_in));
+
+ // set initial state for input lines
+ m_wr_in = true;
+ m_ce_in = true;
+ m_addr_in = 0x00;
+ m_data_in = 0x00;
+
+ // randomise internal RAM
+ for (unsigned i = 0; 4 > i; ++i)
{
- m_digit_ram[i] = machine().rand()&0x3F;
+ 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);
+ //m_cursor_state[i] = bool(BIT(device->machine().rand(), 7));
+ m_cursor_state[i] = false;
}
}
+void dl1416_device::device_start()
+{
+ dl1414_device::device_start();
-const device_type DL1416B = &device_creator<dl1416b_device>;
+ // register for state saving
+ save_item(NAME(m_cu_in));
-dl1416b_device::dl1416b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : dl1416_device(mconfig, DL1416B, "DL1416B", tag, owner, clock, "dl1416b", __FILE__)
-{
+ // set initial state for input lines
+ m_cu_in = true;
}
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
-const device_type DL1416T = &device_creator<dl1416t_device>;
-
-dl1416t_device::dl1416t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : dl1416_device(mconfig, DL1416T, "DL1416T", tag, owner, clock, "dl1416t", __FILE__)
+void dl1414_device::device_reset()
{
+ // push initial display state
+ for (unsigned i = 0; 4 > i; ++i)
+ m_update_cb(i, translate(m_digit_ram[i], m_cursor_state[i]), 0xffff);
}
@@ -183,115 +267,55 @@ dl1416t_device::dl1416t_device(const machine_config &mconfig, const char *tag, d
IMPLEMENTATION
*****************************************************************************/
-/* write enable, active low */
-WRITE_LINE_MEMBER( dl1416_device::wr_w )
+WRITE_LINE_MEMBER( dl1414_device::wr_w )
{
- m_write_enable = !state;
+ if (bool(state) != m_wr_in)
+ {
+ m_wr_in = bool(state);
+ if (!m_ce_in && m_wr_in)
+ bus_w(machine().dummy_space(), m_addr_in, m_data_in, 0x7f);
+ }
}
-/* chip enable, active low */
-WRITE_LINE_MEMBER( dl1416_device::ce_w )
+WRITE_LINE_MEMBER( dl1414_device::ce_w )
{
- m_chip_enable = !state;
+ m_ce_in = bool(state);
}
-/* cursor enable, active low */
WRITE_LINE_MEMBER( dl1416_device::cu_w )
{
- m_cursor_enable = !state;
+ m_cu_in = bool(state);
+}
+
+void dl1414_device::addr_w(u8 state)
+{
+ m_addr_in = state & 0x03;
+}
+
+void dl1414_device::data_w(u8 state)
+{
+ m_data_in = state & 0x7f;
+}
+
+WRITE8_MEMBER( dl1414_device::bus_w )
+{
+ offset &= 0x03; // A0-A1
+ data &= 0x7f; // D0-D6
+
+ if (m_digit_ram[offset] != data)
+ {
+ m_digit_ram[offset] = data;
+ m_update_cb(offset, translate(m_digit_ram[offset], m_cursor_state[offset]), 0xffff);
+ }
}
-/* data */
-WRITE8_MEMBER( dl1416_device::data_w )
+void dl1414_device::set_cursor_state(offs_t offset, bool state)
{
- offset &= 0x03; /* A0-A1 */
- data &= 0x7f; /* D0-D6 */
+ offset &= 0x03; // A0-A1
- /* Only try to update the data if we are enabled and write is enabled */
- if (m_chip_enable && m_write_enable)
+ if (state != m_cursor_state[offset])
{
- /* 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);
- }
+ m_cursor_state[offset] = state;
+ m_update_cb(offset, translate(m_digit_ram[offset], m_cursor_state[offset]), 0xffff);
}
}