diff options
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 |
commit | ed0202220a5243537f5ba7dbc0a38e52a8390d79 (patch) | |
tree | a507513cad7ecd6eb681e4e1722bb89e1fcd63c0 | |
parent | f1d338e9e68c317a7fad8890ddf7c425303cbc75 (diff) |
screenless: make it a device (nw)
-rw-r--r-- | scripts/src/video.lua | 11 | ||||
-rw-r--r-- | scripts/target/mame/arcade.lua | 1 | ||||
-rw-r--r-- | scripts/target/mame/mess.lua | 1 | ||||
-rw-r--r-- | src/devices/machine/chessmachine.h | 6 | ||||
-rw-r--r-- | src/devices/video/hlcd0538.cpp | 2 | ||||
-rw-r--r-- | src/devices/video/pwm.cpp | 269 | ||||
-rw-r--r-- | src/devices/video/pwm.h | 96 | ||||
-rw-r--r-- | src/emu/devcb.h | 16 | ||||
-rw-r--r-- | src/mame/drivers/cking_master.cpp | 28 | ||||
-rw-r--r-- | src/mame/drivers/cxg_ch2001.cpp | 22 | ||||
-rw-r--r-- | src/mame/drivers/hh_amis2k.cpp | 28 | ||||
-rw-r--r-- | src/mame/drivers/hh_tms1k.cpp | 32 | ||||
-rw-r--r-- | src/mame/drivers/tispeak.cpp | 2 | ||||
-rw-r--r-- | src/mame/drivers/tispellb.cpp | 2 | ||||
-rw-r--r-- | src/mame/includes/hh_tms1k.h | 8 | ||||
-rw-r--r-- | src/mame/layout/tntell.lay | 2 | ||||
-rw-r--r-- | src/mame/machine/chessbase.cpp | 2 | ||||
-rw-r--r-- | src/mame/machine/screenless.cpp | 2 |
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 ******************************************************************************/ |