summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2019-06-14 17:45:38 +0200
committer hap <happppp@users.noreply.github.com>2019-06-14 17:45:53 +0200
commited0202220a5243537f5ba7dbc0a38e52a8390d79 (patch)
treea507513cad7ecd6eb681e4e1722bb89e1fcd63c0
parentf1d338e9e68c317a7fad8890ddf7c425303cbc75 (diff)
screenless: make it a device (nw)
-rw-r--r--scripts/src/video.lua11
-rw-r--r--scripts/target/mame/arcade.lua1
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/machine/chessmachine.h6
-rw-r--r--src/devices/video/hlcd0538.cpp2
-rw-r--r--src/devices/video/pwm.cpp269
-rw-r--r--src/devices/video/pwm.h96
-rw-r--r--src/emu/devcb.h16
-rw-r--r--src/mame/drivers/cking_master.cpp28
-rw-r--r--src/mame/drivers/cxg_ch2001.cpp22
-rw-r--r--src/mame/drivers/hh_amis2k.cpp28
-rw-r--r--src/mame/drivers/hh_tms1k.cpp32
-rw-r--r--src/mame/drivers/tispeak.cpp2
-rw-r--r--src/mame/drivers/tispellb.cpp2
-rw-r--r--src/mame/includes/hh_tms1k.h8
-rw-r--r--src/mame/layout/tntell.lay2
-rw-r--r--src/mame/machine/chessbase.cpp2
-rw-r--r--src/mame/machine/screenless.cpp2
18 files changed, 447 insertions, 83 deletions
diff --git a/scripts/src/video.lua b/scripts/src/video.lua
index 042be7e2a19..87a36ce6b5a 100644
--- a/scripts/src/video.lua
+++ b/scripts/src/video.lua
@@ -735,6 +735,17 @@ end
--------------------------------------------------
--
+--@src/devices/video/pwm.h,VIDEOS["PWM_DISPLAY"] = true
+--------------------------------------------------
+if (VIDEOS["PWM_DISPLAY"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/video/pwm.cpp",
+ MAME_DIR .. "src/devices/video/pwm.h",
+ }
+end
+
+--------------------------------------------------
+--
--@src/devices/video/sed1200.h,VIDEOS["SED1200"] = true
--------------------------------------------------
if (VIDEOS["SED1200"]~=null) then
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 1602d1ea032..672498d88f5 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -336,6 +336,7 @@ VIDEOS["RAMDAC"] = true
VIDEOS["SAA5050"] = true
--VIDEOS["SDA5708"] = true
VIDEOS["SCN2674"] = true
+--VIDEOS["PWM_DISPLAY"] = true
--VIDEOS["SED1200"] = true
--VIDEOS["SED1330"] = true
--VIDEOS["SED1520"] = true
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 86c89d6b5be..65f0da3ee75 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -354,6 +354,7 @@ VIDEOS["PSX"] = true
VIDEOS["RAMDAC"] = true
VIDEOS["S2636"] = true
VIDEOS["SAA5050"] = true
+VIDEOS["PWM_DISPLAY"] = true
VIDEOS["SDA5708"] = true
VIDEOS["SED1200"] = true
VIDEOS["SED1330"] = true
diff --git a/src/devices/machine/chessmachine.h b/src/devices/machine/chessmachine.h
index 388e9f9db22..4d589fc97c3 100644
--- a/src/devices/machine/chessmachine.h
+++ b/src/devices/machine/chessmachine.h
@@ -6,8 +6,8 @@
*/
-#ifndef MAME_MACHINE_CHESSM_H
-#define MAME_MACHINE_CHESSM_H
+#ifndef MAME_MACHINE_CHESSMACHINE_H
+#define MAME_MACHINE_CHESSMACHINE_H
#pragma once
@@ -63,4 +63,4 @@ private:
DECLARE_DEVICE_TYPE(CHESSMACHINE, chessmachine_device)
-#endif // MAME_MACHINE_CHESSM_H
+#endif // MAME_MACHINE_CHESSMACHINE_H
diff --git a/src/devices/video/hlcd0538.cpp b/src/devices/video/hlcd0538.cpp
index 12a188d07a0..40498ef84c3 100644
--- a/src/devices/video/hlcd0538.cpp
+++ b/src/devices/video/hlcd0538.cpp
@@ -83,7 +83,7 @@ WRITE_LINE_MEMBER(hlcd0538_device::lcd_w)
// transfer to latches on rising edge
if (state && !m_lcd)
{
- m_write_cols(0, m_shift, ~u64(0));
+ m_write_cols(0, m_shift);
m_shift = 0;
}
diff --git a/src/devices/video/pwm.cpp b/src/devices/video/pwm.cpp
new file mode 100644
index 00000000000..c54cdbc979a
--- /dev/null
+++ b/src/devices/video/pwm.cpp
@@ -0,0 +1,269 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*
+
+This thing is a generic helper for PWM(strobed) display elements, to prevent flickering
+and optionally handle perceived brightness levels.
+
+Common usecase is to call matrix(selmask, datamask), a collision between the 2 masks
+implies a powered-on display element (eg, a LED, or VFD sprite). The maximum matrix
+size is 64 by 64, simply due to uint64_t constraints. If a larger size is needed,
+create an array of pwm_display_device.
+
+If display elements are directly addressable, you can use write_element or write_row
+to set them. In this case it is required to call update() to apply the changes.
+
+Display element states are sent to output tags "y.x" where y is the matrix row number,
+x is the row bit. It is also sent to "y.a" for all rows. The output state is 0 for off,
+and >0 for on, depending on brightness level. If segmask is defined, it is also sent
+to "digity", for use with multi-state elements, eg. 7seg leds.
+
+If you use this device in a slot, or use multiple of them (or just don't want to use
+the default output tags), set a callback.
+
+TODO:
+- multiple brightness levels doesn't work for SVGs
+
+*/
+
+#include "emu.h"
+#include "video/pwm.h"
+
+#include <algorithm>
+
+
+DEFINE_DEVICE_TYPE(PWM_DISPLAY, pwm_display_device, "pwm_display", "PWM Display")
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+pwm_display_device::pwm_display_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, PWM_DISPLAY, tag, owner, clock),
+ m_out_x(*this, "%u.%u", 0U, 0U),
+ m_out_a(*this, "%u.a", 0U),
+ m_out_digit(*this, "digit%u", 0U),
+ m_output_x_cb(*this),
+ m_output_a_cb(*this),
+ m_output_digit_cb(*this)
+{
+ // set defaults (60hz frames, 0.5 interpolation, 1 brightness level)
+ set_refresh(attotime::from_hz(60));
+ set_interpolation(0.5);
+ set_bri_levels(0.02);
+ set_bri_minimum(0);
+ set_size(0, 0);
+ reset_segmask();
+}
+
+
+
+//-------------------------------------------------
+// device_start/reset
+//-------------------------------------------------
+
+ALLOW_SAVE_TYPE(attotime); // m_acc
+
+void pwm_display_device::device_start()
+{
+ // resolve handlers
+ m_out_x.resolve();
+ m_out_a.resolve();
+ m_out_digit.resolve();
+
+ bool cb1 = m_output_x_cb.resolve_safe();
+ bool cb2 = m_output_a_cb.resolve_safe();
+ bool cb3 = m_output_digit_cb.resolve_safe();
+ m_external_output = cb1 || cb2 || cb3;
+
+ // initialize
+ std::fill_n(m_rowdata, ARRAY_LENGTH(m_rowdata), 0);
+ std::fill_n(m_rowdata_prev, ARRAY_LENGTH(m_rowdata_prev), 0);
+ std::fill_n(*m_bri, ARRAY_LENGTH(m_bri) * ARRAY_LENGTH(m_bri[0]), 0.0);
+
+ m_frame_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pwm_display_device::frame_tick),this));
+ m_update_time = machine().time();
+
+ m_rowsel = 0;
+ m_rowsel_prev = 0;
+
+ // register for savestates
+ save_item(NAME(m_width));
+ save_item(NAME(m_height));
+ save_item(NAME(m_framerate_set));
+ save_item(NAME(m_framerate));
+ save_item(NAME(m_interpolation));
+ save_item(NAME(m_levels));
+ save_item(NAME(m_level_min));
+
+ save_item(NAME(m_segmask));
+ save_item(NAME(m_rowsel));
+ save_item(NAME(m_rowsel_prev));
+ save_item(NAME(m_rowdata));
+ save_item(NAME(m_rowdata_prev));
+
+ save_item(NAME(m_bri));
+ save_item(NAME(m_acc));
+ save_item(NAME(m_update_time));
+}
+
+void pwm_display_device::device_reset()
+{
+ if (m_height > 64 || m_width > 64)
+ fatalerror("%s: Invalid size %d*%d, maximum is 64*64!\n", tag(), m_height, m_width);
+
+ schedule_frame();
+ m_update_time = machine().time();
+}
+
+
+
+//-------------------------------------------------
+// public handlers (most of the interface is in the .h file)
+//-------------------------------------------------
+
+pwm_display_device &pwm_display_device::set_bri_levels(double l0, double l1, double l2, double l3)
+{
+ // init brightness level(s) (if you need to set more than 4, use set_bri_one)
+ reset_bri_levels();
+ m_levels[0] = l0;
+ m_levels[1] = l1;
+ m_levels[2] = l2;
+ m_levels[3] = l3;
+
+ return *this;
+}
+
+void pwm_display_device::segmask(u64 digits, u64 mask)
+{
+ // set a segment mask per selected digit, but leave unselected ones alone
+ for (int y = 0; y < m_height; y++)
+ {
+ if (digits & 1)
+ m_segmask[y] = mask;
+ digits >>= 1;
+ }
+}
+
+void pwm_display_device::matrix_partial(u8 start, u8 height, u64 rowsel, u64 rowdata, bool upd)
+{
+ u64 selmask = (u64(1) << height) - 1;
+ rowsel &= selmask;
+ selmask <<= start;
+ m_rowsel = (m_rowsel & ~selmask) | (rowsel << start);
+
+ // update selected rows
+ u64 rowmask = (u64(1) << m_width) - 1;
+ for (int y = start; y < (start + height) && y < m_height; y++)
+ {
+ m_rowdata[y] = (rowsel & 1) ? (rowdata & rowmask) : 0;
+ rowsel >>= 1;
+ }
+
+ if (upd)
+ update();
+}
+
+void pwm_display_device::update()
+{
+ // call this every time after m_rowdata is changed (automatic with matrix)
+ const attotime now = machine().time();
+ const attotime diff = (m_update_time >= now) ? attotime::zero : now - m_update_time;
+
+ u64 sel = m_rowsel_prev;
+ m_rowsel_prev = m_rowsel;
+
+ // accumulate active time
+ for (int y = 0; y < m_height; y++)
+ {
+ u64 row = m_rowdata_prev[y];
+ m_rowdata_prev[y] = m_rowdata[y];
+
+ if (diff != attotime::zero)
+ {
+ if (sel & 1)
+ m_acc[y][m_width] += diff;
+
+ for (int x = 0; x < m_width; x++)
+ {
+ if (row & 1)
+ m_acc[y][x] += diff;
+ row >>= 1;
+ }
+ }
+ sel >>= 1;
+ }
+
+ m_update_time = now;
+}
+
+
+
+//-------------------------------------------------
+// internal handlers
+//-------------------------------------------------
+
+void pwm_display_device::schedule_frame()
+{
+ std::fill_n(*m_acc, m_height * ARRAY_LENGTH(m_acc[0]), attotime::zero);
+
+ m_framerate = m_framerate_set;
+ m_frame_timer->adjust(m_framerate);
+}
+
+TIMER_CALLBACK_MEMBER(pwm_display_device::frame_tick)
+{
+ update(); // final timeslice
+
+ const double frame_time = m_framerate.as_double();
+ const double factor0 = m_interpolation;
+ const double factor1 = 1.0 - factor0;
+
+ for (int y = 0; y < m_height; y++)
+ {
+ u64 row = 0;
+
+ for (int x = 0; x <= m_width; x++)
+ {
+ // determine brightness level
+ double bri = m_bri[y][x] * factor1 + (m_acc[y][x].as_double() / frame_time) * factor0;
+ if (bri > 1.0) bri = 1.0; // shouldn't happen
+ m_bri[y][x] = bri;
+
+ u8 level;
+ for (level = 0; bri > m_levels[level]; level++) { ; }
+
+ // output to y.x, or y.a when always-on
+ if (x != m_width)
+ {
+ if (level > m_level_min)
+ row |= (u64(1) << x);
+
+ if (m_external_output)
+ m_output_x_cb(x << 6 | y, level);
+ else
+ m_out_x[y][x] = level;
+ }
+ else
+ {
+ if (m_external_output)
+ m_output_a_cb(y, level);
+ else
+ m_out_a[y] = level;
+ }
+ }
+
+ // output to digity (does not support brightness levels)
+ if (m_segmask[y] != 0)
+ {
+ row &= m_segmask[y];
+
+ if (m_external_output)
+ m_output_digit_cb(y, row);
+ else
+ m_out_digit[y] = row;
+ }
+ }
+
+ schedule_frame();
+}
diff --git a/src/devices/video/pwm.h b/src/devices/video/pwm.h
new file mode 100644
index 00000000000..07e04bfb388
--- /dev/null
+++ b/src/devices/video/pwm.h
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*
+
+ Generic PWM display device
+
+*/
+
+#ifndef MAME_VIDEO_PWM_H
+#define MAME_VIDEO_PWM_H
+
+#pragma once
+
+class pwm_display_device : public device_t
+{
+public:
+ pwm_display_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ // configuration helpers
+ pwm_display_device &set_size(u8 numrows, u8 rowbits) { m_height = numrows; m_width = rowbits; return *this; } // max 64 * 64
+ pwm_display_device &set_refresh(attotime duration) { m_framerate_set = duration; return *this; } // time between each outputs refresh
+ pwm_display_device &set_interpolation(double factor) { m_interpolation = factor; return *this; } // frame interpolation (0.0 - 1.0)
+ pwm_display_device &set_segmask(u64 digits, u64 mask) { segmask(digits, mask); return *this; } // mask for multi-state outputs, eg. 7seg led
+ pwm_display_device &reset_segmask() { std::fill_n(m_segmask, ARRAY_LENGTH(m_segmask), 0); return *this; }
+ pwm_display_device &set_bri_levels(double l0, double l1 = 1.0, double l2 = 1.0, double l3 = 1.0); // brightness threshold per level (0.0 - 1.0)
+ pwm_display_device &set_bri_minimum(u8 i) { m_level_min = i; return *this; } // minimum level index for element to be considered "on"
+
+ // output callbacks when not using the default output tags
+ auto output_x() { return m_output_x_cb.bind(); } // x = offset >> 6, y = offset & 0x3f
+ auto output_a() { return m_output_a_cb.bind(); }
+ auto output_digit() { return m_output_digit_cb.bind(); }
+
+ void reset_bri_levels() { std::fill_n(m_levels, ARRAY_LENGTH(m_levels), 1.0); }
+ void set_bri_one(u8 i, double level) { m_levels[i] = level; }
+
+ void segmask(u64 digits, u64 mask);
+ void segmask_one(u8 y, u64 mask) { m_segmask[y] = mask; }
+ void matrix_partial(u8 start, u8 height, u64 rowsel, u64 rowdata, bool upd = true);
+ void matrix(u64 rowsel, u64 rowdata, bool upd = true) { matrix_partial(0, m_height, rowsel, rowdata, upd); }
+ void update(); // apply changes to m_rowdata
+
+ // directly handle individual element (does not affect m_rowsel), y = row num, x = row bit
+ int read_element(u8 y, u8 x) { return BIT(m_rowdata[y], x); }
+ void write_element(u8 y, u8 x, int state) { m_rowdata[y] = (m_rowdata[y] & ~(u64(1) << x)) | (u64(state ? 1 : 0) << x); }
+
+ // directly handle row data
+ u64 read_row(offs_t offset) { return m_rowdata[offset]; }
+ void write_row(offs_t offset, u64 data) { m_rowdata[offset] = data; m_rowsel |= u64(1) << offset; }
+ void clear_row(offs_t offset, u64 data = 0) { m_rowdata[offset] = 0; m_rowsel &= ~(u64(1) << offset); }
+
+ double element_bri(u8 y, u8 x) { return m_bri[y][x]; }
+ bool element_on(u8 y, u8 x) { return (m_bri[y][x] > m_levels[m_level_min]); }
+ bool row_on(u8 y) { return element_on(y, m_width); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ output_finder<0x40, 0x40> m_out_x;
+ output_finder<0x40> m_out_a;
+ output_finder<0x40> m_out_digit;
+
+ devcb_write8 m_output_x_cb;
+ devcb_write8 m_output_a_cb;
+ devcb_write64 m_output_digit_cb;
+ bool m_external_output;
+
+ u8 m_width;
+ u8 m_height;
+ attotime m_framerate_set;
+ attotime m_framerate;
+ double m_interpolation;
+ double m_levels[0x100];
+ u8 m_level_min;
+
+ u64 m_segmask[0x40];
+ u64 m_rowsel;
+ u64 m_rowsel_prev;
+ u64 m_rowdata[0x40];
+ u64 m_rowdata_prev[0x40];
+
+ double m_bri[0x40][0x41];
+ attotime m_acc[0x40][0x41];
+ attotime m_update_time;
+
+ emu_timer *m_frame_timer;
+ TIMER_CALLBACK_MEMBER(frame_tick);
+ void schedule_frame();
+};
+
+
+DECLARE_DEVICE_TYPE(PWM_DISPLAY, pwm_display_device)
+
+#endif // MAME_VIDEO_PWM_H
diff --git a/src/emu/devcb.h b/src/emu/devcb.h
index 6b16c37b33a..1ac9cd1e37f 100644
--- a/src/emu/devcb.h
+++ b/src/emu/devcb.h
@@ -899,7 +899,7 @@ public:
virtual void validity_check(validity_checker &valid) const override;
void resolve();
- void resolve_safe(Result dflt);
+ bool resolve_safe(Result dflt);
Result operator()(address_space &space, offs_t offset = 0, std::make_unsigned_t<Result> mem_mask = DefaultMask);
Result operator()(offs_t offset, std::make_unsigned_t<Result> mem_mask = DefaultMask);
@@ -958,11 +958,13 @@ void devcb_read<Result, DefaultMask>::resolve()
}
template <typename Result, std::make_unsigned_t<Result> DefaultMask>
-void devcb_read<Result, DefaultMask>::resolve_safe(Result dflt)
+bool devcb_read<Result, DefaultMask>::resolve_safe(Result dflt)
{
resolve();
- if (m_functions.empty())
+ bool resolved = !m_functions.empty();
+ if (!resolved)
m_functions.emplace_back([dflt] (address_space &space, offs_t offset, std::make_unsigned_t<Result> mem_mask) { return dflt; });
+ return resolved;
}
template <typename Result, std::make_unsigned_t<Result> DefaultMask>
@@ -2369,7 +2371,7 @@ public:
virtual void validity_check(validity_checker &valid) const override;
void resolve();
- void resolve_safe();
+ bool resolve_safe();
void operator()(address_space &space, offs_t offset, Input data, std::make_unsigned_t<Input> mem_mask = DefaultMask);
void operator()(address_space &space, Input data);
@@ -2420,11 +2422,13 @@ void devcb_write<Input, DefaultMask>::resolve()
}
template <typename Input, std::make_unsigned_t<Input> DefaultMask>
-void devcb_write<Input, DefaultMask>::resolve_safe()
+bool devcb_write<Input, DefaultMask>::resolve_safe()
{
resolve();
- if (m_functions.empty())
+ bool resolved = !m_functions.empty();
+ if (!resolved)
m_functions.emplace_back([] (address_space &space, offs_t offset, Input data, std::make_unsigned_t<Input> mem_mask) { });
+ return resolved;
}
template <typename Input, std::make_unsigned_t<Input> DefaultMask>
diff --git a/src/mame/drivers/cking_master.cpp b/src/mame/drivers/cking_master.cpp
index bbf42d914e1..9d2ddcb4893 100644
--- a/src/mame/drivers/cking_master.cpp
+++ b/src/mame/drivers/cking_master.cpp
@@ -3,27 +3,22 @@
// thanks-to:Berger
/******************************************************************************
-* cking_master.cpp, subdriver of machine/screenless.cpp
-
-TODO:
-- 1 WAIT CLK per M1, workaround with z80_set_cycle_tables is possible
- (wait state is similar to MSX) but I can't be bothered, better solution
- is to add M1 pin to the z80 core. Until then, it'll run ~20% too fast.
-
-*******************************************************************************
-
Chess King Master overview (yes, it's plainly named "Master"):
- Z80 CPU(NEC D780C-1) @ 4MHz(8MHz XTAL), IRQ from 555 timer
- 8KB ROM(NEC D2764C-3), 2KB RAM(NEC D4016C), ROM is scrambled for easy PCB placement
- simple I/O via 2*74373 and a 74145
- 8*8 chessboard buttons, 32+1 border leds, piezo
+TODO:
+- 1 WAIT CLK per M1, workaround with z80_set_cycle_tables is possible
+ (wait state is similar to MSX) but I can't be bothered, better solution
+ is to add M1 pin to the z80 core. Until then, it'll run ~20% too fast.
+
******************************************************************************/
#include "emu.h"
-#include "includes/screenless.h"
-
#include "cpu/z80/z80.h"
+#include "video/pwm.h"
#include "machine/bankdev.h"
#include "machine/timer.h"
#include "sound/dac.h"
@@ -36,12 +31,13 @@ Chess King Master overview (yes, it's plainly named "Master"):
namespace {
-class master_state : public screenless_state
+class master_state : public driver_device
{
public:
master_state(const machine_config &mconfig, device_type type, const char *tag) :
- screenless_state(mconfig, type, tag),
+ driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
+ m_display(*this, "display"),
m_irq_on(*this, "irq_on"),
m_dac(*this, "dac"),
m_mainmap(*this, "mainmap"),
@@ -59,6 +55,7 @@ protected:
private:
// devices/pointers
required_device<cpu_device> m_maincpu;
+ required_device<pwm_display_device> m_display;
required_device<timer_device> m_irq_on;
required_device<dac_2bit_binary_weighted_ones_complement_device> m_dac;
required_device<address_map_bank_device> m_mainmap;
@@ -83,8 +80,6 @@ private:
void master_state::machine_start()
{
- screenless_state::machine_start();
-
// zerofill, register for savestates
m_inp_mux = 0;
save_item(NAME(m_inp_mux));
@@ -106,7 +101,7 @@ void master_state::control_w(u8 data)
u16 sel = 1 << m_inp_mux & 0x3ff;
// d4,d5: led data
- display_matrix(2, 9, data >> 4 & 3, sel & 0x1ff);
+ m_display->matrix(sel & 0x1ff, data >> 4 & 3);
// d6,d7: speaker +/-
m_dac->write(data >> 6 & 3);
@@ -301,6 +296,7 @@ void master_state::master(machine_config &config)
m_irq_on->set_start_delay(irq_period - attotime::from_nsec(22870)); // active for 22.87us
TIMER(config, "irq_off").configure_periodic(FUNC(master_state::irq_off<INPUT_LINE_IRQ0>), irq_period);
+ PWM_DISPLAY(config, m_display).set_size(9, 2);
config.set_default_layout(layout_ck_master);
/* sound hardware */
diff --git a/src/mame/drivers/cxg_ch2001.cpp b/src/mame/drivers/cxg_ch2001.cpp
index 6b716a424a4..9df4c7136ff 100644
--- a/src/mame/drivers/cxg_ch2001.cpp
+++ b/src/mame/drivers/cxg_ch2001.cpp
@@ -3,10 +3,6 @@
// thanks-to:Berger
/******************************************************************************
-* cxg_ch2001.cpp, subdriver of machine/screenless.cpp
-
-*******************************************************************************
-
CXG Chess 2001 overview:
- Zilog Z8400APS @ 4 MHz (8MHz XTAL)
- 2KB RAM HM6116, 16KB ROM D27128D
@@ -15,9 +11,8 @@ CXG Chess 2001 overview:
******************************************************************************/
#include "emu.h"
-#include "includes/screenless.h"
-
#include "cpu/z80/z80.h"
+#include "video/pwm.h"
#include "machine/timer.h"
#include "sound/dac.h"
#include "sound/volt_reg.h"
@@ -29,12 +24,13 @@ CXG Chess 2001 overview:
namespace {
-class ch2001_state : public screenless_state
+class ch2001_state : public driver_device
{
public:
ch2001_state(const machine_config &mconfig, device_type type, const char *tag) :
- screenless_state(mconfig, type, tag),
+ driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
+ m_display(*this, "display"),
m_irq_on(*this, "irq_on"),
m_dac(*this, "dac"),
m_speaker_off(*this, "speaker_off"),
@@ -50,6 +46,7 @@ protected:
private:
// devices/pointers
required_device<cpu_device> m_maincpu;
+ required_device<pwm_display_device> m_display;
required_device<timer_device> m_irq_on;
required_device<dac_bit_interface> m_dac;
required_device<timer_device> m_speaker_off;
@@ -74,8 +71,6 @@ private:
void ch2001_state::machine_start()
{
- screenless_state::machine_start();
-
// zerofill, register for savestates
m_inp_mux = 0;
save_item(NAME(m_inp_mux));
@@ -107,7 +102,7 @@ WRITE8_MEMBER(ch2001_state::leds_w)
// 74ls273 Q5-Q8: MC14028 A-D
// MC14028 Q0-Q7: led data, Q8,Q9: N/C
u8 led_data = 1 << (data >> 4 & 0xf) & 0xff;
- display_matrix(8, 10, led_data, sel);
+ m_display->matrix(sel, led_data);
}
READ8_MEMBER(ch2001_state::input_r)
@@ -256,14 +251,15 @@ void ch2001_state::ch2001(machine_config &config)
m_irq_on->set_start_delay(irq_period - attotime::from_nsec(18300)); // active for 18.3us
TIMER(config, "irq_off").configure_periodic(FUNC(ch2001_state::irq_off<INPUT_LINE_IRQ0>), irq_period);
- TIMER(config, m_speaker_off).configure_generic(FUNC(ch2001_state::speaker_off));
-
+ PWM_DISPLAY(config, m_display).set_size(10, 8);
config.set_default_layout(layout_cxg_ch2001);
/* sound hardware */
SPEAKER(config, "speaker").front_center();
DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
VOLTAGE_REGULATOR(config, "vref").add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
+
+ TIMER(config, m_speaker_off).configure_generic(FUNC(ch2001_state::speaker_off));
}
diff --git a/src/mame/drivers/hh_amis2k.cpp b/src/mame/drivers/hh_amis2k.cpp
index 06f6881d13c..fc98c6067b5 100644
--- a/src/mame/drivers/hh_amis2k.cpp
+++ b/src/mame/drivers/hh_amis2k.cpp
@@ -13,9 +13,8 @@
***************************************************************************/
#include "emu.h"
-#include "includes/screenless.h"
-
#include "cpu/amis2000/amis2000.h"
+#include "video/pwm.h"
#include "machine/timer.h"
#include "sound/spkrdev.h"
#include "speaker.h"
@@ -26,20 +25,22 @@
//#include "hh_amis2k_test.lh" // common test-layout - use external artwork
-class hh_amis2k_state : public screenless_state
+class hh_amis2k_state : public driver_device
{
public:
hh_amis2k_state(const machine_config &mconfig, device_type type, const char *tag) :
- screenless_state(mconfig, type, tag),
+ driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
- m_inp_matrix(*this, "IN.%u", 0),
- m_speaker(*this, "speaker")
+ m_display(*this, "display"),
+ m_speaker(*this, "speaker"),
+ m_inp_matrix(*this, "IN.%u", 0)
{ }
// devices
required_device<amis2000_base_device> m_maincpu;
- optional_ioport_array<4> m_inp_matrix; // max 4
+ optional_device<pwm_display_device> m_display;
optional_device<speaker_sound_device> m_speaker;
+ optional_ioport_array<4> m_inp_matrix; // max 4
// misc common
u16 m_a; // MCU address bus
@@ -59,8 +60,6 @@ protected:
void hh_amis2k_state::machine_start()
{
- screenless_state::machine_start();
-
// zerofill
m_a = 0;
m_d = 0;
@@ -144,10 +143,7 @@ class wildfire_state : public hh_amis2k_state
public:
wildfire_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_amis2k_state(mconfig, type, tag)
- {
- // bumpers are dimmed
- set_display_levels(0.02, 0.1);
- }
+ { }
void prepare_display();
DECLARE_WRITE8_MEMBER(write_d);
@@ -192,8 +188,8 @@ TIMER_DEVICE_CALLBACK_MEMBER(wildfire_state::speaker_decay_sim)
void wildfire_state::prepare_display()
{
// A0-A2 are 7segs
- set_display_segmask(7, 0x7f);
- display_matrix(8, 12, m_d, ~m_a);
+ m_display->segmask(7, 0x7f);
+ m_display->matrix(~m_a, m_d);
}
WRITE8_MEMBER(wildfire_state::write_d)
@@ -249,6 +245,8 @@ void wildfire_state::wildfire(machine_config &config)
m_maincpu->write_a().set(FUNC(wildfire_state::write_a));
m_maincpu->write_f().set(FUNC(wildfire_state::write_f));
+ PWM_DISPLAY(config, m_display).set_size(12, 8);
+ m_display->set_bri_levels(0.02, 0.1); // bumpers are dimmed
config.set_default_layout(layout_wildfire);
/* sound hardware */
diff --git a/src/mame/drivers/hh_tms1k.cpp b/src/mame/drivers/hh_tms1k.cpp
index 341b24c5423..2e3e2d03dd4 100644
--- a/src/mame/drivers/hh_tms1k.cpp
+++ b/src/mame/drivers/hh_tms1k.cpp
@@ -244,17 +244,18 @@ void hh_tms1k_state::machine_start()
{
screenless_state::machine_start();
+ // resolve handlers
+ m_out_power.resolve();
+
// zerofill
m_o = 0;
m_r = 0;
m_inp_mux = 0;
- m_power_led = false;
m_power_on = false;
m_grid = 0;
m_plate = 0;
// register for savestates
- /* save_item(NAME(m_power_led)); */ // don't save!
save_item(NAME(m_o));
save_item(NAME(m_r));
save_item(NAME(m_inp_mux));
@@ -265,7 +266,7 @@ void hh_tms1k_state::machine_start()
void hh_tms1k_state::machine_reset()
{
- m_power_on = true;
+ set_power(true);
}
@@ -276,21 +277,6 @@ void hh_tms1k_state::machine_reset()
***************************************************************************/
-// display update
-
-void hh_tms1k_state::display_update()
-{
- screenless_state::display_update();
-
- // output optional power led
- if (m_power_led != m_power_on)
- {
- m_power_led = m_power_on;
- output().set_value("power_led", m_power_led ? 1 : 0);
- }
-}
-
-
// generic input handlers
u8 hh_tms1k_state::read_inputs(int columns)
@@ -337,7 +323,7 @@ INPUT_CHANGED_MEMBER(hh_tms1k_state::reset_button)
INPUT_CHANGED_MEMBER(hh_tms1k_state::power_button)
{
- m_power_on = (bool)(uintptr_t)param;
+ set_power((bool)(uintptr_t)param);
m_maincpu->set_input_line(INPUT_LINE_RESET, m_power_on ? CLEAR_LINE : ASSERT_LINE);
}
@@ -350,10 +336,16 @@ WRITE_LINE_MEMBER(hh_tms1k_state::auto_power_off)
void hh_tms1k_state::power_off()
{
- m_power_on = false;
+ set_power(false);
m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
}
+void hh_tms1k_state::set_power(bool state)
+{
+ m_power_on = state;
+ m_out_power = state ? 1 : 0;
+}
+
/***************************************************************************
diff --git a/src/mame/drivers/tispeak.cpp b/src/mame/drivers/tispeak.cpp
index 48c3a9cb2d3..f9a32b22afe 100644
--- a/src/mame/drivers/tispeak.cpp
+++ b/src/mame/drivers/tispeak.cpp
@@ -784,7 +784,7 @@ INPUT_CHANGED_MEMBER(tispeak_state::power_button)
if (on && !m_power_on)
{
- m_power_on = true;
+ set_power(true);
m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
}
else if (!on && m_power_on)
diff --git a/src/mame/drivers/tispellb.cpp b/src/mame/drivers/tispellb.cpp
index f8f23b55928..c6806552659 100644
--- a/src/mame/drivers/tispellb.cpp
+++ b/src/mame/drivers/tispellb.cpp
@@ -254,7 +254,7 @@ INPUT_CHANGED_MEMBER(tispellb_state::power_button)
if (on && !m_power_on)
{
- m_power_on = true;
+ set_power(true);
m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
if (m_subcpu)
diff --git a/src/mame/includes/hh_tms1k.h b/src/mame/includes/hh_tms1k.h
index 19cd3a524a3..bfb0a329ec0 100644
--- a/src/mame/includes/hh_tms1k.h
+++ b/src/mame/includes/hh_tms1k.h
@@ -32,20 +32,21 @@ public:
screenless_state(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_inp_matrix(*this, "IN.%u", 0),
- m_speaker(*this, "speaker")
+ m_speaker(*this, "speaker"),
+ m_out_power(*this, "power")
{ }
// devices
required_device<tms1k_base_device> m_maincpu;
optional_ioport_array<18> m_inp_matrix; // max 18
optional_device<speaker_sound_device> m_speaker;
+ output_finder<> m_out_power; // power state, eg. led
// misc common
u16 m_r; // MCU R-pins data
u16 m_o; // MCU O-pins data
u32 m_inp_mux; // multiplexed inputs mask
bool m_power_on;
- bool m_power_led;
u32 m_grid; // VFD/LED current row data
u32 m_plate; // VFD/LED current column data
@@ -56,6 +57,7 @@ public:
virtual DECLARE_INPUT_CHANGED_MEMBER(power_button);
virtual DECLARE_WRITE_LINE_MEMBER(auto_power_off);
virtual void power_off();
+ void set_power(bool state);
void switch_change(int sel, u32 mask, bool next);
template<int Sel> DECLARE_INPUT_CHANGED_MEMBER(switch_next) { if (newval) switch_change(Sel, (u32)(uintptr_t)param, true); }
@@ -64,8 +66,6 @@ public:
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
-
- virtual void display_update() override;
};
diff --git a/src/mame/layout/tntell.lay b/src/mame/layout/tntell.lay
index ce4f1c733d8..b0843c33380 100644
--- a/src/mame/layout/tntell.lay
+++ b/src/mame/layout/tntell.lay
@@ -101,7 +101,7 @@
<bezel element="text_off"><bounds x="10.6" y="69.8" width="3" height="1.6" /></bezel>
<bezel element="text_on"><bounds x="67.9" y="69.8" width="2.3" height="1.6" /></bezel>
- <bezel name="power_led" element="led"><bounds x="70.1" y="70.1" width="1" height="1" /></bezel> <!-- fake -->
+ <bezel name="power" element="led"><bounds x="70.1" y="70.1" width="1" height="1" /></bezel> <!-- fake -->
</view>
</mamelayout>
diff --git a/src/mame/machine/chessbase.cpp b/src/mame/machine/chessbase.cpp
index 331552a1895..480a21233a8 100644
--- a/src/mame/machine/chessbase.cpp
+++ b/src/mame/machine/chessbase.cpp
@@ -12,7 +12,7 @@ As workaround for the chess games, use an external chess GUI on the side,
such as Arena(in editmode).
TODO:
-- use screenless class, this file will be removed eventually
+- use pwm_display_device, this file will be removed eventually
******************************************************************************/
diff --git a/src/mame/machine/screenless.cpp b/src/mame/machine/screenless.cpp
index fc54f09201b..78ca02e8af7 100644
--- a/src/mame/machine/screenless.cpp
+++ b/src/mame/machine/screenless.cpp
@@ -7,7 +7,7 @@ Generic screenless base class
This file contains helpers for strobed display elements.
TODO:
-- multiple brightness levels doesn't work for SVGs
+- use pwm_display_device, remove this file
******************************************************************************/